OLD | NEW |
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2008 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 // Patch the IC call. | 310 // Patch the IC call. |
311 ClearDebugBreakAtIC(); | 311 ClearDebugBreakAtIC(); |
312 } | 312 } |
313 ASSERT(!IsDebugBreak()); | 313 ASSERT(!IsDebugBreak()); |
314 } | 314 } |
315 | 315 |
316 | 316 |
317 void BreakLocationIterator::PrepareStepIn() { | 317 void BreakLocationIterator::PrepareStepIn() { |
318 HandleScope scope; | 318 HandleScope scope; |
319 | 319 |
320 // Step in can only be prepared if currently positioned on an IC call or | 320 // Step in can only be prepared if currently positioned on an IC call, |
321 // construct call. | 321 // construct call or CallFunction stub call. |
322 Address target = rinfo()->target_address(); | 322 Address target = rinfo()->target_address(); |
323 Code* code = Code::GetCodeFromTargetAddress(target); | 323 Handle<Code> code(Code::GetCodeFromTargetAddress(target)); |
324 if (code->is_call_stub()) { | 324 if (code->is_call_stub()) { |
325 // Step in through IC call is handled by the runtime system. Therefore make | 325 // Step in through IC call is handled by the runtime system. Therefore make |
326 // sure that the any current IC is cleared and the runtime system is | 326 // sure that the any current IC is cleared and the runtime system is |
327 // called. If the executing code has a debug break at the location change | 327 // called. If the executing code has a debug break at the location change |
328 // the call in the original code as it is the code there that will be | 328 // the call in the original code as it is the code there that will be |
329 // executed in place of the debug break call. | 329 // executed in place of the debug break call. |
330 Handle<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count()); | 330 Handle<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count()); |
331 if (IsDebugBreak()) { | 331 if (IsDebugBreak()) { |
332 original_rinfo()->set_target_address(stub->entry()); | 332 original_rinfo()->set_target_address(stub->entry()); |
333 } else { | 333 } else { |
334 rinfo()->set_target_address(stub->entry()); | 334 rinfo()->set_target_address(stub->entry()); |
335 } | 335 } |
336 } else { | 336 } else { |
| 337 #ifdef DEBUG |
| 338 Handle<Code> maybe_call_function_stub = code; |
| 339 if (IsDebugBreak()) { |
| 340 Address original_target = original_rinfo()->target_address(); |
| 341 maybe_call_function_stub = |
| 342 Handle<Code>(Code::GetCodeFromTargetAddress(original_target)); |
| 343 } |
| 344 bool is_call_function_stub = |
| 345 (maybe_call_function_stub->kind() == Code::STUB && |
| 346 maybe_call_function_stub->major_key() == CodeStub::CallFunction); |
| 347 |
337 // Step in through construct call requires no changes to the running code. | 348 // Step in through construct call requires no changes to the running code. |
338 // Step in through getters/setters should already be prepared as well | 349 // Step in through getters/setters should already be prepared as well |
339 // because caller of this function (Debug::PrepareStep) is expected to | 350 // because caller of this function (Debug::PrepareStep) is expected to |
340 // flood the top frame's function with one shot breakpoints. | 351 // flood the top frame's function with one shot breakpoints. |
341 ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub()); | 352 // Step in through CallFunction stub should also be prepared by caller of |
| 353 // this function (Debug::PrepareStep) which should flood target function |
| 354 // with breakpoints. |
| 355 ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub() |
| 356 || is_call_function_stub); |
| 357 #endif |
342 } | 358 } |
343 } | 359 } |
344 | 360 |
345 | 361 |
346 // Check whether the break point is at a position which will exit the function. | 362 // Check whether the break point is at a position which will exit the function. |
347 bool BreakLocationIterator::IsExit() const { | 363 bool BreakLocationIterator::IsExit() const { |
348 return (RelocInfo::IsJSReturn(rmode())); | 364 return (RelocInfo::IsJSReturn(rmode())); |
349 } | 365 } |
350 | 366 |
351 | 367 |
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 1101 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
1086 | 1102 |
1087 // Find the break location where execution has stopped. | 1103 // Find the break location where execution has stopped. |
1088 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS); | 1104 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS); |
1089 it.FindBreakLocationFromAddress(frame->pc()); | 1105 it.FindBreakLocationFromAddress(frame->pc()); |
1090 | 1106 |
1091 // Compute whether or not the target is a call target. | 1107 // Compute whether or not the target is a call target. |
1092 bool is_call_target = false; | 1108 bool is_call_target = false; |
1093 bool is_load_or_store = false; | 1109 bool is_load_or_store = false; |
1094 bool is_inline_cache_stub = false; | 1110 bool is_inline_cache_stub = false; |
| 1111 Handle<Code> call_function_stub; |
1095 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) { | 1112 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) { |
1096 Address target = it.rinfo()->target_address(); | 1113 Address target = it.rinfo()->target_address(); |
1097 Code* code = Code::GetCodeFromTargetAddress(target); | 1114 Code* code = Code::GetCodeFromTargetAddress(target); |
1098 if (code->is_call_stub()) { | 1115 if (code->is_call_stub()) { |
1099 is_call_target = true; | 1116 is_call_target = true; |
1100 } | 1117 } |
1101 if (code->is_inline_cache_stub()) { | 1118 if (code->is_inline_cache_stub()) { |
1102 is_inline_cache_stub = true; | 1119 is_inline_cache_stub = true; |
1103 is_load_or_store = !is_call_target; | 1120 is_load_or_store = !is_call_target; |
1104 } | 1121 } |
| 1122 |
| 1123 // Check if target code is CallFunction stub. |
| 1124 Code* maybe_call_function_stub = code; |
| 1125 // If there is a breakpoint at this line look at the original code to |
| 1126 // check if it is a CallFunction stub. |
| 1127 if (it.IsDebugBreak()) { |
| 1128 Address original_target = it.original_rinfo()->target_address(); |
| 1129 maybe_call_function_stub = |
| 1130 Code::GetCodeFromTargetAddress(original_target); |
| 1131 } |
| 1132 if (maybe_call_function_stub->kind() == Code::STUB && |
| 1133 maybe_call_function_stub->major_key() == CodeStub::CallFunction) { |
| 1134 // Save reference to the code as we may need it to find out arguments |
| 1135 // count for 'step in' later. |
| 1136 call_function_stub = Handle<Code>(maybe_call_function_stub); |
| 1137 } |
1105 } | 1138 } |
1106 | 1139 |
1107 // If this is the last break code target step out is the only possibility. | 1140 // If this is the last break code target step out is the only possibility. |
1108 if (it.IsExit() || step_action == StepOut) { | 1141 if (it.IsExit() || step_action == StepOut) { |
1109 // Step out: If there is a JavaScript caller frame, we need to | 1142 // Step out: If there is a JavaScript caller frame, we need to |
1110 // flood it with breakpoints. | 1143 // flood it with breakpoints. |
1111 frames_it.Advance(); | 1144 frames_it.Advance(); |
1112 if (!frames_it.done()) { | 1145 if (!frames_it.done()) { |
1113 // Fill the function to return to with one-shot break points. | 1146 // Fill the function to return to with one-shot break points. |
1114 JSFunction* function = JSFunction::cast(frames_it.frame()->function()); | 1147 JSFunction* function = JSFunction::cast(frames_it.frame()->function()); |
1115 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared())); | 1148 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared())); |
1116 } | 1149 } |
1117 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode())) | 1150 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || |
| 1151 !call_function_stub.is_null()) |
1118 || step_action == StepNext || step_action == StepMin) { | 1152 || step_action == StepNext || step_action == StepMin) { |
1119 // Step next or step min. | 1153 // Step next or step min. |
1120 | 1154 |
1121 // Fill the current function with one-shot break points. | 1155 // Fill the current function with one-shot break points. |
1122 FloodWithOneShot(shared); | 1156 FloodWithOneShot(shared); |
1123 | 1157 |
1124 // Remember source position and frame to handle step next. | 1158 // Remember source position and frame to handle step next. |
1125 thread_local_.last_statement_position_ = | 1159 thread_local_.last_statement_position_ = |
1126 debug_info->code()->SourceStatementPosition(frame->pc()); | 1160 debug_info->code()->SourceStatementPosition(frame->pc()); |
1127 thread_local_.last_fp_ = frame->fp(); | 1161 thread_local_.last_fp_ = frame->fp(); |
1128 } else { | 1162 } else { |
| 1163 // If it's CallFunction stub ensure target function is compiled and flood |
| 1164 // it with one shot breakpoints. |
| 1165 if (!call_function_stub.is_null()) { |
| 1166 // Find out number of arguments from the stub minor key. |
| 1167 // Reverse lookup required as the minor key cannot be retrieved |
| 1168 // from the code object. |
| 1169 Handle<Object> obj( |
| 1170 Heap::code_stubs()->SlowReverseLookup(*call_function_stub)); |
| 1171 ASSERT(*obj != Heap::undefined_value()); |
| 1172 ASSERT(obj->IsSmi()); |
| 1173 // Get the STUB key and extract major and minor key. |
| 1174 uint32_t key = Smi::cast(*obj)->value(); |
| 1175 int call_function_arg_count = CodeStub::MinorKeyFromKey(key); |
| 1176 ASSERT(call_function_stub->major_key() == |
| 1177 CodeStub::MajorKeyFromKey(key)); |
| 1178 |
| 1179 // Find target function on the expression stack. |
| 1180 // Expression stack lools like this (top to bottom): |
| 1181 // argN |
| 1182 // ... |
| 1183 // arg0 |
| 1184 // Receiver |
| 1185 // Function to call |
| 1186 int expressions_count = frame->ComputeExpressionsCount(); |
| 1187 ASSERT(expressions_count - 2 - call_function_arg_count >= 0); |
| 1188 Object* fun = frame->GetExpression( |
| 1189 expressions_count - 2 - call_function_arg_count); |
| 1190 if (fun->IsJSFunction()) { |
| 1191 Handle<JSFunction> js_function(JSFunction::cast(fun)); |
| 1192 // Don't step into builtins. |
| 1193 if (!js_function->IsBuiltin()) { |
| 1194 // It will also compile target function if it's not compiled yet. |
| 1195 FloodWithOneShot(Handle<SharedFunctionInfo>(js_function->shared())); |
| 1196 } |
| 1197 } |
| 1198 } |
| 1199 |
1129 // Fill the current function with one-shot break points even for step in on | 1200 // Fill the current function with one-shot break points even for step in on |
1130 // a call target as the function called might be a native function for | 1201 // a call target as the function called might be a native function for |
1131 // which step in will not stop. It also prepares for stepping in | 1202 // which step in will not stop. It also prepares for stepping in |
1132 // getters/setters. | 1203 // getters/setters. |
1133 FloodWithOneShot(shared); | 1204 FloodWithOneShot(shared); |
1134 | 1205 |
1135 if (is_load_or_store) { | 1206 if (is_load_or_store) { |
1136 // Remember source position and frame to handle step in getter/setter. If | 1207 // Remember source position and frame to handle step in getter/setter. If |
1137 // there is a custom getter/setter it will be handled in | 1208 // there is a custom getter/setter it will be handled in |
1138 // Object::Get/SetPropertyWithCallback, otherwise the step action will be | 1209 // Object::Get/SetPropertyWithCallback, otherwise the step action will be |
(...skipping 1426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2565 | 2636 |
2566 | 2637 |
2567 void LockingCommandMessageQueue::Clear() { | 2638 void LockingCommandMessageQueue::Clear() { |
2568 ScopedLock sl(lock_); | 2639 ScopedLock sl(lock_); |
2569 queue_.Clear(); | 2640 queue_.Clear(); |
2570 } | 2641 } |
2571 | 2642 |
2572 #endif // ENABLE_DEBUGGER_SUPPORT | 2643 #endif // ENABLE_DEBUGGER_SUPPORT |
2573 | 2644 |
2574 } } // namespace v8::internal | 2645 } } // namespace v8::internal |
OLD | NEW |