author | Michael Wu <mwu@mozilla.com> |
Mon, 01 Aug 2011 21:20:23 -0700 | |
changeset 74432 | 18f4994c24cc29cda0768482028a6dcfdd93f235 |
parent 74430 | 9134cf8f5f4aae07898266968bce6042cc3d5bf2 (current diff) |
parent 74431 | 9bf13a8e7d3e8aa79f44ff5d9f8ea451d486bba3 (diff) |
child 74434 | 37373e42a69800034911d80607c01e6b97ab6212 |
push id | 235 |
push user | bzbarsky@mozilla.com |
push date | Tue, 27 Sep 2011 17:13:04 +0000 |
treeherder | mozilla-beta@2d1e082d176a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | killer |
bugs | 664249 |
milestone | 8.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/jstypedarray.cpp | file | annotate | diff | comparison | revisions | |
js/src/jstypedarray.h | file | annotate | diff | comparison | revisions |
--- a/js/src/jsclone.cpp +++ b/js/src/jsclone.cpp @@ -433,34 +433,34 @@ TagToArrayType(uint32_t tag) { JS_ASSERT(SCTAG_TYPED_ARRAY_MIN <= tag && tag <= SCTAG_TYPED_ARRAY_MAX); return tag - SCTAG_TYPED_ARRAY_MIN; } bool JSStructuredCloneWriter::writeTypedArray(JSObject *obj) { - JSObject *arr = TypedArray::getTypedArray(obj); - if (!out.writePair(ArrayTypeToTag(TypedArray::getType(arr)), TypedArray::getLength(arr))) + TypedArray *arr = TypedArray::fromJSObject(obj); + if (!out.writePair(ArrayTypeToTag(arr->type), arr->length)) return false; - switch (TypedArray::getType(arr)) { + switch (arr->type) { case TypedArray::TYPE_INT8: case TypedArray::TYPE_UINT8: case TypedArray::TYPE_UINT8_CLAMPED: - return out.writeArray((const uint8_t *) TypedArray::getDataOffset(arr), TypedArray::getLength(arr)); + return out.writeArray((const uint8_t *) arr->data, arr->length); case TypedArray::TYPE_INT16: case TypedArray::TYPE_UINT16: - return out.writeArray((const uint16_t *) TypedArray::getDataOffset(arr), TypedArray::getLength(arr)); + return out.writeArray((const uint16_t *) arr->data, arr->length); case TypedArray::TYPE_INT32: case TypedArray::TYPE_UINT32: case TypedArray::TYPE_FLOAT32: - return out.writeArray((const uint32_t *) TypedArray::getDataOffset(arr), TypedArray::getLength(arr)); + return out.writeArray((const uint32_t *) arr->data, arr->length); case TypedArray::TYPE_FLOAT64: - return out.writeArray((const uint64_t *) TypedArray::getDataOffset(arr), TypedArray::getLength(arr)); + return out.writeArray((const uint64_t *) arr->data, arr->length); default: JS_NOT_REACHED("unknown TypedArray type"); return false; } } bool JSStructuredCloneWriter::writeArrayBuffer(JSObject *obj) @@ -656,33 +656,33 @@ bool JSStructuredCloneReader::readTypedArray(uint32_t tag, uint32_t nelems, Value *vp) { uint32_t atype = TagToArrayType(tag); JSObject *obj = js_CreateTypedArray(context(), atype, nelems); if (!obj) return false; vp->setObject(*obj); - JSObject *arr = TypedArray::getTypedArray(obj); - JS_ASSERT(TypedArray::getLength(arr) == nelems); - JS_ASSERT(TypedArray::getType(arr) == atype); + TypedArray *arr = TypedArray::fromJSObject(obj); + JS_ASSERT(arr->length == nelems); + JS_ASSERT(arr->type == atype); switch (atype) { case TypedArray::TYPE_INT8: case TypedArray::TYPE_UINT8: case TypedArray::TYPE_UINT8_CLAMPED: - return in.readArray((uint8_t *) TypedArray::getDataOffset(arr), nelems); + return in.readArray((uint8_t *) arr->data, nelems); case TypedArray::TYPE_INT16: case TypedArray::TYPE_UINT16: - return in.readArray((uint16_t *) TypedArray::getDataOffset(arr), nelems); + return in.readArray((uint16_t *) arr->data, nelems); case TypedArray::TYPE_INT32: case TypedArray::TYPE_UINT32: case TypedArray::TYPE_FLOAT32: - return in.readArray((uint32_t *) TypedArray::getDataOffset(arr), nelems); + return in.readArray((uint32_t *) arr->data, nelems); case TypedArray::TYPE_FLOAT64: - return in.readArray((uint64_t *) TypedArray::getDataOffset(arr), nelems); + return in.readArray((uint64_t *) arr->data, nelems); default: JS_NOT_REACHED("unknown TypedArray type"); return false; } } bool JSStructuredCloneReader::readArrayBuffer(uint32_t nbytes, Value *vp)
--- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -83,17 +83,16 @@ #include "jsatominlines.h" #include "jsinterpinlines.h" #include "jsobjinlines.h" #include "jsprobes.h" #include "jspropertycacheinlines.h" #include "jsscopeinlines.h" #include "jsscriptinlines.h" #include "jsopcodeinlines.h" -#include "jstypedarrayinlines.h" #include "vm/Stack-inl.h" #include "vm/String-inl.h" #if JS_HAS_XML_SUPPORT #include "jsxml.h" #endif @@ -3553,18 +3552,18 @@ BEGIN_CASE(JSOP_LENGTH) JS_ASSERT(length < INT32_MAX); regs.sp[-1].setInt32(int32_t(length)); len = JSOP_LENGTH_LENGTH; DO_NEXT_OP(len); } } if (js_IsTypedArray(obj)) { - JSObject *tarray = TypedArray::getTypedArray(obj); - regs.sp[-1].setInt32(TypedArray::getLength(tarray)); + TypedArray *tarray = TypedArray::fromJSObject(obj); + regs.sp[-1].setNumber(tarray->length); len = JSOP_LENGTH_LENGTH; DO_NEXT_OP(len); } } i = -2; goto do_getprop_with_lval; }
--- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -86,17 +86,16 @@ #include "jsfuninlines.h" #include "jsinterpinlines.h" #include "jspropertycacheinlines.h" #include "jsobjinlines.h" #include "jsscopeinlines.h" #include "jsscriptinlines.h" #include "jscntxtinlines.h" #include "jsopcodeinlines.h" -#include "jstypedarrayinlines.h" #include "vm/Stack-inl.h" #ifdef JS_METHODJIT #include "methodjit/MethodJIT.h" #endif #include "tracejit/Writer-inl.h" @@ -13193,38 +13192,32 @@ TraceRecorder::setElem(int lval_spindex, *cx->regs().pc == JSOP_INITELEM)); } else if (OkToTraceTypedArrays && js_IsTypedArray(obj)) { // Fast path: assigning to element of typed array. VMSideExit* branchExit = snapshot(BRANCH_EXIT); // Ensure array is a typed array and is the same type as what was written guardClass(obj_ins, obj->getClass(), branchExit, LOAD_CONST); - JSObject* tarray = js::TypedArray::getTypedArray(obj); + js::TypedArray* tarray = js::TypedArray::fromJSObject(obj); + + LIns* priv_ins = w.ldpObjPrivate(obj_ins); // The index was on the stack and is therefore a LIR float; force it to // be an integer. CHECK_STATUS_A(makeNumberInt32(idx_ins, &idx_ins)); - LIns* slots_ins = w.ldpObjFixedSlots(obj_ins); // Ensure idx >= 0 && idx < length (by using uint32) CHECK_STATUS_A(guard(true, - w.name(w.ltui(idx_ins, w.ldiConstTypedArrayLength(slots_ins)), + w.name(w.ltui(idx_ins, w.ldiConstTypedArrayLength(priv_ins)), "inRange"), OVERFLOW_EXIT, /* abortIfAlwaysExits = */true)); // We're now ready to store - LIns* data_base_ins = w.ldpConstTypedArrayData(slots_ins); - LIns* offset_ins = w.ldiConstTypedArrayByteOffset(slots_ins); -#ifdef NANOJIT_64BIT - LIns* data_ins = w.addp(data_base_ins, w.ui2uq(offset_ins)); -#else - LIns* data_ins = w.addp(data_base_ins, offset_ins); -#endif - + LIns* data_ins = w.ldpConstTypedArrayData(priv_ins); LIns* pidx_ins = w.ui2p(idx_ins); LIns* typed_v_ins = v_ins; // If it's not a number, convert objects to NaN, // null to 0, and call StringToNumber or BooleanOrUndefinedToNumber // for those. if (!v.isNumber()) { if (v.isNull()) { @@ -13241,17 +13234,17 @@ TraceRecorder::setElem(int lval_spindex, } else if (v.isBoolean()) { JS_ASSERT(v.isBoolean()); typed_v_ins = w.i2d(typed_v_ins); } else { typed_v_ins = w.immd(js_NaN); } } - switch (js::TypedArray::getType(tarray)) { + switch (tarray->type) { case js::TypedArray::TYPE_INT8: case js::TypedArray::TYPE_INT16: case js::TypedArray::TYPE_INT32: typed_v_ins = d2i(typed_v_ins); break; case js::TypedArray::TYPE_UINT8: case js::TypedArray::TYPE_UINT16: case js::TypedArray::TYPE_UINT32: @@ -13272,17 +13265,17 @@ TraceRecorder::setElem(int lval_spindex, case js::TypedArray::TYPE_FLOAT32: case js::TypedArray::TYPE_FLOAT64: // Do nothing, this is already a float break; default: JS_NOT_REACHED("Unknown typed array type in tracer"); } - switch (js::TypedArray::getType(tarray)) { + switch (tarray->type) { case js::TypedArray::TYPE_INT8: case js::TypedArray::TYPE_UINT8_CLAMPED: case js::TypedArray::TYPE_UINT8: w.sti2cTypedArrayElement(typed_v_ins, data_ins, pidx_ins); break; case js::TypedArray::TYPE_INT16: case js::TypedArray::TYPE_UINT16: w.sti2sTypedArrayElement(typed_v_ins, data_ins, pidx_ins); @@ -14282,49 +14275,44 @@ TraceRecorder::typedArrayElement(Value& JSObject* obj = &oval.toObject(); LIns* obj_ins = get(&oval); jsint idx = ival.toInt32(); LIns* idx_ins; CHECK_STATUS_A(makeNumberInt32(get(&ival), &idx_ins)); LIns* pidx_ins = w.ui2p(idx_ins); - JSObject* tarray = js::TypedArray::getTypedArray(obj); + js::TypedArray* tarray = js::TypedArray::fromJSObject(obj); JS_ASSERT(tarray); - LIns *slots_ins = w.ldpObjFixedSlots(obj_ins); + /* priv_ins will load the TypedArray* */ + LIns* priv_ins = w.ldpObjPrivate(obj_ins); /* Abort if out-of-range. */ - if ((jsuint) idx >= js::TypedArray::getLength(tarray)) + if ((jsuint) idx >= tarray->length) RETURN_STOP_A("out-of-range index on typed array"); /* * Ensure idx < length * * NOTE! mLength is uint32, but it's guaranteed to fit in a Value * 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, - w.name(w.ltui(idx_ins, w.ldiConstTypedArrayLength(slots_ins)), "inRange"), + w.name(w.ltui(idx_ins, w.ldiConstTypedArrayLength(priv_ins)), "inRange"), BRANCH_EXIT); /* We are now ready to load. Do a different type of load * depending on what type of thing we're loading. */ - LIns* data_base_ins = w.ldpConstTypedArrayData(slots_ins); - LIns* offset_ins = w.ldiConstTypedArrayByteOffset(slots_ins); -#ifdef NANOJIT_64BIT - LIns* data_ins = w.addp(data_base_ins, w.ui2uq(offset_ins)); -#else - LIns* data_ins = w.addp(data_base_ins, offset_ins); -#endif - - switch (js::TypedArray::getType(tarray)) { + LIns* data_ins = w.ldpConstTypedArrayData(priv_ins); + + switch (tarray->type) { case js::TypedArray::TYPE_INT8: v_ins = w.i2d(w.ldc2iTypedArrayElement(data_ins, pidx_ins)); break; case js::TypedArray::TYPE_UINT8: case js::TypedArray::TYPE_UINT8_CLAMPED: // i2d on purpose here: it's safe, because an 8-bit uint is guaranteed // to fit in a 32-bit int, and i2d gets more optimization than ui2d. v_ins = w.i2d(w.lduc2uiTypedArrayElement(data_ins, pidx_ins)); @@ -16343,17 +16331,17 @@ TraceRecorder::record_JSOP_LENGTH() guard(true, w.leui(v_ins, w.immi(JSVAL_INT_MAX)), BRANCH_EXIT); v_ins = w.i2d(v_ins); } else { v_ins = w.ui2d(v_ins); } } else if (OkToTraceTypedArrays && js_IsTypedArray(obj)) { // Ensure array is a typed array and is the same type as what was written guardClass(obj_ins, obj->getClass(), snapshot(BRANCH_EXIT), LOAD_NORMAL); - v_ins = w.i2d(w.ldiConstTypedArrayLength(w.ldpObjFixedSlots(obj_ins))); + v_ins = w.i2d(w.ldiConstTypedArrayLength(w.ldpObjPrivate(obj_ins))); } else { if (!obj->isNative()) RETURN_STOP_A("can't trace length property access on non-array, non-native object"); return getProp(obj, obj_ins); } set(&l, v_ins); return ARECORD_CONTINUE; }
--- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -145,17 +145,17 @@ ArrayBuffer::class_constructor(JSContext JSObject *bufobj = create(cx, nbytes); if (!bufobj) return false; vp->setObject(*bufobj); return true; } static inline JSBool -AllocateArrayBufferSlots(JSContext *cx, JSObject *obj, uint32 size) +AllocateSlots(JSContext *cx, JSObject *obj, uint32 size) { uint32 bytes = size + sizeof(Value); if (size > sizeof(Value) * ARRAYBUFFER_RESERVED_SLOTS - sizeof(Value) ) { JS_ASSERT(!obj->hasSlotsArray()); Value *tmpslots = (Value *)cx->calloc_(bytes); if (!tmpslots) return false; obj->setSlotsPtr(tmpslots); @@ -199,17 +199,17 @@ ArrayBuffer::create(JSContext *cx, int32 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH); return NULL; } /* * The first 8 bytes hold the length. * The rest of it is a flat data store for the array buffer. */ - if (!AllocateArrayBufferSlots(cx, obj, nbytes)) + if (!AllocateSlots(cx, obj, nbytes)) return NULL; JS_ASSERT(obj->getClass() == &ArrayBuffer::slowClass); obj->setSharedNonNativeMap(); obj->clasp = &ArrayBuffer::fastClass; return obj; } @@ -319,26 +319,26 @@ ArrayBuffer::obj_setProperty(JSContext * // since obj_getProperty will fetch it as a plain // property from the delegate. JSObject *delegate = DelegateObject(cx, obj); if (!delegate) return false; JSObject *oldDelegateProto = delegate->getProto(); - if (!js_SetPropertyHelper(cx, delegate, id, 0, vp, strict)) + if (!js_SetProperty(cx, delegate, id, vp, strict)) return false; if (delegate->getProto() != oldDelegateProto) { // actual __proto__ was set and not a plain property called // __proto__ if (!SetProto(cx, obj, vp->toObjectOrNull(), true)) { // this can be caused for example by setting x.__proto__ = x // restore delegate prototype chain - SetProto(cx, delegate, oldDelegateProto, true); + delegate->setProto(oldDelegateProto); return false; } } return true; } JSObject *delegate = DelegateObject(cx, obj); if (!delegate) @@ -407,131 +407,134 @@ ArrayBuffer::obj_typeOf(JSContext *cx, J /* * TypedArray * * The non-templated base class for the specific typed implementations. * This class holds all the member variables that are used by * the subclasses. */ -JSObject * -TypedArray::getTypedArray(JSObject *obj) +TypedArray * +TypedArray::fromJSObject(JSObject *obj) { while (!js_IsTypedArray(obj)) obj = obj->getProto(); - return obj; + return reinterpret_cast<TypedArray*>(obj->getPrivate()); } inline bool -TypedArray::isArrayIndex(JSContext *cx, JSObject *obj, jsid id, jsuint *ip) +TypedArray::isArrayIndex(JSContext *cx, jsid id, jsuint *ip) { jsuint index; - if (js_IdIsIndex(id, &index) && index < getLength(obj)) { + if (js_IdIsIndex(id, &index) && index < length) { if (ip) *ip = index; return true; } return false; } -typedef Value (* TypedArrayPropertyGetter)(JSObject *tarray); +typedef Value (* TypedArrayPropertyGetter)(TypedArray *tarray); template <TypedArrayPropertyGetter Get> class TypedArrayGetter { public: static inline bool get(JSContext *cx, JSObject *obj, jsid id, Value *vp) { do { if (js_IsTypedArray(obj)) { - JSObject *tarray = TypedArray::getTypedArray(obj); + TypedArray *tarray = TypedArray::fromJSObject(obj); if (tarray) *vp = Get(tarray); return true; } } while ((obj = obj->getProto()) != NULL); return true; } }; -/* - * For now (until slots directly hold data) - * slots data element points to the JSObject representing the ArrayBuffer. - */ inline Value -getBufferValue(JSObject *tarray) +getBuffer(TypedArray *tarray) { - JSObject *buffer = TypedArray::getBuffer(tarray); - return ObjectValue(*buffer); + return ObjectValue(*tarray->bufferJS); } JSBool TypedArray::prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return TypedArrayGetter<getBufferValue>::get(cx, obj, id, vp); + return TypedArrayGetter<getBuffer>::get(cx, obj, id, vp); } inline Value -getByteOffsetValue(JSObject *tarray) +getByteOffset(TypedArray *tarray) { - return Int32Value(TypedArray::getByteOffset(tarray)); + return Int32Value(tarray->byteOffset); } JSBool TypedArray::prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return TypedArrayGetter<getByteOffsetValue>::get(cx, obj, id, vp); + return TypedArrayGetter<getByteOffset>::get(cx, obj, id, vp); } inline Value -getByteLengthValue(JSObject *tarray) +getByteLength(TypedArray *tarray) { - return Int32Value(TypedArray::getByteLength(tarray)); + return Int32Value(tarray->byteLength); } JSBool TypedArray::prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return TypedArrayGetter<getByteLengthValue>::get(cx, obj, id, vp); + return TypedArrayGetter<getByteLength>::get(cx, obj, id, vp); } inline Value -getLengthValue(JSObject *tarray) +getLength(TypedArray *tarray) { - return Int32Value(TypedArray::getLength(tarray)); + return Int32Value(tarray->length); } JSBool TypedArray::prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp) { - return TypedArrayGetter<getLengthValue>::get(cx, obj, id, vp); + return TypedArrayGetter<getLength>::get(cx, obj, id, vp); } JSBool TypedArray::obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp) { - JSObject *tarray = getTypedArray(obj); + TypedArray *tarray = fromJSObject(obj); JS_ASSERT(tarray); - if (isArrayIndex(cx, tarray, id)) { + if (tarray->isArrayIndex(cx, id)) { *propp = (JSProperty *) 1; /* non-null to indicate found */ *objp = obj; return true; } JSObject *proto = obj->getProto(); if (!proto) { *objp = NULL; *propp = NULL; return true; } return proto->lookupProperty(cx, id, objp, propp); } +void +TypedArray::obj_trace(JSTracer *trc, JSObject *obj) +{ + TypedArray *tarray = fromJSObject(obj); + JS_ASSERT(tarray); + MarkObject(trc, *tarray->bufferJS, "typedarray.buffer"); +} + JSBool TypedArray::obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp) { *attrsp = (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) ? JSPROP_PERMANENT | JSPROP_READONLY : JSPROP_PERMANENT | JSPROP_ENUMERATE; return true; } @@ -704,38 +707,31 @@ class TypedArrayTemplate return &TypedArray::slowClasses[ArrayTypeID()]; } static inline Class *fastClass() { return &TypedArray::fastClasses[ArrayTypeID()]; } - static void - obj_trace(JSTracer *trc, JSObject *obj) - { - JSObject *buffer = static_cast<JSObject*>(getBuffer(obj)); - if (buffer) - MarkObject(trc, *buffer, "typedarray.buffer"); - } - static JSBool obj_getProperty(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp) { - JSObject *tarray = getTypedArray(obj); + ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); + JS_ASSERT(tarray); if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) { - vp->setNumber(getLength(tarray)); + vp->setNumber(tarray->length); return true; } jsuint index; - if (isArrayIndex(cx, tarray, id, &index)) { + if (tarray->isArrayIndex(cx, id, &index)) { // this inline function is specialized for each type - copyIndexToValue(cx, tarray, index, vp); + tarray->copyIndexToValue(cx, index, vp); } else { JSObject *obj2; JSProperty *prop; const Shape *shape; JSObject *proto = obj->getProto(); if (!proto) { vp->setUndefined(); @@ -756,43 +752,43 @@ class TypedArrayTemplate } return true; } static JSBool obj_setProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict) { - JSObject *tarray = getTypedArray(obj); + ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); JS_ASSERT(tarray); if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) { - vp->setNumber(getLength(tarray)); + vp->setNumber(tarray->length); return true; } jsuint index; // We can't just chain to js_SetPropertyHelper, because we're not a normal object. - if (!isArrayIndex(cx, tarray, id, &index)) { + if (!tarray->isArrayIndex(cx, id, &index)) { #if 0 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_INDEX); return false; #endif // Silent ignore is better than an exception here, because // at some point we may want to support other properties on // these objects. This is especially true when these arrays // are used to implement HTML Canvas 2D's PixelArray objects, // which used to be plain old arrays. vp->setUndefined(); return true; } if (vp->isInt32()) { - setIndex(tarray, index, NativeType(vp->toInt32())); + tarray->setIndex(index, NativeType(vp->toInt32())); return true; } jsdouble d; if (vp->isDouble()) { d = vp->toDouble(); } else if (vp->isNull()) { @@ -812,29 +808,29 @@ class TypedArrayTemplate } // If the array is an integer array, we only handle up to // 32-bit ints from this point on. if we want to handle // 64-bit ints, we'll need some changes. // Assign based on characteristics of the destination type if (ArrayTypeIsFloatingPoint()) { - setIndex(tarray, index, NativeType(d)); + tarray->setIndex(index, NativeType(d)); } else if (ArrayTypeIsUnsigned()) { JS_ASSERT(sizeof(NativeType) <= 4); uint32 n = js_DoubleToECMAUint32(d); - setIndex(tarray, index, NativeType(n)); + tarray->setIndex(index, NativeType(n)); } else if (ArrayTypeID() == TypedArray::TYPE_UINT8_CLAMPED) { // The uint8_clamped type has a special rounding converter // for doubles. - setIndex(tarray, index, NativeType(d)); + tarray->setIndex(index, NativeType(d)); } else { JS_ASSERT(sizeof(NativeType) <= 4); int32 n = js_DoubleToECMAInt32(d); - setIndex(tarray, index, NativeType(n)); + tarray->setIndex(index, NativeType(n)); } return true; } static JSBool obj_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *v, PropertyOp getter, StrictPropertyOp setter, uintN attrs) @@ -849,64 +845,64 @@ class TypedArrayTemplate static JSBool obj_deleteProperty(JSContext *cx, JSObject *obj, jsid id, Value *rval, JSBool strict) { if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom)) { rval->setBoolean(false); return true; } - JSObject *tarray = TypedArray::getTypedArray(obj); + TypedArray *tarray = TypedArray::fromJSObject(obj); JS_ASSERT(tarray); - if (isArrayIndex(cx, tarray, id)) { + if (tarray->isArrayIndex(cx, id)) { rval->setBoolean(false); return true; } rval->setBoolean(true); return true; } static JSBool obj_enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, Value *statep, jsid *idp) { - JSObject *tarray = getTypedArray(obj); + ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); JS_ASSERT(tarray); /* * Iteration is "length" (if JSENUMERATE_INIT_ALL), then [0, length). * *statep is JSVAL_TRUE if enumerating "length" and * JSVAL_TO_INT(index) when enumerating index. */ switch (enum_op) { case JSENUMERATE_INIT_ALL: statep->setBoolean(true); if (idp) - *idp = ::INT_TO_JSID(getLength(tarray) + 1); + *idp = ::INT_TO_JSID(tarray->length + 1); break; case JSENUMERATE_INIT: statep->setInt32(0); if (idp) - *idp = ::INT_TO_JSID(getLength(tarray)); + *idp = ::INT_TO_JSID(tarray->length); break; case JSENUMERATE_NEXT: if (statep->isTrue()) { *idp = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); statep->setInt32(0); } else { uint32 index = statep->toInt32(); - if (index < getLength(tarray)) { + if (index < uint32(tarray->length)) { *idp = ::INT_TO_JSID(index); statep->setInt32(index + 1); } else { - JS_ASSERT(index == getLength(tarray)); + JS_ASSERT(index == tarray->length); statep->setNull(); } } break; case JSENUMERATE_DESTROY: statep->setNull(); break; @@ -919,50 +915,28 @@ class TypedArrayTemplate obj_typeOf(JSContext *cx, JSObject *obj) { return JSTYPE_OBJECT; } static JSObject * createTypedArray(JSContext *cx, JSObject *bufobj, uint32 byteOffset, uint32 len) { - JS_ASSERT(bufobj->getClass() == &ArrayBuffer::fastClass); JSObject *obj = NewBuiltinClassInstance(cx, slowClass()); if (!obj) return NULL; - obj->setSlot(FIELD_TYPE, Int32Value(ArrayTypeID())); - - do { - obj->setSlot(FIELD_BUFFER, ObjectValue(*bufobj)); - /* - * NOTE: unlike the earlier implementation where the 'data' pointed - * directly to the right offset in the ArrayBuffer - * this points to the base of the ArrayBuffer. - * getIndex is modified to get the right index. - * - * This is because on 64 bit systems the jsval.h Private API - * requires pointers stored in jsvals to be two-byte aligned. - * TM and JM both need a few extra instructions to add the offset. - */ - obj->setSlot(FIELD_DATA, PrivateValue(ArrayBuffer::getDataOffset(bufobj))); - } while(0); - - obj->setSlot(FIELD_LENGTH, Int32Value(len)); - obj->setSlot(FIELD_BYTEOFFSET, Int32Value(byteOffset)); - obj->setSlot(FIELD_BYTELENGTH, Int32Value(len * sizeof(NativeType))); - - JS_ASSERT(ArrayBuffer::getByteLength(getBuffer(obj)) - getByteOffset(obj) >= getByteLength(obj)); - JS_ASSERT(getByteOffset(obj) <= ArrayBuffer::getByteLength(getBuffer(obj))); - JS_ASSERT(ArrayBuffer::getDataOffset(getBuffer(obj)) <= getDataOffset(obj)); - JS_ASSERT(getDataOffset(obj) <= offsetData(obj, ArrayBuffer::getByteLength(getBuffer(obj)))); + ThisTypeArray *tarray = cx->new_<ThisTypeArray>(bufobj, byteOffset, len); + if (!tarray) + return NULL; JS_ASSERT(obj->getClass() == slowClass()); obj->setSharedNonNativeMap(); obj->clasp = fastClass(); + obj->setPrivate(tarray); // FIXME Bug 599008: make it ok to call preventExtensions here. obj->flags |= JSObject::NOT_EXTENSIBLE; return obj; } /* @@ -1003,26 +977,26 @@ class TypedArrayTemplate JSMSG_TYPED_ARRAY_BAD_ARGS); return NULL; } JSObject *dataObj = &argv[0].toObject(); /* (typedArray) */ if (js_IsTypedArray(dataObj)) { - JSObject *otherTypedArray = getTypedArray(dataObj); + TypedArray *otherTypedArray = TypedArray::fromJSObject(dataObj); JS_ASSERT(otherTypedArray); - uint32 len = getLength(otherTypedArray); + uint32 len = otherTypedArray->length; JSObject *bufobj = createBufferWithSizeAndCount(cx, len); if (!bufobj) return NULL; JSObject *obj = createTypedArray(cx, bufobj, 0, len); - if (!obj || !copyFromTypedArray(cx, obj, otherTypedArray, 0)) + if (!obj || !copyFrom(cx, obj, otherTypedArray, 0)) return NULL; return obj; } /* (obj, byteOffset, length). */ int32_t byteOffset = -1; int32_t length = -1; @@ -1045,37 +1019,45 @@ class TypedArrayTemplate } } } /* (obj, byteOffset, length) */ return createTypedArrayWithOffsetLength(cx, dataObj, byteOffset, length); } + static void + class_finalize(JSContext *cx, JSObject *obj) + { + ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); + if (tarray) + cx->delete_(tarray); + } + /* subarray(start[, end]) */ static JSBool fun_subarray(JSContext *cx, uintN argc, Value *vp) { JSObject *obj = ToObject(cx, &vp[1]); if (!obj) return false; if (obj->getClass() != fastClass()) { // someone tried to apply this subarray() to the wrong class ReportIncompatibleMethod(cx, vp, fastClass()); return false; } - JSObject *tarray = getTypedArray(obj); + ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); if (!tarray) return true; // these are the default values - int32_t begin = 0, end = getLength(tarray); - int32_t length = int32(getLength(tarray)); + int32_t begin = 0, end = tarray->length; + int32_t length = int32(tarray->length); if (argc > 0) { Value *argv = JS_ARGV(cx, vp); if (!ValueToInt32(cx, argv[0], &begin)) return false; if (begin < 0) { begin += length; if (begin < 0) @@ -1116,29 +1098,29 @@ class TypedArrayTemplate return false; if (obj->getClass() != fastClass()) { // someone tried to apply this set() to the wrong class ReportIncompatibleMethod(cx, vp, fastClass()); return false; } - JSObject *tarray = getTypedArray(obj); + ThisTypeArray *tarray = ThisTypeArray::fromJSObject(obj); if (!tarray) return true; // these are the default values int32_t off = 0; Value *argv = JS_ARGV(cx, vp); if (argc > 1) { if (!ValueToInt32(cx, argv[1], &off)) return false; - if (off < 0 || uint32_t(off) > getLength(tarray)) { + if (off < 0 || uint32_t(off) > tarray->length) { // the given offset is bogus JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS); return false; } } uint32 offset(off); @@ -1147,48 +1129,76 @@ class TypedArrayTemplate if (argc == 0 || !argv[0].isObject()) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS); return false; } JSObject *arg0 = argv[0].toObjectOrNull(); if (js_IsTypedArray(arg0)) { - JSObject *src = TypedArray::getTypedArray(arg0); + TypedArray *src = TypedArray::fromJSObject(arg0); if (!src || - getLength(src) > getLength(tarray) - offset) + src->length > tarray->length - offset) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS); return false; } - if (!copyFromTypedArray(cx, obj, src, offset)) + if (!copyFrom(cx, obj, src, offset)) return false; } else { jsuint len; if (!js_GetLengthProperty(cx, arg0, &len)) return false; // avoid overflow; we know that offset <= length - if (len > getLength(tarray) - offset) { + if (len > tarray->length - offset) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS); return false; } - if (!copyFromArray(cx, obj, arg0, len, offset)) + if (!copyFrom(cx, obj, arg0, len, offset)) return false; } vp->setUndefined(); return true; } + static ThisTypeArray * + fromJSObject(JSObject *obj) + { + JS_ASSERT(obj->getClass() == fastClass()); + return reinterpret_cast<ThisTypeArray*>(obj->getPrivate()); + } + public: + TypedArrayTemplate(JSObject *bufobj, uint32 byteOffset, uint32 len) + { + JS_ASSERT(bufobj->getClass() == &ArrayBuffer::fastClass); + + type = ArrayTypeID(); + bufferJS = bufobj; + length = 0; + + this->byteOffset = byteOffset; + + JS_ASSERT(byteOffset <= ArrayBuffer::getByteLength(bufferJS)); + this->data = offsetData(bufferJS, byteOffset); + JS_ASSERT(ArrayBuffer::getDataOffset(bufferJS) <= this->data); + JS_ASSERT(this->data <= offsetData(bufferJS, ArrayBuffer::getByteLength(bufferJS))); + + this->byteLength = len * sizeof(NativeType); + JS_ASSERT(ArrayBuffer::getByteLength(bufferJS) - byteOffset >= this->byteLength); + + this->length = len; + } + static JSObject * createTypedArrayWithOffsetLength(JSContext *cx, JSObject *other, int32 byteOffsetInt, int32 lengthInt) { JS_ASSERT(!js_IsTypedArray(other)); /* Handle creation from an ArrayBuffer not ArrayBuffer.prototype. */ if (other->getClass() == &ArrayBuffer::fastClass) { @@ -1239,54 +1249,54 @@ class TypedArrayTemplate if (!js_GetLengthProperty(cx, other, &len)) return NULL; JSObject *bufobj = createBufferWithSizeAndCount(cx, len); if (!bufobj) return NULL; JSObject *obj = createTypedArray(cx, bufobj, 0, len); - if (!obj || !copyFromArray(cx, obj, other, len)) + if (!obj || !copyFrom(cx, obj, other, len)) return NULL; return obj; } - static const NativeType - getIndex(JSObject *obj, uint32 index) + const NativeType + getIndex(uint32 index) const { - return *(static_cast<const NativeType*>(getDataOffset(obj)) + index); + return *(static_cast<const NativeType*>(data) + index); } - static void - setIndex(JSObject *obj, uint32 index, NativeType val) + void + setIndex(uint32 index, NativeType val) { - *(static_cast<NativeType*>(getDataOffset(obj)) + index) = val; + *(static_cast<NativeType*>(data) + index) = val; } - static void copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp); + inline void copyIndexToValue(JSContext *cx, uint32 index, Value *vp); static JSObject * - createSubarray(JSContext *cx, JSObject *tarray, uint32 begin, uint32 end) + createSubarray(JSContext *cx, ThisTypeArray *tarray, uint32 begin, uint32 end) { JS_ASSERT(tarray); JS_ASSERT(0 <= begin); - JS_ASSERT(begin <= getLength(tarray)); + JS_ASSERT(begin <= tarray->length); JS_ASSERT(0 <= end); - JS_ASSERT(end <= getLength(tarray)); + JS_ASSERT(end <= tarray->length); - JSObject *bufobj = getBuffer(tarray); + JSObject *bufobj = tarray->bufferJS; JS_ASSERT(bufobj); JS_ASSERT(begin <= end); uint32 length = end - begin; JS_ASSERT(begin < UINT32_MAX / sizeof(NativeType)); - JS_ASSERT(UINT32_MAX - begin * sizeof(NativeType) >= getByteOffset(tarray)); - uint32 byteOffset = getByteOffset(tarray) + begin * sizeof(NativeType); + JS_ASSERT(UINT32_MAX - begin * sizeof(NativeType) >= tarray->byteOffset); + uint32 byteOffset = tarray->byteOffset + begin * sizeof(NativeType); return createTypedArray(cx, bufobj, byteOffset, length); } protected: static NativeType nativeFromValue(JSContext *cx, const Value &v) { @@ -1312,25 +1322,25 @@ class TypedArrayTemplate if (ArrayTypeIsFloatingPoint()) return NativeType(js_NaN); return NativeType(int32(0)); } static bool - copyFromArray(JSContext *cx, JSObject *thisTypedArrayObj, + copyFrom(JSContext *cx, JSObject *thisTypedArrayObj, JSObject *ar, jsuint len, jsuint offset = 0) { - thisTypedArrayObj = getTypedArray(thisTypedArrayObj); - JS_ASSERT(thisTypedArrayObj); + ThisTypeArray *thisTypedArray = fromJSObject(thisTypedArrayObj); + JS_ASSERT(thisTypedArray); - JS_ASSERT(offset <= getLength(thisTypedArrayObj)); - JS_ASSERT(len <= getLength(thisTypedArrayObj) - offset); - NativeType *dest = static_cast<NativeType*>(getDataOffset(thisTypedArrayObj)) + offset; + JS_ASSERT(offset <= thisTypedArray->length); + JS_ASSERT(len <= thisTypedArray->length - offset); + NativeType *dest = static_cast<NativeType*>(thisTypedArray->data) + offset; if (ar->isDenseArray() && ar->getDenseArrayCapacity() >= len) { JS_ASSERT(ar->getArrayLength() == len); const Value *src = ar->getDenseArrayElements(); for (uintN i = 0; i < len; ++i) *dest++ = nativeFromValue(cx, *src++); @@ -1344,173 +1354,173 @@ class TypedArrayTemplate *dest++ = nativeFromValue(cx, v); } } return true; } static bool - copyFromTypedArray(JSContext *cx, JSObject *thisTypedArrayObj, JSObject *tarray, jsuint offset) + copyFrom(JSContext *cx, JSObject *thisTypedArrayObj, TypedArray *tarray, jsuint offset) { - thisTypedArrayObj = getTypedArray(thisTypedArrayObj); - JS_ASSERT(thisTypedArrayObj); + ThisTypeArray *thisTypedArray = fromJSObject(thisTypedArrayObj); + JS_ASSERT(thisTypedArray); - JS_ASSERT(offset <= getLength(thisTypedArrayObj)); - JS_ASSERT(getLength(tarray) <= getLength(thisTypedArrayObj) - offset); - if (getBuffer(tarray) == getBuffer(thisTypedArrayObj)) - return copyFromWithOverlap(cx, thisTypedArrayObj, tarray, offset); + JS_ASSERT(offset <= thisTypedArray->length); + JS_ASSERT(tarray->length <= thisTypedArray->length - offset); + if (tarray->bufferJS == thisTypedArray->bufferJS) + return thisTypedArray->copyFromWithOverlap(cx, tarray, offset); - NativeType *dest = static_cast<NativeType*>((void*)getDataOffset(thisTypedArrayObj)) + offset; + NativeType *dest = static_cast<NativeType*>(thisTypedArray->data) + offset; - if (getType(tarray) == getType(thisTypedArrayObj)) { - memcpy(dest, getDataOffset(tarray), getByteLength(tarray)); + if (tarray->type == thisTypedArray->type) { + memcpy(dest, tarray->data, tarray->byteLength); return true; } - uintN srclen = getLength(tarray); - switch (getType(tarray)) { + uintN srclen = tarray->length; + switch (tarray->type) { case TypedArray::TYPE_INT8: { - int8 *src = static_cast<int8*>(getDataOffset(tarray)); + int8 *src = static_cast<int8*>(tarray->data); for (uintN i = 0; i < srclen; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_UINT8: case TypedArray::TYPE_UINT8_CLAMPED: { - uint8 *src = static_cast<uint8*>(getDataOffset(tarray)); + uint8 *src = static_cast<uint8*>(tarray->data); for (uintN i = 0; i < srclen; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_INT16: { - int16 *src = static_cast<int16*>(getDataOffset(tarray)); + int16 *src = static_cast<int16*>(tarray->data); for (uintN i = 0; i < srclen; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_UINT16: { - uint16 *src = static_cast<uint16*>(getDataOffset(tarray)); + uint16 *src = static_cast<uint16*>(tarray->data); for (uintN i = 0; i < srclen; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_INT32: { - int32 *src = static_cast<int32*>(getDataOffset(tarray)); + int32 *src = static_cast<int32*>(tarray->data); for (uintN i = 0; i < srclen; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_UINT32: { - uint32 *src = static_cast<uint32*>(getDataOffset(tarray)); + uint32 *src = static_cast<uint32*>(tarray->data); for (uintN i = 0; i < srclen; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_FLOAT32: { - float *src = static_cast<float*>(getDataOffset(tarray)); + float *src = static_cast<float*>(tarray->data); for (uintN i = 0; i < srclen; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_FLOAT64: { - double *src = static_cast<double*>(getDataOffset(tarray)); + double *src = static_cast<double*>(tarray->data); for (uintN i = 0; i < srclen; ++i) *dest++ = NativeType(*src++); break; } default: JS_NOT_REACHED("copyFrom with a TypedArray of unknown type"); break; } return true; } - static bool - copyFromWithOverlap(JSContext *cx, JSObject *self, JSObject *tarray, jsuint offset) + bool + copyFromWithOverlap(JSContext *cx, TypedArray *tarray, jsuint offset) { - JS_ASSERT(offset <= getLength(self)); + JS_ASSERT(offset <= length); - NativeType *dest = static_cast<NativeType*>(getDataOffset(self)) + offset; + NativeType *dest = static_cast<NativeType*>(data) + offset; - if (getType(tarray) == getType(self)) { - memmove(dest, getDataOffset(tarray), getByteLength(tarray)); + if (tarray->type == type) { + memmove(dest, tarray->data, tarray->byteLength); return true; } // We have to make a copy of the source array here, since // there's overlap, and we have to convert types. - void *srcbuf = cx->malloc_(getLength(tarray)); + void *srcbuf = cx->malloc_(tarray->byteLength); if (!srcbuf) return false; - memcpy(srcbuf, getDataOffset(tarray), getByteLength(tarray)); + memcpy(srcbuf, tarray->data, tarray->byteLength); - switch (getType(tarray)) { + switch (tarray->type) { case TypedArray::TYPE_INT8: { int8 *src = (int8*) srcbuf; - for (uintN i = 0; i < getLength(tarray); ++i) + for (uintN i = 0; i < tarray->length; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_UINT8: case TypedArray::TYPE_UINT8_CLAMPED: { uint8 *src = (uint8*) srcbuf; - for (uintN i = 0; i < getLength(tarray); ++i) + for (uintN i = 0; i < tarray->length; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_INT16: { int16 *src = (int16*) srcbuf; - for (uintN i = 0; i < getLength(tarray); ++i) + for (uintN i = 0; i < tarray->length; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_UINT16: { uint16 *src = (uint16*) srcbuf; - for (uintN i = 0; i < getLength(tarray); ++i) + for (uintN i = 0; i < tarray->length; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_INT32: { int32 *src = (int32*) srcbuf; - for (uintN i = 0; i < getLength(tarray); ++i) + for (uintN i = 0; i < tarray->length; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_UINT32: { uint32 *src = (uint32*) srcbuf; - for (uintN i = 0; i < getLength(tarray); ++i) + for (uintN i = 0; i < tarray->length; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_FLOAT32: { float *src = (float*) srcbuf; - for (uintN i = 0; i < getLength(tarray); ++i) + for (uintN i = 0; i < tarray->length; ++i) *dest++ = NativeType(*src++); break; } case TypedArray::TYPE_FLOAT64: { double *src = (double*) srcbuf; - for (uintN i = 0; i < getLength(tarray); ++i) + for (uintN i = 0; i < tarray->length; ++i) *dest++ = NativeType(*src++); break; } default: JS_NOT_REACHED("copyFromWithOverlap with a TypedArray of unknown type"); break; } UnwantedForeground::free_(srcbuf); return true; } - static void * + void * offsetData(JSObject *obj, uint32 offs) { - return (void*)(((uint8*)getDataOffset(obj)) + offs); + return (void*)(((uint8*)ArrayBuffer::getDataOffset(obj)) + offs); } static JSObject * createBufferWithSizeAndCount(JSContext *cx, uint32 count) { size_t size = sizeof(NativeType); if (size != 0 && count >= INT32_MAX / size) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, @@ -1522,45 +1532,45 @@ class TypedArrayTemplate return ArrayBuffer::create(cx, bytelen); } }; // this default implementation is only valid for integer types // less than 32-bits in size. template<typename NativeType> void -TypedArrayTemplate<NativeType>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp) +TypedArrayTemplate<NativeType>::copyIndexToValue(JSContext *cx, uint32 index, Value *vp) { JS_STATIC_ASSERT(sizeof(NativeType) < 4); - vp->setInt32(getIndex(tarray, index)); + vp->setInt32(getIndex(index)); } // and we need to specialize for 32-bit integers and floats template<> void -TypedArrayTemplate<int32>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp) +TypedArrayTemplate<int32>::copyIndexToValue(JSContext *cx, uint32 index, Value *vp) { - int32 val = getIndex(tarray, index); + int32 val = getIndex(index); vp->setInt32(val); } template<> void -TypedArrayTemplate<uint32>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp) +TypedArrayTemplate<uint32>::copyIndexToValue(JSContext *cx, uint32 index, Value *vp) { - uint32 val = getIndex(tarray, index); + uint32 val = getIndex(index); vp->setNumber(val); } template<> void -TypedArrayTemplate<float>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp) +TypedArrayTemplate<float>::copyIndexToValue(JSContext *cx, uint32 index, Value *vp) { - float val = getIndex(tarray, index); + float val = getIndex(index); double dval = val; /* * Doubles in typed arrays could be typed-punned arrays of integers. This * could allow user code to break the engine-wide invariant that only * canonical nans are stored into jsvals, which means user code could * confuse the engine into interpreting a double-typed jsval as an * object-typed jsval. @@ -1571,19 +1581,19 @@ TypedArrayTemplate<float>::copyIndexToVa if (JS_UNLIKELY(JSDOUBLE_IS_NaN(dval))) dval = js_NaN; vp->setDouble(dval); } template<> void -TypedArrayTemplate<double>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp) +TypedArrayTemplate<double>::copyIndexToValue(JSContext *cx, uint32 index, Value *vp) { - double val = getIndex(tarray, index); + double val = getIndex(index); /* * Doubles in typed arrays could be typed-punned arrays of integers. This * could allow user code to break the engine-wide invariant that only * canonical nans are stored into jsvals, which means user code could * confuse the engine into interpreting a double-typed jsval as an * object-typed jsval. */ @@ -1681,56 +1691,54 @@ JSPropertySpec TypedArray::jsprops[] = { }; /* * TypedArray boilerplate */ #define IMPL_TYPED_ARRAY_STATICS(_typedArray) \ template<> JSFunctionSpec _typedArray::jsfuncs[] = { \ - JS_FN("subarray", _typedArray::fun_subarray, 2, JSFUN_GENERIC_NATIVE), \ - JS_FN("set", _typedArray::fun_set, 2, JSFUN_GENERIC_NATIVE), \ + JS_FN("subarray", _typedArray::fun_subarray, 2, 0), \ + JS_FN("set", _typedArray::fun_set, 2, 0), \ JS_FS_END \ } #define IMPL_TYPED_ARRAY_SLOW_CLASS(_typedArray) \ { \ #_typedArray, \ - JSCLASS_HAS_RESERVED_SLOTS(TypedArray::FIELD_MAX) | \ - JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray), \ + JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray), \ PropertyStub, /* addProperty */ \ PropertyStub, /* delProperty */ \ PropertyStub, /* getProperty */ \ StrictPropertyStub, /* setProperty */ \ EnumerateStub, \ ResolveStub, \ ConvertStub, \ FinalizeStub \ } #define IMPL_TYPED_ARRAY_FAST_CLASS(_typedArray) \ { \ #_typedArray, \ - JSCLASS_HAS_RESERVED_SLOTS(TypedArray::FIELD_MAX) | \ - Class::NON_NATIVE, \ + Class::NON_NATIVE | JSCLASS_HAS_PRIVATE, \ PropertyStub, /* addProperty */ \ PropertyStub, /* delProperty */ \ PropertyStub, /* getProperty */ \ StrictPropertyStub, /* setProperty */ \ EnumerateStub, \ ResolveStub, \ ConvertStub, \ - NULL, /* finalize */ \ + _typedArray::class_finalize, \ NULL, /* reserved0 */ \ NULL, /* checkAccess */ \ NULL, /* call */ \ NULL, /* construct */ \ NULL, /* xdrObject */ \ NULL, /* hasInstance */ \ - _typedArray::obj_trace, /* trace */ \ + _typedArray::obj_trace, \ JS_NULL_CLASS_EXT, \ { \ _typedArray::obj_lookupProperty, \ _typedArray::obj_defineProperty, \ _typedArray::obj_getProperty, \ _typedArray::obj_setProperty, \ _typedArray::obj_getAttributes, \ _typedArray::obj_setAttributes, \ @@ -1760,16 +1768,17 @@ do { JSPROP_PERMANENT | JSPROP_READONLY) || \ !JS_DefineProperty(cx, proto, "BYTES_PER_ELEMENT", \ INT_TO_JSVAL(sizeof(_typedArray::ThisType)), \ JS_PropertyStub, JS_StrictPropertyStub, \ JSPROP_PERMANENT | JSPROP_READONLY)) \ { \ return NULL; \ } \ + proto->setPrivate(0); \ } while (0) IMPL_TYPED_ARRAY_STATICS(Int8Array); IMPL_TYPED_ARRAY_STATICS(Uint8Array); IMPL_TYPED_ARRAY_STATICS(Int16Array); IMPL_TYPED_ARRAY_STATICS(Uint16Array); IMPL_TYPED_ARRAY_STATICS(Int32Array); IMPL_TYPED_ARRAY_STATICS(Uint32Array); @@ -1831,17 +1840,17 @@ js_InitTypedArrayClasses(JSContext *cx, proto->setPrivate(NULL); /* * Initialize the slots to hold the length as 0 * This is required otherwise the length of a * ArrayBuffer's prototype is undefined. */ - if (!AllocateArrayBufferSlots(cx, proto, 0)) + if (!AllocateSlots(cx, proto, 0)) return NULL; return proto; } JS_FRIEND_API(JSBool) js_IsArrayBuffer(JSObject *obj) { JS_ASSERT(obj);
--- a/js/src/jstypedarray.h +++ b/js/src/jstypedarray.h @@ -136,64 +136,62 @@ struct JS_FRIEND_API(TypedArray) { * Special type that's a uint8, but assignments are clamped to 0 .. 255. * Treat the raw data type as a uint8. */ TYPE_UINT8_CLAMPED, TYPE_MAX }; - enum { - FIELD_LENGTH = 0, - FIELD_BYTEOFFSET, - FIELD_BYTELENGTH, - FIELD_TYPE, - FIELD_BUFFER, - FIELD_DATA, - FIELD_MAX - }; - // and MUST NOT be used to construct new objects. static Class fastClasses[TYPE_MAX]; // These are the slow/original classes, used // fo constructing new objects static Class slowClasses[TYPE_MAX]; static JSPropertySpec jsprops[]; - static JSObject *getTypedArray(JSObject *obj); + static TypedArray *fromJSObject(JSObject *obj); static JSBool prop_getBuffer(JSContext *cx, JSObject *obj, jsid id, Value *vp); static JSBool prop_getByteOffset(JSContext *cx, JSObject *obj, jsid id, Value *vp); static JSBool prop_getByteLength(JSContext *cx, JSObject *obj, jsid id, Value *vp); static JSBool prop_getLength(JSContext *cx, JSObject *obj, jsid id, Value *vp); static JSBool obj_lookupProperty(JSContext *cx, JSObject *obj, jsid id, JSObject **objp, JSProperty **propp); + static void obj_trace(JSTracer *trc, JSObject *obj); + static JSBool obj_getAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); static JSBool obj_setAttributes(JSContext *cx, JSObject *obj, jsid id, uintN *attrsp); - static JSUint32 getLength(JSObject *obj); - static JSUint32 getByteOffset(JSObject *obj); - static JSUint32 getByteLength(JSObject *obj); - static JSUint32 getType(JSObject *obj); - static JSObject * getBuffer(JSObject *obj); - static void * getDataOffset(JSObject *obj); - + static int32 lengthOffset() { return offsetof(TypedArray, length); } + static int32 dataOffset() { return offsetof(TypedArray, data); } + static int32 typeOffset() { return offsetof(TypedArray, type); } static void *offsetData(JSObject *obj, uint32 offs); public: - static bool - isArrayIndex(JSContext *cx, JSObject *obj, jsid id, jsuint *ip = NULL); + TypedArray() : bufferJS(0) { } + + bool isArrayIndex(JSContext *cx, jsid id, jsuint *ip = NULL); + bool valid() { return bufferJS != 0; } - static inline int slotWidth(JSObject *obj) { - switch (getType(obj)) { + JSObject *bufferJS; + uint32 byteOffset; + uint32 byteLength; + uint32 length; + uint32 type; + + void *data; + + inline int slotWidth() const { + switch (type) { case js::TypedArray::TYPE_INT8: case js::TypedArray::TYPE_UINT8: case js::TypedArray::TYPE_UINT8_CLAMPED: return 1; case js::TypedArray::TYPE_INT16: case js::TypedArray::TYPE_UINT16: return 2; case js::TypedArray::TYPE_INT32:
--- a/js/src/jstypedarrayinlines.h +++ b/js/src/jstypedarrayinlines.h @@ -51,40 +51,10 @@ ArrayBuffer::getByteLength(JSObject *obj return *((JSUint32*) obj->getSlotsPtr()); } inline uint8 * ArrayBuffer::getDataOffset(JSObject *obj) { uint64 *base = ((uint64*)obj->getSlotsPtr()) + 1; return (uint8*) base; } - -inline JSUint32 -TypedArray::getLength(JSObject *obj) { - return obj->getSlot(FIELD_LENGTH).toInt32(); -} - -inline JSUint32 -TypedArray::getByteOffset(JSObject *obj) { - return obj->getSlot(FIELD_BYTEOFFSET).toInt32(); -} - -inline JSUint32 -TypedArray::getByteLength(JSObject *obj) { - return obj->getSlot(FIELD_BYTELENGTH).toInt32(); -} - -inline JSUint32 -TypedArray::getType(JSObject *obj) { - return obj->getSlot(FIELD_TYPE).toInt32(); -} - -inline JSObject * -TypedArray::getBuffer(JSObject *obj) { - return &obj->getSlot(FIELD_BUFFER).toObject(); -} - -inline void * -TypedArray::getDataOffset(JSObject *obj) { - return (void *)((uint8*)obj->getSlot(FIELD_DATA).toPrivate() + getByteOffset(obj)); -} } #endif /* jstypedarrayinlines_h */
--- a/js/src/methodjit/PolyIC.cpp +++ b/js/src/methodjit/PolyIC.cpp @@ -2462,39 +2462,33 @@ GetElementIC::attachTypedArray(JSContext JS_ASSERT(hasInlineTypeGuard() || idRemat.knownType() == JSVAL_TYPE_INT32); Assembler masm; // Guard on this typed array's clasp. Jump claspGuard = masm.testObjClass(Assembler::NotEqual, objReg, obj->getClass()); // Get the internal typed array. - masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), objReg); + masm.loadPtr(Address(objReg, offsetof(JSObject, privateData)), objReg); // Bounds check. Jump outOfBounds; - Address typedArrayLength(objReg, sizeof(uint64) * js::TypedArray::FIELD_LENGTH); - typedArrayLength = masm.payloadOf(typedArrayLength); + Address typedArrayLength(objReg, js::TypedArray::lengthOffset()); if (idRemat.isConstant()) { JS_ASSERT(idRemat.value().toInt32() == v.toInt32()); outOfBounds = masm.branch32(Assembler::BelowOrEqual, typedArrayLength, Imm32(v.toInt32())); } else { outOfBounds = masm.branch32(Assembler::BelowOrEqual, typedArrayLength, idRemat.dataReg()); } // Load the array's packed data vector. - Address data_base(objReg, sizeof(Value) * js::TypedArray::FIELD_DATA); - masm.loadPrivate(data_base, objReg); - - JSObject *tarray = js::TypedArray::getTypedArray(obj); - int shift = js::TypedArray::slotWidth(tarray); - - int byteOffset = js::TypedArray::getByteOffset(tarray); - masm.addPtr(Imm32(byteOffset), objReg); - + masm.loadPtr(Address(objReg, js::TypedArray::dataOffset()), objReg); + + js::TypedArray *tarray = js::TypedArray::fromJSObject(obj); + int shift = tarray->slotWidth(); if (idRemat.isConstant()) { int32 index = v.toInt32(); Address addr(objReg, index * shift); LoadFromTypedArray(masm, tarray, addr, typeReg, objReg); } else { Assembler::Scale scale = Assembler::TimesOne; switch (shift) { case 2: @@ -2805,41 +2799,36 @@ SetElementIC::attachHoleStub(JSContext * #if defined JS_POLYIC_TYPED_ARRAY LookupStatus SetElementIC::attachTypedArray(JSContext *cx, JSObject *obj, int32 key) { // Right now, only one clasp guard extension is supported. JS_ASSERT(!inlineClaspGuardPatched); Assembler masm; - //masm.breakpoint(); // Guard on this typed array's clasp. Jump claspGuard = masm.testObjClass(Assembler::NotEqual, objReg, obj->getClass()); // Get the internal typed array. - masm.loadPtr(Address(objReg, JSObject::offsetOfSlots()), objReg); + masm.loadPtr(Address(objReg, offsetof(JSObject, privateData)), objReg); // Bounds check. Jump outOfBounds; - Address typedArrayLength(objReg, sizeof(uint64) * js::TypedArray::FIELD_LENGTH); - typedArrayLength = masm.payloadOf(typedArrayLength); + Address typedArrayLength(objReg, js::TypedArray::lengthOffset()); if (hasConstantKey) outOfBounds = masm.branch32(Assembler::BelowOrEqual, typedArrayLength, Imm32(keyValue)); else outOfBounds = masm.branch32(Assembler::BelowOrEqual, typedArrayLength, keyReg); // Load the array's packed data vector. - JSObject *tarray = js::TypedArray::getTypedArray(obj); - int byteOffset = js::TypedArray::getByteOffset(tarray); - Address base_data(objReg, sizeof(uint64) * js::TypedArray::FIELD_DATA); - masm.loadPrivate(base_data, objReg); - masm.addPtr(Imm32(byteOffset), objReg); - - int shift = js::TypedArray::slotWidth(obj); + js::TypedArray *tarray = js::TypedArray::fromJSObject(obj); + masm.loadPtr(Address(objReg, js::TypedArray::dataOffset()), objReg); + + int shift = tarray->slotWidth(); if (hasConstantKey) { Address addr(objReg, keyValue * shift); if (!StoreToTypedArray(cx, masm, tarray, addr, vr, volatileMask)) return error(cx); } else { Assembler::Scale scale = Assembler::TimesOne; switch (shift) { case 2:
--- a/js/src/methodjit/TypedArrayIC.h +++ b/js/src/methodjit/TypedArrayIC.h @@ -39,35 +39,34 @@ #ifndef js_typedarray_ic_h___ #define js_typedarray_ic_h___ #include "jscntxt.h" #include "jstypedarray.h" #include "jsnuminlines.h" -#include "jstypedarrayinlines.h" namespace js { namespace mjit { #ifdef JS_POLYIC_TYPED_ARRAY typedef JSC::MacroAssembler::RegisterID RegisterID; typedef JSC::MacroAssembler::FPRegisterID FPRegisterID; typedef JSC::MacroAssembler::Jump Jump; typedef JSC::MacroAssembler::Imm32 Imm32; typedef JSC::MacroAssembler::ImmDouble ImmDouble; template <typename T> static void -LoadFromTypedArray(Assembler &masm, JSObject *tarray, T address, +LoadFromTypedArray(Assembler &masm, js::TypedArray *tarray, T address, RegisterID typeReg, RegisterID dataReg) { - switch (TypedArray::getType(tarray)) { + switch (tarray->type) { case js::TypedArray::TYPE_INT8: masm.load8SignExtend(address, dataReg); masm.move(ImmType(JSVAL_TYPE_INT32), typeReg); break; case js::TypedArray::TYPE_UINT8: case js::TypedArray::TYPE_UINT8_CLAMPED: masm.load8ZeroExtend(address, dataReg); masm.move(ImmType(JSVAL_TYPE_INT32), typeReg); @@ -92,17 +91,17 @@ LoadFromTypedArray(Assembler &masm, JSOb masm.convertUInt32ToDouble(dataReg, FPRegisters::First); masm.breakDouble(FPRegisters::First, typeReg, dataReg); safeInt.linkTo(masm.label(), &masm); break; } case js::TypedArray::TYPE_FLOAT32: case js::TypedArray::TYPE_FLOAT64: { - if (TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32) + if (tarray->type == js::TypedArray::TYPE_FLOAT32) masm.loadFloat(address, FPRegisters::First); else masm.loadDouble(address, FPRegisters::First); // Make sure NaN gets canonicalized. Jump notNaN = masm.branchDouble(Assembler::DoubleEqual, FPRegisters::First, FPRegisters::First); masm.loadStaticDouble(&js_NaN, FPRegisters::First, dataReg); @@ -159,17 +158,17 @@ ClampIntForUint8Array(int32 x) if (x < 0) return 0; if (x > 255) return 255; return x; } static inline bool -ConstantFoldForIntArray(JSContext *cx, JSObject *tarray, ValueRemat *vr) +ConstantFoldForIntArray(JSContext *cx, js::TypedArray *tarray, ValueRemat *vr) { if (!vr->isTypeKnown()) return true; // Objects and undefined coerce to NaN, which coerces to 0. // Null converts to 0. if (vr->knownType() == JSVAL_TYPE_OBJECT || vr->knownType() == JSVAL_TYPE_UNDEFINED || @@ -187,39 +186,39 @@ ConstantFoldForIntArray(JSContext *cx, J double d; if (!StringToNumberType<double>(cx, v.toString(), &d)) return false; v.setNumber(d); } int32 i32 = 0; if (v.isDouble()) { - i32 = (TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED) + i32 = (tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED) ? js_TypedArray_uint8_clamp_double(v.toDouble()) : js_DoubleToECMAInt32(v.toDouble()); } else if (v.isInt32()) { i32 = v.toInt32(); - if (TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED) + if (tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED) i32 = ClampIntForUint8Array(i32); } else if (v.isBoolean()) { i32 = v.toBoolean() ? 1 : 0; } else { JS_NOT_REACHED("unknown constant type"); } *vr = ValueRemat::FromConstant(Int32Value(i32)); return true; } template <typename S, typename T> static void -StoreToIntArray(Assembler &masm, JSObject *tarray, S src, T address) +StoreToIntArray(Assembler &masm, js::TypedArray *tarray, S src, T address) { - switch (TypedArray::getType(tarray)) { + switch (tarray->type) { case js::TypedArray::TYPE_INT8: case js::TypedArray::TYPE_UINT8: case js::TypedArray::TYPE_UINT8_CLAMPED: masm.store8(src, address); break; case js::TypedArray::TYPE_INT16: case js::TypedArray::TYPE_UINT16: masm.store16(src, address); @@ -230,31 +229,31 @@ StoreToIntArray(Assembler &masm, JSObjec break; default: JS_NOT_REACHED("unknown int array type"); } } template <typename S, typename T> static void -StoreToFloatArray(Assembler &masm, JSObject *tarray, S src, T address) +StoreToFloatArray(Assembler &masm, js::TypedArray *tarray, S src, T address) { - if (TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32) + if (tarray->type == js::TypedArray::TYPE_FLOAT32) masm.storeFloat(src, address); else masm.storeDouble(src, address); } // Generate code that will ensure a dynamically typed value, pinned in |vr|, // can be stored in an integer typed array. If any sort of conversion is // required, |dataReg| will be clobbered by a new value. |saveMask| is // used to ensure that |dataReg| (and volatile registers) are preserved // across any conversion process. static void -GenConversionForIntArray(Assembler &masm, JSObject *tarray, const ValueRemat &vr, +GenConversionForIntArray(Assembler &masm, js::TypedArray *tarray, const ValueRemat &vr, uint32 saveMask) { if (vr.isConstant()) { // Constants are always folded to ints up-front. JS_ASSERT(vr.knownType() == JSVAL_TYPE_INT32); return; } @@ -273,33 +272,33 @@ GenConversionForIntArray(Assembler &masm saveForCall.preserve(saveMask & Registers::TempRegs); masm.setupABICall(Registers::FastCall, 2); masm.storeArg(0, masm.vmFrameOffset(offsetof(VMFrame, cx))); masm.storeArgAddr(1, masm.addressOfExtra(vp)); typedef int32 (JS_FASTCALL *Int32CxVp)(JSContext *, Value *); Int32CxVp stub; - if (TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED) + if (tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED) stub = stubs::ConvertToTypedInt<true>; else stub = stubs::ConvertToTypedInt<false>; masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, stub), false); if (vr.dataReg() != Registers::ReturnReg) masm.move(Registers::ReturnReg, vr.dataReg()); saveForCall.restore(); masm.freeStack(vp); if (checkInt32.isSet()) checkInt32.get().linkTo(masm.label(), &masm); } // Performing clamping, if needed. - if (TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED) { + if (tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED) { // cmp dr, 0 // jge _min // mov dr, 0 // jump _done // _min: // cmp dr, 255 // jle _done // mov dr, 255 @@ -319,17 +318,17 @@ GenConversionForIntArray(Assembler &masm // Generate code that will ensure a dynamically typed value, pinned in |vr|, // can be stored in an integer typed array. saveMask| is used to ensure that // |dataReg| (and volatile registers) are preserved across any conversion // process. // // Constants are left untouched. Any other value is placed into // FPRegisters::First. static void -GenConversionForFloatArray(Assembler &masm, JSObject *tarray, const ValueRemat &vr, +GenConversionForFloatArray(Assembler &masm, js::TypedArray *tarray, const ValueRemat &vr, FPRegisterID destReg, uint32 saveMask) { if (vr.isConstant()) { // Constants are always folded to doubles up-front. JS_ASSERT(vr.knownType() == JSVAL_TYPE_DOUBLE); return; } @@ -384,28 +383,28 @@ GenConversionForFloatArray(Assembler &ma masm.fastLoadDouble(vr.dataReg(), vr.typeReg(), destReg); // At this point, all loads into xmm1 are complete. if (skip1.isSet()) skip1.get().linkTo(masm.label(), &masm); if (skip2.isSet()) skip2.get().linkTo(masm.label(), &masm); - if (TypedArray::getType(tarray) == js::TypedArray::TYPE_FLOAT32) + if (tarray->type == js::TypedArray::TYPE_FLOAT32) masm.convertDoubleToFloat(destReg, destReg); } template <typename T> static bool -StoreToTypedArray(JSContext *cx, Assembler &masm, JSObject *tarray, T address, +StoreToTypedArray(JSContext *cx, Assembler &masm, js::TypedArray *tarray, T address, const ValueRemat &vrIn, uint32 saveMask) { ValueRemat vr = vrIn; - switch (TypedArray::getType(tarray)) { + switch (tarray->type) { case js::TypedArray::TYPE_INT8: case js::TypedArray::TYPE_UINT8: case js::TypedArray::TYPE_UINT8_CLAMPED: case js::TypedArray::TYPE_INT16: case js::TypedArray::TYPE_UINT16: case js::TypedArray::TYPE_INT32: case js::TypedArray::TYPE_UINT32: { @@ -424,21 +423,21 @@ StoreToTypedArray(JSContext *cx, Assembl // In all of these cases, we try to find a free register that can be // used to mutate the RHS. Failing that, we evict an existing volatile // register. // // Note that we are careful to preserve the RHS before saving registers // for the conversion call. This is because the object and key may be // in temporary registers, and we want to restore those without killing // the mutated RHS. - bool singleByte = (TypedArray::getType(tarray) == js::TypedArray::TYPE_INT8 || - TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8 || - TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED); + bool singleByte = (tarray->type == js::TypedArray::TYPE_INT8 || + tarray->type == js::TypedArray::TYPE_UINT8 || + tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED); bool mayNeedConversion = (!vr.isTypeKnown() || vr.knownType() != JSVAL_TYPE_INT32); - bool mayNeedClamping = !vr.isConstant() && (TypedArray::getType(tarray) == js::TypedArray::TYPE_UINT8_CLAMPED); + bool mayNeedClamping = !vr.isConstant() && (tarray->type == js::TypedArray::TYPE_UINT8_CLAMPED); bool needsSingleByteReg = singleByte && !vr.isConstant() && !(Registers::SingleByteRegs & Registers::maskReg(vr.dataReg())); bool rhsIsMutable = !vr.isConstant() && !(saveMask & Registers::maskReg(vr.dataReg())); if (((mayNeedConversion || mayNeedClamping) && !rhsIsMutable) || needsSingleByteReg) { // First attempt to find a free temporary register that: // - is compatible with the RHS constraints
--- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -69,17 +69,16 @@ #include "jsnum.h" #include "jsobj.h" #include "json.h" #include "jsparse.h" #include "jsreflect.h" #include "jsscope.h" #include "jsscript.h" #include "jstypedarray.h" -#include "jstypedarrayinlines.h" #include "jsxml.h" #include "jsperf.h" #include "prmjtime.h" #ifdef JSDEBUGGER #include "jsdebug.h" #ifdef JSDEBUGGER_JAVA_UI @@ -879,17 +878,17 @@ FileAsTypedArray(JSContext *cx, const ch } else { size_t len = ftell(file); if (fseek(file, 0, SEEK_SET) != 0) { JS_ReportError(cx, "can't seek start of %s", pathname); } else { obj = js_CreateTypedArray(cx, TypedArray::TYPE_UINT8, len); if (!obj) return NULL; - char *buf = (char *) TypedArray::getDataOffset(TypedArray::getTypedArray(obj)); + char *buf = (char *) TypedArray::fromJSObject(obj)->data; size_t cc = fread(buf, 1, len, file); if (cc != len) { JS_ReportError(cx, "can't read %s: %s", pathname, (ptrdiff_t(cc) < 0) ? strerror(errno) : "short read"); obj = NULL; } } } @@ -4325,44 +4324,44 @@ Serialize(JSContext *cx, uintN argc, jsv if (!JS_WriteStructuredClone(cx, v, &datap, &nbytes, NULL, NULL)) return false; JSObject *arrayobj = js_CreateTypedArray(cx, TypedArray::TYPE_UINT8, nbytes); if (!arrayobj) { JS_free(cx, datap); return false; } - JSObject *array = TypedArray::getTypedArray(arrayobj); - JS_ASSERT((uintptr_t(TypedArray::getDataOffset(array)) & 7) == 0); - memcpy(TypedArray::getDataOffset(array), datap, nbytes); + TypedArray *array = TypedArray::fromJSObject(arrayobj); + JS_ASSERT((uintptr_t(array->data) & 7) == 0); + memcpy(array->data, datap, nbytes); JS_free(cx, datap); JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(arrayobj)); return true; } JSBool Deserialize(JSContext *cx, uintN argc, jsval *vp) { jsval v = argc > 0 ? JS_ARGV(cx, vp)[0] : JSVAL_VOID; JSObject *obj; if (JSVAL_IS_PRIMITIVE(v) || !js_IsTypedArray((obj = JSVAL_TO_OBJECT(v)))) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize"); return false; } - JSObject *array = TypedArray::getTypedArray(obj); - if ((TypedArray::getByteLength(array) & 7) != 0) { + TypedArray *array = TypedArray::fromJSObject(obj); + if ((array->byteLength & 7) != 0) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize"); return false; } - if ((uintptr_t(TypedArray::getDataOffset(array)) & 7) != 0) { + if ((uintptr_t(array->data) & 7) != 0) { JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_BAD_ALIGNMENT); return false; } - if (!JS_ReadStructuredClone(cx, (uint64 *) TypedArray::getDataOffset(array), TypedArray::getByteLength(array), + if (!JS_ReadStructuredClone(cx, (uint64 *) array->data, array->byteLength, JS_STRUCTURED_CLONE_VERSION, &v, NULL, NULL)) { return false; } JS_SET_RVAL(cx, vp, v); return true; } JSBool
--- a/js/src/tests/js1_8_5/extensions/typedarray.js +++ b/js/src/tests/js1_8_5/extensions/typedarray.js @@ -371,22 +371,14 @@ function test() for (var i = 0; i < a.length; i++) check(function() a[i] == 0) a = new Uint8Array(121); check(function() a.byteLength == 121); check(function() a.length == 121); for (var i = 0; i < a.length; i++) check(function() a[i] == 0) - - // check that TM generated byte offset is right (requires run with -j) - a = new Uint8Array(100); - a[99] = 5; - b = new Uint8Array(a.buffer, 9); // force a offset - // use a loop to invoke the TM - for (var i = 0; i < b.length; i++) - check(function() b[90] == 5) print ("done"); reportCompare(0, TestFailCount, "typed array tests"); exitFunc ('test'); }
--- a/js/src/tracejit/Writer.cpp +++ b/js/src/tracejit/Writer.cpp @@ -454,38 +454,35 @@ void ValidateWriter::checkAccSet(LOpcode // ins = {ld,st}X.slots base[...] ok = couldBeObjectOrString(base) || match(base, LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots)) || (base->isop(LIR_addp) && match(base->oprnd1(), LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots))); break; case ACCSET_TARRAY: - // we actually just want the JSObject itself // This check is imperfect. // // base = ldp.objprivate ...[offsetof(JSObject, privateData)] // ins = ld{i,p}.tarray base[<disp within TypedArray>] - ok = (op == LIR_ldi || op == LIR_ldp); /*&&*/ - //match(base, LIR_ldp, ACCSET_OBJ_SLOTS, offsetof(JSObject, slots)); + ok = (op == LIR_ldi || op == LIR_ldp) && + dispWithin(TypedArray) && + match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData)); break; case ACCSET_TARRAY_DATA: // base = ldp.tarray/c ...[TypedArray::dataOffset()] // ins = {ld,st}X.tdata base[...] // OR // base_oprnd1 = ldp.tarray/c ...[TypedArray::dataOffset()] // base = addp base_oprnd1, ... // ins = {ld,st}X.tdata base[...] - ok = true; - //ok = isConstPrivatePtr(base, TypedArray::FIELD_DATA); - JS_ASSERT(ok); - //ok = match(base, LIR_ldp, ACCSET_TARRAY, LOAD_CONST, sizeof(js::Value) * js::TypedArray::FIELD_DATA) || - //((base->isop(LIR_addp) && - //match(base->oprnd1(), LIR_ldp, ACCSET_TARRAY, sizeof(js::Value) * js::TypedArray::FIELD_DATA))); + ok = match(base, LIR_ldp, ACCSET_TARRAY, LOAD_CONST, TypedArray::dataOffset()) || + (base->isop(LIR_addp) && + match(base->oprnd1(), LIR_ldp, ACCSET_TARRAY, LOAD_CONST, TypedArray::dataOffset())); break; case ACCSET_ITER: // base = ldp.objprivate ...[offsetof(JSObject, privateData)] // ins = {ld,st}p.iter base[<disp within NativeIterator>] ok = (op == LIR_ldp || op == LIR_stp) && dispWithin(NativeIterator) && match(base, LIR_ldp, ACCSET_OBJ_PRIVATE, offsetof(JSObject, privateData));
--- a/js/src/tracejit/Writer.h +++ b/js/src/tracejit/Writer.h @@ -528,51 +528,26 @@ class Writer "capacity"); } nj::LIns *ldpObjSlots(nj::LIns *obj) const { return name(lir->insLoad(nj::LIR_ldp, obj, JSObject::offsetOfSlots(), ACCSET_OBJ_SLOTS), "slots"); } - nj::LIns *ldpObjFixedSlots(nj::LIns *obj) const { - //return name(lir->insLoad(nj::LIR_ldp, obj, sizeof(JSObject), ACCSET_SLOTS), -#if JS_BITS_PER_WORD == 32 - return name(lir->ins2(nj::LIR_addp, obj, lir->insImmI(sizeof(JSObject))), -#else - return name(lir->ins2(nj::LIR_addp, obj, lir->insImmQ(sizeof(JSObject))), -#endif - "fixed_slots"); - } - nj::LIns *ldiConstTypedArrayLength(nj::LIns *array) const { - return name(lir->insLoad(nj::LIR_ldi, array, sizeof(Value) * js::TypedArray::FIELD_LENGTH + sPayloadOffset, ACCSET_TARRAY, + return name(lir->insLoad(nj::LIR_ldi, array, js::TypedArray::lengthOffset(), ACCSET_TARRAY, nj::LOAD_CONST), "typedArrayLength"); } - nj::LIns *ldiConstTypedArrayByteOffset(nj::LIns *array) const { - return name(lir->insLoad(nj::LIR_ldi, array, sizeof(Value) * js::TypedArray::FIELD_BYTEOFFSET + sPayloadOffset, ACCSET_TARRAY, + nj::LIns *ldpConstTypedArrayData(nj::LIns *array) const { + return name(lir->insLoad(nj::LIR_ldp, array, js::TypedArray::dataOffset(), ACCSET_TARRAY, nj::LOAD_CONST), - "typedArrayByteOffset"); - } - - nj::LIns *ldpConstTypedArrayData(nj::LIns *array) const { - //return name(lir->insLoad(nj::LIR_ldp, array, sizeof(Value) * js::TypedArray::FIELD_DATA + sPayloadOffset, ACCSET_TARRAY, - //nj::LOAD_CONST), - //"typedElems"); - uint32 offset = sizeof(Value) * js::TypedArray::FIELD_DATA + sPayloadOffset; -#if JS_BITS_PER_WORD == 32 - return name(lir->insLoad(nj::LIR_ldi, array, offset, ACCSET_TARRAY, nj::LOAD_CONST), "typedArrayData"); -#elif JS_BITS_PER_WORD == 64 - /* N.B. On 64-bit, privatized value are encoded differently from other pointers. */ - nj::LIns *v_ins = lir->insLoad(nj::LIR_ldq, array, offset, - ACCSET_TARRAY, nj::LOAD_CONST); - return name(lshqN(v_ins, 1), "typedArrayData"); -#endif + "typedElems"); } nj::LIns *ldc2iTypedArrayElement(nj::LIns *elems, nj::LIns *index) const { return lir->insLoad(nj::LIR_ldc2i, addp(elems, index), 0, ACCSET_TARRAY_DATA); } nj::LIns *lduc2uiTypedArrayElement(nj::LIns *elems, nj::LIns *index) const { return lir->insLoad(nj::LIR_lduc2ui, addp(elems, index), 0, ACCSET_TARRAY_DATA);