| Index: src/debug.cc
|
| diff --git a/src/debug.cc b/src/debug.cc
|
| index 1098f608c4c227cc752b36900892191581062a53..c8240e084fe85126357aeed1863a829337536eba 100644
|
| --- a/src/debug.cc
|
| +++ b/src/debug.cc
|
| @@ -1436,56 +1436,58 @@ static void CollectActiveFunctionsFromThread(
|
| }
|
|
|
|
|
| -// Figure out how many bytes of "pc_offset" correspond to actual code by
|
| -// subtracting off the bytes that correspond to constant/veneer pools. See
|
| -// Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this
|
| -// is only useful for architectures using constant pools or veneer pools.
|
| -static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) {
|
| +// Count the number of calls before the current frame PC to find the
|
| +// corresponding PC in the newly recompiled code.
|
| +static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code,
|
| + Address old_pc) {
|
| + DCHECK_EQ(old_code->kind(), Code::FUNCTION);
|
| + DCHECK_EQ(new_code->kind(), Code::FUNCTION);
|
| + DCHECK(!old_code->has_debug_break_slots());
|
| + DCHECK(new_code->has_debug_break_slots());
|
| + int mask = RelocInfo::kCodeTargetMask;
|
| + int index = 0;
|
| + intptr_t delta = 0;
|
| + for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
|
| + RelocInfo* rinfo = it.rinfo();
|
| + Address current_pc = rinfo->pc();
|
| + // The frame PC is behind the call instruction by the call instruction size.
|
| + if (current_pc > old_pc) break;
|
| + index++;
|
| + delta = old_pc - current_pc;
|
| + }
|
| +
|
| + RelocIterator it(new_code, mask);
|
| + for (int i = 1; i < index; i++) it.next();
|
| + return it.rinfo()->pc() + delta;
|
| +}
|
| +
|
| +
|
| +// Count the number of continuations at which the current pc offset is at.
|
| +static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) {
|
| DCHECK_EQ(code->kind(), Code::FUNCTION);
|
| DCHECK(!code->has_debug_break_slots());
|
| - DCHECK_LE(0, pc_offset);
|
| - DCHECK_LT(pc_offset, code->instruction_end() - code->instruction_start());
|
| -
|
| - int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
|
| - RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
|
| - byte *pc = code->instruction_start() + pc_offset;
|
| - int code_offset = pc_offset;
|
| + Address pc = code->instruction_start() + pc_offset;
|
| + int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
|
| + int index = 0;
|
| for (RelocIterator it(code, mask); !it.done(); it.next()) {
|
| - RelocInfo* info = it.rinfo();
|
| - if (info->pc() >= pc) break;
|
| - DCHECK(RelocInfo::IsConstPool(info->rmode()));
|
| - code_offset -= static_cast<int>(info->data());
|
| - DCHECK_LE(0, code_offset);
|
| + index++;
|
| + RelocInfo* rinfo = it.rinfo();
|
| + Address current_pc = rinfo->pc();
|
| + if (current_pc == pc) break;
|
| + DCHECK(current_pc < pc);
|
| }
|
| -
|
| - return code_offset;
|
| + return index;
|
| }
|
|
|
|
|
| -// The inverse of ComputeCodeOffsetFromPcOffset.
|
| -static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) {
|
| +// Find the pc offset for the given continuation index.
|
| +static int ComputePcOffsetFromContinuationIndex(Code* code, int index) {
|
| DCHECK_EQ(code->kind(), Code::FUNCTION);
|
| -
|
| - int mask = RelocInfo::kDebugBreakSlotMask |
|
| - RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
|
| - RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
|
| - int reloc = 0;
|
| - for (RelocIterator it(code, mask); !it.done(); it.next()) {
|
| - RelocInfo* info = it.rinfo();
|
| - if (info->pc() - code->instruction_start() - reloc >= code_offset) break;
|
| - if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
|
| - reloc += Assembler::kDebugBreakSlotLength;
|
| - } else {
|
| - DCHECK(RelocInfo::IsConstPool(info->rmode()));
|
| - reloc += static_cast<int>(info->data());
|
| - }
|
| - }
|
| -
|
| - int pc_offset = code_offset + reloc;
|
| -
|
| - DCHECK_LT(code->instruction_start() + pc_offset, code->instruction_end());
|
| -
|
| - return pc_offset;
|
| + DCHECK(code->has_debug_break_slots());
|
| + int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
|
| + RelocIterator it(code, mask);
|
| + for (int i = 1; i < index; i++) it.next();
|
| + return static_cast<int>(it.rinfo()->pc() - code->instruction_start());
|
| }
|
|
|
|
|
| @@ -1510,13 +1512,8 @@ static void RedirectActivationsToRecompiledCodeOnThread(
|
| continue;
|
| }
|
|
|
| - int old_pc_offset =
|
| - static_cast<int>(frame->pc() - frame_code->instruction_start());
|
| - int code_offset = ComputeCodeOffsetFromPcOffset(*frame_code, old_pc_offset);
|
| - int new_pc_offset = ComputePcOffsetFromCodeOffset(*new_code, code_offset);
|
| -
|
| - // Compute the equivalent pc in the new code.
|
| - byte* new_pc = new_code->instruction_start() + new_pc_offset;
|
| + Address new_pc =
|
| + ComputeNewPcForRedirect(*new_code, *frame_code, frame->pc());
|
|
|
| if (FLAG_trace_deopt) {
|
| PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
|
| @@ -1603,8 +1600,8 @@ static void RecompileAndRelocateSuspendedGenerators(
|
|
|
| EnsureFunctionHasDebugBreakSlots(fun);
|
|
|
| - int code_offset = generators[i]->continuation();
|
| - int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset);
|
| + int index = generators[i]->continuation();
|
| + int pc_offset = ComputePcOffsetFromContinuationIndex(fun->code(), index);
|
| generators[i]->set_continuation(pc_offset);
|
| }
|
| }
|
| @@ -1726,11 +1723,11 @@ void Debug::PrepareForBreakPoints() {
|
| int pc_offset = gen->continuation();
|
| DCHECK_LT(0, pc_offset);
|
|
|
| - int code_offset =
|
| - ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset);
|
| + int index =
|
| + ComputeContinuationIndexFromPcOffset(fun->code(), pc_offset);
|
|
|
| // This will be fixed after we recompile the functions.
|
| - gen->set_continuation(code_offset);
|
| + gen->set_continuation(index);
|
|
|
| suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_));
|
| } else if (obj->IsSharedFunctionInfo()) {
|
|
|