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

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