Bug 769743 - simplify ScopedCoordinate::slot and fix names (r=dvander)

--HG--
extra : rebase_source : 5d809f4db11dae7bcaf20591556635b2ae85fe23
This commit is contained in:
Luke Wagner 2012-06-29 11:42:42 -07:00
parent 190597e235
commit 5fabc24706
12 changed files with 104 additions and 100 deletions

View File

@ -847,13 +847,13 @@ EmitAliasedVarOp(JSContext *cx, JSOp op, ParseNode *pn, BytecodeEmitter *bce)
ScopeCoordinate sc; ScopeCoordinate sc;
if (JOF_OPTYPE(pn->getOp()) == JOF_QARG) { if (JOF_OPTYPE(pn->getOp()) == JOF_QARG) {
sc.hops = ClonedBlockDepth(bce); sc.hops = ClonedBlockDepth(bce);
sc.slot = bce->sc->bindings.argToSlot(pn->pn_cookie.slot()); sc.slot = bce->sc->bindings.formalIndexToSlot(pn->pn_cookie.slot());
} else { } else {
JS_ASSERT(JOF_OPTYPE(pn->getOp()) == JOF_LOCAL || pn->isKind(PNK_FUNCTION)); JS_ASSERT(JOF_OPTYPE(pn->getOp()) == JOF_LOCAL || pn->isKind(PNK_FUNCTION));
unsigned local = pn->pn_cookie.slot(); unsigned local = pn->pn_cookie.slot();
if (local < bce->sc->bindings.numVars()) { if (local < bce->sc->bindings.numVars()) {
sc.hops = ClonedBlockDepth(bce); sc.hops = ClonedBlockDepth(bce);
sc.slot = bce->sc->bindings.localToSlot(local); sc.slot = bce->sc->bindings.varIndexToSlot(local);
} else { } else {
unsigned depth = local - bce->sc->bindings.numVars(); unsigned depth = local - bce->sc->bindings.numVars();
unsigned hops = 0; unsigned hops = 0;
@ -864,7 +864,7 @@ EmitAliasedVarOp(JSContext *cx, JSOp op, ParseNode *pn, BytecodeEmitter *bce)
b = b->enclosingBlock(); b = b->enclosingBlock();
} }
sc.hops = hops; sc.hops = hops;
sc.slot = depth - b->stackDepth(); sc.slot = b->localIndexToSlot(bce->sc->bindings, local);
} }
} }
@ -2521,14 +2521,15 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
bce->switchToProlog(); bce->switchToProlog();
if (Emit1(cx, bce, JSOP_ARGUMENTS) < 0) if (Emit1(cx, bce, JSOP_ARGUMENTS) < 0)
return false; return false;
unsigned varIndex = bce->sc->bindings.argumentsVarIndex(cx);
if (bce->sc->bindingsAccessedDynamically()) { if (bce->sc->bindingsAccessedDynamically()) {
ScopeCoordinate sc; ScopeCoordinate sc;
sc.hops = 0; sc.hops = 0;
sc.slot = bce->sc->bindings.localToSlot(bce->sc->argumentsLocal()); sc.slot = bce->sc->bindings.varIndexToSlot(varIndex);
if (!EmitAliasedVarOp(cx, JSOP_SETALIASEDVAR, sc, bce)) if (!EmitAliasedVarOp(cx, JSOP_SETALIASEDVAR, sc, bce))
return false; return false;
} else { } else {
if (!EmitUnaliasedVarOp(cx, JSOP_SETLOCAL, bce->sc->argumentsLocal(), bce)) if (!EmitUnaliasedVarOp(cx, JSOP_SETLOCAL, varIndex, bce))
return false; return false;
} }
if (Emit1(cx, bce, JSOP_POP) < 0) if (Emit1(cx, bce, JSOP_POP) < 0)

View File

@ -46,16 +46,6 @@ SharedContext::needStrictChecks() {
return context->hasStrictOption() || inStrictMode(); return context->hasStrictOption() || inStrictMode();
} }
inline unsigned
SharedContext::argumentsLocal() const
{
PropertyName *arguments = context->runtime->atomState.argumentsAtom;
unsigned slot;
DebugOnly<BindingKind> kind = bindings.lookup(context, arguments, &slot);
JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
return slot;
}
inline inline
TreeContext::TreeContext(Parser *prs, SharedContext *sc, unsigned staticLevel, uint32_t bodyid) TreeContext::TreeContext(Parser *prs, SharedContext *sc, unsigned staticLevel, uint32_t bodyid)
: sc(sc), : sc(sc),

