mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 23:02:20 +00:00
Bug 1722674 - Use a reserved slot instead of a private slot for TypedArray and DataView objects. r=jonco
Differential Revision: https://phabricator.services.mozilla.com/D121068
This commit is contained in:
parent
d64a25c382
commit
25c3d08eef
@ -20,7 +20,7 @@
|
||||
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
#include "js/Object.h" // JS::GetClass, JS::GetPrivate, JS::GetReservedSlot
|
||||
#include "js/Object.h" // JS::GetClass, JS::GetReservedSlot, JS::GetMaybePtrFromReservedSlot
|
||||
#include "js/RootingAPI.h" // JS::Handle
|
||||
#include "js/ScalarType.h" // js::Scalar::Type
|
||||
|
||||
@ -204,19 +204,21 @@ extern JS_PUBLIC_DATA const JSClass* const BigUint64ArrayClassPtr;
|
||||
extern JS_PUBLIC_DATA const JSClass* const Float32ArrayClassPtr;
|
||||
extern JS_PUBLIC_DATA const JSClass* const Float64ArrayClassPtr;
|
||||
|
||||
const size_t TypedArrayLengthSlot = 1;
|
||||
constexpr size_t TypedArrayLengthSlot = 1;
|
||||
constexpr size_t TypedArrayDataSlot = 3;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
|
||||
inline void Get##Type##ArrayLengthAndData( \
|
||||
JSObject* obj, size_t* length, bool* isSharedMemory, type** data) { \
|
||||
MOZ_ASSERT(JS::GetClass(obj) == detail::Type##ArrayClassPtr); \
|
||||
const JS::Value& lenSlot = \
|
||||
JS::GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
|
||||
*length = size_t(lenSlot.toPrivate()); \
|
||||
*isSharedMemory = JS_GetTypedArraySharedness(obj); \
|
||||
*data = static_cast<type*>(JS::GetPrivate(obj)); \
|
||||
#define JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Type, type) \
|
||||
inline void Get##Type##ArrayLengthAndData( \
|
||||
JSObject* obj, size_t* length, bool* isSharedMemory, type** data) { \
|
||||
MOZ_ASSERT(JS::GetClass(obj) == detail::Type##ArrayClassPtr); \
|
||||
const JS::Value& lenSlot = \
|
||||
JS::GetReservedSlot(obj, detail::TypedArrayLengthSlot); \
|
||||
*length = size_t(lenSlot.toPrivate()); \
|
||||
*isSharedMemory = JS_GetTypedArraySharedness(obj); \
|
||||
*data = JS::GetMaybePtrFromReservedSlot<type>(obj, \
|
||||
detail::TypedArrayDataSlot); \
|
||||
}
|
||||
|
||||
JS_DEFINE_DATA_AND_LENGTH_ACCESSOR(Int8, int8_t)
|
||||
|
@ -962,8 +962,7 @@ const ClassSpec DataViewObject::classSpec_ = {
|
||||
|
||||
const JSClass DataViewObject::class_ = {
|
||||
"DataView",
|
||||
JSCLASS_HAS_PRIVATE |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(DataViewObject::RESERVED_SLOTS) |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(DataViewObject::RESERVED_SLOTS) |
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_DataView),
|
||||
&DataViewObjectClassOps, &DataViewObject::classSpec_};
|
||||
|
||||
|
@ -767,24 +767,11 @@ static void FindStartOfUninitializedAndUndefinedSlots(
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Src>
|
||||
inline void MacroAssembler::storeObjPrivate(Src ptr, const Address& address) {
|
||||
// The private pointer is stored as a PrivateValue in a JS::Value, so on 32
|
||||
// bit systems we also need to zero the top word.
|
||||
#ifdef JS_PUNBOX64
|
||||
storePtr(ptr, address);
|
||||
#else
|
||||
storePtr(ptr, LowWord(address));
|
||||
store32(Imm32(0), HighWord(address));
|
||||
#endif
|
||||
}
|
||||
|
||||
void MacroAssembler::initTypedArraySlots(Register obj, Register temp,
|
||||
Register lengthReg,
|
||||
LiveRegisterSet liveRegs, Label* fail,
|
||||
TypedArrayObject* templateObj,
|
||||
TypedArrayLength lengthKind) {
|
||||
MOZ_ASSERT(templateObj->hasPrivate());
|
||||
MOZ_ASSERT(!templateObj->hasBuffer());
|
||||
|
||||
constexpr size_t dataSlotOffset = ArrayBufferViewObject::dataOffset();
|
||||
@ -811,7 +798,7 @@ void MacroAssembler::initTypedArraySlots(Register obj, Register temp,
|
||||
|
||||
// Store data elements inside the remaining JSObject slots.
|
||||
computeEffectiveAddress(Address(obj, dataOffset), temp);
|
||||
storeObjPrivate(temp, Address(obj, dataSlotOffset));
|
||||
storePrivateValue(temp, Address(obj, dataSlotOffset));
|
||||
|
||||
// Write enough zero pointers into fixed data to zero every
|
||||
// element. (This zeroes past the end of a byte count that's
|
||||
@ -845,8 +832,8 @@ void MacroAssembler::initTypedArraySlots(Register obj, Register temp,
|
||||
callWithABI<Fn, AllocateAndInitTypedArrayBuffer>();
|
||||
PopRegsInMask(liveRegs);
|
||||
|
||||
// Fail when data elements is set to NULL.
|
||||
branchPtr(Assembler::Equal, Address(obj, dataSlotOffset), ImmWord(0), fail);
|
||||
// Fail when data slot is UndefinedValue.
|
||||
branchTestUndefined(Assembler::Equal, Address(obj, dataSlotOffset), fail);
|
||||
}
|
||||
}
|
||||
|
||||
@ -936,6 +923,7 @@ void MacroAssembler::initGCThing(Register obj, Register temp,
|
||||
const TemplateNativeObject& ntemplate =
|
||||
templateObj.asTemplateNativeObject();
|
||||
MOZ_ASSERT(!ntemplate.hasDynamicElements());
|
||||
MOZ_ASSERT(!ntemplate.hasPrivate());
|
||||
|
||||
// If the object has dynamic slots, the slots member has already been
|
||||
// filled in.
|
||||
@ -977,12 +965,6 @@ void MacroAssembler::initGCThing(Register obj, Register temp,
|
||||
Address(obj, NativeObject::offsetOfElements()));
|
||||
|
||||
initGCSlots(obj, temp, ntemplate, initContents);
|
||||
|
||||
if (ntemplate.hasPrivate() && !ntemplate.isTypedArrayObject()) {
|
||||
uint32_t nfixed = ntemplate.numFixedSlots();
|
||||
Address privateSlot(obj, NativeObject::getPrivateDataOffset(nfixed));
|
||||
storeObjPrivate(ImmPtr(ntemplate.getPrivate()), privateSlot);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MOZ_CRASH("Unknown object");
|
||||
|
@ -4274,9 +4274,6 @@ class MacroAssembler : public MacroAssemblerSpecific {
|
||||
inline void storeObjShape(Shape* shape, Register obj,
|
||||
EmitPreBarrier emitPreBarrier);
|
||||
|
||||
template <typename T>
|
||||
void storeObjPrivate(T src, const Address& address);
|
||||
|
||||
void loadObjProto(Register obj, Register dest) {
|
||||
loadPtr(Address(obj, JSObject::offsetOfShape()), dest);
|
||||
loadPtr(Address(dest, Shape::offsetOfBaseShape()), dest);
|
||||
|
@ -119,10 +119,6 @@ inline gc::Cell* TemplateNativeObject::regExpShared() const {
|
||||
return regexp->getShared();
|
||||
}
|
||||
|
||||
inline void* TemplateNativeObject::getPrivate() const {
|
||||
return asNativeObject().getPrivate();
|
||||
}
|
||||
|
||||
} // namespace jit
|
||||
} // namespace js
|
||||
|
||||
|
@ -67,10 +67,8 @@ class TemplateNativeObject : public TemplateObject {
|
||||
inline bool hasDynamicElements() const;
|
||||
inline const Value* getDenseElements() const;
|
||||
|
||||
// Reading private slots is safe.
|
||||
inline bool hasPrivate() const;
|
||||
inline gc::Cell* regExpShared() const;
|
||||
inline void* getPrivate() const;
|
||||
};
|
||||
|
||||
} // namespace jit
|
||||
|
@ -2250,7 +2250,9 @@ void AllocateAndInitTypedArrayBuffer(JSContext* cx, TypedArrayObject* obj,
|
||||
int32_t count) {
|
||||
AutoUnsafeCallWithABI unsafe;
|
||||
|
||||
obj->initPrivate(nullptr);
|
||||
// Initialize the data slot to UndefinedValue to signal to our JIT caller that
|
||||
// the allocation failed if the slot isn't overwritten below.
|
||||
obj->initFixedSlot(TypedArrayObject::DATA_SLOT, UndefinedValue());
|
||||
|
||||
// Negative numbers or zero will bail out to the slow path, which in turn will
|
||||
// raise an invalid argument exception or create a correct object with zero
|
||||
@ -2270,7 +2272,8 @@ void AllocateAndInitTypedArrayBuffer(JSContext* cx, TypedArrayObject* obj,
|
||||
void* buf = cx->nursery().allocateZeroedBuffer(obj, nbytes,
|
||||
js::ArrayBufferContentsArena);
|
||||
if (buf) {
|
||||
InitObjectPrivate(obj, buf, nbytes, MemoryUse::TypedArrayElements);
|
||||
InitReservedSlot(obj, TypedArrayObject::DATA_SLOT, buf, nbytes,
|
||||
MemoryUse::TypedArrayElements);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1093,6 +1093,11 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM {
|
||||
store32(temp, ToPayload(dest));
|
||||
}
|
||||
|
||||
void storePrivateValue(Register src, const Address& dest) {
|
||||
store32(Imm32(0), ToType(dest));
|
||||
store32(src, ToPayload(dest));
|
||||
}
|
||||
|
||||
void loadValue(Address src, ValueOperand val);
|
||||
void loadValue(Operand dest, ValueOperand val) {
|
||||
loadValue(dest.toAddress(), val);
|
||||
|
@ -322,6 +322,10 @@ class MacroAssemblerCompat : public vixl::MacroAssembler {
|
||||
storePtr(temp, dest);
|
||||
}
|
||||
|
||||
void storePrivateValue(Register src, const Address& dest) {
|
||||
storePtr(src, dest);
|
||||
}
|
||||
|
||||
void loadValue(Address src, Register val) {
|
||||
Ldr(ARMRegister(val, 64), MemOperand(src));
|
||||
}
|
||||
|
@ -289,6 +289,10 @@ class MacroAssemblerNone : public Assembler {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
template <typename T, typename S>
|
||||
void storePrivateValue(const T&, const S&) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
template <typename T, typename S>
|
||||
void loadValue(T, S) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
@ -171,6 +171,9 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared {
|
||||
loadPtr(src, temp);
|
||||
storePtr(temp, dest);
|
||||
}
|
||||
void storePrivateValue(Register src, const Address& dest) {
|
||||
storePtr(src, dest);
|
||||
}
|
||||
void loadValue(Operand src, ValueOperand val) { movq(src, val.valueReg()); }
|
||||
void loadValue(Address src, ValueOperand val) {
|
||||
loadValue(Operand(src), val);
|
||||
|
@ -180,6 +180,10 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared {
|
||||
load32(ToPayload(src), temp);
|
||||
store32(temp, ToPayload(dest));
|
||||
}
|
||||
void storePrivateValue(Register src, const Address& dest) {
|
||||
store32(Imm32(0), ToType(dest));
|
||||
store32(src, ToPayload(dest));
|
||||
}
|
||||
void loadValue(Operand src, ValueOperand val) {
|
||||
Operand payload = ToPayload(src);
|
||||
Operand type = ToType(src);
|
||||
|
@ -31,20 +31,19 @@ void ArrayBufferViewObject::trace(JSTracer* trc, JSObject* objArg) {
|
||||
TraceEdge(trc, &bufSlot, "ArrayBufferViewObject.buffer");
|
||||
|
||||
// Update obj's data pointer if it moved.
|
||||
if (bufSlot.isObject()) {
|
||||
if (gc::MaybeForwardedObjectIs<ArrayBufferObject>(&bufSlot.toObject())) {
|
||||
ArrayBufferObject& buf =
|
||||
gc::MaybeForwardedObjectAs<ArrayBufferObject>(&bufSlot.toObject());
|
||||
size_t offset = obj->byteOffset();
|
||||
if (bufSlot.isObject() &&
|
||||
gc::MaybeForwardedObjectIs<ArrayBufferObject>(&bufSlot.toObject())) {
|
||||
ArrayBufferObject& buf =
|
||||
gc::MaybeForwardedObjectAs<ArrayBufferObject>(&bufSlot.toObject());
|
||||
size_t offset = obj->byteOffset();
|
||||
|
||||
MOZ_ASSERT_IF(buf.dataPointer() == nullptr, offset == 0);
|
||||
MOZ_ASSERT_IF(buf.dataPointer() == nullptr, offset == 0);
|
||||
|
||||
// The data may or may not be inline with the buffer. The buffer
|
||||
// can only move during a compacting GC, in which case its
|
||||
// objectMoved hook has already updated the buffer's data pointer.
|
||||
size_t nfixed = obj->numFixedSlotsMaybeForwarded();
|
||||
obj->setPrivateUnbarriered(nfixed, buf.dataPointer() + offset);
|
||||
}
|
||||
// The data may or may not be inline with the buffer. The buffer can only
|
||||
// move during a compacting GC, in which case its objectMoved hook has
|
||||
// already updated the buffer's data pointer.
|
||||
void* data = buf.dataPointer() + offset;
|
||||
obj->getFixedSlotRef(DATA_SLOT).unbarrieredSet(PrivateValue(data));
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,8 +58,7 @@ void ArrayBufferViewObject::notifyBufferDetached() {
|
||||
|
||||
setFixedSlot(LENGTH_SLOT, PrivateValue(size_t(0)));
|
||||
setFixedSlot(BYTEOFFSET_SLOT, PrivateValue(size_t(0)));
|
||||
|
||||
setPrivate(nullptr);
|
||||
setFixedSlot(DATA_SLOT, UndefinedValue());
|
||||
}
|
||||
|
||||
/* static */
|
||||
@ -113,7 +111,7 @@ bool ArrayBufferViewObject::init(JSContext* cx,
|
||||
MOZ_ASSERT(length * bytesPerElement <=
|
||||
TypedArrayObject::INLINE_BUFFER_LIMIT);
|
||||
void* data = fixedData(TypedArrayObject::FIXED_DATA_START);
|
||||
initPrivate(data);
|
||||
initReservedSlot(DATA_SLOT, PrivateValue(data));
|
||||
memset(data, 0, length * bytesPerElement);
|
||||
#ifdef DEBUG
|
||||
if (length == 0) {
|
||||
@ -135,9 +133,6 @@ bool ArrayBufferViewObject::init(JSContext* cx,
|
||||
MOZ_ASSERT(bufferByteLength - viewByteOffset >= viewByteLength);
|
||||
MOZ_ASSERT(viewByteOffset <= bufferByteLength);
|
||||
}
|
||||
|
||||
// Verify that the private slot is at the expected place.
|
||||
MOZ_ASSERT(numFixedSlots() == DATA_SLOT);
|
||||
#endif
|
||||
|
||||
// ArrayBufferObjects track their views to support detaching.
|
||||
|
@ -36,18 +36,15 @@ class ArrayBufferViewObject : public NativeObject {
|
||||
// Offset of view within underlying (Shared)ArrayBufferObject.
|
||||
static constexpr size_t BYTEOFFSET_SLOT = 2;
|
||||
|
||||
static constexpr size_t RESERVED_SLOTS = 3;
|
||||
// Pointer to raw buffer memory.
|
||||
static constexpr size_t DATA_SLOT = 3;
|
||||
|
||||
static constexpr size_t RESERVED_SLOTS = 4;
|
||||
|
||||
#ifdef DEBUG
|
||||
static const uint8_t ZeroLengthArrayData = 0x4A;
|
||||
#endif
|
||||
|
||||
// The raw pointer to the buffer memory, the "private" value.
|
||||
//
|
||||
// This offset is exposed for performance reasons - so that it
|
||||
// need not be looked up on accesses.
|
||||
static constexpr size_t DATA_SLOT = 3;
|
||||
|
||||
static constexpr int bufferOffset() {
|
||||
return NativeObject::getFixedSlotOffset(BUFFER_SLOT);
|
||||
}
|
||||
@ -58,14 +55,14 @@ class ArrayBufferViewObject : public NativeObject {
|
||||
return NativeObject::getFixedSlotOffset(BYTEOFFSET_SLOT);
|
||||
}
|
||||
static constexpr int dataOffset() {
|
||||
return NativeObject::getPrivateDataOffset(DATA_SLOT);
|
||||
return NativeObject::getFixedSlotOffset(DATA_SLOT);
|
||||
}
|
||||
|
||||
private:
|
||||
void* dataPointerEither_() const {
|
||||
// Note, do not check whether shared or not
|
||||
// Keep synced with js::Get<Type>ArrayLengthAndData in jsfriendapi.h!
|
||||
return static_cast<void*>(getPrivate(DATA_SLOT));
|
||||
return maybePtrFromReservedSlot<void>(DATA_SLOT);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -86,7 +83,8 @@ class ArrayBufferViewObject : public NativeObject {
|
||||
// accessed only from jitted code and from the
|
||||
// dataPointerEither_() accessor above; in neither case does the
|
||||
// raw pointer escape untagged into C++ code.
|
||||
initPrivate(viewData.unwrap(/*safe - see above*/));
|
||||
void* data = viewData.unwrap(/*safe - see above*/);
|
||||
initReservedSlot(DATA_SLOT, PrivateValue(data));
|
||||
}
|
||||
|
||||
SharedMem<void*> dataPointerShared() const {
|
||||
|
@ -1545,9 +1545,6 @@ class NativeObject : public JSObject {
|
||||
MOZ_ASSERT(slot < MAX_FIXED_SLOTS);
|
||||
return sizeof(NativeObject) + slot * sizeof(Value);
|
||||
}
|
||||
static constexpr size_t getPrivateDataOffset(size_t nfixed) {
|
||||
return getFixedSlotOffset(nfixed);
|
||||
}
|
||||
static constexpr size_t getFixedSlotIndexFromOffset(size_t offset) {
|
||||
MOZ_ASSERT(offset >= sizeof(NativeObject));
|
||||
offset -= sizeof(NativeObject);
|
||||
|
@ -138,8 +138,8 @@ bool TypedArrayObject::ensureHasBuffer(JSContext* cx,
|
||||
RemoveCellMemory(tarray, nbytes, MemoryUse::TypedArrayElements);
|
||||
}
|
||||
|
||||
tarray->setPrivate(buffer->dataPointer());
|
||||
|
||||
tarray->setFixedSlot(TypedArrayObject::DATA_SLOT,
|
||||
PrivateValue(buffer->dataPointer()));
|
||||
tarray->setFixedSlot(TypedArrayObject::BUFFER_SLOT, ObjectValue(*buffer));
|
||||
|
||||
return true;
|
||||
@ -249,7 +249,8 @@ size_t TypedArrayObject::objectMoved(JSObject* obj, JSObject* old) {
|
||||
"Failed to allocate typed array elements while tenuring.");
|
||||
}
|
||||
MOZ_ASSERT(!nursery.isInside(data));
|
||||
InitObjectPrivate(newObj, data, nbytes, MemoryUse::TypedArrayElements);
|
||||
newObj->setReservedSlot(DATA_SLOT, PrivateValue(data));
|
||||
AddCellMemory(newObj, nbytes, MemoryUse::TypedArrayElements);
|
||||
}
|
||||
|
||||
mozilla::PodCopy(newObj->elements(), oldObj->elements(), nbytes);
|
||||
@ -435,10 +436,9 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
|
||||
|
||||
initTypedArraySlots(tarray, len);
|
||||
|
||||
// Template objects do not need memory for its elements, since there
|
||||
// won't be any elements to store. Therefore, we set the pointer to
|
||||
// nullptr and avoid allocating memory that will never be used.
|
||||
tarray->initPrivate(nullptr);
|
||||
// Template objects don't need memory for their elements, since there
|
||||
// won't be any elements to store.
|
||||
MOZ_ASSERT(tarray->getReservedSlot(DATA_SLOT).isUndefined());
|
||||
|
||||
return tarray;
|
||||
}
|
||||
@ -450,9 +450,6 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
|
||||
tarray->initFixedSlot(TypedArrayObject::BYTEOFFSET_SLOT,
|
||||
PrivateValue(size_t(0)));
|
||||
|
||||
// Verify that the private slot is at the expected place.
|
||||
MOZ_ASSERT(tarray->numFixedSlots() == TypedArrayObject::DATA_SLOT);
|
||||
|
||||
#ifdef DEBUG
|
||||
if (len == 0) {
|
||||
uint8_t* output = tarray->fixedData(TypedArrayObject::FIXED_DATA_START);
|
||||
@ -464,7 +461,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
|
||||
static void initTypedArrayData(TypedArrayObject* tarray, void* buf,
|
||||
size_t nbytes, gc::AllocKind allocKind) {
|
||||
if (buf) {
|
||||
InitObjectPrivate(tarray, buf, nbytes, MemoryUse::TypedArrayElements);
|
||||
InitReservedSlot(tarray, TypedArrayObject::DATA_SLOT, buf, nbytes,
|
||||
MemoryUse::TypedArrayElements);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
constexpr size_t dataOffset = ArrayBufferViewObject::dataOffset();
|
||||
@ -473,7 +471,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject {
|
||||
#endif
|
||||
|
||||
void* data = tarray->fixedData(FIXED_DATA_START);
|
||||
tarray->initPrivate(data);
|
||||
tarray->initReservedSlot(DATA_SLOT, PrivateValue(data));
|
||||
memset(data, 0, nbytes);
|
||||
}
|
||||
}
|
||||
@ -2234,13 +2232,13 @@ static const ClassSpec
|
||||
};
|
||||
|
||||
const JSClass TypedArrayObject::classes[Scalar::MaxTypedArrayViewType] = {
|
||||
#define IMPL_TYPED_ARRAY_CLASS(NativeType, Name) \
|
||||
{#Name "Array", \
|
||||
JSCLASS_HAS_RESERVED_SLOTS(TypedArrayObject::RESERVED_SLOTS) | \
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_HAS_CACHED_PROTO(JSProto_##Name##Array) | \
|
||||
JSCLASS_DELAY_METADATA_BUILDER | JSCLASS_SKIP_NURSERY_FINALIZE | \
|
||||
JSCLASS_BACKGROUND_FINALIZE, \
|
||||
&TypedArrayClassOps, &TypedArrayObjectClassSpecs[Scalar::Type::Name], \
|
||||
#define IMPL_TYPED_ARRAY_CLASS(NativeType, Name) \
|
||||
{#Name "Array", \
|
||||
JSCLASS_HAS_RESERVED_SLOTS(TypedArrayObject::RESERVED_SLOTS) | \
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_##Name##Array) | \
|
||||
JSCLASS_DELAY_METADATA_BUILDER | JSCLASS_SKIP_NURSERY_FINALIZE | \
|
||||
JSCLASS_BACKGROUND_FINALIZE, \
|
||||
&TypedArrayClassOps, &TypedArrayObjectClassSpecs[Scalar::Type::Name], \
|
||||
&TypedArrayClassExtension},
|
||||
|
||||
JS_FOR_EACH_TYPED_ARRAY(IMPL_TYPED_ARRAY_CLASS)
|
||||
|
@ -48,6 +48,8 @@ class TypedArrayObject : public ArrayBufferViewObject {
|
||||
public:
|
||||
static_assert(js::detail::TypedArrayLengthSlot == LENGTH_SLOT,
|
||||
"bad inlined constant in TypedData.h");
|
||||
static_assert(js::detail::TypedArrayDataSlot == DATA_SLOT,
|
||||
"bad inlined constant in TypedData.h");
|
||||
|
||||
static bool sameBuffer(Handle<TypedArrayObject*> a,
|
||||
Handle<TypedArrayObject*> b) {
|
||||
@ -78,7 +80,7 @@ class TypedArrayObject : public ArrayBufferViewObject {
|
||||
return &protoClasses[type];
|
||||
}
|
||||
|
||||
static constexpr size_t FIXED_DATA_START = DATA_SLOT + 1;
|
||||
static constexpr size_t FIXED_DATA_START = RESERVED_SLOTS;
|
||||
|
||||
// For typed arrays which can store their data inline, the array buffer
|
||||
// object is created lazily.
|
||||
@ -111,7 +113,7 @@ class TypedArrayObject : public ArrayBufferViewObject {
|
||||
bool hasInlineElements() const;
|
||||
void setInlineElements();
|
||||
uint8_t* elementsRaw() const {
|
||||
return *(uint8_t**)((((char*)this) + ArrayBufferViewObject::dataOffset()));
|
||||
return maybePtrFromReservedSlot<uint8_t>(DATA_SLOT);
|
||||
}
|
||||
uint8_t* elements() const {
|
||||
assertZeroLengthArrayData();
|
||||
|
Loading…
Reference in New Issue
Block a user