b=533659; tracing support for JS typed array types; r=gal

This commit is contained in:
Vladimir Vukicevic 2010-01-25 17:06:36 -08:00
parent a8e66a4bcd
commit dbeceb07e7
3 changed files with 183 additions and 6 deletions

View File

@ -75,6 +75,7 @@
#include "jsstaticcheck.h"
#include "jstracer.h"
#include "jsxml.h"
#include "jstypedarray.h"
#include "jsatominlines.h"
#include "jsobjinlines.h"
@ -11952,6 +11953,13 @@ TraceRecorder::getPropertyWithNativeGetter(LIns* obj_ins, JSScopeProperty* sprop
return RECORD_CONTINUE;
}
// Typed array tracing depends on NJ_EXPANDED_LOADSTORE and LIR_f2i
#if NJ_EXPANDED_LOADSTORE && NJ_F2I_SUPPORTED
static bool OkToTraceTypedArrays = true;
#else
static bool OkToTraceTypedArrays = false;
#endif
JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::record_JSOP_GETELEM()
{
@ -12078,8 +12086,7 @@ TraceRecorder::record_JSOP_GETELEM()
return ARECORD_CONTINUE;
}
RETURN_STOP_A("can't reach arguments object's frame");
}
if (obj->isDenseArray()) {
} else if (obj->isDenseArray()) {
// Fast path for dense arrays accessed with a integer index.
jsval* vp;
LIns* addr_ins;
@ -12090,6 +12097,17 @@ TraceRecorder::record_JSOP_GETELEM()
if (call)
set(&idx, obj_ins);
return ARECORD_CONTINUE;
} else if (OkToTraceTypedArrays && js_IsTypedArray(obj)) {
// Fast path for typed arrays accessed with a integer index.
jsval* vp;
LIns* addr_ins;
guardClass(obj, obj_ins, obj->getClass(), snapshot(BRANCH_EXIT));
CHECK_STATUS_A(typedArrayElement(lval, idx, vp, v_ins, addr_ins));
set(&lval, v_ins);
if (call)
set(&idx, obj_ins);
return ARECORD_CONTINUE;
}
return InjectStatus(getPropertyByIndex(obj_ins, idx_ins, &lval));
@ -12234,6 +12252,85 @@ TraceRecorder::setElem(int lval_spindex, int idx_spindex, int v_spindex)
RETURN_STOP_A("non-primitive index");
CHECK_STATUS_A(initOrSetPropertyByName(obj_ins, &idx, &v,
*cx->fp->regs->pc == JSOP_INITELEM));
} else if (OkToTraceTypedArrays && js_IsTypedArray(obj)) {
// Fast path: assigning to element of typed array.
// Ensure array is a typed array and is the same type as what was written
guardClass(obj, obj_ins, obj->getClass(), snapshot(BRANCH_EXIT));
js::TypedArray* tarray = js::TypedArray::fromJSObject(obj);
LIns* priv_ins = stobj_get_private(obj_ins);
// The index was on the stack and is therefore a LIR float. Force it to
// be an integer.
idx_ins = makeNumberInt32(idx_ins);
// Ensure idx >= 0 && idx < length (by using uint32)
LIns *br = lir->insBranch(LIR_jf,
lir->ins2(LIR_ult,
idx_ins,
lir->insLoad(LIR_ld, priv_ins, js::TypedArray::lengthOffset())),
NULL);
// We're now ready to store
LIns* data_ins = lir->insLoad(LIR_ldp, priv_ins, js::TypedArray::dataOffset());
LIns* pidx_ins = lir->ins_u2p(idx_ins);
LIns* addr_ins = 0;
if (isNumber(v)) {
if (isPromoteInt(v_ins) &&
tarray->type != js::TypedArray::TYPE_FLOAT32) {
LIns *v_ins_int = demote(lir, v_ins);
switch (tarray->type) {
case js::TypedArray::TYPE_INT8:
case js::TypedArray::TYPE_UINT8:
addr_ins = lir->ins2(LIR_piadd, data_ins, pidx_ins);
lir->insStore(LIR_stb, v_ins_int, addr_ins, 0);
break;
case js::TypedArray::TYPE_INT16:
case js::TypedArray::TYPE_UINT16:
addr_ins = lir->ins2(LIR_piadd, data_ins, lir->ins2i(LIR_pilsh, pidx_ins, 1));
lir->insStore(LIR_sts, v_ins_int, addr_ins, 0);
break;
case js::TypedArray::TYPE_INT32:
case js::TypedArray::TYPE_UINT32:
addr_ins = lir->ins2(LIR_piadd, data_ins, lir->ins2i(LIR_pilsh, pidx_ins, 2));
lir->insStore(LIR_sti, v_ins_int, addr_ins, 0);
break;
default:
JS_NOT_REACHED("Unknown typed array in tracer");
}
} else {
switch (tarray->type) {
case js::TypedArray::TYPE_INT8:
case js::TypedArray::TYPE_UINT8:
addr_ins = lir->ins2(LIR_piadd, data_ins, pidx_ins);
lir->insStore(LIR_stb, lir->ins1(LIR_f2i, v_ins), addr_ins, 0);
break;
case js::TypedArray::TYPE_INT16:
case js::TypedArray::TYPE_UINT16:
addr_ins = lir->ins2(LIR_piadd, data_ins, lir->ins2i(LIR_pilsh, pidx_ins, 1));
lir->insStore(LIR_sts, lir->ins1(LIR_f2i, v_ins), addr_ins, 0);
break;
case js::TypedArray::TYPE_INT32:
case js::TypedArray::TYPE_UINT32:
addr_ins = lir->ins2(LIR_piadd, data_ins, lir->ins2i(LIR_pilsh, pidx_ins, 2));
lir->insStore(LIR_sti, lir->ins1(LIR_f2i, v_ins), addr_ins, 0);
break;
case js::TypedArray::TYPE_FLOAT32:
addr_ins = lir->ins2(LIR_piadd, data_ins, lir->ins2i(LIR_pilsh, pidx_ins, 2));
lir->insStore(LIR_st32f, v_ins, addr_ins, 0);
break;
default:
JS_NOT_REACHED("Unknown typed array type in tracer");
}
}
} else {
return ARECORD_STOP;
}
br->setTarget(lir->ins0(LIR_label));
} else if (JSVAL_TO_INT(idx) < 0 || !OBJ_IS_DENSE_ARRAY(cx, obj)) {
CHECK_STATUS_A(initOrSetPropertyByIndex(obj_ins, idx_ins, &v,
*cx->fp->regs->pc == JSOP_INITELEM));
@ -13146,6 +13243,83 @@ TraceRecorder::denseArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_
return RECORD_CONTINUE;
}
JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::typedArrayElement(jsval& oval, jsval& ival, jsval*& vp, LIns*& v_ins,
LIns*& addr_ins)
{
JS_ASSERT(JSVAL_IS_OBJECT(oval) && JSVAL_IS_INT(ival));
JSObject* obj = JSVAL_TO_OBJECT(oval);
LIns* obj_ins = get(&oval);
jsint idx = JSVAL_TO_INT(ival);
LIns* idx_ins = makeNumberInt32(get(&ival));
LIns* pidx_ins = lir->ins_u2p(idx_ins);
js::TypedArray* tarray = js::TypedArray::fromJSObject(obj);
JS_ASSERT(tarray);
/* priv_ins will load the TypedArray* */
LIns* priv_ins = stobj_get_private(obj_ins);
/* for out-of-range, just let the interpreter handle it */
if ((jsuint) idx >= tarray->length)
return ARECORD_STOP;
/*
* Ensure idx < length
*
* NOTE! mLength is uint32, but it's guaranteed to fit in a jsval
* int, so we can treat it as either signed or unsigned.
* If the index happens to be negative, when it's treated as
* unsigned it'll be a very large int, and thus won't be less than
* length.
*/
guard(true,
lir->ins2(LIR_ult,
idx_ins,
lir->insLoad(LIR_ldc, priv_ins, js::TypedArray::lengthOffset())),
OVERFLOW_EXIT);
/* We are now ready to load. Do a different type of load
* depending on what type of thing we're loading. */
LIns* data_ins = lir->insLoad(LIR_ldp, priv_ins, js::TypedArray::dataOffset());
switch (tarray->type) {
case js::TypedArray::TYPE_INT8:
addr_ins = lir->ins2(LIR_piadd, data_ins, pidx_ins);
v_ins = lir->ins1(LIR_i2f, lir->insLoad(LIR_ldsb, addr_ins, 0));
break;
case js::TypedArray::TYPE_UINT8:
addr_ins = lir->ins2(LIR_piadd, data_ins, pidx_ins);
v_ins = lir->ins1(LIR_u2f, lir->insLoad(LIR_ldzb, addr_ins, 0));
break;
case js::TypedArray::TYPE_INT16:
addr_ins = lir->ins2(LIR_piadd, data_ins, lir->ins2i(LIR_pilsh, pidx_ins, 1));
v_ins = lir->ins1(LIR_i2f, lir->insLoad(LIR_ldss, addr_ins, 0));
break;
case js::TypedArray::TYPE_UINT16:
addr_ins = lir->ins2(LIR_piadd, data_ins, lir->ins2i(LIR_pilsh, pidx_ins, 1));
v_ins = lir->ins1(LIR_u2f, lir->insLoad(LIR_ldzs, addr_ins, 0));
break;
case js::TypedArray::TYPE_INT32:
addr_ins = lir->ins2(LIR_piadd, data_ins, lir->ins2i(LIR_pilsh, pidx_ins, 2));
v_ins = lir->ins1(LIR_i2f, lir->insLoad(LIR_ld, addr_ins, 0));
break;
case js::TypedArray::TYPE_UINT32:
addr_ins = lir->ins2(LIR_piadd, data_ins, lir->ins2i(LIR_pilsh, pidx_ins, 2));
v_ins = lir->ins1(LIR_u2f, lir->insLoad(LIR_ld, addr_ins, 0));
break;
case js::TypedArray::TYPE_FLOAT32:
addr_ins = lir->ins2(LIR_piadd, data_ins, lir->ins2i(LIR_pilsh, pidx_ins, 2));
v_ins = lir->insLoad(LIR_ld32f, addr_ins, 0);
break;
default:
JS_NOT_REACHED("Unknown typed array type in tracer");
}
return ARECORD_CONTINUE;
}
JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::getProp(JSObject* obj, LIns* obj_ins)
{

View File

@ -1242,8 +1242,11 @@ class TraceRecorder
uint32 *slotp, nanojit::LIns** v_insp,
jsval* outp);
JS_REQUIRES_STACK RecordingStatus denseArrayElement(jsval& oval, jsval& idx, jsval*& vp,
nanojit::LIns*& v_ins,
nanojit::LIns*& addr_ins);
nanojit::LIns*& v_ins,
nanojit::LIns*& addr_ins);
JS_REQUIRES_STACK AbortableRecordingStatus typedArrayElement(jsval& oval, jsval& idx, jsval*& vp,
nanojit::LIns*& v_ins,
nanojit::LIns*& addr_ins);
JS_REQUIRES_STACK AbortableRecordingStatus getProp(JSObject* obj, nanojit::LIns* obj_ins);
JS_REQUIRES_STACK AbortableRecordingStatus getProp(jsval& v);
JS_REQUIRES_STACK RecordingStatus getThis(nanojit::LIns*& this_ins);

View File

@ -70,7 +70,7 @@ using namespace js;
* access. It can be created explicitly and passed to a TypedArray, or
* can be created implicitly by constructing a TypedArray with a size.
*/
inline ArrayBuffer *
ArrayBuffer *
ArrayBuffer::fromJSObject(JSObject *obj)
{
JS_ASSERT(obj->getClass() == &ArrayBuffer::jsclass);
@ -187,7 +187,7 @@ ArrayBuffer::~ArrayBuffer()
* the subclasses.
*/
inline TypedArray *
TypedArray *
TypedArray::fromJSObject(JSObject *obj)
{
return reinterpret_cast<TypedArray*>(obj->getPrivate());