mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 659577 - emit ScopeCoordinate::hops (r=waldo)
--HG-- extra : rebase_source : 3698a6411ffcae90bbcfaa7a965d8de648b3e509
This commit is contained in:
parent
2dbf26f6da
commit
915b92d180
@ -833,43 +833,85 @@ EmitUnaliasedVarOp(JSContext *cx, JSOp op, uint16_t slot, BytecodeEmitter *bce)
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitAliasedVarOp(JSContext *cx, JSOp op, uint16_t binding, JSAtom *atom, BytecodeEmitter *bce)
|
||||
EmitAliasedVarOp(JSContext *cx, JSOp op, ScopeCoordinate sc, JSAtom *atom, BytecodeEmitter *bce)
|
||||
{
|
||||
JS_ASSERT(JOF_OPTYPE(op) == JOF_SCOPECOORD);
|
||||
|
||||
/*
|
||||
* XXX This is temporary: bug 659577 will need to compute the number of
|
||||
* cloned block objects to hop over.
|
||||
*/
|
||||
uint16_t hops = 0;
|
||||
|
||||
jsatomid atomIndex;
|
||||
if (!bce->makeAtomIndex(atom, &atomIndex))
|
||||
return false;
|
||||
|
||||
bool decomposed = js_CodeSpec[op].format & JOF_DECOMPOSE;
|
||||
unsigned n = 2 * sizeof(uint16_t) + sizeof(uint32_t) + (decomposed ? 1 : 0);
|
||||
unsigned n = 2 * sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint16_t) + (decomposed ? 1 : 0);
|
||||
JS_ASSERT(int(n) + 1 /* op */ == js_CodeSpec[op].length);
|
||||
|
||||
ptrdiff_t off = EmitN(cx, bce, op, n);
|
||||
if (off < 0)
|
||||
return false;
|
||||
|
||||
jsbytecode *pc = bce->code(off);
|
||||
SET_UINT16(pc, hops);
|
||||
SET_UINT16(pc, sc.hops);
|
||||
pc += sizeof(uint16_t);
|
||||
SET_UINT16(pc, binding);
|
||||
SET_UINT16(pc, sc.binding);
|
||||
pc += sizeof(uint16_t);
|
||||
SET_UINT32_INDEX(pc, atomIndex);
|
||||
pc += sizeof(uint32_t);
|
||||
SET_UINT16(pc, sc.frameBinding);
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned
|
||||
ClonedBlockDepth(BytecodeEmitter *bce)
|
||||
{
|
||||
unsigned clonedBlockDepth = 0;
|
||||
for (StaticBlockObject *b = bce->sc->blockChain; b; b = b->enclosingBlock()) {
|
||||
if (b->needsClone())
|
||||
++clonedBlockDepth;
|
||||
}
|
||||
|
||||
return clonedBlockDepth;
|
||||
}
|
||||
|
||||
static bool
|
||||
EmitAliasedVarOp(JSContext *cx, JSOp op, ParseNode *pn, BytecodeEmitter *bce)
|
||||
{
|
||||
uint16_t binding = JOF_OPTYPE(pn->getOp()) == JOF_QARG
|
||||
? bce->sc->bindings.argToBinding(pn->pn_cookie.slot())
|
||||
: bce->sc->bindings.localToBinding(pn->pn_cookie.slot());
|
||||
return EmitAliasedVarOp(cx, op, binding, pn->atom(), bce);
|
||||
/*
|
||||
* The contents of the dynamic scope chain (fp->scopeChain) exactly reflect
|
||||
* the needsClone-subset of the block chain. Use this to determine the
|
||||
* number of ClonedBlockObjects on fp->scopeChain to skip to find the scope
|
||||
* object containing the var to which pn is bound. ALIASEDVAR ops cannot
|
||||
* reach across with scopes so ClonedBlockObjects is the only NestedScope
|
||||
* on the scope chain.
|
||||
*/
|
||||
ScopeCoordinate sc;
|
||||
if (JOF_OPTYPE(pn->getOp()) == JOF_QARG) {
|
||||
JS_ASSERT(bce->sc->funIsHeavyweight());
|
||||
sc.hops = ClonedBlockDepth(bce);
|
||||
sc.binding = bce->sc->bindings.argToBinding(pn->pn_cookie.slot());
|
||||
sc.frameBinding = sc.binding;
|
||||
} else {
|
||||
JS_ASSERT(JOF_OPTYPE(pn->getOp()) == JOF_LOCAL || pn->isKind(PNK_FUNCTION));
|
||||
unsigned local = pn->pn_cookie.slot();
|
||||
sc.frameBinding = bce->sc->bindings.localToBinding(local);
|
||||
if (local < bce->sc->bindings.numVars()) {
|
||||
JS_ASSERT(bce->sc->funIsHeavyweight());
|
||||
sc.hops = ClonedBlockDepth(bce);
|
||||
sc.binding = sc.frameBinding;
|
||||
} else {
|
||||
unsigned depth = local - bce->sc->bindings.numVars();
|
||||
unsigned hops = 0;
|
||||
StaticBlockObject *b = bce->sc->blockChain;
|
||||
while (!b->containsVarAtDepth(depth)) {
|
||||
if (b->needsClone())
|
||||
hops++;
|
||||
b = b->enclosingBlock();
|
||||
}
|
||||
sc.hops = hops;
|
||||
sc.binding = depth - b->stackDepth();
|
||||
}
|
||||
}
|
||||
|
||||
return EmitAliasedVarOp(cx, op, sc, pn->atom(), bce);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1031,11 +1073,9 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
|
||||
Definition *dn = blockObj->maybeDefinitionParseNode(i);
|
||||
|
||||
/* Beware the empty destructuring dummy. */
|
||||
if (!dn) {
|
||||
JS_ASSERT(i + 1 <= blockObj->slotCount());
|
||||
if (!dn)
|
||||
blockObj->setAliased(i, bce->sc->bindingsAccessedDynamically());
|
||||
continue;
|
||||
}
|
||||
|
||||
JS_ASSERT(dn->isDefn());
|
||||
JS_ASSERT(unsigned(dn->frameSlot() + depthPlusFixed) < JS_BIT(16));
|
||||
@ -2591,9 +2631,12 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
|
||||
if (Emit1(cx, bce, JSOP_ARGUMENTS) < 0)
|
||||
return false;
|
||||
if (bce->sc->bindingsAccessedDynamically()) {
|
||||
ScopeCoordinate sc;
|
||||
sc.hops = 0;
|
||||
sc.binding = bce->sc->bindings.localToBinding(bce->sc->argumentsLocalSlot());
|
||||
sc.frameBinding = sc.binding;
|
||||
JSAtom *atom = cx->runtime->atomState.argumentsAtom;
|
||||
uint16_t binding = bce->sc->bindings.localToBinding(bce->sc->argumentsLocalSlot());
|
||||
if (!EmitAliasedVarOp(cx, JSOP_SETALIASEDVAR, binding, atom, bce))
|
||||
if (!EmitAliasedVarOp(cx, JSOP_SETALIASEDVAR, sc, atom, bce))
|
||||
return false;
|
||||
} else {
|
||||
if (!EmitUnaliasedVarOp(cx, JSOP_SETLOCAL, bce->sc->argumentsLocalSlot(), bce))
|
||||
|
@ -3,7 +3,7 @@ setDebug(true);
|
||||
x = "notset";
|
||||
function main() {
|
||||
/* The JSOP_STOP in main. */
|
||||
a = { valueOf: function () { trap(main, 95, "success()"); } };
|
||||
a = { valueOf: function () { trap(main, 97, "success()"); } };
|
||||
b = "";
|
||||
eval();
|
||||
a + b;
|
||||
|
@ -320,13 +320,19 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
|
||||
|
||||
case JSOP_GETALIASEDVAR:
|
||||
case JSOP_CALLALIASEDVAR:
|
||||
case JSOP_SETALIASEDVAR:
|
||||
case JSOP_SETALIASEDVAR: {
|
||||
JS_ASSERT(!isInlineable);
|
||||
usesScopeChain_ = true;
|
||||
|
||||
/* XXX: this can be removed after bug 659577. */
|
||||
if (ScopeCoordinate(pc).binding >= script->nfixed)
|
||||
ScopeCoordinate sc(pc);
|
||||
if (script->bindings.bindingIsLocal(sc.frameBinding) &&
|
||||
script->bindings.bindingToLocal(sc.frameBinding) >= script->nfixed)
|
||||
{
|
||||
localsAliasStack_ = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case JSOP_DEFFUN:
|
||||
case JSOP_DEFVAR:
|
||||
|
@ -364,9 +364,9 @@ static inline uint32_t GetBytecodeSlot(JSScript *script, jsbytecode *pc)
|
||||
case JSOP_SETALIASEDVAR:
|
||||
{
|
||||
ScopeCoordinate sc = ScopeCoordinate(pc);
|
||||
return script->bindings.bindingIsArg(sc.binding)
|
||||
? ArgSlot(script->bindings.bindingToArg(sc.binding))
|
||||
: LocalSlot(script, script->bindings.bindingToLocal(sc.binding));
|
||||
return script->bindings.bindingIsArg(sc.frameBinding)
|
||||
? ArgSlot(script->bindings.bindingToArg(sc.frameBinding))
|
||||
: LocalSlot(script, script->bindings.bindingToLocal(sc.frameBinding));
|
||||
}
|
||||
|
||||
|
||||
|
@ -880,26 +880,6 @@ CheckArgAccess(StackFrame *fp, unsigned index)
|
||||
fp->script()->argsObjAliasesFormals());
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is temporary. Bug 659577 will change all ALIASEDVAR
|
||||
* access to use the scope chain instead.
|
||||
*/
|
||||
static inline Value &
|
||||
AliasedVar(StackFrame *fp, ScopeCoordinate sc)
|
||||
{
|
||||
JSScript *script = fp->script();
|
||||
#ifdef DEBUG
|
||||
JS_ASSERT(sc.hops == 0); /* Temporary */
|
||||
if (script->bindings.bindingIsArg(sc.binding))
|
||||
JS_ASSERT(script->formalLivesInCallObject(script->bindings.bindingToArg(sc.binding)));
|
||||
else
|
||||
CheckLocalAccess(fp, script->bindings.bindingToLocal(sc.binding), true);
|
||||
#endif
|
||||
return script->bindings.bindingIsArg(sc.binding)
|
||||
? fp->formalArg(script->bindings.bindingToArg(sc.binding))
|
||||
: fp->localSlot(script->bindings.bindingToLocal(sc.binding));
|
||||
}
|
||||
|
||||
#define PUSH_COPY(v) do { *regs.sp++ = v; assertSameCompartment(cx, regs.sp[-1]); } while (0)
|
||||
#define PUSH_COPY_SKIP_CHECK(v) *regs.sp++ = v
|
||||
#define PUSH_NULL() regs.sp++->setNull()
|
||||
@ -1178,6 +1158,8 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode)
|
||||
# define END_CASE_LEN8 len = 8; goto advance_pc;
|
||||
# define END_CASE_LEN9 len = 9; goto advance_pc;
|
||||
# define END_CASE_LEN10 len = 10; goto advance_pc;
|
||||
# define END_CASE_LEN11 len = 11; goto advance_pc;
|
||||
# define END_CASE_LEN12 len = 12; goto advance_pc;
|
||||
# define END_VARLEN_CASE goto advance_pc;
|
||||
# define ADD_EMPTY_CASE(OP) BEGIN_CASE(OP)
|
||||
# define END_EMPTY_CASES goto advance_pc_by_one;
|
||||
@ -2846,16 +2828,14 @@ BEGIN_CASE(JSOP_CALLALIASEDVAR)
|
||||
BEGIN_CASE(JSOP_GETALIASEDVAR)
|
||||
{
|
||||
ScopeCoordinate sc = ScopeCoordinate(regs.pc);
|
||||
Value &var = AliasedVar(regs.fp(), sc);
|
||||
PUSH_COPY(var);
|
||||
PUSH_COPY(regs.fp()->aliasedVarScope(sc).aliasedVar(sc));
|
||||
}
|
||||
END_CASE(JSOP_GETALIASEDVAR)
|
||||
|
||||
BEGIN_CASE(JSOP_SETALIASEDVAR)
|
||||
{
|
||||
ScopeCoordinate sc = ScopeCoordinate(regs.pc);
|
||||
Value &var = AliasedVar(regs.fp(), sc);
|
||||
var = regs.sp[-1];
|
||||
regs.fp()->aliasedVarScope(sc).setAliasedVar(sc, regs.sp[-1]);
|
||||
}
|
||||
END_CASE(JSOP_SETALIASEDVAR)
|
||||
|
||||
|
@ -333,14 +333,18 @@ OPDEF(JSOP_FINALLY, 135,"finally", NULL, 1, 0, 2, 0, JOF_BYTE)
|
||||
* function, function statements that are conditionally executed, 'eval',
|
||||
* 'with', 'arguments' and E4X filters. All of these cases require creating a
|
||||
* CallObject to own the aliased variable.
|
||||
*
|
||||
* XXX: there is also a temporary 2-byte index (indicating the frame slot
|
||||
* aliased by the scope chain) which will be removed with the last patch of bug
|
||||
* 659577.
|
||||
*/
|
||||
OPDEF(JSOP_GETALIASEDVAR, 136,"getaliasedvar",NULL, 9, 0, 1, 19, JOF_SCOPECOORD|JOF_NAME)
|
||||
OPDEF(JSOP_CALLALIASEDVAR,137,"callaliasedvar",NULL, 9, 0, 1, 19, JOF_SCOPECOORD|JOF_NAME)
|
||||
OPDEF(JSOP_SETALIASEDVAR, 138,"setaliasedvar",NULL, 9, 1, 1, 3, JOF_SCOPECOORD|JOF_NAME|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_INCALIASEDVAR, 139,"incaliasedvar",NULL, 10, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_INC|JOF_TMPSLOT3|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_DECALIASEDVAR, 140,"decaliasedvar",NULL, 10, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_DEC|JOF_TMPSLOT3|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_ALIASEDVARINC, 141,"aliasedvarinc",NULL, 10, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_ALIASEDVARDEC, 142,"aliasedvardec",NULL, 10, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_GETALIASEDVAR, 136,"getaliasedvar",NULL, 11, 0, 1, 19, JOF_SCOPECOORD|JOF_NAME)
|
||||
OPDEF(JSOP_CALLALIASEDVAR,137,"callaliasedvar",NULL, 11, 0, 1, 19, JOF_SCOPECOORD|JOF_NAME)
|
||||
OPDEF(JSOP_SETALIASEDVAR, 138,"setaliasedvar",NULL, 11, 1, 1, 3, JOF_SCOPECOORD|JOF_NAME|JOF_SET|JOF_DETECTING)
|
||||
OPDEF(JSOP_INCALIASEDVAR, 139,"incaliasedvar",NULL, 12, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_INC|JOF_TMPSLOT3|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_DECALIASEDVAR, 140,"decaliasedvar",NULL, 12, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_DEC|JOF_TMPSLOT3|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_ALIASEDVARINC, 141,"aliasedvarinc",NULL, 12, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_INC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
|
||||
OPDEF(JSOP_ALIASEDVARDEC, 142,"aliasedvardec",NULL, 12, 0, 1, 15, JOF_SCOPECOORD|JOF_NAME|JOF_DEC|JOF_POST|JOF_TMPSLOT3|JOF_DECOMPOSE)
|
||||
|
||||
/* Unused. */
|
||||
OPDEF(JSOP_UNUSED8, 143,"unused8", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
@ -2816,10 +2816,10 @@ mjit::Compiler::generateMethod()
|
||||
frame.push(ObjectValue(*singleton));
|
||||
} else {
|
||||
ScopeCoordinate sc = ScopeCoordinate(PC);
|
||||
if (script->bindings.bindingIsArg(sc.binding))
|
||||
frame.pushArg(script->bindings.bindingToArg(sc.binding));
|
||||
if (script->bindings.bindingIsArg(sc.frameBinding))
|
||||
frame.pushArg(script->bindings.bindingToArg(sc.frameBinding));
|
||||
else
|
||||
frame.pushLocal(script->bindings.bindingToLocal(sc.binding));
|
||||
frame.pushLocal(script->bindings.bindingToLocal(sc.frameBinding));
|
||||
}
|
||||
}
|
||||
END_CASE(JSOP_GETALIASEDVAR)
|
||||
@ -2850,10 +2850,10 @@ mjit::Compiler::generateMethod()
|
||||
jsbytecode *next = &PC[JSOP_SETALIASEDVAR_LENGTH];
|
||||
bool pop = JSOp(*next) == JSOP_POP && !analysis->jumpTarget(next);
|
||||
ScopeCoordinate sc = ScopeCoordinate(PC);
|
||||
if (script->bindings.bindingIsArg(sc.binding))
|
||||
frame.storeArg(script->bindings.bindingToArg(sc.binding), pop);
|
||||
if (script->bindings.bindingIsArg(sc.frameBinding))
|
||||
frame.storeArg(script->bindings.bindingToArg(sc.frameBinding), pop);
|
||||
else
|
||||
frame.storeLocal(script->bindings.bindingToLocal(sc.binding), pop);
|
||||
frame.storeLocal(script->bindings.bindingToLocal(sc.frameBinding), pop);
|
||||
updateVarType();
|
||||
|
||||
if (pop) {
|
||||
|
@ -14,7 +14,8 @@ namespace js {
|
||||
|
||||
inline
|
||||
ScopeCoordinate::ScopeCoordinate(jsbytecode *pc)
|
||||
: hops(GET_UINT16(pc)), binding(GET_UINT16(pc + 2))
|
||||
: hops(GET_UINT16(pc)), binding(GET_UINT16(pc + 2)),
|
||||
frameBinding(GET_UINT16(pc + 8))
|
||||
{
|
||||
JS_ASSERT(JOF_OPTYPE(*pc) == JOF_SCOPECOORD);
|
||||
}
|
||||
@ -55,6 +56,58 @@ ScopeObject::setStackFrame(StackFrame *frame)
|
||||
return setPrivate(frame);
|
||||
}
|
||||
|
||||
inline const Value &
|
||||
ScopeObject::aliasedVar(ScopeCoordinate sc)
|
||||
{
|
||||
/* XXX: all this is temporary until the last patch of 659577 */
|
||||
StackFrame *fp = maybeStackFrame();
|
||||
Bindings &bindings = fp->script()->bindings;
|
||||
if (isCall()) {
|
||||
JS_ASSERT(sc.binding == sc.frameBinding);
|
||||
if (bindings.bindingIsArg(sc.binding)) {
|
||||
unsigned arg = bindings.bindingToArg(sc.binding);
|
||||
JS_ASSERT(fp->script()->formalLivesInCallObject(arg));
|
||||
return fp->formalArg(arg);
|
||||
}
|
||||
|
||||
unsigned var = bindings.bindingToLocal(sc.binding);
|
||||
JS_ASSERT(fp->script()->varIsAliased(var));
|
||||
return fp->localSlot(var);
|
||||
}
|
||||
|
||||
unsigned var = bindings.bindingToLocal(sc.frameBinding);
|
||||
fp = js_LiveFrameIfGenerator(fp);
|
||||
JS_ASSERT(var == sc.binding + asClonedBlock().staticBlock().stackDepth() + fp->numFixed());
|
||||
JS_ASSERT(asClonedBlock().staticBlock().isAliased(sc.binding));
|
||||
return fp->localSlot(var);
|
||||
}
|
||||
|
||||
inline void
|
||||
ScopeObject::setAliasedVar(ScopeCoordinate sc, const Value &v)
|
||||
{
|
||||
/* XXX: all this is temporary until the last patch of 659577 */
|
||||
StackFrame *fp = maybeStackFrame();
|
||||
Bindings &bindings = fp->script()->bindings;
|
||||
if (isCall()) {
|
||||
JS_ASSERT(sc.binding == sc.frameBinding);
|
||||
if (bindings.bindingIsArg(sc.binding)) {
|
||||
unsigned arg = bindings.bindingToArg(sc.binding);
|
||||
JS_ASSERT(fp->script()->formalLivesInCallObject(arg));
|
||||
fp->formalArg(arg) = v;
|
||||
} else {
|
||||
unsigned var = bindings.bindingToLocal(sc.binding);
|
||||
JS_ASSERT(fp->script()->varIsAliased(var));
|
||||
fp->localSlot(var) = v;
|
||||
}
|
||||
} else {
|
||||
unsigned var = bindings.bindingToLocal(sc.frameBinding);
|
||||
fp = js_LiveFrameIfGenerator(fp);
|
||||
JS_ASSERT(var == sc.binding + asClonedBlock().staticBlock().stackDepth() + fp->numFixed());
|
||||
JS_ASSERT(asClonedBlock().staticBlock().isAliased(sc.binding));
|
||||
fp->localSlot(var) = v;
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ inline size_t
|
||||
ScopeObject::offsetOfEnclosingScope()
|
||||
{
|
||||
|
@ -9,6 +9,7 @@
|
||||
#define ScopeObject_h___
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsiter.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsweakmap.h"
|
||||
|
||||
@ -21,20 +22,17 @@ namespace js {
|
||||
* given lexically-enclosing variable. A scope coordinate has two dimensions:
|
||||
* - hops: the number of scope objects on the scope chain to skip
|
||||
* - binding: which binding on the scope object
|
||||
*
|
||||
* XXX: Until bug 659577 lands, this is all for show and all ScopeCoordinates
|
||||
* have hops fixed at 0 and 'binding' is just the js::Bindings binding for args
|
||||
* and vars and the stack depth for let bindings. Thus, aliased-var access
|
||||
* touches the StackFrame like it always did and 'binding' must be first
|
||||
* converted to either an arg or local slot (using Bindings::bindingToLocal or
|
||||
* bindingToArg). With bug 659577, ScopeObject will have a 'var' function that
|
||||
* takes a ScopeCoordinate.
|
||||
*/
|
||||
struct ScopeCoordinate
|
||||
{
|
||||
uint16_t hops;
|
||||
uint16_t binding;
|
||||
|
||||
/* XXX this will be removed with the last patch of bug 659577. */
|
||||
uint16_t frameBinding;
|
||||
|
||||
inline ScopeCoordinate(jsbytecode *pc);
|
||||
inline ScopeCoordinate() {}
|
||||
};
|
||||
|
||||
inline JSAtom *
|
||||
@ -97,6 +95,15 @@ class ScopeObject : public JSObject
|
||||
inline JSObject &enclosingScope() const;
|
||||
inline bool setEnclosingScope(JSContext *cx, HandleObject obj);
|
||||
|
||||
/*
|
||||
* Get or set an aliased variable contained in this scope. Unaliased
|
||||
* variables should instead access the StackFrame. Aliased variable access
|
||||
* is primarily made through JOF_SCOPECOORD ops which is why these members
|
||||
* take a ScopeCoordinate instead of just the slot index.
|
||||
*/
|
||||
inline const Value &aliasedVar(ScopeCoordinate sc);
|
||||
inline void setAliasedVar(ScopeCoordinate sc, const Value &v);
|
||||
|
||||
/*
|
||||
* The stack frame for this scope object, if the frame is still active.
|
||||
* Note: these members may not be called for a StaticBlockObject or
|
||||
|
@ -286,6 +286,28 @@ StackFrame::actualArgsEnd() const
|
||||
return formalArgs() + numActualArgs();
|
||||
}
|
||||
|
||||
inline ScopeObject &
|
||||
StackFrame::aliasedVarScope(ScopeCoordinate sc) const
|
||||
{
|
||||
JSObject *scope = &scopeChain()->asScope();
|
||||
for (unsigned i = sc.hops; i; i--)
|
||||
scope = &scope->asScope().enclosingScope();
|
||||
|
||||
#ifdef DEBUG
|
||||
if (scope->isCall()) {
|
||||
JS_ASSERT(scope->asCall() == callObj());
|
||||
JS_ASSERT(scope->asCall().maybeStackFrame() == this);
|
||||
} else {
|
||||
StaticBlockObject &target = scope->asClonedBlock().staticBlock();
|
||||
StaticBlockObject *b = &blockChain();
|
||||
while (b != &target)
|
||||
b = b->enclosingBlock();
|
||||
}
|
||||
#endif
|
||||
|
||||
return scope->asScope();
|
||||
}
|
||||
|
||||
inline void
|
||||
StackFrame::setScopeChain(JSObject &obj)
|
||||
{
|
||||
|
@ -43,6 +43,8 @@ class ScriptFrameIter;
|
||||
class AllFramesIter;
|
||||
|
||||
class ArgumentsObject;
|
||||
class ScopeCoordinate;
|
||||
class ScopeObject;
|
||||
class StaticBlockObject;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
@ -847,6 +849,7 @@ class StackFrame
|
||||
*/
|
||||
|
||||
inline HandleObject scopeChain() const;
|
||||
inline ScopeObject &aliasedVarScope(ScopeCoordinate sc) const;
|
||||
inline GlobalObject &global() const;
|
||||
|
||||
bool hasCallObj() const {
|
||||
|
Loading…
Reference in New Issue
Block a user