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, | 320 // Step in can only be prepared if currently positioned on an IC call or |
321 // construct call or CallFunction stub call. | 321 // construct call. |
322 Address target = rinfo()->target_address(); | 322 Address target = rinfo()->target_address(); |
323 Handle<Code> code(Code::GetCodeFromTargetAddress(target)); | 323 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 | |
348 // Step in through construct call requires no changes to the running code. | 337 // Step in through construct call requires no changes to the running code. |
349 // Step in through getters/setters should already be prepared as well | 338 // Step in through getters/setters should already be prepared as well |
350 // because caller of this function (Debug::PrepareStep) is expected to | 339 // because caller of this function (Debug::PrepareStep) is expected to |
351 // flood the top frame's function with one shot breakpoints. | 340 // flood the top frame's function with one shot breakpoints. |
352 // Step in through CallFunction stub should also be prepared by caller of | 341 ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub()); |
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 | |
358 } | 342 } |
359 } | 343 } |
360 | 344 |
361 | 345 |
362 // Check whether the break point is at a position which will exit the function. | 346 // Check whether the break point is at a position which will exit the function. |
363 bool BreakLocationIterator::IsExit() const { | 347 bool BreakLocationIterator::IsExit() const { |
364 return (RelocInfo::IsJSReturn(rmode())); | 348 return (RelocInfo::IsJSReturn(rmode())); |
365 } | 349 } |
366 | 350 |
367 | 351 |
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 1085 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
1102 | 1086 |
1103 // Find the break location where execution has stopped. | 1087 // Find the break location where execution has stopped. |
1104 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS); | 1088 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS); |
1105 it.FindBreakLocationFromAddress(frame->pc()); | 1089 it.FindBreakLocationFromAddress(frame->pc()); |
1106 | 1090 |
1107 // Compute whether or not the target is a call target. | 1091 // Compute whether or not the target is a call target. |
1108 bool is_call_target = false; | 1092 bool is_call_target = false; |
1109 bool is_load_or_store = false; | 1093 bool is_load_or_store = false; |
1110 bool is_inline_cache_stub = false; | 1094 bool is_inline_cache_stub = false; |
1111 Handle<Code> call_function_stub; | |
1112 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) { | 1095 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) { |
1113 Address target = it.rinfo()->target_address(); | 1096 Address target = it.rinfo()->target_address(); |
1114 Code* code = Code::GetCodeFromTargetAddress(target); | 1097 Code* code = Code::GetCodeFromTargetAddress(target); |
1115 if (code->is_call_stub()) { | 1098 if (code->is_call_stub()) { |
1116 is_call_target = true; | 1099 is_call_target = true; |
1117 } | 1100 } |
1118 if (code->is_inline_cache_stub()) { | 1101 if (code->is_inline_cache_stub()) { |
1119 is_inline_cache_stub = true; | 1102 is_inline_cache_stub = true; |
1120 is_load_or_store = !is_call_target; | 1103 is_load_or_store = !is_call_target; |
1121 } | 1104 } |
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 } | |
1138 } | 1105 } |
1139 | 1106 |
1140 // If this is the last break code target step out is the only possibility. | 1107 // If this is the last break code target step out is the only possibility. |
1141 if (it.IsExit() || step_action == StepOut) { | 1108 if (it.IsExit() || step_action == StepOut) { |
1142 // Step out: If there is a JavaScript caller frame, we need to | 1109 // Step out: If there is a JavaScript caller frame, we need to |
1143 // flood it with breakpoints. | 1110 // flood it with breakpoints. |
1144 frames_it.Advance(); | 1111 frames_it.Advance(); |
1145 if (!frames_it.done()) { | 1112 if (!frames_it.done()) { |
1146 // Fill the function to return to with one-shot break points. | 1113 // Fill the function to return to with one-shot break points. |
1147 JSFunction* function = JSFunction::cast(frames_it.frame()->function()); | 1114 JSFunction* function = JSFunction::cast(frames_it.frame()->function()); |
1148 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared())); | 1115 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared())); |
1149 } | 1116 } |
1150 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || | 1117 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode())) |
1151 !call_function_stub.is_null()) | |
1152 || step_action == StepNext || step_action == StepMin) { | 1118 || step_action == StepNext || step_action == StepMin) { |
1153 // Step next or step min. | 1119 // Step next or step min. |
1154 | 1120 |
1155 // Fill the current function with one-shot break points. | 1121 // Fill the current function with one-shot break points. |
1156 FloodWithOneShot(shared); | 1122 FloodWithOneShot(shared); |
1157 | 1123 |
1158 // Remember source position and frame to handle step next. | 1124 // Remember source position and frame to handle step next. |
1159 thread_local_.last_statement_position_ = | 1125 thread_local_.last_statement_position_ = |
1160 debug_info->code()->SourceStatementPosition(frame->pc()); | 1126 debug_info->code()->SourceStatementPosition(frame->pc()); |
1161 thread_local_.last_fp_ = frame->fp(); | 1127 thread_local_.last_fp_ = frame->fp(); |
1162 } else { | 1128 } 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 | |
1200 // Fill the current function with one-shot break points even for step in on | 1129 // Fill the current function with one-shot break points even for step in on |
1201 // a call target as the function called might be a native function for | 1130 // a call target as the function called might be a native function for |
1202 // which step in will not stop. It also prepares for stepping in | 1131 // which step in will not stop. It also prepares for stepping in |
1203 // getters/setters. | 1132 // getters/setters. |
1204 FloodWithOneShot(shared); | 1133 FloodWithOneShot(shared); |
1205 | 1134 |
1206 if (is_load_or_store) { | 1135 if (is_load_or_store) { |
1207 // Remember source position and frame to handle step in getter/setter. If | 1136 // Remember source position and frame to handle step in getter/setter. If |
1208 // there is a custom getter/setter it will be handled in | 1137 // there is a custom getter/setter it will be handled in |
1209 // Object::Get/SetPropertyWithCallback, otherwise the step action will be | 1138 // Object::Get/SetPropertyWithCallback, otherwise the step action will be |
(...skipping 1426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2636 | 2565 |
2637 | 2566 |
2638 void LockingCommandMessageQueue::Clear() { | 2567 void LockingCommandMessageQueue::Clear() { |
2639 ScopedLock sl(lock_); | 2568 ScopedLock sl(lock_); |
2640 queue_.Clear(); | 2569 queue_.Clear(); |
2641 } | 2570 } |
2642 | 2571 |
2643 #endif // ENABLE_DEBUGGER_SUPPORT | 2572 #endif // ENABLE_DEBUGGER_SUPPORT |
2644 | 2573 |
2645 } } // namespace v8::internal | 2574 } } // namespace v8::internal |
OLD | NEW |