View File

@ -175,8 +175,6 @@ struct SharedContext {
#undef INFUNC #undef INFUNC
unsigned argumentsLocal() const;
bool inFunction() const { return !!fun_; } bool inFunction() const { return !!fun_; }
JSFunction *fun() const { JS_ASSERT(inFunction()); return fun_; } JSFunction *fun() const { JS_ASSERT(inFunction()); return fun_; }

View File

@ -123,7 +123,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
PodZero(escapedSlots, numSlots); PodZero(escapedSlots, numSlots);
if (script->bindingsAccessedDynamically || script->compartment()->debugMode() || if (script->bindingsAccessedDynamically || script->compartment()->debugMode() ||
script->argumentsHasLocalBinding()) script->argumentsHasVarBinding())
{ {
for (unsigned i = 0; i < nargs; i++) for (unsigned i = 0; i < nargs; i++)
escapedSlots[ArgSlot(i)] = true; escapedSlots[ArgSlot(i)] = true;
@ -159,7 +159,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
isInlineable = true; isInlineable = true;
if (script->numClosedArgs() || script->numClosedVars() || heavyweight || if (script->numClosedArgs() || script->numClosedVars() || heavyweight ||
script->bindingsAccessedDynamically || script->argumentsHasLocalBinding() || script->bindingsAccessedDynamically || script->argumentsHasVarBinding() ||
cx->compartment->debugMode()) cx->compartment->debugMode())
{ {
isInlineable = false; isInlineable = false;
@ -1947,7 +1947,7 @@ ScriptAnalysis::needsArgsObj(JSContext *cx, SeenVector &seen, SSAUseChain *use)
bool bool
ScriptAnalysis::needsArgsObj(JSContext *cx) ScriptAnalysis::needsArgsObj(JSContext *cx)
{ {
JS_ASSERT(script->argumentsHasLocalBinding()); JS_ASSERT(script->argumentsHasVarBinding());
/* /*
* Since let variables and dynamic name access are not tracked, we cannot * Since let variables and dynamic name access are not tracked, we cannot

View File

@ -364,7 +364,7 @@ static inline uint32_t GetBytecodeSlot(JSScript *script, jsbytecode *pc)
case JSOP_SETALIASEDVAR: case JSOP_SETALIASEDVAR:
{ {
unsigned index; unsigned index;
return ScopeCoordinateToFrameVar(script, pc, &index) == FrameVar_Local return ScopeCoordinateToFrameIndex(script, pc, &index) == FrameIndex_Local
? LocalSlot(script, index) ? LocalSlot(script, index)
: ArgSlot(index); : ArgSlot(index);
} }

View File

@ -355,7 +355,7 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
StrictModeCode, StrictModeCode,
ContainsDynamicNameAccess, ContainsDynamicNameAccess,
FunHasExtensibleScope, FunHasExtensibleScope,
ArgumentsHasLocalBinding, ArgumentsHasVarBinding,
NeedsArgsObj, NeedsArgsObj,
OwnFilename, OwnFilename,
ParentFilename, ParentFilename,
@ -373,7 +373,7 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
nsrcnotes = ntrynotes = natoms = nobjects = nregexps = nconsts = nClosedArgs = nClosedVars = 0; nsrcnotes = ntrynotes = natoms = nobjects = nregexps = nconsts = nClosedArgs = nClosedVars = 0;
jssrcnote *notes = NULL; jssrcnote *notes = NULL;
/* XDR arguments, local vars, and upvars. */ /* XDR arguments, var vars, and upvars. */
uint16_t nargs, nvars; uint16_t nargs, nvars;
#if defined(DEBUG) || defined(__GNUC__) /* quell GCC overwarning */ #if defined(DEBUG) || defined(__GNUC__) /* quell GCC overwarning */
script = NULL; script = NULL;
@ -511,8 +511,8 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
scriptBits |= (1 << ContainsDynamicNameAccess); scriptBits |= (1 << ContainsDynamicNameAccess);
if (script->funHasExtensibleScope) if (script->funHasExtensibleScope)
scriptBits |= (1 << FunHasExtensibleScope); scriptBits |= (1 << FunHasExtensibleScope);
if (script->argumentsHasLocalBinding()) if (script->argumentsHasVarBinding())
scriptBits |= (1 << ArgumentsHasLocalBinding); scriptBits |= (1 << ArgumentsHasVarBinding);
if (script->analyzedArgsUsage() && script->needsArgsObj()) if (script->analyzedArgsUsage() && script->needsArgsObj())
scriptBits |= (1 << NeedsArgsObj); scriptBits |= (1 << NeedsArgsObj);
if (script->filename) { if (script->filename) {
@ -593,13 +593,8 @@ js::XDRScript(XDRState<mode> *xdr, JSScript **scriptp, JSScript *parentScript)
script->bindingsAccessedDynamically = true; script->bindingsAccessedDynamically = true;
if (scriptBits & (1 << FunHasExtensibleScope)) if (scriptBits & (1 << FunHasExtensibleScope))
script->funHasExtensibleScope = true; script->funHasExtensibleScope = true;
if (scriptBits & (1 << ArgumentsHasLocalBinding)) { if (scriptBits & (1 << ArgumentsHasVarBinding))
PropertyName *arguments = cx->runtime->atomState.argumentsAtom; script->setArgumentsHasVarBinding();
unsigned local;
DebugOnly<BindingKind> kind = script->bindings.lookup(cx, arguments, &local);
JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
script->setArgumentsHasLocalBinding(local);
}
if (scriptBits & (1 << NeedsArgsObj)) if (scriptBits & (1 << NeedsArgsObj))
script->setNeedsArgsObj(true); script->setNeedsArgsObj(true);
if (scriptBits & (1 << IsGenerator)) if (scriptBits & (1 << IsGenerator))
@ -1326,7 +1321,7 @@ JSScript::fullyInitFromEmitter(JSContext *cx, BytecodeEmitter *bce)
if (bce->sc->inFunction()) { if (bce->sc->inFunction()) {
if (bce->sc->funArgumentsHasLocalBinding()) { if (bce->sc->funArgumentsHasLocalBinding()) {
// This must precede the script->bindings.transfer() call below // This must precede the script->bindings.transfer() call below
script->setArgumentsHasLocalBinding(bce->sc->argumentsLocal()); script->setArgumentsHasVarBinding();
if (bce->sc->funDefinitelyNeedsArgsObj()) if (bce->sc->funDefinitelyNeedsArgsObj())
script->setNeedsArgsObj(true); script->setNeedsArgsObj(true);
} else { } else {
@ -1795,8 +1790,8 @@ js::CloneScript(JSContext *cx, HandleScript src)
dst->nfixed = src->nfixed; dst->nfixed = src->nfixed;
dst->nTypeSets = src->nTypeSets; dst->nTypeSets = src->nTypeSets;
dst->nslots = src->nslots; dst->nslots = src->nslots;
if (src->argumentsHasLocalBinding()) { if (src->argumentsHasVarBinding()) {
dst->setArgumentsHasLocalBinding(src->argumentsLocal()); dst->setArgumentsHasVarBinding();
if (src->analyzedArgsUsage()) if (src->analyzedArgsUsage())
dst->setNeedsArgsObj(src->needsArgsObj()); dst->setNeedsArgsObj(src->needsArgsObj());
} }
@ -2127,10 +2122,9 @@ JSScript::markChildren(JSTracer *trc)
} }
void void
JSScript::setArgumentsHasLocalBinding(uint16_t local) JSScript::setArgumentsHasVarBinding()
{ {
argsHasLocalBinding_ = true; argsHasVarBinding_ = true;
argsLocal_ = local;
needsArgsAnalysis_ = true; needsArgsAnalysis_ = true;
} }
@ -2138,7 +2132,7 @@ void
JSScript::setNeedsArgsObj(bool needsArgsObj) JSScript::setNeedsArgsObj(bool needsArgsObj)
{ {
JS_ASSERT(!analyzedArgsUsage()); JS_ASSERT(!analyzedArgsUsage());
JS_ASSERT_IF(needsArgsObj, argumentsHasLocalBinding()); JS_ASSERT_IF(needsArgsObj, argumentsHasVarBinding());
needsArgsAnalysis_ = false; needsArgsAnalysis_ = false;
needsArgsObj_ = needsArgsObj; needsArgsObj_ = needsArgsObj;
} }
@ -2149,7 +2143,7 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, JSScript *script_)
Rooted<JSScript*> script(cx, script_); Rooted<JSScript*> script(cx, script_);
JS_ASSERT(script->analyzedArgsUsage()); JS_ASSERT(script->analyzedArgsUsage());
JS_ASSERT(script->argumentsHasLocalBinding()); JS_ASSERT(script->argumentsHasVarBinding());
/* /*
* It is possible that the apply speculation has already failed, everything * It is possible that the apply speculation has already failed, everything
@ -2162,7 +2156,7 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, JSScript *script_)
script->needsArgsObj_ = true; script->needsArgsObj_ = true;
const unsigned local = script->argumentsLocal(); const unsigned var = script->bindings.argumentsVarIndex(cx);
/* /*
* By design, the apply-arguments optimization is only made when there * By design, the apply-arguments optimization is only made when there
@ -2191,8 +2185,8 @@ JSScript::argumentsOptimizationFailed(JSContext *cx, JSScript *script_)
} }
/* Note: 'arguments' may have already been overwritten. */ /* Note: 'arguments' may have already been overwritten. */
if (fp->unaliasedLocal(local).isMagic(JS_OPTIMIZED_ARGUMENTS)) if (fp->unaliasedLocal(var).isMagic(JS_OPTIMIZED_ARGUMENTS))
fp->unaliasedLocal(local) = ObjectValue(*argsobj); fp->unaliasedLocal(var) = ObjectValue(*argsobj);
} }
} }

View File

@ -104,15 +104,13 @@ class Bindings
unsigned count() const { return nargs + nvars; } unsigned count() const { return nargs + nvars; }
/* /*
* These functions map between argument/var indices [0, nargs/nvars) and * The VM's StackFrame allocates a Value for each formal and variable.
* and Bindings indices [0, nargs + nvars). * A (formal|var)Index is the index passed to fp->unaliasedFormal/Var to
* access this variable. These two functions convert between formal/var
* indices and the corresponding slot in the CallObject.
*/ */
bool slotIsArg(uint16_t i) const { return i < nargs; } inline uint16_t formalIndexToSlot(uint16_t i);
bool slotIsLocal(uint16_t i) const { return i >= nargs; } inline uint16_t varIndexToSlot(uint16_t i);
uint16_t argToSlot(uint16_t i) { JS_ASSERT(i < nargs); return i; }
uint16_t localToSlot(uint16_t i) { return i + nargs; }
uint16_t slotToArg(uint16_t i) { JS_ASSERT(slotIsArg(i)); return i; }
uint16_t slotToLocal(uint16_t i) { JS_ASSERT(slotIsLocal(i)); return i - nargs; }
/* Ensure these bindings have a shape lineage. */ /* Ensure these bindings have a shape lineage. */
inline bool ensureShape(JSContext *cx); inline bool ensureShape(JSContext *cx);
@ -188,6 +186,9 @@ class Bindings
return lookup(cx, name, NULL) != NONE; return lookup(cx, name, NULL) != NONE;
} }
/* Convenience method to get the var index of 'arguments'. */
inline unsigned argumentsVarIndex(JSContext *cx) const;
/* /*
* This method returns the local variable, argument, etc. names used by a * This method returns the local variable, argument, etc. names used by a
* script. This function must be called only when count() > 0. * script. This function must be called only when count() > 0.
@ -478,9 +479,6 @@ struct JSScript : public js::gc::Cell
uint16_t nslots; /* vars plus maximum stack depth */ uint16_t nslots; /* vars plus maximum stack depth */
uint16_t staticLevel;/* static level for display maintenance */ uint16_t staticLevel;/* static level for display maintenance */
private:
uint16_t argsLocal_; /* local holding 'arguments' (if argumentsHasLocalBindings) */
// 8-bit fields. // 8-bit fields.
public: public:
@ -542,7 +540,7 @@ struct JSScript : public js::gc::Cell
private: private:
/* See comments below. */ /* See comments below. */
bool argsHasLocalBinding_:1; bool argsHasVarBinding_:1;
bool needsArgsAnalysis_:1; bool needsArgsAnalysis_:1;
bool needsArgsObj_:1; bool needsArgsObj_:1;
@ -570,10 +568,9 @@ struct JSScript : public js::gc::Cell
void setVersion(JSVersion v) { version = v; } void setVersion(JSVersion v) { version = v; }
/* See ContextFlags::funArgumentsHasLocalBinding comment. */ /* See ContextFlags::funArgumentsHasLocalBinding comment. */
bool argumentsHasLocalBinding() const { return argsHasLocalBinding_; } bool argumentsHasVarBinding() const { return argsHasVarBinding_; }
jsbytecode *argumentsBytecode() const { JS_ASSERT(code[0] == JSOP_ARGUMENTS); return code; } jsbytecode *argumentsBytecode() const { JS_ASSERT(code[0] == JSOP_ARGUMENTS); return code; }
unsigned argumentsLocal() const { JS_ASSERT(argsHasLocalBinding_); return argsLocal_; } void setArgumentsHasVarBinding();
void setArgumentsHasLocalBinding(uint16_t local);
/* /*
* As an optimization, even when argsHasLocalBinding, the function prologue * As an optimization, even when argsHasLocalBinding, the function prologue

View File

@ -76,6 +76,30 @@ Bindings::extensibleParents()
return lastBinding && lastBinding->extensibleParents(); return lastBinding && lastBinding->extensibleParents();
} }
uint16_t
Bindings::formalIndexToSlot(uint16_t i)
{
JS_ASSERT(i < nargs);
return CallObject::RESERVED_SLOTS + i;
}
uint16_t
Bindings::varIndexToSlot(uint16_t i)
{
JS_ASSERT(i < nvars);
return CallObject::RESERVED_SLOTS + i + nargs;
}
unsigned
Bindings::argumentsVarIndex(JSContext *cx) const
{
PropertyName *arguments = cx->runtime->atomState.argumentsAtom;
unsigned i;
DebugOnly<BindingKind> kind = lookup(cx, arguments, &i);
JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
return i;
}
extern void extern void
CurrentScriptFileLineOriginSlow(JSContext *cx, const char **file, unsigned *linenop, JSPrincipals **origin); CurrentScriptFileLineOriginSlow(JSContext *cx, const char **file, unsigned *linenop, JSPrincipals **origin);

View File

@ -1106,7 +1106,7 @@ mjit::Compiler::generatePrologue()
* fp->u.nactual. fp->u.nactual is only set when numActual != numFormal, * fp->u.nactual. fp->u.nactual is only set when numActual != numFormal,
* so store 'fp->u.nactual = numFormal' when there is no over/underflow. * so store 'fp->u.nactual = numFormal' when there is no over/underflow.
*/ */
if (script->argumentsHasLocalBinding()) { if (script->argumentsHasVarBinding()) {
Jump hasArgs = masm.branchTest32(Assembler::NonZero, FrameFlagsAddress(), Jump hasArgs = masm.branchTest32(Assembler::NonZero, FrameFlagsAddress(),
Imm32(StackFrame::UNDERFLOW_ARGS | Imm32(StackFrame::UNDERFLOW_ARGS |
StackFrame::OVERFLOW_ARGS)); StackFrame::OVERFLOW_ARGS));
@ -5846,8 +5846,6 @@ mjit::Compiler::jsop_aliasedVar(ScopeCoordinate sc, bool get, bool poppedAfter)
for (unsigned i = 0; i < sc.hops; i++) for (unsigned i = 0; i < sc.hops; i++)
masm.loadPayload(Address(reg, ScopeObject::offsetOfEnclosingScope()), reg); masm.loadPayload(Address(reg, ScopeObject::offsetOfEnclosingScope()), reg);
unsigned slot = ScopeObject::CALL_BLOCK_RESERVED_SLOTS + sc.slot;
/* /*
* TODO bug 753158: Call and Block objects should use the same layout * TODO bug 753158: Call and Block objects should use the same layout
* strategy: up to the maximum numFixedSlots and overflow (if any) in * strategy: up to the maximum numFixedSlots and overflow (if any) in
@ -5862,11 +5860,11 @@ mjit::Compiler::jsop_aliasedVar(ScopeCoordinate sc, bool get, bool poppedAfter)
* slot over is in the dynamic slots. * slot over is in the dynamic slots.
*/ */
uint32_t nfixed = gc::GetGCKindSlots(BlockObject::FINALIZE_KIND); uint32_t nfixed = gc::GetGCKindSlots(BlockObject::FINALIZE_KIND);
if (nfixed <= slot) { if (nfixed <= sc.slot) {
masm.loadPtr(Address(reg, JSObject::offsetOfSlots()), reg); masm.loadPtr(Address(reg, JSObject::offsetOfSlots()), reg);
addr = Address(reg, (slot - nfixed) * sizeof(Value)); addr = Address(reg, (sc.slot - nfixed) * sizeof(Value));
} else { } else {
addr = Address(reg, JSObject::getFixedSlotOffset(slot)); addr = Address(reg, JSObject::getFixedSlotOffset(sc.slot));
} }
} else { } else {
/* /*
@ -5874,17 +5872,17 @@ mjit::Compiler::jsop_aliasedVar(ScopeCoordinate sc, bool get, bool poppedAfter)
* slots are either altogether in fixed slots or altogether in dynamic * slots are either altogether in fixed slots or altogether in dynamic
* slots (by having numFixed == RESERVED_SLOTS). * slots (by having numFixed == RESERVED_SLOTS).
*/ */
if (script->bindings.lastShape()->numFixedSlots() <= slot) { if (script->bindings.lastShape()->numFixedSlots() <= sc.slot) {
masm.loadPtr(Address(reg, JSObject::offsetOfSlots()), reg); masm.loadPtr(Address(reg, JSObject::offsetOfSlots()), reg);
addr = Address(reg, sc.slot * sizeof(Value)); addr = Address(reg, (sc.slot - CallObject::RESERVED_SLOTS) * sizeof(Value));
} else { } else {
addr = Address(reg, JSObject::getFixedSlotOffset(slot)); addr = Address(reg, JSObject::getFixedSlotOffset(sc.slot));
} }
} }
if (get) { if (get) {
unsigned index; unsigned index;
FrameEntry *fe = ScopeCoordinateToFrameVar(script, PC, &index) == FrameVar_Local FrameEntry *fe = ScopeCoordinateToFrameIndex(script, PC, &index) == FrameIndex_Local
? frame.getLocal(index) ? frame.getLocal(index)
: frame.getArg(index); : frame.getArg(index);
JSValueType type = fe->isTypeKnown() ? fe->getKnownType() : JSVAL_TYPE_UNKNOWN; JSValueType type = fe->isTypeKnown() ? fe->getKnownType() : JSVAL_TYPE_UNKNOWN;

View File

@ -39,18 +39,15 @@ inline const Value &
ScopeObject::aliasedVar(ScopeCoordinate sc) ScopeObject::aliasedVar(ScopeCoordinate sc)
{ {
JS_ASSERT(isCall() || isClonedBlock()); JS_ASSERT(isCall() || isClonedBlock());
JS_STATIC_ASSERT(CALL_BLOCK_RESERVED_SLOTS == CallObject::RESERVED_SLOTS); return getSlot(sc.slot);
JS_STATIC_ASSERT(CALL_BLOCK_RESERVED_SLOTS == BlockObject::RESERVED_SLOTS);
return getSlot(CALL_BLOCK_RESERVED_SLOTS + sc.slot);
} }
inline void inline void
ScopeObject::setAliasedVar(ScopeCoordinate sc, const Value &v) ScopeObject::setAliasedVar(ScopeCoordinate sc, const Value &v)
{ {
JS_ASSERT(isCall() || isClonedBlock()); JS_ASSERT(isCall() || isClonedBlock());
JS_STATIC_ASSERT(CALL_BLOCK_RESERVED_SLOTS == CallObject::RESERVED_SLOTS); JS_STATIC_ASSERT(CallObject::RESERVED_SLOTS == BlockObject::RESERVED_SLOTS);
JS_STATIC_ASSERT(CALL_BLOCK_RESERVED_SLOTS == BlockObject::RESERVED_SLOTS); setSlot(sc.slot, v);
setSlot(CALL_BLOCK_RESERVED_SLOTS + sc.slot, v);
} }
/*static*/ inline size_t /*static*/ inline size_t
@ -159,10 +156,16 @@ BlockObject::slotCount() const
} }
inline unsigned inline unsigned
BlockObject::slotToFrameLocal(JSScript *script, unsigned i) BlockObject::slotToLocalIndex(const Bindings &bindings, unsigned slot)
{ {
JS_ASSERT(i < slotCount()); JS_ASSERT(slot < RESERVED_SLOTS + slotCount());
return script->nfixed + stackDepth() + i; return bindings.numVars() + stackDepth() + (slot - RESERVED_SLOTS);
}
inline unsigned
BlockObject::localIndexToSlot(const Bindings &bindings, unsigned i)
{
return RESERVED_SLOTS + (i - (bindings.numVars() + stackDepth()));
} }
inline const Value & inline const Value &

View File

@ -49,10 +49,9 @@ js::ScopeCoordinateName(JSRuntime *rt, JSScript *script, jsbytecode *pc)
{ {
StaticBlockObject *maybeBlock = ScopeCoordinateBlockChain(script, pc); StaticBlockObject *maybeBlock = ScopeCoordinateBlockChain(script, pc);
ScopeCoordinate sc(pc); ScopeCoordinate sc(pc);
uint32_t targetSlot = ScopeObject::CALL_BLOCK_RESERVED_SLOTS + sc.slot;
Shape *shape = maybeBlock ? maybeBlock->lastProperty() : script->bindings.lastShape(); Shape *shape = maybeBlock ? maybeBlock->lastProperty() : script->bindings.lastShape();
Shape::Range r = shape->all(); Shape::Range r = shape->all();
while (r.front().slot() != targetSlot) while (r.front().slot() != sc.slot)
r.popFront(); r.popFront();
jsid id = r.front().propid(); jsid id = r.front().propid();
/* Beware nameless destructuring formal. */ /* Beware nameless destructuring formal. */
@ -61,22 +60,24 @@ js::ScopeCoordinateName(JSRuntime *rt, JSScript *script, jsbytecode *pc)
return JSID_TO_ATOM(id)->asPropertyName(); return JSID_TO_ATOM(id)->asPropertyName();
} }
FrameVarType FrameIndexType
js::ScopeCoordinateToFrameVar(JSScript *script, jsbytecode *pc, unsigned *index) js::ScopeCoordinateToFrameIndex(JSScript *script, jsbytecode *pc, unsigned *index)
{ {
ScopeCoordinate sc(pc); ScopeCoordinate sc(pc);
if (StaticBlockObject *block = ScopeCoordinateBlockChain(script, pc)) { if (StaticBlockObject *block = ScopeCoordinateBlockChain(script, pc)) {
*index = block->slotToFrameLocal(script, sc.slot); *index = block->slotToLocalIndex(script->bindings, sc.slot);
return FrameVar_Local; return FrameIndex_Local;
} }
if (script->bindings.slotIsLocal(sc.slot)) { unsigned i = sc.slot - CallObject::RESERVED_SLOTS;
*index = script->bindings.slotToLocal(sc.slot); if (i < script->bindings.numArgs()) {
return FrameVar_Local; *index = i;
return FrameIndex_Arg;
} }
*index = script->bindings.slotToArg(sc.slot); *index = i - script->bindings.numArgs();
return FrameVar_Arg; JS_ASSERT(*index < script->bindings.numVars());
return FrameIndex_Local;
} }
/*****************************************************************************/ /*****************************************************************************/
@ -626,7 +627,7 @@ void
ClonedBlockObject::copyUnaliasedValues(StackFrame *fp) ClonedBlockObject::copyUnaliasedValues(StackFrame *fp)
{ {
StaticBlockObject &block = staticBlock(); StaticBlockObject &block = staticBlock();
unsigned base = block.slotToFrameLocal(fp->script(), 0); unsigned base = fp->script()->nfixed + block.stackDepth();
for (unsigned i = 0; i < slotCount(); ++i) { for (unsigned i = 0; i < slotCount(); ++i) {
if (!block.isAliased(i)) if (!block.isAliased(i))
setVar(i, fp->unaliasedLocal(base + i), DONT_CHECK_ALIASING); setVar(i, fp->unaliasedLocal(base + i), DONT_CHECK_ALIASING);
@ -1205,7 +1206,7 @@ class DebugScopeProxy : public BaseProxyHandler
if (maybefp) { if (maybefp) {
JSScript *script = maybefp->script(); JSScript *script = maybefp->script();
unsigned local = block.slotToFrameLocal(script, i); unsigned local = block.slotToLocalIndex(script->bindings, shape->slot());
if (action == GET) if (action == GET)
*vp = maybefp->unaliasedLocal(local); *vp = maybefp->unaliasedLocal(local);
else else
@ -1244,7 +1245,7 @@ class DebugScopeProxy : public BaseProxyHandler
static bool isMissingArgumentsBinding(ScopeObject &scope) static bool isMissingArgumentsBinding(ScopeObject &scope)
{ {
return isFunctionScope(scope) && return isFunctionScope(scope) &&
!scope.asCall().getCalleeFunction()->script()->argumentsHasLocalBinding(); !scope.asCall().getCalleeFunction()->script()->argumentsHasVarBinding();
} }
/* /*

View File

@ -51,9 +51,9 @@ ScopeCoordinateName(JSRuntime *rt, JSScript *script, jsbytecode *pc);
* variable is used to refer to the jit/inference information). This function * variable is used to refer to the jit/inference information). This function
* maps from the ScopeCoordinate space to the StackFrame variable space. * maps from the ScopeCoordinate space to the StackFrame variable space.
*/ */
enum FrameVarType { FrameVar_Local, FrameVar_Arg }; enum FrameIndexType { FrameIndex_Local, FrameIndex_Arg };
extern FrameVarType extern FrameIndexType
ScopeCoordinateToFrameVar(JSScript *script, jsbytecode *pc, unsigned *index); ScopeCoordinateToFrameIndex(JSScript *script, jsbytecode *pc, unsigned *index);
/*****************************************************************************/ /*****************************************************************************/
@ -101,9 +101,6 @@ class ScopeObject : public JSObject
static const uint32_t SCOPE_CHAIN_SLOT = 0; static const uint32_t SCOPE_CHAIN_SLOT = 0;
public: public:
/* Number of reserved slots for both CallObject and BlockObject. */
static const uint32_t CALL_BLOCK_RESERVED_SLOTS = 2;
/* /*
* Since every scope chain terminates with a global object and GlobalObject * Since every scope chain terminates with a global object and GlobalObject
* does not derive ScopeObject (it has a completely different layout), the * does not derive ScopeObject (it has a completely different layout), the
@ -133,7 +130,7 @@ class CallObject : public ScopeObject
create(JSContext *cx, JSScript *script, HandleObject enclosing, HandleFunction callee); create(JSContext *cx, JSScript *script, HandleObject enclosing, HandleFunction callee);
public: public:
static const uint32_t RESERVED_SLOTS = CALL_BLOCK_RESERVED_SLOTS; static const uint32_t RESERVED_SLOTS = 2;
static CallObject *createForFunction(JSContext *cx, StackFrame *fp); static CallObject *createForFunction(JSContext *cx, StackFrame *fp);
static CallObject *createForStrictEval(JSContext *cx, StackFrame *fp); static CallObject *createForStrictEval(JSContext *cx, StackFrame *fp);
@ -216,7 +213,7 @@ class WithObject : public NestedScopeObject
class BlockObject : public NestedScopeObject class BlockObject : public NestedScopeObject
{ {
public: public:
static const unsigned RESERVED_SLOTS = CALL_BLOCK_RESERVED_SLOTS; static const unsigned RESERVED_SLOTS = 2;
static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT4_BACKGROUND; static const gc::AllocKind FINALIZE_KIND = gc::FINALIZE_OBJECT4_BACKGROUND;
/* Return the number of variables associated with this block. */ /* Return the number of variables associated with this block. */
@ -227,7 +224,8 @@ class BlockObject : public NestedScopeObject
* range [0, slotCount()) and the return local index is in the range * range [0, slotCount()) and the return local index is in the range
* [script->nfixed, script->nfixed + script->nslots). * [script->nfixed, script->nfixed + script->nslots).
*/ */
unsigned slotToFrameLocal(JSScript *script, unsigned i); unsigned slotToLocalIndex(const Bindings &bindings, unsigned slot);
unsigned localIndexToSlot(const Bindings &bindings, uint32_t i);
protected: protected:
/* Blocks contain an object slot for each slot i: 0 <= i < slotCount. */ /* Blocks contain an object slot for each slot i: 0 <= i < slotCount. */