Index: runtime/vm/debugger_test.cc |
diff --git a/runtime/vm/debugger_test.cc b/runtime/vm/debugger_test.cc |
index 233211cdf968156e047d91c90b76883f15b0b683..a660e7ad4d4eac687964f43c99028e9034c2deea 100644 |
--- a/runtime/vm/debugger_test.cc |
+++ b/runtime/vm/debugger_test.cc |
@@ -12,8 +12,12 @@ namespace dart { |
#ifndef PRODUCT |
+DECLARE_FLAG(bool, background_compilation); |
+DECLARE_FLAG(bool, enable_inlining_annotations); |
+DECLARE_FLAG(bool, prune_dead_locals); |
DECLARE_FLAG(bool, remove_script_timestamps_for_test); |
DECLARE_FLAG(bool, trace_rewind); |
+DECLARE_FLAG(int, optimization_counter_threshold); |
// Search for the formatted string in buffer. |
// |
@@ -266,6 +270,8 @@ static void RewindOnce(Dart_IsolateId isolate_id, |
TEST_CASE(Debugger_RewindOneFrame_Unoptimized) { |
SetFlagScope<bool> sfs(&FLAG_trace_rewind, true); |
+ |
+ // These variables are global state used by RewindOnce. |
saw_paused_event = false; |
rewind_frame_index = "1"; |
@@ -303,6 +309,8 @@ TEST_CASE(Debugger_RewindOneFrame_Unoptimized) { |
TEST_CASE(Debugger_RewindTwoFrames_Unoptimized) { |
SetFlagScope<bool> sfs(&FLAG_trace_rewind, true); |
+ |
+ // These variables are global state used by RewindOnce. |
saw_paused_event = false; |
rewind_frame_index = "2"; |
@@ -345,6 +353,88 @@ TEST_CASE(Debugger_RewindTwoFrames_Unoptimized) { |
EXPECT(saw_paused_event); |
} |
+ |
+TEST_CASE(Debugger_Rewind_Optimized) { |
+ SetFlagScope<bool> sfs1(&FLAG_trace_rewind, true); |
+ SetFlagScope<bool> sfs2(&FLAG_prune_dead_locals, false); |
+ SetFlagScope<bool> sfs3(&FLAG_enable_inlining_annotations, true); |
+ SetFlagScope<bool> sfs4(&FLAG_background_compilation, false); |
+ SetFlagScope<int> sfs5(&FLAG_optimization_counter_threshold, 10); |
+ |
+ // These variables are global state used by RewindOnce. |
+ saw_paused_event = false; |
+ rewind_frame_index = "2"; |
+ |
+ const char* kScriptChars = |
+ "import 'dart:developer';\n" |
+ "\n" |
+ "const alwaysInline = \"AlwaysInline\";\n" |
+ "const noInline = \"NeverInline\";\n" |
+ "\n" |
+ "var msg = new StringBuffer();\n" |
+ "int i;\n" |
+ "\n" |
+ "@noInline\n" |
+ "foo() {\n" |
+ " msg.write('enter(foo) ');\n" |
+ " if (i > 15) {\n" |
+ " debugger();\n" |
+ " msg.write('exit(foo) ');\n" |
+ " return true;\n" |
+ " } else {\n" |
+ " msg.write('exit(foo) ');\n" |
+ " return false;\n" |
+ " }\n" |
+ "}\n" |
+ "\n" |
+ "@alwaysInline\n" |
+ "bar3() {\n" |
+ " msg.write('enter(bar3) ');\n" |
+ " var result = foo();\n" |
+ " msg.write('exit(bar3) ');\n" |
+ " return result;\n" |
+ "}\n" |
+ "\n" |
+ "@alwaysInline\n" |
+ "bar2() {\n" |
+ " msg.write('enter(bar2) ');\n" |
+ " var result = bar3();\n" |
+ " msg.write('exit(bar2) ');\n" |
+ " return result;\n" |
+ "}\n" |
+ "\n" |
+ "@alwaysInline\n" |
+ "bar1() {\n" |
+ " msg.write('enter(bar1) ');\n" |
+ " var result = bar2();\n" |
+ " msg.write('exit(bar1) ');\n" |
+ " return result;\n" |
+ "}\n" |
+ "\n" |
+ "main() {\n" |
+ " for (i = 0; i < 20; i++) {\n" |
+ " msg.clear();\n" |
+ " if (bar1()) break;\n;" |
+ " }\n" |
+ " return msg.toString();\n" |
+ "}\n"; |
+ Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL); |
+ EXPECT_VALID(lib); |
+ |
+ Dart_SetPausedEventHandler(RewindOnce); |
+ Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL); |
+ const char* result_cstr; |
+ EXPECT_VALID(result); |
+ EXPECT(Dart_IsString(result)); |
+ EXPECT_VALID(Dart_StringToCString(result, &result_cstr)); |
+ EXPECT_STREQ( |
+ "enter(bar1) enter(bar2) enter(bar3) enter(foo) " |
+ "enter(bar3) enter(foo) " |
+ "exit(foo) exit(bar3) exit(bar2) exit(bar1) ", |
+ result_cstr); |
+ EXPECT(saw_paused_event); |
+} |
+ |
#endif // !PRODUCT |
} // namespace dart |