From 567f771d2540f2530a36e39926a524227f2ae56f Mon Sep 17 00:00:00 2001 From: Eddy Bruel Date: Fri, 18 Jan 2013 14:21:32 +0100 Subject: [PATCH] Bug 568593 - Refactor SharedContext; r=jorendorff --- js/src/frontend/BytecodeEmitter.cpp | 44 +++++++++--------- js/src/frontend/ParseNode.cpp | 8 ++++ js/src/frontend/ParseNode.h | 2 +- js/src/frontend/Parser.cpp | 72 ++++++++++++++--------------- js/src/frontend/Parser.h | 4 +- js/src/frontend/SharedContext-inl.h | 13 +++--- js/src/frontend/SharedContext.h | 17 +++---- js/src/jsscript.cpp | 4 +- 8 files changed, 86 insertions(+), 78 deletions(-) diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 4eabc13bfe5..45a9ae4fd0d 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -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; diff --git a/js/src/frontend/ParseNode.cpp b/js/src/frontend/ParseNode.cpp index e1ee182ce10..386aa9933f8 100644 --- a/js/src/frontend/ParseNode.cpp +++ b/js/src/frontend/ParseNode.cpp @@ -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(this); } void diff --git a/js/src/frontend/ParseNode.h b/js/src/frontend/ParseNode.h index 50029bd5315..c59b72a11f6 100644 --- a/js/src/frontend/ParseNode.h +++ b/js/src/frontend/ParseNode.h @@ -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: diff --git a/js/src/frontend/Parser.cpp b/js/src/frontend/Parser.cpp index d0604aaab8f..386725b53be 100644 --- a/js/src/frontend/Parser.cpp +++ b/js/src/frontend/Parser.cpp @@ -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) const { - JS_ASSERT(sc->isFunction); + JS_ASSERT(sc->isFunctionBox()); unsigned count = args_.length() + vars_.length(); Binding *packedBindings = cx->tempLifoAlloc().newArrayUninitialized(count); @@ -303,7 +303,7 @@ ParseContext::generateFunctionBindings(JSContext *cx, InternalHandle 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(...). */ diff --git a/js/src/frontend/Parser.h b/js/src/frontend/Parser.h index 8b711afe9d6..3bfd77acbfc 100644 --- a/js/src/frontend/Parser.h +++ b/js/src/frontend/Parser.h @@ -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(); } diff --git a/js/src/frontend/SharedContext-inl.h b/js/src/frontend/SharedContext-inl.h index 0ecfee4c1d3..e1365119f69 100644 --- a/js/src/frontend/SharedContext-inl.h +++ b/js/src/frontend/SharedContext-inl.h @@ -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(this); } inline FunctionBox * -SharedContext::asFunbox() +SharedContext::asFunctionBox() { - JS_ASSERT(isFunction); + JS_ASSERT(isFunctionBox()); return static_cast(this); } GlobalSharedContext::GlobalSharedContext(JSContext *cx, JSObject *scopeChain, bool strict) - : SharedContext(cx, /* isFunction = */ false, strict), + : SharedContext(cx, strict), scopeChain_(cx, scopeChain) { } diff --git a/js/src/frontend/SharedContext.h b/js/src/frontend/SharedContext.h index a5a137d87ba..7659637d4f6 100644 --- a/js/src/frontend/SharedContext.h +++ b/js/src/frontend/SharedContext.h @@ -137,20 +137,19 @@ class GlobalSharedContext; class SharedContext { public: - JSContext *const context; - - const bool isFunction; /* true for function code, false for - global code */ + JSContext *const context; 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; } diff --git a/js/src/jsscript.cpp b/js/src/jsscript.cpp index 3643d33aec1..86dc098f204 100644 --- a/js/src/jsscript.cpp +++ b/js/src/jsscript.cpp @@ -1750,7 +1750,7 @@ JSScript::fullyInitFromEmitter(JSContext *cx, Handle script, Bytecode script->mainOffset = prologLength; PodCopy(script->code, bce->prologBase(), prologLength); PodCopy(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 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;