Bug 759246 (part 3) - Initialize more SharedContext stuff via the constructor. r=jorendorff.

--HG--
extra : rebase_source : 8ffdf29429f0606181bf04c00d57d13bbb650b8d
This commit is contained in:
Nicholas Nethercote 2012-05-28 21:50:52 -07:00
parent a4d19f28d9
commit 4cde2c6b53
9 changed files with 130 additions and 145 deletions

View File

@ -99,7 +99,7 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
if (!parser.init())
return NULL;
SharedContext sc(cx, /* inFunction = */ false);
SharedContext sc(cx, scopeChain, /* fun = */ NULL, /* funbox = */ NULL);
TreeContext tc(&parser, &sc);
if (!tc.init())
@ -118,7 +118,6 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
JS_ASSERT_IF(globalObj, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalObj->getClass()));
GlobalScope globalScope(cx, globalObj);
sc.setScopeChain(scopeChain);
bce.globalScope = &globalScope;
if (!SetStaticLevel(&sc, staticLevel))
return NULL;
@ -264,7 +263,8 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
if (!parser.init())
return false;
SharedContext funsc(cx, /* inFunction = */ true);
JS_ASSERT(fun);
SharedContext funsc(cx, /* scopeChain = */ NULL, fun, /* funbox = */ NULL);
TreeContext funtc(&parser, &funsc);
if (!funtc.init())
@ -275,7 +275,6 @@ frontend::CompileFunctionBody(JSContext *cx, JSFunction *fun,
if (!funbce.init())
return false;
funsc.setFunction(fun);
funsc.bindings.transfer(cx, bindings);
fun->setArgCount(funsc.bindings.numArgs());
if (!GenerateBlockId(&funsc, funsc.bodyid))

View File

@ -660,7 +660,7 @@ LookupCompileTimeConstant(JSContext *cx, BytecodeEmitter *bce, JSAtom *atom, Val
*/
constp->setMagic(JS_NO_CONSTANT);
do {
if (bce->sc->inFunction || bce->parser->compileAndGo) {
if (bce->sc->inFunction() || bce->parser->compileAndGo) {
/* XXX this will need revising if 'const' becomes block-scoped. */
StmtInfo *stmt = LexicalLookup(bce->sc, atom, NULL);
if (stmt)
@ -679,7 +679,7 @@ LookupCompileTimeConstant(JSContext *cx, BytecodeEmitter *bce, JSAtom *atom, Val
* with object or catch variable; nor can prop's value be changed,
* nor can prop be deleted.
*/
if (bce->sc->inFunction) {
if (bce->sc->inFunction()) {
if (bce->sc->bindings.hasBinding(cx, atom))
break;
} else {
@ -997,7 +997,7 @@ static int
AdjustBlockSlot(JSContext *cx, BytecodeEmitter *bce, int slot)
{
JS_ASSERT((unsigned) slot < bce->maxStackDepth);
if (bce->sc->inFunction) {
if (bce->sc->inFunction()) {
slot += bce->sc->bindings.numVars();
if ((unsigned) slot >= SLOTNO_LIMIT) {
ReportCompileErrorNumber(cx, bce->tokenStream(), NULL, JSREPORT_ERROR,
@ -1564,7 +1564,13 @@ BytecodeEmitter::needsImplicitThis()
{
if (!parser->compileAndGo)
return true;
if (!sc->inFunction) {
if (sc->inFunction()) {
for (const FunctionBox *funbox = this->sc->funbox(); funbox; funbox = funbox->parent) {
if (funbox->inWith)
return true;
}
} else {
JSObject *scope = sc->scopeChain();
while (scope) {
if (scope->isWith())
@ -1572,10 +1578,7 @@ BytecodeEmitter::needsImplicitThis()
scope = scope->enclosingScope();
}
}
for (const FunctionBox *funbox = this->sc->funbox; funbox; funbox = funbox->parent) {
if (funbox->inWith)
return true;
}
for (StmtInfo *stmt = sc->topStmt; stmt; stmt = stmt->down) {
if (stmt->type == STMT_WITH)
return true;
@ -2630,7 +2633,7 @@ MaybeEmitVarDecl(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *
}
if (JOF_OPTYPE(pn->getOp()) == JOF_ATOM &&
(!bce->sc->inFunction || bce->sc->funIsHeavyweight()))
(!bce->sc->inFunction() || bce->sc->funIsHeavyweight()))
{
bce->switchToProlog();
if (!UpdateLineNumberNotes(cx, bce, pn->pn_pos.begin.lineno))
@ -2640,7 +2643,7 @@ MaybeEmitVarDecl(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *
bce->switchToMain();
}
if (bce->sc->inFunction &&
if (bce->sc->inFunction() &&
JOF_OPTYPE(pn->getOp()) == JOF_LOCAL &&
!pn->isLet() &&
bce->shouldNoteClosedName(pn))
@ -4402,7 +4405,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->inFunction))
: !bce->sc->inFunction()))
{
/* There must be no source note already output for the next op. */
JS_ASSERT(bce->noteCount() == 0 ||
@ -4792,7 +4795,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
* comments in EmitStatementList.
*/
JS_ASSERT(pn->isOp(JSOP_NOP));
JS_ASSERT(bce->sc->inFunction);
JS_ASSERT(bce->sc->inFunction());
return EmitFunctionDefNop(cx, bce, pn->pn_index);
}
@ -4800,20 +4803,18 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
fun->kind() == JSFUN_INTERPRETED);
{
SharedContext sc(cx, /* inFunction = */ true);
FunctionBox *funbox = pn->pn_funbox;
SharedContext sc(cx, /* scopeChain = */ NULL, fun, funbox);
BytecodeEmitter bce2(bce->parser, &sc, pn->pn_pos.begin.lineno,
/* noScriptRval = */ false, /* needsScriptGlobal = */ false);
if (!bce2.init())
return false;
FunctionBox *funbox = pn->pn_funbox;
sc.cxFlags = funbox->cxFlags;
if (bce->sc->funMightAliasLocals())
sc.setFunMightAliasLocals(); // inherit funMightAliasLocals from parent
sc.bindings.transfer(cx, &funbox->bindings);
sc.setFunction(fun);
sc.funbox = funbox;
bce2.parent = bce;
bce2.globalScope = bce->globalScope;
@ -4851,7 +4852,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->inFunction) {
if (!bce->sc->inFunction()) {
JS_ASSERT(!bce->sc->topStmt);
JS_ASSERT(pn->pn_cookie.isFree());
if (pn->pn_cookie.isFree()) {
@ -5137,7 +5138,7 @@ EmitStatement(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
*/
bool wantval = false;
JSBool useful = JS_FALSE;
if (bce->sc->inFunction) {
if (bce->sc->inFunction()) {
JS_ASSERT(!bce->noScriptRval);
} else {
useful = wantval = !bce->noScriptRval;
@ -5825,7 +5826,7 @@ static bool
EmitDefaults(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{
JS_ASSERT(pn->isKind(PNK_ARGSBODY));
uint16_t ndefaults = bce->sc->funbox->ndefaults;
uint16_t ndefaults = bce->sc->funbox()->ndefaults;
JSFunction *fun = bce->sc->fun();
unsigned nformal = fun->nargs - fun->hasRest();
EMIT_UINT16_IMM_OP(JSOP_ACTUALSFILLED, nformal - ndefaults);
@ -6074,7 +6075,7 @@ frontend::EmitTree(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
#if JS_HAS_GENERATORS
case PNK_YIELD:
JS_ASSERT(bce->sc->inFunction);
JS_ASSERT(bce->sc->inFunction());
if (pn->pn_kid) {
if (!EmitTree(cx, bce, pn->pn_kid))
return JS_FALSE;

View File

@ -163,7 +163,7 @@ struct BytecodeEmitter
}
bool checkSingletonContext() {
if (!parser->compileAndGo || sc->inFunction)
if (!parser->compileAndGo || sc->inFunction())
return false;
for (StmtInfo *stmt = sc->topStmt; stmt; stmt = stmt->down) {
if (STMT_IS_LOOP(stmt))

View File

@ -175,7 +175,7 @@ FunctionBox::FunctionBox(ObjectBox* traceListHead, JSObject *obj, ParseNode *fn,
node(fn),
siblings(tc->functionList),
kids(NULL),
parent(tc->sc->funbox),
parent(tc->sc->inFunction() ? tc->sc->funbox() : NULL),
bindings(tc->sc->context),
level(tc->sc->staticLevel),
ndefaults(0),
@ -192,7 +192,7 @@ FunctionBox::FunctionBox(ObjectBox* traceListHead, JSObject *obj, ParseNode *fn,
break;
}
}
if (!tc->sc->inFunction) {
if (!tc->sc->inFunction()) {
JSObject *scope = tc->sc->scopeChain();
while (scope) {
if (scope->isWith())
@ -267,11 +267,10 @@ Parser::parse(JSObject *chain)
* an object lock before it finishes generating bytecode into a script
* protected from the GC by a root or a stack frame reference.
*/
SharedContext globalsc(context, /* inFunction = */ false);
SharedContext globalsc(context, chain, /* fun = */ NULL, /* funbox = */ NULL);
TreeContext globaltc(this, &globalsc);
if (!globaltc.init())
return NULL;
globalsc.setScopeChain(chain);
if (!GenerateBlockId(&globalsc, globalsc.bodyid))
return NULL;
@ -432,7 +431,7 @@ ReportBadReturn(JSContext *cx, Parser *parser, ParseNode *pn, unsigned flags, un
static JSBool
CheckFinalReturn(JSContext *cx, Parser *parser, ParseNode *pn)
{
JS_ASSERT(parser->tc->sc->inFunction);
JS_ASSERT(parser->tc->sc->inFunction());
return HasFinalReturn(pn) == ENDS_IN_RETURN ||
ReportBadReturn(cx, parser, pn, JSREPORT_WARNING | JSREPORT_STRICT,
JSMSG_NO_RETURN_VALUE, JSMSG_ANON_NO_RETURN_VALUE);
@ -505,7 +504,7 @@ static bool
CheckStrictParameters(JSContext *cx, Parser *parser)
{
SharedContext *sc = parser->tc->sc;
JS_ASSERT(sc->inFunction);
JS_ASSERT(sc->inFunction());
if (!sc->needStrictChecks() || sc->bindings.numArgs() == 0)
return true;
@ -574,7 +573,7 @@ BindLocalVariable(JSContext *cx, SharedContext *sc, ParseNode *pn, BindingKind k
ParseNode *
Parser::functionBody(FunctionBodyType type)
{
JS_ASSERT(tc->sc->inFunction);
JS_ASSERT(tc->sc->inFunction());
StmtInfo stmtInfo(context);
PushStatement(tc->sc, &stmtInfo, STMT_BLOCK, -1);
@ -734,7 +733,7 @@ Parser::functionBody(FunctionBodyType type)
bool
Parser::checkForArgumentsAndRest()
{
JS_ASSERT(!tc->sc->inFunction);
JS_ASSERT(!tc->sc->inFunction());
if (callerFrame && callerFrame->isFunctionFrame() && callerFrame->fun()->hasRest()) {
PropertyName *arguments = context->runtime->atomState.argumentsAtom;
for (AtomDefnRange r = tc->lexdeps->all(); !r.empty(); r.popFront()) {
@ -992,7 +991,7 @@ static JSBool
BindDestructuringArg(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
{
TreeContext *tc = parser->tc;
JS_ASSERT(tc->sc->inFunction);
JS_ASSERT(tc->sc->inFunction());
/*
* NB: Check tc->decls rather than tc->sc->bindings, because destructuring
@ -1048,7 +1047,7 @@ Parser::newFunction(TreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind)
tc = tc->parent;
RootedObject parent(context);
parent = tc->sc->inFunction ? NULL : tc->sc->scopeChain();
parent = tc->sc->inFunction() ? NULL : tc->sc->scopeChain();
RootedFunction fun(context);
fun = js_NewFunction(context, NULL, NULL, 0,
@ -1080,31 +1079,17 @@ MatchOrInsertSemicolon(JSContext *cx, TokenStream *ts)
return JS_TRUE;
}
static FunctionBox *
EnterFunction(ParseNode *fn, Parser *parser, JSAtom *funAtom = NULL,
FunctionSyntaxKind kind = Expression)
static bool
EnterFunction(SharedContext *outersc, SharedContext *funsc)
{
TreeContext *funtc = parser->tc;
TreeContext *outertc = funtc->parent;
JSFunction *fun = parser->newFunction(outertc, funAtom, kind);
if (!fun)
return NULL;
/* Initialize non-default members of funsc. */
funsc->blockidGen = outersc->blockidGen;
if (!GenerateBlockId(funsc, funsc->bodyid))
return false;
if (!SetStaticLevel(funsc, outersc->staticLevel + 1))
return false;
/* Create box for fun->object early to protect against last-ditch GC. */
FunctionBox *funbox = parser->newFunctionBox(fun, fn, outertc);
if (!funbox)
return NULL;
/* Initialize non-default members of funtc->sc. */
funtc->sc->blockidGen = outertc->sc->blockidGen;
if (!GenerateBlockId(funtc->sc, funtc->sc->bodyid))
return NULL;
funtc->sc->setFunction(fun);
funtc->sc->funbox = funbox;
if (!SetStaticLevel(funtc->sc, outertc->sc->staticLevel + 1))
return NULL;
return funbox;
return true;
}
static bool
@ -1293,7 +1278,7 @@ Parser::functionArguments(ParseNode **listp, bool &hasRest)
return false;
argsbody->setOp(JSOP_NOP);
argsbody->makeEmpty();
tc->sc->funbox->node->pn_body = argsbody;
tc->sc->funbox()->node->pn_body = argsbody;
if (!tokenStream.matchToken(TOK_RP)) {
bool hasDefaults = false;
@ -1418,7 +1403,7 @@ Parser::functionArguments(ParseNode **listp, bool &hasRest)
uint16_t slot;
if (!tc->sc->bindings.addArgument(context, name, &slot))
return false;
if (!DefineArg(tc->sc->funbox->node, name, slot, this))
if (!DefineArg(tc->sc->funbox()->node, name, slot, this))
return false;
if (tokenStream.matchToken(TOK_ASSIGN)) {
@ -1430,10 +1415,10 @@ Parser::functionArguments(ParseNode **listp, bool &hasRest)
ParseNode *def_expr = assignExprWithoutYield(JSMSG_YIELD_IN_DEFAULT);
if (!def_expr)
return false;
ParseNode *arg = tc->sc->funbox->node->pn_body->last();
ParseNode *arg = tc->sc->funbox()->node->pn_body->last();
arg->pn_dflags |= PND_DEFAULT;
arg->pn_expr = def_expr;
tc->sc->funbox->ndefaults++;
tc->sc->funbox()->ndefaults++;
} else if (!hasRest && hasDefaults) {
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_NONDEFAULT_FORMAL_AFTER_DEFAULT);
return false;
@ -1552,7 +1537,7 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
* when BytecodeEmitter.cpp's BindNameToSlot can optimize a JSOP_NAME
* into a JSOP_GETLOCAL bytecode).
*/
if (bodyLevel && tc->sc->inFunction) {
if (bodyLevel && tc->sc->inFunction()) {
/*
* Define a local in the outer function so that BindNameToSlot
* can properly optimize accesses. Note that we need a local
@ -1581,21 +1566,27 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
TreeContext *outertc = tc;
RootedFunction fun(context, newFunction(outertc, funName, kind));
if (!fun)
return NULL;
/* Create box for fun->object early to protect against last-ditch GC. */
FunctionBox *funbox = newFunctionBox(fun, pn, outertc);
if (!funbox)
return NULL;
/* Initialize early for possible flags mutation via destructuringExpr. */
SharedContext funsc(context, /* inFunction = */ true);
SharedContext funsc(context, /* scopeChain = */ NULL, fun, funbox);
TreeContext funtc(this, &funsc);
if (!funtc.init())
return NULL;
FunctionBox *funbox = EnterFunction(pn, this, funName, kind);
if (!funbox)
if (!EnterFunction(outertc->sc, &funsc))
return NULL;
if (outertc->sc->inStrictMode())
funsc.setInStrictMode(); // inherit strict mode from parent
RootedFunction fun(context, funbox->function());
/* Now parse formal argument list and compute fun->nargs. */
ParseNode *prelude = NULL;
bool hasRest;
@ -1764,7 +1755,7 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
pn->pn_body->append(body);
pn->pn_body->pn_pos = body->pn_pos;
JS_ASSERT_IF(!outertc->sc->inFunction && bodyLevel && kind == Statement,
JS_ASSERT_IF(!outertc->sc->inFunction() && bodyLevel && kind == Statement,
pn->pn_cookie.isFree());
pn->pn_blockid = outertc->sc->blockid();
@ -2123,7 +2114,7 @@ OuterLet(SharedContext *sc, StmtInfo *stmt, JSAtom *atom)
static bool
BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, SharedContext *sc)
{
JS_ASSERT(sc->inFunction);
JS_ASSERT(sc->inFunction());
ParseNode *pn = data->pn;
JSAtom *name = pn->pn_atom;
@ -2146,7 +2137,7 @@ BindFunctionLocal(JSContext *cx, BindData *data, MultiDeclRange &mdl, SharedCont
}
if (kind == ARGUMENT) {
JS_ASSERT(sc->inFunction);
JS_ASSERT(sc->inFunction());
JS_ASSERT(!mdl.empty() && mdl.front()->kind() == Definition::ARG);
} else {
JS_ASSERT(kind == VARIABLE || kind == CONSTANT);
@ -2299,7 +2290,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
if (data->op == JSOP_DEFCONST)
pn->pn_dflags |= PND_CONST;
if (tc->sc->inFunction)
if (tc->sc->inFunction())
return BindFunctionLocal(cx, data, mdl, tc->sc);
return true;
@ -2355,7 +2346,7 @@ NoteLValue(JSContext *cx, ParseNode *pn, SharedContext *sc, unsigned dflag = PND
* mode, we must have a binding for it in the scope chain; we ensure this
* happens by making such functions heavyweight.
*/
if (sc->inFunction && pn->pn_atom == sc->fun()->atom)
if (sc->inFunction() && pn->pn_atom == sc->fun()->atom)
sc->setFunIsHeavyweight();
}
@ -2691,7 +2682,7 @@ ParseNode *
Parser::returnOrYield(bool useAssignExpr)
{
TokenKind tt = tokenStream.currentToken().type;
if (!tc->sc->inFunction) {
if (!tc->sc->inFunction()) {
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_BAD_RETURN_OR_YIELD,
(tt == TOK_RETURN) ? js_return_str : js_yield_str);
return NULL;
@ -5007,7 +4998,7 @@ GenexpGuard::maybeNoteGenerator(ParseNode *pn)
TreeContext *tc = parser->tc;
if (tc->yieldCount > 0) {
tc->sc->setFunIsGenerator();
if (!tc->sc->inFunction) {
if (!tc->sc->inFunction()) {
parser->reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_BAD_RETURN_OR_YIELD,
js_yield_str);
return false;
@ -5112,7 +5103,7 @@ CompExprTransplanter::transplant(ParseNode *pn)
funbox->level = tc->sc->staticLevel + funcLevel;
if (++funcLevel == 1 && genexp) {
FunctionBox *parent = tc->sc->funbox;
FunctionBox *parent = tc->sc->funbox();
FunctionBox **funboxp = &tc->parent->functionList;
while (*funboxp != funbox)
@ -5499,13 +5490,22 @@ Parser::generatorExpr(ParseNode *kid)
{
TreeContext *outertc = tc;
SharedContext gensc(context, /* inFunction = */ true);
RootedFunction fun(context, newFunction(outertc, /* atom = */ NULL, Expression));
if (!fun)
return NULL;
/* Create box for fun->object early to protect against last-ditch GC. */
FunctionBox *funbox = newFunctionBox(fun, genfn, outertc);
if (!funbox)
return NULL;
SharedContext gensc(context, /* scopeChain = */ NULL, fun, funbox);
TreeContext gentc(this, &gensc);
if (!gentc.init())
return NULL;
FunctionBox *funbox = EnterFunction(genfn, this);
if (!funbox)
if (!EnterFunction(outertc->sc, &gensc))
return NULL;
/*
@ -6477,12 +6477,11 @@ Parser::parseXMLText(JSObject *chain, bool allowList)
* lightweight function activation, or if its scope chain doesn't match
* the one passed to us.
*/
SharedContext xmlsc(context, /* inFunction = */ false);
SharedContext xmlsc(context, chain, /* fun = */ NULL, /* funbox = */ NULL);
TreeContext xmltc(this, &xmlsc);
if (!xmltc.init())
return NULL;
JS_ASSERT(!xmlsc.inStrictMode());
xmlsc.setScopeChain(chain);
/* Set XML-only mode to turn off special treatment of {expr} in XML. */
tokenStream.setXMLOnlyMode();

View File

@ -168,7 +168,7 @@ frontend::AnalyzeFunctions(Parser *parser)
return false;
bool isDirectEval = !!parser->callerFrame;
bool isHeavyweight = false;
SetFunctionKinds(tc->functionList, &isHeavyweight, sc->inFunction, isDirectEval);
SetFunctionKinds(tc->functionList, &isHeavyweight, sc->inFunction(), isDirectEval);
if (isHeavyweight)
sc->setFunIsHeavyweight();
return true;

View File

@ -16,23 +16,24 @@
namespace js {
inline
SharedContext::SharedContext(JSContext *cx, bool inFunction)
SharedContext::SharedContext(JSContext *cx, JSObject *scopeChain, JSFunction *fun,
FunctionBox *funbox)
: context(cx),
bodyid(0),
blockidGen(0),
topStmt(NULL),
topScopeStmt(NULL),
blockChain(cx),
fun_(cx),
scopeChain_(cx),
fun_(cx, fun),
funbox_(funbox),
scopeChain_(cx, scopeChain),
staticLevel(0),
funbox(NULL),
bindings(cx),
bindingsRoot(cx, &bindings),
inFunction(inFunction),
inForInit(false),
cxFlags(cx)
{
JS_ASSERT((fun && !scopeChain_) || (!fun && !funbox));
}
inline unsigned

View File

@ -43,8 +43,7 @@ bool
frontend::GenerateBlockId(SharedContext *sc, uint32_t &blockid)
{
if (sc->blockidGen == JS_BIT(20)) {
JS_ReportErrorNumber(sc->context, js_GetErrorMessage, NULL,
JSMSG_NEED_DIET, "program");
JS_ReportErrorNumber(sc->context, js_GetErrorMessage, NULL, JSMSG_NEED_DIET, "program");
return false;
}
blockid = sc->blockidGen++;

View File

@ -61,10 +61,6 @@ class ContextFlags {
//
bool bindingsAccessedDynamically:1;
// The |fun*| flags are only relevant if |inFunction| is true. Due to
// sloppiness, however, some are set in cases where |inFunction| is
// false.
// The function needs Call object per call.
bool funIsHeavyweight:1;
@ -145,66 +141,63 @@ struct SharedContext {
chain when in head of let block/expr) */
private:
RootedFunction fun_; /* function to store argument and variable
names when inFunction is set */
RootedObject scopeChain_; /* scope chain object for the script */
const RootedFunction fun_; /* function to store argument and variable
names when it's a function's context */
FunctionBox *const funbox_; /* null or box for function we're compiling
if inFunction() is true and not in
js::frontend::CompileFunctionBody */
const RootedObject scopeChain_; /* scope chain object for the script */
public:
unsigned staticLevel; /* static compilation unit nesting level */
FunctionBox *funbox; /* null or box for function we're compiling
if inFunction is set and not in
js::frontend::CompileFunctionBody */
Bindings bindings; /* bindings in this code, including
arguments if we're compiling a function */
Bindings::AutoRooter bindingsRoot; /* root for stack allocated bindings. */
const bool inFunction:1; /* parsing/emitting inside function body */
bool inForInit:1; /* parsing/emitting init expr of for; exclude 'in' */
ContextFlags cxFlags;
inline SharedContext(JSContext *cx, bool inFunction);
// If it's function code, fun must be non-NULL and scopeChain must be NULL.
// If it's global code, fun and funbox must be NULL.
inline SharedContext(JSContext *cx, JSObject *scopeChain, JSFunction *fun, FunctionBox *funbox);
bool inStrictMode() const { return cxFlags.inStrictMode; }
bool bindingsAccessedDynamically() const { return cxFlags.bindingsAccessedDynamically; }
bool funIsHeavyweight() const { return cxFlags.funIsHeavyweight; }
bool funIsGenerator() const { return cxFlags.funIsGenerator; }
bool funMightAliasLocals() const { return cxFlags.funMightAliasLocals; }
bool funHasExtensibleScope() const { return cxFlags.funHasExtensibleScope; }
bool funArgumentsHasLocalBinding() const { return cxFlags.funArgumentsHasLocalBinding; }
bool funDefinitelyNeedsArgsObj() const { return cxFlags.funDefinitelyNeedsArgsObj; }
// In theory, |fun*| flags are only relevant if |inFunction()| is true.
// However, we get and set in some cases where |inFunction()| is false,
// which is why |INFUNC| doesn't appear in all of the fun* and setFun*
// functions below.
#define INFUNC JS_ASSERT(inFunction())
void setInStrictMode() { cxFlags.inStrictMode = true; }
void setBindingsAccessedDynamically() { cxFlags.bindingsAccessedDynamically = true; }
void setFunIsHeavyweight() { cxFlags.funIsHeavyweight = true; }
void setFunIsGenerator() { cxFlags.funIsGenerator = true; }
void setFunMightAliasLocals() { cxFlags.funMightAliasLocals = true; }
void setFunHasExtensibleScope() { cxFlags.funHasExtensibleScope = true; }
void setFunArgumentsHasLocalBinding() { cxFlags.funArgumentsHasLocalBinding = true; }
bool inStrictMode() const { return cxFlags.inStrictMode; }
bool bindingsAccessedDynamically() const { return cxFlags.bindingsAccessedDynamically; }
bool funIsHeavyweight() const { INFUNC; return cxFlags.funIsHeavyweight; }
bool funIsGenerator() const { INFUNC; return cxFlags.funIsGenerator; }
bool funMightAliasLocals() const { return cxFlags.funMightAliasLocals; }
bool funHasExtensibleScope() const { return cxFlags.funHasExtensibleScope; }
bool funArgumentsHasLocalBinding() const { INFUNC; return cxFlags.funArgumentsHasLocalBinding; }
bool funDefinitelyNeedsArgsObj() const { INFUNC; return cxFlags.funDefinitelyNeedsArgsObj; }
void setInStrictMode() { cxFlags.inStrictMode = true; }
void setBindingsAccessedDynamically() { cxFlags.bindingsAccessedDynamically = true; }
void setFunIsHeavyweight() { cxFlags.funIsHeavyweight = true; }
void setFunIsGenerator() { INFUNC; cxFlags.funIsGenerator = true; }
void setFunMightAliasLocals() { cxFlags.funMightAliasLocals = true; }
void setFunHasExtensibleScope() { cxFlags.funHasExtensibleScope = true; }
void setFunArgumentsHasLocalBinding() { INFUNC; cxFlags.funArgumentsHasLocalBinding = true; }
void setFunDefinitelyNeedsArgsObj() { JS_ASSERT(cxFlags.funArgumentsHasLocalBinding);
cxFlags.funDefinitelyNeedsArgsObj = true; }
INFUNC; cxFlags.funDefinitelyNeedsArgsObj = true; }
#undef INFUNC
unsigned argumentsLocalSlot() const;
JSFunction *fun() const {
JS_ASSERT(inFunction);
return fun_;
}
void setFunction(JSFunction *fun) {
JS_ASSERT(inFunction);
fun_ = fun;
}
JSObject *scopeChain() const {
JS_ASSERT(!inFunction);
return scopeChain_;
}
void setScopeChain(JSObject *scopeChain) {
JS_ASSERT(!inFunction);
scopeChain_ = scopeChain;
}
bool inFunction() const { return !!fun_; }
JSFunction *fun() const { JS_ASSERT(inFunction()); return fun_; }
FunctionBox *funbox() const { JS_ASSERT(inFunction()); return funbox_; }
JSObject *scopeChain() const { JS_ASSERT(!inFunction()); return scopeChain_; }
unsigned blockid();

View File

@ -1246,7 +1246,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
script->mainOffset = prologLength;
PodCopy<jsbytecode>(script->code, bce->prologBase(), prologLength);
PodCopy<jsbytecode>(script->main(), bce->base(), mainLength);
nfixed = bce->sc->inFunction ? bce->sc->bindings.numVars() : 0;
nfixed = bce->sc->inFunction() ? bce->sc->bindings.numVars() : 0;
JS_ASSERT(nfixed < SLOTNO_LIMIT);
script->nfixed = uint16_t(nfixed);
InitAtomMap(cx, bce->atomIndices.getMap(), script->atoms);
@ -1309,7 +1309,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
script->debugMode = true;
#endif
if (bce->sc->inFunction) {
if (bce->sc->inFunction()) {
if (bce->sc->funArgumentsHasLocalBinding()) {
// This must precede the script->bindings.transfer() call below.
script->setArgumentsHasLocalBinding(bce->sc->argumentsLocalSlot());
@ -1318,9 +1318,6 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
} else {
JS_ASSERT(!bce->sc->funDefinitelyNeedsArgsObj());
}
} else {
JS_ASSERT(!bce->sc->funArgumentsHasLocalBinding());
JS_ASSERT(!bce->sc->funDefinitelyNeedsArgsObj());
}
if (nClosedArgs)
@ -1331,7 +1328,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
script->bindings.transfer(cx, &bce->sc->bindings);
fun = NULL;
if (bce->sc->inFunction) {
if (bce->sc->inFunction()) {
JS_ASSERT(!bce->noScriptRval);
JS_ASSERT(!bce->needScriptGlobal);
@ -1362,10 +1359,6 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
script->globalObject = fun->getParent() ? &fun->getParent()->global() : NULL;
} else {
// It'd be nice to JS_ASSERT(!bce->sc->funIsHeavyweight()) here, but
// Parser.cpp is sloppy and sometimes applies it to non-functions.
JS_ASSERT(!bce->sc->funIsGenerator());
/*
* Initialize script->object, if necessary, so that the debugger has a
* valid holder object.