Bug 857838 - Fix script-pc calculatins when iterating on baseline frames. r=jandem

This commit is contained in:
Kannan Vijayan 2013-04-22 12:06:46 -04:00
parent 6837e0d82f
commit d549443ef1
5 changed files with 113 additions and 7 deletions

View File

@ -1184,6 +1184,13 @@ ion::FinishBailoutToBaseline(BaselineBailoutInfo *bailoutInfo)
IonSpew(IonSpew_BaselineBailouts, " Done restoring frames");
// Check that we can get the current script's PC.
#ifdef DEBUG
jsbytecode *pc;
cx->stack.currentScript(&pc);
IonSpew(IonSpew_BaselineBailouts, " Got pc=%p", pc);
#endif
uint32_t numFrames = bailoutInfo->numFrames;
JS_ASSERT(numFrames > 0);
BailoutKind bailoutKind = bailoutInfo->bailoutKind;

View File

@ -388,8 +388,8 @@ BaselineScript::pcMappingReader(size_t indexEntry)
return CompactBufferReader(dataStart, dataEnd);
}
ICEntry &
BaselineScript::icEntryFromReturnOffset(CodeOffsetLabel returnOffset)
ICEntry *
BaselineScript::maybeICEntryFromReturnOffset(CodeOffsetLabel returnOffset)
{
size_t bottom = 0;
size_t top = numICEntries();
@ -402,8 +402,21 @@ BaselineScript::icEntryFromReturnOffset(CodeOffsetLabel returnOffset)
top = mid;
mid = (bottom + top) / 2;
}
JS_ASSERT(icEntry(mid).returnOffset().offset() == returnOffset.offset());
return icEntry(mid);
if (mid >= numICEntries())
return NULL;
if (icEntry(mid).returnOffset().offset() != returnOffset.offset())
return NULL;
return &icEntry(mid);
}
ICEntry &
BaselineScript::icEntryFromReturnOffset(CodeOffsetLabel returnOffset)
{
ICEntry *result = maybeICEntryFromReturnOffset(returnOffset);
JS_ASSERT(result);
return *result;
}
uint8_t *
@ -468,10 +481,20 @@ BaselineScript::icEntryFromPCOffset(uint32_t pcOffset, ICEntry *prevLookedUpEntr
return icEntryFromPCOffset(pcOffset);
}
ICEntry *
BaselineScript::maybeICEntryFromReturnAddress(uint8_t *returnAddr)
{
JS_ASSERT(returnAddr > method_->raw());
JS_ASSERT(returnAddr < method_->raw() + method_->instructionsSize());
CodeOffsetLabel offset(returnAddr - method_->raw());
return maybeICEntryFromReturnOffset(offset);
}
ICEntry &
BaselineScript::icEntryFromReturnAddress(uint8_t *returnAddr)
{
JS_ASSERT(returnAddr > method_->raw());
JS_ASSERT(returnAddr < method_->raw() + method_->instructionsSize());
CodeOffsetLabel offset(returnAddr - method_->raw());
return icEntryFromReturnOffset(offset);
}
@ -581,6 +604,60 @@ BaselineScript::nativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotI
return NULL;
}
jsbytecode *
BaselineScript::pcForReturnOffset(JSScript *script, uint32_t nativeOffset)
{
JS_ASSERT(script->baselineScript() == this);
JS_ASSERT(nativeOffset < method_->instructionsSize());
// Look for the first PCMappingIndexEntry with native offset > the native offset we are
// interested in.
uint32_t i = 1;
for (; i < numPCMappingIndexEntries(); i++) {
if (pcMappingIndexEntry(i).nativeOffset > nativeOffset)
break;
}
// Go back an entry to search forward from.
JS_ASSERT(i > 0);
i--;
PCMappingIndexEntry &entry = pcMappingIndexEntry(i);
JS_ASSERT(nativeOffset >= entry.nativeOffset);
CompactBufferReader reader(pcMappingReader(i));
jsbytecode *curPC = script->code + entry.pcOffset;
uint32_t curNativeOffset = entry.nativeOffset;
JS_ASSERT(curPC >= script->code);
JS_ASSERT(curNativeOffset <= nativeOffset);
while (true) {
// If the high bit is set, the native offset relative to the
// previous pc != 0 and comes next.
uint8_t b = reader.readByte();
if (b & 0x80)
curNativeOffset += reader.readUnsigned();
if (curNativeOffset == nativeOffset)
return curPC;
curPC += GetBytecodeLength(curPC);
}
JS_NOT_REACHED("Invalid pc");
return NULL;
}
jsbytecode *
BaselineScript::pcForReturnAddress(JSScript *script, uint8_t *nativeAddress)
{
JS_ASSERT(script->baselineScript() == this);
JS_ASSERT(nativeAddress >= method_->raw());
JS_ASSERT(nativeAddress < method_->raw() + method_->instructionsSize());
return pcForReturnOffset(script, uint32_t(nativeAddress - method_->raw()));
}
void
BaselineScript::toggleDebugTraps(RawScript script, jsbytecode *pc)
{

View File

@ -211,9 +211,11 @@ struct BaselineScript
}
ICEntry &icEntry(size_t index);
ICEntry *maybeICEntryFromReturnOffset(CodeOffsetLabel returnOffset);
ICEntry &icEntryFromReturnOffset(CodeOffsetLabel returnOffset);
ICEntry &icEntryFromPCOffset(uint32_t pcOffset);
ICEntry &icEntryFromPCOffset(uint32_t pcOffset, ICEntry *prevLookedUpEntry);
ICEntry *maybeICEntryFromReturnAddress(uint8_t *returnAddr);
ICEntry &icEntryFromReturnAddress(uint8_t *returnAddr);
uint8_t *returnAddressForIC(const ICEntry &ent);
@ -235,6 +237,8 @@ struct BaselineScript
void copyPCMappingEntries(const CompactBufferWriter &entries);
uint8_t *nativeCodeForPC(JSScript *script, jsbytecode *pc, PCMappingSlotInfo *slotInfo = NULL);
jsbytecode *pcForReturnOffset(JSScript *script, uint32_t nativeOffset);
jsbytecode *pcForReturnAddress(JSScript *script, uint8_t *nativeAddress);
// Toggle debug traps (used for breakpoints and step mode) in the script.
// If |pc| is NULL, toggle traps for all ops in the script. Else, only

