mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1103273 - Fix uses of forwarding pointers in inline typed objects, r=sfink.
This commit is contained in:
parent
96b7a29c5f
commit
b8bc67a4f9
@ -1511,6 +1511,11 @@ PrototypeForTypeDescr(JSContext *cx, HandleTypeDescr descr)
|
||||
void
|
||||
OutlineTypedObject::setOwnerAndData(JSObject *owner, uint8_t *data)
|
||||
{
|
||||
// Make sure we don't associate with array buffers whose data is from an
|
||||
// inline typed object, see obj_trace.
|
||||
MOZ_ASSERT_IF(owner && owner->is<ArrayBufferObject>(),
|
||||
!owner->as<ArrayBufferObject>().forInlineTypedObject());
|
||||
|
||||
// Typed objects cannot move from one owner to another, so don't worry
|
||||
// about pre barriers during this initialization.
|
||||
owner_ = owner;
|
||||
@ -1554,6 +1559,14 @@ OutlineTypedObject::attach(JSContext *cx, ArrayBufferObject &buffer, int32_t off
|
||||
MOZ_ASSERT(offset >= 0);
|
||||
MOZ_ASSERT((size_t) (offset + size()) <= buffer.byteLength());
|
||||
|
||||
// If the owner's data is from an inline typed object, associate this with
|
||||
// the inline typed object instead, to simplify tracing.
|
||||
if (buffer.forInlineTypedObject()) {
|
||||
InlineTypedObject &realOwner = buffer.firstView()->as<InlineTypedObject>();
|
||||
attach(cx, realOwner, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.setHasTypedObjectViews();
|
||||
|
||||
if (!buffer.addView(cx, this))
|
||||
@ -1683,22 +1696,29 @@ OutlineTypedObject::obj_trace(JSTracer *trc, JSObject *object)
|
||||
gc::MarkObjectUnbarriered(trc, &typedObj.owner_, "typed object owner");
|
||||
JSObject *owner = typedObj.owner_;
|
||||
|
||||
uint8_t *mem = typedObj.outOfLineTypedMem();
|
||||
uint8_t *oldData = typedObj.outOfLineTypedMem();
|
||||
uint8_t *newData = oldData;
|
||||
|
||||
// Update the data pointer if the owner moved and the owner's data is
|
||||
// inline with it.
|
||||
// inline with it. Note that an array buffer pointing to data in an inline
|
||||
// typed object will never be used as an owner for another outline typed
|
||||
// object. In such cases, the owner will be the inline typed object itself.
|
||||
MOZ_ASSERT_IF(owner->is<ArrayBufferObject>(),
|
||||
!owner->as<ArrayBufferObject>().forInlineTypedObject());
|
||||
if (owner != oldOwner &&
|
||||
(owner->is<InlineTypedObject>() ||
|
||||
owner->as<ArrayBufferObject>().hasInlineData()))
|
||||
{
|
||||
mem += reinterpret_cast<uint8_t *>(owner) - reinterpret_cast<uint8_t *>(oldOwner);
|
||||
typedObj.setData(mem);
|
||||
newData += reinterpret_cast<uint8_t *>(owner) - reinterpret_cast<uint8_t *>(oldOwner);
|
||||
typedObj.setData(newData);
|
||||
|
||||
trc->runtime()->gc.nursery.maybeSetForwardingPointer(trc, oldData, newData, /* direct = */ false);
|
||||
}
|
||||
|
||||
if (!descr.opaque() || !typedObj.maybeForwardedIsAttached())
|
||||
return;
|
||||
|
||||
descr.traceInstances(trc, mem, 1);
|
||||
descr.traceInstances(trc, newData, 1);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -2260,6 +2280,25 @@ InlineTypedObject::obj_trace(JSTracer *trc, JSObject *object)
|
||||
descr.traceInstances(trc, typedObj.inlineTypedMem(), 1);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
InlineTypedObject::objectMovedDuringMinorGC(JSTracer *trc, JSObject *dst, JSObject *src)
|
||||
{
|
||||
// Inline typed object element arrays can be preserved on the stack by Ion
|
||||
// and need forwarding pointers created during a minor GC. We can't do this
|
||||
// in the trace hook because we don't have any stale data to determine
|
||||
// whether this object moved and where it was moved from.
|
||||
TypeDescr &descr = dst->as<InlineTypedObject>().typeDescr();
|
||||
if (descr.kind() == type::Array) {
|
||||
// The forwarding pointer can be direct as long as there is enough
|
||||
// space for it. Other objects might point into the object's buffer,
|
||||
// but they will not set any direct forwarding pointers.
|
||||
uint8_t *oldData = reinterpret_cast<uint8_t *>(src) + offsetOfDataStart();
|
||||
uint8_t *newData = dst->as<InlineTypedObject>().inlineTypedMem();
|
||||
trc->runtime()->gc.nursery.maybeSetForwardingPointer(trc, oldData, newData,
|
||||
descr.size() >= sizeof(uintptr_t));
|
||||
}
|
||||
}
|
||||
|
||||
ArrayBufferObject *
|
||||
InlineTransparentTypedObject::getOrCreateBuffer(JSContext *cx)
|
||||
{
|
||||
|
@ -741,6 +741,7 @@ class InlineTypedObject : public TypedObject
|
||||
}
|
||||
|
||||
static void obj_trace(JSTracer *trace, JSObject *object);
|
||||
static void objectMovedDuringMinorGC(JSTracer *trc, JSObject *dst, JSObject *src);
|
||||
|
||||
static size_t offsetOfDataStart() {
|
||||
return offsetof(InlineTypedObject, data_);
|
||||
|
@ -393,8 +393,8 @@ GetObjectAllocKindForCopy(const Nursery &nursery, JSObject *obj)
|
||||
// Proxies have finalizers and are not nursery allocated.
|
||||
MOZ_ASSERT(!IsProxy(obj));
|
||||
|
||||
// Inlined opaque typed objects are followed by their data, so make sure we
|
||||
// copy it all over to the new object.
|
||||
// Inlined typed objects are followed by their data, so make sure we copy
|
||||
// it all over to the new object.
|
||||
if (obj->is<InlineTypedObject>()) {
|
||||
// Figure out the size of this object, from the prototype's TypeDescr.
|
||||
// The objects we are traversing here are all tenured, so we don't need
|
||||
@ -429,28 +429,41 @@ js::Nursery::allocateFromTenured(Zone *zone, AllocKind thingKind)
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::setSlotsForwardingPointer(HeapSlot *oldSlots, HeapSlot *newSlots, uint32_t nslots)
|
||||
Nursery::setForwardingPointer(void *oldData, void *newData, bool direct)
|
||||
{
|
||||
MOZ_ASSERT(nslots > 0);
|
||||
MOZ_ASSERT(isInside(oldSlots));
|
||||
MOZ_ASSERT(!isInside(newSlots));
|
||||
*reinterpret_cast<HeapSlot **>(oldSlots) = newSlots;
|
||||
MOZ_ASSERT(isInside(oldData));
|
||||
MOZ_ASSERT(!isInside(newData));
|
||||
|
||||
if (direct) {
|
||||
*reinterpret_cast<void **>(oldData) = newData;
|
||||
} else {
|
||||
if (!forwardedBuffers.initialized() && !forwardedBuffers.init())
|
||||
CrashAtUnhandlableOOM("Nursery::setForwardingPointer");
|
||||
#ifdef DEBUG
|
||||
if (ForwardedBufferMap::Ptr p = forwardedBuffers.lookup(oldData))
|
||||
MOZ_ASSERT(p->value() == newData);
|
||||
#endif
|
||||
if (!forwardedBuffers.put(oldData, newData))
|
||||
CrashAtUnhandlableOOM("Nursery::setForwardingPointer");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::setElementsForwardingPointer(ObjectElements *oldHeader, ObjectElements *newHeader,
|
||||
uint32_t nelems)
|
||||
Nursery::setSlotsForwardingPointer(HeapSlot *oldSlots, HeapSlot *newSlots, uint32_t nslots)
|
||||
{
|
||||
MOZ_ASSERT(isInside(oldHeader));
|
||||
MOZ_ASSERT(!isInside(newHeader));
|
||||
if (nelems - ObjectElements::VALUES_PER_HEADER < 1) {
|
||||
if (!forwardedBuffers.initialized() && !forwardedBuffers.init())
|
||||
CrashAtUnhandlableOOM("Nursery::setElementsForwardingPointer");
|
||||
if (!forwardedBuffers.put(oldHeader->elements(), newHeader->elements()))
|
||||
CrashAtUnhandlableOOM("Nursery::setElementsForwardingPointer");
|
||||
return;
|
||||
}
|
||||
*reinterpret_cast<HeapSlot **>(oldHeader->elements()) = newHeader->elements();
|
||||
// Slot arrays always have enough space for a forwarding pointer, since the
|
||||
// number of slots is never zero.
|
||||
MOZ_ASSERT(nslots > 0);
|
||||
setForwardingPointer(oldSlots, newSlots, /* direct = */ true);
|
||||
}
|
||||
|
||||
void
|
||||
Nursery::setElementsForwardingPointer(ObjectElements *oldHeader, ObjectElements *newHeader,
|
||||
uint32_t nelems)
|
||||
{
|
||||
// Only use a direct forwarding pointer if there is enough space for one.
|
||||
setForwardingPointer(oldHeader->elements(), newHeader->elements(),
|
||||
nelems > ObjectElements::VALUES_PER_HEADER);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -590,7 +603,7 @@ js::Nursery::moveToTenured(MinorCollectionTracer *trc, JSObject *src)
|
||||
if (!dst)
|
||||
CrashAtUnhandlableOOM("Failed to allocate object while tenuring.");
|
||||
|
||||
trc->tenuredSize += moveObjectToTenured(dst, src, dstKind);
|
||||
trc->tenuredSize += moveObjectToTenured(trc, dst, src, dstKind);
|
||||
|
||||
RelocationOverlay *overlay = RelocationOverlay::fromCell(src);
|
||||
overlay->forwardTo(dst);
|
||||
@ -601,7 +614,8 @@ js::Nursery::moveToTenured(MinorCollectionTracer *trc, JSObject *src)
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
js::Nursery::moveObjectToTenured(JSObject *dst, JSObject *src, AllocKind dstKind)
|
||||
js::Nursery::moveObjectToTenured(MinorCollectionTracer *trc,
|
||||
JSObject *dst, JSObject *src, AllocKind dstKind)
|
||||
{
|
||||
size_t srcSize = Arena::thingSize(dstKind);
|
||||
size_t tenuredSize = srcSize;
|
||||
@ -625,8 +639,8 @@ js::Nursery::moveObjectToTenured(JSObject *dst, JSObject *src, AllocKind dstKind
|
||||
tenuredSize += moveElementsToTenured(ndst, nsrc, dstKind);
|
||||
}
|
||||
|
||||
if (src->is<TypedArrayObject>())
|
||||
forwardTypedArrayPointers(&dst->as<TypedArrayObject>(), &src->as<TypedArrayObject>());
|
||||
if (src->is<InlineTypedObject>())
|
||||
InlineTypedObject::objectMovedDuringMinorGC(trc, dst, src);
|
||||
|
||||
/* The shape's list head may point into the old object. */
|
||||
if (&src->shape_ == dst->shape_->listp)
|
||||
@ -635,35 +649,6 @@ js::Nursery::moveObjectToTenured(JSObject *dst, JSObject *src, AllocKind dstKind
|
||||
return tenuredSize;
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::forwardTypedArrayPointers(TypedArrayObject *dst, TypedArrayObject *src)
|
||||
{
|
||||
/*
|
||||
* Typed array data may be stored inline inside the object's fixed slots. If
|
||||
* so, we need update the private pointer and leave a forwarding pointer at
|
||||
* the start of the data.
|
||||
*/
|
||||
if (src->buffer()) {
|
||||
MOZ_ASSERT(!isInside(src->getPrivate()));
|
||||
return;
|
||||
}
|
||||
|
||||
void *srcData = src->fixedData(TypedArrayObject::FIXED_DATA_START);
|
||||
void *dstData = dst->fixedData(TypedArrayObject::FIXED_DATA_START);
|
||||
MOZ_ASSERT(src->getPrivate() == srcData);
|
||||
dst->setPrivate(dstData);
|
||||
|
||||
/*
|
||||
* We don't know the number of slots here, but
|
||||
* TypedArrayObject::AllocKindForLazyBuffer ensures that it's always at
|
||||
* least one.
|
||||
*/
|
||||
size_t nslots = 1;
|
||||
setSlotsForwardingPointer(reinterpret_cast<HeapSlot*>(srcData),
|
||||
reinterpret_cast<HeapSlot*>(dstData),
|
||||
nslots);
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
js::Nursery::moveSlotsToTenured(NativeObject *dst, NativeObject *src, AllocKind dstKind)
|
||||
{
|
||||
|
@ -137,6 +137,11 @@ class Nursery
|
||||
|
||||
static void forwardBufferPointer(JSTracer* trc, HeapSlot **pSlotsElems);
|
||||
|
||||
void maybeSetForwardingPointer(JSTracer *trc, void *oldData, void *newData, bool direct) {
|
||||
if (IsMinorCollectionTracer(trc) && isInside(oldData))
|
||||
setForwardingPointer(oldData, newData, direct);
|
||||
}
|
||||
|
||||
size_t sizeOfHeapCommitted() const {
|
||||
return numActiveChunks_ * gc::ChunkSize;
|
||||
}
|
||||
@ -295,12 +300,14 @@ class Nursery
|
||||
MOZ_ALWAYS_INLINE void markSlots(gc::MinorCollectionTracer *trc, HeapSlot *vp, HeapSlot *end);
|
||||
MOZ_ALWAYS_INLINE void markSlot(gc::MinorCollectionTracer *trc, HeapSlot *slotp);
|
||||
void *moveToTenured(gc::MinorCollectionTracer *trc, JSObject *src);
|
||||
size_t moveObjectToTenured(JSObject *dst, JSObject *src, gc::AllocKind dstKind);
|
||||
size_t moveObjectToTenured(gc::MinorCollectionTracer *trc, JSObject *dst, JSObject *src,
|
||||
gc::AllocKind dstKind);
|
||||
size_t moveElementsToTenured(NativeObject *dst, NativeObject *src, gc::AllocKind dstKind);
|
||||
size_t moveSlotsToTenured(NativeObject *dst, NativeObject *src, gc::AllocKind dstKind);
|
||||
void forwardTypedArrayPointers(TypedArrayObject *dst, TypedArrayObject *src);
|
||||
|
||||
/* Handle relocation of slots/elements pointers stored in Ion frames. */
|
||||
void setForwardingPointer(void *oldData, void *newData, bool direct);
|
||||
|
||||
void setSlotsForwardingPointer(HeapSlot *oldSlots, HeapSlot *newSlots, uint32_t nslots);
|
||||
void setElementsForwardingPointer(ObjectElements *oldHeader, ObjectElements *newHeader,
|
||||
uint32_t nelems);
|
||||
|
12
js/src/jit-test/tests/TypedObject/bug1103273-1.js
Normal file
12
js/src/jit-test/tests/TypedObject/bug1103273-1.js
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
gczeal(2);
|
||||
var Vec3u16Type = TypedObject.uint16.array(3);
|
||||
function foo_u16(n) {
|
||||
if (n == 0)
|
||||
return;
|
||||
var i = 0;
|
||||
var vec = new Vec3u16Type([i, i+1, i+2]);
|
||||
var sum = vec[0] + vec[1] + vec[(/[]/g )];
|
||||
foo_u16(n - 1);
|
||||
}
|
||||
foo_u16(100);
|
20
js/src/jit-test/tests/TypedObject/bug1103273-2.js
Normal file
20
js/src/jit-test/tests/TypedObject/bug1103273-2.js
Normal file
@ -0,0 +1,20 @@
|
||||
|
||||
var Vec3u16Type = TypedObject.uint16.array(3);
|
||||
|
||||
function foo() {
|
||||
var x = 0;
|
||||
for (var i = 0; i < 3; i++) {
|
||||
var obj = new Vec3u16Type;
|
||||
var buf = TypedObject.storage(obj).buffer;
|
||||
var arr = new Uint8Array(buf, 3);
|
||||
arr[0] = i + 1;
|
||||
arr[1] = i + 2;
|
||||
arr[2] = i + 3;
|
||||
for (var j = 0; j < arr.length; j++) {
|
||||
minorgc();
|
||||
x += arr[j];
|
||||
}
|
||||
}
|
||||
assertEq(x, 27);
|
||||
}
|
||||
foo();
|
@ -1187,13 +1187,36 @@ ArrayBufferViewObject::trace(JSTracer *trc, JSObject *objArg)
|
||||
HeapSlot &bufSlot = obj->getReservedSlotRef(TypedArrayLayout::BUFFER_SLOT);
|
||||
MarkSlot(trc, &bufSlot, "typedarray.buffer");
|
||||
|
||||
// Update obj's data pointer if the array buffer moved. Note that during
|
||||
// initialization, bufSlot may still contain |undefined|.
|
||||
// Update obj's data pointer if it moved.
|
||||
if (bufSlot.isObject()) {
|
||||
ArrayBufferObject &buf = AsArrayBuffer(MaybeForwarded(&bufSlot.toObject()));
|
||||
int32_t offset = obj->getReservedSlot(TypedArrayLayout::BYTEOFFSET_SLOT).toInt32();
|
||||
MOZ_ASSERT(buf.dataPointer() != nullptr);
|
||||
obj->initPrivate(buf.dataPointer() + offset);
|
||||
|
||||
if (buf.forInlineTypedObject()) {
|
||||
// The data is inline with an InlineTypedObject associated with the
|
||||
// buffer. Get a new address for the typed object if it moved.
|
||||
JSObject *view = buf.firstView();
|
||||
|
||||
// Mark the object to move it into the tenured space.
|
||||
MarkObjectUnbarriered(trc, &view, "typed array nursery owner");
|
||||
MOZ_ASSERT(view->is<InlineTypedObject>() && view != obj);
|
||||
|
||||
void *srcData = obj->getPrivate();
|
||||
void *dstData = view->as<InlineTypedObject>().inlineTypedMem() + offset;
|
||||
obj->setPrivate(dstData);
|
||||
|
||||
// We can't use a direct forwarding pointer here, as there might
|
||||
// not be enough bytes available, and other views might have data
|
||||
// pointers whose forwarding pointers would overlap this one.
|
||||
trc->runtime()->gc.nursery.maybeSetForwardingPointer(trc, srcData, dstData,
|
||||
/* direct = */ false);
|
||||
} else {
|
||||
// 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.
|
||||
obj->initPrivate(buf.dataPointer() + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,22 @@ class ArrayBufferViewObject;
|
||||
// As ArrayBufferObject and SharedArrayBufferObject are separated, so are the
|
||||
// TypedArray hierarchies below the two. However, the TypedArrays have the
|
||||
// same layout (see TypedArrayObject.h), so there is little code duplication.
|
||||
//
|
||||
// The possible data ownership and reference relationships with array buffers
|
||||
// and related classes are enumerated below. These are the possible locations
|
||||
// for typed data:
|
||||
//
|
||||
// (1) malloc'ed or mmap'ed data owned by an ArrayBufferObject.
|
||||
// (2) Data allocated inline with an ArrayBufferObject.
|
||||
// (3) Data allocated inline with a TypedArrayObject.
|
||||
// (4) Data allocated inline with an InlineTypedObject.
|
||||
//
|
||||
// An ArrayBufferObject may point to any of these sources of data, except (3).
|
||||
// All array buffer views may point to any of these sources of data, except
|
||||
// that (3) may only be pointed to by the typed array the data is inline with.
|
||||
//
|
||||
// During a minor GC, (3) and (4) may move. During a compacting GC, (2), (3),
|
||||
// and (4) may move.
|
||||
|
||||
class ArrayBufferObjectMaybeShared;
|
||||
|
||||
@ -329,6 +345,8 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
||||
setFlags(flags() | TYPED_OBJECT_VIEWS);
|
||||
}
|
||||
|
||||
bool forInlineTypedObject() const { return flags() & FOR_INLINE_TYPED_OBJECT; }
|
||||
|
||||
protected:
|
||||
void setDataPointer(BufferContents contents, OwnsState ownsState);
|
||||
void setByteLength(size_t length);
|
||||
@ -341,7 +359,6 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
||||
setFlags(owns ? (flags() | OWNS_DATA) : (flags() & ~OWNS_DATA));
|
||||
}
|
||||
|
||||
bool forInlineTypedObject() const { return flags() & FOR_INLINE_TYPED_OBJECT; }
|
||||
bool hasTypedObjectViews() const { return flags() & TYPED_OBJECT_VIEWS; }
|
||||
|
||||
void setIsAsmJSMalloced() { setFlags((flags() & ~KIND_MASK) | ASMJS_MALLOCED); }
|
||||
|
@ -125,13 +125,25 @@ TypedArrayObject::ensureHasBuffer(JSContext *cx, Handle<TypedArrayObject *> tarr
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
TypedArrayObject::ObjectMoved(JSObject *dstArg, const JSObject *srcArg)
|
||||
TypedArrayObject::trace(JSTracer *trc, JSObject *objArg)
|
||||
{
|
||||
const TypedArrayObject &src = srcArg->as<TypedArrayObject>();
|
||||
TypedArrayObject &dst = dstArg->as<TypedArrayObject>();
|
||||
if (!src.hasBuffer()) {
|
||||
MOZ_ASSERT(src.getPrivate() == src.fixedData(FIXED_DATA_START));
|
||||
dst.setPrivate(dst.fixedData(FIXED_DATA_START));
|
||||
// Handle all tracing required when the object has a buffer.
|
||||
ArrayBufferViewObject::trace(trc, objArg);
|
||||
|
||||
// If the typed array doesn't have a buffer, it must have a lazy buffer and
|
||||
// its data pointer must point to its inline data. Watch for cases where
|
||||
// the GC moved this object and fix up its data pointer.
|
||||
TypedArrayObject &obj = objArg->as<TypedArrayObject>();
|
||||
if (!obj.hasBuffer() && obj.getPrivate() != obj.fixedData(FIXED_DATA_START)) {
|
||||
void *oldData = obj.getPrivate();
|
||||
void *newData = obj.fixedData(FIXED_DATA_START);
|
||||
|
||||
obj.setPrivateUnbarriered(newData);
|
||||
|
||||
// If this is a minor GC, set a forwarding pointer for the array data.
|
||||
// This can always be done inline, as AllocKindForLazyBuffer ensures
|
||||
// there is at least a pointer's worth of inline data.
|
||||
trc->runtime()->gc.nursery.maybeSetForwardingPointer(trc, oldData, newData, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,6 +366,12 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
||||
|
||||
if (buffer) {
|
||||
obj->initPrivate(buffer->dataPointer() + byteOffset);
|
||||
|
||||
// If the buffer is for an inline typed object, the data pointer
|
||||
// may be in the nursery, so include a barrier to make sure this
|
||||
// object is updated if that typed object moves.
|
||||
if (!IsInsideNursery(obj) && cx->runtime()->gc.nursery.isInside(buffer->dataPointer()))
|
||||
cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj);
|
||||
} else {
|
||||
void *data = obj->fixedData(FIXED_DATA_START);
|
||||
obj->initPrivate(data);
|
||||
@ -967,6 +985,11 @@ DataViewObject::create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength,
|
||||
dvobj.initPrivate(arrayBuffer->dataPointer() + byteOffset);
|
||||
MOZ_ASSERT(byteOffset + byteLength <= arrayBuffer->byteLength());
|
||||
|
||||
// Include a barrier if the data view's data pointer is in the nursery, as
|
||||
// is done for typed arrays.
|
||||
if (!IsInsideNursery(obj) && cx->runtime()->gc.nursery.isInside(arrayBuffer->dataPointer()))
|
||||
cx->runtime()->gc.storeBuffer.putWholeCellFromMainThread(obj);
|
||||
|
||||
// Verify that the private slot is at the expected place
|
||||
MOZ_ASSERT(dvobj.numFixedSlots() == TypedArrayLayout::DATA_SLOT);
|
||||
|
||||
@ -1747,15 +1770,8 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
|
||||
nullptr, /* call */ \
|
||||
nullptr, /* hasInstance */ \
|
||||
nullptr, /* construct */ \
|
||||
ArrayBufferViewObject::trace, /* trace */ \
|
||||
TYPED_ARRAY_CLASS_SPEC(_typedArray), \
|
||||
{ \
|
||||
nullptr, /* outerObject */ \
|
||||
nullptr, /* innerObject */ \
|
||||
false, /* isWrappedNative */ \
|
||||
nullptr, /* weakmapKeyDelegateOp */ \
|
||||
TypedArrayObject::ObjectMoved \
|
||||
} \
|
||||
TypedArrayObject::trace, /* trace */ \
|
||||
TYPED_ARRAY_CLASS_SPEC(_typedArray) \
|
||||
}
|
||||
|
||||
const Class TypedArrayObject::classes[Scalar::TypeMax] = {
|
||||
|
@ -182,7 +182,7 @@ class TypedArrayObject : public NativeObject
|
||||
return layout_;
|
||||
}
|
||||
|
||||
static void ObjectMoved(JSObject *obj, const JSObject *old);
|
||||
static void trace(JSTracer *trc, JSObject *obj);
|
||||
|
||||
/* Initialization bits */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user