mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 788957 (part 2) - Split ContextFlags into AnyContextFlags and FunctionContextFlags. r=benjamin.
--HG-- extra : rebase_source : a850729d3ca94cc6a04c87bf26e6154a7e1ef18b
This commit is contained in:
parent
198b733431
commit
90142084a7
@ -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;
|
||||||
|
@ -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(...). */
|
||||||
|
@ -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);
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user