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

Side by Side Diff: src/debug.cc

Issue 942003002: Fix GC-unsafe use of BreakLocationIterator. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « src/debug.h ('k') | test/mjsunit/mjsunit.status » ('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 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 369 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); 380 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
381 if (target_code->kind() == Code::STUB) { 381 if (target_code->kind() == Code::STUB) {
382 return CodeStub::GetMajorKey(*target_code) == CodeStub::CallFunction; 382 return CodeStub::GetMajorKey(*target_code) == CodeStub::CallFunction;
383 } 383 }
384 return target_code->is_call_stub(); 384 return target_code->is_call_stub();
385 } 385 }
386 return false; 386 return false;
387 } 387 }
388 388
389 389
390 void BreakLocationIterator::PrepareStepIn(Isolate* isolate) {
391 #ifdef DEBUG
392 HandleScope scope(isolate);
393 // Step in can only be prepared if currently positioned on an IC call,
394 // construct call or CallFunction stub call.
395 Address target = rinfo()->target_address();
396 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
397 // All the following stuff is needed only for assertion checks so the code
398 // is wrapped in ifdef.
399 Handle<Code> maybe_call_function_stub = target_code;
400 if (IsDebugBreak()) {
401 Address original_target = original_rinfo()->target_address();
402 maybe_call_function_stub =
403 Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
404 }
405 bool is_call_function_stub =
406 (maybe_call_function_stub->kind() == Code::STUB &&
407 CodeStub::GetMajorKey(*maybe_call_function_stub) ==
408 CodeStub::CallFunction);
409
410 // Step in through construct call requires no changes to the running code.
411 // Step in through getters/setters should already be prepared as well
412 // because caller of this function (Debug::PrepareStep) is expected to
413 // flood the top frame's function with one shot breakpoints.
414 // Step in through CallFunction stub should also be prepared by caller of
415 // this function (Debug::PrepareStep) which should flood target function
416 // with breakpoints.
417 DCHECK(RelocInfo::IsConstructCall(rmode()) ||
418 target_code->is_inline_cache_stub() ||
419 is_call_function_stub);
420 #endif
421 }
422
423
424 // Check whether the break point is at a position which will exit the function. 390 // Check whether the break point is at a position which will exit the function.
425 bool BreakLocationIterator::IsExit() const { 391 bool BreakLocationIterator::IsExit() const {
426 return (RelocInfo::IsJSReturn(rmode())); 392 return (RelocInfo::IsJSReturn(rmode()));
427 } 393 }
428 394
429 395
430 bool BreakLocationIterator::HasBreakPoint() { 396 bool BreakLocationIterator::HasBreakPoint() {
431 return debug_info_->HasBreakPoint(code_position()); 397 return debug_info_->HasBreakPoint(code_position());
432 } 398 }
433 399
(...skipping 930 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 1330
1365 // Get the debug info (create it if it does not exist). 1331 // Get the debug info (create it if it does not exist).
1366 Handle<JSFunction> function(frame->function()); 1332 Handle<JSFunction> function(frame->function());
1367 Handle<SharedFunctionInfo> shared(function->shared()); 1333 Handle<SharedFunctionInfo> shared(function->shared());
1368 if (!EnsureDebugInfo(shared, function)) { 1334 if (!EnsureDebugInfo(shared, function)) {
1369 // Return if ensuring debug info failed. 1335 // Return if ensuring debug info failed.
1370 return; 1336 return;
1371 } 1337 }
1372 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 1338 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1373 1339
1374 // Find the break location where execution has stopped.
1375 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1376 // pc points to the instruction after the current one, possibly a break
1377 // location as well. So the "- 1" to exclude it from the search.
1378 it.FindBreakLocationFromAddress(frame->pc() - 1);
1379
1380 // Compute whether or not the target is a call target. 1340 // Compute whether or not the target is a call target.
1381 bool is_load_or_store = false; 1341 bool is_load_or_store = false;
1382 bool is_inline_cache_stub = false; 1342 bool is_inline_cache_stub = false;
1383 bool is_at_restarted_function = false; 1343 bool is_at_restarted_function = false;
1344 bool is_exit = false;
1345 bool is_construct_call = false;
1384 Handle<Code> call_function_stub; 1346 Handle<Code> call_function_stub;
1385 1347
1386 if (thread_local_.restarter_frame_function_pointer_ == NULL) { 1348 {
1387 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) { 1349 // Find the break location where execution has stopped.
1388 bool is_call_target = false; 1350 DisallowHeapAllocation no_gc;
1389 Address target = it.rinfo()->target_address(); 1351 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1390 Code* code = Code::GetCodeFromTargetAddress(target); 1352
1391 if (code->is_call_stub()) { 1353 // pc points to the instruction after the current one, possibly a break
1392 is_call_target = true; 1354 // location as well. So the "- 1" to exclude it from the search.
1355 it.FindBreakLocationFromAddress(frame->pc() - 1);
1356
1357 is_exit = it.IsExit();
1358
1359 if (thread_local_.restarter_frame_function_pointer_ == NULL) {
1360 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1361 bool is_call_target = false;
1362 Address target = it.rinfo()->target_address();
1363 Code* code = Code::GetCodeFromTargetAddress(target);
1364
1365 is_call_target = code->is_call_stub();
1366 is_construct_call = RelocInfo::IsConstructCall(it.rmode());
1367 is_inline_cache_stub = code->is_inline_cache_stub();
1368 is_load_or_store = is_inline_cache_stub && !is_call_target;
1369
1370 // Check if target code is CallFunction stub.
1371 Code* maybe_call_function_stub = code;
1372 // If there is a breakpoint at this line look at the original code to
1373 // check if it is a CallFunction stub.
1374 if (it.IsDebugBreak()) {
1375 Address original_target = it.original_rinfo()->target_address();
1376 maybe_call_function_stub =
1377 Code::GetCodeFromTargetAddress(original_target);
1378 }
1379 if ((maybe_call_function_stub->kind() == Code::STUB &&
1380 CodeStub::GetMajorKey(maybe_call_function_stub) ==
1381 CodeStub::CallFunction) ||
1382 maybe_call_function_stub->is_call_stub()) {
1383 // Save reference to the code as we may need it to find out arguments
1384 // count for 'step in' later.
1385 call_function_stub = Handle<Code>(maybe_call_function_stub);
1386 }
1393 } 1387 }
1394 if (code->is_inline_cache_stub()) { 1388 } else {
1395 is_inline_cache_stub = true; 1389 is_at_restarted_function = true;
1396 is_load_or_store = !is_call_target;
1397 }
1398
1399 // Check if target code is CallFunction stub.
1400 Code* maybe_call_function_stub = code;
1401 // If there is a breakpoint at this line look at the original code to
1402 // check if it is a CallFunction stub.
1403 if (it.IsDebugBreak()) {
1404 Address original_target = it.original_rinfo()->target_address();
1405 maybe_call_function_stub =
1406 Code::GetCodeFromTargetAddress(original_target);
1407 }
1408 if ((maybe_call_function_stub->kind() == Code::STUB &&
1409 CodeStub::GetMajorKey(maybe_call_function_stub) ==
1410 CodeStub::CallFunction) ||
1411 maybe_call_function_stub->is_call_stub()) {
1412 // Save reference to the code as we may need it to find out arguments
1413 // count for 'step in' later.
1414 call_function_stub = Handle<Code>(maybe_call_function_stub);
1415 }
1416 } 1390 }
1417 } else {
1418 is_at_restarted_function = true;
1419 } 1391 }
1420 1392
1421 // If this is the last break code target step out is the only possibility. 1393 // If this is the last break code target step out is the only possibility.
1422 if (it.IsExit() || step_action == StepOut) { 1394 if (is_exit || step_action == StepOut) {
1423 if (step_action == StepOut) { 1395 if (step_action == StepOut) {
1424 // Skip step_count frames starting with the current one. 1396 // Skip step_count frames starting with the current one.
1425 while (step_count-- > 0 && !frames_it.done()) { 1397 while (step_count-- > 0 && !frames_it.done()) {
1426 frames_it.Advance(); 1398 frames_it.Advance();
1427 } 1399 }
1428 } else { 1400 } else {
1429 DCHECK(it.IsExit()); 1401 DCHECK(is_exit);
1430 frames_it.Advance(); 1402 frames_it.Advance();
1431 } 1403 }
1432 // Skip builtin functions on the stack. 1404 // Skip builtin functions on the stack.
1433 while (!frames_it.done() && 1405 while (!frames_it.done() &&
1434 frames_it.frame()->function()->IsFromNativeScript()) { 1406 frames_it.frame()->function()->IsFromNativeScript()) {
1435 frames_it.Advance(); 1407 frames_it.Advance();
1436 } 1408 }
1437 // Step out: If there is a JavaScript caller frame, we need to 1409 // Step out: If there is a JavaScript caller frame, we need to
1438 // flood it with breakpoints. 1410 // flood it with breakpoints.
1439 if (!frames_it.done()) { 1411 if (!frames_it.done()) {
1440 // Fill the function to return to with one-shot break points. 1412 // Fill the function to return to with one-shot break points.
1441 JSFunction* function = frames_it.frame()->function(); 1413 JSFunction* function = frames_it.frame()->function();
1442 FloodWithOneShot(Handle<JSFunction>(function)); 1414 FloodWithOneShot(Handle<JSFunction>(function));
1443 // Set target frame pointer. 1415 // Set target frame pointer.
1444 ActivateStepOut(frames_it.frame()); 1416 ActivateStepOut(frames_it.frame());
1445 } 1417 }
1446 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || 1418 } else if (!(is_inline_cache_stub || is_construct_call ||
1447 !call_function_stub.is_null() || is_at_restarted_function) 1419 !call_function_stub.is_null() || is_at_restarted_function) ||
1448 || step_action == StepNext || step_action == StepMin) { 1420 step_action == StepNext || step_action == StepMin) {
1449 // Step next or step min. 1421 // Step next or step min.
1450 1422
1451 // Fill the current function with one-shot break points. 1423 // Fill the current function with one-shot break points.
1452 // If we are stepping into another frame, only fill calls and returns. 1424 // If we are stepping into another frame, only fill calls and returns.
1453 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS 1425 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
1454 : ALL_BREAK_LOCATIONS); 1426 : ALL_BREAK_LOCATIONS);
1455 1427
1456 // Remember source position and frame to handle step next. 1428 // Remember source position and frame to handle step next.
1457 thread_local_.last_statement_position_ = 1429 thread_local_.last_statement_position_ =
1458 debug_info->code()->SourceStatementPosition(frame->pc()); 1430 debug_info->code()->SourceStatementPosition(frame->pc());
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1525 // Remember source position and frame to handle step in getter/setter. If 1497 // Remember source position and frame to handle step in getter/setter. If
1526 // there is a custom getter/setter it will be handled in 1498 // there is a custom getter/setter it will be handled in
1527 // Object::Get/SetPropertyWithAccessor, otherwise the step action will be 1499 // Object::Get/SetPropertyWithAccessor, otherwise the step action will be
1528 // propagated on the next Debug::Break. 1500 // propagated on the next Debug::Break.
1529 thread_local_.last_statement_position_ = 1501 thread_local_.last_statement_position_ =
1530 debug_info->code()->SourceStatementPosition(frame->pc()); 1502 debug_info->code()->SourceStatementPosition(frame->pc());
1531 thread_local_.last_fp_ = frame->UnpaddedFP(); 1503 thread_local_.last_fp_ = frame->UnpaddedFP();
1532 } 1504 }
1533 1505
1534 // Step in or Step in min 1506 // Step in or Step in min
1535 it.PrepareStepIn(isolate_); 1507 // Step in through construct call requires no changes to the running code.
1508 // Step in through getters/setters should already be prepared as well
1509 // because caller of this function (Debug::PrepareStep) is expected to
1510 // flood the top frame's function with one shot breakpoints.
1511 // Step in through CallFunction stub should also be prepared by caller of
1512 // this function (Debug::PrepareStep) which should flood target function
1513 // with breakpoints.
1514 DCHECK(is_construct_call || is_inline_cache_stub ||
1515 !call_function_stub.is_null());
1536 ActivateStepIn(frame); 1516 ActivateStepIn(frame);
1537 } 1517 }
1538 } 1518 }
1539 1519
1540 1520
1541 // Check whether the current debug break should be reported to the debugger. It 1521 // Check whether the current debug break should be reported to the debugger. It
1542 // is used to have step next and step in only report break back to the debugger 1522 // is used to have step next and step in only report break back to the debugger
1543 // if on a different frame or in a different statement. In some situations 1523 // if on a different frame or in a different statement. In some situations
1544 // there will be several break points in the same statement when the code is 1524 // there will be several break points in the same statement when the code is
1545 // flooded with one-shot break points. This function helps to perform several 1525 // flooded with one-shot break points. This function helps to perform several
(...skipping 1946 matching lines...) Expand 10 before | Expand all | Expand 10 after
3492 logger_->DebugEvent("Put", message.text()); 3472 logger_->DebugEvent("Put", message.text());
3493 } 3473 }
3494 3474
3495 3475
3496 void LockingCommandMessageQueue::Clear() { 3476 void LockingCommandMessageQueue::Clear() {
3497 base::LockGuard<base::Mutex> lock_guard(&mutex_); 3477 base::LockGuard<base::Mutex> lock_guard(&mutex_);
3498 queue_.Clear(); 3478 queue_.Clear();
3499 } 3479 }
3500 3480
3501 } } // namespace v8::internal 3481 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/debug.h ('k') | test/mjsunit/mjsunit.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698