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 f3a88b80ef
commit 21744a3d27
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;
if (JOF_OPTYPE(pn->getOp()) == JOF_QARG) {
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 {
JS_ASSERT(JOF_OPTYPE(pn->getOp()) == JOF_LOCAL || pn->isKind(PNK_FUNCTION));
unsigned local = pn->pn_cookie.slot();
if (local < bce->sc->bindings.numVars()) {
sc.hops = ClonedBlockDepth(bce);
sc.slot = bce->sc->bindings.localToSlot(local);
sc.slot = bce->sc->bindings.varIndexToSlot(local);
} else {
unsigned depth = local - bce->sc->bindings.numVars();
unsigned hops = 0;
@ -864,7 +864,7 @@ EmitAliasedVarOp(JSContext *cx, JSOp op, ParseNode *pn, BytecodeEmitter *bce)
b = b->enclosingBlock();
}
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();
if (Emit1(cx, bce, JSOP_ARGUMENTS) < 0)
return false;
unsigned varIndex = bce->sc->bindings.argumentsVarIndex(cx);
if (bce->sc->bindingsAccessedDynamically()) {
ScopeCoordinate sc;
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))
return false;
} else {
if (!EmitUnaliasedVarOp(cx, JSOP_SETLOCAL, bce->sc->argumentsLocal(), bce))
if (!EmitUnaliasedVarOp(cx, JSOP_SETLOCAL, varIndex, bce))
return false;
}
if (Emit1(cx, bce, JSOP_POP) < 0)

View File

