зеркало из https://github.com/mozilla/pjs.git
Bug 514570 - 2 - Push |undefined| rather than |null| when calling functions without a specified |this| value, per ES5. r=jorendorff
This commit is contained in:
Родитель
8a276492f8
Коммит
545f7104c0
|
@ -2816,12 +2816,17 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
|
|||
|
||||
Value thisv;
|
||||
if (argc > 1 && !REDUCE_MODE(mode)) {
|
||||
JSObject *thisp;
|
||||
if (!js_ValueToObjectOrNull(cx, argv[1], &thisp))
|
||||
return JS_FALSE;
|
||||
thisv.setObjectOrNull(thisp);
|
||||
if (argv[1].isNullOrUndefined()) {
|
||||
thisv.setUndefined();
|
||||
} else {
|
||||
JSObject *thisObj;
|
||||
if (!js_ValueToObjectOrNull(cx, argv[1], &thisObj))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(thisObj);
|
||||
thisv.setObject(*thisObj);
|
||||
}
|
||||
} else {
|
||||
thisv.setNull();
|
||||
thisv.setUndefined();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -6525,12 +6525,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
* interpose the lambda-initialized method read barrier -- see the code
|
||||
* in jsinterp.cpp for JSOP_LAMBDA followed by JSOP_{SET,INIT}PROP.
|
||||
*
|
||||
* Then (or in a call case that has no explicit reference-base object)
|
||||
* we emit JSOP_NULL as a placeholder local GC root to hold the |this|
|
||||
* parameter: in the operator new case, the newborn instance; in the
|
||||
* base-less call case, a cookie meaning "use the global object as the
|
||||
* |this| value" (or in ES5 strict mode, "use undefined", so we should
|
||||
* use JSOP_PUSH instead of JSOP_NULL -- see bug 514570).
|
||||
* Then (or in a call case that has no explicit reference-base
|
||||
* object) we emit JSOP_PUSH to produce the |this| slot required
|
||||
* for calls (which non-strict mode functions will box into the
|
||||
* global object).
|
||||
*/
|
||||
pn2 = pn->pn_head;
|
||||
switch (pn2->pn_type) {
|
||||
|
@ -6552,22 +6550,18 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
if (pn2->pn_op == JSOP_XMLNAME) {
|
||||
if (!EmitXMLName(cx, pn2, JSOP_CALLXMLNAME, cg))
|
||||
return JS_FALSE;
|
||||
callop = true; /* suppress JSOP_NULL after */
|
||||
callop = true; /* suppress JSOP_PUSH after */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
/* FALL THROUGH */
|
||||
default:
|
||||
/*
|
||||
* Push null as a placeholder for the global object, per ECMA-262
|
||||
* 11.2.3 step 6.
|
||||
*/
|
||||
if (!js_EmitTree(cx, cg, pn2))
|
||||
return JS_FALSE;
|
||||
callop = false; /* trigger JSOP_NULL after */
|
||||
callop = false; /* trigger JSOP_PUSH after */
|
||||
break;
|
||||
}
|
||||
if (!callop && js_Emit1(cx, cg, JSOP_NULL) < 0)
|
||||
if (!callop && js_Emit1(cx, cg, JSOP_PUSH) < 0)
|
||||
return JS_FALSE;
|
||||
|
||||
/* Remember start of callable-object bytecode for decompilation hint. */
|
||||
|
|
|
@ -2258,15 +2258,20 @@ js_fun_call(JSContext *cx, uintN argc, Value *vp)
|
|||
}
|
||||
|
||||
Value *argv = vp + 2;
|
||||
Value thisv;
|
||||
if (argc == 0) {
|
||||
/* Call fun with its global object as the 'this' param if no args. */
|
||||
obj = NULL;
|
||||
thisv.setUndefined();
|
||||
} else {
|
||||
/* Otherwise convert the first arg to 'this' and skip over it. */
|
||||
if (argv[0].isObject())
|
||||
obj = &argv[0].toObject();
|
||||
else if (!js_ValueToObjectOrNull(cx, argv[0], &obj))
|
||||
return JS_FALSE;
|
||||
if (argv[0].isNullOrUndefined()) {
|
||||
thisv.setUndefined();
|
||||
} else {
|
||||
if (!js_ValueToObjectOrNull(cx, argv[0], &obj))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(obj);
|
||||
thisv.setObject(*obj);
|
||||
}
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
@ -2276,9 +2281,9 @@ js_fun_call(JSContext *cx, uintN argc, Value *vp)
|
|||
if (!cx->stack().pushInvokeArgs(cx, argc, &args))
|
||||
return JS_FALSE;
|
||||
|
||||
/* Push fval, obj, and the args. */
|
||||
/* Push fval, thisv, and the args. */
|
||||
args.callee() = fval;
|
||||
args.thisv().setObjectOrNull(obj);
|
||||
args.thisv() = thisv;
|
||||
memcpy(args.argv(), argv, argc * sizeof *argv);
|
||||
|
||||
bool ok = Invoke(cx, args, 0);
|
||||
|
@ -2360,11 +2365,17 @@ js_fun_apply(JSContext *cx, uintN argc, Value *vp)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/* Convert the first arg to 'this' and skip over it. */
|
||||
if (vp[2].isObject())
|
||||
obj = &vp[2].toObject();
|
||||
else if (!js_ValueToObjectOrNull(cx, vp[2], &obj))
|
||||
return JS_FALSE;
|
||||
Value thisv;
|
||||
if (vp[2].isNullOrUndefined()) {
|
||||
thisv.setUndefined();
|
||||
} else {
|
||||
if (!js_ValueToObjectOrNull(cx, vp[2], &obj))
|
||||
return JS_FALSE;
|
||||
JS_ASSERT(obj);
|
||||
thisv.setObject(*obj);
|
||||
}
|
||||
|
||||
LeaveTrace(cx);
|
||||
|
||||
|
@ -2377,7 +2388,7 @@ js_fun_apply(JSContext *cx, uintN argc, Value *vp)
|
|||
|
||||
/* Push fval, obj, and aobj's elements as args. */
|
||||
args.callee() = fval;
|
||||
args.thisv().setObjectOrNull(obj);
|
||||
args.thisv() = thisv;
|
||||
|
||||
/* Steps 7-8. */
|
||||
if (aobj && aobj->isArguments() && !aobj->isArgsLengthOverridden()) {
|
||||
|
@ -2525,15 +2536,15 @@ CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp)
|
|||
* very shortly when this-boxing only occurs for non-strict
|
||||
* functions, callee-side, in bug 514570.
|
||||
*/
|
||||
JSObject *boundThisObj;
|
||||
if (boundThis.isObjectOrNull()) {
|
||||
boundThisObj = boundThis.toObjectOrNull();
|
||||
if (boundThis.isNullOrUndefined()) {
|
||||
args.thisv().setUndefined();
|
||||
} else {
|
||||
JSObject *boundThisObj;
|
||||
if (!js_ValueToObjectOrNull(cx, boundThis, &boundThisObj))
|
||||
return false;
|
||||
JS_ASSERT(boundThisObj);
|
||||
args.thisv().setObject(*boundThisObj);
|
||||
}
|
||||
|
||||
args.thisv() = ObjectOrNullValue(boundThisObj);
|
||||
}
|
||||
|
||||
if (constructing ? !InvokeConstructor(cx, args) : !Invoke(cx, args, 0))
|
||||
|
|
|
@ -498,7 +498,7 @@ ComputeThisFromArgv(JSContext *cx, Value *argv)
|
|||
*/
|
||||
JS_ASSERT(!argv[-1].isMagic());
|
||||
|
||||
if (argv[-1].isNull())
|
||||
if (argv[-1].isNullOrUndefined())
|
||||
return ComputeGlobalThis(cx, argv);
|
||||
|
||||
if (!argv[-1].isObject())
|
||||
|
@ -678,7 +678,7 @@ Invoke(JSContext *cx, const CallArgs &argsRef, uint32 flags)
|
|||
JSFunction *fun = callee.getFunctionPrivate();
|
||||
JS_ASSERT_IF(flags & JSINVOKE_CONSTRUCT, !fun->isConstructor());
|
||||
if (fun->isNative()) {
|
||||
JS_ASSERT(args.thisv().isObjectOrNull() || PrimitiveThisTest(fun, args.thisv()));
|
||||
JS_ASSERT(args.thisv().isObject() || args.thisv().isUndefined() || PrimitiveThisTest(fun, args.thisv()));
|
||||
return CallJSNative(cx, fun->u.n.native, args.argc(), args.base());
|
||||
}
|
||||
|
||||
|
@ -4239,7 +4239,7 @@ BEGIN_CASE(JSOP_CALLPROP)
|
|||
/* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
|
||||
JSObject *funobj;
|
||||
if (!IsFunctionObject(rval, &funobj) ||
|
||||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, funobj), lval)) {
|
||||
!PrimitiveThisTest(funobj->getFunctionPrivate(), lval)) {
|
||||
if (!js_PrimitiveToObject(cx, ®s.sp[-1]))
|
||||
goto error;
|
||||
}
|
||||
|
@ -4721,7 +4721,7 @@ BEGIN_CASE(JSOP_APPLY)
|
|||
DO_OP();
|
||||
}
|
||||
|
||||
JS_ASSERT(vp[1].isObjectOrNull() || PrimitiveThisTest(newfun, vp[1]));
|
||||
JS_ASSERT(vp[1].isObject() || vp[1].isUndefined() || PrimitiveThisTest(newfun, vp[1]));
|
||||
|
||||
Probes::enterJSFun(cx, newfun);
|
||||
JSBool ok = CallJSNative(cx, newfun->u.n.native, argc, vp);
|
||||
|
@ -4766,15 +4766,17 @@ END_CASE(JSOP_SETCALL)
|
|||
(clasp = thisp->getClass()) == &js_CallClass || \
|
||||
clasp == &js_BlockClass || \
|
||||
clasp == &js_DeclEnvClass) { \
|
||||
/* Normal case: thisp is global or an activation record. */ \
|
||||
/* Callee determines |this|. */ \
|
||||
thisp = NULL; \
|
||||
/* Push the ImplicitThisValue for the Environment Record */ \
|
||||
/* associated with obj. See ES5 sections 10.2.1.1.6 and */ \
|
||||
/* 10.2.1.2.6 (ImplicitThisValue) and section 11.2.3 */ \
|
||||
/* (Function Calls). */ \
|
||||
PUSH_UNDEFINED(); \
|
||||
} else { \
|
||||
thisp = thisp->thisObject(cx); \
|
||||
if (!thisp) \
|
||||
goto error; \
|
||||
PUSH_OBJECT(*thisp); \
|
||||
} \
|
||||
PUSH_OBJECT_OR_NULL(thisp); \
|
||||
JS_END_MACRO
|
||||
|
||||
BEGIN_CASE(JSOP_GETGNAME)
|
||||
|
@ -4819,7 +4821,7 @@ BEGIN_CASE(JSOP_CALLNAME)
|
|||
clasp == &js_DeclEnvClass);
|
||||
#endif
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
|
||||
PUSH_NULL();
|
||||
PUSH_UNDEFINED();
|
||||
len = JSOP_NAME_LENGTH;
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
|
@ -5180,7 +5182,7 @@ BEGIN_CASE(JSOP_CALLARG)
|
|||
METER_SLOT_OP(op, slot);
|
||||
PUSH_COPY(argv[slot]);
|
||||
if (op == JSOP_CALLARG)
|
||||
PUSH_NULL();
|
||||
PUSH_UNDEFINED();
|
||||
}
|
||||
END_CASE(JSOP_GETARG)
|
||||
|
||||
|
@ -5206,7 +5208,7 @@ BEGIN_CASE(JSOP_CALLLOCAL)
|
|||
uint32 slot = GET_SLOTNO(regs.pc);
|
||||
JS_ASSERT(slot < script->nslots);
|
||||
PUSH_COPY(regs.fp->slots()[slot]);
|
||||
PUSH_NULL();
|
||||
PUSH_UNDEFINED();
|
||||
}
|
||||
END_CASE(JSOP_CALLLOCAL)
|
||||
|
||||
|
@ -5230,7 +5232,7 @@ BEGIN_CASE(JSOP_CALLUPVAR)
|
|||
PUSH_COPY(rval);
|
||||
|
||||
if (op == JSOP_CALLUPVAR)
|
||||
PUSH_NULL();
|
||||
PUSH_UNDEFINED();
|
||||
}
|
||||
END_CASE(JSOP_GETUPVAR)
|
||||
|
||||
|
@ -5272,7 +5274,7 @@ BEGIN_CASE(JSOP_CALLUPVAR_DBG)
|
|||
goto error;
|
||||
|
||||
if (op == JSOP_CALLUPVAR_DBG)
|
||||
PUSH_NULL();
|
||||
PUSH_UNDEFINED();
|
||||
}
|
||||
END_CASE(JSOP_GETUPVAR_DBG)
|
||||
|
||||
|
@ -5286,7 +5288,7 @@ BEGIN_CASE(JSOP_CALLFCSLOT)
|
|||
JS_ASSERT(index < obj->getFunctionPrivate()->u.i.nupvars);
|
||||
PUSH_COPY(obj->getFlatClosureUpvar(index));
|
||||
if (op == JSOP_CALLFCSLOT)
|
||||
PUSH_NULL();
|
||||
PUSH_UNDEFINED();
|
||||
}
|
||||
END_CASE(JSOP_GETFCSLOT)
|
||||
|
||||
|
@ -5299,7 +5301,7 @@ BEGIN_CASE(JSOP_CALLGLOBAL)
|
|||
JS_ASSERT(obj->containsSlot(slot));
|
||||
PUSH_COPY(obj->getSlot(slot));
|
||||
if (op == JSOP_CALLGLOBAL)
|
||||
PUSH_NULL();
|
||||
PUSH_UNDEFINED();
|
||||
}
|
||||
END_CASE(JSOP_GETGLOBAL)
|
||||
|
||||
|
|
|
@ -5926,12 +5926,14 @@ js_PrimitiveToObject(JSContext *cx, Value *vp)
|
|||
JS_ASSERT(v.isPrimitive());
|
||||
|
||||
Class *clasp;
|
||||
if (v.isNumber())
|
||||
if (v.isNumber()) {
|
||||
clasp = &js_NumberClass;
|
||||
else if (v.isString())
|
||||
} else if (v.isString()) {
|
||||
clasp = &js_StringClass;
|
||||
else
|
||||
} else {
|
||||
JS_ASSERT(v.isBoolean());
|
||||
clasp = &js_BooleanClass;
|
||||
}
|
||||
|
||||
JSObject *obj = NewBuiltinClassInstance(cx, clasp);
|
||||
if (!obj)
|
||||
|
|
|
@ -4117,8 +4117,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
} else {
|
||||
JS_NOT_REACHED("should see block chain operation");
|
||||
}
|
||||
LOCAL_ASSERT(*pc == JSOP_NULL);
|
||||
pc += JSOP_NULL_LENGTH;
|
||||
LOCAL_ASSERT(*pc == JSOP_PUSH);
|
||||
pc += JSOP_PUSH_LENGTH;
|
||||
LOCAL_ASSERT(*pc == JSOP_CALL);
|
||||
LOCAL_ASSERT(GET_ARGC(pc) == 0);
|
||||
len = JSOP_CALL_LENGTH;
|
||||
|
|
|
@ -856,7 +856,7 @@ Class js_StringClass = {
|
|||
static JSString *
|
||||
NormalizeThis(JSContext *cx, Value *vp)
|
||||
{
|
||||
if (vp[1].isNull() && (!ComputeThisFromVp(cx, vp) || vp[1].isNull()))
|
||||
if (vp[1].isNullOrUndefined() && !ComputeThisFromVp(cx, vp))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
|
@ -2100,7 +2100,7 @@ FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t
|
|||
InvokeSessionGuard &session = rdata.session;
|
||||
if (!session.started()) {
|
||||
Value lambdav = ObjectValue(*lambda);
|
||||
if (!rdata.session.start(cx, lambdav, NullValue(), argc))
|
||||
if (!session.start(cx, lambdav, UndefinedValue(), argc))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2409,7 +2409,7 @@ str_replace_flat_lambda(JSContext *cx, uintN argc, Value *vp, ReplaceData &rdata
|
|||
|
||||
CallArgs &args = rdata.singleShot;
|
||||
args.callee().setObject(*rdata.lambda);
|
||||
args.thisv().setNull();
|
||||
args.thisv().setUndefined();
|
||||
|
||||
Value *sp = args.argv();
|
||||
sp[0].setString(matchStr);
|
||||
|
|
|
@ -7063,12 +7063,6 @@ LeaveTree(TraceMonitor *tm, TracerState& state, VMSideExit* lr)
|
|||
JS_ASSERT(state.eos == state.stackBase + MAX_NATIVE_STACK_SLOTS);
|
||||
JSObject* globalObj = outermostTree->globalObj;
|
||||
FlushNativeGlobalFrame(cx, globalObj, state.eos, ngslots, gslots, globalTypeMap);
|
||||
#ifdef DEBUG
|
||||
/* Verify that our state restoration worked. */
|
||||
for (JSStackFrame* fp = cx->fp(); fp; fp = fp->prev()) {
|
||||
JS_ASSERT_IF(fp->isFunctionFrame(), fp->thisValue().isObjectOrNull());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JS_JIT_SPEW
|
||||
if (innermost->exitType != TIMEOUT_EXIT)
|
||||
|
@ -10063,10 +10057,10 @@ TraceRecorder::getThis(LIns*& this_ins)
|
|||
JS_ASSERT(fp->callee().getGlobal() == globalObj);
|
||||
const Value& thisv = fp->thisValue();
|
||||
|
||||
if (!thisv.isNull()) {
|
||||
if (!thisv.isUndefined()) {
|
||||
/*
|
||||
* fp->argv[-1] has already been computed. Since the type-specialization
|
||||
* of traces distinguishes between null and objects, the same will be
|
||||
* of traces distinguishes between |undefined| and objects, the same will be
|
||||
* true at run time (or we won't get this far).
|
||||
*/
|
||||
this_ins = get(&fp->thisValue());
|
||||
|
@ -13139,7 +13133,7 @@ TraceRecorder::record_JSOP_CALLNAME()
|
|||
NameResult nr;
|
||||
CHECK_STATUS_A(scopeChainProp(obj, vp, ins, nr));
|
||||
stack(0, ins);
|
||||
stack(1, INS_NULL());
|
||||
stack(1, INS_UNDEFINED());
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -13153,7 +13147,7 @@ TraceRecorder::record_JSOP_CALLNAME()
|
|||
RETURN_STOP_A("callee is not an object");
|
||||
|
||||
stack(0, INS_CONSTOBJ(&pcval.toFunObj()));
|
||||
stack(1, INS_NULL());
|
||||
stack(1, INS_UNDEFINED());
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -13282,7 +13276,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus
|
|||
TraceRecorder::record_JSOP_CALLUPVAR()
|
||||
{
|
||||
CHECK_STATUS_A(record_JSOP_GETUPVAR());
|
||||
stack(1, INS_NULL());
|
||||
stack(1, INS_UNDEFINED());
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -13306,7 +13300,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus
|
|||
TraceRecorder::record_JSOP_CALLFCSLOT()
|
||||
{
|
||||
CHECK_STATUS_A(record_JSOP_GETFCSLOT());
|
||||
stack(1, INS_NULL());
|
||||
stack(1, INS_UNDEFINED());
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -15954,7 +15948,7 @@ TraceRecorder::record_JSOP_CALLLOCAL()
|
|||
{
|
||||
uintN slot = GET_SLOTNO(cx->regs->pc);
|
||||
stack(0, var(slot));
|
||||
stack(1, INS_NULL());
|
||||
stack(1, INS_UNDEFINED());
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -15963,7 +15957,7 @@ TraceRecorder::record_JSOP_CALLARG()
|
|||
{
|
||||
uintN slot = GET_ARGNO(cx->regs->pc);
|
||||
stack(0, arg(slot));
|
||||
stack(1, INS_NULL());
|
||||
stack(1, INS_UNDEFINED());
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -16167,7 +16161,7 @@ TraceRecorder::record_JSOP_CALLGLOBAL()
|
|||
|
||||
Value &v = globalObj->getSlotRef(slot);
|
||||
stack(0, get(&v));
|
||||
stack(1, INS_NULL());
|
||||
stack(1, INS_UNDEFINED());
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -1208,7 +1208,7 @@ mjit::Compiler::generateMethod()
|
|||
{
|
||||
jsop_getarg(GET_SLOTNO(PC));
|
||||
if (op == JSOP_CALLARG)
|
||||
frame.push(NullValue());
|
||||
frame.push(UndefinedValue());
|
||||
}
|
||||
END_CASE(JSOP_GETARG)
|
||||
|
||||
|
@ -1497,7 +1497,7 @@ mjit::Compiler::generateMethod()
|
|||
frame.freeReg(reg);
|
||||
frame.push(Address(reg, index * sizeof(Value)));
|
||||
if (op == JSOP_CALLFCSLOT)
|
||||
frame.push(NullValue());
|
||||
frame.push(UndefinedValue());
|
||||
}
|
||||
END_CASE(JSOP_CALLFCSLOT)
|
||||
|
||||
|
@ -1536,7 +1536,7 @@ mjit::Compiler::generateMethod()
|
|||
BEGIN_CASE(JSOP_CALLGNAME)
|
||||
jsop_getgname(fullAtomIndex(PC));
|
||||
if (op == JSOP_CALLGNAME)
|
||||
frame.push(NullValue());
|
||||
frame.push(UndefinedValue());
|
||||
END_CASE(JSOP_GETGNAME)
|
||||
|
||||
BEGIN_CASE(JSOP_SETGNAME)
|
||||
|
@ -1571,7 +1571,7 @@ mjit::Compiler::generateMethod()
|
|||
stubCall(stubs::GetUpvar);
|
||||
frame.pushSynced();
|
||||
if (op == JSOP_CALLUPVAR)
|
||||
frame.push(NullValue());
|
||||
frame.push(UndefinedValue());
|
||||
}
|
||||
END_CASE(JSOP_CALLUPVAR)
|
||||
|
||||
|
@ -1607,7 +1607,7 @@ mjit::Compiler::generateMethod()
|
|||
|
||||
BEGIN_CASE(JSOP_CALLLOCAL)
|
||||
frame.pushLocal(GET_SLOTNO(PC));
|
||||
frame.push(NullValue());
|
||||
frame.push(UndefinedValue());
|
||||
END_CASE(JSOP_CALLLOCAL)
|
||||
|
||||
BEGIN_CASE(JSOP_INT8)
|
||||
|
@ -1682,7 +1682,7 @@ mjit::Compiler::generateMethod()
|
|||
BEGIN_CASE(JSOP_CALLGLOBAL)
|
||||
jsop_getglobal(GET_SLOTNO(PC));
|
||||
if (op == JSOP_CALLGLOBAL)
|
||||
frame.push(NullValue());
|
||||
frame.push(UndefinedValue());
|
||||
END_CASE(JSOP_GETGLOBAL)
|
||||
|
||||
BEGIN_CASE(JSOP_SETGLOBAL)
|
||||
|
@ -3314,7 +3314,7 @@ mjit::Compiler::jsop_this()
|
|||
{
|
||||
Address thisvAddr(JSFrameReg, JSStackFrame::offsetOfThis(fun));
|
||||
if (0 && !script->strictModeCode) {
|
||||
Jump null = masm.testNull(Assembler::Equal, thisvAddr);
|
||||
Jump null = masm.testUndefined(Assembler::Equal, thisvAddr);
|
||||
stubcc.linkExit(null, Uses(1));
|
||||
stubcc.leave();
|
||||
stubcc.call(stubs::ComputeThis);
|
||||
|
@ -3325,7 +3325,7 @@ mjit::Compiler::jsop_this()
|
|||
frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
|
||||
} else {
|
||||
frame.push(thisvAddr);
|
||||
Jump null = frame.testNull(Assembler::Equal, frame.peek(-1));
|
||||
Jump null = frame.testUndefined(Assembler::Equal, frame.peek(-1));
|
||||
stubcc.linkExit(null, Uses(1));
|
||||
stubcc.leave();
|
||||
stubcc.call(stubs::This);
|
||||
|
|
|
@ -567,6 +567,15 @@ FrameState::testNull(Assembler::Condition cond, FrameEntry *fe)
|
|||
return masm.testNull(cond, tempRegForType(fe));
|
||||
}
|
||||
|
||||
inline JSC::MacroAssembler::Jump
|
||||
FrameState::testUndefined(Assembler::Condition cond, FrameEntry *fe)
|
||||
{
|
||||
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
|
||||
if (shouldAvoidTypeRemat(fe))
|
||||
return masm.testUndefined(cond, addressOf(fe));
|
||||
return masm.testUndefined(cond, tempRegForType(fe));
|
||||
}
|
||||
|
||||
inline JSC::MacroAssembler::Jump
|
||||
FrameState::testInt32(Assembler::Condition cond, FrameEntry *fe)
|
||||
{
|
||||
|
|
|
@ -660,43 +660,49 @@ class FrameState
|
|||
void discardFe(FrameEntry *fe);
|
||||
|
||||
/*
|
||||
* Helper function. Tests if a slot's type is null. Condition should
|
||||
* Helper function. Tests if a slot's type is null. Condition must
|
||||
* be Equal or NotEqual.
|
||||
*/
|
||||
inline Jump testNull(Assembler::Condition cond, FrameEntry *fe);
|
||||
|
||||
/*
|
||||
* Helper function. Tests if a slot's type is an integer. Condition should
|
||||
* Helper function. Tests if a slot's type is undefined. Condition must
|
||||
* be Equal or NotEqual.
|
||||
*/
|
||||
inline Jump testUndefined(Assembler::Condition cond, FrameEntry *fe);
|
||||
|
||||
/*
|
||||
* Helper function. Tests if a slot's type is an integer. Condition must
|
||||
* be Equal or NotEqual.
|
||||
*/
|
||||
inline Jump testInt32(Assembler::Condition cond, FrameEntry *fe);
|
||||
|
||||
/*
|
||||
* Helper function. Tests if a slot's type is a double. Condition should
|
||||
* Helper function. Tests if a slot's type is a double. Condition must
|
||||
* be Equal or Not Equal.
|
||||
*/
|
||||
inline Jump testDouble(Assembler::Condition cond, FrameEntry *fe);
|
||||
|
||||
/*
|
||||
* Helper function. Tests if a slot's type is a boolean. Condition should
|
||||
* Helper function. Tests if a slot's type is a boolean. Condition must
|
||||
* be Equal or NotEqual.
|
||||
*/
|
||||
inline Jump testBoolean(Assembler::Condition cond, FrameEntry *fe);
|
||||
|
||||
/*
|
||||
* Helper function. Tests if a slot's type is a string. Condition should
|
||||
* Helper function. Tests if a slot's type is a string. Condition must
|
||||
* be Equal or NotEqual.
|
||||
*/
|
||||
inline Jump testString(Assembler::Condition cond, FrameEntry *fe);
|
||||
|
||||
/*
|
||||
* Helper function. Tests if a slot's type is a non-funobj. Condition should
|
||||
* Helper function. Tests if a slot's type is a non-funobj. Condition must
|
||||
* be Equal or NotEqual.
|
||||
*/
|
||||
inline Jump testObject(Assembler::Condition cond, FrameEntry *fe);
|
||||
|
||||
/*
|
||||
* Helper function. Tests if a slot's type is primitve. Condition should
|
||||
* Helper function. Tests if a slot's type is primitive. Condition must
|
||||
* be Equal or NotEqual.
|
||||
*/
|
||||
inline Jump testPrimitive(Assembler::Condition cond, FrameEntry *fe);
|
||||
|
|
|
@ -215,6 +215,14 @@ class Assembler : public BaseAssembler
|
|||
return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_NULL));
|
||||
}
|
||||
|
||||
Jump testUndefined(Assembler::Condition cond, RegisterID reg) {
|
||||
return branch32(cond, reg, ImmTag(JSVAL_TAG_UNDEFINED));
|
||||
}
|
||||
|
||||
Jump testUndefined(Assembler::Condition cond, Address address) {
|
||||
return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_UNDEFINED));
|
||||
}
|
||||
|
||||
Jump testInt32(Assembler::Condition cond, RegisterID reg) {
|
||||
return branch32(cond, reg, ImmTag(JSVAL_TAG_INT32));
|
||||
}
|
||||
|
|
|
@ -236,6 +236,15 @@ class Assembler : public BaseAssembler
|
|||
return branchPtr(cond, Registers::ValueReg, Imm64(JSVAL_BITS(JSVAL_NULL)));
|
||||
}
|
||||
|
||||
Jump testUndefined(Assembler::Condition cond, RegisterID reg) {
|
||||
return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_UNDEFINED));
|
||||
}
|
||||
|
||||
Jump testUndefined(Assembler::Condition cond, Address address) {
|
||||
loadValue(address, Registers::ValueReg);
|
||||
return branchPtr(cond, Registers::ValueReg, Imm64(JSVAL_BITS(JSVAL_VOID)));
|
||||
}
|
||||
|
||||
Jump testInt32(Assembler::Condition cond, RegisterID reg) {
|
||||
return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_INT32));
|
||||
}
|
||||
|
|
|
@ -371,7 +371,7 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false)
|
|||
#endif
|
||||
if (callname) {
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setNull();
|
||||
f.regs.sp[-1].setUndefined();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
@ -416,14 +416,15 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false)
|
|||
(clasp = thisp->getClass()) == &js_CallClass ||
|
||||
clasp == &js_BlockClass ||
|
||||
clasp == &js_DeclEnvClass) {
|
||||
thisp = NULL;
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setUndefined();
|
||||
} else {
|
||||
thisp = thisp->thisObject(cx);
|
||||
if (!thisp)
|
||||
return NULL;
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setObject(*thisp);
|
||||
}
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setObjectOrNull(thisp);
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
@ -2161,7 +2162,7 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom)
|
|||
/* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
|
||||
JSObject *funobj;
|
||||
if (!IsFunctionObject(rval, &funobj) ||
|
||||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, funobj), lval)) {
|
||||
!PrimitiveThisTest(funobj->getFunctionPrivate(), lval)) {
|
||||
if (!js_PrimitiveToObject(cx, ®s.sp[-1]))
|
||||
THROW();
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче