Merge tracemonkey to mozilla-central.

This commit is contained in:
Robert Sayre 2009-05-30 01:29:06 -07:00
commit d05b84c5aa
4 changed files with 52 additions and 31 deletions

View File

@ -220,30 +220,22 @@ ValueIsLength(JSContext *cx, jsval* vp)
JSBool
js_GetLengthProperty(JSContext *cx, JSObject *obj, jsuint *lengthp)
{
JSTempValueRooter tvr;
jsid id;
JSBool ok;
jsint i;
if (OBJ_IS_ARRAY(cx, obj)) {
*lengthp = obj->fslots[JSSLOT_ARRAY_LENGTH];
return JS_TRUE;
}
JS_PUSH_SINGLE_TEMP_ROOT(cx, JSVAL_NULL, &tvr);
id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom);
ok = OBJ_GET_PROPERTY(cx, obj, id, &tvr.u.value);
if (ok) {
if (JSVAL_IS_INT(tvr.u.value)) {
i = JSVAL_TO_INT(tvr.u.value);
*lengthp = (jsuint)i; /* jsuint cast does ToUint32 */
} else {
*lengthp = js_ValueToECMAUint32(cx, &tvr.u.value);
ok = !JSVAL_IS_NULL(tvr.u.value);
}
JSAutoTempValueRooter tvr(cx, JSVAL_NULL);
if (!OBJ_GET_PROPERTY(cx, obj, ATOM_TO_JSID(cx->runtime->atomState.lengthAtom), tvr.addr()))
return JS_FALSE;
if (JSVAL_IS_INT(tvr.value())) {
*lengthp = jsuint(jsint(JSVAL_TO_INT(tvr.value()))); /* jsuint cast does ToUint32 */
return JS_TRUE;
}
JS_POP_TEMP_ROOT(cx, &tvr);
return ok;
*lengthp = js_ValueToECMAUint32(cx, tvr.addr());
return !JSVAL_IS_NULL(tvr.value());
}
static JSBool

View File