@ -46,16 +46,6 @@ SharedContext::needStrictChecks() {
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
TreeContext::TreeContext(Parser *prs, SharedContext *sc, unsigned staticLevel, uint32_t bodyid)
: sc(sc),

View File

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

View File

@ -123,7 +123,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
PodZero(escapedSlots, numSlots);
if (script->bindingsAccessedDynamically || script->compartment()->debugMode() ||
script->argumentsHasLocalBinding())
script->argumentsHasVarBinding())
{
for (unsigned i = 0; i < nargs; i++)
escapedSlots[ArgSlot(i)] = true;
@ -159,7 +159,7 @@ ScriptAnalysis::analyzeBytecode(JSContext *cx)
isInlineable = true;
if (script->numClosedArgs() || script->numClosedVars() || heavyweight ||
script->bindingsAccessedDynamically || script->argumentsHasLocalBinding() ||
script->bindingsAccessedDynamically || script->argumentsHasVarBinding() ||
cx->compartment->debugMode())
{
isInlineable = false;
@ -1947,7 +1947,7 @@ ScriptAnalysis::needsArgsObj(JSContext *cx, SeenVector &seen, SSAUseChain *use)
bool
ScriptAnalysis::needsArgsObj(JSContext *cx)
{
JS_ASSERT(script->argumentsHasLocalBinding());
JS_ASSERT(script->argumentsHasVarBinding());
/*
* 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:
{
unsigned index;
return ScopeCoordinateToFrameVar(script, pc, &index) == FrameVar_Local
return ScopeCoordinateToFrameIndex(script, pc, &index) == FrameIndex_Local
? LocalSlot(script, index)
: ArgSlot(index);
}

View File

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

View File

@ -104,15 +104,13 @@ class Bindings
unsigned count() const { return nargs + nvars; }
/*
* These functions map between argument/var indices [0, nargs/nvars) and
* and Bindings indices [0, nargs + nvars).
* The VM's StackFrame allocates a Value for each formal and variable.
* 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; }
bool slotIsLocal(uint16_t i) const { return i >= nargs; }
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; }
inline uint16_t formalIndexToSlot(uint16_t i);
inline uint16_t varIndexToSlot(uint16_t i);
/* Ensure these bindings have a shape lineage. */
inline bool ensureShape(JSContext *cx);
@ -188,6 +186,9 @@ class Bindings
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
* 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 staticLevel;/* static level for display maintenance */
private:
uint16_t argsLocal_; /* local holding 'arguments' (if argumentsHasLocalBindings) */
// 8-bit fields.
public:
@ -542,7 +540,7 @@ struct JSScript : public js::gc::Cell
private:
/* See comments below. */
bool argsHasLocalBinding_:1;
bool argsHasVarBinding_:1;
bool needsArgsAnalysis_:1;
bool needsArgsObj_:1;
@ -570,10 +568,9 @@ struct JSScript : public js::gc::Cell
void setVersion(JSVersion v) { version = v; }
/* 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; }
unsigned argumentsLocal() const { JS_ASSERT(argsHasLocalBinding_); return argsLocal_; }
void setArgumentsHasLocalBinding(uint16_t local);
void setArgumentsHasVarBinding();
/*
* As an optimization, even when argsHasLocalBinding, the function prologue

View File

@ -76,6 +76,30 @@ Bindings::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
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,
* 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(),
Imm32(StackFrame::UNDERFLOW_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++)
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
* 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.
*/
uint32_t nfixed = gc::GetGCKindSlots(BlockObject::FINALIZE_KIND);
if (nfixed <= slot) {
if (nfixed <= sc.slot) {
masm.loadPtr(Address(reg, JSObject::offsetOfSlots()), reg);
addr = Address(reg, (slot - nfixed) * sizeof(Value));
addr = Address(reg, (sc.slot - nfixed) * sizeof(Value));
} else {
addr = Address(reg, JSObject::getFixedSlotOffset(slot));
addr = Address(reg, JSObject::getFixedSlotOffset(sc.slot));
}
} 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 (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);
addr = Address(reg, sc.slot * sizeof(Value));
addr = Address(reg, (sc.slot - CallObject::RESERVED_SLOTS) * sizeof(Value));
} else {
addr = Address(reg, JSObject::getFixedSlotOffset(slot));
addr = Address(reg, JSObject::getFixedSlotOffset(sc.slot));
}
}
if (get) {
unsigned index;
FrameEntry *fe = ScopeCoordinateToFrameVar(script, PC, &index) == FrameVar_Local
FrameEntry *fe = ScopeCoordinateToFrameIndex(script, PC, &index) == FrameIndex_Local
? frame.getLocal(index)
: frame.getArg(index);
JSValueType type = fe->isTypeKnown() ? fe->getKnownType() : JSVAL_TYPE_UNKNOWN;

View File

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

View File

@ -49,10 +49,9 @@ js::ScopeCoordinateName(JSRuntime *rt, JSScript *script, jsbytecode *pc)
{
StaticBlockObject *maybeBlock = ScopeCoordinateBlockChain(script, pc);
ScopeCoordinate sc(pc);
uint32_t targetSlot = ScopeObject::CALL_BLOCK_RESERVED_SLOTS + sc.slot;
Shape *shape = maybeBlock ? maybeBlock->lastProperty() : script->bindings.lastShape();
Shape::Range r = shape->all();
while (r.front().slot() != targetSlot)
while (r.front().slot() != sc.slot)
r.popFront();
jsid id = r.front().propid();
/* Beware nameless destructuring formal. */
@ -61,22 +60,24 @@ js::ScopeCoordinateName(JSRuntime *rt, JSScript *script, jsbytecode *pc)
return JSID_TO_ATOM(id)->asPropertyName();
}
FrameVarType
js::ScopeCoordinateToFrameVar(JSScript *script, jsbytecode *pc, unsigned *index)
FrameIndexType
js::ScopeCoordinateToFrameIndex(JSScript *script, jsbytecode *pc, unsigned *index)
{
ScopeCoordinate sc(pc);
if (StaticBlockObject *block = ScopeCoordinateBlockChain(script, pc)) {
*index = block->slotToFrameLocal(script, sc.slot);
return FrameVar_Local;
*index = block->slotToLocalIndex(script->bindings, sc.slot);
return FrameIndex_Local;
}
if (script->bindings.slotIsLocal(sc.slot)) {
*index = script->bindings.slotToLocal(sc.slot);
return FrameVar_Local;
unsigned i = sc.slot - CallObject::RESERVED_SLOTS;
if (i < script->bindings.numArgs()) {
*index = i;
return FrameIndex_Arg;
}
*index = script->bindings.slotToArg(sc.slot);
return FrameVar_Arg;
*index = i - script->bindings.numArgs();
JS_ASSERT(*index < script->bindings.numVars());
return FrameIndex_Local;
}
/*****************************************************************************/
@ -626,7 +627,7 @@ void
ClonedBlockObject::copyUnaliasedValues(StackFrame *fp)
{
StaticBlockObject &block = staticBlock();
unsigned base = block.slotToFrameLocal(fp->script(), 0);
unsigned base = fp->script()->nfixed + block.stackDepth();
for (unsigned i = 0; i < slotCount(); ++i) {
if (!block.isAliased(i))
setVar(i, fp->unaliasedLocal(base + i), DONT_CHECK_ALIASING);
@ -1205,7 +1206,7 @@ class DebugScopeProxy : public BaseProxyHandler
if (maybefp) {
JSScript *script = maybefp->script();
unsigned local = block.slotToFrameLocal(script, i);
unsigned local = block.slotToLocalIndex(script->bindings, shape->slot());
if (action == GET)
*vp = maybefp->unaliasedLocal(local);
else
@ -1244,7 +1245,7 @@ class DebugScopeProxy : public BaseProxyHandler
static bool isMissingArgumentsBinding(ScopeObject &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
* maps from the ScopeCoordinate space to the StackFrame variable space.
*/
enum FrameVarType { FrameVar_Local, FrameVar_Arg };
extern FrameVarType
ScopeCoordinateToFrameVar(JSScript *script, jsbytecode *pc, unsigned *index);
enum FrameIndexType { FrameIndex_Local, FrameIndex_Arg };
extern FrameIndexType
ScopeCoordinateToFrameIndex(JSScript *script, jsbytecode *pc, unsigned *index);
/*****************************************************************************/
@ -101,9 +101,6 @@ class ScopeObject : public JSObject
static const uint32_t SCOPE_CHAIN_SLOT = 0;
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
* 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);
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 *createForStrictEval(JSContext *cx, StackFrame *fp);
@ -216,7 +213,7 @@ class WithObject : public NestedScopeObject
class BlockObject : public NestedScopeObject
{
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;
/* 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
* [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:
/* Blocks contain an object slot for each slot i: 0 <= i < slotCount. */