mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 753657 (part 3): Remove the remaining parts of TreeContextFlags. r=luke.
--HG-- extra : rebase_source : 7d62aac9f3049a5bb6e8821d2055e59348cf9d85
This commit is contained in:
parent
0da09800c8
commit
dc9e955005
@ -157,8 +157,9 @@ frontend::CompileScript(JSContext *cx, JSObject *scopeChain, StackFrame *callerF
|
||||
/* If this is a direct call to eval, inherit the caller's strictness. */
|
||||
if (callerFrame &&
|
||||
callerFrame->isScriptFrame() &&
|
||||
callerFrame->script()->strictModeCode) {
|
||||
bce.sc->flags |= TCF_STRICT_MODE_CODE;
|
||||
callerFrame->script()->strictModeCode)
|
||||
{
|
||||
bce.sc->setInStrictMode();
|
||||
tokenStream.setStrictMode();
|
||||
}
|
||||
|
||||
|
@ -1000,7 +1000,7 @@ BytecodeEmitter::noteClosedVar(ParseNode *pn)
|
||||
for (size_t i = 0; i < closedVars.length(); ++i)
|
||||
JS_ASSERT(closedVars[i] != pn->pn_cookie.slot());
|
||||
#endif
|
||||
sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
sc->setFunIsHeavyweight();
|
||||
return closedVars.append(pn->pn_cookie.slot());
|
||||
}
|
||||
|
||||
@ -1015,7 +1015,7 @@ BytecodeEmitter::noteClosedArg(ParseNode *pn)
|
||||
for (size_t i = 0; i < closedArgs.length(); ++i)
|
||||
JS_ASSERT(closedArgs[i] != pn->pn_cookie.slot());
|
||||
#endif
|
||||
sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
sc->setFunIsHeavyweight();
|
||||
return closedArgs.append(pn->pn_cookie.slot());
|
||||
}
|
||||
|
||||
@ -1090,7 +1090,7 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
|
||||
* clones must get unique shapes; see the comments for
|
||||
* js::Bindings::extensibleParents.
|
||||
*/
|
||||
if ((bce->sc->flags & TCF_FUN_EXTENSIBLE_SCOPE) ||
|
||||
if (bce->sc->funHasExtensibleScope() ||
|
||||
bce->sc->bindings.extensibleParents()) {
|
||||
Shape *newShape = Shape::setExtensibleParents(cx, blockObj->lastProperty());
|
||||
if (!newShape)
|
||||
@ -1127,9 +1127,9 @@ TryConvertToGname(BytecodeEmitter *bce, ParseNode *pn, JSOp *op)
|
||||
{
|
||||
if (bce->parser->compileAndGo &&
|
||||
bce->globalScope->globalObj &&
|
||||
!bce->sc->mightAliasLocals() &&
|
||||
!bce->sc->funMightAliasLocals() &&
|
||||
!pn->isDeoptimized() &&
|
||||
!(bce->sc->flags & TCF_STRICT_MODE_CODE)) {
|
||||
!bce->sc->inStrictMode()) {
|
||||
switch (*op) {
|
||||
case JSOP_NAME: *op = JSOP_GETGNAME; break;
|
||||
case JSOP_SETNAME: *op = JSOP_SETGNAME; break;
|
||||
@ -1356,7 +1356,7 @@ BindNameToSlot(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
* the scope chain so that assignment will throw a TypeError.
|
||||
*/
|
||||
JS_ASSERT(op != JSOP_DELNAME);
|
||||
if (!(bce->sc->flags & TCF_FUN_HEAVYWEIGHT)) {
|
||||
if (!bce->sc->funIsHeavyweight()) {
|
||||
op = JSOP_CALLEE;
|
||||
pn->pn_dflags |= PND_CONST;
|
||||
}
|
||||
@ -2618,7 +2618,7 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
|
||||
* execution starts from script->code, so this has no semantic effect.
|
||||
*/
|
||||
|
||||
if (bce->sc->argumentsHasLocalBinding()) {
|
||||
if (bce->sc->funArgumentsHasLocalBinding()) {
|
||||
JS_ASSERT(bce->next() == bce->base()); /* See JSScript::argumentsBytecode. */
|
||||
bce->switchToProlog();
|
||||
if (Emit1(cx, bce, JSOP_ARGUMENTS) < 0)
|
||||
@ -2637,7 +2637,7 @@ frontend::EmitFunctionScript(JSContext *cx, BytecodeEmitter *bce, ParseNode *bod
|
||||
bce->switchToMain();
|
||||
}
|
||||
|
||||
if (bce->sc->flags & TCF_FUN_IS_GENERATOR) {
|
||||
if (bce->sc->funIsGenerator()) {
|
||||
bce->switchToProlog();
|
||||
if (Emit1(cx, bce, JSOP_GENERATOR) < 0)
|
||||
return false;
|
||||
@ -2663,7 +2663,7 @@ MaybeEmitVarDecl(JSContext *cx, BytecodeEmitter *bce, JSOp prologOp, ParseNode *
|
||||
}
|
||||
|
||||
if (JOF_OPTYPE(pn->getOp()) == JOF_ATOM &&
|
||||
(!bce->sc->inFunction || (bce->sc->flags & TCF_FUN_HEAVYWEIGHT)))
|
||||
(!bce->sc->inFunction || bce->sc->funIsHeavyweight()))
|
||||
{
|
||||
bce->switchToProlog();
|
||||
if (!UpdateLineNumberNotes(cx, bce, pn->pn_pos.begin.lineno))
|
||||
@ -4827,7 +4827,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
return EmitFunctionDefNop(cx, bce, pn->pn_index);
|
||||
}
|
||||
|
||||
JS_ASSERT_IF(pn->pn_funbox->tcflags & TCF_FUN_HEAVYWEIGHT,
|
||||
JS_ASSERT_IF(pn->pn_funbox->funIsHeavyweight(),
|
||||
fun->kind() == JSFUN_INTERPRETED);
|
||||
|
||||
{
|
||||
@ -4837,10 +4837,14 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
if (!bce2.init())
|
||||
return false;
|
||||
|
||||
bce2.sc->flags = pn->pn_funbox->tcflags | (bce->sc->flags & TCF_FUN_MIGHT_ALIAS_LOCALS);
|
||||
bce2.sc->bindings.transfer(cx, &pn->pn_funbox->bindings);
|
||||
FunctionBox *funbox = pn->pn_funbox;
|
||||
bce2.sc->cxFlags = funbox->cxFlags;
|
||||
if (bce->sc->funMightAliasLocals())
|
||||
bce2.sc->setFunMightAliasLocals(); // inherit funMightAliasLocals from parent
|
||||
|
||||
bce2.sc->bindings.transfer(cx, &funbox->bindings);
|
||||
bce2.sc->setFunction(fun);
|
||||
bce2.sc->funbox = pn->pn_funbox;
|
||||
bce2.sc->funbox = funbox;
|
||||
bce2.parent = bce;
|
||||
bce2.globalScope = bce->globalScope;
|
||||
|
||||
@ -4863,7 +4867,7 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
|
||||
/* Emit a bytecode pointing to the closure object in its immediate. */
|
||||
if (pn->getOp() != JSOP_NOP) {
|
||||
if ((pn->pn_funbox->inGenexpLambda) && NewSrcNote(cx, bce, SRC_GENEXP) < 0)
|
||||
if (pn->pn_funbox->inGenexpLambda && NewSrcNote(cx, bce, SRC_GENEXP) < 0)
|
||||
return false;
|
||||
|
||||
return EmitFunctionOp(cx, pn->getOp(), index, bce);
|
||||
|
@ -39,6 +39,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "frontend/ParseNode.h"
|
||||
#include "frontend/Parser.h"
|
||||
|
||||
#include "jsscriptinlines.h"
|
||||
|
||||
@ -112,18 +113,12 @@ bool
|
||||
FunctionBox::inAnyDynamicScope() const
|
||||
{
|
||||
for (const FunctionBox *funbox = this; funbox; funbox = funbox->parent) {
|
||||
if (funbox->inWith || (funbox->tcflags & TCF_FUN_EXTENSIBLE_SCOPE))
|
||||
if (funbox->inWith || funbox->funHasExtensibleScope())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
FunctionBox::scopeIsExtensible() const
|
||||
{
|
||||
return tcflags & TCF_FUN_EXTENSIBLE_SCOPE;
|
||||
}
|
||||
|
||||
/* Add |node| to |parser|'s free node list. */
|
||||
void
|
||||
ParseNodeAllocator::freeNode(ParseNode *pn)
|
||||
|
@ -47,6 +47,7 @@
|
||||
|
||||
#include "frontend/ParseMaps.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "frontend/TreeContext.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -1534,18 +1535,25 @@ struct ObjectBox {
|
||||
|
||||
struct FunctionBox : public ObjectBox
|
||||
{
|
||||
ParseNode *node;
|
||||
FunctionBox *siblings;
|
||||
FunctionBox *kids;
|
||||
FunctionBox *parent;
|
||||
Bindings bindings; /* bindings for this function */
|
||||
uint32_t queued:1,
|
||||
inLoop:1, /* in a loop in parent function */
|
||||
level:JSFB_LEVEL_BITS;
|
||||
uint32_t tcflags;
|
||||
bool inWith:1; /* some enclosing scope is a with-statement
|
||||
or E4X filter-expression */
|
||||
bool inGenexpLambda:1; /* lambda from generator expression */
|
||||
ParseNode *node;
|
||||
FunctionBox *siblings;
|
||||
FunctionBox *kids;
|
||||
FunctionBox *parent;
|
||||
Bindings bindings; /* bindings for this function */
|
||||
uint32_t level:JSFB_LEVEL_BITS;
|
||||
bool queued:1;
|
||||
bool inLoop:1; /* in a loop in parent function */
|
||||
bool inWith:1; /* some enclosing scope is a with-statement
|
||||
or E4X filter-expression */
|
||||
bool inGenexpLambda:1; /* lambda from generator expression */
|
||||
|
||||
ContextFlags cxFlags;
|
||||
|
||||
bool funIsHeavyweight() const { return cxFlags.funIsHeavyweight; }
|
||||
bool funIsGenerator() const { return cxFlags.funIsGenerator; }
|
||||
bool funHasExtensibleScope() const { return cxFlags.funHasExtensibleScope; }
|
||||
|
||||
void setFunIsHeavyweight() { cxFlags.funIsHeavyweight = true; }
|
||||
|
||||
JSFunction *function() const { return (JSFunction *) object; }
|
||||
|
||||
@ -1554,12 +1562,6 @@ struct FunctionBox : public ObjectBox
|
||||
* filter-expression, or a function that uses direct eval.
|
||||
*/
|
||||
bool inAnyDynamicScope() const;
|
||||
|
||||
/*
|
||||
* Must this function's descendants be marked as having an extensible
|
||||
* ancestor?
|
||||
*/
|
||||
bool scopeIsExtensible() const;
|
||||
};
|
||||
|
||||
struct FunctionBoxQueue {
|
||||
|
@ -236,7 +236,6 @@ Parser::newFunctionBox(JSObject *obj, ParseNode *fn, TreeContext *tc)
|
||||
}
|
||||
}
|
||||
funbox->level = tc->sc->staticLevel;
|
||||
funbox->tcflags = 0; // this is set in LeaveFunction
|
||||
funbox->inWith = !!tc->innermostWith;
|
||||
if (!tc->sc->inFunction) {
|
||||
JSObject *scope = tc->sc->scopeChain();
|
||||
@ -247,6 +246,9 @@ Parser::newFunctionBox(JSObject *obj, ParseNode *fn, TreeContext *tc)
|
||||
}
|
||||
}
|
||||
funbox->inGenexpLambda = false;
|
||||
|
||||
new (&funbox->cxFlags) ContextFlags(context); // the cxFlags are set in LeaveFunction
|
||||
|
||||
return funbox;
|
||||
}
|
||||
|
||||
@ -619,7 +621,7 @@ Parser::functionBody(FunctionBodyType type)
|
||||
if (!pn->pn_kid) {
|
||||
pn = NULL;
|
||||
} else {
|
||||
if (tc->sc->flags & TCF_FUN_IS_GENERATOR) {
|
||||
if (tc->sc->funIsGenerator()) {
|
||||
ReportBadReturn(context, this, pn, JSREPORT_ERROR,
|
||||
JSMSG_BAD_GENERATOR_RETURN,
|
||||
JSMSG_BAD_ANON_GENERATOR_RETURN);
|
||||
@ -665,16 +667,16 @@ Parser::functionBody(FunctionBodyType type)
|
||||
for (FuncStmtSet::Range r = set->all(); !r.empty(); r.popFront()) {
|
||||
PropertyName *name = r.front()->asPropertyName();
|
||||
if (name == arguments)
|
||||
tc->sc->noteBindingsAccessedDynamically();
|
||||
tc->sc->setBindingsAccessedDynamically();
|
||||
else if (Definition *dn = tc->decls.lookupFirst(name))
|
||||
dn->pn_dflags |= PND_CLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* As explained by the TCF_ARGUMENTS_HAS_LOCAL_BINDING comment, turn uses
|
||||
* of 'arguments' into bindings. Use of 'arguments' should never escape a
|
||||
* nested function as an upvar.
|
||||
* As explained by the ContextFlags::funArgumentsHasLocalBinding comment,
|
||||
* turn uses of 'arguments' into bindings. Use of 'arguments' should never
|
||||
* escape a nested function as an upvar.
|
||||
*/
|
||||
for (AtomDefnRange r = tc->lexdeps->all(); !r.empty(); r.popFront()) {
|
||||
JSAtom *atom = r.front().key();
|
||||
@ -712,11 +714,11 @@ Parser::functionBody(FunctionBodyType type)
|
||||
*/
|
||||
BindingKind bindKind = tc->sc->bindings.lookup(context, arguments, NULL);
|
||||
if (bindKind == VARIABLE || bindKind == CONSTANT) {
|
||||
tc->sc->noteArgumentsHasLocalBinding();
|
||||
tc->sc->setFunArgumentsHasLocalBinding();
|
||||
|
||||
/* Dynamic scope access destroys all hope of optimization. */
|
||||
if (tc->sc->bindingsAccessedDynamically())
|
||||
tc->sc->noteDefinitelyNeedsArgsObj();
|
||||
tc->sc->setFunDefinitelyNeedsArgsObj();
|
||||
|
||||
/*
|
||||
* Check whether any parameters have been assigned within this
|
||||
@ -729,7 +731,7 @@ Parser::functionBody(FunctionBodyType type)
|
||||
AtomDeclsIter iter(&tc->decls);
|
||||
while (Definition *dn = iter.next()) {
|
||||
if (dn->kind() == Definition::ARG && dn->isAssigned()) {
|
||||
tc->sc->noteDefinitelyNeedsArgsObj();
|
||||
tc->sc->setFunDefinitelyNeedsArgsObj();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1083,25 +1085,23 @@ EnterFunction(ParseNode *fn, Parser *parser, JSAtom *funAtom = NULL,
|
||||
FunctionSyntaxKind kind = Expression)
|
||||
{
|
||||
TreeContext *funtc = parser->tc;
|
||||
TreeContext *tc = funtc->parent;
|
||||
JSFunction *fun = parser->newFunction(tc, funAtom, kind);
|
||||
TreeContext *outertc = funtc->parent;
|
||||
JSFunction *fun = parser->newFunction(outertc, funAtom, kind);
|
||||
if (!fun)
|
||||
return NULL;
|
||||
|
||||
/* Create box for fun->object early to protect against last-ditch GC. */
|
||||
FunctionBox *funbox = parser->newFunctionBox(fun, fn, tc);
|
||||
FunctionBox *funbox = parser->newFunctionBox(fun, fn, outertc);
|
||||
if (!funbox)
|
||||
return NULL;
|
||||
|
||||
/* Initialize non-default members of funtc. */
|
||||
JS_ASSERT(!funtc->sc->flags);
|
||||
funtc->sc->flags = tc->sc->flags & TCF_STRICT_MODE_CODE; // inherit strict mode from parent
|
||||
funtc->sc->blockidGen = tc->sc->blockidGen;
|
||||
/* 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, tc->sc->staticLevel + 1))
|
||||
if (!SetStaticLevel(funtc->sc, outertc->sc->staticLevel + 1))
|
||||
return NULL;
|
||||
|
||||
return funbox;
|
||||
@ -1139,8 +1139,7 @@ LeaveFunction(ParseNode *fn, Parser *parser, PropertyName *funName = NULL,
|
||||
tc->sc->blockidGen = funtc->sc->blockidGen;
|
||||
|
||||
FunctionBox *funbox = fn->pn_funbox;
|
||||
JS_ASSERT(!funbox->tcflags); // we don't set any of these flags until now
|
||||
funbox->tcflags = funtc->sc->flags;
|
||||
funbox->cxFlags = funtc->sc->cxFlags; // copy all the flags
|
||||
|
||||
fn->pn_dflags |= PND_INITIALIZED;
|
||||
if (!tc->sc->topStmt || tc->sc->topStmt->type == STMT_BLOCK)
|
||||
@ -1542,6 +1541,9 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
|
||||
if (!funbox)
|
||||
return NULL;
|
||||
|
||||
if (outertc->sc->inStrictMode())
|
||||
funsc.setInStrictMode(); // inherit strict mode from parent
|
||||
|
||||
RootedVarFunction fun(context, funbox->function());
|
||||
|
||||
/* Now parse formal argument list and compute fun->nargs. */
|
||||
@ -1619,7 +1621,7 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
|
||||
* parents: any local can be read at runtime.
|
||||
*/
|
||||
if (funsc.bindingsAccessedDynamically())
|
||||
outertc->sc->noteBindingsAccessedDynamically();
|
||||
outertc->sc->setBindingsAccessedDynamically();
|
||||
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
/*
|
||||
@ -1662,9 +1664,9 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
|
||||
* visible eval call, or assignment to 'arguments'), flag the function as
|
||||
* heavyweight (requiring a call object per invocation).
|
||||
*/
|
||||
if (funsc.flags & TCF_FUN_HEAVYWEIGHT) {
|
||||
if (funsc.funIsHeavyweight()) {
|
||||
fun->flags |= JSFUN_HEAVYWEIGHT;
|
||||
outertc->sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
outertc->sc->setFunIsHeavyweight();
|
||||
}
|
||||
|
||||
JSOp op = JSOP_NOP;
|
||||
@ -1680,12 +1682,12 @@ Parser::functionDef(HandlePropertyName funName, FunctionType type, FunctionSynta
|
||||
*/
|
||||
JS_ASSERT(!outertc->sc->inStrictMode());
|
||||
op = JSOP_DEFFUN;
|
||||
outertc->sc->noteMightAliasLocals();
|
||||
outertc->sc->noteHasExtensibleScope();
|
||||
outertc->sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
outertc->sc->setFunMightAliasLocals();
|
||||
outertc->sc->setFunHasExtensibleScope();
|
||||
outertc->sc->setFunIsHeavyweight();
|
||||
|
||||
/*
|
||||
* Instead of noteBindingsAccessedDynamically, which would be
|
||||
* Instead of setting bindingsAccessedDynamically, which would be
|
||||
* overly conservative, remember the names of all function
|
||||
* statements and mark any bindings with the same as aliased at the
|
||||
* end of functionBody.
|
||||
@ -1821,7 +1823,7 @@ Parser::recognizeDirectivePrologue(ParseNode *pn, bool *isDirectivePrologueMembe
|
||||
return false;
|
||||
}
|
||||
|
||||
tc->sc->flags |= TCF_STRICT_MODE_CODE;
|
||||
tc->sc->setInStrictMode();
|
||||
tokenStream.setStrictMode();
|
||||
}
|
||||
}
|
||||
@ -1887,7 +1889,7 @@ Parser::statements(bool *hasFunctionStmt)
|
||||
* General deoptimization was done in functionDef, here we just
|
||||
* need to tell TOK_LC in Parser::statement to add braces.
|
||||
*/
|
||||
JS_ASSERT(tc->sc->hasExtensibleScope());
|
||||
JS_ASSERT(tc->sc->funHasExtensibleScope());
|
||||
if (hasFunctionStmt)
|
||||
*hasFunctionStmt = true;
|
||||
}
|
||||
@ -2124,7 +2126,7 @@ BindVarOrConst(JSContext *cx, BindData *data, JSAtom *atom, Parser *parser)
|
||||
if (stmt && stmt->type == STMT_WITH) {
|
||||
data->fresh = false;
|
||||
pn->pn_dflags |= PND_DEOPTIMIZED;
|
||||
tc->sc->noteMightAliasLocals();
|
||||
tc->sc->setFunMightAliasLocals();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2308,7 +2310,7 @@ NoteLValue(JSContext *cx, ParseNode *pn, SharedContext *sc, unsigned dflag = PND
|
||||
* happens by making such functions heavyweight.
|
||||
*/
|
||||
if (sc->inFunction && pn->pn_atom == sc->fun()->atom)
|
||||
sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
sc->setFunIsHeavyweight();
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -2660,7 +2662,7 @@ Parser::returnOrYield(bool useAssignExpr)
|
||||
* a |for| token, so we have to delay flagging the current function.
|
||||
*/
|
||||
if (tc->parenDepth == 0) {
|
||||
tc->sc->flags |= TCF_FUN_IS_GENERATOR;
|
||||
tc->sc->setFunIsGenerator();
|
||||
} else {
|
||||
tc->yieldCount++;
|
||||
tc->yieldNode = pn;
|
||||
@ -2697,7 +2699,7 @@ Parser::returnOrYield(bool useAssignExpr)
|
||||
tc->hasReturnVoid = true;
|
||||
}
|
||||
|
||||
if (tc->hasReturnExpr && (tc->sc->flags & TCF_FUN_IS_GENERATOR)) {
|
||||
if (tc->hasReturnExpr && tc->sc->funIsGenerator()) {
|
||||
/* As in Python (see PEP-255), disallow return v; in generators. */
|
||||
ReportBadReturn(context, this, pn, JSREPORT_ERROR,
|
||||
JSMSG_BAD_GENERATOR_RETURN,
|
||||
@ -3607,7 +3609,7 @@ Parser::withStatement()
|
||||
* doesn't even merit a warning under JSOPTION_STRICT. See
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=514576#c1.
|
||||
*/
|
||||
if (tc->sc->flags & TCF_STRICT_MODE_CODE) {
|
||||
if (tc->sc->inStrictMode()) {
|
||||
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_STRICT_CODE_WITH);
|
||||
return NULL;
|
||||
}
|
||||
@ -3635,8 +3637,8 @@ Parser::withStatement()
|
||||
pn->pn_pos.end = pn2->pn_pos.end;
|
||||
pn->pn_right = pn2;
|
||||
|
||||
tc->sc->noteBindingsAccessedDynamically();
|
||||
tc->sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->sc->setBindingsAccessedDynamically();
|
||||
tc->sc->setFunIsHeavyweight();
|
||||
tc->innermostWith = oldWith;
|
||||
|
||||
/*
|
||||
@ -4121,7 +4123,7 @@ Parser::statement()
|
||||
pn = new_<DebuggerStatement>(tokenStream.currentToken().pos);
|
||||
if (!pn)
|
||||
return NULL;
|
||||
tc->sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->sc->setFunIsHeavyweight();
|
||||
break;
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
@ -4146,7 +4148,7 @@ Parser::statement()
|
||||
JS_ASSERT(tokenStream.currentToken().t_op == JSOP_NOP);
|
||||
|
||||
/* Is this an E4X dagger I see before me? */
|
||||
tc->sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->sc->setFunIsHeavyweight();
|
||||
ParseNode *pn2 = expr();
|
||||
if (!pn2)
|
||||
return NULL;
|
||||
@ -4959,14 +4961,14 @@ GenexpGuard::maybeNoteGenerator(ParseNode *pn)
|
||||
{
|
||||
TreeContext *tc = parser->tc;
|
||||
if (tc->yieldCount > 0) {
|
||||
tc->sc->flags |= TCF_FUN_IS_GENERATOR;
|
||||
tc->sc->setFunIsGenerator();
|
||||
if (!tc->sc->inFunction) {
|
||||
parser->reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_BAD_RETURN_OR_YIELD,
|
||||
js_yield_str);
|
||||
return false;
|
||||
}
|
||||
if (tc->hasReturnExpr) {
|
||||
/* At the time we saw the yield, we might not have set TCF_FUN_IS_GENERATOR yet. */
|
||||
/* At the time we saw the yield, we might not have set funIsGenerator yet. */
|
||||
ReportBadReturn(tc->sc->context, parser, pn, JSREPORT_ERROR,
|
||||
JSMSG_BAD_GENERATOR_RETURN,
|
||||
JSMSG_BAD_ANON_GENERATOR_RETURN);
|
||||
@ -5462,12 +5464,14 @@ Parser::generatorExpr(ParseNode *kid)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* We assume conservatively that any deoptimization flags in tc->sc->flags
|
||||
* We assume conservatively that any deoptimization flags in tc->sc
|
||||
* come from the kid. So we propagate these flags into genfn. For code
|
||||
* simplicity we also do not detect if the flags were only set in the
|
||||
* kid and could be removed from tc->sc->flags.
|
||||
* kid and could be removed from tc->sc.
|
||||
*/
|
||||
gensc.flags |= TCF_FUN_IS_GENERATOR | outertc->sc->flags;
|
||||
gensc.cxFlags = outertc->sc->cxFlags;
|
||||
gensc.setFunIsGenerator();
|
||||
|
||||
funbox->inGenexpLambda = true;
|
||||
genfn->pn_funbox = funbox;
|
||||
genfn->pn_blockid = gensc.bodyid;
|
||||
@ -5638,8 +5642,8 @@ Parser::memberExpr(JSBool allowCallSyntax)
|
||||
TokenPtr begin = lhs->pn_pos.begin;
|
||||
if (tt == TOK_LP) {
|
||||
/* Filters are effectively 'with', so deoptimize names. */
|
||||
tc->sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->sc->noteBindingsAccessedDynamically();
|
||||
tc->sc->setFunIsHeavyweight();
|
||||
tc->sc->setBindingsAccessedDynamically();
|
||||
|
||||
StmtInfo stmtInfo(context);
|
||||
ParseNode *oldWith = tc->innermostWith;
|
||||
@ -5758,14 +5762,14 @@ Parser::memberExpr(JSBool allowCallSyntax)
|
||||
if (lhs->pn_atom == context->runtime->atomState.evalAtom) {
|
||||
/* Select JSOP_EVAL and flag tc as heavyweight. */
|
||||
nextMember->setOp(JSOP_EVAL);
|
||||
tc->sc->noteBindingsAccessedDynamically();
|
||||
tc->sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->sc->setBindingsAccessedDynamically();
|
||||
tc->sc->setFunIsHeavyweight();
|
||||
/*
|
||||
* In non-strict mode code, direct calls to eval can add
|
||||
* variables to the call object.
|
||||
*/
|
||||
if (!tc->sc->inStrictMode())
|
||||
tc->sc->noteHasExtensibleScope();
|
||||
tc->sc->setFunHasExtensibleScope();
|
||||
}
|
||||
} else if (lhs->isOp(JSOP_GETPROP)) {
|
||||
/* Select JSOP_FUNAPPLY given foo.apply(...). */
|
||||
@ -5914,8 +5918,8 @@ Parser::qualifiedSuffix(ParseNode *pn)
|
||||
if (!pn2)
|
||||
return NULL;
|
||||
|
||||
tc->sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->sc->noteBindingsAccessedDynamically();
|
||||
tc->sc->setFunIsHeavyweight();
|
||||
tc->sc->setBindingsAccessedDynamically();
|
||||
|
||||
/* Left operand of :: must be evaluated if it is an identifier. */
|
||||
if (pn->isOp(JSOP_QNAMEPART))
|
||||
@ -5961,8 +5965,8 @@ Parser::qualifiedIdentifier()
|
||||
return NULL;
|
||||
if (tokenStream.matchToken(TOK_DBLCOLON)) {
|
||||
/* Hack for bug 496316. Slowing down E4X won't make it go away, alas. */
|
||||
tc->sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->sc->noteBindingsAccessedDynamically();
|
||||
tc->sc->setFunIsHeavyweight();
|
||||
tc->sc->setBindingsAccessedDynamically();
|
||||
pn = qualifiedSuffix(pn);
|
||||
}
|
||||
return pn;
|
||||
@ -6466,8 +6470,8 @@ Parser::propertyQualifiedIdentifier()
|
||||
JS_ASSERT(tokenStream.peekToken() == TOK_DBLCOLON);
|
||||
|
||||
/* Deoptimize QualifiedIdentifier properties to avoid tricky analysis. */
|
||||
tc->sc->flags |= TCF_FUN_HEAVYWEIGHT;
|
||||
tc->sc->noteBindingsAccessedDynamically();
|
||||
tc->sc->setFunIsHeavyweight();
|
||||
tc->sc->setBindingsAccessedDynamically();
|
||||
|
||||
PropertyName *name = tokenStream.currentToken().name();
|
||||
ParseNode *node = NameNode::create(PNK_NAME, name, this, this->tc->sc);
|
||||
|
@ -52,7 +52,7 @@ using namespace js;
|
||||
using namespace js::frontend;
|
||||
|
||||
static void
|
||||
FlagHeavyweights(Definition *dn, FunctionBox *funbox, uint32_t *tcflags, bool topInFunction)
|
||||
FlagHeavyweights(Definition *dn, FunctionBox *funbox, bool *isHeavyweight, bool topInFunction)
|
||||
{
|
||||
unsigned dnLevel = dn->frameLevel();
|
||||
|
||||
@ -64,17 +64,17 @@ FlagHeavyweights(Definition *dn, FunctionBox *funbox, uint32_t *tcflags, bool to
|
||||
* funbox whose body contains the dn definition.
|
||||
*/
|
||||
if (funbox->level + 1U == dnLevel || (dnLevel == 0 && dn->isLet())) {
|
||||
funbox->tcflags |= TCF_FUN_HEAVYWEIGHT;
|
||||
funbox->setFunIsHeavyweight();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!funbox && topInFunction)
|
||||
*tcflags |= TCF_FUN_HEAVYWEIGHT;
|
||||
*isHeavyweight = true;
|
||||
}
|
||||
|
||||
static void
|
||||
SetFunctionKinds(FunctionBox *funbox, uint32_t *tcflags, bool topInFunction, bool isDirectEval)
|
||||
SetFunctionKinds(FunctionBox *funbox, bool *isHeavyweight, bool topInFunction, bool isDirectEval)
|
||||
{
|
||||
for (; funbox; funbox = funbox->siblings) {
|
||||
ParseNode *fn = funbox->node;
|
||||
@ -86,13 +86,13 @@ SetFunctionKinds(FunctionBox *funbox, uint32_t *tcflags, bool topInFunction, boo
|
||||
continue;
|
||||
|
||||
if (funbox->kids)
|
||||
SetFunctionKinds(funbox->kids, tcflags, topInFunction, isDirectEval);
|
||||
SetFunctionKinds(funbox->kids, isHeavyweight, topInFunction, isDirectEval);
|
||||
|
||||
JSFunction *fun = funbox->function();
|
||||
|
||||
JS_ASSERT(fun->kind() == JSFUN_INTERPRETED);
|
||||
|
||||
if (funbox->tcflags & TCF_FUN_HEAVYWEIGHT) {
|
||||
if (funbox->funIsHeavyweight()) {
|
||||
/* nothing to do */
|
||||
} else if (isDirectEval || funbox->inAnyDynamicScope()) {
|
||||
/*
|
||||
@ -134,7 +134,7 @@ SetFunctionKinds(FunctionBox *funbox, uint32_t *tcflags, bool topInFunction, boo
|
||||
* ensure that its containing function has been flagged as
|
||||
* heavyweight.
|
||||
*
|
||||
* The emitter must see TCF_FUN_HEAVYWEIGHT accurately before
|
||||
* The emitter must see funIsHeavyweight() accurately before
|
||||
* generating any code for a tree of nested functions.
|
||||
*/
|
||||
AtomDefnMapPtr upvars = pn->pn_names;
|
||||
@ -144,7 +144,7 @@ SetFunctionKinds(FunctionBox *funbox, uint32_t *tcflags, bool topInFunction, boo
|
||||
Definition *defn = r.front().value();
|
||||
Definition *lexdep = defn->resolve();
|
||||
if (!lexdep->isFreeVar())
|
||||
FlagHeavyweights(lexdep, funbox, tcflags, topInFunction);
|
||||
FlagHeavyweights(lexdep, funbox, isHeavyweight, topInFunction);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -179,7 +179,9 @@ MarkExtensibleScopeDescendants(JSContext *context, FunctionBox *funbox, bool has
|
||||
|
||||
if (funbox->kids) {
|
||||
if (!MarkExtensibleScopeDescendants(context, funbox->kids,
|
||||
hasExtensibleParent || funbox->scopeIsExtensible())) {
|
||||
hasExtensibleParent ||
|
||||
funbox->funHasExtensibleScope()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -197,6 +199,9 @@ frontend::AnalyzeFunctions(Parser *parser)
|
||||
if (!MarkExtensibleScopeDescendants(sc->context, sc->functionList, false))
|
||||
return false;
|
||||
bool isDirectEval = !!parser->callerFrame;
|
||||
SetFunctionKinds(sc->functionList, &sc->flags, sc->inFunction, isDirectEval);
|
||||
bool isHeavyweight = false;
|
||||
SetFunctionKinds(sc->functionList, &isHeavyweight, sc->inFunction, isDirectEval);
|
||||
if (isHeavyweight)
|
||||
sc->setFunIsHeavyweight();
|
||||
return true;
|
||||
}
|
||||
|
@ -563,7 +563,7 @@ js::ReportStrictModeError(JSContext *cx, TokenStream *ts, SharedContext *sc, Par
|
||||
|
||||
/* In strict mode code, this is an error, not merely a warning. */
|
||||
unsigned flags;
|
||||
if ((ts && ts->isStrictMode()) || (sc && (sc->flags & TCF_STRICT_MODE_CODE))) {
|
||||
if ((ts && ts->isStrictMode()) || (sc && sc->inStrictMode())) {
|
||||
flags = JSREPORT_ERROR;
|
||||
} else {
|
||||
if (!cx->hasStrictOption())
|
||||
|
@ -51,7 +51,6 @@ namespace js {
|
||||
inline
|
||||
SharedContext::SharedContext(JSContext *cx, bool inFunction)
|
||||
: context(cx),
|
||||
flags(0),
|
||||
bodyid(0),
|
||||
blockidGen(0),
|
||||
topStmt(NULL),
|
||||
@ -65,7 +64,8 @@ SharedContext::SharedContext(JSContext *cx, bool inFunction)
|
||||
bindings(cx),
|
||||
bindingsRoot(cx, &bindings),
|
||||
inFunction(inFunction),
|
||||
inForInit(false)
|
||||
inForInit(false),
|
||||
cxFlags(cx)
|
||||
{
|
||||
}
|
||||
|
||||
@ -119,8 +119,6 @@ TreeContext::TreeContext(Parser *prs, SharedContext *sc)
|
||||
inline bool
|
||||
TreeContext::init(JSContext *cx)
|
||||
{
|
||||
if (cx->hasRunOption(JSOPTION_STRICT_MODE))
|
||||
sc->flags |= TCF_STRICT_MODE_CODE;
|
||||
return decls.init() && lexdeps.ensureMap(sc->context);
|
||||
}
|
||||
|
||||
|
@ -56,20 +56,20 @@ typedef struct BindData BindData;
|
||||
|
||||
namespace js {
|
||||
|
||||
JS_ENUM_HEADER(TreeContextFlags, uint32_t)
|
||||
{
|
||||
// function needs Call object per call
|
||||
TCF_FUN_HEAVYWEIGHT = 0x1,
|
||||
struct StmtInfo;
|
||||
|
||||
// parsed yield statement in function
|
||||
TCF_FUN_IS_GENERATOR = 0x2,
|
||||
class ContextFlags {
|
||||
|
||||
// This class's data is all private and so only visible to these friends.
|
||||
friend class SharedContext;
|
||||
friend class FunctionBox;
|
||||
|
||||
// This function/global/eval code body contained a Use Strict Directive.
|
||||
// Treat certain strict warnings as errors, and forbid the use of 'with'.
|
||||
// See also TSF_STRICT_MODE_CODE, JSScript::strictModeCode, and
|
||||
// JSREPORT_STRICT_ERROR.
|
||||
//
|
||||
TCF_STRICT_MODE_CODE = 0x4,
|
||||
bool inStrictMode:1;
|
||||
|
||||
// The (static) bindings of this script need to support dynamic name
|
||||
// read/write access. Here, 'dynamic' means dynamic dictionary lookup on
|
||||
@ -91,11 +91,22 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
|
||||
// taken not to turn off the whole 'arguments' optimization). To answer the
|
||||
// more general "is this argument aliased" question, script->needsArgsObj
|
||||
// should be tested (see JSScript::argIsAlised).
|
||||
TCF_BINDINGS_ACCESSED_DYNAMICALLY = 0x8,
|
||||
//
|
||||
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;
|
||||
|
||||
// We parsed a yield statement in the function.
|
||||
bool funIsGenerator:1;
|
||||
|
||||
// The function or a function that encloses it may define new local names
|
||||
// at runtime through means other than calling eval.
|
||||
TCF_FUN_MIGHT_ALIAS_LOCALS = 0x10,
|
||||
bool funMightAliasLocals:1;
|
||||
|
||||
// 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
|
||||
@ -104,7 +115,7 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
|
||||
// This flag is *not* inherited by enclosed or enclosing functions; it
|
||||
// applies only to the function in whose flags it appears.
|
||||
//
|
||||
TCF_FUN_EXTENSIBLE_SCOPE = 0x20,
|
||||
bool funHasExtensibleScope:1;
|
||||
|
||||
// Technically, every function has a binding named 'arguments'. Internally,
|
||||
// this binding is only added when 'arguments' is mentioned by the function
|
||||
@ -127,7 +138,7 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
|
||||
// have no special semantics: the initial value is unconditionally the
|
||||
// actual argument (or undefined if nactual < nformal).
|
||||
//
|
||||
TCF_ARGUMENTS_HAS_LOCAL_BINDING = 0x40,
|
||||
bool funArgumentsHasLocalBinding:1;
|
||||
|
||||
// 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
|
||||
@ -138,16 +149,24 @@ JS_ENUM_HEADER(TreeContextFlags, uint32_t)
|
||||
// be unsound in several cases. The frontend filters out such cases by
|
||||
// setting this flag which eagerly sets script->needsArgsObj to true.
|
||||
//
|
||||
TCF_DEFINITELY_NEEDS_ARGS_OBJ = 0x80
|
||||
bool funDefinitelyNeedsArgsObj:1;
|
||||
|
||||
} JS_ENUM_FOOTER(TreeContextFlags);
|
||||
|
||||
struct StmtInfo;
|
||||
public:
|
||||
ContextFlags(JSContext *cx)
|
||||
: inStrictMode(cx->hasRunOption(JSOPTION_STRICT_MODE)),
|
||||
bindingsAccessedDynamically(false),
|
||||
funIsHeavyweight(false),
|
||||
funIsGenerator(false),
|
||||
funMightAliasLocals(false),
|
||||
funHasExtensibleScope(false),
|
||||
funArgumentsHasLocalBinding(false),
|
||||
funDefinitelyNeedsArgsObj(false)
|
||||
{ }
|
||||
};
|
||||
|
||||
struct SharedContext {
|
||||
JSContext *context;
|
||||
|
||||
uint32_t flags; /* statement state flags, see above */
|
||||
uint32_t bodyid; /* block number of program/function body */
|
||||
uint32_t blockidGen; /* preincremented block number generator */
|
||||
|
||||
@ -179,21 +198,28 @@ struct SharedContext {
|
||||
|
||||
bool inForInit:1; /* parsing/emitting init expr of for; exclude 'in' */
|
||||
|
||||
ContextFlags cxFlags;
|
||||
|
||||
inline SharedContext(JSContext *cx, bool inFunction);
|
||||
|
||||
bool inStrictMode() const { return flags & TCF_STRICT_MODE_CODE; }
|
||||
bool bindingsAccessedDynamically() const { return flags & TCF_BINDINGS_ACCESSED_DYNAMICALLY; }
|
||||
bool mightAliasLocals() const { return flags & TCF_FUN_MIGHT_ALIAS_LOCALS; }
|
||||
bool hasExtensibleScope() const { return flags & TCF_FUN_EXTENSIBLE_SCOPE; }
|
||||
bool argumentsHasLocalBinding() const { return flags & TCF_ARGUMENTS_HAS_LOCAL_BINDING; }
|
||||
bool definitelyNeedsArgsObj() const { return flags & TCF_DEFINITELY_NEEDS_ARGS_OBJ; }
|
||||
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; }
|
||||
|
||||
void noteMightAliasLocals() { flags |= TCF_FUN_MIGHT_ALIAS_LOCALS; }
|
||||
void noteBindingsAccessedDynamically() { flags |= TCF_BINDINGS_ACCESSED_DYNAMICALLY; }
|
||||
void noteHasExtensibleScope() { flags |= TCF_FUN_EXTENSIBLE_SCOPE; }
|
||||
void noteArgumentsHasLocalBinding() { flags |= TCF_ARGUMENTS_HAS_LOCAL_BINDING; }
|
||||
void noteDefinitelyNeedsArgsObj() { JS_ASSERT(argumentsHasLocalBinding());
|
||||
flags |= TCF_DEFINITELY_NEEDS_ARGS_OBJ; }
|
||||
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; }
|
||||
void setFunDefinitelyNeedsArgsObj() { JS_ASSERT(cxFlags.funArgumentsHasLocalBinding);
|
||||
cxFlags.funDefinitelyNeedsArgsObj = true; }
|
||||
|
||||
unsigned argumentsLocalSlot() const;
|
||||
|
||||
|
@ -2950,7 +2950,7 @@ ASTSerializer::function(ParseNode *pn, ASTType type, Value *dst)
|
||||
|
||||
bool isGenerator =
|
||||
#if JS_HAS_GENERATORS
|
||||
pn->pn_funbox->tcflags & TCF_FUN_IS_GENERATOR;
|
||||
pn->pn_funbox->funIsGenerator();
|
||||
#else
|
||||
false;
|
||||
#endif
|
||||
|
@ -1329,24 +1329,28 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
||||
bce->regexpList.finish(script->regexps());
|
||||
if (bce->constList.length() != 0)
|
||||
bce->constList.finish(script->consts());
|
||||
if (bce->sc->flags & TCF_STRICT_MODE_CODE)
|
||||
script->strictModeCode = true;
|
||||
script->strictModeCode = bce->sc->inStrictMode();
|
||||
if (bce->parser->compileAndGo) {
|
||||
script->compileAndGo = true;
|
||||
const StackFrame *fp = bce->parser->callerFrame;
|
||||
if (fp && fp->isFunctionFrame())
|
||||
script->savedCallerFun = true;
|
||||
}
|
||||
if (bce->sc->bindingsAccessedDynamically())
|
||||
script->bindingsAccessedDynamically = true;
|
||||
script->bindingsAccessedDynamically = bce->sc->bindingsAccessedDynamically();
|
||||
script->hasSingletons = bce->hasSingletons;
|
||||
if (bce->sc->flags & TCF_FUN_IS_GENERATOR)
|
||||
script->isGenerator = true;
|
||||
|
||||
if (bce->sc->argumentsHasLocalBinding()) {
|
||||
script->setArgumentsHasLocalBinding(bce->sc->argumentsLocalSlot());
|
||||
if (bce->sc->definitelyNeedsArgsObj())
|
||||
script->setNeedsArgsObj(true);
|
||||
if (bce->sc->inFunction) {
|
||||
if (bce->sc->funArgumentsHasLocalBinding()) {
|
||||
// This must precede the script->bindings.transfer() call below.
|
||||
script->setArgumentsHasLocalBinding(bce->sc->argumentsLocalSlot());
|
||||
if (bce->sc->funDefinitelyNeedsArgsObj())
|
||||
script->setNeedsArgsObj(true);
|
||||
} else {
|
||||
JS_ASSERT(!bce->sc->funDefinitelyNeedsArgsObj());
|
||||
}
|
||||
} else {
|
||||
JS_ASSERT(!bce->sc->funArgumentsHasLocalBinding());
|
||||
JS_ASSERT(!bce->sc->funDefinitelyNeedsArgsObj());
|
||||
}
|
||||
|
||||
if (nClosedArgs)
|
||||
@ -1360,6 +1364,9 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
||||
if (bce->sc->inFunction) {
|
||||
JS_ASSERT(!bce->noScriptRval);
|
||||
JS_ASSERT(!bce->needScriptGlobal);
|
||||
|
||||
script->isGenerator = bce->sc->funIsGenerator();
|
||||
|
||||
/*
|
||||
* We initialize fun->script() to be the script constructed above
|
||||
* so that the debugger has a valid fun->script().
|
||||
@ -1367,7 +1374,7 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
||||
fun = bce->sc->fun();
|
||||
JS_ASSERT(fun->isInterpreted());
|
||||
JS_ASSERT(!fun->script());
|
||||
if (bce->sc->flags & TCF_FUN_HEAVYWEIGHT)
|
||||
if (bce->sc->funIsHeavyweight())
|
||||
fun->flags |= JSFUN_HEAVYWEIGHT;
|
||||
|
||||
/*
|
||||
@ -1383,7 +1390,12 @@ JSScript::NewScriptFromEmitter(JSContext *cx, BytecodeEmitter *bce)
|
||||
|
||||
fun->setScript(script);
|
||||
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.
|
||||
|
@ -529,7 +529,7 @@ struct JSScript : public js::gc::Cell
|
||||
bool savedCallerFun:1; /* can call getCallerFunction() */
|
||||
bool strictModeCode:1; /* code is in strict mode */
|
||||
bool compileAndGo:1; /* see Parser::compileAndGo */
|
||||
bool bindingsAccessedDynamically:1; /* see TCF_BINDINGS_ACCESSED_DYNAMICALLY */
|
||||
bool bindingsAccessedDynamically:1; /* see ContextFlags' field of the same name */
|
||||
bool warnedAboutTwoArgumentEval:1; /* have warned about use of
|
||||
obsolete eval(s, o) in
|
||||
this script */
|
||||
@ -589,7 +589,7 @@ struct JSScript : public js::gc::Cell
|
||||
|
||||
void setVersion(JSVersion v) { version = v; }
|
||||
|
||||
/* See TCF_ARGUMENTS_HAS_LOCAL_BINDING comment. */
|
||||
/* See ContextFlags::funArgumentsHasLocalBinding comment. */
|
||||
bool argumentsHasLocalBinding() const { return argsHasLocalBinding_; }
|
||||
jsbytecode *argumentsBytecode() const { JS_ASSERT(code[0] == JSOP_ARGUMENTS); return code; }
|
||||
unsigned argumentsLocalSlot() const { JS_ASSERT(argsHasLocalBinding_); return argsSlot_; }
|
||||
|
Loading…
Reference in New Issue
Block a user