mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1001090 - Part 2b: Fix unwinding all scopes to not use pc. (r=jimb)
This commit is contained in:
parent
64bf587eff
commit
1cfa4cd614
@ -555,7 +555,7 @@ HandleExceptionBaseline(JSContext *cx, const JitFrameIterator &frame, ResumeFrom
|
||||
|
||||
// Unwind scope chain (pop block objects).
|
||||
if (cx->isExceptionPending()) {
|
||||
*unwoundScopeToPc = script->main() + tn->start;
|
||||
*unwoundScopeToPc = UnwindScopeToTryPc(script, tn);
|
||||
UnwindScope(cx, si, *unwoundScopeToPc);
|
||||
}
|
||||
|
||||
|
@ -809,8 +809,8 @@ DebugEpilogue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool ok)
|
||||
{
|
||||
// Unwind scope chain to stack depth 0.
|
||||
ScopeIter si(frame, pc, cx);
|
||||
UnwindAllScopes(cx, si);
|
||||
jsbytecode *unwindPc = frame->script()->main();
|
||||
UnwindScope(cx, si, unwindPc);
|
||||
frame->setUnwoundScopeOverridePc(unwindPc);
|
||||
|
||||
// If ScriptDebugEpilogue returns |true| we have to return the frame's
|
||||
|
@ -866,6 +866,25 @@ js::EnterWithOperation(JSContext *cx, AbstractFramePtr frame, HandleValue val,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
PopScope(JSContext *cx, ScopeIter &si)
|
||||
{
|
||||
switch (si.type()) {
|
||||
case ScopeIter::Block:
|
||||
if (cx->compartment()->debugMode())
|
||||
DebugScopes::onPopBlock(cx, si);
|
||||
if (si.staticBlock().needsClone())
|
||||
si.frame().popBlock(cx);
|
||||
break;
|
||||
case ScopeIter::With:
|
||||
si.frame().popWith(cx);
|
||||
break;
|
||||
case ScopeIter::Call:
|
||||
case ScopeIter::StrictEvalScope:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Unwind scope chain and iterator to match the static scope corresponding to
|
||||
// the given bytecode position.
|
||||
void
|
||||
@ -876,28 +895,42 @@ js::UnwindScope(JSContext *cx, ScopeIter &si, jsbytecode *pc)
|
||||
|
||||
Rooted<NestedScopeObject *> staticScope(cx, si.frame().script()->getStaticScope(pc));
|
||||
|
||||
for (; si.staticScope() != staticScope; ++si) {
|
||||
switch (si.type()) {
|
||||
case ScopeIter::Block:
|
||||
if (cx->compartment()->debugMode())
|
||||
DebugScopes::onPopBlock(cx, si);
|
||||
if (si.staticBlock().needsClone())
|
||||
si.frame().popBlock(cx);
|
||||
break;
|
||||
case ScopeIter::With:
|
||||
si.frame().popWith(cx);
|
||||
break;
|
||||
case ScopeIter::Call:
|
||||
case ScopeIter::StrictEvalScope:
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; si.staticScope() != staticScope; ++si)
|
||||
PopScope(cx, si);
|
||||
}
|
||||
|
||||
// Unwind all scopes. This is needed because block scopes may cover the
|
||||
// first bytecode at a script's main(). e.g.,
|
||||
//
|
||||
// function f() { { let i = 0; } }
|
||||
//
|
||||
// will have no pc location distinguishing the first block scope from the
|
||||
// outermost function scope.
|
||||
void
|
||||
js::UnwindAllScopes(JSContext *cx, ScopeIter &si)
|
||||
{
|
||||
for (; !si.done(); ++si)
|
||||
PopScope(cx, si);
|
||||
}
|
||||
|
||||
// Compute the pc needed to unwind the scope to the beginning of a try
|
||||
// block. We cannot unwind to *after* the JSOP_TRY, because that might be the
|
||||
// first opcode of an inner scope, with the same problem as above. e.g.,
|
||||
//
|
||||
// try { { let x; } }
|
||||
//
|
||||
// will have no pc location distinguishing the try block scope from the inner
|
||||
// let block scope.
|
||||
jsbytecode *
|
||||
js::UnwindScopeToTryPc(JSScript *script, JSTryNote *tn)
|
||||
{
|
||||
return script->main() + tn->start - js_CodeSpec[JSOP_TRY].length;
|
||||
}
|
||||
|
||||
static void
|
||||
ForcedReturn(JSContext *cx, ScopeIter &si, InterpreterRegs ®s)
|
||||
{
|
||||
UnwindScope(cx, si, regs.fp()->script()->main());
|
||||
UnwindAllScopes(cx, si);
|
||||
regs.setToEndOfScript();
|
||||
}
|
||||
|
||||
@ -1022,24 +1055,8 @@ HandleError(JSContext *cx, InterpreterRegs ®s)
|
||||
for (TryNoteIter tni(cx, regs); !tni.done(); ++tni) {
|
||||
JSTryNote *tn = *tni;
|
||||
|
||||
// Unwind the scope to the beginning of the JSOP_TRY. We cannot
|
||||
// unwind to *after* the JSOP_TRY, because that might be the first
|
||||
// opcode of an inner scope. Consider the following:
|
||||
//
|
||||
// try {
|
||||
// { let x; }
|
||||
// }
|
||||
//
|
||||
// This would generate
|
||||
//
|
||||
// 0000: try
|
||||
// 0001: undefined
|
||||
// 0002: initlet 0
|
||||
//
|
||||
// If we unwound to 0001, we would be unwinding to the inner
|
||||
// scope, and not the scope of the try { }.
|
||||
UnwindScope(cx, si, (regs.fp()->script()->main() + tn->start -
|
||||
js_CodeSpec[JSOP_TRY].length));
|
||||
// Unwind the scope to the beginning of the JSOP_TRY.
|
||||
UnwindScope(cx, si, UnwindScopeToTryPc(regs.fp()->script(), tn));
|
||||
|
||||
/*
|
||||
* Set pc to the first bytecode after the the try note to point
|
||||
|
@ -325,6 +325,15 @@ HasInstance(JSContext *cx, HandleObject obj, HandleValue v, bool *bp);
|
||||
extern void
|
||||
UnwindScope(JSContext *cx, ScopeIter &si, jsbytecode *pc);
|
||||
|
||||
// Unwind all scopes.
|
||||
extern void
|
||||
UnwindAllScopes(JSContext *cx, ScopeIter &si);
|
||||
|
||||
// Compute the pc needed to unwind the scope to the beginning of the block
|
||||
// pointed to by the try note.
|
||||
extern jsbytecode *
|
||||
UnwindScopeToTryPc(JSScript *script, JSTryNote *tn);
|
||||
|
||||
/*
|
||||
* Unwind for an uncatchable exception. This means not running finalizers, etc;
|
||||
* just preserving the basic engine stack invariants.
|
||||
|
Loading…
Reference in New Issue
Block a user