Bug 889146 (part 11) - Move some functions into TypedArrayObject and make its SLOT members private. r=sfink.

--HG--
extra : rebase_source : dc626c3c0df3cfea856dd7e5b49122c6ef092d36
This commit is contained in:
Nicholas Nethercote 2013-07-02 13:30:37 -07:00
parent ea5e9da9f9
commit 2ff709e375
14 changed files with 287 additions and 320 deletions

View File

@ -3487,9 +3487,9 @@ static bool TryAttachNativeGetElemStub(JSContext *cx, HandleScript script,
}
static bool
TypedArrayRequiresFloatingPoint(JSObject *obj)
TypedArrayRequiresFloatingPoint(TypedArrayObject *tarr)
{
uint32_t type = TypedArrayObject::type(obj);
uint32_t type = tarr->type();
return (type == TypedArrayObject::TYPE_UINT32 ||
type == TypedArrayObject::TYPE_FLOAT32 ||
type == TypedArrayObject::TYPE_FLOAT64);
@ -3575,11 +3575,12 @@ TryAttachGetElemStub(JSContext *cx, HandleScript script, ICGetElem_Fallback *stu
if (obj->isTypedArray() && rhs.isInt32() && res.isNumber() &&
!TypedArrayGetElemStubExists(stub, obj))
{
if (!cx->runtime()->jitSupportsFloatingPoint && TypedArrayRequiresFloatingPoint(obj))
Rooted<TypedArrayObject*> tarr(cx, &obj->as<TypedArrayObject>());
if (!cx->runtime()->jitSupportsFloatingPoint && TypedArrayRequiresFloatingPoint(tarr))
return true;
IonSpew(IonSpew_BaselineIC, " Generating GetElem(TypedArray[Int32]) stub");
ICGetElem_TypedArray::Compiler compiler(cx, obj->lastProperty(), TypedArrayObject::type(obj));
ICGetElem_TypedArray::Compiler compiler(cx, tarr->lastProperty(), tarr->type());
ICStub *typedArrayStub = compiler.getStub(compiler.getStubSpace(script));
if (!typedArrayStub)
return false;
@ -4241,23 +4242,23 @@ DoSetElemFallback(JSContext *cx, BaselineFrame *frame, ICSetElem_Fallback *stub,
}
if (obj->isTypedArray() && index.isInt32() && rhs.isNumber()) {
if (!cx->runtime()->jitSupportsFloatingPoint && TypedArrayRequiresFloatingPoint(obj))
Rooted<TypedArrayObject*> tarr(cx, &obj->as<TypedArrayObject>());
if (!cx->runtime()->jitSupportsFloatingPoint && TypedArrayRequiresFloatingPoint(tarr))
return true;
uint32_t len = TypedArrayObject::length(obj);
uint32_t len = tarr->length();
int32_t idx = index.toInt32();
bool expectOutOfBounds = (idx < 0) || (static_cast<uint32_t>(idx) >= len);
if (!TypedArraySetElemStubExists(stub, obj, expectOutOfBounds)) {
if (!TypedArraySetElemStubExists(stub, tarr, expectOutOfBounds)) {
// Remove any existing TypedArraySetElemStub that doesn't handle out-of-bounds
if (expectOutOfBounds)
RemoveExistingTypedArraySetElemStub(cx, stub, obj);
RemoveExistingTypedArraySetElemStub(cx, stub, tarr);
IonSpew(IonSpew_BaselineIC,
" Generating SetElem_TypedArray stub (shape=%p, type=%u, oob=%s)",
obj->lastProperty(), TypedArrayObject::type(obj),
expectOutOfBounds ? "yes" : "no");
ICSetElem_TypedArray::Compiler compiler(cx, obj->lastProperty(), TypedArrayObject::type(obj),
tarr->lastProperty(), tarr->type(), expectOutOfBounds ? "yes" : "no");
ICSetElem_TypedArray::Compiler compiler(cx, tarr->lastProperty(), tarr->type(),
expectOutOfBounds);
ICStub *typedArrayStub = compiler.getStub(compiler.getStubSpace(script));
if (!typedArrayStub)

View File

@ -6432,8 +6432,8 @@ MInstruction *
IonBuilder::getTypedArrayLength(MDefinition *obj)
{
if (obj->isConstant() && obj->toConstant()->value().isObject()) {
JSObject *array = &obj->toConstant()->value().toObject();
int32_t length = (int32_t) TypedArrayObject::length(array);
TypedArrayObject *tarr = &obj->toConstant()->value().toObject().as<TypedArrayObject>();
int32_t length = (int32_t) tarr->length();
obj->setFoldedUnchecked();
return MConstant::New(Int32Value(length));
}
@ -6444,12 +6444,12 @@ MInstruction *
IonBuilder::getTypedArrayElements(MDefinition *obj)
{
if (obj->isConstant() && obj->toConstant()->value().isObject()) {
JSObject *array = &obj->toConstant()->value().toObject();
void *data = TypedArrayObject::viewData(array);
TypedArrayObject *tarr = &obj->toConstant()->value().toObject().as<TypedArrayObject>();
void *data = tarr->viewData();
// The 'data' pointer can change in rare circumstances
// (ArrayBufferObject::changeContents).
types::HeapTypeSet::WatchObjectStateChange(cx, array->getType(cx));
types::HeapTypeSet::WatchObjectStateChange(cx, tarr->getType(cx));
obj->setFoldedUnchecked();
return MConstantElements::New(data);
@ -6497,12 +6497,12 @@ IonBuilder::jsop_getelem_typed_static(bool *psucceeded)
if (!obj->resultTypeSet())
return true;
JSObject *typedArray = obj->resultTypeSet()->getSingleton();
if (!typedArray)
JSObject *tarrObj = obj->resultTypeSet()->getSingleton();
if (!tarrObj)
return true;
JS_ASSERT(typedArray->isTypedArray());
TypedArrayObject *tarr = &tarrObj->as<TypedArrayObject>();
ArrayBufferView::ViewType viewType = JS_GetArrayBufferViewType(typedArray);
ArrayBufferView::ViewType viewType = JS_GetArrayBufferViewType(tarr);
MDefinition *ptr = convertShiftToMaskForStaticTypedArray(id, viewType);
if (!ptr)
@ -6510,7 +6510,7 @@ IonBuilder::jsop_getelem_typed_static(bool *psucceeded)
obj->setFoldedUnchecked();
MLoadTypedArrayElementStatic *load = MLoadTypedArrayElementStatic::New(typedArray, ptr);
MLoadTypedArrayElementStatic *load = MLoadTypedArrayElementStatic::New(tarr, ptr);
current->add(load);
// The load is infallible if an undefined result will be coerced to the
@ -6842,12 +6842,12 @@ IonBuilder::jsop_setelem_typed_static(MDefinition *obj, MDefinition *id, MDefini
if (!obj->resultTypeSet())
return true;
JSObject *typedArray = obj->resultTypeSet()->getSingleton();
if (!typedArray)
JSObject *tarrObj = obj->resultTypeSet()->getSingleton();
if (!tarrObj)
return true;
JS_ASSERT(typedArray->isTypedArray());
TypedArrayObject *tarr = &tarrObj->as<TypedArrayObject>();
ArrayBufferView::ViewType viewType = JS_GetArrayBufferViewType(typedArray);
ArrayBufferView::ViewType viewType = JS_GetArrayBufferViewType(tarr);
MDefinition *ptr = convertShiftToMaskForStaticTypedArray(id, viewType);
if (!ptr)
@ -6862,7 +6862,7 @@ IonBuilder::jsop_setelem_typed_static(MDefinition *obj, MDefinition *id, MDefini
current->add(toWrite->toInstruction());
}
MInstruction *store = MStoreTypedArrayElementStatic::New(typedArray, ptr, toWrite);
MInstruction *store = MStoreTypedArrayElementStatic::New(tarr, ptr, toWrite);
current->add(store);
current->push(value);

View File

@ -2225,17 +2225,15 @@ GetElementIC::attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, c
}
bool
GetElementIC::attachTypedArrayElement(JSContext *cx, IonScript *ion, JSObject *obj,
GetElementIC::attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr,
const Value &idval)
{
JS_ASSERT(obj->isTypedArray());
Label failures;
MacroAssembler masm(cx);
RepatchStubAppender attacher(*this);
// The array type is the object within the table of typed array classes.
int arrayType = TypedArrayObject::type(obj);
int arrayType = tarr->type();
// The output register is not yet specialized as a float register, the only
// way to accept float typed arrays for now is to return a Value type.
@ -2248,7 +2246,7 @@ GetElementIC::attachTypedArrayElement(JSContext *cx, IonScript *ion, JSObject *o
// Check that the typed array is of the same type as the current object
// because load size differ in function of the typed array data width.
masm.branchTestObjClass(Assembler::NotEqual, object(), tmpReg, obj->getClass(), &failures);
masm.branchTestObjClass(Assembler::NotEqual, object(), tmpReg, tarr->getClass(), &failures);
// Decide to what type index the stub should be optimized
Register indexReg = tmpReg;
@ -2503,11 +2501,12 @@ GetElementIC::update(JSContext *cx, size_t cacheIndex, HandleObject obj,
if ((idval.isInt32()) ||
(idval.isString() && GetIndexFromString(idval.toString()) != UINT32_MAX))
{
int arrayType = TypedArrayObject::type(obj);
Rooted<TypedArrayObject*> tarr(cx, &obj->as<TypedArrayObject>());
int arrayType = tarr->type();
bool floatOutput = arrayType == TypedArrayObject::TYPE_FLOAT32 ||
arrayType == TypedArrayObject::TYPE_FLOAT64;
if (!floatOutput || cache.output().hasValue()) {
if (!cache.attachTypedArrayElement(cx, ion, obj, idval))
if (!cache.attachTypedArrayElement(cx, ion, tarr, idval))
return false;
attachedStub = true;
}

View File

@ -16,6 +16,9 @@ class JSFunction;
class JSScript;
namespace js {
class TypedArrayObject;
namespace ion {
#define IONCACHE_KIND_LIST(_) \
@ -667,7 +670,8 @@ class GetElementIC : public RepatchIonCache
bool attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj, const Value &idval, HandlePropertyName name);
bool attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval);
bool attachTypedArrayElement(JSContext *cx, IonScript *ion, JSObject *obj, const Value &idval);
bool attachTypedArrayElement(JSContext *cx, IonScript *ion, TypedArrayObject *tarr,
const Value &idval);
bool attachArgumentsElement(JSContext *cx, IonScript *ion, JSObject *obj);
static bool

View File

@ -2307,25 +2307,25 @@ MInArray::needsNegativeIntCheck() const
void *
MLoadTypedArrayElementStatic::base() const
{
return TypedArrayObject::viewData(typedArray_);
return typedArray_->viewData();
}
size_t
MLoadTypedArrayElementStatic::length() const
{
return TypedArrayObject::byteLength(typedArray_);
return typedArray_->byteLength();
}
void *
MStoreTypedArrayElementStatic::base() const
{
return TypedArrayObject::viewData(typedArray_);
return typedArray_->viewData();
}
size_t
MStoreTypedArrayElementStatic::length() const
{
return TypedArrayObject::byteLength(typedArray_);
return typedArray_->byteLength();
}
bool

View File

@ -5012,23 +5012,23 @@ class MLoadTypedArrayElementHole
// Load a value fallibly or infallibly from a statically known typed array.
class MLoadTypedArrayElementStatic : public MUnaryInstruction
{
MLoadTypedArrayElementStatic(JSObject *typedArray, MDefinition *ptr)
MLoadTypedArrayElementStatic(TypedArrayObject *typedArray, MDefinition *ptr)
: MUnaryInstruction(ptr), typedArray_(typedArray), fallible_(true)
{
int type = TypedArrayObject::type(typedArray_);
int type = typedArray_->type();
if (type == TypedArrayObject::TYPE_FLOAT32 || type == TypedArrayObject::TYPE_FLOAT64)
setResultType(MIRType_Double);
else
setResultType(MIRType_Int32);
}
CompilerRootObject typedArray_;
CompilerRoot<TypedArrayObject*> typedArray_;
bool fallible_;
public:
INSTRUCTION_HEADER(LoadTypedArrayElementStatic);
static MLoadTypedArrayElementStatic *New(JSObject *typedArray, MDefinition *ptr) {
static MLoadTypedArrayElementStatic *New(TypedArrayObject *typedArray, MDefinition *ptr) {
return new MLoadTypedArrayElementStatic(typedArray, ptr);
}
@ -5182,16 +5182,18 @@ class MStoreTypedArrayElementStatic :
public MBinaryInstruction
, public StoreTypedArrayElementStaticPolicy
{
MStoreTypedArrayElementStatic(JSObject *typedArray, MDefinition *ptr, MDefinition *v)
MStoreTypedArrayElementStatic(TypedArrayObject *typedArray, MDefinition *ptr, MDefinition *v)
: MBinaryInstruction(ptr, v), typedArray_(typedArray)
{}
CompilerRootObject typedArray_;
CompilerRoot<TypedArrayObject*> typedArray_;
public:
INSTRUCTION_HEADER(StoreTypedArrayElementStatic);
static MStoreTypedArrayElementStatic *New(JSObject *typedArray, MDefinition *ptr, MDefinition *v) {
static MStoreTypedArrayElementStatic *New(TypedArrayObject *typedArray, MDefinition *ptr,
MDefinition *v)
{
return new MStoreTypedArrayElementStatic(typedArray, ptr, v);
}

View File

@ -992,7 +992,7 @@ MLoadTypedArrayElement::computeRange()
void
MLoadTypedArrayElementStatic::computeRange()
{
if (Range *range = GetTypedArrayRange(TypedArrayObject::type(typedArray_)))
if (Range *range = GetTypedArrayRange(typedArray_->type()))
setRange(range);
}

View File

@ -582,19 +582,20 @@ JS_WriteTypedArray(JSStructuredCloneWriter *w, jsval v)
* swapped; the Int16Array requires that they are.
*/
bool
JSStructuredCloneWriter::writeTypedArray(HandleObject arr)
JSStructuredCloneWriter::writeTypedArray(HandleObject obj)
{
if (!out.writePair(SCTAG_TYPED_ARRAY_OBJECT, TypedArrayObject::length(arr)))
Rooted<TypedArrayObject*> tarr(context(), &obj->as<TypedArrayObject>());
if (!out.writePair(SCTAG_TYPED_ARRAY_OBJECT, tarr->length()))
return false;
uint64_t type = TypedArrayObject::type(arr);
uint64_t type = tarr->type();
if (!out.write(type))
return false;
// Write out the ArrayBuffer tag and contents
if (!startWrite(TypedArrayObject::bufferValue(arr)))
if (!startWrite(TypedArrayObject::bufferValue(tarr)))
return false;
return out.write(TypedArrayObject::byteOffset(arr));
return out.write(tarr->byteOffset());
}
bool

View File

@ -618,7 +618,7 @@ ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents,
ArrayBufferObject::setElementsHeader(header, 0);
GetViewList(&buffer)->init(views);
for (ArrayBufferViewObject *view = views; view; view = view->nextView())
TypedArrayObject::neuter(view);
view->neuter();
return true;
}
@ -1133,10 +1133,10 @@ ArrayBufferViewObject::setNextView(ArrayBufferViewObject *view)
*/
inline bool
TypedArrayObject::isArrayIndex(JSObject *obj, jsid id, uint32_t *ip)
TypedArrayObject::isArrayIndex(jsid id, uint32_t *ip)
{
uint32_t index;
if (js_IdIsIndex(id, &index) && index < length(obj)) {
if (js_IdIsIndex(id, &index) && index < length()) {
if (ip)
*ip = index;
return true;
@ -1146,22 +1146,19 @@ TypedArrayObject::isArrayIndex(JSObject *obj, jsid id, uint32_t *ip)
}
void
TypedArrayObject::neuter(JSObject *tarray)
TypedArrayObject::neuter()
{
JS_ASSERT(tarray->isTypedArray());
tarray->setSlot(LENGTH_SLOT, Int32Value(0));
tarray->setSlot(BYTELENGTH_SLOT, Int32Value(0));
tarray->setSlot(BYTEOFFSET_SLOT, Int32Value(0));
tarray->setPrivate(NULL);
setSlot(LENGTH_SLOT, Int32Value(0));
setSlot(BYTELENGTH_SLOT, Int32Value(0));
setSlot(BYTEOFFSET_SLOT, Int32Value(0));
setPrivate(NULL);
}
JSBool
TypedArrayObject::obj_lookupGeneric(JSContext *cx, HandleObject tarray, HandleId id,
MutableHandleObject objp, MutableHandleShape propp)
{
JS_ASSERT(tarray->isTypedArray());
if (isArrayIndex(tarray, id)) {
if (tarray->as<TypedArrayObject>().isArrayIndex(id)) {
MarkNonNativePropertyFound(propp);
objp.set(tarray);
return true;
@ -1189,9 +1186,7 @@ JSBool
TypedArrayObject::obj_lookupElement(JSContext *cx, HandleObject tarray, uint32_t index,
MutableHandleObject objp, MutableHandleShape propp)
{
JS_ASSERT(tarray->isTypedArray());
if (index < length(tarray)) {
if (index < tarray->as<TypedArrayObject>().length()) {
MarkNonNativePropertyFound(propp);
objp.set(tarray);
return true;
@ -1412,9 +1407,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
obj_getElement(JSContext *cx, HandleObject tarray, HandleObject receiver, uint32_t index,
MutableHandleValue vp)
{
JS_ASSERT(tarray->isTypedArray());
if (index < length(tarray)) {
if (index < tarray->as<TypedArrayObject>().length()) {
copyIndexToValue(tarray, index, vp);
return true;
}
@ -1470,10 +1463,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject
obj_getElementIfPresent(JSContext *cx, HandleObject tarray, HandleObject receiver, uint32_t index,
MutableHandleValue vp, bool *present)
{
JS_ASSERT(tarray->isTypedArray());
// Fast-path the common case of index < length
if (index < length(tarray)) {
if (index < tarray->as<TypedArrayObject>().length()) {
// this inline function is specialized for each type
copyIndexToValue(tarray, index, vp);
*present = true;
@ -1519,7 +1510,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
MutableHandleValue vp, JSBool strict)
{
JS_ASSERT(tarray);
JS_ASSERT(index < length(tarray));
JS_ASSERT(index < tarray->as<TypedArrayObject>().length());
if (vp.isInt32()) {
setIndex(tarray, index, NativeType(vp.toInt32()));
@ -1558,11 +1549,9 @@ class TypedArrayObjectTemplate : public TypedArrayObject
obj_setGeneric(JSContext *cx, HandleObject tarray, HandleId id,
MutableHandleValue vp, JSBool strict)
{
JS_ASSERT(tarray->isTypedArray());
uint32_t index;
// We can't just chain to js_SetPropertyHelper, because we're not a normal object.
if (!isArrayIndex(tarray, id, &index)) {
if (!tarray->as<TypedArrayObject>().isArrayIndex(id, &index)) {
// 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
@ -1587,9 +1576,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
obj_setElement(JSContext *cx, HandleObject tarray, uint32_t index,
MutableHandleValue vp, JSBool strict)
{
JS_ASSERT(tarray->isTypedArray());
if (index >= length(tarray)) {
if (index >= tarray->as<TypedArrayObject>().length()) {
// 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
@ -1652,9 +1639,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
static JSBool
obj_deleteElement(JSContext *cx, HandleObject tarray, uint32_t index, JSBool *succeeded)
{
JS_ASSERT(tarray->isTypedArray());
if (index < length(tarray)) {
if (index < tarray->as<TypedArrayObject>().length()) {
*succeeded = false;
return true;
}
@ -1681,20 +1666,21 @@ class TypedArrayObjectTemplate : public TypedArrayObject
case JSENUMERATE_INIT_ALL:
case JSENUMERATE_INIT:
statep.setInt32(0);
idp.set(::INT_TO_JSID(length(tarray)));
idp.set(::INT_TO_JSID(tarray->as<TypedArrayObject>().length()));
break;
case JSENUMERATE_NEXT:
case JSENUMERATE_NEXT: {
index = static_cast<uint32_t>(statep.toInt32());
if (index < length(tarray)) {
uint32_t length = tarray->as<TypedArrayObject>().length();
if (index < length) {
idp.set(::INT_TO_JSID(index));
statep.setInt32(index + 1);
} else {
JS_ASSERT(index == length(tarray));
JS_ASSERT(index == length);
statep.setNull();
}
break;
}
case JSENUMERATE_DESTROY:
statep.setNull();
break;
@ -1791,7 +1777,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
uint32_t bufferByteLength = buffer->byteLength();
uint32_t arrayByteLength = static_cast<uint32_t>(byteLengthValue(obj).toInt32());
uint32_t arrayByteOffset = static_cast<uint32_t>(byteOffsetValue(obj).toInt32());
JS_ASSERT(buffer->dataPointer() <= viewData(obj));
JS_ASSERT(buffer->dataPointer() <= obj->viewData());
JS_ASSERT(bufferByteLength - byteOffsetValue(obj).toInt32() >= arrayByteLength);
JS_ASSERT(arrayByteOffset <= bufferByteLength);
@ -1889,19 +1875,19 @@ class TypedArrayObjectTemplate : public TypedArrayObject
return v.isObject() && v.toObject().hasClass(fastClass());
}
template<Value ValueGetter(JSObject *obj)>
template<Value ValueGetter(TypedArrayObject *tarr)>
static bool
GetterImpl(JSContext *cx, CallArgs args)
{
JS_ASSERT(IsThisClass(args.thisv()));
args.rval().set(ValueGetter(&args.thisv().toObject()));
args.rval().set(ValueGetter(&args.thisv().toObject().as<TypedArrayObject>()));
return true;
}
// ValueGetter is a function that takes an unwrapped typed array object and
// returns a Value. Given such a function, Getter<> is a native that
// retrieves a given Value, probably from a slot on the object.
template<Value ValueGetter(JSObject *obj)>
template<Value ValueGetter(TypedArrayObject *tarr)>
static JSBool
Getter(JSContext *cx, unsigned argc, Value *vp)
{
@ -1911,7 +1897,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
}
// Define an accessor for a read-only property that invokes a native getter
template<Value ValueGetter(JSObject *obj)>
template<Value ValueGetter(TypedArrayObject *tarr)>
static bool
DefineGetter(JSContext *cx, PropertyName *name, HandleObject proto)
{
@ -1953,11 +1939,11 @@ class TypedArrayObjectTemplate : public TypedArrayObject
fun_subarray_impl(JSContext *cx, CallArgs args)
{
JS_ASSERT(IsThisClass(args.thisv()));
RootedObject tarray(cx, &args.thisv().toObject());
Rooted<TypedArrayObject*> tarray(cx, &args.thisv().toObject().as<TypedArrayObject>());
// these are the default values
uint32_t begin = 0, end = length(tarray);
uint32_t length = TypedArrayObject::length(tarray);
uint32_t length = tarray->length();
uint32_t begin = 0, end = length;
if (args.length() > 0) {
if (!ToClampedIndex(cx, args[0], length, &begin))
@ -1992,7 +1978,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
fun_move_impl(JSContext *cx, CallArgs args)
{
JS_ASSERT(IsThisClass(args.thisv()));
RootedObject tarray(cx, &args.thisv().toObject());
Rooted<TypedArrayObject*> tarray(cx, &args.thisv().toObject().as<TypedArrayObject>());
if (args.length() < 3) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_ARGS);
@ -2003,7 +1989,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
uint32_t srcEnd;
uint32_t dest;
uint32_t length = TypedArrayObject::length(tarray);
uint32_t length = tarray->length();
if (!ToClampedIndex(cx, args[0], length, &srcBegin) ||
!ToClampedIndex(cx, args[1], length, &srcEnd) ||
!ToClampedIndex(cx, args[2], length, &dest) ||
@ -2037,7 +2023,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
JS_ASSERT(byteSrc + byteSize >= byteSrc);
#endif
uint8_t *data = static_cast<uint8_t*>(viewData(tarray));
uint8_t *data = static_cast<uint8_t*>(tarray->viewData());
memmove(&data[byteDest], &data[byteSrc], byteSize);
args.rval().setUndefined();
return true;
@ -2056,7 +2042,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
fun_set_impl(JSContext *cx, CallArgs args)
{
JS_ASSERT(IsThisClass(args.thisv()));
RootedObject tarray(cx, &args.thisv().toObject());
Rooted<TypedArrayObject*> tarray(cx, &args.thisv().toObject().as<TypedArrayObject>());
// first arg must be either a typed array or a JS array
if (args.length() == 0 || !args[0].isObject()) {
@ -2069,7 +2055,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
if (!ToInt32(cx, args[1], &offset))
return false;
if (offset < 0 || uint32_t(offset) > length(tarray)) {
if (offset < 0 || uint32_t(offset) > tarray->length()) {
// the given offset is bogus
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_TYPED_ARRAY_BAD_INDEX, "2");
return false;
@ -2083,7 +2069,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
RootedObject arg0(cx, args[0].toObjectOrNull());
if (arg0->isTypedArray()) {
if (length(arg0) > length(tarray) - offset) {
if (arg0->as<TypedArrayObject>().length() > tarray->length() - offset) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
return false;
}
@ -2096,7 +2082,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
return false;
// avoid overflow; we know that offset <= length
if (len > length(tarray) - offset) {
if (len > tarray->length() - offset) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_ARRAY_LENGTH);
return false;
}
@ -2232,7 +2218,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
{
uint32_t len;
if (other->isTypedArray()) {
len = length(other);
len = other->as<TypedArrayObject>().length();
} else if (!GetLengthProperty(cx, other, &len)) {
return NULL;
}
@ -2250,26 +2236,26 @@ class TypedArrayObjectTemplate : public TypedArrayObject
static const NativeType
getIndex(JSObject *obj, uint32_t index)
{
return *(static_cast<const NativeType*>(viewData(obj)) + index);
return *(static_cast<const NativeType*>(obj->as<TypedArrayObject>().viewData()) + index);
}
static void
setIndex(JSObject *obj, uint32_t index, NativeType val)
{
*(static_cast<NativeType*>(viewData(obj)) + index) = val;
*(static_cast<NativeType*>(obj->as<TypedArrayObject>().viewData()) + index) = val;
}
static void copyIndexToValue(JSObject *tarray, uint32_t index, MutableHandleValue vp);
static JSObject *
createSubarray(JSContext *cx, HandleObject tarray, uint32_t begin, uint32_t end)
createSubarray(JSContext *cx, HandleObject tarrayArg, uint32_t begin, uint32_t end)
{
JS_ASSERT(tarray);
Rooted<TypedArrayObject*> tarray(cx, &tarrayArg->as<TypedArrayObject>());
JS_ASSERT(begin <= length(tarray));
JS_ASSERT(end <= length(tarray));
JS_ASSERT(begin <= tarray->length());
JS_ASSERT(end <= tarray->length());
RootedObject bufobj(cx, buffer(tarray));
RootedObject bufobj(cx, tarray->buffer());
JS_ASSERT(bufobj);
JS_ASSERT(begin <= end);
@ -2333,14 +2319,14 @@ class TypedArrayObjectTemplate : public TypedArrayObject
copyFromArray(JSContext *cx, HandleObject thisTypedArrayObj,
HandleObject ar, uint32_t len, uint32_t offset = 0)
{
JS_ASSERT(thisTypedArrayObj->isTypedArray());
JS_ASSERT(offset <= length(thisTypedArrayObj));
JS_ASSERT(len <= length(thisTypedArrayObj) - offset);
Rooted<TypedArrayObject*> thisTypedArray(cx, &thisTypedArrayObj->as<TypedArrayObject>());
JS_ASSERT(offset <= thisTypedArray->length());
JS_ASSERT(len <= thisTypedArray->length() - offset);
if (ar->isTypedArray())
return copyFromTypedArray(cx, thisTypedArrayObj, ar, offset);
return copyFromTypedArray(cx, thisTypedArray, ar, offset);
const Value *src = NULL;
NativeType *dest = static_cast<NativeType*>(viewData(thisTypedArrayObj)) + offset;
NativeType *dest = static_cast<NativeType*>(thisTypedArray->viewData()) + offset;
// The only way the code below can GC is if nativeFromValue fails, but
// in that case we return false immediately, so we do not need to root
@ -2376,68 +2362,70 @@ class TypedArrayObjectTemplate : public TypedArrayObject
}
static bool
copyFromTypedArray(JSContext *cx, JSObject *thisTypedArrayObj, JSObject *tarray, uint32_t offset)
copyFromTypedArray(JSContext *cx, JSObject *thisTypedArrayObj, JSObject *tarrayObj,
uint32_t offset)
{
JS_ASSERT(thisTypedArrayObj->isTypedArray());
JS_ASSERT(offset <= length(thisTypedArrayObj));
JS_ASSERT(length(tarray) <= length(thisTypedArrayObj) - offset);
if (buffer(tarray) == buffer(thisTypedArrayObj))
return copyFromWithOverlap(cx, thisTypedArrayObj, tarray, offset);
TypedArrayObject *thisTypedArray = &thisTypedArrayObj->as<TypedArrayObject>();
TypedArrayObject *tarray = &tarrayObj->as<TypedArrayObject>();
JS_ASSERT(offset <= thisTypedArray->length());
JS_ASSERT(tarray->length() <= thisTypedArray->length() - offset);
if (tarray->buffer() == thisTypedArray->buffer())
return copyFromWithOverlap(cx, thisTypedArray, tarray, offset);
NativeType *dest = static_cast<NativeType*>(viewData(thisTypedArrayObj)) + offset;
NativeType *dest = static_cast<NativeType*>(thisTypedArray->viewData()) + offset;
if (type(tarray) == type(thisTypedArrayObj)) {
js_memcpy(dest, viewData(tarray), byteLengthValue(tarray).toInt32());
if (tarray->type() == thisTypedArray->type()) {
js_memcpy(dest, tarray->viewData(), byteLengthValue(tarray).toInt32());
return true;
}
unsigned srclen = length(tarray);
switch (type(tarray)) {
unsigned srclen = tarray->length();
switch (tarray->type()) {
case TypedArrayObject::TYPE_INT8: {
int8_t *src = static_cast<int8_t*>(viewData(tarray));
int8_t *src = static_cast<int8_t*>(tarray->viewData());
for (unsigned i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_UINT8:
case TypedArrayObject::TYPE_UINT8_CLAMPED: {
uint8_t *src = static_cast<uint8_t*>(viewData(tarray));
uint8_t *src = static_cast<uint8_t*>(tarray->viewData());
for (unsigned i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_INT16: {
int16_t *src = static_cast<int16_t*>(viewData(tarray));
int16_t *src = static_cast<int16_t*>(tarray->viewData());
for (unsigned i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_UINT16: {
uint16_t *src = static_cast<uint16_t*>(viewData(tarray));
uint16_t *src = static_cast<uint16_t*>(tarray->viewData());
for (unsigned i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_INT32: {
int32_t *src = static_cast<int32_t*>(viewData(tarray));
int32_t *src = static_cast<int32_t*>(tarray->viewData());
for (unsigned i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_UINT32: {
uint32_t *src = static_cast<uint32_t*>(viewData(tarray));
uint32_t *src = static_cast<uint32_t*>(tarray->viewData());
for (unsigned i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_FLOAT32: {
float *src = static_cast<float*>(viewData(tarray));
float *src = static_cast<float*>(tarray->viewData());
for (unsigned i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_FLOAT64: {
double *src = static_cast<double*>(viewData(tarray));
double *src = static_cast<double*>(tarray->viewData());
for (unsigned i = 0; i < srclen; ++i)
*dest++ = NativeType(*src++);
break;
@ -2450,15 +2438,18 @@ class TypedArrayObjectTemplate : public TypedArrayObject
}
static bool
copyFromWithOverlap(JSContext *cx, JSObject *self, JSObject *tarray, uint32_t offset)
copyFromWithOverlap(JSContext *cx, JSObject *selfObj, JSObject *tarrayObj, uint32_t offset)
{
JS_ASSERT(offset <= length(self));
TypedArrayObject *self = &selfObj->as<TypedArrayObject>();
TypedArrayObject *tarray = &tarrayObj->as<TypedArrayObject>();
NativeType *dest = static_cast<NativeType*>(viewData(self)) + offset;
JS_ASSERT(offset <= self->length());
NativeType *dest = static_cast<NativeType*>(self->viewData()) + offset;
uint32_t byteLength = byteLengthValue(tarray).toInt32();
if (type(tarray) == type(self)) {
memmove(dest, viewData(tarray), byteLength);
if (tarray->type() == self->type()) {
memmove(dest, tarray->viewData(), byteLength);
return true;
}
@ -2467,55 +2458,55 @@ class TypedArrayObjectTemplate : public TypedArrayObject
void *srcbuf = cx->malloc_(byteLength);
if (!srcbuf)
return false;
js_memcpy(srcbuf, viewData(tarray), byteLength);
js_memcpy(srcbuf, tarray->viewData(), byteLength);
switch (type(tarray)) {
switch (tarray->type()) {
case TypedArrayObject::TYPE_INT8: {
int8_t *src = (int8_t*) srcbuf;
for (unsigned i = 0; i < length(tarray); ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_UINT8:
case TypedArrayObject::TYPE_UINT8_CLAMPED: {
uint8_t *src = (uint8_t*) srcbuf;
for (unsigned i = 0; i < length(tarray); ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_INT16: {
int16_t *src = (int16_t*) srcbuf;
for (unsigned i = 0; i < length(tarray); ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_UINT16: {
uint16_t *src = (uint16_t*) srcbuf;
for (unsigned i = 0; i < length(tarray); ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_INT32: {
int32_t *src = (int32_t*) srcbuf;
for (unsigned i = 0; i < length(tarray); ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_UINT32: {
uint32_t *src = (uint32_t*) srcbuf;
for (unsigned i = 0; i < length(tarray); ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_FLOAT32: {
float *src = (float*) srcbuf;
for (unsigned i = 0; i < length(tarray); ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
case TypedArrayObject::TYPE_FLOAT64: {
double *src = (double*) srcbuf;
for (unsigned i = 0; i < length(tarray); ++i)
for (unsigned i = 0; i < tarray->length(); ++i)
*dest++ = NativeType(*src++);
break;
}
@ -2651,6 +2642,15 @@ ArrayBufferViewObject::prependToViews(HeapPtr<ArrayBufferViewObject> *views)
WeakObjectSlotBarrierPost(this, NEXT_BUFFER_SLOT, "view.nextbuffer");
}
void
ArrayBufferViewObject::neuter()
{
if (is<DataViewObject>())
as<DataViewObject>().neuter();
else
as<TypedArrayObject>().neuter();
}
// this default implementation is only valid for integer types
// less than 32-bits in size.
template<typename NativeType>
@ -3521,8 +3521,9 @@ IMPL_TYPED_ARRAY_JSAPI_CONSTRUCTORS(Float64, double)
if (clasp != &TypedArrayObject::classes[TypedArrayObjectTemplate<InternalType>::ArrayTypeID()]) \
return NULL; \
\
*length = TypedArrayObject::length(obj); \
*data = static_cast<ExternalType *>(TypedArrayObject::viewData(obj)); \
TypedArrayObject *tarr = &obj->as<TypedArrayObject>(); \
*length = tarr->length(); \
*data = static_cast<ExternalType *>(tarr->viewData()); \
\
return obj; \
}
@ -3893,6 +3894,14 @@ DataViewObject::initClass(JSContext *cx)
return proto;
}
void
DataViewObject::neuter()
{
setSlot(BYTELENGTH_SLOT, Int32Value(0));
setSlot(BYTEOFFSET_SLOT, Int32Value(0));
setPrivate(NULL);
}
JSObject *
js_InitTypedArrayClasses(JSContext *cx, HandleObject obj)
{
@ -4068,8 +4077,7 @@ JS_GetTypedArrayLength(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return 0;
JS_ASSERT(obj->isTypedArray());
return TypedArrayObject::length(obj);
return obj->as<TypedArrayObject>().length();
}
JS_FRIEND_API(uint32_t)
@ -4078,8 +4086,7 @@ JS_GetTypedArrayByteOffset(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return 0;
JS_ASSERT(obj->isTypedArray());
return TypedArrayObject::byteOffset(obj);
return obj->as<TypedArrayObject>().byteOffset();
}
JS_FRIEND_API(uint32_t)
@ -4088,8 +4095,7 @@ JS_GetTypedArrayByteLength(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return 0;
JS_ASSERT(obj->isTypedArray());
return TypedArrayObject::byteLength(obj);
return obj->as<TypedArrayObject>().byteLength();
}
JS_FRIEND_API(JSArrayBufferViewType)
@ -4100,7 +4106,7 @@ JS_GetArrayBufferViewType(JSObject *obj)
return ArrayBufferView::TYPE_MAX;
if (obj->isTypedArray())
return static_cast<JSArrayBufferViewType>(TypedArrayObject::type(obj));
return static_cast<JSArrayBufferViewType>(obj->as<TypedArrayObject>().type());
else if (obj->is<DataViewObject>())
return ArrayBufferView::TYPE_DATAVIEW;
MOZ_ASSUME_UNREACHABLE("invalid ArrayBufferView type");
@ -4112,9 +4118,9 @@ JS_GetInt8ArrayData(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(TypedArrayObject::type(obj) == ArrayBufferView::TYPE_INT8);
return static_cast<int8_t *>(TypedArrayObject::viewData(obj));
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_INT8);
return static_cast<int8_t *>(tarr->viewData());
}
JS_FRIEND_API(uint8_t *)
@ -4123,9 +4129,9 @@ JS_GetUint8ArrayData(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(TypedArrayObject::type(obj) == ArrayBufferView::TYPE_UINT8);
return static_cast<uint8_t *>(TypedArrayObject::viewData(obj));
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_UINT8);
return static_cast<uint8_t *>(tarr->viewData());
}
JS_FRIEND_API(uint8_t *)
@ -4134,9 +4140,9 @@ JS_GetUint8ClampedArrayData(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(TypedArrayObject::type(obj) == ArrayBufferView::TYPE_UINT8_CLAMPED);
return static_cast<uint8_t *>(TypedArrayObject::viewData(obj));
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_UINT8_CLAMPED);
return static_cast<uint8_t *>(tarr->viewData());
}
JS_FRIEND_API(int16_t *)
@ -4145,9 +4151,9 @@ JS_GetInt16ArrayData(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(TypedArrayObject::type(obj) == ArrayBufferView::TYPE_INT16);
return static_cast<int16_t *>(TypedArrayObject::viewData(obj));
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_INT16);
return static_cast<int16_t *>(tarr->viewData());
}
JS_FRIEND_API(uint16_t *)
@ -4156,9 +4162,9 @@ JS_GetUint16ArrayData(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(TypedArrayObject::type(obj) == ArrayBufferView::TYPE_UINT16);
return static_cast<uint16_t *>(TypedArrayObject::viewData(obj));
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_UINT16);
return static_cast<uint16_t *>(tarr->viewData());
}
JS_FRIEND_API(int32_t *)
@ -4167,9 +4173,9 @@ JS_GetInt32ArrayData(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(TypedArrayObject::type(obj) == ArrayBufferView::TYPE_INT32);
return static_cast<int32_t *>(TypedArrayObject::viewData(obj));
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_INT32);
return static_cast<int32_t *>(tarr->viewData());
}
JS_FRIEND_API(uint32_t *)
@ -4178,9 +4184,9 @@ JS_GetUint32ArrayData(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(TypedArrayObject::type(obj) == ArrayBufferView::TYPE_UINT32);
return static_cast<uint32_t *>(TypedArrayObject::viewData(obj));
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_UINT32);
return static_cast<uint32_t *>(tarr->viewData());
}
JS_FRIEND_API(float *)
@ -4189,9 +4195,9 @@ JS_GetFloat32ArrayData(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(TypedArrayObject::type(obj) == ArrayBufferView::TYPE_FLOAT32);
return static_cast<float *>(TypedArrayObject::viewData(obj));
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_FLOAT32);
return static_cast<float *>(tarr->viewData());
}
JS_FRIEND_API(double *)
@ -4200,9 +4206,9 @@ JS_GetFloat64ArrayData(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return NULL;
JS_ASSERT(obj->isTypedArray());
JS_ASSERT(TypedArrayObject::type(obj) == ArrayBufferView::TYPE_FLOAT64);
return static_cast<double *>(TypedArrayObject::viewData(obj));
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT(tarr->type() == ArrayBufferView::TYPE_FLOAT64);
return static_cast<double *>(tarr->viewData());
}
JS_FRIEND_API(JSBool)
@ -4246,7 +4252,7 @@ JS_GetArrayBufferViewData(JSObject *obj)
if (!obj)
return NULL;
return obj->is<DataViewObject>() ? obj->as<DataViewObject>().dataPointer()
: TypedArrayObject::viewData(obj);
: obj->as<TypedArrayObject>().viewData();
}
JS_FRIEND_API(JSObject *)
@ -4264,10 +4270,9 @@ JS_GetArrayBufferViewByteLength(JSObject *obj)
obj = CheckedUnwrap(obj);
if (!obj)
return 0;
JS_ASSERT(obj->is<ArrayBufferViewObject>());
return obj->is<DataViewObject>()
? obj->as<DataViewObject>().byteLength()
: TypedArrayObject::byteLengthValue(obj).toInt32();
: TypedArrayObject::byteLengthValue(&obj->as<TypedArrayObject>()).toInt32();
}
JS_FRIEND_API(JSObject *)
@ -4278,12 +4283,13 @@ JS_GetObjectAsArrayBufferView(JSObject *obj, uint32_t *length, uint8_t **data)
if (!(obj->is<ArrayBufferViewObject>()))
return NULL;
*length = obj->is<DataViewObject>() ? obj->as<DataViewObject>().byteLength()
: TypedArrayObject::byteLengthValue(obj).toInt32();
*length = obj->is<DataViewObject>()
? obj->as<DataViewObject>().byteLength()
: TypedArrayObject::byteLengthValue(&obj->as<TypedArrayObject>()).toInt32();
*data = static_cast<uint8_t *>(obj->is<DataViewObject>()
? obj->as<DataViewObject>().dataPointer()
: TypedArrayObject::viewData(obj));
*data = static_cast<uint8_t*>(obj->is<DataViewObject>()
? obj->as<DataViewObject>().dataPointer()
: obj->as<TypedArrayObject>().viewData());
return obj;
}

View File

@ -257,6 +257,8 @@ class ArrayBufferViewObject : public JSObject
void prependToViews(HeapPtr<ArrayBufferViewObject> *views);
void neuter();
static void trace(JSTracer *trc, JSObject *obj);
};
@ -270,6 +272,14 @@ class ArrayBufferViewObject : public JSObject
class TypedArrayObject : public ArrayBufferViewObject
{
protected:
// Typed array properties stored in slots, beyond those shared by all
// ArrayBufferViews.
static const size_t LENGTH_SLOT = ArrayBufferViewObject::NUM_SLOTS;
static const size_t TYPE_SLOT = ArrayBufferViewObject::NUM_SLOTS + 1;
static const size_t RESERVED_SLOTS = ArrayBufferViewObject::NUM_SLOTS + 2;
static const size_t DATA_SLOT = 7; // private slot, based on alloc kind
public:
enum {
TYPE_INT8 = 0,
@ -290,15 +300,6 @@ class TypedArrayObject : public ArrayBufferViewObject
TYPE_MAX
};
/*
* Typed array properties stored in slots, beyond those shared by all
* ArrayBufferViews.
*/
static const size_t LENGTH_SLOT = ArrayBufferViewObject::NUM_SLOTS;
static const size_t TYPE_SLOT = ArrayBufferViewObject::NUM_SLOTS + 1;
static const size_t RESERVED_SLOTS = ArrayBufferViewObject::NUM_SLOTS + 2;
static const size_t DATA_SLOT = 7; // private slot, based on alloc kind
static Class classes[TYPE_MAX];
static Class protoClasses[TYPE_MAX];
@ -329,26 +330,66 @@ class TypedArrayObject : public ArrayBufferViewObject
static JSBool obj_setSpecialAttributes(JSContext *cx, HandleObject obj,
HandleSpecialId sid, unsigned *attrsp);
static inline Value bufferValue(JSObject *obj);
static inline Value byteOffsetValue(JSObject *obj);
static inline Value byteLengthValue(JSObject *obj);
static inline Value lengthValue(JSObject *obj);
static Value bufferValue(TypedArrayObject *tarr) {
return tarr->getFixedSlot(BUFFER_SLOT);
}
static Value byteOffsetValue(TypedArrayObject *tarr) {
return tarr->getFixedSlot(BYTEOFFSET_SLOT);
}
static Value byteLengthValue(TypedArrayObject *tarr) {
return tarr->getFixedSlot(BYTELENGTH_SLOT);
}
static Value lengthValue(TypedArrayObject *tarr) {
return tarr->getFixedSlot(LENGTH_SLOT);
}
static inline ArrayBufferObject * buffer(JSObject *obj);
static inline uint32_t byteOffset(JSObject *obj);
static inline uint32_t byteLength(JSObject *obj);
static inline uint32_t length(JSObject *obj);
ArrayBufferObject *buffer() const {
return &bufferValue(const_cast<TypedArrayObject*>(this)).toObject().as<ArrayBufferObject>();
}
uint32_t byteOffset() const {
return byteOffsetValue(const_cast<TypedArrayObject*>(this)).toInt32();
}
uint32_t byteLength() const {
return byteLengthValue(const_cast<TypedArrayObject*>(this)).toInt32();
}
uint32_t length() const {
return lengthValue(const_cast<TypedArrayObject*>(this)).toInt32();
}
static inline uint32_t type(JSObject *obj);
static inline void * viewData(JSObject *obj);
uint32_t type() const {
return getFixedSlot(TYPE_SLOT).toInt32();
}
void *viewData() const {
return static_cast<void*>(getPrivate(DATA_SLOT));
}
public:
static bool isArrayIndex(JSObject *obj, jsid id, uint32_t *ip = NULL);
inline bool isArrayIndex(jsid id, uint32_t *ip = NULL);
static void neuter(JSObject *tarray);
void neuter();
static inline uint32_t slotWidth(int atype);
static inline int slotWidth(JSObject *obj);
static uint32_t slotWidth(int atype) {
switch (atype) {
case js::TypedArrayObject::TYPE_INT8:
case js::TypedArrayObject::TYPE_UINT8:
case js::TypedArrayObject::TYPE_UINT8_CLAMPED:
return 1;
case js::TypedArrayObject::TYPE_INT16:
case js::TypedArrayObject::TYPE_UINT16:
return 2;
case js::TypedArrayObject::TYPE_INT32:
case js::TypedArrayObject::TYPE_UINT32:
case js::TypedArrayObject::TYPE_FLOAT32:
return 4;
case js::TypedArrayObject::TYPE_FLOAT64:
return 8;
default:
MOZ_ASSUME_UNREACHABLE("invalid typed array type");
}
}
int slotWidth() {
return slotWidth(type());
}
/*
* Byte length above which created typed arrays and data views will have
@ -531,6 +572,9 @@ class DataViewObject : public ArrayBufferViewObject
template<typename NativeType>
static bool write(JSContext *cx, Handle<DataViewObject*> obj,
CallArgs &args, const char *method);
void neuter();
private:
static const JSFunctionSpec jsfuncs[];
};

View File

@ -26,98 +26,6 @@ ClampIntForUint8Array(int32_t x)
return x;
}
inline Value
TypedArrayObject::lengthValue(JSObject *obj)
{
JS_ASSERT(obj->isTypedArray());
return obj->getFixedSlot(LENGTH_SLOT);
}
inline uint32_t
TypedArrayObject::length(JSObject *obj)
{
return lengthValue(obj).toInt32();
}
inline Value
TypedArrayObject::byteOffsetValue(JSObject *obj)
{
JS_ASSERT(obj->isTypedArray());
return obj->getFixedSlot(BYTEOFFSET_SLOT);
}
inline uint32_t
TypedArrayObject::byteOffset(JSObject *obj)
{
return byteOffsetValue(obj).toInt32();
}
inline Value
TypedArrayObject::byteLengthValue(JSObject *obj)
{
JS_ASSERT(obj->isTypedArray());
return obj->getFixedSlot(BYTELENGTH_SLOT);
}
inline uint32_t
TypedArrayObject::byteLength(JSObject *obj)
{
return byteLengthValue(obj).toInt32();
}
inline uint32_t
TypedArrayObject::type(JSObject *obj)
{
JS_ASSERT(obj->isTypedArray());
return obj->getFixedSlot(TYPE_SLOT).toInt32();
}
inline Value
TypedArrayObject::bufferValue(JSObject *obj)
{
JS_ASSERT(obj->isTypedArray());
return obj->getFixedSlot(BUFFER_SLOT);
}
inline ArrayBufferObject *
TypedArrayObject::buffer(JSObject *obj)
{
return &bufferValue(obj).toObject().as<ArrayBufferObject>();
}
inline void *
TypedArrayObject::viewData(JSObject *obj)
{
JS_ASSERT(obj->isTypedArray());
return (void *)obj->getPrivate(DATA_SLOT);
}
inline uint32_t
TypedArrayObject::slotWidth(int atype) {
switch (atype) {
case js::TypedArrayObject::TYPE_INT8:
case js::TypedArrayObject::TYPE_UINT8:
case js::TypedArrayObject::TYPE_UINT8_CLAMPED:
return 1;
case js::TypedArrayObject::TYPE_INT16:
case js::TypedArrayObject::TYPE_UINT16:
return 2;
case js::TypedArrayObject::TYPE_INT32:
case js::TypedArrayObject::TYPE_UINT32:
case js::TypedArrayObject::TYPE_FLOAT32:
return 4;
case js::TypedArrayObject::TYPE_FLOAT64:
return 8;
default:
MOZ_ASSUME_UNREACHABLE("invalid typed array type");
}
}
inline int
TypedArrayObject::slotWidth(JSObject *obj) {
return slotWidth(type(obj));
}
#ifdef JSGC_GENERATIONAL
class ArrayBufferViewByteOffsetRef : public gc::BufferableRef
{

View File

@ -1156,7 +1156,7 @@ FileAsTypedArray(JSContext *cx, const char *pathname)
obj = JS_NewUint8Array(cx, len);
if (!obj)
return NULL;
char *buf = (char *) TypedArrayObject::viewData(obj);
char *buf = (char *) obj->as<TypedArrayObject>().viewData();
size_t cc = fread(buf, 1, len, file);
if (cc != len) {
JS_ReportError(cx, "can't read %s: %s", pathname,
@ -3438,16 +3438,17 @@ Serialize(JSContext *cx, unsigned argc, jsval *vp)
if (!JS_WriteStructuredClone(cx, v, &datap, &nbytes, NULL, NULL, UndefinedValue()))
return false;
JSObject *array = JS_NewUint8Array(cx, nbytes);
if (!array) {
JSObject *obj = JS_NewUint8Array(cx, nbytes);
if (!obj) {
JS_free(cx, datap);
return false;
}
JS_ASSERT((uintptr_t(TypedArrayObject::viewData(array)) & 7) == 0);
js_memcpy(TypedArrayObject::viewData(array), datap, nbytes);
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
JS_ASSERT((uintptr_t(tarr->viewData()) & 7) == 0);
js_memcpy(tarr->viewData(), datap, nbytes);
JS_ClearStructuredClone(datap, nbytes);
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(array));
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(tarr));
return true;
}
@ -3460,16 +3461,17 @@ Deserialize(JSContext *cx, unsigned argc, jsval *vp)
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize");
return false;
}
if ((TypedArrayObject::byteLength(obj) & 7) != 0) {
TypedArrayObject *tarr = &obj->as<TypedArrayObject>();
if ((tarr->byteLength() & 7) != 0) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "deserialize");
return false;
}
if ((uintptr_t(TypedArrayObject::viewData(obj)) & 7) != 0) {
if ((uintptr_t(tarr->viewData()) & 7) != 0) {
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_BAD_ALIGNMENT);
return false;
}
if (!JS_ReadStructuredClone(cx, (uint64_t *) TypedArrayObject::viewData(obj), TypedArrayObject::byteLength(obj),
if (!JS_ReadStructuredClone(cx, (uint64_t *) tarr->viewData(), tarr->byteLength(),
JS_STRUCTURED_CLONE_VERSION, v.address(), NULL, NULL)) {
return false;
}

View File

@ -216,7 +216,7 @@ GetLengthProperty(const Value &lval, MutableHandleValue vp)
}
if (obj->isTypedArray()) {
vp.setInt32(TypedArrayObject::length(obj));
vp.setInt32(obj->as<TypedArrayObject>().length());
return true;
}
}

View File

@ -453,7 +453,7 @@ js::intrinsic_UnsafeSetElement(JSContext *cx, unsigned argc, Value *vp)
JS_ASSERT(idx < arrobj->getDenseInitializedLength());
JSObject::setDenseElementWithType(cx, arrobj, idx, args[elemi]);
} else {
JS_ASSERT(idx < TypedArrayObject::length(arrobj));
JS_ASSERT(idx < arrobj->as<TypedArrayObject>().length());
RootedValue tmp(cx, args[elemi]);
// XXX: Always non-strict.
if (!JSObject::setElement(cx, arrobj, arrobj, idx, &tmp, false))