Beginning of SETELEM/GETELEM tracing for dense arrays. Needs computed-offset

insLoad before they'll work.
This commit is contained in:
shaver@mozilla.org 2008-07-05 09:47:59 -04:00
parent f298721bf2
commit de59f88d9c
2 changed files with 111 additions and 0 deletions

View File

@ -41,6 +41,8 @@
#include "nanojit/avmplus.h"
#include "nanojit/nanojit.h"
#include "jsarray.h"
#include "jsbool.h"
#include "jstracer.h"
#include "jscntxt.h"
#include "jsscript.h"
@ -788,6 +790,15 @@ TraceRecorder::map_is_native(JSObjectMap* map, LIns* map_ins)
return false;
}
LIns*
TraceRecorder::loadObjectClass(LIns* objld)
{
return lir->ins2(LIR_and,
lir->insLoadi(objld,
offsetof(JSObject, fslots[JSSLOT_CLASS])),
lir->insImmPtr((void *)~3));
}
bool TraceRecorder::JSOP_INTERRUPT()
{
return false;
@ -1018,12 +1029,104 @@ bool TraceRecorder::JSOP_SETPROP()
{
return false;
}
bool TraceRecorder::guardAndLoadDenseArray(jsval& aval, jsval& ival,
LIns*& objld, LIns*& dslotsld)
{
JS_ASSERT(!JSVAL_IS_PRIMITIVE(aval));
JSObject *obj = JSVAL_TO_OBJECT(aval);
objld = get(&aval);
dslotsld = lir->insLoadi(objld, offsetof(JSObject, dslots));
// guard(OBJ_GET_CLASS(obj) == &js_ArrayClass);
guard(true, lir->ins2(LIR_eq,
loadObjectClass(objld),
lir->insImmPtr(&js_ArrayClass)));
jsint i = asInt(ival);
jsuint capacity = ARRAY_DENSE_LENGTH(obj);
jsint length = obj->fslots[JSSLOT_ARRAY_LENGTH];
if ((jsuint)i >= capacity || i >= length)
return false;
// load lengths
LIns* lengthld = lir->insLoadi(objld,
offsetof(JSObject,
fslots[JSSLOT_ARRAY_LENGTH]));
// guard(i < length);
guard(true, lir->ins2(LIR_lt, get(&ival), lengthld));
// guard(i < capacity)
guard(false, lir->ins_eq0(dslotsld));
guard(true, lir->ins2(LIR_lt, get(&ival),
lir->insLoadi(dslotsld, sizeof(jsval) * -1)));
return true;
}
bool TraceRecorder::JSOP_GETELEM()
{
jsval& r = stackval(-1);
jsval& l = stackval(-2);
if (!isInt(r))
return false;
jsint i = asInt(r);
if (!JSVAL_IS_PRIMITIVE(l)) {
JSObject* obj = JSVAL_TO_OBJECT(l);
if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
LInsp objld, dslotsld;
if (!guardAndLoadDenseArray(l, r, objld, dslotsld))
return false;
LIns* slotoff = lir->ins2(LIR_mul, get(&r),
lir->insImm(sizeof(jsval)));
// XXX LIR_ld only accepts constant displacements!
return false;
LIns* val = lir->insLoad(LIR_ld, dslotsld, slotoff);
if (obj->dslots[i] == JSVAL_HOLE)
return false;
guard(false, lir->ins2i(LIR_eq, val, JSVAL_HOLE));
set(&l, val);
return true;
}
}
return false;
}
bool TraceRecorder::JSOP_SETELEM()
{
jsval& v = stackval(-1);
jsval& r = stackval(-2);
jsval& l = stackval(-3);
if (!isInt(r))
return false;
jsint i = asInt(r);
if (!JSVAL_IS_PRIMITIVE(l)) {
JSObject* obj = JSVAL_TO_OBJECT(l);
if (OBJ_IS_DENSE_ARRAY(cx, obj)) {
LInsp objld, dslotsld;
if (!guardAndLoadDenseArray(l, r, objld, dslotsld))
return false;
LIns* slotoff = lir->ins2(LIR_mul, get(&r),
lir->insImm(sizeof(jsval)));
// XXX LIR_ld only accepts constant displacements!
return false;
LIns* oldval = lir->insLoad(LIR_ld, dslotsld, slotoff);
if (obj->dslots[i] == JSVAL_HOLE)
return false;
guard(false, lir->ins2i(LIR_eq, oldval, JSVAL_HOLE));
lir->insStore(get(&v), dslotsld, slotoff);
set(&l, get(&v));
return true;
}
}
return false;
}
bool TraceRecorder::JSOP_CALLNAME()

View File

@ -133,6 +133,14 @@ class TraceRecorder {
bool inc(jsval& v, jsint incr, bool pre);
bool cmp(nanojit::LOpcode op, bool negate = false);
bool ibinary(nanojit::LOpcode op, bool ov = false);
nanojit::LIns* loadObjectClass(nanojit::LIns* objld);
// Guard that aval is a dense array, and that ival represents an index
// within the length and capacity of the array, and loads obj and
// obj->dslots.
bool guardAndLoadDenseArray(jsval& aval, jsval& ival,
nanojit::LIns*& objld,
nanojit::LIns*& dslotsld);
bool map_is_native(JSObjectMap* map, nanojit::LIns* map_ins);
public: