mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 03:27:43 +00:00
[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:
parent
53883c6044
commit
43417df9c7
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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()) {
|
||||
int num_vars = 0;
|
||||
// Variable locations and number are unknown when precompiling.
|
||||
#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();
|
||||
}
|
||||
const int num_vars = frame->NumLocalVariables();
|
||||
#else
|
||||
// Variable locations and number are unknown when precompiling.
|
||||
const int num_vars = 0;
|
||||
num_vars = frame->NumLocalVariables();
|
||||
}
|
||||
#endif
|
||||
TokenPosition unused = TokenPosition::kNoSource;
|
||||
for (intptr_t v = 0; v < num_vars; v++) {
|
||||
|
|
|
@ -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.)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
24
tests/ffi/stacktrace_regress_37910_test.dart
Normal file
24
tests/ffi/stacktrace_regress_37910_test.dart
Normal 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();
|
||||
}
|
Loading…
Reference in a new issue