Merge tracemonkey to mozilla-central.

This commit is contained in:
Robert Sayre 2009-05-12 23:19:58 -04:00
commit f3cf0427b7
6 changed files with 123 additions and 25 deletions

View File

@ -211,6 +211,7 @@ struct JSTraceableNative {
#define _JS_CTYPE_INTERPSTATE _JS_CTYPE(InterpState *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_FRAGMENT _JS_CTYPE(nanojit::Fragment *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_CLASS _JS_CTYPE(JSClass *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_CTYPE_DOUBLEPTR _JS_CTYPE(double *, _JS_PTR, --, --, INFALLIBLE)
#define _JS_EXPAND(tokens) tokens

View File

@ -2024,7 +2024,7 @@ js_DoIncDec(JSContext *cx, const JSCodeSpec *cs, jsval *vp, jsval *vp2)
return JS_TRUE;
}
jsval
jsval&
js_GetUpvar(JSContext *cx, uintN level, uintN cookie)
{
level -= UPVAR_FRAME_SKIP(cookie);

View File

@ -555,7 +555,7 @@ js_InternNonIntElementId(JSContext *cx, JSObject *obj, jsval idval, jsid *idp);
* Given an active context, a static scope level, and an upvar cookie, return
* the value of the upvar.
*/
extern jsval
extern jsval&
js_GetUpvar(JSContext *cx, uintN level, uintN cookie);
/*

View File

@ -367,7 +367,7 @@ Tracker::set(const void* v, LIns* i)
p->map[(jsuword(v) & PAGEMASK) >> 2] = i;
}
static inline jsint argSlots(JSStackFrame* fp)
static inline jsuint argSlots(JSStackFrame* fp)
{
return JS_MAX(fp->argc, fp->fun->nargs);
}
@ -1238,7 +1238,7 @@ TypeMap::captureTypes(JSContext* cx, SlotList& slots, unsigned callDepth)
if ((type == JSVAL_INT) && oracle.isStackSlotUndemotable(cx, unsigned(m - map)))
type = JSVAL_DOUBLE;
JS_ASSERT(type != JSVAL_BOXED);
debug_only_v(printf("capture stack type %s%d: %d=%c vp=%p v=%x\n", vpname, vpnum, type, typeChar[type], vp, (uint32) *vp);)
debug_only_v(printf("capture stack type %s%d: %d=%c\n", vpname, vpnum, type, typeChar[type]);)
JS_ASSERT(uintptr_t(m - map) < length());
*m++ = type;
);
@ -1838,6 +1838,47 @@ FlushNativeGlobalFrame(JSContext* cx, unsigned ngslots, uint16* gslots, uint8* m
return mp - mp_base;
}
/*
* Builtin to get an upvar on trace. See js_GetUpvar for the meaning
* of the first three arguments. The value of the upvar is stored in
* *result as an unboxed native. The return value is the typemap type.
*/
uint32 JS_FASTCALL
js_GetUpvarOnTrace(JSContext *cx, uint32 level, uint32 cookie, double* result)
{
uintN skip = UPVAR_FRAME_SKIP(cookie);
InterpState* state = cx->interpState;
uintN callDepth = state->rp - state->callstackBase;
/*
* If we are skipping past all frames that are part of active traces,
* then we simply get the value from the interpreter state.
*/
if (skip > callDepth) {
jsval v = js_GetUpvar(cx, level, cookie);
uint8 type = getCoercedType(v);
ValueToNative(cx, v, type, result);
return type;
}
/*
* The value we need is logically in a stack frame that is part of
* an active trace. We reconstruct the value we need from the tracer
* stack records.
*/
uintN frameIndex = callDepth - skip; // pos of target frame in rp stack
uintN nativeStackFramePos = 0; // pos of target stack frame in sp stack
for (uintN i = 0; i < frameIndex; ++i)
nativeStackFramePos += state->callstackBase[i]->s.spdist;
FrameInfo* fi = state->callstackBase[frameIndex];
uint8* typemap = (uint8*) (fi+1);
uintN slot = UPVAR_FRAME_SLOT(cookie);
slot = slot == CALLEE_UPVAR_SLOT ? 0 : slot + 2;
*result = state->stackBase[nativeStackFramePos + slot];
return typemap[slot];
}
/**
* Box the given native stack frame into the virtual machine stack. This
* is infallible.
@ -8282,6 +8323,8 @@ TraceRecorder::record_JSOP_CALLNAME()
return JSRS_CONTINUE;
}
JS_DEFINE_CALLINFO_4(extern, UINT32, js_GetUpvarOnTrace, CONTEXT, UINT32, UINT32, DOUBLEPTR, 0, 0)
JS_REQUIRES_STACK JSRecordingStatus
TraceRecorder::record_JSOP_GETUPVAR()
{
@ -8291,26 +8334,60 @@ TraceRecorder::record_JSOP_GETUPVAR()
JSUpvarArray* uva = JS_SCRIPT_UPVARS(script);
JS_ASSERT(index < uva->length);
uintN skip = UPVAR_FRAME_SKIP(uva->vector[index]);
if (skip > callDepth)
ABORT_TRACE("upvar out of reach");
JSStackFrame* fp2 = cx->display[script->staticLevel - skip];
JS_ASSERT(fp2->script);
uintN slot = UPVAR_FRAME_SLOT(uva->vector[index]);
jsval* vp;
if (!fp2->fun) {
vp = fp2->slots + fp2->script->nfixed;
} else if (slot < fp2->fun->nargs) {
vp = fp2->argv;
} else {
slot -= fp2->fun->nargs;
JS_ASSERT(slot < fp2->script->nslots);
vp = fp2->slots;
/*
* Try to find the upvar in the current trace's tracker.
*/
jsval& v = js_GetUpvar(cx, script->staticLevel, uva->vector[index]);
LIns* upvar_ins = get(&v);
if (upvar_ins) {
stack(0, upvar_ins);
return JSRS_CONTINUE;
}
stack(0, get(&vp[slot]));
/*
* The upvar is not in the current trace, so get the upvar value
* exactly as the interpreter does and unbox.
*/
LIns* outp = lir->insAlloc(sizeof(double));
LIns* args[] = {
outp,
lir->insImm(uva->vector[index]),
lir->insImm(script->staticLevel),
cx_ins
};
const CallInfo* ci = &js_GetUpvarOnTrace_ci;
LIns* call_ins = lir->insCall(ci, args);
uint8 type = getCoercedType(v);
guard(true,
addName(lir->ins2(LIR_eq, call_ins, lir->insImm(type)),
"guard(type-stable upvar)"),
BRANCH_EXIT);
LOpcode loadOp;
switch (type) {
case JSVAL_DOUBLE:
loadOp = LIR_ldq;
break;
case JSVAL_OBJECT:
case JSVAL_STRING:
case JSVAL_TFUN:
case JSVAL_TNULL:
loadOp = LIR_ldp;
break;
case JSVAL_INT:
case JSVAL_BOOLEAN:
loadOp = LIR_ld;
break;
case JSVAL_BOXED:
default:
JS_NOT_REACHED("found boxed type in an upvar type map entry");
return JSRS_STOP;
}
LIns* result = lir->insLoad(loadOp, outp, lir->insImm(0));
if (type == JSVAL_INT)
result = lir->ins1(LIR_i2f, result);
stack(0, result);
return JSRS_CONTINUE;
}
@ -10527,13 +10604,20 @@ TraceRecorder::record_JSOP_NEWARRAY()
guard(false, lir->ins_eq0(v_ins), OOM_EXIT);
LIns* dslots_ins = NULL;
uint32 count = 0;
for (uint32 i = 0; i < len; i++) {
jsval& v = stackval(int(i) - int(len));
if (v != JSVAL_HOLE)
count++;
LIns* elt_ins = get(&v);
box_jsval(v, elt_ins);
stobj_set_dslot(v_ins, i, dslots_ins, elt_ins, "set_array_elt");
}
LIns* dummy = NULL;
if (count > 0)
stobj_set_slot(v_ins, JSSLOT_ARRAY_COUNT, dummy, INS_CONST(count));
stack(-int(len), v_ins);
return JSRS_CONTINUE;
}

View File

@ -367,7 +367,7 @@ typedef enum JSBuiltinStatus {
struct InterpState
{
double *sp; // native stack pointer, stack[0] is spbase[0]
void *rp; // call stack pointer
FrameInfo** rp; // call stack pointer
JSContext *cx; // current VM context handle
double *eos; // first unusable word after the native stack
void *eor; // first unusable word after the call stack

View File

@ -4180,8 +4180,8 @@ function testBug458838() {
testBug458838.expected = 10;
testBug458838.jitstats = {
recorderStarted: 1,
recorderAborted: 1,
traceCompleted: 0
recorderAborted: 0,
traceCompleted: 1
};
test(testBug458838);
@ -5200,6 +5200,19 @@ function testConstructorBail() {
}
test(testConstructorBail);
function testNewArrayCount()
{
var a = [];
for (var i = 0; i < 5; i++)
a = [0];
assertEq(a.__count__, 1);
for (var i = 0; i < 5; i++)
a = [0, , 2];
assertEq(a.__count__, 2);
}
test(testNewArrayCount);
/*****************************************************************************
* *
* _____ _ _ _____ ______ _____ _______ *