Chromium Code Reviews| Index: runtime/vm/code_generator.cc |
| diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc |
| index 8eee03d0c66b665d7023c44ceab630f4157825ad..26691c485b31b4712d17bf62cdb05c768b639ab8 100644 |
| --- a/runtime/vm/code_generator.cc |
| +++ b/runtime/vm/code_generator.cc |
| @@ -60,7 +60,14 @@ DECLARE_FLAG(bool, report_usage_count); |
| DEFINE_FLAG(bool, use_osr, true, "Use on-stack replacement."); |
| DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement."); |
| -DECLARE_FLAG(charp, deoptimize_filter); |
| +DEFINE_FLAG(int, stacktrace_every, 0, |
| + "Compute debugger stacktrace on every N stack overflow checks"); |
| +DEFINE_FLAG(charp, stacktrace_filter, NULL, |
| + "Compute stacktrace in named function on stack overflow checks"); |
| +DEFINE_FLAG(int, deoptimize_every, 0, |
| + "Deoptimize on every N stack overflow checks"); |
| +DEFINE_FLAG(charp, deoptimize_filter, NULL, |
| + "Deoptimize in named function on stack overflow checks"); |
| DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) { |
| @@ -1022,9 +1029,14 @@ DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { |
| #else |
| uword stack_pos = reinterpret_cast<uword>(&arguments); |
| #endif |
| + // Always clear the stack overflow flags. They are meant for this |
| + // particular stack overflow runtime call and are not meant to |
| + // persist. |
| + uword stack_overflow_flags = isolate->GetAndClearStackOverflowFlags(); |
| // If an interrupt happens at the same time as a stack overflow, we |
| - // process the stack overflow first. |
| + // process the stack overflow now and leave the interrupt for next |
| + // time. |
| if (stack_pos < isolate->saved_stack_limit()) { |
| // Use the preallocated stack overflow exception to avoid calling |
| // into dart code. |
| @@ -1065,7 +1077,8 @@ DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { |
| } |
| } |
| - if (FLAG_use_osr && (interrupt_bits == 0)) { |
| + if (stack_overflow_flags & Isolate::kOsrRequest) { |
|
Cutch
2014/04/07 23:19:57
(stack_overflow_flags & Isolate::kOsrRequest) != 0
turnidge
2014/04/09 17:22:02
Done.
|
| + ASSERT(FLAG_use_osr); |
| DartFrameIterator iterator; |
| StackFrame* frame = iterator.NextFrame(); |
| ASSERT(frame != NULL); |
| @@ -1112,24 +1125,65 @@ DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { |
| } |
| } |
| - if (FLAG_deoptimize_filter != NULL) { |
| + // The following code is used to stress test deoptimization and |
| + // debugger stack tracing. |
| + bool do_deopt = false; |
| + bool do_stacktrace = false; |
| + if (FLAG_deoptimize_every > 0 || |
| + FLAG_stacktrace_every > 0) { |
| + // TODO(turnidge): To make --deoptimize_every and |
| + // --stacktrace-every faster we could move this increment/test to |
| + // the generated code. |
| + int32_t count = isolate->IncrementAndGetStackOverflowCount(); |
| + if (FLAG_deoptimize_every > 0 && |
| + (count % FLAG_deoptimize_every) == 0) { |
| + do_deopt = true; |
| + } |
| + if (FLAG_stacktrace_every > 0 && |
| + (count % FLAG_stacktrace_every) == 0) { |
| + do_stacktrace = true; |
| + } |
| + } |
| + if (FLAG_deoptimize_filter != NULL || |
| + FLAG_stacktrace_filter != NULL) { |
| DartFrameIterator iterator; |
| StackFrame* frame = iterator.NextFrame(); |
| ASSERT(frame != NULL); |
| const Code& code = Code::Handle(frame->LookupDartCode()); |
| ASSERT(!code.IsNull()); |
| - if (code.is_optimized()) { |
| - const Function& function = Function::Handle(code.function()); |
| - ASSERT(!function.IsNull()); |
| - if (strstr(function.ToFullyQualifiedCString(), |
| - FLAG_deoptimize_filter) != NULL) { |
| - if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| - OS::PrintErr("*** Forcing deoptimization (%s)\n", |
| - function.ToFullyQualifiedCString()); |
| - // TODO(turnidge): Consider changing to DeoptimizeAt for |
| - // just the top frame. |
| - DeoptimizeAll(); |
| - } |
| + const Function& function = Function::Handle(code.function()); |
| + ASSERT(!function.IsNull()); |
| + const char* function_name = function.ToFullyQualifiedCString(); |
| + ASSERT(function_name != NULL); |
| + if (code.is_optimized() && |
| + FLAG_deoptimize_filter != NULL && |
| + strstr(function_name, FLAG_deoptimize_filter) != NULL) { |
| + OS::PrintErr("*** Forcing deoptimization (%s)\n", |
| + function.ToFullyQualifiedCString()); |
| + do_deopt = true; |
| + } |
| + if (FLAG_stacktrace_filter != NULL && |
| + strstr(function_name, FLAG_stacktrace_filter) != NULL) { |
| + OS::PrintErr("*** Computing stacktrace (%s)\n", |
| + function.ToFullyQualifiedCString()); |
| + do_stacktrace = true; |
| + } |
| + } |
| + if (do_deopt) { |
| + // TODO(turnidge): Consider using DeoptimizeAt instead. |
| + DeoptimizeAll(); |
| + } |
| + if (do_stacktrace) { |
| + String& var_name = String::Handle(); |
| + Instance& var_value = Instance::Handle(); |
| + DebuggerStackTrace* stack = isolate->debugger()->StackTrace(); |
| + intptr_t num_frames = stack->Length(); |
| + for (intptr_t i = 0; i < num_frames; i++) { |
| + ActivationFrame* frame = stack->FrameAt(i); |
| + const int num_vars = frame->NumLocalVariables(); |
| + intptr_t unused; |
| + for (intptr_t v = 0; v < num_vars; v++) { |
| + frame->VariableAt(v, &var_name, &unused, &unused, &var_value); |
| } |
| } |
| } |