| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/api.h" | 7 #include "src/api.h" |
| 8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
| 9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 rinfo()->data() - debug_info_->shared()->start_position()); | 113 rinfo()->data() - debug_info_->shared()->start_position()); |
| 114 } | 114 } |
| 115 // Always update the position as we don't want that to be before the | 115 // Always update the position as we don't want that to be before the |
| 116 // statement position. | 116 // statement position. |
| 117 position_ = static_cast<int>( | 117 position_ = static_cast<int>( |
| 118 rinfo()->data() - debug_info_->shared()->start_position()); | 118 rinfo()->data() - debug_info_->shared()->start_position()); |
| 119 DCHECK(position_ >= 0); | 119 DCHECK(position_ >= 0); |
| 120 DCHECK(statement_position_ >= 0); | 120 DCHECK(statement_position_ >= 0); |
| 121 } | 121 } |
| 122 | 122 |
| 123 if (IsDebugBreakSlot()) { | 123 // Check for break at return. |
| 124 // There is always a possible break point at a debug break slot. | 124 if (RelocInfo::IsJSReturn(rmode())) { |
| 125 // Set the positions to the end of the function. |
| 126 if (debug_info_->shared()->HasSourceCode()) { |
| 127 position_ = debug_info_->shared()->end_position() - |
| 128 debug_info_->shared()->start_position() - 1; |
| 129 } else { |
| 130 position_ = 0; |
| 131 } |
| 132 statement_position_ = position_; |
| 125 break_point_++; | 133 break_point_++; |
| 126 return; | 134 return; |
| 127 } else if (RelocInfo::IsCodeTarget(rmode())) { | 135 } |
| 136 |
| 137 if (RelocInfo::IsCodeTarget(rmode())) { |
| 128 // Check for breakable code target. Look in the original code as setting | 138 // Check for breakable code target. Look in the original code as setting |
| 129 // break points can cause the code targets in the running (debugged) code | 139 // break points can cause the code targets in the running (debugged) code |
| 130 // to be of a different kind than in the original code. | 140 // to be of a different kind than in the original code. |
| 131 Address target = original_rinfo()->target_address(); | 141 Address target = original_rinfo()->target_address(); |
| 132 Code* code = Code::GetCodeFromTargetAddress(target); | 142 Code* code = Code::GetCodeFromTargetAddress(target); |
| 133 if ((code->is_inline_cache_stub() && | 143 |
| 134 !code->is_binary_op_stub() && | 144 if (RelocInfo::IsConstructCall(rmode()) || code->is_call_stub()) { |
| 135 !code->is_compare_ic_stub() && | |
| 136 !code->is_to_boolean_ic_stub()) || | |
| 137 RelocInfo::IsConstructCall(rmode())) { | |
| 138 break_point_++; | 145 break_point_++; |
| 139 return; | 146 return; |
| 140 } | 147 } |
| 148 |
| 149 // Skip below if we only want locations for calls and returns. |
| 150 if (type_ == CALLS_AND_RETURNS) continue; |
| 151 |
| 152 if ((code->is_inline_cache_stub() && !code->is_binary_op_stub() && |
| 153 !code->is_compare_ic_stub() && !code->is_to_boolean_ic_stub())) { |
| 154 break_point_++; |
| 155 return; |
| 156 } |
| 141 if (code->kind() == Code::STUB) { | 157 if (code->kind() == Code::STUB) { |
| 142 if (IsDebuggerStatement()) { | 158 if (IsDebuggerStatement()) { |
| 143 break_point_++; | 159 break_point_++; |
| 144 return; | 160 return; |
| 145 } else if (type_ == ALL_BREAK_LOCATIONS) { | 161 } else if (type_ == ALL_BREAK_LOCATIONS) { |
| 146 if (IsBreakStub(code)) { | 162 if (IsBreakStub(code)) { |
| 147 break_point_++; | 163 break_point_++; |
| 148 return; | 164 return; |
| 149 } | 165 } |
| 150 } else { | 166 } else { |
| 151 DCHECK(type_ == SOURCE_BREAK_LOCATIONS); | 167 DCHECK(type_ == SOURCE_BREAK_LOCATIONS); |
| 152 if (IsSourceBreakStub(code)) { | 168 if (IsSourceBreakStub(code)) { |
| 153 break_point_++; | 169 break_point_++; |
| 154 return; | 170 return; |
| 155 } | 171 } |
| 156 } | 172 } |
| 157 } | 173 } |
| 158 } | 174 } |
| 159 | 175 |
| 160 // Check for break at return. | 176 if (IsDebugBreakSlot() && type_ != CALLS_AND_RETURNS) { |
| 161 if (RelocInfo::IsJSReturn(rmode())) { | 177 // There is always a possible break point at a debug break slot. |
| 162 // Set the positions to the end of the function. | |
| 163 if (debug_info_->shared()->HasSourceCode()) { | |
| 164 position_ = debug_info_->shared()->end_position() - | |
| 165 debug_info_->shared()->start_position() - 1; | |
| 166 } else { | |
| 167 position_ = 0; | |
| 168 } | |
| 169 statement_position_ = position_; | |
| 170 break_point_++; | 178 break_point_++; |
| 171 return; | 179 return; |
| 172 } | 180 } |
| 173 } | 181 } |
| 174 } | 182 } |
| 175 | 183 |
| 176 | 184 |
| 177 void BreakLocationIterator::Next(int count) { | 185 void BreakLocationIterator::Next(int count) { |
| 178 while (count > 0) { | 186 while (count > 0) { |
| 179 Next(); | 187 Next(); |
| (...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1182 node = node->next(); | 1190 node = node->next(); |
| 1183 } | 1191 } |
| 1184 | 1192 |
| 1185 // Remove all debug info. | 1193 // Remove all debug info. |
| 1186 while (debug_info_list_ != NULL) { | 1194 while (debug_info_list_ != NULL) { |
| 1187 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); | 1195 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); |
| 1188 } | 1196 } |
| 1189 } | 1197 } |
| 1190 | 1198 |
| 1191 | 1199 |
| 1192 void Debug::FloodWithOneShot(Handle<JSFunction> function) { | 1200 void Debug::FloodWithOneShot(Handle<JSFunction> function, |
| 1201 BreakLocatorType type) { |
| 1193 PrepareForBreakPoints(); | 1202 PrepareForBreakPoints(); |
| 1194 | 1203 |
| 1195 // Make sure the function is compiled and has set up the debug info. | 1204 // Make sure the function is compiled and has set up the debug info. |
| 1196 Handle<SharedFunctionInfo> shared(function->shared()); | 1205 Handle<SharedFunctionInfo> shared(function->shared()); |
| 1197 if (!EnsureDebugInfo(shared, function)) { | 1206 if (!EnsureDebugInfo(shared, function)) { |
| 1198 // Return if we failed to retrieve the debug info. | 1207 // Return if we failed to retrieve the debug info. |
| 1199 return; | 1208 return; |
| 1200 } | 1209 } |
| 1201 | 1210 |
| 1202 // Flood the function with break points. | 1211 // Flood the function with break points. |
| 1203 BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS); | 1212 BreakLocationIterator it(GetDebugInfo(shared), type); |
| 1204 while (!it.Done()) { | 1213 while (!it.Done()) { |
| 1205 it.SetOneShot(); | 1214 it.SetOneShot(); |
| 1206 it.Next(); | 1215 it.Next(); |
| 1207 } | 1216 } |
| 1208 } | 1217 } |
| 1209 | 1218 |
| 1210 | 1219 |
| 1211 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) { | 1220 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) { |
| 1212 Handle<FixedArray> new_bindings(function->function_bindings()); | 1221 Handle<FixedArray> new_bindings(function->function_bindings()); |
| 1213 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex), | 1222 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex), |
| 1214 isolate_); | 1223 isolate_); |
| 1215 | 1224 |
| 1216 if (!bindee.is_null() && bindee->IsJSFunction() && | 1225 if (!bindee.is_null() && bindee->IsJSFunction() && |
| 1217 !JSFunction::cast(*bindee)->IsFromNativeScript()) { | 1226 !JSFunction::cast(*bindee)->IsFromNativeScript()) { |
| 1218 Handle<JSFunction> bindee_function(JSFunction::cast(*bindee)); | 1227 Handle<JSFunction> bindee_function(JSFunction::cast(*bindee)); |
| 1219 Debug::FloodWithOneShot(bindee_function); | 1228 FloodWithOneShot(bindee_function); |
| 1220 } | 1229 } |
| 1221 } | 1230 } |
| 1222 | 1231 |
| 1223 | 1232 |
| 1224 void Debug::FloodHandlerWithOneShot() { | 1233 void Debug::FloodHandlerWithOneShot() { |
| 1225 // Iterate through the JavaScript stack looking for handlers. | 1234 // Iterate through the JavaScript stack looking for handlers. |
| 1226 StackFrame::Id id = break_frame_id(); | 1235 StackFrame::Id id = break_frame_id(); |
| 1227 if (id == StackFrame::NO_ID) { | 1236 if (id == StackFrame::NO_ID) { |
| 1228 // If there is no JavaScript stack don't do anything. | 1237 // If there is no JavaScript stack don't do anything. |
| 1229 return; | 1238 return; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1289 id = frame_id; | 1298 id = frame_id; |
| 1290 } | 1299 } |
| 1291 JavaScriptFrameIterator frames_it(isolate_, id); | 1300 JavaScriptFrameIterator frames_it(isolate_, id); |
| 1292 JavaScriptFrame* frame = frames_it.frame(); | 1301 JavaScriptFrame* frame = frames_it.frame(); |
| 1293 | 1302 |
| 1294 // First of all ensure there is one-shot break points in the top handler | 1303 // First of all ensure there is one-shot break points in the top handler |
| 1295 // if any. | 1304 // if any. |
| 1296 FloodHandlerWithOneShot(); | 1305 FloodHandlerWithOneShot(); |
| 1297 | 1306 |
| 1298 // If the function on the top frame is unresolved perform step out. This will | 1307 // If the function on the top frame is unresolved perform step out. This will |
| 1299 // be the case when calling unknown functions and having the debugger stopped | 1308 // be the case when calling unknown function and having the debugger stopped |
| 1300 // in an unhandled exception. | 1309 // in an unhandled exception. |
| 1301 if (!frame->function()->IsJSFunction()) { | 1310 if (!frame->function()->IsJSFunction()) { |
| 1302 // Step out: Find the calling JavaScript frame and flood it with | 1311 // Step out: Find the calling JavaScript frame and flood it with |
| 1303 // breakpoints. | 1312 // breakpoints. |
| 1304 frames_it.Advance(); | 1313 frames_it.Advance(); |
| 1305 // Fill the function to return to with one-shot break points. | 1314 // Fill the function to return to with one-shot break points. |
| 1306 JSFunction* function = frames_it.frame()->function(); | 1315 JSFunction* function = frames_it.frame()->function(); |
| 1307 FloodWithOneShot(Handle<JSFunction>(function)); | 1316 FloodWithOneShot(Handle<JSFunction>(function)); |
| 1308 return; | 1317 return; |
| 1309 } | 1318 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1347 // If there is a breakpoint at this line look at the original code to | 1356 // If there is a breakpoint at this line look at the original code to |
| 1348 // check if it is a CallFunction stub. | 1357 // check if it is a CallFunction stub. |
| 1349 if (it.IsDebugBreak()) { | 1358 if (it.IsDebugBreak()) { |
| 1350 Address original_target = it.original_rinfo()->target_address(); | 1359 Address original_target = it.original_rinfo()->target_address(); |
| 1351 maybe_call_function_stub = | 1360 maybe_call_function_stub = |
| 1352 Code::GetCodeFromTargetAddress(original_target); | 1361 Code::GetCodeFromTargetAddress(original_target); |
| 1353 } | 1362 } |
| 1354 if ((maybe_call_function_stub->kind() == Code::STUB && | 1363 if ((maybe_call_function_stub->kind() == Code::STUB && |
| 1355 CodeStub::GetMajorKey(maybe_call_function_stub) == | 1364 CodeStub::GetMajorKey(maybe_call_function_stub) == |
| 1356 CodeStub::CallFunction) || | 1365 CodeStub::CallFunction) || |
| 1357 maybe_call_function_stub->kind() == Code::CALL_IC) { | 1366 maybe_call_function_stub->is_call_stub()) { |
| 1358 // Save reference to the code as we may need it to find out arguments | 1367 // Save reference to the code as we may need it to find out arguments |
| 1359 // count for 'step in' later. | 1368 // count for 'step in' later. |
| 1360 call_function_stub = Handle<Code>(maybe_call_function_stub); | 1369 call_function_stub = Handle<Code>(maybe_call_function_stub); |
| 1361 } | 1370 } |
| 1362 } | 1371 } |
| 1363 } else { | 1372 } else { |
| 1364 is_at_restarted_function = true; | 1373 is_at_restarted_function = true; |
| 1365 } | 1374 } |
| 1366 | 1375 |
| 1367 // If this is the last break code target step out is the only possibility. | 1376 // If this is the last break code target step out is the only possibility. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1388 FloodWithOneShot(Handle<JSFunction>(function)); | 1397 FloodWithOneShot(Handle<JSFunction>(function)); |
| 1389 // Set target frame pointer. | 1398 // Set target frame pointer. |
| 1390 ActivateStepOut(frames_it.frame()); | 1399 ActivateStepOut(frames_it.frame()); |
| 1391 } | 1400 } |
| 1392 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || | 1401 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || |
| 1393 !call_function_stub.is_null() || is_at_restarted_function) | 1402 !call_function_stub.is_null() || is_at_restarted_function) |
| 1394 || step_action == StepNext || step_action == StepMin) { | 1403 || step_action == StepNext || step_action == StepMin) { |
| 1395 // Step next or step min. | 1404 // Step next or step min. |
| 1396 | 1405 |
| 1397 // Fill the current function with one-shot break points. | 1406 // Fill the current function with one-shot break points. |
| 1398 FloodWithOneShot(function); | 1407 // If we are stepping into another frame, only fill calls and returns. |
| 1408 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS |
| 1409 : ALL_BREAK_LOCATIONS); |
| 1399 | 1410 |
| 1400 // Remember source position and frame to handle step next. | 1411 // Remember source position and frame to handle step next. |
| 1401 thread_local_.last_statement_position_ = | 1412 thread_local_.last_statement_position_ = |
| 1402 debug_info->code()->SourceStatementPosition(frame->pc()); | 1413 debug_info->code()->SourceStatementPosition(frame->pc()); |
| 1403 thread_local_.last_fp_ = frame->UnpaddedFP(); | 1414 thread_local_.last_fp_ = frame->UnpaddedFP(); |
| 1404 } else { | 1415 } else { |
| 1405 // If there's restarter frame on top of the stack, just get the pointer | 1416 // If there's restarter frame on top of the stack, just get the pointer |
| 1406 // to function which is going to be restarted. | 1417 // to function which is going to be restarted. |
| 1407 if (is_at_restarted_function) { | 1418 if (is_at_restarted_function) { |
| 1408 Handle<JSFunction> restarted_function( | 1419 Handle<JSFunction> restarted_function( |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1447 Code* code = JSFunction::cast(fun)->shared()->code(); | 1458 Code* code = JSFunction::cast(fun)->shared()->code(); |
| 1448 if (code != apply && code != call) break; | 1459 if (code != apply && code != call) break; |
| 1449 fun = frame->GetExpression( | 1460 fun = frame->GetExpression( |
| 1450 expressions_count - 1 - call_function_arg_count); | 1461 expressions_count - 1 - call_function_arg_count); |
| 1451 } | 1462 } |
| 1452 } | 1463 } |
| 1453 | 1464 |
| 1454 if (fun->IsJSFunction()) { | 1465 if (fun->IsJSFunction()) { |
| 1455 Handle<JSFunction> js_function(JSFunction::cast(fun)); | 1466 Handle<JSFunction> js_function(JSFunction::cast(fun)); |
| 1456 if (js_function->shared()->bound()) { | 1467 if (js_function->shared()->bound()) { |
| 1457 Debug::FloodBoundFunctionWithOneShot(js_function); | 1468 FloodBoundFunctionWithOneShot(js_function); |
| 1458 } else if (!js_function->IsFromNativeScript()) { | 1469 } else if (!js_function->IsFromNativeScript()) { |
| 1459 // Don't step into builtins. | 1470 // Don't step into builtins. |
| 1460 // It will also compile target function if it's not compiled yet. | 1471 // It will also compile target function if it's not compiled yet. |
| 1461 FloodWithOneShot(js_function); | 1472 FloodWithOneShot(js_function); |
| 1462 } | 1473 } |
| 1463 } | 1474 } |
| 1464 } | 1475 } |
| 1465 | 1476 |
| 1466 // Fill the current function with one-shot break points even for step in on | 1477 // Fill the current function with one-shot break points even for step in on |
| 1467 // a call target as the function called might be a native function for | 1478 // a call target as the function called might be a native function for |
| 1468 // which step in will not stop. It also prepares for stepping in | 1479 // which step in will not stop. It also prepares for stepping in |
| 1469 // getters/setters. | 1480 // getters/setters. |
| 1470 FloodWithOneShot(function); | 1481 // If we are stepping into another frame, only fill calls and returns. |
| 1482 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS |
| 1483 : ALL_BREAK_LOCATIONS); |
| 1471 | 1484 |
| 1472 if (is_load_or_store) { | 1485 if (is_load_or_store) { |
| 1473 // Remember source position and frame to handle step in getter/setter. If | 1486 // Remember source position and frame to handle step in getter/setter. If |
| 1474 // there is a custom getter/setter it will be handled in | 1487 // there is a custom getter/setter it will be handled in |
| 1475 // Object::Get/SetPropertyWithAccessor, otherwise the step action will be | 1488 // Object::Get/SetPropertyWithAccessor, otherwise the step action will be |
| 1476 // propagated on the next Debug::Break. | 1489 // propagated on the next Debug::Break. |
| 1477 thread_local_.last_statement_position_ = | 1490 thread_local_.last_statement_position_ = |
| 1478 debug_info->code()->SourceStatementPosition(frame->pc()); | 1491 debug_info->code()->SourceStatementPosition(frame->pc()); |
| 1479 thread_local_.last_fp_ = frame->UnpaddedFP(); | 1492 thread_local_.last_fp_ = frame->UnpaddedFP(); |
| 1480 } | 1493 } |
| 1481 | 1494 |
| 1482 // Step in or Step in min | 1495 // Step in or Step in min |
| 1483 it.PrepareStepIn(isolate_); | 1496 it.PrepareStepIn(isolate_); |
| 1484 ActivateStepIn(frame); | 1497 ActivateStepIn(frame); |
| 1485 } | 1498 } |
| 1486 } | 1499 } |
| 1487 | 1500 |
| 1488 | 1501 |
| 1489 // Check whether the current debug break should be reported to the debugger. It | 1502 // Check whether the current debug break should be reported to the debugger. It |
| 1490 // is used to have step next and step in only report break back to the debugger | 1503 // is used to have step next and step in only report break back to the debugger |
| 1491 // if on a different frame or in a different statement. In some situations | 1504 // if on a different frame or in a different statement. In some situations |
| 1492 // there will be several break points in the same statement when the code is | 1505 // there will be several break points in the same statement when the code is |
| 1493 // flooded with one-shot break points. This function helps to perform several | 1506 // flooded with one-shot break points. This function helps to perform several |
| 1494 // steps before reporting break back to the debugger. | 1507 // steps before reporting break back to the debugger. |
| 1495 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator, | 1508 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator, |
| 1496 JavaScriptFrame* frame) { | 1509 JavaScriptFrame* frame) { |
| 1497 // StepNext and StepOut shouldn't bring us deeper in code, so last frame | 1510 // StepNext and StepOut shouldn't bring us deeper in code, so last frame |
| 1498 // shouldn't be a parent of current frame. | 1511 // shouldn't be a parent of current frame. |
| 1499 if (thread_local_.last_step_action_ == StepNext || | 1512 StepAction step_action = thread_local_.last_step_action_; |
| 1500 thread_local_.last_step_action_ == StepOut) { | 1513 |
| 1514 if (step_action == StepNext || step_action == StepOut) { |
| 1501 if (frame->fp() < thread_local_.last_fp_) return true; | 1515 if (frame->fp() < thread_local_.last_fp_) return true; |
| 1502 } | 1516 } |
| 1503 | 1517 |
| 1518 // We stepped into a new frame if the frame pointer changed. |
| 1519 if (step_action == StepFrame) { |
| 1520 return frame->UnpaddedFP() == thread_local_.last_fp_; |
| 1521 } |
| 1522 |
| 1504 // If the step last action was step next or step in make sure that a new | 1523 // If the step last action was step next or step in make sure that a new |
| 1505 // statement is hit. | 1524 // statement is hit. |
| 1506 if (thread_local_.last_step_action_ == StepNext || | 1525 if (step_action == StepNext || step_action == StepIn) { |
| 1507 thread_local_.last_step_action_ == StepIn) { | |
| 1508 // Never continue if returning from function. | 1526 // Never continue if returning from function. |
| 1509 if (break_location_iterator->IsExit()) return false; | 1527 if (break_location_iterator->IsExit()) return false; |
| 1510 | 1528 |
| 1511 // Continue if we are still on the same frame and in the same statement. | 1529 // Continue if we are still on the same frame and in the same statement. |
| 1512 int current_statement_position = | 1530 int current_statement_position = |
| 1513 break_location_iterator->code()->SourceStatementPosition(frame->pc()); | 1531 break_location_iterator->code()->SourceStatementPosition(frame->pc()); |
| 1514 return thread_local_.last_fp_ == frame->UnpaddedFP() && | 1532 return thread_local_.last_fp_ == frame->UnpaddedFP() && |
| 1515 thread_local_.last_statement_position_ == current_statement_position; | 1533 thread_local_.last_statement_position_ == current_statement_position; |
| 1516 } | 1534 } |
| 1517 | 1535 |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1564 | 1582 |
| 1565 locations->set(count++, position); | 1583 locations->set(count++, position); |
| 1566 } | 1584 } |
| 1567 } | 1585 } |
| 1568 } | 1586 } |
| 1569 return locations; | 1587 return locations; |
| 1570 } | 1588 } |
| 1571 | 1589 |
| 1572 | 1590 |
| 1573 // Handle stepping into a function. | 1591 // Handle stepping into a function. |
| 1574 void Debug::HandleStepIn(Handle<JSFunction> function, | 1592 void Debug::HandleStepIn(Handle<Object> function_obj, Handle<Object> holder, |
| 1575 Handle<Object> holder, | 1593 Address fp, bool is_constructor) { |
| 1576 Address fp, | 1594 // Flood getter/setter if we either step in or step to another frame. |
| 1577 bool is_constructor) { | 1595 bool step_frame = thread_local_.last_step_action_ == StepFrame; |
| 1596 if (!StepInActive() && !step_frame) return; |
| 1597 if (!function_obj->IsJSFunction()) return; |
| 1598 Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj); |
| 1578 Isolate* isolate = function->GetIsolate(); | 1599 Isolate* isolate = function->GetIsolate(); |
| 1579 // If the frame pointer is not supplied by the caller find it. | 1600 // If the frame pointer is not supplied by the caller find it. |
| 1580 if (fp == 0) { | 1601 if (fp == 0) { |
| 1581 StackFrameIterator it(isolate); | 1602 StackFrameIterator it(isolate); |
| 1582 it.Advance(); | 1603 it.Advance(); |
| 1583 // For constructor functions skip another frame. | 1604 // For constructor functions skip another frame. |
| 1584 if (is_constructor) { | 1605 if (is_constructor) { |
| 1585 DCHECK(it.frame()->is_construct()); | 1606 DCHECK(it.frame()->is_construct()); |
| 1586 it.Advance(); | 1607 it.Advance(); |
| 1587 } | 1608 } |
| 1588 fp = it.frame()->fp(); | 1609 fp = it.frame()->fp(); |
| 1589 } | 1610 } |
| 1590 | 1611 |
| 1591 // Flood the function with one-shot break points if it is called from where | 1612 // Flood the function with one-shot break points if it is called from where |
| 1592 // step into was requested. | 1613 // step into was requested, or when stepping into a new frame. |
| 1593 if (fp == thread_local_.step_into_fp_) { | 1614 if (fp == thread_local_.step_into_fp_ || step_frame) { |
| 1594 if (function->shared()->bound()) { | 1615 if (function->shared()->bound()) { |
| 1595 // Handle Function.prototype.bind | 1616 // Handle Function.prototype.bind |
| 1596 Debug::FloodBoundFunctionWithOneShot(function); | 1617 FloodBoundFunctionWithOneShot(function); |
| 1597 } else if (!function->IsFromNativeScript()) { | 1618 } else if (!function->IsFromNativeScript()) { |
| 1598 // Don't allow step into functions in the native context. | 1619 // Don't allow step into functions in the native context. |
| 1599 if (function->shared()->code() == | 1620 if (function->shared()->code() == |
| 1600 isolate->builtins()->builtin(Builtins::kFunctionApply) || | 1621 isolate->builtins()->builtin(Builtins::kFunctionApply) || |
| 1601 function->shared()->code() == | 1622 function->shared()->code() == |
| 1602 isolate->builtins()->builtin(Builtins::kFunctionCall)) { | 1623 isolate->builtins()->builtin(Builtins::kFunctionCall)) { |
| 1603 // Handle function.apply and function.call separately to flood the | 1624 // Handle function.apply and function.call separately to flood the |
| 1604 // function to be called and not the code for Builtins::FunctionApply or | 1625 // function to be called and not the code for Builtins::FunctionApply or |
| 1605 // Builtins::FunctionCall. The receiver of call/apply is the target | 1626 // Builtins::FunctionCall. The receiver of call/apply is the target |
| 1606 // function. | 1627 // function. |
| 1607 if (!holder.is_null() && holder->IsJSFunction()) { | 1628 if (!holder.is_null() && holder->IsJSFunction()) { |
| 1608 Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder); | 1629 Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder); |
| 1609 if (!js_function->IsFromNativeScript()) { | 1630 if (!js_function->IsFromNativeScript()) { |
| 1610 Debug::FloodWithOneShot(js_function); | 1631 FloodWithOneShot(js_function); |
| 1611 } else if (js_function->shared()->bound()) { | 1632 } else if (js_function->shared()->bound()) { |
| 1612 // Handle Function.prototype.bind | 1633 // Handle Function.prototype.bind |
| 1613 Debug::FloodBoundFunctionWithOneShot(js_function); | 1634 FloodBoundFunctionWithOneShot(js_function); |
| 1614 } | 1635 } |
| 1615 } | 1636 } |
| 1616 } else { | 1637 } else { |
| 1617 Debug::FloodWithOneShot(function); | 1638 FloodWithOneShot(function); |
| 1618 } | 1639 } |
| 1619 } | 1640 } |
| 1620 } | 1641 } |
| 1621 } | 1642 } |
| 1622 | 1643 |
| 1623 | 1644 |
| 1624 void Debug::ClearStepping() { | 1645 void Debug::ClearStepping() { |
| 1625 // Clear the various stepping setup. | 1646 // Clear the various stepping setup. |
| 1626 ClearOneShot(); | 1647 ClearOneShot(); |
| 1627 ClearStepIn(); | 1648 ClearStepIn(); |
| (...skipping 1777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3405 logger_->DebugEvent("Put", message.text()); | 3426 logger_->DebugEvent("Put", message.text()); |
| 3406 } | 3427 } |
| 3407 | 3428 |
| 3408 | 3429 |
| 3409 void LockingCommandMessageQueue::Clear() { | 3430 void LockingCommandMessageQueue::Clear() { |
| 3410 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 3431 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 3411 queue_.Clear(); | 3432 queue_.Clear(); |
| 3412 } | 3433 } |
| 3413 | 3434 |
| 3414 } } // namespace v8::internal | 3435 } } // namespace v8::internal |
| OLD | NEW |