View File

@ -193,8 +193,25 @@ IonFrameIterator::baselineScriptAndPc(JSScript **scriptRes, jsbytecode **pcRes)
if (scriptRes)
*scriptRes = script;
uint8_t *retAddr = returnAddressToFp();
if (pcRes)
*pcRes = script->baselineScript()->icEntryFromReturnAddress(retAddr).pc(script);
if (pcRes) {
// If the return address is into the prologue entry addr, then assume PC 0.
if (retAddr == script->baselineScript()->prologueEntryAddr()) {
*pcRes = 0;
return;
}
// The return address _may_ be a return from a callVM or IC chain call done for
// some op.
ICEntry *icEntry = script->baselineScript()->maybeICEntryFromReturnAddress(retAddr);
if (icEntry) {
*pcRes = icEntry->pc(script);
return;
}
// If not, the return address _must_ be the start address of an op, which can
// be computed from the pc mapping table.
*pcRes = script->baselineScript()->pcForReturnAddress(script, retAddr);
}
}
Value *

View File

@ -847,7 +847,8 @@ MacroAssembler::generateBailoutTail(Register scratch, Register bailoutInfo)
load32(Address(temp, BaselineFrame::reverseOffsetOfFrameSize()), temp);
makeFrameDescriptor(temp, IonFrame_BaselineJS);
push(temp);
push(Imm32(0)); // Fake return address.
loadPtr(Address(bailoutInfo, offsetof(BaselineBailoutInfo, resumeAddr)), temp);
push(temp);
enterFakeExitFrame();
// If monitorStub is non-null, handle resumeAddr appropriately.