From 193ddba4dbabd983b7e9ad8bdf2f7c9d976fbf9f Mon Sep 17 00:00:00 2001 From: Todd Turnidge Date: Tue, 22 Nov 2016 16:05:26 -0800 Subject: [PATCH] Revert "Implement rewind: drop one or more frames from the debugger." This reverts commit af1875be910a24f34f1983b314f45c1ecd8097ad. BUG= Review URL: https://codereview.chromium.org/2521413002 . --- .../lib/src/elements/debugger.dart | 124 ++----- .../observatory/lib/src/service/object.dart | 10 +- .../service/pause_idle_isolate_test.dart | 5 +- .../service/pause_on_start_and_exit_test.dart | 5 +- .../pause_on_start_then_step_test.dart | 5 +- .../service/rewind_optimized_out_test.dart | 86 ----- .../tests/service/rewind_test.dart | 173 ---------- .../observatory/tests/service/service.status | 2 - .../tests/service/service_test_common.dart | 4 - .../tests/service/set_vm_name_rpc_test.dart | 4 +- .../tests/service/step_over_await_test.dart | 2 +- .../tests/service/test_helper.dart | 87 +++-- runtime/vm/code_generator.cc | 8 - runtime/vm/dart_entry.cc | 2 +- runtime/vm/debugger.cc | 323 +----------------- runtime/vm/debugger.h | 40 +-- runtime/vm/debugger_api_impl.cc | 6 +- runtime/vm/exceptions.cc | 20 +- runtime/vm/exceptions.h | 3 +- runtime/vm/flow_graph_compiler.cc | 1 - runtime/vm/intermediate_language.cc | 2 - runtime/vm/json_stream.cc | 2 - runtime/vm/json_stream.h | 1 - runtime/vm/object.cc | 2 - runtime/vm/raw_object.h | 3 +- runtime/vm/runtime_entry_list.h | 1 - runtime/vm/service.cc | 74 ++-- runtime/vm/simulator_dbc.cc | 15 +- runtime/vm/stub_code.h | 8 - runtime/vm/stub_code_arm.cc | 33 +- runtime/vm/stub_code_arm64.cc | 33 +- runtime/vm/stub_code_dbc.cc | 6 - runtime/vm/stub_code_ia32.cc | 27 +- runtime/vm/stub_code_mips.cc | 33 +- runtime/vm/stub_code_x64.cc | 32 +- 35 files changed, 182 insertions(+), 1000 deletions(-) delete mode 100644 runtime/observatory/tests/service/rewind_optimized_out_test.dart delete mode 100644 runtime/observatory/tests/service/rewind_test.dart diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart index a01064fb9e1..8b91efffe5b 100644 --- a/runtime/observatory/lib/src/elements/debugger.dart +++ b/runtime/observatory/lib/src/elements/debugger.dart @@ -209,8 +209,7 @@ class DownCommand extends DebuggerCommand { debugger.downFrame(count); debugger.console.print('frame = ${debugger.currentFrame}'); } catch (e) { - debugger.console.print( - 'frame must be in range [${e.start}..${e.end-1}]'); + debugger.console.print('frame must be in range [${e.start},${e.end-1}]'); } return new Future.value(null); } @@ -244,8 +243,7 @@ class UpCommand extends DebuggerCommand { debugger.upFrame(count); debugger.console.print('frame = ${debugger.currentFrame}'); } on RangeError catch (e) { - debugger.console.print( - 'frame must be in range [${e.start}..${e.end-1}]'); + debugger.console.print('frame must be in range [${e.start},${e.end-1}]'); } return new Future.value(null); } @@ -281,8 +279,7 @@ class FrameCommand extends DebuggerCommand { debugger.currentFrame = frame; debugger.console.print('frame = ${debugger.currentFrame}'); } on RangeError catch (e) { - debugger.console.print( - 'frame must be in range [${e.start}..${e.end-1}]'); + debugger.console.print('frame must be in range [${e.start},${e.end-1}]'); } return new Future.value(null); } @@ -406,73 +403,6 @@ class StepCommand extends DebuggerCommand { 'Syntax: step\n'; } -class RewindCommand extends DebuggerCommand { - RewindCommand(Debugger debugger) : super(debugger, 'rewind', []); - - Future run(List args) async { - try { - int count = 1; - if (args.length == 1) { - count = int.parse(args[0]); - } else if (args.length > 1) { - debugger.console.print('rewind expects 0 or 1 argument'); - return; - } else if (count < 1 || count > debugger.stackDepth) { - debugger.console.print( - 'frame must be in range [1..${debugger.stackDepth - 1}]'); - return; - } - await debugger.rewind(count); - } on S.ServerRpcException catch(e) { - if (e.code == S.ServerRpcException.kCannotResume) { - debugger.console.printRed(e.data['details']); - } else { - rethrow; - } - } - } - - String helpShort = 'Rewind the stack to a previous frame'; - - String helpLong = - 'Rewind the stack to a previous frame.\n' - '\n' - 'Syntax: rewind\n' - ' rewind \n'; -} - -class ReloadCommand extends DebuggerCommand { - ReloadCommand(Debugger debugger) : super(debugger, 'reload', []); - - Future run(List args) async { - try { - int count = 1; - if (args.length > 0) { - debugger.console.print('reload expects no arguments'); - return; - } - await debugger.isolate.reloadSources(); - debugger.console.print('reload complete'); - await debugger.refreshStack(); - } on S.ServerRpcException catch(e) { - if (e.code == S.ServerRpcException.kIsolateReloadBarred || - e.code == S.ServerRpcException.kIsolateReloadFailed || - e.code == S.ServerRpcException.kIsolateIsReloading) { - debugger.console.printRed(e.data['details']); - } else { - rethrow; - } - } - } - - String helpShort = 'Reload the sources for the current isolate'; - - String helpLong = - 'Reload the sources for the current isolate.\n' - '\n' - 'Syntax: reload\n'; -} - class ClsCommand extends DebuggerCommand { ClsCommand(Debugger debugger) : super(debugger, 'cls', []) {} @@ -733,8 +663,8 @@ class BreakCommand extends DebuggerCommand { var script = loc.script; await script.load(); if (loc.line < 1 || loc.line > script.lines.length) { - debugger.console.print( - 'line number must be in range [1..${script.lines.length}]'); + debugger.console + .print('line number must be in range [1,${script.lines.length}]'); return; } try { @@ -814,7 +744,7 @@ class ClearCommand extends DebuggerCommand { var script = loc.script; if (loc.line < 1 || loc.line > script.lines.length) { debugger.console - .print('line number must be in range [1..${script.lines.length}]'); + .print('line number must be in range [1,${script.lines.length}]'); return; } var lineInfo = script.getLine(loc.line); @@ -969,6 +899,7 @@ class IsolateCommand extends DebuggerCommand { : super(debugger, 'isolate', [ new IsolateListCommand(debugger), new IsolateNameCommand(debugger), + new IsolateReloadCommand(debugger), ]) { alias = 'i'; } @@ -1111,6 +1042,27 @@ class IsolateNameCommand extends DebuggerCommand { 'Syntax: isolate name \n'; } +class IsolateReloadCommand extends DebuggerCommand { + IsolateReloadCommand(Debugger debugger) : super(debugger, 'reload', []); + + Future run(List args) async { + if (debugger.isolate == null) { + debugger.console.print('There is no current vm'); + return; + } + + await debugger.isolate.reloadSources(); + + debugger.console.print('Isolate reloading....'); + } + + String helpShort = 'Reload the sources for the current isolate.'; + + String helpLong = 'Reload the sources for the current isolate.\n' + '\n' + 'Syntax: reload\n'; +} + class InfoCommand extends DebuggerCommand { InfoCommand(Debugger debugger) : super(debugger, 'info', [ @@ -1419,9 +1371,7 @@ class ObservatoryDebugger extends Debugger { new LogCommand(this), new PauseCommand(this), new PrintCommand(this), - new ReloadCommand(this), new RefreshCommand(this), - new RewindCommand(this), new SetCommand(this), new SmartNextCommand(this), new StepCommand(this), @@ -1929,20 +1879,6 @@ class ObservatoryDebugger extends Debugger { return new Future.value(null); } } - - Future rewind(int count) { - if (isolatePaused()) { - var event = isolate.pauseEvent; - if (event is M.PauseExitEvent) { - console.print("Type 'continue' [F7] to exit the isolate"); - return new Future.value(null); - } - return isolate.rewind(count); - } else { - console.print('The program must be paused'); - return new Future.value(null); - } - } } class DebuggerPageElement extends HtmlElement implements Renderable { @@ -2577,9 +2513,7 @@ class DebuggerFrameElement extends HtmlElement implements Renderable { } bool matchFrame(S.Frame newFrame) { - return (newFrame.function.id == _frame.function.id && - newFrame.location.script.id == - frame.location.script.id); + return newFrame.function.id == _frame.function.id; } void updateFrame(S.Frame newFrame) { diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart index 13202aa8cf7..c638dd90d9f 100644 --- a/runtime/observatory/lib/src/service/object.dart +++ b/runtime/observatory/lib/src/service/object.dart @@ -42,13 +42,11 @@ class ServerRpcException extends RpcException implements M.RequestException { static const kStreamNotSubscribed = 104; static const kIsolateMustBeRunnable = 105; static const kIsolateMustBePaused = 106; - static const kCannotResume = 107; static const kIsolateIsReloading = 1000; static const kFileSystemAlreadyExists = 1001; static const kFileSystemDoesNotExist = 1002; static const kFileDoesNotExist = 1003; static const kIsolateReloadFailed = 1004; - static const kIsolateReloadBarred = 1005; int code; Map data; @@ -1281,6 +1279,7 @@ class Isolate extends ServiceObjectOwner implements M.Isolate { bool loading = true; bool runnable = false; bool ioEnabled = false; + bool reloading = false; M.IsolateStatus get status { if (paused) { return M.IsolateStatus.paused; @@ -1345,12 +1344,13 @@ class Isolate extends ServiceObjectOwner implements M.Isolate { params['pause'] = pause; } return invokeRpc('reloadSources', params).then((result) { - _cache.clear(); + reloading = true; return result; }); } void _handleIsolateReloadEvent(ServiceEvent event) { + reloading = false; if (event.reloadError != null) { // Failure. print('Reload failed: ${event.reloadError}'); @@ -1768,10 +1768,6 @@ class Isolate extends ServiceObjectOwner implements M.Isolate { return invokeRpc('resume', {'step': 'Out'}); } - Future rewind(int count) { - return invokeRpc('resume', {'step': 'Rewind', 'frameIndex': count}); - } - Future setName(String newName) { return invokeRpc('setName', {'name': newName}); } diff --git a/runtime/observatory/tests/service/pause_idle_isolate_test.dart b/runtime/observatory/tests/service/pause_idle_isolate_test.dart index d042f4b8558..484230b2cad 100644 --- a/runtime/observatory/tests/service/pause_idle_isolate_test.dart +++ b/runtime/observatory/tests/service/pause_idle_isolate_test.dart @@ -52,6 +52,5 @@ hasStoppedAtBreakpoint, main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain, - verbose_vm: true, - extraArgs: [ '--trace-service', - '--trace-service-verbose' ]); + trace_service: true, + verbose_vm: true); diff --git a/runtime/observatory/tests/service/pause_on_start_and_exit_test.dart b/runtime/observatory/tests/service/pause_on_start_and_exit_test.dart index b292b31d811..146be22ae44 100644 --- a/runtime/observatory/tests/service/pause_on_start_and_exit_test.dart +++ b/runtime/observatory/tests/service/pause_on_start_and_exit_test.dart @@ -86,6 +86,5 @@ main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain, pause_on_start: true, pause_on_exit: true, - verbose_vm: true, - extraArgs: [ '--trace-service', - '--trace-service-verbose' ]); + trace_service: true, + verbose_vm: true); diff --git a/runtime/observatory/tests/service/pause_on_start_then_step_test.dart b/runtime/observatory/tests/service/pause_on_start_then_step_test.dart index 480d9846881..107d2ee8ce3 100644 --- a/runtime/observatory/tests/service/pause_on_start_then_step_test.dart +++ b/runtime/observatory/tests/service/pause_on_start_then_step_test.dart @@ -89,6 +89,5 @@ main(args) => runIsolateTests(args, tests, testeeConcurrent: testMain, pause_on_start: true, pause_on_exit: true, - verbose_vm: true, - extraArgs: [ '--trace-service', - '--trace-service-verbose' ]); + trace_service: true, + verbose_vm: true); diff --git a/runtime/observatory/tests/service/rewind_optimized_out_test.dart b/runtime/observatory/tests/service/rewind_optimized_out_test.dart deleted file mode 100644 index 23b8c9a9a67..00000000000 --- a/runtime/observatory/tests/service/rewind_optimized_out_test.dart +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2016, 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=--error_on_bad_type --error_on_bad_override - -import 'dart:developer'; -import 'package:observatory/service_io.dart'; -import 'package:unittest/unittest.dart'; -import 'service_test_common.dart'; -import 'test_helper.dart'; - -const alwaysInline = "AlwaysInline"; -const noInline = "NeverInline"; - -int LINE_A = 35; -int LINE_B = 40; -int LINE_C = 43; -int LINE_D = 47; - -int global = 0; - -@noInline -b3(x) { - int sum = 0; - try { - for (int i = 0; i < x; i++) { - sum += x; - } - } catch (e) { - print("caught $e"); - } - if (global >= 100) { - debugger(); - } - global = global + 1; // Line A - return sum; -} - -@alwaysInline -b2(x) => b3(x); // Line B - -@alwaysInline -b1(x) => b2(x); // Line C - -test() { - while (true) { - b1(10000); // Line D - } -} - -var tests = [ - hasStoppedAtBreakpoint, - stoppedAtLine(LINE_A), - - (Isolate isolate) async { - // We are at our breakpoint with global=100. - var result = await isolate.rootLibrary.evaluate('global'); - print('global is $result'); - expect(result.type, equals('Instance')); - expect(result.valueAsString, equals('100')); - - // Rewind the top stack frame. - bool caughtException; - try { - result = await isolate.rewind(1); - expect(false, isTrue, reason:'Unreachable'); - } on ServerRpcException catch(e) { - caughtException = true; - expect(e.code, equals(ServerRpcException.kCannotResume)); - expect(e.message, - 'Cannot rewind to frame 1 due to conflicting compiler ' - 'optimizations. Run the vm with --no-prune-dead-locals to ' - 'disallow these optimizations. Next valid rewind frame is 4.'); - } - expect(caughtException, isTrue); - }, -]; - - -main(args) => runIsolateTests(args, tests, testeeConcurrent: test, - extraArgs: - ['--trace-rewind', - '--prune-dead-locals', - '--enable-inlining-annotations', - '--no-background-compilation', - '--optimization-counter-threshold=10']); diff --git a/runtime/observatory/tests/service/rewind_test.dart b/runtime/observatory/tests/service/rewind_test.dart deleted file mode 100644 index 152d711d40d..00000000000 --- a/runtime/observatory/tests/service/rewind_test.dart +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) 2016, 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=--error_on_bad_type --error_on_bad_override - -import 'dart:developer'; -import 'package:observatory/service_io.dart'; -import 'package:unittest/unittest.dart'; -import 'service_test_common.dart'; -import 'test_helper.dart'; - -const alwaysInline = "AlwaysInline"; -const noInline = "NeverInline"; - -int LINE_A = 35; -int LINE_B = 40; -int LINE_C = 43; -int LINE_D = 47; - -int global = 0; - -@noInline -b3(x) { - int sum = 0; - try { - for (int i = 0; i < x; i++) { - sum += x; - } - } catch (e) { - print("caught $e"); - } - if (global >= 100) { - debugger(); - } - global = global + 1; // Line A - return sum; -} - -@alwaysInline -b2(x) => b3(x); // Line B - -@alwaysInline -b1(x) => b2(x); // Line C - -test() { - while (true) { - b1(10000); // Line D - } -} - -var tests = [ - hasStoppedAtBreakpoint, - stoppedAtLine(LINE_A), - - (Isolate isolate) async { - // We are not able to rewind frame 0. - bool caughtException; - try { - await isolate.rewind(0); - expect(false, isTrue, reason:'Unreachable'); - } on ServerRpcException catch(e) { - caughtException = true; - expect(e.code, equals(ServerRpcException.kCannotResume)); - expect(e.message, 'Frame must be in bounds [1..9]: saw 0'); - } - expect(caughtException, isTrue); - }, - - (Isolate isolate) async { - // We are not able to rewind frame 10. - bool caughtException; - try { - await isolate.rewind(10); - expect(false, isTrue, reason:'Unreachable'); - } on ServerRpcException catch(e) { - caughtException = true; - expect(e.code, equals(ServerRpcException.kCannotResume)); - expect(e.message, 'Frame must be in bounds [1..9]: saw 10'); - } - expect(caughtException, isTrue); - }, - - (Isolate isolate) async { - // We are at our breakpoint with global=100. - var result = await isolate.rootLibrary.evaluate('global'); - print('global is $result'); - expect(result.type, equals('Instance')); - expect(result.valueAsString, equals('100')); - - // Rewind the top stack frame. - result = await isolate.rewind(1); - expect(result['type'], equals('Success')); - }, - - hasStoppedAtBreakpoint, - stoppedAtLine(LINE_B), - - (Isolate isolate) async { - var result = await isolate.resume(); - expect(result['type'], equals('Success')); - }, - - hasStoppedAtBreakpoint, - stoppedAtLine(LINE_A), - - (Isolate isolate) async { - // global still is equal to 100. We did not execute "global++". - var result = await isolate.rootLibrary.evaluate('global'); - print('global is $result'); - expect(result.type, equals('Instance')); - expect(result.valueAsString, equals('100')); - - // Resume again, for fun. - result = await isolate.resume(); - expect(result['type'], equals('Success')); - }, - - hasStoppedAtBreakpoint, - stoppedAtLine(LINE_A), - - (Isolate isolate) async { - // global is now 101. - var result = await isolate.rootLibrary.evaluate('global'); - print('global is $result'); - expect(result.type, equals('Instance')); - expect(result.valueAsString, equals('101')); - - // Rewind up to 'test'/ - result = await isolate.rewind(3); - expect(result['type'], equals('Success')); - }, - - hasStoppedAtBreakpoint, - stoppedAtLine(LINE_D), - - (Isolate isolate) async { - // Reset global to 0 and start again. - var result = await isolate.rootLibrary.evaluate('global=0'); - print('set global to $result'); - expect(result.type, equals('Instance')); - expect(result.valueAsString, equals('0')); - - result = await isolate.resume(); - expect(result['type'], equals('Success')); - }, - - hasStoppedAtBreakpoint, - stoppedAtLine(LINE_A), - - (Isolate isolate) async { - // We are at our breakpoint with global=100. - var result = await isolate.rootLibrary.evaluate('global'); - print('global is $result'); - expect(result.type, equals('Instance')); - expect(result.valueAsString, equals('100')); - - // Rewind the top 2 stack frames. - result = await isolate.rewind(2); - expect(result['type'], equals('Success')); - }, - - hasStoppedAtBreakpoint, - stoppedAtLine(LINE_C), -]; - - -main(args) => runIsolateTests(args, tests, testeeConcurrent: test, - extraArgs: - ['--trace-rewind', - '--no-prune-dead-locals', - '--enable-inlining-annotations', - '--no-background-compilation', - '--optimization-counter-threshold=10']); diff --git a/runtime/observatory/tests/service/service.status b/runtime/observatory/tests/service/service.status index 18d213acb21..bb0c4331206 100644 --- a/runtime/observatory/tests/service/service.status +++ b/runtime/observatory/tests/service/service.status @@ -63,8 +63,6 @@ evaluate_activation_in_method_class_test: CompileTimeError # Issue 24478 get_allocation_samples_test: RuntimeError # Profiling unimplemented. get_cpu_profile_timeline_rpc_test: RuntimeError # Profiling unimplemented. implicit_getter_setter_test: RuntimeError # Field guards unimplemented. -rewind_test: RuntimeError # Issue 27878 -rewind_optimized_out_test: RuntimeError # Issue 27878 [ $hot_reload || $hot_reload_rollback ] # Skip all service tests because random reloads interfere. diff --git a/runtime/observatory/tests/service/service_test_common.dart b/runtime/observatory/tests/service/service_test_common.dart index 243b41a2c4e..2a68a528c6b 100644 --- a/runtime/observatory/tests/service/service_test_common.dart +++ b/runtime/observatory/tests/service/service_test_common.dart @@ -234,10 +234,6 @@ IsolateTest stoppedAtLine(int line) { return (Isolate isolate) async { print("Checking we are at line $line"); - // Make sure that the isolate has stopped. - isolate.reload(); - expect(isolate.pauseEvent is! M.ResumeEvent, isTrue); - ServiceMap stack = await isolate.getStack(); expect(stack.type, equals('Stack')); diff --git a/runtime/observatory/tests/service/set_vm_name_rpc_test.dart b/runtime/observatory/tests/service/set_vm_name_rpc_test.dart index 8554ad3f275..7e3a53a8e6f 100644 --- a/runtime/observatory/tests/service/set_vm_name_rpc_test.dart +++ b/runtime/observatory/tests/service/set_vm_name_rpc_test.dart @@ -32,6 +32,4 @@ var tests = [ }, ]; -main(args) async => runVMTests(args, tests, - extraArgs: [ '--trace-service', - '--trace-service-verbose' ]); +main(args) async => runVMTests(args, tests, trace_service: true); diff --git a/runtime/observatory/tests/service/step_over_await_test.dart b/runtime/observatory/tests/service/step_over_await_test.dart index d5f946cb937..1bbb3b791b7 100644 --- a/runtime/observatory/tests/service/step_over_await_test.dart +++ b/runtime/observatory/tests/service/step_over_await_test.dart @@ -1,7 +1,7 @@ // Copyright (c) 2015, 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=--error_on_bad_type --error_on_bad_override --verbose_debug +// VMOptions=--error_on_bad_type --error_on_bad_override --verbose_debug --trace_service import 'dart:async'; import 'dart:developer'; diff --git a/runtime/observatory/tests/service/test_helper.dart b/runtime/observatory/tests/service/test_helper.dart index f444bf83be1..9e8caa883ff 100644 --- a/runtime/observatory/tests/service/test_helper.dart +++ b/runtime/observatory/tests/service/test_helper.dart @@ -90,12 +90,15 @@ class _ServiceTesteeLauncher { Future _spawnProcess(bool pause_on_start, bool pause_on_exit, bool pause_on_unhandled_exceptions, + bool trace_service, + bool trace_compiler, bool testeeControlsServer, - bool useAuthToken, - List extraArgs) { + bool useAuthToken) { assert(pause_on_start != null); assert(pause_on_exit != null); assert(pause_on_unhandled_exceptions != null); + assert(trace_service != null); + assert(trace_compiler != null); assert(testeeControlsServer != null); assert(useAuthToken != null); @@ -103,29 +106,39 @@ class _ServiceTesteeLauncher { return _spawnSkyProcess(pause_on_start, pause_on_exit, pause_on_unhandled_exceptions, - testeeControlsServer, - extraArgs); + trace_service, + trace_compiler, + testeeControlsServer); } else { return _spawnDartProcess(pause_on_start, pause_on_exit, pause_on_unhandled_exceptions, + trace_service, + trace_compiler, testeeControlsServer, - useAuthToken, - extraArgs); + useAuthToken); } } Future _spawnDartProcess(bool pause_on_start, bool pause_on_exit, bool pause_on_unhandled_exceptions, + bool trace_service, + bool trace_compiler, bool testeeControlsServer, - bool useAuthToken, - List extraArgs) { + bool useAuthToken) { assert(!_shouldLaunchSkyShell()); String dartExecutable = Platform.executable; var fullArgs = []; + if (trace_service) { + fullArgs.add('--trace-service'); + fullArgs.add('--trace-service-verbose'); + } + if (trace_compiler) { + fullArgs.add('--trace-compiler'); + } if (pause_on_start) { fullArgs.add('--pause-isolates-on-start'); } @@ -135,9 +148,6 @@ class _ServiceTesteeLauncher { if (pause_on_unhandled_exceptions) { fullArgs.add('--pause-isolates-on-unhandled-exceptions'); } - if (extraArgs != null) { - fullArgs.addAll(extraArgs); - } fullArgs.addAll(Platform.executableArguments); if (!testeeControlsServer) { @@ -156,14 +166,22 @@ class _ServiceTesteeLauncher { Future _spawnSkyProcess(bool pause_on_start, bool pause_on_exit, bool pause_on_unhandled_exceptions, - bool testeeControlsServer, - List extraArgs) { + bool trace_service, + bool trace_compiler, + bool testeeControlsServer) { assert(_shouldLaunchSkyShell()); String dartExecutable = _skyShellPath(); var dartFlags = []; var fullArgs = []; + if (trace_service) { + dartFlags.add('--trace_service'); + dartFlags.add('--trace_service_verbose'); + } + if (trace_compiler) { + dartFlags.add('--trace_compiler'); + } if (pause_on_start) { dartFlags.add('--pause_isolates_on_start'); fullArgs.add('--start-paused'); @@ -176,9 +194,6 @@ class _ServiceTesteeLauncher { } // Override mirrors. dartFlags.add('--enable_mirrors=true'); - if (extraArgs != null) { - fullArgs.addAll(extraArgs); - } fullArgs.addAll(Platform.executableArguments); if (!testeeControlsServer) { @@ -208,15 +223,17 @@ class _ServiceTesteeLauncher { Future launch(bool pause_on_start, bool pause_on_exit, bool pause_on_unhandled_exceptions, + bool trace_service, + bool trace_compiler, bool testeeControlsServer, - bool useAuthToken, - List extraArgs) { + bool useAuthToken) { return _spawnProcess(pause_on_start, pause_on_exit, pause_on_unhandled_exceptions, + trace_service, + trace_compiler, testeeControlsServer, - useAuthToken, - extraArgs).then((p) { + useAuthToken).then((p) { Completer completer = new Completer(); process = p; Uri uri; @@ -271,11 +288,12 @@ void setupAddresses(Uri serverAddress) { class _ServiceTesterRunner { void run({List mainArgs, - List extraArgs, List vmTests, List isolateTests, bool pause_on_start: false, bool pause_on_exit: false, + bool trace_service: false, + bool trace_compiler: false, bool verbose_vm: false, bool pause_on_unhandled_exceptions: false, bool testeeControlsServer: false, @@ -283,8 +301,9 @@ class _ServiceTesterRunner { var process = new _ServiceTesteeLauncher(); process.launch(pause_on_start, pause_on_exit, pause_on_unhandled_exceptions, + trace_service, trace_compiler, testeeControlsServer, - useAuthToken, extraArgs).then((Uri serverAddress) async { + useAuthToken).then((Uri serverAddress) async { if (mainArgs.contains("--gdb")) { var pid = process.process.pid; var wait = new Duration(seconds: 10); @@ -345,11 +364,12 @@ Future runIsolateTests(List mainArgs, testeeConcurrent(), bool pause_on_start: false, bool pause_on_exit: false, + bool trace_service: false, + bool trace_compiler: false, bool verbose_vm: false, bool pause_on_unhandled_exceptions: false, bool testeeControlsServer: false, - bool useAuthToken: false, - List extraArgs}) async { + bool useAuthToken: false}) async { assert(!pause_on_start || testeeBefore == null); if (_isTestee()) { new _ServiceTesteeRunner().run(testeeBefore: testeeBefore, @@ -359,10 +379,11 @@ Future runIsolateTests(List mainArgs, } else { new _ServiceTesterRunner().run( mainArgs: mainArgs, - extraArgs: extraArgs, isolateTests: tests, pause_on_start: pause_on_start, pause_on_exit: pause_on_exit, + trace_service: trace_service, + trace_compiler: trace_compiler, verbose_vm: verbose_vm, pause_on_unhandled_exceptions: pause_on_unhandled_exceptions, testeeControlsServer: testeeControlsServer, @@ -385,9 +406,10 @@ void runIsolateTestsSynchronous(List mainArgs, void testeeConcurrent(), bool pause_on_start: false, bool pause_on_exit: false, + bool trace_service: false, + bool trace_compiler: false, bool verbose_vm: false, - bool pause_on_unhandled_exceptions: false, - List extraArgs}) { + bool pause_on_unhandled_exceptions: false}) { assert(!pause_on_start || testeeBefore == null); if (_isTestee()) { new _ServiceTesteeRunner().runSync(testeeBeforeSync: testeeBefore, @@ -397,10 +419,11 @@ void runIsolateTestsSynchronous(List mainArgs, } else { new _ServiceTesterRunner().run( mainArgs: mainArgs, - extraArgs: extraArgs, isolateTests: tests, pause_on_start: pause_on_start, pause_on_exit: pause_on_exit, + trace_service: trace_service, + trace_compiler: trace_compiler, verbose_vm: verbose_vm, pause_on_unhandled_exceptions: pause_on_unhandled_exceptions); } @@ -417,9 +440,10 @@ Future runVMTests(List mainArgs, testeeConcurrent(), bool pause_on_start: false, bool pause_on_exit: false, + bool trace_service: false, + bool trace_compiler: false, bool verbose_vm: false, - bool pause_on_unhandled_exceptions: false, - List extraArgs}) async { + bool pause_on_unhandled_exceptions: false}) async { if (_isTestee()) { new _ServiceTesteeRunner().run(testeeBefore: testeeBefore, testeeConcurrent: testeeConcurrent, @@ -428,10 +452,11 @@ Future runVMTests(List mainArgs, } else { new _ServiceTesterRunner().run( mainArgs: mainArgs, - extraArgs: extraArgs, vmTests: tests, pause_on_start: pause_on_start, pause_on_exit: pause_on_exit, + trace_service: trace_service, + trace_compiler: trace_compiler, verbose_vm: verbose_vm, pause_on_unhandled_exceptions: pause_on_unhandled_exceptions); } diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc index b2fca6b9229..4a35895f3fa 100644 --- a/runtime/vm/code_generator.cc +++ b/runtime/vm/code_generator.cc @@ -2215,14 +2215,6 @@ DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { } -DEFINE_RUNTIME_ENTRY(RewindPostDeopt, 0) { -#if !defined(DART_PRECOMPILED_RUNTIME) - isolate->debugger()->RewindPostDeopt(); -#else - UNREACHABLE(); -#endif // !DART_PRECOMPILED_RUNTIME -} - DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, BigintCompare, 2, diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc index ae0f13f0713..3346befc81d 100644 --- a/runtime/vm/dart_entry.cc +++ b/runtime/vm/dart_entry.cc @@ -551,7 +551,7 @@ RawObject* DartLibraryCalls::HandleMessage(const Object& handler, // If the isolate is being debugged and the debugger was stepping // through code, enable single stepping so debugger will stop // at the first location the user is interested in. - isolate->debugger()->SetResumeAction(Debugger::kStepInto); + isolate->debugger()->SetSingleStep(); } const Object& result = Object::Handle(zone, DartEntry::InvokeFunction(function, args)); diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc index 5c54271bc56..3cdf810c8d6 100644 --- a/runtime/vm/debugger.cc +++ b/runtime/vm/debugger.cc @@ -6,8 +6,6 @@ #include "include/dart_api.h" -#include "platform/address_sanitizer.h" - #include "vm/code_generator.h" #include "vm/code_patcher.h" #include "vm/compiler.h" @@ -44,7 +42,6 @@ DEFINE_FLAG(bool, trace_debugger_stacktrace, false, "Trace debugger stacktrace collection"); -DEFINE_FLAG(bool, trace_rewind, false, "Trace frame rewind"); DEFINE_FLAG(bool, verbose_debug, false, "Verbose debugger messages"); DEFINE_FLAG(bool, steal_breakpoints, @@ -853,24 +850,6 @@ RawObject* ActivationFrame::GetStackVar(intptr_t slot_index) { } -bool ActivationFrame::IsRewindable() const { - if (deopt_frame_.IsNull()) { - return true; - } - // TODO(turnidge): This is conservative. It looks at all values in - // the deopt_frame_ even though some of them may correspond to other - // inlined frames. - Object& obj = Object::Handle(); - for (int i = 0; i < deopt_frame_.Length(); i++) { - obj = deopt_frame_.At(i); - if (obj.raw() == Symbols::OptimizedOut().raw()) { - return false; - } - } - return true; -} - - void ActivationFrame::PrintContextMismatchError(intptr_t ctx_slot, intptr_t frame_ctx_level, intptr_t var_ctx_level) { @@ -1129,13 +1108,9 @@ void ActivationFrame::PrintToJSONObject(JSONObject* jsobj, bool full) { } } -static bool IsFunctionVisible(const Function& function) { - return FLAG_show_invisible_frames || function.is_visible(); -} - void DebuggerStackTrace::AddActivation(ActivationFrame* frame) { - if (IsFunctionVisible(frame->function())) { + if (FLAG_show_invisible_frames || frame->function().is_visible()) { trace_.Add(frame); } } @@ -1262,8 +1237,6 @@ Debugger::Debugger() breakpoint_locations_(NULL), code_breakpoints_(NULL), resume_action_(kContinue), - resume_frame_index_(-1), - post_deopt_frame_index_(-1), ignore_breakpoints_(false), pause_event_(NULL), obj_cache_(NULL), @@ -1327,13 +1300,10 @@ static RawFunction* ResolveLibraryFunction(const Library& library, } -bool Debugger::SetupStepOverAsyncSuspension(const char** error) { +bool Debugger::SetupStepOverAsyncSuspension() { ActivationFrame* top_frame = TopDartFrame(); if (!IsAtAsyncJump(top_frame)) { // Not at an async operation. - if (error) { - *error = "Isolate must be paused at an async suspension point"; - } return false; } Object& closure = Object::Handle(top_frame->GetAsyncOperation()); @@ -1343,42 +1313,24 @@ bool Debugger::SetupStepOverAsyncSuspension(const char** error) { Breakpoint* bpt = SetBreakpointAtActivation(Instance::Cast(closure), true); if (bpt == NULL) { // Unable to set the breakpoint. - if (error) { - *error = "Unable to set breakpoint at async suspension point"; - } return false; } return true; } -bool Debugger::SetResumeAction(ResumeAction action, - intptr_t frame_index, - const char** error) { - if (error) { - *error = NULL; - } - resume_frame_index_ = -1; - switch (action) { - case kStepInto: - case kStepOver: - case kStepOut: - case kContinue: - resume_action_ = action; - return true; - case kStepRewind: - if (!CanRewindFrame(frame_index, error)) { - return false; - } - resume_action_ = kStepRewind; - resume_frame_index_ = frame_index; - return true; - case kStepOverAsyncSuspension: - return SetupStepOverAsyncSuspension(error); - default: - UNREACHABLE(); - return false; - } +void Debugger::SetSingleStep() { + resume_action_ = kSingleStep; +} + + +void Debugger::SetStepOver() { + resume_action_ = kStepOver; +} + + +void Debugger::SetStepOut() { + resume_action_ = kStepOut; } @@ -1670,7 +1622,6 @@ void Debugger::PauseException(const Instance& exc) { ASSERT(stack_trace_ == NULL); stack_trace_ = stack_trace; Pause(&event); - HandleSteppingRequest(stack_trace_); // we may get a rewind request stack_trace_ = NULL; } @@ -2596,7 +2547,7 @@ void Debugger::EnterSingleStepMode() { void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace, bool skip_next_step) { stepping_fp_ = 0; - if (resume_action_ == kStepInto) { + if (resume_action_ == kSingleStep) { // When single stepping, we need to deoptimize because we might be // stepping into optimized code. This happens in particular if // the isolate has been interrupted, but can happen in other cases @@ -2606,7 +2557,7 @@ void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace, isolate_->set_single_step(true); skip_next_step_ = skip_next_step; if (FLAG_verbose_debug) { - OS::Print("HandleSteppingRequest- kStepInto\n"); + OS::Print("HandleSteppingRequest- kSingleStep\n"); } } else if (resume_action_ == kStepOver) { DeoptimizeWorld(); @@ -2631,244 +2582,6 @@ void Debugger::HandleSteppingRequest(DebuggerStackTrace* stack_trace, if (FLAG_verbose_debug) { OS::Print("HandleSteppingRequest- kStepOut %" Px "\n", stepping_fp_); } - } else if (resume_action_ == kStepRewind) { - if (FLAG_trace_rewind) { - OS::PrintErr("Rewinding to frame %" Pd "\n", resume_frame_index_); - OS::PrintErr( - "-------------------------\n" - "All frames...\n\n"); - StackFrameIterator iterator(false); - StackFrame* frame = iterator.NextFrame(); - intptr_t num = 0; - while ((frame != NULL)) { - OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); - frame = iterator.NextFrame(); - } - } - RewindToFrame(resume_frame_index_); - UNREACHABLE(); - } -} - - -static intptr_t FindNextRewindFrameIndex(DebuggerStackTrace* stack, - intptr_t frame_index) { - for (intptr_t i = frame_index + 1; i < stack->Length(); i++) { - ActivationFrame* frame = stack->FrameAt(i); - if (frame->IsRewindable()) { - return i; - } - } - return -1; -} - - -// Can the top frame be rewound? -bool Debugger::CanRewindFrame(intptr_t frame_index, const char** error) const { - // check rewind pc is found - DebuggerStackTrace* stack = Isolate::Current()->debugger()->StackTrace(); - intptr_t num_frames = stack->Length(); - if (frame_index < 1 || frame_index >= num_frames) { - if (error) { - *error = Thread::Current()->zone()->PrintToString( - "Frame must be in bounds [1..%" Pd - "]: " - "saw %" Pd "", - num_frames - 1, frame_index); - } - return false; - } - ActivationFrame* frame = stack->FrameAt(frame_index); - if (!frame->IsRewindable()) { - intptr_t next_index = FindNextRewindFrameIndex(stack, frame_index); - if (next_index > 0) { - *error = Thread::Current()->zone()->PrintToString( - "Cannot rewind to frame %" Pd - " due to conflicting compiler " - "optimizations. " - "Run the vm with --no-prune-dead-locals to disallow these " - "optimizations. " - "Next valid rewind frame is %" Pd ".", - frame_index, next_index); - } else { - *error = Thread::Current()->zone()->PrintToString( - "Cannot rewind to frame %" Pd - " due to conflicting compiler " - "optimizations. " - "Run the vm with --no-prune-dead-locals to disallow these " - "optimizations.", - frame_index); - } - return false; - } - return true; -} - - -// Given a return address pc, find the "rewind" pc, which is the pc -// before the corresponding call. -static uword LookupRewindPc(const Code& code, uword pc) { - ASSERT(!code.is_optimized()); - ASSERT(code.ContainsInstructionAt(pc)); - - uword pc_offset = pc - code.PayloadStart(); - const PcDescriptors& descriptors = - PcDescriptors::Handle(code.pc_descriptors()); - PcDescriptors::Iterator iter( - descriptors, RawPcDescriptors::kRewind | RawPcDescriptors::kIcCall | - RawPcDescriptors::kUnoptStaticCall); - intptr_t rewind_deopt_id = -1; - uword rewind_pc = 0; - while (iter.MoveNext()) { - if (iter.Kind() == RawPcDescriptors::kRewind) { - // Remember the last rewind so we don't need to iterator twice. - rewind_pc = code.PayloadStart() + iter.PcOffset(); - rewind_deopt_id = iter.DeoptId(); - } - if ((pc_offset == iter.PcOffset()) && (iter.DeoptId() == rewind_deopt_id)) { - return rewind_pc; - } - } - return 0; -} - - -void Debugger::RewindToFrame(intptr_t frame_index) { - Thread* thread = Thread::Current(); - Zone* zone = thread->zone(); - Code& code = Code::Handle(zone); - Function& function = Function::Handle(zone); - - // Find the requested frame. - StackFrameIterator iterator(false); - intptr_t current_frame = 0; - for (StackFrame* frame = iterator.NextFrame(); frame != NULL; - frame = iterator.NextFrame()) { - ASSERT(frame->IsValid()); - if (frame->IsDartFrame()) { - code = frame->LookupDartCode(); - function = code.function(); - if (!IsFunctionVisible(function)) { - continue; - } - if (code.is_optimized()) { - intptr_t sub_index = 0; - for (InlinedFunctionsIterator it(code, frame->pc()); !it.Done(); - it.Advance()) { - if (current_frame == frame_index) { - RewindToOptimizedFrame(frame, code, sub_index); - UNREACHABLE(); - } - current_frame++; - sub_index++; - } - } else { - if (current_frame == frame_index) { - // We are rewinding to an unoptimized frame. - RewindToUnoptimizedFrame(frame, code); - UNREACHABLE(); - } - current_frame++; - } - } - } - UNIMPLEMENTED(); -} - - -void Debugger::RewindToUnoptimizedFrame(StackFrame* frame, const Code& code) { - // We will be jumping out of the debugger rather than exiting this - // function, so prepare the debugger state. - stack_trace_ = NULL; - resume_action_ = kContinue; - resume_frame_index_ = -1; - EnterSingleStepMode(); - - uword rewind_pc = LookupRewindPc(code, frame->pc()); - if (FLAG_trace_rewind && rewind_pc == 0) { - OS::PrintErr("Unable to find rewind pc for pc(%" Px ")\n", frame->pc()); - } - ASSERT(rewind_pc != 0); - if (FLAG_trace_rewind) { - OS::PrintErr( - "===============================\n" - "Rewinding to unoptimized frame:\n" - " rewind_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px - ")\n" - "===============================\n", - rewind_pc, frame->sp(), frame->fp()); - } - Exceptions::JumpToFrame(Thread::Current(), rewind_pc, frame->sp(), - frame->fp(), true /* clear lazy deopt at target */); - UNREACHABLE(); -} - - -void Debugger::RewindToOptimizedFrame(StackFrame* frame, - const Code& optimized_code, - intptr_t sub_index) { - post_deopt_frame_index_ = sub_index; - - // We will be jumping out of the debugger rather than exiting this - // function, so prepare the debugger state. - stack_trace_ = NULL; - resume_action_ = kContinue; - resume_frame_index_ = -1; - EnterSingleStepMode(); - - if (FLAG_trace_rewind) { - OS::PrintErr( - "===============================\n" - "Deoptimizing frame for rewind:\n" - " deopt_pc(0x%" Px ") sp(0x%" Px ") fp(0x%" Px - ")\n" - "===============================\n", - frame->pc(), frame->sp(), frame->fp()); - } - Thread* thread = Thread::Current(); - thread->set_resume_pc(frame->pc()); - uword deopt_stub_pc = StubCode::DeoptForRewind_entry()->EntryPoint(); - Exceptions::JumpToFrame(thread, deopt_stub_pc, frame->sp(), frame->fp(), - true /* clear lazy deopt at target */); - UNREACHABLE(); -} - - -void Debugger::RewindPostDeopt() { - intptr_t rewind_frame = post_deopt_frame_index_; - post_deopt_frame_index_ = -1; - if (FLAG_trace_rewind) { - OS::PrintErr("Post deopt, jumping to frame %" Pd "\n", rewind_frame); - OS::PrintErr( - "-------------------------\n" - "All frames...\n\n"); - StackFrameIterator iterator(false); - StackFrame* frame = iterator.NextFrame(); - intptr_t num = 0; - while ((frame != NULL)) { - OS::PrintErr("#%04" Pd " %s\n", num++, frame->ToCString()); - frame = iterator.NextFrame(); - } - } - - Thread* thread = Thread::Current(); - Zone* zone = thread->zone(); - Code& code = Code::Handle(zone); - - StackFrameIterator iterator(false); - intptr_t current_frame = 0; - for (StackFrame* frame = iterator.NextFrame(); frame != NULL; - frame = iterator.NextFrame()) { - ASSERT(frame->IsValid()); - if (frame->IsDartFrame()) { - code = frame->LookupDartCode(); - ASSERT(!code.is_optimized()); - if (current_frame == rewind_frame) { - RewindToUnoptimizedFrame(frame, code); - UNREACHABLE(); - } - current_frame++; - } } } @@ -3080,7 +2793,7 @@ RawError* Debugger::PauseBreakpoint() { // We are at the entry of an async function. // We issue a step over to resume at the point after the await statement. - SetResumeAction(kStepOver); + SetStepOver(); // When we single step from a user breakpoint, our next stepping // point will be at the exact same pc. Skip it. HandleSteppingRequest(stack_trace_, true /* skip next step */); @@ -3133,7 +2846,7 @@ void Debugger::PauseDeveloper(const String& msg) { // We are in the native call to Developer_debugger. the developer // gets a better experience by not seeing this call. To accomplish // this, we continue execution until the call exits (step out). - SetResumeAction(kStepOut); + SetStepOut(); HandleSteppingRequest(stack_trace_); stack_trace_ = NULL; diff --git a/runtime/vm/debugger.h b/runtime/vm/debugger.h index 74fd1ea5a5e..7319c8e41fd 100644 --- a/runtime/vm/debugger.h +++ b/runtime/vm/debugger.h @@ -276,9 +276,6 @@ class ActivationFrame : public ZoneAllocated { // to the user and can be debugged. bool IsDebuggable() const; - // Returns true if it is possible to rewind the debugger to this frame. - bool IsRewindable() const; - // The context level of a frame is the context level at the // PC/token index of the frame. It determines the depth of the context // chain that belongs to the function of this activation frame. @@ -376,15 +373,6 @@ class DebuggerStackTrace : public ZoneAllocated { class Debugger { public: - enum ResumeAction { - kContinue, - kStepInto, - kStepOver, - kStepOut, - kStepRewind, - kStepOverAsyncSuspension, - }; - typedef void EventHandler(ServiceEvent* event); Debugger(); @@ -424,10 +412,11 @@ class Debugger { void RemoveBreakpoint(intptr_t bp_id); Breakpoint* GetBreakpointById(intptr_t id); - bool SetResumeAction(ResumeAction action, - intptr_t frame_index = 1, - const char** error = NULL); - + // Will return false if we are not at an await. + bool SetupStepOverAsyncSuspension(); + void SetStepOver(); + void SetSingleStep(); + void SetStepOut(); bool IsStepping() const { return resume_action_ != kContinue; } bool IsPaused() const { return pause_event_ != NULL; } @@ -524,14 +513,10 @@ class Debugger { intptr_t limitBreakpointId() { return next_id_; } - // Callback to the debugger to continue frame rewind, post-deoptimization. - void RewindPostDeopt(); - private: - RawError* PauseRequest(ServiceEvent::EventKind kind); + enum ResumeAction { kContinue, kStepOver, kStepOut, kSingleStep }; - // Will return false if we are not at an await. - bool SetupStepOverAsyncSuspension(const char** error); + RawError* PauseRequest(ServiceEvent::EventKind kind); bool NeedsIsolateEvents(); bool NeedsDebugEvents(); @@ -603,15 +588,6 @@ class Debugger { void HandleSteppingRequest(DebuggerStackTrace* stack_trace, bool skip_next_step = false); - // Can we rewind to the indicated frame? - bool CanRewindFrame(intptr_t frame_index, const char** error) const; - - void RewindToFrame(intptr_t frame_index); - void RewindToUnoptimizedFrame(StackFrame* frame, const Code& code); - void RewindToOptimizedFrame(StackFrame* frame, - const Code& code, - intptr_t post_deopt_frame_index); - Isolate* isolate_; Dart_Port isolate_id_; // A unique ID for the isolate in the debugger. bool initialized_; @@ -625,8 +601,6 @@ class Debugger { // Tells debugger what to do when resuming execution after a breakpoint. ResumeAction resume_action_; - intptr_t resume_frame_index_; - intptr_t post_deopt_frame_index_; // Do not call back to breakpoint handler if this flag is set. // Effectively this means ignoring breakpoints. Set when Dart code may diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc index 77b7b272fc4..71610d2b096 100644 --- a/runtime/vm/debugger_api_impl.cc +++ b/runtime/vm/debugger_api_impl.cc @@ -485,7 +485,7 @@ DART_EXPORT Dart_Handle Dart_SetStepOver() { DARTSCOPE(Thread::Current()); Isolate* I = T->isolate(); CHECK_DEBUGGER(I); - I->debugger()->SetResumeAction(Debugger::kStepOver); + I->debugger()->SetStepOver(); return Api::Success(); } @@ -494,7 +494,7 @@ DART_EXPORT Dart_Handle Dart_SetStepInto() { DARTSCOPE(Thread::Current()); Isolate* I = T->isolate(); CHECK_DEBUGGER(I); - I->debugger()->SetResumeAction(Debugger::kStepInto); + I->debugger()->SetSingleStep(); return Api::Success(); } @@ -503,7 +503,7 @@ DART_EXPORT Dart_Handle Dart_SetStepOut() { DARTSCOPE(Thread::Current()); Isolate* I = T->isolate(); CHECK_DEBUGGER(I); - I->debugger()->SetResumeAction(Debugger::kStepOut); + I->debugger()->SetStepOut(); return Api::Success(); } diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc index 560de5541be..71eb55aea03 100644 --- a/runtime/vm/exceptions.cc +++ b/runtime/vm/exceptions.cc @@ -189,6 +189,7 @@ static bool FindExceptionHandler(Thread* thread, static void FindErrorHandler(uword* handler_pc, uword* handler_sp, uword* handler_fp) { + // TODO(turnidge): Is there a faster way to get the next entry frame? StackFrameIterator frames(StackFrameIterator::kDontValidateFrames); StackFrame* frame = frames.NextFrame(); ASSERT(frame != NULL); @@ -227,17 +228,7 @@ static uword RemapExceptionPCForDeopt(Thread* thread, break; } } - } -#endif // !DBC - return program_counter; -} - -static void ClearLazyDeopts(Thread* thread, uword frame_pointer) { -#if !defined(TARGET_ARCH_DBC) - MallocGrowableArray* pending_deopts = - thread->isolate()->pending_deopts(); - if (pending_deopts->length() > 0) { // We may be jumping over frames scheduled for lazy deopt. Remove these // frames from the pending deopt table, but only after unmarking them so // any stack walk that happens before the stack is unwound will still work. @@ -273,6 +264,7 @@ static void ClearLazyDeopts(Thread* thread, uword frame_pointer) { #endif } #endif // !DBC + return program_counter; } @@ -289,18 +281,14 @@ static void JumpToExceptionHandler(Thread* thread, thread->set_resume_pc(remapped_pc); uword run_exception_pc = StubCode::RunExceptionHandler_entry()->EntryPoint(); Exceptions::JumpToFrame(thread, run_exception_pc, stack_pointer, - frame_pointer, false /* do not clear deopt */); + frame_pointer); } void Exceptions::JumpToFrame(Thread* thread, uword program_counter, uword stack_pointer, - uword frame_pointer, - bool clear_deopt_at_target) { - uword fp_for_clearing = - (clear_deopt_at_target ? frame_pointer + 1 : frame_pointer); - ClearLazyDeopts(thread, fp_for_clearing); + uword frame_pointer) { #if defined(USING_SIMULATOR) // Unwinding of the C++ frames and destroying of their stack resources is done // by the simulator, because the target stack_pointer is a simulated stack diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h index 2b6fd7503d2..c3fc4082d37 100644 --- a/runtime/vm/exceptions.h +++ b/runtime/vm/exceptions.h @@ -83,8 +83,7 @@ class Exceptions : AllStatic { static void JumpToFrame(Thread* thread, uword program_counter, uword stack_pointer, - uword frame_pointer, - bool clear_deopt_at_target); + uword frame_pointer); private: DISALLOW_COPY_AND_ASSIGN(Exceptions); diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc index 405b37f7b9f..c6b6663ba45 100644 --- a/runtime/vm/flow_graph_compiler.cc +++ b/runtime/vm/flow_graph_compiler.cc @@ -1271,7 +1271,6 @@ void FlowGraphCompiler::GenerateStaticCall(intptr_t deopt_id, kNumArgsChecked) ->raw(); } - AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id, token_pos); EmitUnoptimizedStaticCall(argument_count, deopt_id, token_pos, locs, call_ic_data); } diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc index 373aa483729..49126f9b6e7 100644 --- a/runtime/vm/intermediate_language.cc +++ b/runtime/vm/intermediate_language.cc @@ -3075,8 +3075,6 @@ void InstanceCallInstr::EmitNativeCode(FlowGraphCompiler* compiler) { } else { // Unoptimized code. ASSERT(!HasICData()); - compiler->AddCurrentDescriptor(RawPcDescriptors::kRewind, deopt_id(), - token_pos()); bool is_smi_two_args_op = false; const StubEntry* stub_entry = TwoArgsSmiOpInlineCacheEntry(token_kind()); if (stub_entry != NULL) { diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc index e75ba30f6c3..8310e70a603 100644 --- a/runtime/vm/json_stream.cc +++ b/runtime/vm/json_stream.cc @@ -139,8 +139,6 @@ static const char* GetJSONRpcErrorMessage(intptr_t code) { return "Isolate must be runnable"; case kIsolateMustBePaused: return "Isolate must be paused"; - case kCannotResume: - return "Cannot resume execution"; case kIsolateIsReloading: return "Isolate is reloading"; case kFileSystemAlreadyExists: diff --git a/runtime/vm/json_stream.h b/runtime/vm/json_stream.h index bdf1b3a58c7..b54bfb24f13 100644 --- a/runtime/vm/json_stream.h +++ b/runtime/vm/json_stream.h @@ -53,7 +53,6 @@ enum JSONRpcErrorCode { kStreamNotSubscribed = 104, kIsolateMustBeRunnable = 105, kIsolateMustBePaused = 106, - kCannotResume = 107, // Experimental (used in private rpcs). kIsolateIsReloading = 1000, diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 0e8a0f74aeb..2b05ec58e92 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -11702,8 +11702,6 @@ const char* PcDescriptors::KindAsStr(RawPcDescriptors::Kind kind) { return "runtime-call "; case RawPcDescriptors::kOsrEntry: return "osr-entry "; - case RawPcDescriptors::kRewind: - return "rewind "; case RawPcDescriptors::kOther: return "other "; case RawPcDescriptors::kAnyKind: diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 8ca70b7686a..9097b1d6501 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h @@ -1197,8 +1197,7 @@ class RawPcDescriptors : public RawObject { kUnoptStaticCall = kIcCall << 1, // Call to a known target via stub. kRuntimeCall = kUnoptStaticCall << 1, // Runtime call. kOsrEntry = kRuntimeCall << 1, // OSR entry point in unopt. code. - kRewind = kOsrEntry << 1, // Call rewind target address. - kOther = kRewind << 1, + kOther = kOsrEntry << 1, kLastKind = kOther, kAnyKind = -1 }; diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h index edc0e41a426..d450ee4b9eb 100644 --- a/runtime/vm/runtime_entry_list.h +++ b/runtime/vm/runtime_entry_list.h @@ -40,7 +40,6 @@ namespace dart { V(TraceFunctionEntry) \ V(TraceFunctionExit) \ V(DeoptimizeMaterialize) \ - V(RewindPostDeopt) \ V(UpdateFieldCid) \ V(InitStaticField) \ V(GrowRegExpStack) \ diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc index deedaed5e3f..5e34b4a9a4b 100644 --- a/runtime/vm/service.cc +++ b/runtime/vm/service.cc @@ -2988,57 +2988,18 @@ static bool GetVMTimeline(Thread* thread, JSONStream* js) { } -static const char* const step_enum_names[] = { - "None", "Into", "Over", "Out", "Rewind", "OverAsyncSuspension", NULL, -}; - - -static const Debugger::ResumeAction step_enum_values[] = { - Debugger::kContinue, Debugger::kStepInto, - Debugger::kStepOver, Debugger::kStepOut, - Debugger::kStepRewind, Debugger::kStepOverAsyncSuspension, - Debugger::kContinue, // Default value -}; - - static const MethodParameter* resume_params[] = { - RUNNABLE_ISOLATE_PARAMETER, - new EnumParameter("step", false, step_enum_names), - new UIntParameter("frameIndex", false), NULL, + RUNNABLE_ISOLATE_PARAMETER, NULL, }; static bool Resume(Thread* thread, JSONStream* js) { const char* step_param = js->LookupParam("step"); - Debugger::ResumeAction step = Debugger::kContinue; - if (step_param != NULL) { - step = EnumMapper(step_param, step_enum_names, step_enum_values); - } -#if defined(TARGET_ARCH_DBC) - if (step == Debugger::kStepRewind) { - js->PrintError(kCannotResume, - "Rewind not yet implemented on this architecture"); - return true; - } -#endif - intptr_t frame_index = 1; - const char* frame_index_param = js->LookupParam("frameIndex"); - if (frame_index_param != NULL) { - if (step != Debugger::kStepRewind) { - // Only rewind supports the frameIndex parameter. - js->PrintError( - kInvalidParams, - "%s: the 'frameIndex' parameter can only be used when rewinding", - js->method()); - return true; - } - frame_index = UIntParameter::Parse(js->LookupParam("frameIndex")); - } Isolate* isolate = thread->isolate(); if (isolate->message_handler()->is_paused_on_start()) { // If the user is issuing a 'Over' or an 'Out' step, that is the // same as a regular resume request. - if (step == Debugger::kStepInto) { + if ((step_param != NULL) && (strcmp(step_param, "Into") == 0)) { isolate->debugger()->EnterSingleStepMode(); } isolate->message_handler()->set_should_pause_on_start(false); @@ -3067,18 +3028,31 @@ static bool Resume(Thread* thread, JSONStream* js) { PrintSuccess(js); return true; } - if (isolate->debugger()->PauseEvent() == NULL) { - js->PrintError(kIsolateMustBePaused, NULL); + if (isolate->debugger()->PauseEvent() != NULL) { + if (step_param != NULL) { + if (strcmp(step_param, "Into") == 0) { + isolate->debugger()->SetSingleStep(); + } else if (strcmp(step_param, "Over") == 0) { + isolate->debugger()->SetStepOver(); + } else if (strcmp(step_param, "Out") == 0) { + isolate->debugger()->SetStepOut(); + } else if (strcmp(step_param, "OverAsyncSuspension") == 0) { + if (!isolate->debugger()->SetupStepOverAsyncSuspension()) { + js->PrintError(kInvalidParams, + "Isolate must be paused at an async suspension point"); + return true; + } + } else { + PrintInvalidParamError(js, "step"); + return true; + } + } + isolate->SetResumeRequest(); + PrintSuccess(js); return true; } - const char* error = NULL; - if (!isolate->debugger()->SetResumeAction(step, frame_index, &error)) { - js->PrintError(kCannotResume, error); - return true; - } - isolate->SetResumeRequest(); - PrintSuccess(js); + js->PrintError(kIsolateMustBePaused, NULL); return true; } diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc index 445397360ed..8febf134689 100644 --- a/runtime/vm/simulator_dbc.cc +++ b/runtime/vm/simulator_dbc.cc @@ -3715,25 +3715,14 @@ void Simulator::JumpToFrame(uword pc, uword sp, uword fp, Thread* thread) { fp_ = reinterpret_cast(fp); if (pc == StubCode::RunExceptionHandler_entry()->EntryPoint()) { - // The RunExceptionHandler stub is a placeholder. We implement - // its behavior here. + // Instead of executing the RunException stub, we implement its + // behavior here. RawObject* raw_exception = thread->active_exception(); RawObject* raw_stacktrace = thread->active_stacktrace(); ASSERT(raw_exception != Object::null()); special_[kExceptionSpecialIndex] = raw_exception; special_[kStacktraceSpecialIndex] = raw_stacktrace; pc_ = thread->resume_pc(); - } else if (pc == StubCode::DeoptForRewind_entry()->EntryPoint()) { - // The DeoptForRewind stub is a placeholder. We will eventually - // implement its behavior here. - // - // TODO(turnidge): Refactor the Deopt bytecode so that we can use - // the implementation here too. The deopt pc is stored in - // Thread::resume_pc(). After invoking deoptimization, we usually - // call into Debugger::RewindPostDeopt(), but I need to figure out - // if that makes any sense (it would JumpToFrame during a - // JumpToFrame, which seems wrong). - UNIMPLEMENTED(); } else { pc_ = pc; } diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h index 04b03602fc7..3a2cea016c3 100644 --- a/runtime/vm/stub_code.h +++ b/runtime/vm/stub_code.h @@ -27,7 +27,6 @@ class Deserializer; V(GetStackPointer) \ V(JumpToFrame) \ V(RunExceptionHandler) \ - V(DeoptForRewind) \ V(UpdateStoreBuffer) \ V(PrintStopMessage) \ V(CallToRuntime) \ @@ -76,7 +75,6 @@ class Deserializer; V(LazyCompile) \ V(OptimizeFunction) \ V(RunExceptionHandler) \ - V(DeoptForRewind) \ V(FixCallersTarget) \ V(Deoptimize) \ V(DeoptimizeLazyFromReturn) \ @@ -197,12 +195,6 @@ class StubCode : public AllStatic { enum DeoptStubKind { kLazyDeoptFromReturn, kLazyDeoptFromThrow, kEagerDeopt }; -// Zap value used to indicate unused CODE_REG in deopt. -static const int64_t kZapCodeReg = 0xf1f1f1f1; - -// Zap value used to indicate unused return address in deopt. -static const int64_t kZapReturnAddress = 0xe1e1e1e1; - } // namespace dart #endif // RUNTIME_VM_STUB_CODE_H_ diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc index 58124b2428e..87b054d36ae 100644 --- a/runtime/vm/stub_code_arm.cc +++ b/runtime/vm/stub_code_arm.cc @@ -537,20 +537,19 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, __ LeaveStubFrame(); // Remove materialization arguments. __ add(SP, SP, Operand(R2, ASR, kSmiTagSize)); - // The caller is responsible for emitting the return instruction. + __ Ret(); } // R0: result, must be preserved void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { // Push zap value instead of CODE_REG for lazy deopt. - __ LoadImmediate(IP, kZapCodeReg); + __ LoadImmediate(IP, 0xf1f1f1f1); __ Push(IP); // Return address for "call" to deopt stub. - __ LoadImmediate(LR, kZapReturnAddress); + __ LoadImmediate(LR, 0xe1e1e1e1); __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset())); GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); - __ Ret(); } @@ -558,19 +557,17 @@ void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { // R1: stacktrace, must be preserved void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { // Push zap value instead of CODE_REG for lazy deopt. - __ LoadImmediate(IP, kZapCodeReg); + __ LoadImmediate(IP, 0xf1f1f1f1); __ Push(IP); // Return address for "call" to deopt stub. - __ LoadImmediate(LR, kZapReturnAddress); + __ LoadImmediate(LR, 0xe1e1e1e1); __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset())); GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); - __ Ret(); } void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { GenerateDeoptimizationSequence(assembler, kEagerDeopt); - __ Ret(); } @@ -1902,26 +1899,6 @@ void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { } -// Deoptimize a frame on the call stack before rewinding. -// The arguments are stored in the Thread object. -// No result. -void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { - // Push zap value instead of CODE_REG. - __ LoadImmediate(IP, kZapCodeReg); - __ Push(IP); - - // Load the deopt pc into LR. - __ LoadFromOffset(kWord, LR, THR, Thread::resume_pc_offset()); - GenerateDeoptimizationSequence(assembler, kEagerDeopt); - - // After we have deoptimized, jump to the correct frame. - __ EnterStubFrame(); - __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); - __ LeaveStubFrame(); - __ bkpt(0); -} - - // Calls to the runtime to optimize the given function. // R8: function to be reoptimized. // R4: argument descriptor (preserved). diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc index 385e7038d2a..5a5a156ae60 100644 --- a/runtime/vm/stub_code_arm64.cc +++ b/runtime/vm/stub_code_arm64.cc @@ -558,20 +558,19 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, __ LeaveStubFrame(); // Remove materialization arguments. __ add(SP, SP, Operand(R2)); - // The caller is responsible for emitting the return instruction. + __ ret(); } // R0: result, must be preserved void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { // Push zap value instead of CODE_REG for lazy deopt. - __ LoadImmediate(TMP, kZapCodeReg); + __ LoadImmediate(TMP, 0xf1f1f1f1); __ Push(TMP); // Return address for "call" to deopt stub. - __ LoadImmediate(LR, kZapReturnAddress); + __ LoadImmediate(LR, 0xe1e1e1e1); __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset())); GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); - __ ret(); } @@ -579,19 +578,17 @@ void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { // R1: stacktrace, must be preserved void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { // Push zap value instead of CODE_REG for lazy deopt. - __ LoadImmediate(TMP, kZapCodeReg); + __ LoadImmediate(TMP, 0xf1f1f1f1); __ Push(TMP); // Return address for "call" to deopt stub. - __ LoadImmediate(LR, kZapReturnAddress); + __ LoadImmediate(LR, 0xe1e1e1e1); __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset())); GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); - __ ret(); } void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { GenerateDeoptimizationSequence(assembler, kEagerDeopt); - __ ret(); } @@ -1952,26 +1949,6 @@ void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { } -// Deoptimize a frame on the call stack before rewinding. -// The arguments are stored in the Thread object. -// No result. -void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { - // Push zap value instead of CODE_REG. - __ LoadImmediate(TMP, kZapCodeReg); - __ Push(TMP); - - // Load the deopt pc into LR. - __ LoadFromOffset(LR, THR, Thread::resume_pc_offset()); - GenerateDeoptimizationSequence(assembler, kEagerDeopt); - - // After we have deoptimized, jump to the correct frame. - __ EnterStubFrame(); - __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); - __ LeaveStubFrame(); - __ brk(0); -} - - // Calls to the runtime to optimize the given function. // R6: function to be re-optimized. // R4: argument descriptor (preserved). diff --git a/runtime/vm/stub_code_dbc.cc b/runtime/vm/stub_code_dbc.cc index ef4118222cf..da24e19b745 100644 --- a/runtime/vm/stub_code_dbc.cc +++ b/runtime/vm/stub_code_dbc.cc @@ -47,12 +47,6 @@ void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { } -// Not executed, but used as a sentinel in Simulator::JumpToFrame. -void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { - __ Trap(); -} - - // TODO(vegorov) Don't generate this stub. void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { __ Trap(); diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc index ce6521d339d..ca70617824b 100644 --- a/runtime/vm/stub_code_ia32.cc +++ b/runtime/vm/stub_code_ia32.cc @@ -351,6 +351,8 @@ static void PushArgumentsArray(Assembler* assembler) { // +------------------+ // | return-address | (deoptimization point) // +------------------+ +// | Saved CODE_REG | +// +------------------+ // | ... | <- SP of optimized frame // // Parts of the code cannot GC, part of the code can GC. @@ -460,16 +462,15 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, __ popl(ECX); // Pop return address. __ addl(ESP, EBX); // Remove materialization arguments. __ pushl(ECX); // Push return address. - // The caller is responsible for emitting the return instruction. + __ ret(); } // EAX: result, must be preserved void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { // Return address for "call" to deopt stub. - __ pushl(Immediate(kZapReturnAddress)); + __ pushl(Immediate(0xe1e1e1e1)); GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); - __ ret(); } @@ -477,15 +478,13 @@ void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { // EDX: stacktrace, must be preserved void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { // Return address for "call" to deopt stub. - __ pushl(Immediate(kZapReturnAddress)); + __ pushl(Immediate(0xe1e1e1e1)); GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); - __ ret(); } void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { GenerateDeoptimizationSequence(assembler, kEagerDeopt); - __ ret(); } @@ -1836,22 +1835,6 @@ void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { } -// Deoptimize a frame on the call stack before rewinding. -// The arguments are stored in the Thread object. -// No result. -void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { - // Push the deopt pc. - __ pushl(Address(THR, Thread::resume_pc_offset())); - GenerateDeoptimizationSequence(assembler, kEagerDeopt); - - // After we have deoptimized, jump to the correct frame. - __ EnterStubFrame(); - __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); - __ LeaveFrame(); - __ int3(); -} - - // Calls to the runtime to optimize the given function. // EBX: function to be reoptimized. // EDX: argument descriptor (preserved). diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc index 53394cf82eb..d52e6cc6439 100644 --- a/runtime/vm/stub_code_mips.cc +++ b/runtime/vm/stub_code_mips.cc @@ -549,19 +549,18 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, // Remove materialization arguments. __ SmiUntag(T1); __ addu(SP, SP, T1); - // The caller is responsible for emitting the return instruction. + __ Ret(); } // V0: result, must be preserved void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { // Push zap value instead of CODE_REG for lazy deopt. - __ LoadImmediate(TMP, kZapCodeReg); + __ LoadImmediate(TMP, 0xf1f1f1f1); __ Push(TMP); // Return address for "call" to deopt stub. - __ LoadImmediate(RA, kZapReturnAddress); + __ LoadImmediate(RA, 0xe1e1e1e1); __ lw(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset())); GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); - __ Ret(); } @@ -569,19 +568,17 @@ void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { // V1: stacktrace, must be preserved void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { // Push zap value instead of CODE_REG for lazy deopt. - __ LoadImmediate(TMP, kZapCodeReg); + __ LoadImmediate(TMP, 0xf1f1f1f1); __ Push(TMP); // Return address for "call" to deopt stub. - __ LoadImmediate(RA, kZapReturnAddress); + __ LoadImmediate(RA, 0xe1e1e1e1); __ lw(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset())); GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); - __ Ret(); } void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { GenerateDeoptimizationSequence(assembler, kEagerDeopt); - __ Ret(); } @@ -2031,26 +2028,6 @@ void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { } -// Deoptimize a frame on the call stack before rewinding. -// The arguments are stored in the Thread object. -// No result. -void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { - // Push zap value instead of CODE_REG. - __ LoadImmediate(TMP, kZapCodeReg); - __ Push(TMP); - - // Load the deopt pc into RA. - __ lw(RA, Address(THR, Thread::resume_pc_offset())); - GenerateDeoptimizationSequence(assembler, kEagerDeopt); - - // After we have deoptimized, jump to the correct frame. - __ EnterStubFrame(); - __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); - __ LeaveStubFrame(); - __ break_(0); -} - - // Calls to the runtime to optimize the given function. // T0: function to be reoptimized. // S4: argument descriptor (preserved). diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc index 0341f268f80..167154b0879 100644 --- a/runtime/vm/stub_code_x64.cc +++ b/runtime/vm/stub_code_x64.cc @@ -498,19 +498,18 @@ static void GenerateDeoptimizationSequence(Assembler* assembler, __ popq(RCX); // Pop return address. __ addq(RSP, RBX); // Remove materialization arguments. __ pushq(RCX); // Push return address. - // The caller is responsible for emitting the return instruction. + __ ret(); } // RAX: result, must be preserved void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { // Push zap value instead of CODE_REG for lazy deopt. - __ pushq(Immediate(kZapCodeReg)); + __ pushq(Immediate(0xf1f1f1f1)); // Return address for "call" to deopt stub. - __ pushq(Immediate(kZapReturnAddress)); + __ pushq(Immediate(0xe1e1e1e1)); __ movq(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset())); GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn); - __ ret(); } @@ -518,18 +517,16 @@ void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) { // RDX: stacktrace, must be preserved void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) { // Push zap value instead of CODE_REG for lazy deopt. - __ pushq(Immediate(kZapCodeReg)); + __ pushq(Immediate(0xf1f1f1f1)); // Return address for "call" to deopt stub. - __ pushq(Immediate(kZapReturnAddress)); + __ pushq(Immediate(0xe1e1e1e1)); __ movq(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset())); GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow); - __ ret(); } void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { GenerateDeoptimizationSequence(assembler, kEagerDeopt); - __ ret(); } @@ -1894,25 +1891,6 @@ void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) { } -// Deoptimize a frame on the call stack before rewinding. -// The arguments are stored in the Thread object. -// No result. -void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) { - // Push zap value instead of CODE_REG. - __ pushq(Immediate(kZapCodeReg)); - - // Push the deopt pc. - __ pushq(Address(THR, Thread::resume_pc_offset())); - GenerateDeoptimizationSequence(assembler, kEagerDeopt); - - // After we have deoptimized, jump to the correct frame. - __ EnterStubFrame(); - __ CallRuntime(kRewindPostDeoptRuntimeEntry, 0); - __ LeaveStubFrame(); - __ int3(); -} - - // Calls to the runtime to optimize the given function. // RDI: function to be reoptimized. // R10: argument descriptor (preserved).