diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc index b8f26d8656c..aec1843d3ea 100644 --- a/runtime/vm/compiler/compiler_pass.cc +++ b/runtime/vm/compiler/compiler_pass.cc @@ -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); diff --git a/runtime/vm/compiler/compiler_pass.h b/runtime/vm/compiler/compiler_pass.h index 72bd2e428ac..c3ee7674b15 100644 --- a/runtime/vm/compiler/compiler_pass.h +++ b/runtime/vm/compiler/compiler_pass.h @@ -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); diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc index 81d31da7e39..c1c62fb67ec 100644 --- a/runtime/vm/debugger.cc +++ b/runtime/vm/debugger.cc @@ -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(); diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 4f26eadc421..a9e7804fc81 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -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(); } diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc index 4ed96a499a8..0ffa031ed0f 100644 --- a/runtime/vm/runtime_entry.cc +++ b/runtime/vm/runtime_entry.cc @@ -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++) { diff --git a/tests/ffi/ffi.status b/tests/ffi/ffi.status index 7652349434f..9ae71a3f51b 100644 --- a/tests/ffi/ffi.status +++ b/tests/ffi/ffi.status @@ -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.) diff --git a/tests/ffi/function_callbacks_test.dart b/tests/ffi/function_callbacks_test.dart index 43779382f08..637c9245d03 100644 --- a/tests/ffi/function_callbacks_test.dart +++ b/tests/ffi/function_callbacks_test.dart @@ -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(); } -} \ No newline at end of file +} diff --git a/tests/ffi/function_gc_test.dart b/tests/ffi/function_gc_test.dart index b212b32ab12..ed56e34a3cc 100644 --- a/tests/ffi/function_gc_test.dart +++ b/tests/ffi/function_gc_test.dart @@ -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. diff --git a/tests/ffi/function_test.dart b/tests/ffi/function_test.dart index 68529bdbef6..b4e6d7c4468 100644 --- a/tests/ffi/function_test.dart +++ b/tests/ffi/function_test.dart @@ -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; diff --git a/tests/ffi/stacktrace_regress_37910_test.dart b/tests/ffi/stacktrace_regress_37910_test.dart new file mode 100644 index 00000000000..0a76648ffda --- /dev/null +++ b/tests/ffi/stacktrace_regress_37910_test.dart @@ -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(fooFfi1, 0) + .cast>() + .asFunction(); + +main() { + foo1(); +}