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:
Ted Campbell 2018-10-22 18:33:54 +00:00
Родитель d4af807d62
Коммит cd0e8cd66d
20 изменённых файлов: 70 добавлений и 55 удалений

Просмотреть файл

@ -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(&note);
// 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;
}
}