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

Side by Side Diff: src/debug.cc

Issue 1235603002: Debugger: make debug code on-stack replacement more robust. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix arm64 Created 5 years, 5 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/assembler.cc ('k') | src/ia32/assembler-ia32.h » ('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 1414 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 } else if (frame->function()->IsJSFunction()) { 1425 } else if (frame->function()->IsJSFunction()) {
1426 JSFunction* function = frame->function(); 1426 JSFunction* function = frame->function();
1427 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); 1427 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION);
1428 active_functions->Add(Handle<JSFunction>(function)); 1428 active_functions->Add(Handle<JSFunction>(function));
1429 function->shared()->code()->set_gc_metadata(active_code_marker); 1429 function->shared()->code()->set_gc_metadata(active_code_marker);
1430 } 1430 }
1431 } 1431 }
1432 } 1432 }
1433 1433
1434 1434
1435 // Figure out how many bytes of "pc_offset" correspond to actual code by 1435 // Count the number of calls before the current frame PC to find the
1436 // subtracting off the bytes that correspond to constant/veneer pools. See 1436 // corresponding PC in the newly recompiled code.
1437 // Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this 1437 static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code,
1438 // is only useful for architectures using constant pools or veneer pools. 1438 Address old_pc) {
1439 static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) { 1439 DCHECK_EQ(old_code->kind(), Code::FUNCTION);
1440 DCHECK_EQ(code->kind(), Code::FUNCTION); 1440 DCHECK_EQ(new_code->kind(), Code::FUNCTION);
1441 DCHECK(!code->has_debug_break_slots()); 1441 DCHECK(!old_code->has_debug_break_slots());
1442 DCHECK_LE(0, pc_offset); 1442 DCHECK(new_code->has_debug_break_slots());
1443 DCHECK_LT(pc_offset, code->instruction_end() - code->instruction_start()); 1443 int mask = RelocInfo::kCodeTargetMask;
1444 1444 int index = 0;
1445 int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) | 1445 intptr_t delta = 0;
1446 RelocInfo::ModeMask(RelocInfo::VENEER_POOL); 1446 for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
1447 byte *pc = code->instruction_start() + pc_offset; 1447 RelocInfo* rinfo = it.rinfo();
1448 int code_offset = pc_offset; 1448 Address current_pc = rinfo->pc();
1449 for (RelocIterator it(code, mask); !it.done(); it.next()) { 1449 // The frame PC is behind the call instruction by the call instruction size.
1450 RelocInfo* info = it.rinfo(); 1450 if (current_pc > old_pc) break;
1451 if (info->pc() >= pc) break; 1451 index++;
1452 DCHECK(RelocInfo::IsConstPool(info->rmode())); 1452 delta = old_pc - current_pc;
Michael Starzinger 2015/07/13 19:35:24 This assumes that for each call site the size is t
1453 code_offset -= static_cast<int>(info->data());
1454 DCHECK_LE(0, code_offset);
1455 } 1453 }
1456 1454
1457 return code_offset; 1455 RelocIterator it(new_code, mask);
1456 for (int i = 1; i < index; i++) it.next();
1457 return it.rinfo()->pc() + delta;
1458 } 1458 }
1459 1459
1460 1460
1461 // The inverse of ComputeCodeOffsetFromPcOffset. 1461 // Count the number of continuations at which the current pc offset is at.
1462 static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) { 1462 static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) {
1463 DCHECK_EQ(code->kind(), Code::FUNCTION); 1463 DCHECK_EQ(code->kind(), Code::FUNCTION);
1464 1464 DCHECK(!code->has_debug_break_slots());
1465 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | 1465 Address pc = code->instruction_start() + pc_offset;
1466 RelocInfo::ModeMask(RelocInfo::CONST_POOL) | 1466 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
1467 RelocInfo::ModeMask(RelocInfo::VENEER_POOL); 1467 int index = 0;
1468 int reloc = 0;
1469 for (RelocIterator it(code, mask); !it.done(); it.next()) { 1468 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1470 RelocInfo* info = it.rinfo(); 1469 index++;
1471 if (info->pc() - code->instruction_start() - reloc >= code_offset) break; 1470 RelocInfo* rinfo = it.rinfo();
1472 if (RelocInfo::IsDebugBreakSlot(info->rmode())) { 1471 Address current_pc = rinfo->pc();
1473 reloc += Assembler::kDebugBreakSlotLength; 1472 if (current_pc == pc) break;
1474 } else { 1473 DCHECK(current_pc < pc);
1475 DCHECK(RelocInfo::IsConstPool(info->rmode()));
1476 reloc += static_cast<int>(info->data());
1477 }
1478 } 1474 }
1479 1475 return index;
1480 int pc_offset = code_offset + reloc;
1481
1482 DCHECK_LT(code->instruction_start() + pc_offset, code->instruction_end());
1483
1484 return pc_offset;
1485 } 1476 }
1486 1477
1487 1478
1479 // Find the pc offset for the given continuation index.
1480 static int ComputePcOffsetFromContinuationIndex(Code* code, int index) {
1481 DCHECK_EQ(code->kind(), Code::FUNCTION);
1482 DCHECK(code->has_debug_break_slots());
1483 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
1484 RelocIterator it(code, mask);
1485 for (int i = 1; i < index; i++) it.next();
1486 return static_cast<int>(it.rinfo()->pc() - code->instruction_start());
1487 }
1488
1489
1488 static void RedirectActivationsToRecompiledCodeOnThread( 1490 static void RedirectActivationsToRecompiledCodeOnThread(
1489 Isolate* isolate, 1491 Isolate* isolate,
1490 ThreadLocalTop* top) { 1492 ThreadLocalTop* top) {
1491 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { 1493 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1492 JavaScriptFrame* frame = it.frame(); 1494 JavaScriptFrame* frame = it.frame();
1493 1495
1494 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue; 1496 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue;
1495 1497
1496 JSFunction* function = frame->function(); 1498 JSFunction* function = frame->function();
1497 1499
1498 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); 1500 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION);
1499 1501
1500 Handle<Code> frame_code(frame->LookupCode()); 1502 Handle<Code> frame_code(frame->LookupCode());
1501 if (frame_code->has_debug_break_slots()) continue; 1503 if (frame_code->has_debug_break_slots()) continue;
1502 1504
1503 Handle<Code> new_code(function->shared()->code()); 1505 Handle<Code> new_code(function->shared()->code());
1504 if (new_code->kind() != Code::FUNCTION || 1506 if (new_code->kind() != Code::FUNCTION ||
1505 !new_code->has_debug_break_slots()) { 1507 !new_code->has_debug_break_slots()) {
1506 continue; 1508 continue;
1507 } 1509 }
1508 1510
1509 int old_pc_offset = 1511 Address new_pc =
1510 static_cast<int>(frame->pc() - frame_code->instruction_start()); 1512 ComputeNewPcForRedirect(*new_code, *frame_code, frame->pc());
1511 int code_offset = ComputeCodeOffsetFromPcOffset(*frame_code, old_pc_offset);
1512 int new_pc_offset = ComputePcOffsetFromCodeOffset(*new_code, code_offset);
1513
1514 // Compute the equivalent pc in the new code.
1515 byte* new_pc = new_code->instruction_start() + new_pc_offset;
1516 1513
1517 if (FLAG_trace_deopt) { 1514 if (FLAG_trace_deopt) {
1518 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " 1515 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1519 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " 1516 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1520 "for debugging, " 1517 "for debugging, "
1521 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n", 1518 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
1522 reinterpret_cast<intptr_t>( 1519 reinterpret_cast<intptr_t>(
1523 frame_code->instruction_start()), 1520 frame_code->instruction_start()),
1524 reinterpret_cast<intptr_t>( 1521 reinterpret_cast<intptr_t>(
1525 frame_code->instruction_start()) + 1522 frame_code->instruction_start()) +
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1592 } 1589 }
1593 1590
1594 1591
1595 static void RecompileAndRelocateSuspendedGenerators( 1592 static void RecompileAndRelocateSuspendedGenerators(
1596 const List<Handle<JSGeneratorObject> > &generators) { 1593 const List<Handle<JSGeneratorObject> > &generators) {
1597 for (int i = 0; i < generators.length(); i++) { 1594 for (int i = 0; i < generators.length(); i++) {
1598 Handle<JSFunction> fun(generators[i]->function()); 1595 Handle<JSFunction> fun(generators[i]->function());
1599 1596
1600 EnsureFunctionHasDebugBreakSlots(fun); 1597 EnsureFunctionHasDebugBreakSlots(fun);
1601 1598
1602 int code_offset = generators[i]->continuation(); 1599 int index = generators[i]->continuation();
1603 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset); 1600 int pc_offset = ComputePcOffsetFromContinuationIndex(fun->code(), index);
1604 generators[i]->set_continuation(pc_offset); 1601 generators[i]->set_continuation(pc_offset);
1605 } 1602 }
1606 } 1603 }
1607 1604
1608 1605
1609 static bool SkipSharedFunctionInfo(SharedFunctionInfo* shared, 1606 static bool SkipSharedFunctionInfo(SharedFunctionInfo* shared,
1610 Object* active_code_marker) { 1607 Object* active_code_marker) {
1611 if (!shared->allows_lazy_compilation()) return true; 1608 if (!shared->allows_lazy_compilation()) return true;
1612 Object* script = shared->script(); 1609 Object* script = shared->script();
1613 if (!script->IsScript()) return true; 1610 if (!script->IsScript()) return true;
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1715 JSGeneratorObject* gen = JSGeneratorObject::cast(obj); 1712 JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
1716 if (!gen->is_suspended()) continue; 1713 if (!gen->is_suspended()) continue;
1717 1714
1718 JSFunction* fun = gen->function(); 1715 JSFunction* fun = gen->function();
1719 DCHECK_EQ(fun->code()->kind(), Code::FUNCTION); 1716 DCHECK_EQ(fun->code()->kind(), Code::FUNCTION);
1720 if (fun->code()->has_debug_break_slots()) continue; 1717 if (fun->code()->has_debug_break_slots()) continue;
1721 1718
1722 int pc_offset = gen->continuation(); 1719 int pc_offset = gen->continuation();
1723 DCHECK_LT(0, pc_offset); 1720 DCHECK_LT(0, pc_offset);
1724 1721
1725 int code_offset = 1722 int index =
1726 ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset); 1723 ComputeContinuationIndexFromPcOffset(fun->code(), pc_offset);
1727 1724
1728 // This will be fixed after we recompile the functions. 1725 // This will be fixed after we recompile the functions.
1729 gen->set_continuation(code_offset); 1726 gen->set_continuation(index);
1730 1727
1731 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_)); 1728 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_));
1732 } else if (obj->IsSharedFunctionInfo()) { 1729 } else if (obj->IsSharedFunctionInfo()) {
1733 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); 1730 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
1734 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue; 1731 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue;
1735 if (shared->is_generator()) continue; 1732 if (shared->is_generator()) continue;
1736 if (HasDebugBreakSlots(shared->code())) continue; 1733 if (HasDebugBreakSlots(shared->code())) continue;
1737 shared->ReplaceCode(*lazy_compile); 1734 shared->ReplaceCode(*lazy_compile);
1738 } 1735 }
1739 } 1736 }
(...skipping 1449 matching lines...) Expand 10 before | Expand all | Expand 10 after
3189 masm->RecordDebugBreakSlotForCall(call_argc); 3186 masm->RecordDebugBreakSlotForCall(call_argc);
3190 return; 3187 return;
3191 case DEBUG_BREAK_AT_CONSTRUCT_CALL: 3188 case DEBUG_BREAK_AT_CONSTRUCT_CALL:
3192 masm->RecordDebugBreakSlotForConstructCall(); 3189 masm->RecordDebugBreakSlotForConstructCall();
3193 return; 3190 return;
3194 } 3191 }
3195 } 3192 }
3196 3193
3197 } // namespace internal 3194 } // namespace internal
3198 } // namespace v8 3195 } // namespace v8
OLDNEW
« no previous file with comments | « src/assembler.cc ('k') | src/ia32/assembler-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698