| 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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 68 | 68 |
| 69 static Handle<Code> ComputeCallDebugPrepareStepIn(int argc) { | 69 static Handle<Code> ComputeCallDebugPrepareStepIn(int argc) { |
| 70 CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugPrepareStepIn(argc), Code); | 70 CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugPrepareStepIn(argc), Code); |
| 71 } | 71 } |
| 72 | 72 |
| 73 | 73 |
| 74 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info, | 74 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info, |
| 75 BreakLocatorType type) { | 75 BreakLocatorType type) { |
| 76 debug_info_ = debug_info; | 76 debug_info_ = debug_info; |
| 77 type_ = type; | 77 type_ = type; |
| 78 // Get the stub early to avoid possible GC during iterations. We may need |
| 79 // this stub to detect debugger calls generated from debugger statements. |
| 80 debug_break_stub_ = RuntimeStub(Runtime::kDebugBreak, 0).GetCode(); |
| 78 reloc_iterator_ = NULL; | 81 reloc_iterator_ = NULL; |
| 79 reloc_iterator_original_ = NULL; | 82 reloc_iterator_original_ = NULL; |
| 80 Reset(); // Initialize the rest of the member variables. | 83 Reset(); // Initialize the rest of the member variables. |
| 81 } | 84 } |
| 82 | 85 |
| 83 | 86 |
| 84 BreakLocationIterator::~BreakLocationIterator() { | 87 BreakLocationIterator::~BreakLocationIterator() { |
| 85 ASSERT(reloc_iterator_ != NULL); | 88 ASSERT(reloc_iterator_ != NULL); |
| 86 ASSERT(reloc_iterator_original_ != NULL); | 89 ASSERT(reloc_iterator_original_ != NULL); |
| 87 delete reloc_iterator_; | 90 delete reloc_iterator_; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 // break points can cause the code targets in the running (debugged) code to | 122 // break points can cause the code targets in the running (debugged) code to |
| 120 // be of a different kind than in the original code. | 123 // be of a different kind than in the original code. |
| 121 if (RelocInfo::IsCodeTarget(rmode())) { | 124 if (RelocInfo::IsCodeTarget(rmode())) { |
| 122 Address target = original_rinfo()->target_address(); | 125 Address target = original_rinfo()->target_address(); |
| 123 Code* code = Code::GetCodeFromTargetAddress(target); | 126 Code* code = Code::GetCodeFromTargetAddress(target); |
| 124 if (code->is_inline_cache_stub() || RelocInfo::IsConstructCall(rmode())) { | 127 if (code->is_inline_cache_stub() || RelocInfo::IsConstructCall(rmode())) { |
| 125 break_point_++; | 128 break_point_++; |
| 126 return; | 129 return; |
| 127 } | 130 } |
| 128 if (code->kind() == Code::STUB) { | 131 if (code->kind() == Code::STUB) { |
| 132 if (IsDebuggerStatement()) { |
| 133 break_point_++; |
| 134 return; |
| 135 } |
| 129 if (type_ == ALL_BREAK_LOCATIONS) { | 136 if (type_ == ALL_BREAK_LOCATIONS) { |
| 130 if (Debug::IsBreakStub(code)) { | 137 if (Debug::IsBreakStub(code)) { |
| 131 break_point_++; | 138 break_point_++; |
| 132 return; | 139 return; |
| 133 } | 140 } |
| 134 } else { | 141 } else { |
| 135 ASSERT(type_ == SOURCE_BREAK_LOCATIONS); | 142 ASSERT(type_ == SOURCE_BREAK_LOCATIONS); |
| 136 if (Debug::IsSourceBreakStub(code)) { | 143 if (Debug::IsSourceBreakStub(code)) { |
| 137 break_point_++; | 144 break_point_++; |
| 138 return; | 145 return; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 return RinfoDone(); | 238 return RinfoDone(); |
| 232 } | 239 } |
| 233 | 240 |
| 234 | 241 |
| 235 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) { | 242 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) { |
| 236 // If there is not already a real break point here patch code with debug | 243 // If there is not already a real break point here patch code with debug |
| 237 // break. | 244 // break. |
| 238 if (!HasBreakPoint()) { | 245 if (!HasBreakPoint()) { |
| 239 SetDebugBreak(); | 246 SetDebugBreak(); |
| 240 } | 247 } |
| 241 ASSERT(IsDebugBreak()); | 248 ASSERT(IsDebugBreak() || IsDebuggerStatement()); |
| 242 // Set the break point information. | 249 // Set the break point information. |
| 243 DebugInfo::SetBreakPoint(debug_info_, code_position(), | 250 DebugInfo::SetBreakPoint(debug_info_, code_position(), |
| 244 position(), statement_position(), | 251 position(), statement_position(), |
| 245 break_point_object); | 252 break_point_object); |
| 246 } | 253 } |
| 247 | 254 |
| 248 | 255 |
| 249 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) { | 256 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) { |
| 250 // Clear the break point information. | 257 // Clear the break point information. |
| 251 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object); | 258 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object); |
| 252 // If there are no more break points here remove the debug break. | 259 // If there are no more break points here remove the debug break. |
| 253 if (!HasBreakPoint()) { | 260 if (!HasBreakPoint()) { |
| 254 ClearDebugBreak(); | 261 ClearDebugBreak(); |
| 255 ASSERT(!IsDebugBreak()); | 262 ASSERT(!IsDebugBreak()); |
| 256 } | 263 } |
| 257 } | 264 } |
| 258 | 265 |
| 259 | 266 |
| 260 void BreakLocationIterator::SetOneShot() { | 267 void BreakLocationIterator::SetOneShot() { |
| 268 // Debugger statement always calls debugger. No need to modify it. |
| 269 if (IsDebuggerStatement()) { |
| 270 return; |
| 271 } |
| 272 |
| 261 // If there is a real break point here no more to do. | 273 // If there is a real break point here no more to do. |
| 262 if (HasBreakPoint()) { | 274 if (HasBreakPoint()) { |
| 263 ASSERT(IsDebugBreak()); | 275 ASSERT(IsDebugBreak()); |
| 264 return; | 276 return; |
| 265 } | 277 } |
| 266 | 278 |
| 267 // Patch code with debug break. | 279 // Patch code with debug break. |
| 268 SetDebugBreak(); | 280 SetDebugBreak(); |
| 269 } | 281 } |
| 270 | 282 |
| 271 | 283 |
| 272 void BreakLocationIterator::ClearOneShot() { | 284 void BreakLocationIterator::ClearOneShot() { |
| 285 // Debugger statement always calls debugger. No need to modify it. |
| 286 if (IsDebuggerStatement()) { |
| 287 return; |
| 288 } |
| 289 |
| 273 // If there is a real break point here no more to do. | 290 // If there is a real break point here no more to do. |
| 274 if (HasBreakPoint()) { | 291 if (HasBreakPoint()) { |
| 275 ASSERT(IsDebugBreak()); | 292 ASSERT(IsDebugBreak()); |
| 276 return; | 293 return; |
| 277 } | 294 } |
| 278 | 295 |
| 279 // Patch code removing debug break. | 296 // Patch code removing debug break. |
| 280 ClearDebugBreak(); | 297 ClearDebugBreak(); |
| 281 ASSERT(!IsDebugBreak()); | 298 ASSERT(!IsDebugBreak()); |
| 282 } | 299 } |
| 283 | 300 |
| 284 | 301 |
| 285 void BreakLocationIterator::SetDebugBreak() { | 302 void BreakLocationIterator::SetDebugBreak() { |
| 303 // Debugger statement always calls debugger. No need to modify it. |
| 304 if (IsDebuggerStatement()) { |
| 305 return; |
| 306 } |
| 307 |
| 286 // If there is already a break point here just return. This might happen if | 308 // If there is already a break point here just return. This might happen if |
| 287 // the same code is flooded with break points twice. Flooding the same | 309 // the same code is flooded with break points twice. Flooding the same |
| 288 // function twice might happen when stepping in a function with an exception | 310 // function twice might happen when stepping in a function with an exception |
| 289 // handler as the handler and the function is the same. | 311 // handler as the handler and the function is the same. |
| 290 if (IsDebugBreak()) { | 312 if (IsDebugBreak()) { |
| 291 return; | 313 return; |
| 292 } | 314 } |
| 293 | 315 |
| 294 if (RelocInfo::IsJSReturn(rmode())) { | 316 if (RelocInfo::IsJSReturn(rmode())) { |
| 295 // Patch the frame exit code with a break point. | 317 // Patch the frame exit code with a break point. |
| 296 SetDebugBreakAtReturn(); | 318 SetDebugBreakAtReturn(); |
| 297 } else { | 319 } else { |
| 298 // Patch the IC call. | 320 // Patch the IC call. |
| 299 SetDebugBreakAtIC(); | 321 SetDebugBreakAtIC(); |
| 300 } | 322 } |
| 301 ASSERT(IsDebugBreak()); | 323 ASSERT(IsDebugBreak()); |
| 302 } | 324 } |
| 303 | 325 |
| 304 | 326 |
| 305 void BreakLocationIterator::ClearDebugBreak() { | 327 void BreakLocationIterator::ClearDebugBreak() { |
| 328 // Debugger statement always calls debugger. No need to modify it. |
| 329 if (IsDebuggerStatement()) { |
| 330 return; |
| 331 } |
| 332 |
| 306 if (RelocInfo::IsJSReturn(rmode())) { | 333 if (RelocInfo::IsJSReturn(rmode())) { |
| 307 // Restore the frame exit code. | 334 // Restore the frame exit code. |
| 308 ClearDebugBreakAtReturn(); | 335 ClearDebugBreakAtReturn(); |
| 309 } else { | 336 } else { |
| 310 // Patch the IC call. | 337 // Patch the IC call. |
| 311 ClearDebugBreakAtIC(); | 338 ClearDebugBreakAtIC(); |
| 312 } | 339 } |
| 313 ASSERT(!IsDebugBreak()); | 340 ASSERT(!IsDebugBreak()); |
| 314 } | 341 } |
| 315 | 342 |
| 316 | 343 |
| 317 void BreakLocationIterator::PrepareStepIn() { | 344 void BreakLocationIterator::PrepareStepIn() { |
| 318 HandleScope scope; | 345 HandleScope scope; |
| 319 | 346 |
| 320 // Step in can only be prepared if currently positioned on an IC call or | 347 // Step in can only be prepared if currently positioned on an IC call, |
| 321 // construct call. | 348 // construct call or CallFunction stub call. |
| 322 Address target = rinfo()->target_address(); | 349 Address target = rinfo()->target_address(); |
| 323 Code* code = Code::GetCodeFromTargetAddress(target); | 350 Handle<Code> code(Code::GetCodeFromTargetAddress(target)); |
| 324 if (code->is_call_stub()) { | 351 if (code->is_call_stub()) { |
| 325 // Step in through IC call is handled by the runtime system. Therefore make | 352 // 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 | 353 // 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 | 354 // 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 | 355 // the call in the original code as it is the code there that will be |
| 329 // executed in place of the debug break call. | 356 // executed in place of the debug break call. |
| 330 Handle<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count()); | 357 Handle<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count()); |
| 331 if (IsDebugBreak()) { | 358 if (IsDebugBreak()) { |
| 332 original_rinfo()->set_target_address(stub->entry()); | 359 original_rinfo()->set_target_address(stub->entry()); |
| 333 } else { | 360 } else { |
| 334 rinfo()->set_target_address(stub->entry()); | 361 rinfo()->set_target_address(stub->entry()); |
| 335 } | 362 } |
| 336 } else { | 363 } else { |
| 364 #ifdef DEBUG |
| 365 // All the following stuff is needed only for assertion checks so the code |
| 366 // is wrapped in ifdef. |
| 367 Handle<Code> maybe_call_function_stub = code; |
| 368 if (IsDebugBreak()) { |
| 369 Address original_target = original_rinfo()->target_address(); |
| 370 maybe_call_function_stub = |
| 371 Handle<Code>(Code::GetCodeFromTargetAddress(original_target)); |
| 372 } |
| 373 bool is_call_function_stub = |
| 374 (maybe_call_function_stub->kind() == Code::STUB && |
| 375 maybe_call_function_stub->major_key() == CodeStub::CallFunction); |
| 376 |
| 337 // Step in through construct call requires no changes to the running code. | 377 // Step in through construct call requires no changes to the running code. |
| 338 // Step in through getters/setters should already be prepared as well | 378 // Step in through getters/setters should already be prepared as well |
| 339 // because caller of this function (Debug::PrepareStep) is expected to | 379 // because caller of this function (Debug::PrepareStep) is expected to |
| 340 // flood the top frame's function with one shot breakpoints. | 380 // flood the top frame's function with one shot breakpoints. |
| 341 ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub()); | 381 // Step in through CallFunction stub should also be prepared by caller of |
| 382 // this function (Debug::PrepareStep) which should flood target function |
| 383 // with breakpoints. |
| 384 ASSERT(RelocInfo::IsConstructCall(rmode()) || code->is_inline_cache_stub() |
| 385 || is_call_function_stub); |
| 386 #endif |
| 342 } | 387 } |
| 343 } | 388 } |
| 344 | 389 |
| 345 | 390 |
| 346 // Check whether the break point is at a position which will exit the function. | 391 // Check whether the break point is at a position which will exit the function. |
| 347 bool BreakLocationIterator::IsExit() const { | 392 bool BreakLocationIterator::IsExit() const { |
| 348 return (RelocInfo::IsJSReturn(rmode())); | 393 return (RelocInfo::IsJSReturn(rmode())); |
| 349 } | 394 } |
| 350 | 395 |
| 351 | 396 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 // Restore the inlined version of keyed stores to get back to the | 447 // Restore the inlined version of keyed stores to get back to the |
| 403 // fast case. We need to patch back the keyed store because no | 448 // fast case. We need to patch back the keyed store because no |
| 404 // patching happens when running normally. For keyed loads, the | 449 // patching happens when running normally. For keyed loads, the |
| 405 // map check will get patched back when running normally after ICs | 450 // map check will get patched back when running normally after ICs |
| 406 // have been cleared at GC. | 451 // have been cleared at GC. |
| 407 if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); | 452 if (code->is_keyed_store_stub()) KeyedStoreIC::RestoreInlinedVersion(pc()); |
| 408 } | 453 } |
| 409 } | 454 } |
| 410 | 455 |
| 411 | 456 |
| 457 bool BreakLocationIterator::IsDebuggerStatement() { |
| 458 if (RelocInfo::IsCodeTarget(rmode())) { |
| 459 Address target = original_rinfo()->target_address(); |
| 460 Code* code = Code::GetCodeFromTargetAddress(target); |
| 461 if (code->kind() == Code::STUB) { |
| 462 CodeStub::Major major_key = code->major_key(); |
| 463 if (major_key == CodeStub::Runtime) { |
| 464 return (*debug_break_stub_ == code); |
| 465 } |
| 466 } |
| 467 } |
| 468 return false; |
| 469 } |
| 470 |
| 471 |
| 412 Object* BreakLocationIterator::BreakPointObjects() { | 472 Object* BreakLocationIterator::BreakPointObjects() { |
| 413 return debug_info_->GetBreakPointObjects(code_position()); | 473 return debug_info_->GetBreakPointObjects(code_position()); |
| 414 } | 474 } |
| 415 | 475 |
| 416 | 476 |
| 417 // Clear out all the debug break code. This is ONLY supposed to be used when | 477 // Clear out all the debug break code. This is ONLY supposed to be used when |
| 418 // shutting down the debugger as it will leave the break point information in | 478 // shutting down the debugger as it will leave the break point information in |
| 419 // DebugInfo even though the code is patched back to the non break point state. | 479 // DebugInfo even though the code is patched back to the non break point state. |
| 420 void BreakLocationIterator::ClearAllDebugBreak() { | 480 void BreakLocationIterator::ClearAllDebugBreak() { |
| 421 while (!Done()) { | 481 while (!Done()) { |
| (...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 1145 Handle<DebugInfo> debug_info = GetDebugInfo(shared); |
| 1086 | 1146 |
| 1087 // Find the break location where execution has stopped. | 1147 // Find the break location where execution has stopped. |
| 1088 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS); | 1148 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS); |
| 1089 it.FindBreakLocationFromAddress(frame->pc()); | 1149 it.FindBreakLocationFromAddress(frame->pc()); |
| 1090 | 1150 |
| 1091 // Compute whether or not the target is a call target. | 1151 // Compute whether or not the target is a call target. |
| 1092 bool is_call_target = false; | 1152 bool is_call_target = false; |
| 1093 bool is_load_or_store = false; | 1153 bool is_load_or_store = false; |
| 1094 bool is_inline_cache_stub = false; | 1154 bool is_inline_cache_stub = false; |
| 1155 Handle<Code> call_function_stub; |
| 1095 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) { | 1156 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) { |
| 1096 Address target = it.rinfo()->target_address(); | 1157 Address target = it.rinfo()->target_address(); |
| 1097 Code* code = Code::GetCodeFromTargetAddress(target); | 1158 Code* code = Code::GetCodeFromTargetAddress(target); |
| 1098 if (code->is_call_stub()) { | 1159 if (code->is_call_stub()) { |
| 1099 is_call_target = true; | 1160 is_call_target = true; |
| 1100 } | 1161 } |
| 1101 if (code->is_inline_cache_stub()) { | 1162 if (code->is_inline_cache_stub()) { |
| 1102 is_inline_cache_stub = true; | 1163 is_inline_cache_stub = true; |
| 1103 is_load_or_store = !is_call_target; | 1164 is_load_or_store = !is_call_target; |
| 1104 } | 1165 } |
| 1166 |
| 1167 // Check if target code is CallFunction stub. |
| 1168 Code* maybe_call_function_stub = code; |
| 1169 // If there is a breakpoint at this line look at the original code to |
| 1170 // check if it is a CallFunction stub. |
| 1171 if (it.IsDebugBreak()) { |
| 1172 Address original_target = it.original_rinfo()->target_address(); |
| 1173 maybe_call_function_stub = |
| 1174 Code::GetCodeFromTargetAddress(original_target); |
| 1175 } |
| 1176 if (maybe_call_function_stub->kind() == Code::STUB && |
| 1177 maybe_call_function_stub->major_key() == CodeStub::CallFunction) { |
| 1178 // Save reference to the code as we may need it to find out arguments |
| 1179 // count for 'step in' later. |
| 1180 call_function_stub = Handle<Code>(maybe_call_function_stub); |
| 1181 } |
| 1105 } | 1182 } |
| 1106 | 1183 |
| 1107 // If this is the last break code target step out is the only possibility. | 1184 // If this is the last break code target step out is the only possibility. |
| 1108 if (it.IsExit() || step_action == StepOut) { | 1185 if (it.IsExit() || step_action == StepOut) { |
| 1109 // Step out: If there is a JavaScript caller frame, we need to | 1186 // Step out: If there is a JavaScript caller frame, we need to |
| 1110 // flood it with breakpoints. | 1187 // flood it with breakpoints. |
| 1111 frames_it.Advance(); | 1188 frames_it.Advance(); |
| 1112 if (!frames_it.done()) { | 1189 if (!frames_it.done()) { |
| 1113 // Fill the function to return to with one-shot break points. | 1190 // Fill the function to return to with one-shot break points. |
| 1114 JSFunction* function = JSFunction::cast(frames_it.frame()->function()); | 1191 JSFunction* function = JSFunction::cast(frames_it.frame()->function()); |
| 1115 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared())); | 1192 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared())); |
| 1116 } | 1193 } |
| 1117 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode())) | 1194 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || |
| 1195 !call_function_stub.is_null()) |
| 1118 || step_action == StepNext || step_action == StepMin) { | 1196 || step_action == StepNext || step_action == StepMin) { |
| 1119 // Step next or step min. | 1197 // Step next or step min. |
| 1120 | 1198 |
| 1121 // Fill the current function with one-shot break points. | 1199 // Fill the current function with one-shot break points. |
| 1122 FloodWithOneShot(shared); | 1200 FloodWithOneShot(shared); |
| 1123 | 1201 |
| 1124 // Remember source position and frame to handle step next. | 1202 // Remember source position and frame to handle step next. |
| 1125 thread_local_.last_statement_position_ = | 1203 thread_local_.last_statement_position_ = |
| 1126 debug_info->code()->SourceStatementPosition(frame->pc()); | 1204 debug_info->code()->SourceStatementPosition(frame->pc()); |
| 1127 thread_local_.last_fp_ = frame->fp(); | 1205 thread_local_.last_fp_ = frame->fp(); |
| 1128 } else { | 1206 } else { |
| 1207 // If it's CallFunction stub ensure target function is compiled and flood |
| 1208 // it with one shot breakpoints. |
| 1209 if (!call_function_stub.is_null()) { |
| 1210 // Find out number of arguments from the stub minor key. |
| 1211 // Reverse lookup required as the minor key cannot be retrieved |
| 1212 // from the code object. |
| 1213 Handle<Object> obj( |
| 1214 Heap::code_stubs()->SlowReverseLookup(*call_function_stub)); |
| 1215 ASSERT(*obj != Heap::undefined_value()); |
| 1216 ASSERT(obj->IsSmi()); |
| 1217 // Get the STUB key and extract major and minor key. |
| 1218 uint32_t key = Smi::cast(*obj)->value(); |
| 1219 // Argc in the stub is the number of arguments passed - not the |
| 1220 // expected arguments of the called function. |
| 1221 int call_function_arg_count = CodeStub::MinorKeyFromKey(key); |
| 1222 ASSERT(call_function_stub->major_key() == |
| 1223 CodeStub::MajorKeyFromKey(key)); |
| 1224 |
| 1225 // Find target function on the expression stack. |
| 1226 // Expression stack lools like this (top to bottom): |
| 1227 // argN |
| 1228 // ... |
| 1229 // arg0 |
| 1230 // Receiver |
| 1231 // Function to call |
| 1232 int expressions_count = frame->ComputeExpressionsCount(); |
| 1233 ASSERT(expressions_count - 2 - call_function_arg_count >= 0); |
| 1234 Object* fun = frame->GetExpression( |
| 1235 expressions_count - 2 - call_function_arg_count); |
| 1236 if (fun->IsJSFunction()) { |
| 1237 Handle<JSFunction> js_function(JSFunction::cast(fun)); |
| 1238 // Don't step into builtins. |
| 1239 if (!js_function->IsBuiltin()) { |
| 1240 // It will also compile target function if it's not compiled yet. |
| 1241 FloodWithOneShot(Handle<SharedFunctionInfo>(js_function->shared())); |
| 1242 } |
| 1243 } |
| 1244 } |
| 1245 |
| 1129 // Fill the current function with one-shot break points even for step in on | 1246 // 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 | 1247 // 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 | 1248 // which step in will not stop. It also prepares for stepping in |
| 1132 // getters/setters. | 1249 // getters/setters. |
| 1133 FloodWithOneShot(shared); | 1250 FloodWithOneShot(shared); |
| 1134 | 1251 |
| 1135 if (is_load_or_store) { | 1252 if (is_load_or_store) { |
| 1136 // Remember source position and frame to handle step in getter/setter. If | 1253 // Remember source position and frame to handle step in getter/setter. If |
| 1137 // there is a custom getter/setter it will be handled in | 1254 // there is a custom getter/setter it will be handled in |
| 1138 // Object::Get/SetPropertyWithCallback, otherwise the step action will be | 1255 // Object::Get/SetPropertyWithCallback, otherwise the step action will be |
| (...skipping 1424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2563 | 2680 |
| 2564 | 2681 |
| 2565 void LockingCommandMessageQueue::Clear() { | 2682 void LockingCommandMessageQueue::Clear() { |
| 2566 ScopedLock sl(lock_); | 2683 ScopedLock sl(lock_); |
| 2567 queue_.Clear(); | 2684 queue_.Clear(); |
| 2568 } | 2685 } |
| 2569 | 2686 |
| 2570 #endif // ENABLE_DEBUGGER_SUPPORT | 2687 #endif // ENABLE_DEBUGGER_SUPPORT |
| 2571 | 2688 |
| 2572 } } // namespace v8::internal | 2689 } } // namespace v8::internal |
| OLD | NEW |