Bug 568593 - Refactor SharedContext; r=jorendorff

This commit is contained in:
Eddy Bruel 2013-01-18 14:21:32 +01:00
Родитель 751c2cf809
Коммит 9021fcbf06
8 изменённых файлов: 86 добавлений и 78 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -1750,7 +1750,7 @@ JSScript::fullyInitFromEmitter(JSContext *cx, Handle<JSScript*> script, Bytecode
script->mainOffset = prologLength; script->mainOffset = prologLength;
PodCopy<jsbytecode>(script->code, bce->prologBase(), prologLength); PodCopy<jsbytecode>(script->code, bce->prologBase(), prologLength);
PodCopy<jsbytecode>(script->main(), bce->base(), mainLength); 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); JS_ASSERT(nfixed < SLOTNO_LIMIT);
script->nfixed = uint16_t(nfixed); script->nfixed = uint16_t(nfixed);
InitAtomMap(cx, bce->atomIndices.getMap(), script->atoms); 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; 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())) if (!FinishTakingSrcNotes(cx, bce, script->notes()))
return false; return false;