Bug 568593 - Refactor SharedContext; r=jorendorff

This commit is contained in:
Eddy Bruel 2013-01-18 14:21:32 +01:00
parent f044eb2056
commit 567f771d25
8 changed files with 86 additions and 78 deletions

View File

@ -699,12 +699,12 @@ EnclosingStaticScope(BytecodeEmitter *bce)
if (bce->blockChain)
return bce->blockChain;
if (!bce->sc->isFunction) {
if (!bce->sc->isFunctionBox()) {
JS_ASSERT(!bce->parent);
return NULL;
}
return bce->sc->asFunbox()->function();
return bce->sc->asFunctionBox()->function();
}
// Push a block scope statement and link blockObj into bce->blockChain.
@ -920,7 +920,7 @@ EmitAliasedVarOp(JSContext *cx, JSOp op, ParseNode *pn, BytecodeEmitter *bce)
*/
for (unsigned i = pn->pn_cookie.level(); i; i--) {
skippedScopes += ClonedBlockDepth(bceOfDef);
JSFunction *funOfDef = bceOfDef->sc->asFunbox()->function();
JSFunction *funOfDef = bceOfDef->sc->asFunctionBox()->function();
if (funOfDef->isHeavyweight()) {
skippedScopes++;
if (funOfDef->isNamedLambda())
@ -1082,7 +1082,7 @@ static int
AdjustBlockSlot(JSContext *cx, BytecodeEmitter *bce, int slot)
{
JS_ASSERT((unsigned) slot < bce->maxStackDepth);
if (bce->sc->isFunction) {
if (bce->sc->isFunctionBox()) {
slot += bce->script->bindings.numVars();
if ((unsigned) slot >= SLOTNO_LIMIT) {
bce->reportError(NULL, JSMSG_TOO_MANY_LOCALS);
@ -1180,7 +1180,7 @@ TryConvertToGname(BytecodeEmitter *bce, ParseNode *pn, JSOp *op)
}
if (bce->script->compileAndGo &&
bce->hasGlobalScope &&
!(bce->sc->isFunction && bce->sc->asFunbox()->mightAliasLocals()) &&
!(bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->mightAliasLocals()) &&
!pn->isDeoptimized() &&
!bce->sc->strict)
{
@ -1382,7 +1382,7 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
if (dn->pn_cookie.level() != bce->script->staticLevel)
return true;
RootedFunction fun(cx, bce->sc->asFunbox()->function());
RootedFunction fun(cx, bce->sc->asFunctionBox()->function());
JS_ASSERT(fun->isLambda());
JS_ASSERT(pn->pn_atom == fun->atom());
@ -1445,7 +1445,7 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
BytecodeEmitter *bceSkipped = bce;
for (unsigned i = 0; i < skip; i++)
bceSkipped = bceSkipped->parent;
if (!bceSkipped->sc->isFunction)
if (!bceSkipped->sc->isFunctionBox())
return true;
}
@ -1657,7 +1657,7 @@ CheckSideEffects(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool *answe
bool
BytecodeEmitter::checkSingletonContext()
{
if (!script->compileAndGo || sc->isFunction)
if (!script->compileAndGo || sc->isFunctionBox())
return false;
for (StmtInfoBCE *stmt = topStmt; stmt; stmt = stmt->down) {
if (stmt->isLoop())
@ -1673,11 +1673,11 @@ BytecodeEmitter::needsImplicitThis()
if (!script->compileAndGo)
return true;
if (sc->isFunction) {
if (sc->asFunbox()->inWith)
if (sc->isFunctionBox()) {
if (sc->asFunctionBox()->inWith)
return true;
} else {
JSObject *scope = sc->asGlobal()->scopeChain();
JSObject *scope = sc->asGlobalSharedContext()->scopeChain();
while (scope) {
if (scope->isWith())
return true;
@ -2547,7 +2547,7 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
* execution starts from script->code, so this has no semantic effect.
*/
FunctionBox *funbox = bce->sc->asFunbox();
FunctionBox *funbox = bce->sc->asFunctionBox();
if (funbox->argumentsHasLocalBinding()) {
JS_ASSERT(bce->next() == bce->base()); /* See JSScript::argumentsBytecode. */
bce->switchToProlog();
@ -2624,7 +2624,7 @@ MaybeEmitVarDecl(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *
}
if (JOF_OPTYPE(pn->getOp()) == JOF_ATOM &&
(!bce->sc->isFunction || bce->sc->asFunbox()->function()->isHeavyweight()))
(!bce->sc->isFunctionBox() || bce->sc->asFunctionBox()->function()->isHeavyweight()))
{
bce->switchToProlog();
if (!UpdateSourceCoordNotes(cx, bce, pn->pn_pos.begin))
@ -4400,7 +4400,7 @@ EmitLexicalScope(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
(stmtInfo.down
? stmtInfo.down->type == STMT_BLOCK &&
(!stmtInfo.down->down || stmtInfo.down->down->type != STMT_FOR_IN_LOOP)
: !bce->sc->isFunction))
: !bce->sc->isFunctionBox()))
{
/* There must be no source note already output for the next op. */
JS_ASSERT(bce->noteCount() == 0 ||
@ -4793,7 +4793,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* comments in EmitStatementList.
*/
JS_ASSERT(pn->functionIsHoisted());
JS_ASSERT(bce->sc->isFunction);
JS_ASSERT(bce->sc->isFunctionBox());
return EmitFunctionDefNop(cx, bce, pn->pn_index);
}
@ -4801,7 +4801,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
SharedContext *outersc = bce->sc;
FunctionBox *funbox = pn->pn_funbox;
if (outersc->isFunction && outersc->asFunbox()->mightAliasLocals())
if (outersc->isFunctionBox() && outersc->asFunctionBox()->mightAliasLocals())
funbox->setMightAliasLocals(); // inherit mightAliasLocals from parent
JS_ASSERT_IF(outersc->strict, funbox->strict);
@ -4854,7 +4854,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* invocation of the emitter and calls to EmitTree for function
* definitions can be scheduled before generating the rest of code.
*/
if (!bce->sc->isFunction) {
if (!bce->sc->isFunctionBox()) {
JS_ASSERT(pn->pn_cookie.isFree());
JS_ASSERT(pn->getOp() == JSOP_NOP);
JS_ASSERT(!bce->topStmt);
@ -5147,7 +5147,7 @@ EmitStatement(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
*/
bool wantval = false;
bool useful = false;
if (bce->sc->isFunction) {
if (bce->sc->isFunctionBox()) {
JS_ASSERT(!bce->script->noScriptRval);
} else {
useful = wantval = !bce->script->noScriptRval;
@ -5962,7 +5962,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
case PNK_ARGSBODY:
{
RootedFunction fun(cx, bce->sc->asFunbox()->function());
RootedFunction fun(cx, bce->sc->asFunctionBox()->function());
ParseNode *pnlast = pn->last();
// Carefully emit everything in the right order:
@ -6000,7 +6000,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
ParseNode *rest = NULL;
bool restIsDefn = false;
if (fun->hasRest()) {
JS_ASSERT(!bce->sc->asFunbox()->argumentsHasLocalBinding());
JS_ASSERT(!bce->sc->asFunctionBox()->argumentsHasLocalBinding());
// Defaults with a rest parameter need special handling. The
// rest parameter needs to be undefined while defaults are being
// processed. To do this, we create the rest argument and let it
@ -6045,7 +6045,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
return false;
if (pn2->pn_next == pnlast && fun->hasRest() && !fun->hasDefaults()) {
// Fill rest parameter. We handled the case with defaults above.
JS_ASSERT(!bce->sc->asFunbox()->argumentsHasLocalBinding());
JS_ASSERT(!bce->sc->asFunctionBox()->argumentsHasLocalBinding());
bce->switchToProlog();
if (Emit1(cx, bce, JSOP_REST) < 0)
return false;
@ -6115,7 +6115,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
#if JS_HAS_GENERATORS
case PNK_YIELD:
JS_ASSERT(bce->sc->isFunction);
JS_ASSERT(bce->sc->isFunctionBox());
if (pn->pn_kid) {
if (!EmitTree(cx, bce, pn->pn_kid))
return false;

View File

@ -805,6 +805,14 @@ ObjectBox::ObjectBox(JSFunction *function, ObjectBox* traceLink)
emitLink(NULL)
{
JS_ASSERT(object->isFunction());
JS_ASSERT(asFunctionBox()->function() == function);
}
FunctionBox *
ObjectBox::asFunctionBox()
{
JS_ASSERT(isFunctionBox());
return static_cast<FunctionBox *>(this);
}
void

View File

@ -1503,7 +1503,7 @@ class ObjectBox {
ObjectBox(JSObject *object, ObjectBox *traceLink);
bool isFunctionBox() { return object->isFunction(); }
FunctionBox *asFunctionBox() { JS_ASSERT(isFunctionBox()); return (FunctionBox *)(this); }
FunctionBox *asFunctionBox();
void trace(JSTracer *trc);
protected:

View File

@ -154,7 +154,7 @@ ParseContext::define(JSContext *cx, PropertyName *name, ParseNode *pn, Definitio
Definition *dn = (Definition *)pn;
switch (kind) {
case Definition::ARG:
JS_ASSERT(sc->isFunction);
JS_ASSERT(sc->isFunctionBox());
dn->setOp(JSOP_GETARG);
dn->pn_dflags |= PND_BOUND;
if (!dn->pn_cookie.set(cx, staticLevel, args_.length()))
@ -169,7 +169,7 @@ ParseContext::define(JSContext *cx, PropertyName *name, ParseNode *pn, Definitio
case Definition::CONST:
case Definition::VAR:
if (sc->isFunction) {
if (sc->isFunctionBox()) {
dn->setOp(JSOP_GETLOCAL);
dn->pn_dflags |= PND_BOUND;
if (!dn->pn_cookie.set(cx, staticLevel, vars_.length()))
@ -216,7 +216,7 @@ ParseContext::updateDecl(JSAtom *atom, ParseNode *pn)
Definition *newDecl = (Definition *)pn;
decls_.updateFirst(atom, newDecl);
if (!sc->isFunction) {
if (!sc->isFunctionBox()) {
JS_ASSERT(newDecl->isFreeVar());
return;
}
@ -285,7 +285,7 @@ AppendPackedBindings(const ParseContext *pc, const DeclVector &vec, Binding *dst
bool
ParseContext::generateFunctionBindings(JSContext *cx, InternalHandle<Bindings*> bindings) const
{
JS_ASSERT(sc->isFunction);
JS_ASSERT(sc->isFunctionBox());
unsigned count = args_.length() + vars_.length();
Binding *packedBindings = cx->tempLifoAlloc().newArrayUninitialized<Binding>(count);
@ -303,7 +303,7 @@ ParseContext::generateFunctionBindings(JSContext *cx, InternalHandle<Bindings*>
return false;
}
FunctionBox *funbox = sc->asFunbox();
FunctionBox *funbox = sc->asFunctionBox();
if (bindings->hasAnyAliasedBindings() || funbox->hasExtensibleScope())
funbox->function()->setIsHeavyweight();
@ -373,7 +373,7 @@ Parser::newObjectBox(JSObject *obj)
FunctionBox::FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fun,
ParseContext *outerpc, bool strict)
: ObjectBox(fun, traceListHead),
SharedContext(cx, /* isFunction = */ true, strict),
SharedContext(cx, strict),
bindings(),
bufStart(0),
bufEnd(0),
@ -394,7 +394,7 @@ FunctionBox::FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fu
// outerpc->parsingWith is true.
inWith = true;
} else if (!outerpc->sc->isFunction) {
} else if (!outerpc->sc->isFunctionBox()) {
// This covers the case where a function is nested within an eval()
// within a |with| statement.
//
@ -405,7 +405,7 @@ FunctionBox::FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fu
// ParseContext chain, and |parent| is NULL (again because of the
// eval(), so we have to look at |outerpc|'s scopeChain.
//
JSObject *scope = outerpc->sc->asGlobal()->scopeChain();
JSObject *scope = outerpc->sc->asGlobalSharedContext()->scopeChain();
while (scope) {
if (scope->isWith())
inWith = true;
@ -419,7 +419,7 @@ FunctionBox::FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fu
//
// In this case, the inner anonymous function needs to inherit the
// setting of |inWith| from the outer one.
FunctionBox *parent = outerpc->sc->asFunbox();
FunctionBox *parent = outerpc->sc->asFunctionBox();
if (parent && parent->inWith)
inWith = true;
}
@ -629,7 +629,7 @@ ReportBadReturn(JSContext *cx, Parser *parser, ParseNode *pn, Parser::Reporter r
unsigned errnum, unsigned anonerrnum)
{
JSAutoByteString name;
JSAtom *atom = parser->pc->sc->asFunbox()->function()->atom();
JSAtom *atom = parser->pc->sc->asFunctionBox()->function()->atom();
if (atom) {
if (!js_AtomToPrintableString(cx, atom, &name))
return false;
@ -642,7 +642,7 @@ ReportBadReturn(JSContext *cx, Parser *parser, ParseNode *pn, Parser::Reporter r
static bool
CheckFinalReturn(JSContext *cx, Parser *parser, ParseNode *pn)
{
JS_ASSERT(parser->pc->sc->isFunction);
JS_ASSERT(parser->pc->sc->isFunctionBox());
return HasFinalReturn(pn) == ENDS_IN_RETURN ||
ReportBadReturn(cx, parser, pn, &Parser::reportStrictWarning,
JSMSG_NO_RETURN_VALUE, JSMSG_ANON_NO_RETURN_VALUE);
@ -739,7 +739,7 @@ Parser::standaloneFunctionBody(HandleFunction fun, const AutoNameVector &formals
ParseNode *
Parser::functionBody(FunctionBodyType type)
{
JS_ASSERT(pc->sc->isFunction);
JS_ASSERT(pc->sc->isFunctionBox());
JS_ASSERT(!pc->funHasReturnExpr && !pc->funHasReturnVoid);
ParseNode *pn;
@ -755,7 +755,7 @@ Parser::functionBody(FunctionBodyType type)
if (!pn->pn_kid) {
pn = NULL;
} else {
if (pc->sc->asFunbox()->isGenerator()) {
if (pc->sc->asFunctionBox()->isGenerator()) {
ReportBadReturn(context, this, pn, &Parser::reportError,
JSMSG_BAD_GENERATOR_RETURN,
JSMSG_BAD_ANON_GENERATOR_RETURN);
@ -822,7 +822,7 @@ Parser::functionBody(FunctionBodyType type)
Definition *maybeArgDef = pc->decls().lookupFirst(arguments);
bool argumentsHasBinding = !!maybeArgDef;
bool argumentsHasLocalBinding = maybeArgDef && maybeArgDef->kind() != Definition::ARG;
bool hasRest = pc->sc->asFunbox()->function()->hasRest();
bool hasRest = pc->sc->asFunctionBox()->function()->hasRest();
if (hasRest && argumentsHasLocalBinding) {
reportError(NULL, JSMSG_ARGUMENTS_AND_REST);
return NULL;
@ -849,7 +849,7 @@ Parser::functionBody(FunctionBodyType type)
* arguments object. (Also see the flags' comments in ContextFlags.)
*/
if (argumentsHasLocalBinding) {
FunctionBox *funbox = pc->sc->asFunbox();
FunctionBox *funbox = pc->sc->asFunctionBox();
funbox->setArgumentsHasLocalBinding();
/* Dynamic scope access destroys all hope of optimization. */
@ -1075,7 +1075,7 @@ Parser::newFunction(ParseContext *pc, HandleAtom atom, FunctionSyntaxKind kind)
pc = pc->parent;
RootedObject parent(context);
parent = pc->sc->isFunction ? NULL : pc->sc->asGlobal()->scopeChain();
parent = pc->sc->isFunctionBox() ? NULL : pc->sc->asGlobalSharedContext()->scopeChain();
RootedFunction fun(context);
JSFunction::Flags flags = (kind == Expression)
@ -1143,7 +1143,7 @@ LeaveFunction(ParseNode *fn, Parser *parser, PropertyName *funName = NULL,
pc->blockidGen = funpc->blockidGen;
FunctionBox *funbox = fn->pn_funbox;
JS_ASSERT(funbox == funpc->sc->asFunbox());
JS_ASSERT(funbox == funpc->sc->asFunctionBox());
if (!pc->topStmt || pc->topStmt->type == STMT_BLOCK)
fn->pn_dflags |= PND_BLOCKCHILD;
@ -1330,7 +1330,7 @@ static bool
BindDestructuringArg(JSContext *cx, BindData *data, HandlePropertyName name, Parser *parser)
{
ParseContext *pc = parser->pc;
JS_ASSERT(pc->sc->isFunction);
JS_ASSERT(pc->sc->isFunctionBox());
if (pc->decls().lookupFirst(name)) {
parser->reportError(NULL, JSMSG_BAD_DUP_ARGS);
@ -1352,7 +1352,7 @@ Parser::functionArguments(ParseNode **listp, ParseNode* funcpn, bool &hasRest)
return false;
}
FunctionBox *funbox = pc->sc->asFunbox();
FunctionBox *funbox = pc->sc->asFunctionBox();
funbox->bufStart = tokenStream.offsetOfToken(tokenStream.currentToken());
hasRest = false;
@ -1583,13 +1583,13 @@ Parser::functionDef(HandlePropertyName funName, const TokenStream::Position &sta
*/
if (bodyLevel) {
JS_ASSERT(pn->functionIsHoisted());
JS_ASSERT_IF(pc->sc->isFunction, !pn->pn_cookie.isFree());
JS_ASSERT_IF(!pc->sc->isFunction, pn->pn_cookie.isFree());
JS_ASSERT_IF(pc->sc->isFunctionBox(), !pn->pn_cookie.isFree());
JS_ASSERT_IF(!pc->sc->isFunctionBox(), pn->pn_cookie.isFree());
} else {
JS_ASSERT(!pc->sc->strict);
JS_ASSERT(pn->pn_cookie.isFree());
if (pc->sc->isFunction) {
FunctionBox *funbox = pc->sc->asFunbox();
if (pc->sc->isFunctionBox()) {
FunctionBox *funbox = pc->sc->asFunctionBox();
funbox->setMightAliasLocals();
funbox->setHasExtensibleScope();
}
@ -1876,7 +1876,7 @@ Parser::maybeParseDirective(ParseNode *pn, bool *cont)
// had "use strict";
pc->sc->setExplicitUseStrict();
if (!pc->sc->strict) {
if (pc->sc->isFunction) {
if (pc->sc->isFunctionBox()) {
// Request that this function be reparsed as strict.
pc->funBecameStrict = true;
return false;
@ -1956,7 +1956,7 @@ Parser::statements(bool *hasFunctionStmt)
* General deoptimization was done in functionDef, here we just
* need to tell TOK_LC in Parser::statement to add braces.
*/
JS_ASSERT_IF(pc->sc->isFunction, pc->sc->asFunbox()->hasExtensibleScope());
JS_ASSERT_IF(pc->sc->isFunctionBox(), pc->sc->asFunctionBox()->hasExtensibleScope());
if (hasFunctionStmt)
*hasFunctionStmt = true;
}
@ -2156,8 +2156,8 @@ BindVarOrConst(JSContext *cx, BindData *data, HandlePropertyName name, Parser *p
if (stmt && stmt->type == STMT_WITH) {
pn->pn_dflags |= PND_DEOPTIMIZED;
if (pc->sc->isFunction)
pc->sc->asFunbox()->setMightAliasLocals();
if (pc->sc->isFunctionBox())
pc->sc->asFunctionBox()->setMightAliasLocals();
return true;
}
@ -2528,7 +2528,7 @@ ParseNode *
Parser::returnOrYield(bool useAssignExpr)
{
TokenKind tt = tokenStream.currentToken().type;
if (!pc->sc->isFunction) {
if (!pc->sc->isFunctionBox()) {
reportError(NULL, JSMSG_BAD_RETURN_OR_YIELD,
(tt == TOK_RETURN) ? js_return_str : js_yield_str);
return NULL;
@ -2545,7 +2545,7 @@ Parser::returnOrYield(bool useAssignExpr)
* a |for| token, so we have to delay flagging the current function.
*/
if (pc->parenDepth == 0) {
pc->sc->asFunbox()->setIsGenerator();
pc->sc->asFunctionBox()->setIsGenerator();
} else {
pc->yieldCount++;
pc->yieldNode = pn;
@ -2582,7 +2582,7 @@ Parser::returnOrYield(bool useAssignExpr)
pc->funHasReturnVoid = true;
}
if (pc->funHasReturnExpr && pc->sc->asFunbox()->isGenerator()) {
if (pc->funHasReturnExpr && pc->sc->asFunctionBox()->isGenerator()) {
/* As in Python (see PEP-255), disallow return v; in generators. */
ReportBadReturn(context, this, pn, &Parser::reportError, JSMSG_BAD_GENERATOR_RETURN,
JSMSG_BAD_ANON_GENERATOR_RETURN);
@ -4836,11 +4836,11 @@ GenexpGuard::maybeNoteGenerator(ParseNode *pn)
{
ParseContext *pc = parser->pc;
if (pc->yieldCount > 0) {
if (!pc->sc->isFunction) {
if (!pc->sc->isFunctionBox()) {
parser->reportError(NULL, JSMSG_BAD_RETURN_OR_YIELD, js_yield_str);
return false;
}
pc->sc->asFunbox()->setIsGenerator();
pc->sc->asFunctionBox()->setIsGenerator();
if (pc->funHasReturnExpr) {
/* At the time we saw the yield, we might not have set isGenerator yet. */
ReportBadReturn(pc->sc->context, parser, pn, &Parser::reportError,
@ -5337,8 +5337,8 @@ Parser::generatorExpr(ParseNode *kid)
* kid and could be removed from pc->sc.
*/
genFunbox->anyCxFlags = outerpc->sc->anyCxFlags;
if (outerpc->sc->isFunction)
genFunbox->funCxFlags = outerpc->sc->asFunbox()->funCxFlags;
if (outerpc->sc->isFunctionBox())
genFunbox->funCxFlags = outerpc->sc->asFunctionBox()->funCxFlags;
genFunbox->setIsGenerator();
genFunbox->inGenexpLambda = true;
@ -5664,8 +5664,8 @@ Parser::memberExpr(bool allowCallSyntax)
* In non-strict mode code, direct calls to eval can add
* variables to the call object.
*/
if (pc->sc->isFunction && !pc->sc->strict)
pc->sc->asFunbox()->setHasExtensibleScope();
if (pc->sc->isFunctionBox() && !pc->sc->strict)
pc->sc->asFunctionBox()->setHasExtensibleScope();
}
} else if (lhs->isOp(JSOP_GETPROP)) {
/* Select JSOP_FUNAPPLY given foo.apply(...). */

View File

@ -81,12 +81,12 @@ struct ParseContext /* tree context for semantic checks */
}
uint32_t numArgs() const {
JS_ASSERT(sc->isFunction);
JS_ASSERT(sc->isFunctionBox());
return args_.length();
}
uint32_t numVars() const {
JS_ASSERT(sc->isFunction);
JS_ASSERT(sc->isFunctionBox());
return vars_.length();
}

View File

@ -15,9 +15,8 @@ namespace js {
namespace frontend {
inline
SharedContext::SharedContext(JSContext *cx, bool isFun, bool strict)
SharedContext::SharedContext(JSContext *cx, bool strict)
: context(cx),
isFunction(isFun),
anyCxFlags(),
strict(strict)
{
@ -30,21 +29,21 @@ SharedContext::needStrictChecks()
}
inline GlobalSharedContext *
SharedContext::asGlobal()
SharedContext::asGlobalSharedContext()
{
JS_ASSERT(!isFunction);
JS_ASSERT(isGlobalSharedContext());
return static_cast<GlobalSharedContext*>(this);
}
inline FunctionBox *
SharedContext::asFunbox()
SharedContext::asFunctionBox()
{
JS_ASSERT(isFunction);
JS_ASSERT(isFunctionBox());
return static_cast<FunctionBox*>(this);
}
GlobalSharedContext::GlobalSharedContext(JSContext *cx, JSObject *scopeChain, bool strict)
: SharedContext(cx, /* isFunction = */ false, strict),
: SharedContext(cx, strict),
scopeChain_(cx, scopeChain)
{
}

View File

@ -138,19 +138,18 @@ class SharedContext
{
public:
JSContext *const context;
const bool isFunction; /* true for function code, false for
global code */
AnyContextFlags anyCxFlags;
bool strict;
// If it's function code, funbox must be non-NULL and scopeChain must be NULL.
// If it's global code, funbox must be NULL.
inline SharedContext(JSContext *cx, bool isFun, bool strict);
inline SharedContext(JSContext *cx, bool strict);
inline GlobalSharedContext *asGlobal();
inline FunctionBox *asFunbox();
virtual ObjectBox *toObjectBox() = 0;
inline bool isGlobalSharedContext() { return toObjectBox() == NULL; }
inline bool isFunctionBox() { return toObjectBox() && toObjectBox()->isFunctionBox(); }
inline GlobalSharedContext *asGlobalSharedContext();
inline FunctionBox *asFunctionBox();
bool hasExplicitUseStrict() const { return anyCxFlags.hasExplicitUseStrict; }
bool bindingsAccessedDynamically() const { return anyCxFlags.bindingsAccessedDynamically; }
@ -170,6 +169,7 @@ class GlobalSharedContext : public SharedContext
public:
inline GlobalSharedContext(JSContext *cx, JSObject *scopeChain, bool strict);
ObjectBox *toObjectBox() { return NULL; }
JSObject *scopeChain() const { return scopeChain_; }
};
@ -189,6 +189,7 @@ class FunctionBox : public ObjectBox, public SharedContext
FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fun, ParseContext *pc,
bool strict);
ObjectBox *toObjectBox() { return this; }
JSFunction *function() const { return object->toFunction(); }
bool isGenerator() const { return funCxFlags.isGenerator; }

View File

@ -1750,7 +1750,7 @@ JSScript::fullyInitFromEmitter(JSContext *cx, Handle<JSScript*> script, Bytecode
script->mainOffset = prologLength;
PodCopy<jsbytecode>(script->code, bce->prologBase(), prologLength);
PodCopy<jsbytecode>(script->main(), bce->base(), mainLength);
uint32_t nfixed = bce->sc->isFunction ? script->bindings.numVars() : 0;
uint32_t nfixed = bce->sc->isFunctionBox() ? script->bindings.numVars() : 0;
JS_ASSERT(nfixed < SLOTNO_LIMIT);
script->nfixed = uint16_t(nfixed);
InitAtomMap(cx, bce->atomIndices.getMap(), script->atoms);
@ -1768,7 +1768,7 @@ JSScript::fullyInitFromEmitter(JSContext *cx, Handle<JSScript*> script, Bytecode
}
script->nslots = script->nfixed + bce->maxStackDepth;
FunctionBox *funbox = bce->sc->isFunction ? bce->sc->asFunbox() : NULL;
FunctionBox *funbox = bce->sc->isFunctionBox() ? bce->sc->asFunctionBox() : NULL;
if (!FinishTakingSrcNotes(cx, bce, script->notes()))
return false;