зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1500822 - Make TryNote::start relative to JSScript::code() r=jorendorff
Currently it is relative to JSScript::main(), but it is the only part of the engine that uses this definition to describe a "pcOffset". This is unnecessarily confusing, and fixing it is easy. Differential Revision: https://phabricator.services.mozilla.com/D9358 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
d4af807d62
Коммит
cd0e8cd66d
|
@ -684,7 +684,9 @@ NonLocalExitControl::leaveScope(EmitterScope* es)
|
|||
}
|
||||
if (!bce_->scopeNoteList.append(enclosingScopeIndex, bce_->offset(), bce_->inPrologue(),
|
||||
openScopeNoteIndex_))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
openScopeNoteIndex_ = bce_->scopeNoteList.length() - 1;
|
||||
|
||||
return true;
|
||||
|
@ -2938,7 +2940,7 @@ BytecodeEmitter::wrapWithDestructuringIteratorCloseTryNote(int32_t iterDepth, In
|
|||
}
|
||||
ptrdiff_t end = offset();
|
||||
if (start != end) {
|
||||
return tryNoteList.append(JSTRY_DESTRUCTURING_ITERCLOSE, iterDepth, start, end);
|
||||
return addTryNote(JSTRY_DESTRUCTURING_ITERCLOSE, iterDepth, start, end);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -4862,8 +4864,8 @@ BytecodeEmitter::emitSpread(bool allowSelfHosted)
|
|||
MOZ_ASSERT(loopInfo.breaks.offset == -1);
|
||||
MOZ_ASSERT(loopInfo.continues.offset == -1);
|
||||
|
||||
if (!tryNoteList.append(JSTRY_FOR_OF, stackDepth, loopInfo.headOffset(),
|
||||
loopInfo.breakTargetOffset()))
|
||||
if (!addTryNote(JSTRY_FOR_OF, stackDepth, loopInfo.headOffset(),
|
||||
loopInfo.breakTargetOffset()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -8922,6 +8924,16 @@ AllocSrcNote(JSContext* cx, SrcNotesVector& notes, unsigned* index)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::addTryNote(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end)
|
||||
{
|
||||
// The tryNoteList stores offsets relative to current section should must
|
||||
// be main section. During tryNoteList.finish(), the prologueLength will be
|
||||
// added to correct offset.
|
||||
MOZ_ASSERT(!inPrologue());
|
||||
return tryNoteList.append(kind, stackDepth, start, end);
|
||||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::newSrcNote(SrcNoteType type, unsigned* indexp)
|
||||
{
|
||||
|
@ -9189,6 +9201,9 @@ CGTryNoteList::append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, siz
|
|||
MOZ_ASSERT(size_t(uint32_t(start)) == start);
|
||||
MOZ_ASSERT(size_t(uint32_t(end)) == end);
|
||||
|
||||
// Offsets are given relative to sections, but we only expect main-section
|
||||
// to have TryNotes. In finish() we will fixup base offset.
|
||||
|
||||
JSTryNote note;
|
||||
note.kind = kind;
|
||||
note.stackDepth = stackDepth;
|
||||
|
@ -9199,11 +9214,12 @@ CGTryNoteList::append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, siz
|
|||
}
|
||||
|
||||
void
|
||||
CGTryNoteList::finish(mozilla::Span<JSTryNote> array)
|
||||
CGTryNoteList::finish(mozilla::Span<JSTryNote> array, uint32_t prologueLength)
|
||||
{
|
||||
MOZ_ASSERT(length() == array.size());
|
||||
|
||||
for (unsigned i = 0; i < length(); i++) {
|
||||
list[i].start += prologueLength;
|
||||
array[i] = list[i];
|
||||
}
|
||||
}
|
||||
|
@ -9215,6 +9231,9 @@ CGScopeNoteList::append(uint32_t scopeIndex, uint32_t offset, bool inPrologue,
|
|||
CGScopeNote note;
|
||||
mozilla::PodZero(¬e);
|
||||
|
||||
// Offsets are given relative to sections. In finish() we will fixup base
|
||||
// offset if needed.
|
||||
|
||||
note.index = scopeIndex;
|
||||
note.start = offset;
|
||||
note.parent = parent;
|
||||
|
|
|
@ -66,9 +66,12 @@ struct CGTryNoteList {
|
|||
Vector<JSTryNote> list;
|
||||
explicit CGTryNoteList(JSContext* cx) : list(cx) {}
|
||||
|
||||
// Start/end offset are relative to main section and will be patch in
|
||||
// finish().
|
||||
|
||||
MOZ_MUST_USE bool append(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end);
|
||||
size_t length() const { return list.length(); }
|
||||
void finish(mozilla::Span<JSTryNote> array);
|
||||
void finish(mozilla::Span<JSTryNote> array, uint32_t prologueLength);
|
||||
};
|
||||
|
||||
struct CGScopeNote : public ScopeNote
|
||||
|
@ -432,6 +435,10 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
MOZ_MUST_USE bool checkStrictOrSloppy(JSOp op);
|
||||
#endif
|
||||
|
||||
// Add TryNote to the tryNoteList array. The start and end offset are
|
||||
// relative to current section.
|
||||
MOZ_MUST_USE bool addTryNote(JSTryNoteKind kind, uint32_t stackDepth, size_t start, size_t end);
|
||||
|
||||
// Append a new source note of the given type (and therefore size) to the
|
||||
// notes dynamic array, updating noteCount. Return the new note's index
|
||||
// within the array pointed at by current->notes as outparam.
|
||||
|
|
|
@ -232,8 +232,8 @@ CForEmitter::emitEnd()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!bce_->tryNoteList.append(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset()))
|
||||
if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -82,8 +82,8 @@ DoWhileEmitter::emitEnd()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!bce_->tryNoteList.append(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset()))
|
||||
if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -168,8 +168,8 @@ ForInEmitter::emitEnd(const Maybe<uint32_t>& forPos)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!bce_->tryNoteList.append(JSTRY_FOR_IN, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
bce_->offset()))
|
||||
if (!bce_->addTryNote(JSTRY_FOR_IN, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
bce_->offset()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -243,8 +243,8 @@ ForOfEmitter::emitEnd(const Maybe<uint32_t>& iteratedPos)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!bce_->tryNoteList.append(JSTRY_FOR_OF, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset()))
|
||||
if (!bce_->addTryNote(JSTRY_FOR_OF, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ ForOfLoopControl::emitIteratorCloseInScope(BytecodeEmitter* bce,
|
|||
return false;
|
||||
}
|
||||
ptrdiff_t end = bce->offset();
|
||||
return bce->tryNoteList.append(JSTRY_FOR_OF_ITERCLOSE, 0, start, end);
|
||||
return bce->addTryNote(JSTRY_FOR_OF_ITERCLOSE, 0, start, end);
|
||||
}
|
||||
|
||||
// Since we're in the middle of emitting code that will leave
|
||||
|
|
|
@ -283,7 +283,7 @@ TryEmitter::emitEnd()
|
|||
// Add the try note last, to let post-order give us the right ordering
|
||||
// (first to last for a given nesting level, inner to outer by level).
|
||||
if (hasCatch()) {
|
||||
if (!bce_->tryNoteList.append(JSTRY_CATCH, depth_, tryStart_, tryEnd_.offset)) {
|
||||
if (!bce_->addTryNote(JSTRY_CATCH, depth_, tryStart_, tryEnd_.offset)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +292,7 @@ TryEmitter::emitEnd()
|
|||
// trynote to catch exceptions (re)thrown from a catch block or
|
||||
// for the try{}finally{} case.
|
||||
if (hasFinally()) {
|
||||
if (!bce_->tryNoteList.append(JSTRY_FINALLY, depth_, tryStart_, finallyStart_.offset)) {
|
||||
if (!bce_->addTryNote(JSTRY_FINALLY, depth_, tryStart_, finallyStart_.offset)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -109,8 +109,8 @@ WhileEmitter::emitEnd()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!bce_->tryNoteList.append(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset()))
|
||||
if (!bce_->addTryNote(JSTRY_LOOP, bce_->stackDepth, loopInfo_->headOffset(),
|
||||
loopInfo_->breakTargetOffset()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -489,7 +489,7 @@ HasLiveStackValueAtDepth(JSScript* script, jsbytecode* pc, uint32_t stackDepth)
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t pcOffset = uint32_t(pc - script->main());
|
||||
uint32_t pcOffset = script->pcToOffset(pc);
|
||||
|
||||
for (const JSTryNote& tn : script->trynotes()) {
|
||||
if (pcOffset < tn.start) {
|
||||
|
|
|
@ -118,9 +118,8 @@ BytecodeAnalysis::init(TempAllocator& alloc, GSNCache& gsn)
|
|||
|
||||
case JSOP_TRY: {
|
||||
for (const JSTryNote& tn : script_->trynotes()) {
|
||||
unsigned startOffset = script_->mainOffset() + tn.start;
|
||||
if (startOffset == offset + 1) {
|
||||
unsigned catchOffset = startOffset + tn.length;
|
||||
if (tn.start == offset + 1) {
|
||||
unsigned catchOffset = tn.start + tn.length;
|
||||
|
||||
if (tn.kind != JSTRY_FOR_IN) {
|
||||
infos_[catchOffset].init(stackDepth);
|
||||
|
|
|
@ -234,7 +234,7 @@ HandleExceptionIon(JSContext* cx, const InlineFrameIterator& frame, ResumeFromEx
|
|||
}
|
||||
|
||||
MOZ_ASSERT_IF(tn->kind == JSTRY_FOR_IN,
|
||||
JSOp(*(script->main() + tn->start + tn->length)) == JSOP_ENDITER);
|
||||
JSOp(*(script->offsetToPC(tn->start + tn->length))) == JSOP_ENDITER);
|
||||
CloseLiveIteratorIon(cx, frame, tn);
|
||||
break;
|
||||
|
||||
|
@ -262,7 +262,7 @@ HandleExceptionIon(JSContext* cx, const InlineFrameIterator& frame, ResumeFromEx
|
|||
script->resetWarmUpCounter();
|
||||
|
||||
// Bailout at the start of the catch block.
|
||||
jsbytecode* catchPC = script->main() + tn->start + tn->length;
|
||||
jsbytecode* catchPC = script->offsetToPC(tn->start + tn->length);
|
||||
ExceptionBailoutInfo excInfo(frame.frameNo(), catchPC, tn->stackDepth);
|
||||
uint32_t retval = ExceptionHandlerBailout(cx, frame, rfe, excInfo, overrecursed);
|
||||
if (retval == BAILOUT_RETURN_OK) {
|
||||
|
@ -329,7 +329,7 @@ SettleOnTryNote(JSContext* cx, const JSTryNote* tn, const JSJitFrameIter& frame,
|
|||
BaselineFrameAndStackPointersFromTryNote(tn, frame, &rfe->framePointer, &rfe->stackPointer);
|
||||
|
||||
// Compute the pc.
|
||||
*pc = script->main() + tn->start + tn->length;
|
||||
*pc = script->offsetToPC(tn->start + tn->length);
|
||||
}
|
||||
|
||||
struct AutoBaselineHandlingException
|
||||
|
|
|
@ -3102,10 +3102,9 @@ TryNotes(JSContext* cx, HandleScript script, Sprinter* sp)
|
|||
}
|
||||
|
||||
for (const JSTryNote& tn : script->trynotes()) {
|
||||
uint32_t startOff = script->pcToOffset(script->main()) + tn.start;
|
||||
if (!sp->jsprintf(" %-16s %6u %8u %8u\n",
|
||||
TryNoteName(static_cast<JSTryNoteKind>(tn.kind)),
|
||||
tn.stackDepth, startOff, startOff + tn.length))
|
||||
tn.stackDepth, tn.start, tn.start + tn.length))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -947,9 +947,8 @@ BytecodeParser::parse()
|
|||
// exception but is not caught by a later handler in the same function:
|
||||
// no more code will execute, and it does not matter what is defined.
|
||||
for (const JSTryNote& tn : script_->trynotes()) {
|
||||
uint32_t startOffset = script_->mainOffset() + tn.start;
|
||||
if (startOffset == offset + 1) {
|
||||
uint32_t catchOffset = startOffset + tn.length;
|
||||
if (tn.start == offset + 1) {
|
||||
uint32_t catchOffset = tn.start + tn.length;
|
||||
if (tn.kind == JSTRY_CATCH) {
|
||||
if (!addJump(catchOffset, &nextOffset, stackDepth, offsetStack,
|
||||
pc, JumpKind::TryCatch))
|
||||
|
@ -1456,7 +1455,7 @@ Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
|
|||
if (op == JSOP_TRY) {
|
||||
size_t mainOffset = script->mainOffset();
|
||||
for (const JSTryNote& tn : script->trynotes()) {
|
||||
if (tn.kind == JSTRY_CATCH && tn.start + mainOffset == loc + 1) {
|
||||
if (tn.kind == JSTRY_CATCH && tn.start == loc + 1) {
|
||||
if (!sp->jsprintf(" %u (%+d)",
|
||||
unsigned(loc + tn.length + 1),
|
||||
int(tn.length + 1)))
|
||||
|
|
|
@ -6449,9 +6449,8 @@ class FlowGraphSummary {
|
|||
// because we only report offsets of entry points which have
|
||||
// valid incoming edges.
|
||||
for (const JSTryNote& tn : script->trynotes()) {
|
||||
uint32_t startOffset = script->mainOffset() + tn.start;
|
||||
if (startOffset == r.frontOffset() + 1) {
|
||||
uint32_t catchOffset = startOffset + tn.length;
|
||||
if (tn.start == r.frontOffset() + 1) {
|
||||
uint32_t catchOffset = tn.start + tn.length;
|
||||
if (tn.kind == JSTRY_CATCH || tn.kind == JSTRY_FINALLY) {
|
||||
addEdge(lineno, column, catchOffset);
|
||||
}
|
||||
|
@ -7467,14 +7466,10 @@ class DebuggerScriptIsInCatchScopeMatcher
|
|||
return false;
|
||||
}
|
||||
|
||||
// Try note ranges are relative to the mainOffset of the script, so adjust
|
||||
// offset accordingly.
|
||||
size_t offset = offset_ - script->mainOffset();
|
||||
|
||||
if (script->hasTrynotes()) {
|
||||
for (const JSTryNote& tn : script->trynotes()) {
|
||||
if (tn.start <= offset &&
|
||||
offset <= tn.start + tn.length &&
|
||||
if (tn.start <= offset_ &&
|
||||
offset_ <= tn.start + tn.length &&
|
||||
tn.kind == JSTRY_CATCH)
|
||||
{
|
||||
isInCatch_ = true;
|
||||
|
|
|
@ -1316,7 +1316,7 @@ js::UnwindAllEnvironmentsInFrame(JSContext* cx, EnvironmentIter& ei)
|
|||
jsbytecode*
|
||||
js::UnwindEnvironmentToTryPc(JSScript* script, const JSTryNote* tn)
|
||||
{
|
||||
jsbytecode* pc = script->main() + tn->start;
|
||||
jsbytecode* pc = script->offsetToPC(tn->start);
|
||||
if (tn->kind == JSTRY_CATCH || tn->kind == JSTRY_FINALLY) {
|
||||
pc -= JSOP_TRY_LENGTH;
|
||||
MOZ_ASSERT(*pc == JSOP_TRY);
|
||||
|
@ -1345,7 +1345,7 @@ SettleOnTryNote(JSContext* cx, const JSTryNote* tn, EnvironmentIter& ei, Interpr
|
|||
|
||||
// Set pc to the first bytecode after the the try note to point
|
||||
// to the beginning of catch or finally.
|
||||
regs.pc = regs.fp()->script()->main() + tn->start + tn->length;
|
||||
regs.pc = regs.fp()->script()->offsetToPC(tn->start + tn->length);
|
||||
regs.sp = regs.spForStackDepth(tn->stackDepth);
|
||||
}
|
||||
|
||||
|
@ -1468,7 +1468,7 @@ ProcessTryNotes(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs)
|
|||
}
|
||||
|
||||
/* This is similar to JSOP_ENDITER in the interpreter loop. */
|
||||
DebugOnly<jsbytecode*> pc = regs.fp()->script()->main() + tn->start + tn->length;
|
||||
DebugOnly<jsbytecode*> pc = regs.fp()->script()->offsetToPC(tn->start + tn->length);
|
||||
MOZ_ASSERT(JSOp(*pc) == JSOP_ENDITER);
|
||||
Value* sp = regs.spForStackDepth(tn->stackDepth);
|
||||
JSObject* obj = &sp[-1].toObject();
|
||||
|
|
|
@ -393,7 +393,7 @@ class MOZ_STACK_CLASS TryNoteIter
|
|||
TryNoteIter(JSContext* cx, JSScript* script, jsbytecode* pc,
|
||||
StackDepthOp getStackDepth)
|
||||
: script_(cx, script),
|
||||
pcOffset_(pc - script->main()),
|
||||
pcOffset_(script->pcToOffset(pc)),
|
||||
getStackDepth_(getStackDepth)
|
||||
{
|
||||
if (script->hasTrynotes()) {
|
||||
|
|
|
@ -3522,7 +3522,7 @@ JSScript::fullyInitFromEmitter(JSContext* cx, HandleScript script, frontend::Byt
|
|||
bce->scopeList.finish(script->scopes());
|
||||
}
|
||||
if (bce->tryNoteList.length() != 0) {
|
||||
bce->tryNoteList.finish(script->trynotes());
|
||||
bce->tryNoteList.finish(script->trynotes(), prologueLength);
|
||||
}
|
||||
if (bce->scopeNoteList.length() != 0) {
|
||||
bce->scopeNoteList.finish(script->scopeNotes(), prologueLength);
|
||||
|
@ -3608,7 +3608,7 @@ JSScript::assertValidJumpTargets() const
|
|||
// Check catch/finally blocks as jump targets.
|
||||
if (hasTrynotes()) {
|
||||
for (const JSTryNote& tn : trynotes()) {
|
||||
jsbytecode* tryStart = mainEntry + tn.start;
|
||||
jsbytecode* tryStart = offsetToPC(tn.start);
|
||||
jsbytecode* tryPc = tryStart - 1;
|
||||
if (tn.kind != JSTRY_CATCH && tn.kind != JSTRY_FINALLY) {
|
||||
continue;
|
||||
|
|
|
@ -109,8 +109,8 @@ enum JSTryNoteKind {
|
|||
struct JSTryNote {
|
||||
uint8_t kind; /* one of JSTryNoteKind */
|
||||
uint32_t stackDepth; /* stack depth upon exception handler entry */
|
||||
uint32_t start; /* start of the try statement or loop
|
||||
relative to script->main */
|
||||
uint32_t start; /* start of the try statement or loop relative
|
||||
to script->code() */
|
||||
uint32_t length; /* length of the try statement or loop */
|
||||
};
|
||||
|
||||
|
@ -139,8 +139,8 @@ struct ScopeNote {
|
|||
uint32_t index; // Index of Scope in the scopes array, or
|
||||
// NoScopeIndex if there is no block scope in
|
||||
// this range.
|
||||
uint32_t start; // Bytecode offset at which this scope starts,
|
||||
// from script->main().
|
||||
uint32_t start; // Bytecode offset at which this scope starts
|
||||
// relative to script->code().
|
||||
uint32_t length; // Bytecode length of scope.
|
||||
uint32_t parent; // Index of parent block scope in notes, or NoScopeNote.
|
||||
};
|
||||
|
|
|
@ -238,17 +238,14 @@ ObjectGroup::useSingletonForAllocationSite(JSScript* script, jsbytecode* pc, JSP
|
|||
return SingletonObject;
|
||||
}
|
||||
|
||||
unsigned offset = script->pcToOffset(pc);
|
||||
uint32_t offset = script->pcToOffset(pc);
|
||||
|
||||
for (const JSTryNote& tn : script->trynotes()) {
|
||||
if (tn.kind != JSTRY_FOR_IN && tn.kind != JSTRY_FOR_OF && tn.kind != JSTRY_LOOP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned startOffset = script->mainOffset() + tn.start;
|
||||
unsigned endOffset = startOffset + tn.length;
|
||||
|
||||
if (offset >= startOffset && offset < endOffset) {
|
||||
if (tn.start <= offset && offset < tn.start + tn.length) {
|
||||
return GenericObject;
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче