Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(29)

Side by Side Diff: runtime/vm/code_generator.cc

Issue 226543007: Implement new stacktrace and deoptimization stress testing flags: (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 3rd times a charm Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/vm/flow_graph_compiler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/code_generator.h" 5 #include "vm/code_generator.h"
6 6
7 #include "vm/assembler.h" 7 #include "vm/assembler.h"
8 #include "vm/ast.h" 8 #include "vm/ast.h"
9 #include "vm/bigint_operations.h" 9 #include "vm/bigint_operations.h"
10 #include "vm/code_patcher.h" 10 #include "vm/code_patcher.h"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls"); 53 DEFINE_FLAG(bool, trace_runtime_calls, false, "Trace runtime calls");
54 DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks."); 54 DEFINE_FLAG(bool, trace_type_checks, false, "Trace runtime type checks.");
55 55
56 DECLARE_FLAG(int, deoptimization_counter_threshold); 56 DECLARE_FLAG(int, deoptimization_counter_threshold);
57 DECLARE_FLAG(bool, enable_type_checks); 57 DECLARE_FLAG(bool, enable_type_checks);
58 DECLARE_FLAG(bool, report_usage_count); 58 DECLARE_FLAG(bool, report_usage_count);
59 59
60 DEFINE_FLAG(bool, use_osr, true, "Use on-stack replacement."); 60 DEFINE_FLAG(bool, use_osr, true, "Use on-stack replacement.");
61 DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement."); 61 DEFINE_FLAG(bool, trace_osr, false, "Trace attempts at on-stack replacement.");
62 62
63 DECLARE_FLAG(charp, deoptimize_filter); 63 DEFINE_FLAG(int, stacktrace_every, 0,
64 "Compute debugger stacktrace on every N stack overflow checks");
65 DEFINE_FLAG(charp, stacktrace_filter, NULL,
66 "Compute stacktrace in named function on stack overflow checks");
67 DEFINE_FLAG(int, deoptimize_every, 0,
68 "Deoptimize on every N stack overflow checks");
69 DEFINE_FLAG(charp, deoptimize_filter, NULL,
70 "Deoptimize in named function on stack overflow checks");
64 71
65 72
66 DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) { 73 DEFINE_RUNTIME_ENTRY(TraceFunctionEntry, 1) {
67 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); 74 const Function& function = Function::CheckedHandle(arguments.ArgAt(0));
68 const String& function_name = String::Handle(function.name()); 75 const String& function_name = String::Handle(function.name());
69 const String& class_name = 76 const String& class_name =
70 String::Handle(Class::Handle(function.Owner()).Name()); 77 String::Handle(Class::Handle(function.Owner()).Name());
71 OS::PrintErr("> Entering '%s.%s'\n", 78 OS::PrintErr("> Entering '%s.%s'\n",
72 class_name.ToCString(), function_name.ToCString()); 79 class_name.ToCString(), function_name.ToCString());
73 } 80 }
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after
1015 return true; 1022 return true;
1016 } 1023 }
1017 1024
1018 1025
1019 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) { 1026 DEFINE_RUNTIME_ENTRY(StackOverflow, 0) {
1020 #if defined(USING_SIMULATOR) 1027 #if defined(USING_SIMULATOR)
1021 uword stack_pos = Simulator::Current()->get_register(SPREG); 1028 uword stack_pos = Simulator::Current()->get_register(SPREG);
1022 #else 1029 #else
1023 uword stack_pos = reinterpret_cast<uword>(&arguments); 1030 uword stack_pos = reinterpret_cast<uword>(&arguments);
1024 #endif 1031 #endif
1032 // Always clear the stack overflow flags. They are meant for this
1033 // particular stack overflow runtime call and are not meant to
1034 // persist.
1035 uword stack_overflow_flags = isolate->GetAndClearStackOverflowFlags();
1025 1036
1026 // If an interrupt happens at the same time as a stack overflow, we 1037 // If an interrupt happens at the same time as a stack overflow, we
1027 // process the stack overflow first. 1038 // process the stack overflow now and leave the interrupt for next
1039 // time.
1028 if (stack_pos < isolate->saved_stack_limit()) { 1040 if (stack_pos < isolate->saved_stack_limit()) {
1029 // Use the preallocated stack overflow exception to avoid calling 1041 // Use the preallocated stack overflow exception to avoid calling
1030 // into dart code. 1042 // into dart code.
1031 const Instance& exception = 1043 const Instance& exception =
1032 Instance::Handle(isolate->object_store()->stack_overflow()); 1044 Instance::Handle(isolate->object_store()->stack_overflow());
1033 Exceptions::Throw(exception); 1045 Exceptions::Throw(exception);
1034 UNREACHABLE(); 1046 UNREACHABLE();
1035 } 1047 }
1036 1048
1037 uword interrupt_bits = isolate->GetAndClearInterrupts(); 1049 uword interrupt_bits = isolate->GetAndClearInterrupts();
1038 if (interrupt_bits & Isolate::kStoreBufferInterrupt) { 1050 if ((interrupt_bits & Isolate::kStoreBufferInterrupt) != 0) {
1039 if (FLAG_verbose_gc) { 1051 if (FLAG_verbose_gc) {
1040 OS::PrintErr("Scavenge scheduled by store buffer overflow.\n"); 1052 OS::PrintErr("Scavenge scheduled by store buffer overflow.\n");
1041 } 1053 }
1042 isolate->heap()->CollectGarbage(Heap::kNew); 1054 isolate->heap()->CollectGarbage(Heap::kNew);
1043 } 1055 }
1044 if (interrupt_bits & Isolate::kMessageInterrupt) { 1056 if ((interrupt_bits & Isolate::kMessageInterrupt) != 0) {
1045 isolate->message_handler()->HandleOOBMessages(); 1057 isolate->message_handler()->HandleOOBMessages();
1046 } 1058 }
1047 if (interrupt_bits & Isolate::kApiInterrupt) { 1059 if ((interrupt_bits & Isolate::kApiInterrupt) != 0) {
1048 // Signal isolate interrupt event. 1060 // Signal isolate interrupt event.
1049 Debugger::SignalIsolateInterrupted(); 1061 Debugger::SignalIsolateInterrupted();
1050 1062
1051 Dart_IsolateInterruptCallback callback = isolate->InterruptCallback(); 1063 Dart_IsolateInterruptCallback callback = isolate->InterruptCallback();
1052 if (callback) { 1064 if (callback) {
1053 if ((*callback)()) { 1065 if ((*callback)()) {
1054 return; 1066 return;
1055 } else { 1067 } else {
1056 // TODO(turnidge): Unwind the stack. 1068 // TODO(turnidge): Unwind the stack.
1057 UNIMPLEMENTED(); 1069 UNIMPLEMENTED();
1058 } 1070 }
1059 } 1071 }
1060 } 1072 }
1061 if (interrupt_bits & Isolate::kVmStatusInterrupt) { 1073 if ((interrupt_bits & Isolate::kVmStatusInterrupt) != 0) {
1062 Dart_IsolateInterruptCallback callback = isolate->VmStatsCallback(); 1074 Dart_IsolateInterruptCallback callback = isolate->VmStatsCallback();
1063 if (callback) { 1075 if (callback) {
1064 (*callback)(); 1076 (*callback)();
1065 } 1077 }
1066 } 1078 }
1067 1079
1068 if (FLAG_use_osr && (interrupt_bits == 0)) { 1080 if ((stack_overflow_flags & Isolate::kOsrRequest) != 0) {
1081 ASSERT(FLAG_use_osr);
1069 DartFrameIterator iterator; 1082 DartFrameIterator iterator;
1070 StackFrame* frame = iterator.NextFrame(); 1083 StackFrame* frame = iterator.NextFrame();
1071 ASSERT(frame != NULL); 1084 ASSERT(frame != NULL);
1072 const Code& code = Code::ZoneHandle(frame->LookupDartCode()); 1085 const Code& code = Code::ZoneHandle(frame->LookupDartCode());
1073 ASSERT(!code.IsNull()); 1086 ASSERT(!code.IsNull());
1074 const Function& function = Function::Handle(code.function()); 1087 const Function& function = Function::Handle(code.function());
1075 ASSERT(!function.IsNull()); 1088 ASSERT(!function.IsNull());
1076 // Since the code is referenced from the frame and the ZoneHandle, 1089 // Since the code is referenced from the frame and the ZoneHandle,
1077 // it cannot have been removed from the function. 1090 // it cannot have been removed from the function.
1078 ASSERT(function.HasCode()); 1091 ASSERT(function.HasCode());
(...skipping 26 matching lines...) Expand all
1105 // The OSR code does not work for calling the function, so restore the 1118 // The OSR code does not work for calling the function, so restore the
1106 // unoptimized code. Patch the stack frame to return into the OSR 1119 // unoptimized code. Patch the stack frame to return into the OSR
1107 // code. 1120 // code.
1108 uword optimized_entry = 1121 uword optimized_entry =
1109 Instructions::Handle(optimized_code.instructions()).EntryPoint(); 1122 Instructions::Handle(optimized_code.instructions()).EntryPoint();
1110 function.AttachCode(original_code); 1123 function.AttachCode(original_code);
1111 frame->set_pc(optimized_entry); 1124 frame->set_pc(optimized_entry);
1112 } 1125 }
1113 } 1126 }
1114 1127
1115 if (FLAG_deoptimize_filter != NULL) { 1128 // The following code is used to stress test deoptimization and
1129 // debugger stack tracing.
1130 bool do_deopt = false;
1131 bool do_stacktrace = false;
1132 if (FLAG_deoptimize_every > 0 ||
1133 FLAG_stacktrace_every > 0) {
1134 // TODO(turnidge): To make --deoptimize_every and
1135 // --stacktrace-every faster we could move this increment/test to
1136 // the generated code.
1137 int32_t count = isolate->IncrementAndGetStackOverflowCount();
1138 if (FLAG_deoptimize_every > 0 &&
1139 (count % FLAG_deoptimize_every) == 0) {
1140 do_deopt = true;
1141 }
1142 if (FLAG_stacktrace_every > 0 &&
1143 (count % FLAG_stacktrace_every) == 0) {
1144 do_stacktrace = true;
1145 }
1146 }
1147 if (FLAG_deoptimize_filter != NULL ||
1148 FLAG_stacktrace_filter != NULL) {
1116 DartFrameIterator iterator; 1149 DartFrameIterator iterator;
1117 StackFrame* frame = iterator.NextFrame(); 1150 StackFrame* frame = iterator.NextFrame();
1118 ASSERT(frame != NULL); 1151 ASSERT(frame != NULL);
1119 const Code& code = Code::Handle(frame->LookupDartCode()); 1152 const Code& code = Code::Handle(frame->LookupDartCode());
1120 ASSERT(!code.IsNull()); 1153 ASSERT(!code.IsNull());
1121 if (code.is_optimized()) { 1154 const Function& function = Function::Handle(code.function());
1122 const Function& function = Function::Handle(code.function()); 1155 ASSERT(!function.IsNull());
1123 ASSERT(!function.IsNull()); 1156 const char* function_name = function.ToFullyQualifiedCString();
1124 if (strstr(function.ToFullyQualifiedCString(), 1157 ASSERT(function_name != NULL);
1125 FLAG_deoptimize_filter) != NULL) { 1158 if (code.is_optimized() &&
1126 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { 1159 FLAG_deoptimize_filter != NULL &&
1127 OS::PrintErr("*** Forcing deoptimization (%s)\n", 1160 strstr(function_name, FLAG_deoptimize_filter) != NULL) {
1128 function.ToFullyQualifiedCString()); 1161 OS::PrintErr("*** Forcing deoptimization (%s)\n",
1129 // TODO(turnidge): Consider changing to DeoptimizeAt for 1162 function.ToFullyQualifiedCString());
1130 // just the top frame. 1163 do_deopt = true;
1131 DeoptimizeAll(); 1164 }
1132 } 1165 if (FLAG_stacktrace_filter != NULL &&
1166 strstr(function_name, FLAG_stacktrace_filter) != NULL) {
1167 OS::PrintErr("*** Computing stacktrace (%s)\n",
1168 function.ToFullyQualifiedCString());
1169 do_stacktrace = true;
1170 }
1171 }
1172 if (do_deopt) {
1173 // TODO(turnidge): Consider using DeoptimizeAt instead.
1174 DeoptimizeAll();
1175 }
1176 if (do_stacktrace) {
1177 String& var_name = String::Handle();
1178 Instance& var_value = Instance::Handle();
1179 DebuggerStackTrace* stack = isolate->debugger()->StackTrace();
1180 intptr_t num_frames = stack->Length();
1181 for (intptr_t i = 0; i < num_frames; i++) {
1182 ActivationFrame* frame = stack->FrameAt(i);
1183 const int num_vars = frame->NumLocalVariables();
1184 intptr_t unused;
1185 for (intptr_t v = 0; v < num_vars; v++) {
1186 frame->VariableAt(v, &var_name, &unused, &unused, &var_value);
1133 } 1187 }
1134 } 1188 }
1135 } 1189 }
1136 } 1190 }
1137 1191
1138 1192
1139 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) { 1193 DEFINE_RUNTIME_ENTRY(TraceICCall, 2) {
1140 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0)); 1194 const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(0));
1141 const Function& function = Function::CheckedHandle(arguments.ArgAt(1)); 1195 const Function& function = Function::CheckedHandle(arguments.ArgAt(1));
1142 DartFrameIterator iterator; 1196 DartFrameIterator iterator;
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
1458 // of the given value. 1512 // of the given value.
1459 // Arg0: Field object; 1513 // Arg0: Field object;
1460 // Arg1: Value that is being stored. 1514 // Arg1: Value that is being stored.
1461 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { 1515 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) {
1462 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); 1516 const Field& field = Field::CheckedHandle(arguments.ArgAt(0));
1463 const Object& value = Object::Handle(arguments.ArgAt(1)); 1517 const Object& value = Object::Handle(arguments.ArgAt(1));
1464 field.UpdateGuardedCidAndLength(value); 1518 field.UpdateGuardedCidAndLength(value);
1465 } 1519 }
1466 1520
1467 } // namespace dart 1521 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/flow_graph_compiler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698