@ -1863,7 +1863,7 @@ js_GetUpvarOnTrace(JSContext* cx, uint32 level, uint32 cookie, uint32 callDepth,
* activation record corresponding to *fip in the native
* stack.
*/
uintN nativeStackFramePos = state->callstackBase[0]->caller_argc;
uintN nativeStackFramePos = state->callstackBase[0]->spoffset;
for (FrameInfo** fip2 = state->callstackBase; fip2 <= fip; fip2++)
nativeStackFramePos += (*fip2)->s.spdist;
nativeStackFramePos -= (2 + (*fip)->s.argc);
@ -2465,6 +2465,10 @@ TraceRecorder::createGuardRecord(VMSideExit* exit)
JS_REQUIRES_STACK void
TraceRecorder::guard(bool expected, LIns* cond, VMSideExit* exit)
{
debug_only_v(nj_dprintf(" About to try emitting guard code for "
"SideExit=%p exitType=%d\n",
(void*)exit, exit->exitType);)
LIns* guardRec = createGuardRecord(exit);
/*
@ -2483,10 +2487,8 @@ TraceRecorder::guard(bool expected, LIns* cond, VMSideExit* exit)
LIns* guardIns =
lir->insGuard(expected ? LIR_xf : LIR_xt, cond, guardRec);
if (guardIns) {
debug_only_v(nj_dprintf(" SideExit=%p exitType=%d\n", (void*)exit, exit->exitType);)
} else {
debug_only_v(nj_dprintf(" redundant guard, eliminated\n");)
if (!guardIns) {
debug_only_v(nj_dprintf(" redundant guard, eliminated, no codegen\n");)
}
}
@ -5325,7 +5327,9 @@ js_PurgeScriptFragments(JSContext* cx, JSScript* script)
(void*)frag, frag->ip, script->code,
script->code + script->length));
VMFragment* next = frag->next;
js_TrashTree(cx, frag);
for (Fragment *p = frag; p; p = p->peer)
js_TrashTree(cx, p);
tm->fragmento->clearFragment(frag);
*f = next;
} else {
f = &((*f)->next);
@ -6473,7 +6477,7 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2
if (aobj != globalObj) {
LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)),
"shape");
guard(true, addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(kshape)"),
guard(true, addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(kshape)(test_property_cache)"),
BRANCH_EXIT);
}
} else {
@ -6517,7 +6521,7 @@ TraceRecorder::test_property_cache(JSObject* obj, LIns* obj_ins, JSObject*& obj2
LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)),
"shape");
guard(true,
addName(lir->ins2i(LIR_eq, shape_ins, vshape), "guard(vshape)"),
addName(lir->ins2i(LIR_eq, shape_ins, vshape), "guard(vshape)(test_property_cache)"),
BRANCH_EXIT);
}
@ -6683,6 +6687,10 @@ TraceRecorder::unbox_jsval(jsval v, LIns*& v_ins, VMSideExit* exit)
JS_REQUIRES_STACK JSRecordingStatus
TraceRecorder::getThis(LIns*& this_ins)
{
/*
* js_ComputeThisForFrame updates cx->fp->argv[-1], so sample it into 'original' first.
*/
jsval original = cx->fp->callee ? cx->fp->argv[-1] : JSVAL_NULL;
JSObject* thisObj = js_ComputeThisForFrame(cx, cx->fp);
if (!thisObj)
ABORT_TRACE_ERROR("js_ComputeThisForName failed");
@ -6709,7 +6717,7 @@ TraceRecorder::getThis(LIns*& this_ins)
* can only detect this condition prior to calling js_ComputeThisForFrame, since it
* updates the interpreter's copy of argv[-1].
*/
if (JSVAL_IS_NULL(thisv)) {
if (JSVAL_IS_NULL(original)) {
JS_ASSERT(!JSVAL_IS_PRIMITIVE(thisv));
if (thisObj != globalObj)
ABORT_TRACE("global object was wrapped while recording");
@ -6726,6 +6734,7 @@ TraceRecorder::getThis(LIns*& this_ins)
* are wrapped as we obtain them through XPConnect. The only exception are With objects,
* which have to call the getThis object hook. We don't trace those cases.
*/
JS_ASSERT(original == thisv);
if (guardClass(JSVAL_TO_OBJECT(thisv), this_ins, &js_WithClass, snapshot(MISMATCH_EXIT)))
ABORT_TRACE("can't trace getThis on With object");
@ -8046,7 +8055,7 @@ TraceRecorder::record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop
ABORT_TRACE("non-native map");
LIns* shape_ins = addName(lir->insLoad(LIR_ld, map_ins, offsetof(JSScope, shape)), "shape");
guard(true, addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(kshape)"),
guard(true, addName(lir->ins2i(LIR_eq, shape_ins, entry->kshape), "guard(kshape)(record_SetPropHit)"),
BRANCH_EXIT);
uint32 vshape = PCVCAP_SHAPE(entry->vcap);
@ -8054,7 +8063,7 @@ TraceRecorder::record_SetPropHit(JSPropCacheEntry* entry, JSScopeProperty* sprop
LIns *vshape_ins = lir->insLoad(LIR_ld,
lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, runtime)),
offsetof(JSRuntime, protoHazardShape));
guard(true, addName(lir->ins2i(LIR_eq, vshape_ins, vshape), "guard(vshape)"),
guard(true, addName(lir->ins2i(LIR_eq, vshape_ins, vshape), "guard(vshape)(record_SetPropHit)"),
MISMATCH_EXIT);
LIns* args[] = { INS_CONSTPTR(sprop), obj_ins, cx_ins };
@ -8542,11 +8551,13 @@ TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc,
fi->imacpc = fp->imacpc;
fi->s.spdist = fp->regs->sp - fp->slots;
fi->s.argc = argc | (constructing ? 0x8000 : 0);
fi->caller_argc = 2 + fp->argc;
fi->spoffset = 2 /*callee,this*/ + fp->argc;
unsigned callDepth = getCallDepth();
if (callDepth >= treeInfo->maxCallDepth)
treeInfo->maxCallDepth = callDepth + 1;
if (callDepth == 0)
fi->spoffset = 2 /*callee,this*/ + argc - fi->s.spdist;
lir->insStorei(INS_CONSTPTR(fi), lirbuf->rp, callDepth * sizeof(FrameInfo*));

View File

@ -298,7 +298,16 @@ struct FrameInfo {
} s;
uint32 word; // for spdist/argc LIR store in record_JSOP_CALL
};
uint32 caller_argc; // fp->argv - stackBase
/*
* Stack pointer adjustment needed for navigation of native stack in
* js_GetUpvarOnTrace. spoffset is the number of slots in the native
* stack frame for the caller *before* the slots covered by spdist.
* This may be negative if the caller is the top level script.
* The key fact is that if we let 'cpos' be the start of the caller's
* native stack frame, then (cpos + spoffset) points to the first
* non-argument slot in the callee's native stack frame.
*/
int32 spoffset;
};
struct UnstableExit

View File

@ -5234,6 +5234,15 @@ function testGetCallObj() {
testGetCallObj.expected = "ok";
test(testGetCallObj);
function testGetThis() {
for (var i = 0; i < 3; ++i) {
(function() { return this; })();
}
return "ok";
}
testGetThis.expected = "ok";
test(testGetThis);
/*****************************************************************************
* *
* _____ _ _ _____ ______ _____ _______ *