[vm/ffi] Fix crashes on stacktraces and debugging with force-optimized frames.

Issue https://github.com/dart-lang/sdk/issues/37910

Change-Id: I76630fbc6733712c8709b782619a76190c70bfd5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/113999
Commit-Queue: Samir Jindel <sjindel@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Samir Jindel 2019-08-26 10:18:34 +00:00 committed by commit-bot@chromium.org
parent 53883c6044
commit 43417df9c7
10 changed files with 92 additions and 20 deletions

View file

@ -238,6 +238,40 @@ void CompilerPass::RunInliningPipeline(PipelineMode mode,
FlowGraph* CompilerPass::RunPipeline(PipelineMode mode,
CompilerPassState* pass_state) {
if (mode == kForced) {
INVOKE_PASS(ComputeSSA);
if (FLAG_early_round_trip_serialization) {
INVOKE_PASS(RoundTripSerialization);
}
INVOKE_PASS(TypePropagation);
INVOKE_PASS(ApplyClassIds);
INVOKE_PASS(Canonicalize);
INVOKE_PASS(BranchSimplify);
INVOKE_PASS(IfConvert);
INVOKE_PASS(ConstantPropagation);
INVOKE_PASS(TypePropagation);
INVOKE_PASS(WidenSmiToInt32);
INVOKE_PASS(SelectRepresentations);
INVOKE_PASS(TypePropagation);
INVOKE_PASS(TryCatchOptimization);
INVOKE_PASS(EliminateEnvironments);
INVOKE_PASS(EliminateDeadPhis);
INVOKE_PASS(Canonicalize);
INVOKE_PASS(WriteBarrierElimination);
INVOKE_PASS(FinalizeGraph);
#if defined(DART_PRECOMPILER)
if (mode == kAOT) {
INVOKE_PASS(SerializeGraph);
}
#endif
if (FLAG_late_round_trip_serialization) {
INVOKE_PASS(RoundTripSerialization);
}
INVOKE_PASS(AllocateRegisters);
INVOKE_PASS(ReorderBlocks);
return pass_state->flow_graph;
}
INVOKE_PASS(ComputeSSA);
if (FLAG_early_round_trip_serialization) {
INVOKE_PASS(RoundTripSerialization);

View file

@ -141,7 +141,11 @@ class CompilerPass {
static void ParseFilters(const char* filter);
enum PipelineMode { kJIT, kAOT };
enum PipelineMode {
kJIT, // Includes speculative and inter-procedural optimizations.
kAOT, // Includes inter-procedural optimizations.
kForced // Does not include speculative or inter-procedural optimizations.
};
static void RunGraphIntrinsicPipeline(CompilerPassState* state);

View file

@ -2222,7 +2222,7 @@ void Debugger::AppendCodeFrames(Thread* thread,
Code* inlined_code,
Array* deopt_frame) {
#if !defined(DART_PRECOMPILED_RUNTIME)
if (code->is_optimized()) {
if (code->is_optimized() && !code->is_force_optimized()) {
// TODO(rmacnak): Use CodeSourceMap
*deopt_frame = DeoptimizeToArray(thread, frame, *code);
for (InlinedFunctionsIterator it(*code, frame->pc()); !it.Done();

View file

@ -7363,6 +7363,13 @@ RawFunction* Function::New(const String& name,
// in new space.
ASSERT(space == Heap::kOld);
}
// Force-optimized functions are not debuggable because they cannot
// deoptimize.
if (result.ForceOptimize()) {
result.set_is_debuggable(false);
}
return result.raw();
}

View file

@ -2149,15 +2149,18 @@ static void HandleStackOverflowTestCases(Thread* thread) {
intptr_t num_frames = stack->Length();
for (intptr_t i = 0; i < num_frames; i++) {
ActivationFrame* frame = stack->FrameAt(i);
#ifndef DART_PRECOMPILED_RUNTIME
if (!frame->IsInterpreted() && !frame->function().ForceOptimize()) {
// Ensure that we have unoptimized code.
frame->function().EnsureHasCompiledUnoptimizedCode();
}
const int num_vars = frame->NumLocalVariables();
#else
int num_vars = 0;
// Variable locations and number are unknown when precompiling.
const int num_vars = 0;
#if !defined(DART_PRECOMPILED_RUNTIME)
// NumLocalVariables() can call EnsureHasUnoptimizedCode() for
// non-interpreted functions.
if (!frame->function().ForceOptimize()) {
if (!frame->IsInterpreted()) {
// Ensure that we have unoptimized code.
frame->function().EnsureHasCompiledUnoptimizedCode();
}
num_vars = frame->NumLocalVariables();
}
#endif
TokenPosition unused = TokenPosition::kNoSource;
for (intptr_t v = 0; v < num_vars; v++) {

View file

@ -2,12 +2,8 @@
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
[ $arch == simdbc ]
*: Skip # FFI not yet supported on SimDBC32: dartbug.com/36809
[ $arch == simdbc64 ]
function_callbacks_test: Skip # Issue 37140
regress_37511_callbacks_test: Skip # Issue 37140
[ $arch == simdbc || $arch == simdbc64 ]
*: Skip # SIMDBC will be deleted soon.
[ $builder_tag == asan ]
data_not_asan_test: SkipByDesign # This test tries to allocate too much memory on purpose.
@ -22,13 +18,11 @@ function_callbacks_test/03: Skip
[ $runtime == dart_precompiled ]
function_callbacks_test: Skip # Issue dartbug.com/37295
regress_37511_callbacks_test: Skip # Issue dartbug.com/37295
stacktrace_regress_37910_test: Skip # Issue dartbug.com/37295
[ $arch == arm && $system != android ]
*: Skip # "hardfp" calling convention is not yet supported (iOS is also supported but not tested): dartbug.com/36309
[ $arch == simdbc64 && $system != linux && $system != macos ]
*: Skip # DBC is only supported on MacOS and Linux for testing
[ $runtime != dart_precompiled && $runtime != vm ]
*: SkipByDesign # FFI is a VM-only feature. (This test suite is part of the default set.)

View file

@ -5,7 +5,9 @@
// Dart test program for testing dart:ffi function pointers with callbacks.
//
// VMOptions=--enable-testing-pragmas
// VMOptions=--enable-testing-pragmas --stacktrace-every=100
// VMOptions=--enable-testing-pragmas --write-protect-code --no-dual-map-code
// VMOptions=--enable-testing-pragmas --write-protect-code --no-dual-map-code --stacktrace-every=100
// SharedObjects=ffi_test_functions
library FfiTest;
@ -268,4 +270,4 @@ void testManyCallbacks() {
for (final pointer in pointers) {
Test("SimpleAddition", pointer).run();
}
}
}

View file

@ -6,6 +6,8 @@
// VMOptions=--deterministic --optimization-counter-threshold=-1 --enable-testing-pragmas
// VMOptions=--deterministic --optimization-counter-threshold=500 --enable-testing-pragmas --no-dual-map-code --write-protect-code
// VMOptions=--deterministic --optimization-counter-threshold=-1 --enable-testing-pragmas --no-dual-map-code --write-protect-code
// VMOptions=--enable-testing-pragmas --no-dual-map-code --write-protect-code
// VMOptions=--enable-testing-pragmas --no-dual-map-code --write-protect-code --stacktrace-every=100
//
// Dart test program for stress-testing boxing and GC in return paths from FFI
// trampolines.

View file

@ -7,8 +7,10 @@
// VMOptions=
// VMOptions=--deterministic --optimization-counter-threshold=10
// VMOptions=--use-slow-path
// VMOptions=--use-slow-path --stacktrace-every=100
// VMOptions=--write-protect-code --no-dual-map-code
// VMOptions=--write-protect-code --no-dual-map-code --use-slow-path
// VMOptions=--write-protect-code --no-dual-map-code --stacktrace-every=100
// SharedObjects=ffi_test_functions
library FfiTest;

View file

@ -0,0 +1,24 @@
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
//
// VMOptions=--stacktrace_every=100
import 'dart:ffi' as ffi;
typedef fooFfi1Type = ffi.Int32 Function();
int fooFfi1() {
int a = 0;
for (int i = 0; i < 1000; ++i) {
a += i;
}
return a;
}
int Function() foo1 = ffi.Pointer.fromFunction<fooFfi1Type>(fooFfi1, 0)
.cast<ffi.NativeFunction<fooFfi1Type>>()
.asFunction();
main() {
foo1();
}