mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 09:45:41 +00:00
Bug 690446 - Emit *GNAME ops in non-eval strict-mode code. r=bhackett
--HG-- extra : rebase_source : 11bced315dd2d4fa125ac1e2cd7f4b599dd62c3c
This commit is contained in:
parent
3a5e115094
commit
db26d3fc93
@ -286,6 +286,7 @@ EvalKernel(JSContext *cx, const CallArgs &args, EvalType evalType, AbstractFrame
|
||||
CompileOptions options(cx);
|
||||
options.setFileAndLine(filename, lineno)
|
||||
.setCompileAndGo(true)
|
||||
.setForEval(true)
|
||||
.setNoScriptRval(false)
|
||||
.setPrincipals(principals)
|
||||
.setOriginPrincipals(originPrincipals);
|
||||
@ -347,6 +348,7 @@ js::DirectEvalFromIon(JSContext *cx,
|
||||
CompileOptions options(cx);
|
||||
options.setFileAndLine(filename, lineno)
|
||||
.setCompileAndGo(true)
|
||||
.setForEval(true)
|
||||
.setNoScriptRval(false)
|
||||
.setPrincipals(principals)
|
||||
.setOriginPrincipals(originPrincipals);
|
||||
|
@ -90,6 +90,7 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
|
||||
* and non-zero static level requires callerFrame.
|
||||
*/
|
||||
JS_ASSERT_IF(evalCaller, options.compileAndGo);
|
||||
JS_ASSERT_IF(evalCaller, options.forEval);
|
||||
JS_ASSERT_IF(staticLevel != 0, evalCaller);
|
||||
|
||||
if (!CheckLength(cx, length))
|
||||
@ -146,8 +147,8 @@ frontend::CompileScript(JSContext *cx, HandleObject scopeChain,
|
||||
JS_ASSERT_IF(globalScope, globalScope->isNative());
|
||||
JS_ASSERT_IF(globalScope, JSCLASS_HAS_GLOBAL_FLAG_AND_SLOTS(globalScope->getClass()));
|
||||
|
||||
BytecodeEmitter bce(/* parent = */ NULL, &parser, &globalsc, script, evalCaller, !!globalScope,
|
||||
options.lineno, options.selfHostingMode);
|
||||
BytecodeEmitter bce(/* parent = */ NULL, &parser, &globalsc, script, options.forEval, evalCaller,
|
||||
!!globalScope, options.lineno, options.selfHostingMode);
|
||||
if (!bce.init())
|
||||
return NULL;
|
||||
|
||||
@ -330,6 +331,8 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ASSERT(!options.forEval);
|
||||
|
||||
Parser<FullParseHandler> parser(cx, options, chars, length, /* foldConstants = */ true);
|
||||
if (!parser.init())
|
||||
return false;
|
||||
@ -420,7 +423,7 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
|
||||
* is cloned immediately onto the right scope chain.
|
||||
*/
|
||||
BytecodeEmitter funbce(/* parent = */ NULL, &parser, funbox, script,
|
||||
/* evalCaller = */ NullPtr(),
|
||||
/* insideEval = */ false, /* evalCaller = */ NullPtr(),
|
||||
fun->environment() && fun->environment()->isGlobal(),
|
||||
options.lineno);
|
||||
if (!funbce.init())
|
||||
|
@ -90,8 +90,8 @@ struct frontend::StmtInfoBCE : public StmtInfoBase
|
||||
|
||||
BytecodeEmitter::BytecodeEmitter(BytecodeEmitter *parent,
|
||||
Parser<FullParseHandler> *parser, SharedContext *sc,
|
||||
HandleScript script, HandleScript evalCaller, bool hasGlobalScope,
|
||||
uint32_t lineNum, bool selfHostingMode)
|
||||
HandleScript script, bool insideEval, HandleScript evalCaller,
|
||||
bool hasGlobalScope, uint32_t lineNum, bool selfHostingMode)
|
||||
: sc(sc),
|
||||
parent(parent),
|
||||
script(sc->context, script),
|
||||
@ -114,9 +114,11 @@ BytecodeEmitter::BytecodeEmitter(BytecodeEmitter *parent,
|
||||
hasSingletons(false),
|
||||
emittingForInit(false),
|
||||
emittingRunOnceLambda(false),
|
||||
insideEval(insideEval),
|
||||
hasGlobalScope(hasGlobalScope),
|
||||
selfHostingMode(selfHostingMode)
|
||||
{
|
||||
JS_ASSERT_IF(evalCaller, insideEval);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1096,11 +1098,10 @@ EmitEnterBlock(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn, JSOp op)
|
||||
|
||||
/*
|
||||
* Try to convert a *NAME op to a *GNAME op, which optimizes access to
|
||||
* undeclared globals. Return true if a conversion was made.
|
||||
* globals. Return true if a conversion was made.
|
||||
*
|
||||
* This conversion is not made if we are in strict mode. In eval code nested
|
||||
* within (strict mode) eval code, access to an undeclared "global" might
|
||||
* merely be to a binding local to that outer eval:
|
||||
* Don't convert to *GNAME ops within strict-mode eval, since access
|
||||
* to a "global" might merely be to a binding local to that eval:
|
||||
*
|
||||
* "use strict";
|
||||
* var x = "global";
|
||||
@ -1136,7 +1137,7 @@ TryConvertToGname(BytecodeEmitter *bce, ParseNode *pn, JSOp *op)
|
||||
bce->hasGlobalScope &&
|
||||
!(bce->sc->isFunctionBox() && bce->sc->asFunctionBox()->mightAliasLocals()) &&
|
||||
!pn->isDeoptimized() &&
|
||||
!bce->sc->strict)
|
||||
!(bce->sc->strict && bce->insideEval))
|
||||
{
|
||||
// If you change anything here, you might also need to change
|
||||
// js::ReportIfUndeclaredVarAssignment.
|
||||
@ -4453,8 +4454,9 @@ EmitFunc(JSContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
||||
script->bindings = funbox->bindings;
|
||||
|
||||
uint32_t lineNum = bce->parser->tokenStream.srcCoords.lineNum(pn->pn_pos.begin);
|
||||
BytecodeEmitter bce2(bce, bce->parser, funbox, script, bce->evalCaller,
|
||||
bce->hasGlobalScope, lineNum, bce->selfHostingMode);
|
||||
BytecodeEmitter bce2(bce, bce->parser, funbox, script, bce->insideEval,
|
||||
bce->evalCaller, bce->hasGlobalScope, lineNum,
|
||||
bce->selfHostingMode);
|
||||
if (!bce2.init())
|
||||
return false;
|
||||
|
||||
|
@ -124,6 +124,9 @@ struct BytecodeEmitter
|
||||
bool emittingRunOnceLambda:1; /* true while emitting a lambda which is only
|
||||
expected to run once. */
|
||||
|
||||
bool insideEval:1; /* True if compiling an eval-expression or a function
|
||||
nested inside an eval. */
|
||||
|
||||
const bool hasGlobalScope:1; /* frontend::CompileScript's scope chain is the
|
||||
global object */
|
||||
|
||||
@ -139,8 +142,8 @@ struct BytecodeEmitter
|
||||
* destruction.
|
||||
*/
|
||||
BytecodeEmitter(BytecodeEmitter *parent, Parser<FullParseHandler> *parser, SharedContext *sc,
|
||||
HandleScript script, HandleScript evalCaller, bool hasGlobalScope,
|
||||
uint32_t lineNum, bool selfHostingMode = false);
|
||||
HandleScript script, bool insideEval, HandleScript evalCaller,
|
||||
bool hasGlobalScope, uint32_t lineNum, bool selfHostingMode = false);
|
||||
bool init();
|
||||
|
||||
bool isAliasedName(ParseNode *pn);
|
||||
|
@ -5415,7 +5415,8 @@ CodeGenerator::visitCallSetProperty(LCallSetProperty *ins)
|
||||
ConstantOrRegister value = TypedOrValueRegister(ToValue(ins, LCallSetProperty::Value));
|
||||
|
||||
const Register objReg = ToRegister(ins->getOperand(0));
|
||||
bool isSetName = JSOp(*ins->mir()->resumePoint()->pc()) == JSOP_SETNAME;
|
||||
jsbytecode *pc = ins->mir()->resumePoint()->pc();
|
||||
bool isSetName = JSOp(*pc) == JSOP_SETNAME || JSOp(*pc) == JSOP_SETGNAME;
|
||||
|
||||
pushArg(Imm32(isSetName));
|
||||
pushArg(Imm32(ins->mir()->strict()));
|
||||
@ -5451,7 +5452,8 @@ CodeGenerator::visitSetPropertyCacheV(LSetPropertyCacheV *ins)
|
||||
RegisterSet liveRegs = ins->safepoint()->liveRegs();
|
||||
Register objReg = ToRegister(ins->getOperand(0));
|
||||
ConstantOrRegister value = TypedOrValueRegister(ToValue(ins, LSetPropertyCacheV::Value));
|
||||
bool isSetName = JSOp(*ins->mir()->resumePoint()->pc()) == JSOP_SETNAME;
|
||||
jsbytecode *pc = ins->mir()->resumePoint()->pc();
|
||||
bool isSetName = JSOp(*pc) == JSOP_SETNAME || JSOp(*pc) == JSOP_SETGNAME;
|
||||
|
||||
SetPropertyIC cache(liveRegs, objReg, ins->mir()->name(), value,
|
||||
isSetName, ins->mir()->strict());
|
||||
|
@ -5258,6 +5258,7 @@ JS::CompileOptions::CompileOptions(JSContext *cx)
|
||||
filename(NULL),
|
||||
lineno(1),
|
||||
compileAndGo(cx->hasOption(JSOPTION_COMPILE_N_GO)),
|
||||
forEval(false),
|
||||
noScriptRval(cx->hasOption(JSOPTION_NO_SCRIPT_RVAL)),
|
||||
selfHostingMode(false),
|
||||
userBit(false),
|
||||
|
@ -3844,6 +3844,7 @@ struct JS_PUBLIC_API(CompileOptions) {
|
||||
const char *filename;
|
||||
unsigned lineno;
|
||||
bool compileAndGo;
|
||||
bool forEval;
|
||||
bool noScriptRval;
|
||||
bool selfHostingMode;
|
||||
bool userBit;
|
||||
@ -3862,6 +3863,7 @@ struct JS_PUBLIC_API(CompileOptions) {
|
||||
filename = f; lineno = l; return *this;
|
||||
}
|
||||
CompileOptions &setCompileAndGo(bool cng) { compileAndGo = cng; return *this; }
|
||||
CompileOptions &setForEval(bool eval) { forEval = eval; return *this; }
|
||||
CompileOptions &setNoScriptRval(bool nsr) { noScriptRval = nsr; return *this; }
|
||||
CompileOptions &setSelfHostingMode(bool shm) { selfHostingMode = shm; return *this; }
|
||||
CompileOptions &setUserBit(bool bit) { userBit = bit; return *this; }
|
||||
|
@ -3915,6 +3915,7 @@ js::EvaluateInEnv(JSContext *cx, Handle<Env*> env, HandleValue thisv, AbstractFr
|
||||
CompileOptions options(cx);
|
||||
options.setPrincipals(env->compartment()->principals)
|
||||
.setCompileAndGo(true)
|
||||
.setForEval(true)
|
||||
.setNoScriptRval(false)
|
||||
.setFileAndLine(filename, lineno);
|
||||
RootedScript callerScript(cx, frame ? frame.script() : NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user