[JAEGER] Bug 582411: Make JM throw an exception setting undefined global vars in strict mode, r=dvander

--HG--
extra : rebase_source : 6ee3399c7f4ffadab34765a4bf3c2ccaa4c8c1f2
This commit is contained in:
David Mandelin 2010-07-29 16:04:54 -07:00
Родитель 86e20cfe21
Коммит 4290da179d
6 изменённых файлов: 110 добавлений и 26 удалений

Просмотреть файл

@ -2114,7 +2114,14 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
return MakeUpvarForEval(pn, cg);
}
if (cg->compileAndGo() && cg->compiler()->globalScope->globalObj) {
/*
* Optimize accesses to undeclared globals, but only if we are in
* compile-and-go mode, the global is the same as the scope chain,
* and we are not in strict mode.
*/
if (cg->compileAndGo() &&
cg->compiler()->globalScope->globalObj &&
!(cg->flags & TCF_STRICT_MODE_CODE)) {
switch (op) {
case JSOP_NAME: op = JSOP_GETGNAME; break;
case JSOP_SETNAME: op = JSOP_SETGNAME; break;
@ -2405,7 +2412,7 @@ JSCodeGenerator::addGlobalUse(JSAtom *atom, uint32 slot, UpvarCookie &cookie)
{
JSAtomListElement *ale = globalMap.lookup(atom);
if (ale) {
cookie.set(0, ALE_INDEX(ale));
cookie.set(0, uint16(ALE_INDEX(ale)));
return true;
}

Просмотреть файл

@ -1138,14 +1138,30 @@ mjit::Compiler::generateMethod()
BEGIN_CASE(JSOP_LAMBDA)
{
JSFunction *fun = script->getFunction(fullAtomIndex(PC));
prepareStubCall(Uses(0));
masm.move(ImmPtr(fun), Registers::ArgReg1);
JSObjStubFun stub = stubs::Lambda;
uint32 uses = 0;
JSOp next = JSOp(PC[JSOP_LAMBDA_LENGTH]);
if (next == JSOP_INITMETHOD)
stubCall(stubs::LambdaForInit);
else
stubCall(stubs::Lambda);
if (next == JSOP_INITMETHOD) {
stub = stubs::LambdaForInit;
} else if (next == JSOP_SETMETHOD) {
stub = stubs::LambdaForSet;
uses = 1;
} else if (fun->joinable()) {
if (next == JSOP_CALL) {
stub = stubs::LambdaJoinableForCall;
uses = frame.frameDepth();
} else if (next == JSOP_NULL) {
stub = stubs::LambdaJoinableForNull;
}
}
prepareStubCall(Uses(uses));
masm.move(ImmPtr(fun), Registers::ArgReg1);
stubCall(stub);
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
}

Просмотреть файл

@ -1782,9 +1782,7 @@ ic::SetProp(VMFrame &f, uint32 index)
}
Value rval = f.regs.sp[-1];
if (!obj->setProperty(f.cx, ATOM_TO_JSID(atom), &f.regs.sp[-1]))
THROW();
f.regs.sp[-2] = rval;
stub(f, index);
}
static void JS_FASTCALL

Просмотреть файл

@ -1522,24 +1522,76 @@ JSObject * JS_FASTCALL
stubs::LambdaForInit(VMFrame &f, JSFunction *fun)
{
JSObject *obj = FUN_OBJECT(fun);
JSObject *parent;
if (FUN_NULL_CLOSURE(fun)) {
parent = f.fp->scopeChain;
if (obj->getParent() == parent)
return obj;
} else {
parent = js_GetScopeChain(f.cx, f.fp);
if (!parent)
THROWV(NULL);
if (FUN_NULL_CLOSURE(fun) && obj->getParent() == f.fp->scopeChain) {
fun->setMethodAtom(f.fp->script->getAtom(GET_SLOTNO(f.regs.pc + JSOP_LAMBDA_LENGTH)));
return obj;
}
return Lambda(f, fun);
}
obj = CloneFunctionObject(f.cx, fun, parent);
if (!obj)
THROWV(NULL);
JSObject * JS_FASTCALL
stubs::LambdaForSet(VMFrame &f, JSFunction *fun)
{
JSObject *obj = FUN_OBJECT(fun);
if (FUN_NULL_CLOSURE(fun) && obj->getParent() == f.fp->scopeChain) {
const Value &lref = f.regs.sp[-1];
if (lref.isObject() && lref.toObject().canHaveMethodBarrier()) {
fun->setMethodAtom(f.fp->script->getAtom(GET_SLOTNO(f.regs.pc + JSOP_LAMBDA_LENGTH)));
return obj;
}
}
return Lambda(f, fun);
}
return obj;
JSObject * JS_FASTCALL
stubs::LambdaJoinableForCall(VMFrame &f, JSFunction *fun)
{
JSObject *obj = FUN_OBJECT(fun);
if (FUN_NULL_CLOSURE(fun) && obj->getParent() == f.fp->scopeChain) {
/*
* Array.prototype.sort and String.prototype.replace are
* optimized as if they are special form. We know that they
* won't leak the joined function object in obj, therefore
* we don't need to clone that compiler- created function
* object for identity/mutation reasons.
*/
int iargc = GET_ARGC(f.regs.pc + JSOP_LAMBDA_LENGTH);
/*
* Note that we have not yet pushed obj as the final argument,
* so regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)],
* is the callee for this JSOP_CALL.
*/
const Value &cref = f.regs.sp[1 - (iargc + 2)];
JSObject *callee;
if (IsFunctionObject(cref, &callee)) {
JSFunction *calleeFun = GET_FUNCTION_PRIVATE(cx, callee);
FastNative fastNative = FUN_FAST_NATIVE(calleeFun);
if (fastNative) {
if (iargc == 1 && fastNative == array_sort)
return obj;
if (iargc == 2 && fastNative == str_replace)
return obj;
}
}
}
return Lambda(f, fun);
}
JSObject * JS_FASTCALL
stubs::LambdaJoinableForNull(VMFrame &f, JSFunction *fun)
{
JSObject *obj = FUN_OBJECT(fun);
if (FUN_NULL_CLOSURE(fun) && obj->getParent() == f.fp->scopeChain) {
jsbytecode *pc2 = f.regs.pc + JSOP_LAMBDA_LENGTH + JSOP_NULL_LENGTH;
JSOp op2 = JSOp(*pc2);
if (op2 == JSOP_CALL && GET_ARGC(pc2) == 0)
return obj;
}
return Lambda(f, fun);
}
JSObject * JS_FASTCALL

Просмотреть файл

@ -116,6 +116,9 @@ JSObject * JS_FASTCALL DefLocalFun_FC(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL RegExp(VMFrame &f, JSObject *regex);
JSObject * JS_FASTCALL Lambda(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL LambdaForInit(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL LambdaForSet(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL LambdaJoinableForCall(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL LambdaJoinableForNull(VMFrame &f, JSFunction *fun);
JSObject * JS_FASTCALL FlatLambda(VMFrame &f, JSFunction *fun);
void JS_FASTCALL Arguments(VMFrame &f);
void JS_FASTCALL ArgSub(VMFrame &f, uint32 n);

Просмотреть файл

@ -0,0 +1,8 @@
// |trace-test| error: ReferenceError;
function f() {
"use strict";
foo = 1;
}
f();