Bug 788957 (part 2) - Split ContextFlags into AnyContextFlags and FunctionContextFlags. r=benjamin.

--HG--
extra : rebase_source : a850729d3ca94cc6a04c87bf26e6154a7e1ef18b
This commit is contained in:
Nicholas Nethercote 2012-09-10 20:40:11 -07:00
parent 198b733431
commit 90142084a7
6 changed files with 89 additions and 76 deletions

View File

@ -1178,7 +1178,7 @@ TryConvertToGname(BytecodeEmitter *bce, ParseNode *pn, JSOp *op)
} }
if (bce->script->compileAndGo && if (bce->script->compileAndGo &&
bce->hasGlobalScope && bce->hasGlobalScope &&
!(bce->sc->inFunction() && bce->sc->funMightAliasLocals()) && !(bce->sc->inFunction() && bce->sc->funbox()->mightAliasLocals()) &&
!pn->isDeoptimized() && !pn->isDeoptimized() &&
!bce->sc->inStrictMode()) !bce->sc->inStrictMode())
{ {
@ -2613,7 +2613,8 @@ 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.
*/ */
if (bce->sc->funArgumentsHasLocalBinding()) { FunctionBox *funbox = bce->sc->funbox();
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();
if (Emit1(cx, bce, JSOP_ARGUMENTS) < 0) if (Emit1(cx, bce, JSOP_ARGUMENTS) < 0)
@ -2634,7 +2635,7 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
bce->switchToMain(); bce->switchToMain();
} }
if (bce->sc->funIsGenerator()) { if (funbox->isGenerator()) {
bce->switchToProlog(); bce->switchToProlog();
if (Emit1(cx, bce, JSOP_GENERATOR) < 0) if (Emit1(cx, bce, JSOP_GENERATOR) < 0)
return false; return false;
@ -4846,9 +4847,9 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
{ {
FunctionBox *funbox = pn->pn_funbox; FunctionBox *funbox = pn->pn_funbox;
SharedContext sc(cx, /* scopeChain = */ NULL, funbox, funbox->strictModeState); SharedContext sc(cx, /* scopeChain = */ NULL, funbox, funbox->strictModeState);
sc.cxFlags = funbox->cxFlags; sc.anyCxFlags = funbox->anyCxFlags; // copy the non-func-specific flags
if (bce->sc->inFunction() && bce->sc->funMightAliasLocals()) if (bce->sc->inFunction() && bce->sc->funbox()->mightAliasLocals())
sc.setFunMightAliasLocals(); // inherit funMightAliasLocals from parent funbox->setMightAliasLocals(); // inherit mightAliasLocals from parent
JS_ASSERT_IF(bce->sc->inStrictMode(), sc.inStrictMode()); JS_ASSERT_IF(bce->sc->inStrictMode(), sc.inStrictMode());
// Inherit most things (principals, version, etc) from the parent. // Inherit most things (principals, version, etc) from the parent.
@ -6087,7 +6088,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->funArgumentsHasLocalBinding()); JS_ASSERT(!bce->sc->funbox()->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
@ -6132,7 +6133,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->funArgumentsHasLocalBinding()); JS_ASSERT(!bce->sc->funbox()->argumentsHasLocalBinding());
bce->switchToProlog(); bce->switchToProlog();
if (Emit1(cx, bce, JSOP_REST) < 0) if (Emit1(cx, bce, JSOP_REST) < 0)
return false; return false;

View File

@ -316,7 +316,7 @@ ParseContext::generateFunctionBindings(JSContext *cx, InternalHandle<Bindings*>
return false; return false;
} }
if (bindings->hasAnyAliasedBindings() || sc->funHasExtensibleScope()) if (bindings->hasAnyAliasedBindings() || sc->funbox()->hasExtensibleScope())
sc->funbox()->fun()->flags |= JSFUN_HEAVYWEIGHT; sc->funbox()->fun()->flags |= JSFUN_HEAVYWEIGHT;
return true; return true;
@ -410,7 +410,8 @@ FunctionBox::FunctionBox(ObjectBox *traceListHead, JSFunction *fun, ParseContext
strictModeState(sms), strictModeState(sms),
inWith(false), // initialized below inWith(false), // initialized below
inGenexpLambda(false), inGenexpLambda(false),
cxFlags() // the cxFlags are set in LeaveFunction anyCxFlags(),
funCxFlags() // the funCxFlags are set in LeaveFunction
{ {
if (!outerpc) { if (!outerpc) {
inWith = false; inWith = false;
@ -762,7 +763,7 @@ Parser::functionBody(FunctionBodyType type)
if (!pn->pn_kid) { if (!pn->pn_kid) {
pn = NULL; pn = NULL;
} else { } else {
if (pc->sc->funIsGenerator()) { if (pc->sc->funbox()->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);
@ -859,11 +860,12 @@ 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) {
pc->sc->setFunArgumentsHasLocalBinding(); FunctionBox *funbox = pc->sc->funbox();
funbox->setArgumentsHasLocalBinding();
/* Dynamic scope access destroys all hope of optimization. */ /* Dynamic scope access destroys all hope of optimization. */
if (pc->sc->bindingsAccessedDynamically()) if (pc->sc->bindingsAccessedDynamically())
pc->sc->setFunDefinitelyNeedsArgsObj(); funbox->setDefinitelyNeedsArgsObj();
/* /*
* Check whether any parameters have been assigned within this * Check whether any parameters have been assigned within this
@ -878,7 +880,7 @@ Parser::functionBody(FunctionBodyType type)
for (DefinitionList::Range dr = dlist.all(); !dr.empty(); dr.popFront()) { for (DefinitionList::Range dr = dlist.all(); !dr.empty(); dr.popFront()) {
Definition *dn = dr.front(); Definition *dn = dr.front();
if (dn->kind() == Definition::ARG && dn->isAssigned()) { if (dn->kind() == Definition::ARG && dn->isAssigned()) {
pc->sc->setFunDefinitelyNeedsArgsObj(); funbox->setDefinitelyNeedsArgsObj();
goto exitLoop; goto exitLoop;
} }
} }
@ -1152,7 +1154,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;
funbox->cxFlags = funpc->sc->cxFlags; // copy all the flags funbox->anyCxFlags = funpc->sc->anyCxFlags; // copy the non-func flags
funbox->kids = funpc->functionList; funbox->kids = funpc->functionList;
if (!pc->topStmt || pc->topStmt->type == STMT_BLOCK) if (!pc->topStmt || pc->topStmt->type == STMT_BLOCK)
@ -1196,7 +1198,7 @@ LeaveFunction(ParseNode *fn, Parser *parser, PropertyName *funName = NULL,
* by eval and function statements (which both flag the function as * by eval and function statements (which both flag the function as
* having an extensible scope) or any enclosing 'with'. * having an extensible scope) or any enclosing 'with'.
*/ */
if (funpc->sc->funHasExtensibleScope() || pc->parsingWith) if (funpc->sc->funbox()->hasExtensibleScope() || pc->parsingWith)
DeoptimizeUsesWithin(dn, fn->pn_pos); DeoptimizeUsesWithin(dn, fn->pn_pos);
if (!outer_dn) { if (!outer_dn) {
@ -1598,8 +1600,9 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
JS_ASSERT(pc->sc->strictModeState != StrictMode::STRICT); JS_ASSERT(pc->sc->strictModeState != StrictMode::STRICT);
JS_ASSERT(pn->pn_cookie.isFree()); JS_ASSERT(pn->pn_cookie.isFree());
if (pc->sc->inFunction()) { if (pc->sc->inFunction()) {
pc->sc->setFunMightAliasLocals(); FunctionBox *funbox = pc->sc->funbox();
pc->sc->setFunHasExtensibleScope(); funbox->setMightAliasLocals();
funbox->setHasExtensibleScope();
} }
pn->setOp(JSOP_DEFFUN); pn->setOp(JSOP_DEFFUN);
@ -1994,7 +1997,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->inFunction(), pc->sc->funHasExtensibleScope()); JS_ASSERT_IF(pc->sc->inFunction(), pc->sc->funbox()->hasExtensibleScope());
if (hasFunctionStmt) if (hasFunctionStmt)
*hasFunctionStmt = true; *hasFunctionStmt = true;
} }
@ -2194,8 +2197,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->inFunction()) if (pc->sc->inFunction())
pc->sc->setFunMightAliasLocals(); pc->sc->funbox()->setMightAliasLocals();
return true; return true;
} }
@ -2582,7 +2585,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->setFunIsGenerator(); pc->sc->funbox()->setIsGenerator();
} else { } else {
pc->yieldCount++; pc->yieldCount++;
pc->yieldNode = pn; pc->yieldNode = pn;
@ -2619,7 +2622,7 @@ Parser::returnOrYield(bool useAssignExpr)
pc->funHasReturnVoid = true; pc->funHasReturnVoid = true;
} }
if (pc->funHasReturnExpr && pc->sc->funIsGenerator()) { if (pc->funHasReturnExpr && pc->sc->funbox()->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);
@ -4859,9 +4862,9 @@ GenexpGuard::maybeNoteGenerator(ParseNode *pn)
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->setFunIsGenerator(); pc->sc->funbox()->setIsGenerator();
if (pc->funHasReturnExpr) { if (pc->funHasReturnExpr) {
/* At the time we saw the yield, we might not have set funIsGenerator 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,
JSMSG_BAD_GENERATOR_RETURN, JSMSG_BAD_ANON_GENERATOR_RETURN); JSMSG_BAD_GENERATOR_RETURN, JSMSG_BAD_ANON_GENERATOR_RETURN);
return false; return false;
@ -5378,9 +5381,11 @@ Parser::generatorExpr(ParseNode *kid)
* simplicity we also do not detect if the flags were only set in the * simplicity we also do not detect if the flags were only set in the
* kid and could be removed from pc->sc. * kid and could be removed from pc->sc.
*/ */
gensc.cxFlags = outerpc->sc->cxFlags; gensc.anyCxFlags = outerpc->sc->anyCxFlags;
gensc.setFunIsGenerator(); if (outerpc->sc->inFunction())
funbox->funCxFlags = outerpc->sc->funbox()->funCxFlags;
funbox->setIsGenerator();
funbox->inGenexpLambda = true; funbox->inGenexpLambda = true;
genfn->pn_funbox = funbox; genfn->pn_funbox = funbox;
genfn->pn_blockid = genpc.bodyid; genfn->pn_blockid = genpc.bodyid;
@ -5704,7 +5709,7 @@ Parser::memberExpr(bool allowCallSyntax)
* variables to the call object. * variables to the call object.
*/ */
if (pc->sc->inFunction() && pc->sc->strictModeState != StrictMode::STRICT) if (pc->sc->inFunction() && pc->sc->strictModeState != StrictMode::STRICT)
pc->sc->setFunHasExtensibleScope(); pc->sc->funbox()->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(...). */

View File

@ -20,7 +20,7 @@ SharedContext::SharedContext(JSContext *cx, JSObject *scopeChain, FunctionBox *f
: context(cx), : context(cx),
funbox_(funbox), funbox_(funbox),
scopeChain_(cx, scopeChain), scopeChain_(cx, scopeChain),
cxFlags(), anyCxFlags(),
strictModeState(sms) strictModeState(sms)
{ {
JS_ASSERT((funbox && !scopeChain_) || !funbox); JS_ASSERT((funbox && !scopeChain_) || !funbox);

View File

@ -22,11 +22,11 @@
namespace js { namespace js {
namespace frontend { namespace frontend {
class ContextFlags { // These flags apply to both global and function contexts.
class AnyContextFlags {
// This class's data is all private and so only visible to these friends. // This class's data is all private and so only visible to these friends.
friend struct SharedContext; friend struct SharedContext;
friend struct FunctionBox;
// True if "use strict"; appears in the body instead of being inherited. // True if "use strict"; appears in the body instead of being inherited.
bool hasExplicitUseStrict:1; bool hasExplicitUseStrict:1;
@ -54,12 +54,24 @@ class ContextFlags {
// //
bool bindingsAccessedDynamically:1; bool bindingsAccessedDynamically:1;
public:
AnyContextFlags()
: hasExplicitUseStrict(false),
bindingsAccessedDynamically(false)
{ }
};
class FunctionContextFlags {
// This class's data is all private and so only visible to these friends.
friend struct FunctionBox;
// We parsed a yield statement in the function. // We parsed a yield statement in the function.
bool funIsGenerator:1; bool isGenerator:1;
// The function or a function that encloses it may define new local names // The function or a function that encloses it may define new local names
// at runtime through means other than calling eval. // at runtime through means other than calling eval.
bool funMightAliasLocals:1; bool mightAliasLocals:1;
// This function does something that can extend the set of bindings in its // This function does something that can extend the set of bindings in its
// call objects --- it does a direct eval in non-strict code, or includes a // call objects --- it does a direct eval in non-strict code, or includes a
@ -68,7 +80,7 @@ class ContextFlags {
// This flag is *not* inherited by enclosed or enclosing functions; it // This flag is *not* inherited by enclosed or enclosing functions; it
// applies only to the function in whose flags it appears. // applies only to the function in whose flags it appears.
// //
bool funHasExtensibleScope:1; bool hasExtensibleScope:1;
// Technically, every function has a binding named 'arguments'. Internally, // Technically, every function has a binding named 'arguments'. Internally,
// this binding is only added when 'arguments' is mentioned by the function // this binding is only added when 'arguments' is mentioned by the function
@ -91,7 +103,7 @@ class ContextFlags {
// have no special semantics: the initial value is unconditionally the // have no special semantics: the initial value is unconditionally the
// actual argument (or undefined if nactual < nformal). // actual argument (or undefined if nactual < nformal).
// //
bool funArgumentsHasLocalBinding:1; bool argumentsHasLocalBinding:1;
// In many cases where 'arguments' has a local binding (as described above) // In many cases where 'arguments' has a local binding (as described above)
// we do not need to actually create an arguments object in the function // we do not need to actually create an arguments object in the function
@ -102,17 +114,15 @@ class ContextFlags {
// be unsound in several cases. The frontend filters out such cases by // be unsound in several cases. The frontend filters out such cases by
// setting this flag which eagerly sets script->needsArgsObj to true. // setting this flag which eagerly sets script->needsArgsObj to true.
// //
bool funDefinitelyNeedsArgsObj:1; bool definitelyNeedsArgsObj:1;
public: public:
ContextFlags() FunctionContextFlags()
: hasExplicitUseStrict(false), : isGenerator(false),
bindingsAccessedDynamically(false), mightAliasLocals(false),
funIsGenerator(false), hasExtensibleScope(false),
funMightAliasLocals(false), argumentsHasLocalBinding(false),
funHasExtensibleScope(false), definitelyNeedsArgsObj(false)
funArgumentsHasLocalBinding(false),
funDefinitelyNeedsArgsObj(false)
{ } { }
}; };
@ -133,8 +143,7 @@ struct SharedContext {
(if inFunction() is false) */ (if inFunction() is false) */
public: public:
ContextFlags cxFlags; AnyContextFlags anyCxFlags;
// strictModeState tracks the strictness of this context. Normally, it // strictModeState tracks the strictness of this context. Normally, it
// should be STRICT or NOTSTRICT. However, it can be UNKNOWN when parsing // should be STRICT or NOTSTRICT. However, it can be UNKNOWN when parsing
@ -161,27 +170,11 @@ struct SharedContext {
inline SharedContext(JSContext *cx, JSObject *scopeChain, FunctionBox *funbox, inline SharedContext(JSContext *cx, JSObject *scopeChain, FunctionBox *funbox,
StrictMode sms); StrictMode sms);
// The |fun*| flags are only relevant if |inFunction()| is true. bool hasExplicitUseStrict() const { return anyCxFlags.hasExplicitUseStrict; }
#define INFUNC JS_ASSERT(inFunction()) bool bindingsAccessedDynamically() const { return anyCxFlags.bindingsAccessedDynamically; }
bool hasExplicitUseStrict() const { return cxFlags.hasExplicitUseStrict; } void setExplicitUseStrict() { anyCxFlags.hasExplicitUseStrict = true; }
bool bindingsAccessedDynamically() const { return cxFlags.bindingsAccessedDynamically; } void setBindingsAccessedDynamically() { anyCxFlags.bindingsAccessedDynamically = true; }
bool funIsGenerator() const { INFUNC; return cxFlags.funIsGenerator; }
bool funMightAliasLocals() const { INFUNC; return cxFlags.funMightAliasLocals; }
bool funHasExtensibleScope() const { INFUNC; return cxFlags.funHasExtensibleScope; }
bool funArgumentsHasLocalBinding() const { INFUNC; return cxFlags.funArgumentsHasLocalBinding; }
bool funDefinitelyNeedsArgsObj() const { INFUNC; return cxFlags.funDefinitelyNeedsArgsObj; }
void setExplicitUseStrict() { cxFlags.hasExplicitUseStrict = true; }
void setBindingsAccessedDynamically() { cxFlags.bindingsAccessedDynamically = true; }
void setFunIsGenerator() { INFUNC; cxFlags.funIsGenerator = true; }
void setFunMightAliasLocals() { INFUNC; cxFlags.funMightAliasLocals = true; }
void setFunHasExtensibleScope() { INFUNC; cxFlags.funHasExtensibleScope = true; }
void setFunArgumentsHasLocalBinding() { INFUNC; cxFlags.funArgumentsHasLocalBinding = true; }
void setFunDefinitelyNeedsArgsObj() { JS_ASSERT(cxFlags.funArgumentsHasLocalBinding);
INFUNC; cxFlags.funDefinitelyNeedsArgsObj = true; }
#undef INFUNC
bool inFunction() const { return !!funbox_; } bool inFunction() const { return !!funbox_; }
@ -297,15 +290,27 @@ struct FunctionBox
or E4X filter-expression */ or E4X filter-expression */
bool inGenexpLambda:1; /* lambda from generator expression */ bool inGenexpLambda:1; /* lambda from generator expression */
ContextFlags cxFlags; AnyContextFlags anyCxFlags;
FunctionContextFlags funCxFlags;
FunctionBox(ObjectBox *traceListHead, JSFunction *fun, ParseContext *pc, StrictMode sms); FunctionBox(ObjectBox *traceListHead, JSFunction *fun, ParseContext *pc, StrictMode sms);
bool funIsGenerator() const { return cxFlags.funIsGenerator; }
JSFunction *fun() const { return objbox.object->toFunction(); } JSFunction *fun() const { return objbox.object->toFunction(); }
void recursivelySetStrictMode(StrictMode strictness); void recursivelySetStrictMode(StrictMode strictness);
bool isGenerator() const { return funCxFlags.isGenerator; }
bool mightAliasLocals() const { return funCxFlags.mightAliasLocals; }
bool hasExtensibleScope() const { return funCxFlags.hasExtensibleScope; }
bool argumentsHasLocalBinding() const { return funCxFlags.argumentsHasLocalBinding; }
bool definitelyNeedsArgsObj() const { return funCxFlags.definitelyNeedsArgsObj; }
void setIsGenerator() { funCxFlags.isGenerator = true; }
void setMightAliasLocals() { funCxFlags.mightAliasLocals = true; }
void setHasExtensibleScope() { funCxFlags.hasExtensibleScope = true; }
void setArgumentsHasLocalBinding() { funCxFlags.argumentsHasLocalBinding = true; }
void setDefinitelyNeedsArgsObj() { JS_ASSERT(funCxFlags.argumentsHasLocalBinding);
funCxFlags.definitelyNeedsArgsObj = true; }
}; };
// Push the C-stack-allocated struct at stmt onto the StmtInfoPC stack. // Push the C-stack-allocated struct at stmt onto the StmtInfoPC stack.

View File

@ -3104,7 +3104,7 @@ ASTSerializer::function(ParseNode *pn, ASTType type, Value *dst)
bool isGenerator = bool isGenerator =
#if JS_HAS_GENERATORS #if JS_HAS_GENERATORS
pn->pn_funbox->funIsGenerator(); pn->pn_funbox->isGenerator();
#else #else
false; false;
#endif #endif

View File

@ -1670,7 +1670,7 @@ JSScript::fullyInitFromEmitter(JSContext *cx, Handle<JSScript*> script, Bytecode
script->explicitUseStrict = bce->sc->hasExplicitUseStrict(); script->explicitUseStrict = bce->sc->hasExplicitUseStrict();
script->bindingsAccessedDynamically = bce->sc->bindingsAccessedDynamically(); script->bindingsAccessedDynamically = bce->sc->bindingsAccessedDynamically();
script->funHasExtensibleScope = script->funHasExtensibleScope =
bce->sc->inFunction() ? bce->sc->funHasExtensibleScope() : false; bce->sc->inFunction() ? bce->sc->funbox()->hasExtensibleScope() : false;
script->hasSingletons = bce->hasSingletons; script->hasSingletons = bce->hasSingletons;
#ifdef JS_METHODJIT #ifdef JS_METHODJIT
if (cx->compartment->debugMode()) if (cx->compartment->debugMode())
@ -1678,21 +1678,23 @@ JSScript::fullyInitFromEmitter(JSContext *cx, Handle<JSScript*> script, Bytecode
#endif #endif
if (bce->sc->inFunction()) { if (bce->sc->inFunction()) {
if (bce->sc->funArgumentsHasLocalBinding()) { FunctionBox *funbox = bce->sc->funbox();
if (funbox->argumentsHasLocalBinding()) {
// This must precede the script->bindings.transfer() call below // This must precede the script->bindings.transfer() call below
script->setArgumentsHasVarBinding(); script->setArgumentsHasVarBinding();
if (bce->sc->funDefinitelyNeedsArgsObj()) if (funbox->definitelyNeedsArgsObj())
script->setNeedsArgsObj(true); script->setNeedsArgsObj(true);
} else { } else {
JS_ASSERT(!bce->sc->funDefinitelyNeedsArgsObj()); JS_ASSERT(!funbox->definitelyNeedsArgsObj());
} }
} }
RootedFunction fun(cx, NULL); RootedFunction fun(cx, NULL);
if (bce->sc->inFunction()) { if (bce->sc->inFunction()) {
JS_ASSERT(!bce->script->noScriptRval); JS_ASSERT(!bce->script->noScriptRval);
script->isGenerator = bce->sc->funIsGenerator(); FunctionBox *funbox = bce->sc->funbox();
script->isGeneratorExp = bce->sc->funbox()->inGenexpLambda; script->isGenerator = funbox->isGenerator();
script->isGeneratorExp = funbox->inGenexpLambda;
script->setFunction(bce->sc->funbox()->fun()); script->setFunction(bce->sc->funbox()->fun());
} }