зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1069680 - Restore array buffer view trace hook, clean up use of typed array layout constants, r=sfink.
This commit is contained in:
Родитель
a495f0231b
Коммит
0eb54db50c
|
@ -1653,11 +1653,11 @@ ReportTypedObjTypeError(JSContext *cx,
|
|||
/*static*/ void
|
||||
TypedObject::obj_trace(JSTracer *trace, JSObject *object)
|
||||
{
|
||||
ArrayBufferViewObject::trace(trace, object);
|
||||
|
||||
JS_ASSERT(object->is<TypedObject>());
|
||||
TypedObject &typedObj = object->as<TypedObject>();
|
||||
|
||||
gc::MarkSlot(trace, &typedObj.getFixedSlotRef(JS_BUFVIEW_SLOT_OWNER), "typed object owner");
|
||||
|
||||
// When this is called for compacting GC, the related objects we touch here
|
||||
// may not have had their slots updated yet. Note that this does not apply
|
||||
// to generational GC because these objects (type descriptors and
|
||||
|
|
|
@ -1744,7 +1744,7 @@ GCMarker::processMarkStackTop(SliceBudget &budget)
|
|||
const Class *clasp = type->clasp();
|
||||
if (clasp->trace) {
|
||||
// Global objects all have the same trace hook. That hook is safe without barriers
|
||||
// if the gloal has no custom trace hook of it's own, or has been moved to a different
|
||||
// if the global has no custom trace hook of its own, or has been moved to a different
|
||||
// compartment, and so can't have one.
|
||||
JS_ASSERT_IF(runtime()->gc.isIncrementalGCEnabled() &&
|
||||
!(clasp->trace == JS_GlobalObjectTraceHook &&
|
||||
|
|
|
@ -519,6 +519,12 @@ ArrayBufferObject::releaseMappedArray()
|
|||
DeallocateMappedContent(dataPointer(), byteLength());
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
ArrayBufferObject::inlineDataPointer() const
|
||||
{
|
||||
return static_cast<uint8_t *>(fixedData(JSCLASS_RESERVED_SLOTS(&class_)));
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
ArrayBufferObject::dataPointer() const
|
||||
{
|
||||
|
@ -620,7 +626,7 @@ ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, BufferContents content
|
|||
JS_ASSERT(!gc::IsInsideNursery(obj));
|
||||
|
||||
if (!contents) {
|
||||
void *data = obj->fixedData(reservedSlots);
|
||||
void *data = obj->inlineDataPointer();
|
||||
memset(data, 0, nbytes);
|
||||
obj->initialize(nbytes, BufferContents::createUnowned(data), DoesntOwnData);
|
||||
} else {
|
||||
|
@ -772,9 +778,8 @@ ArrayBufferObject::objectMoved(JSObject *obj, const JSObject *old)
|
|||
const ArrayBufferObject &src = old->as<ArrayBufferObject>();
|
||||
|
||||
// Fix up possible inline data pointer.
|
||||
const size_t reservedSlots = JSCLASS_RESERVED_SLOTS(&ArrayBufferObject::class_);
|
||||
if (src.dataPointer() == src.fixedData(reservedSlots))
|
||||
dst.setSlot(DATA_SLOT, PrivateValue(dst.fixedData(reservedSlots)));
|
||||
if (src.hasInlineData())
|
||||
dst.setSlot(DATA_SLOT, PrivateValue(dst.inlineDataPointer()));
|
||||
}
|
||||
|
||||
ArrayBufferViewObject *
|
||||
|
@ -954,6 +959,27 @@ InnerViewTable::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf)
|
|||
* ArrayBufferViewObject
|
||||
*/
|
||||
|
||||
/*
|
||||
* This method is used to trace TypedArrayObjects and DataViewObjects. We need
|
||||
* a custom tracer to move the object's data pointer if its owner was moved and
|
||||
* stores its data inline.
|
||||
*/
|
||||
/* static */ void
|
||||
ArrayBufferViewObject::trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
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|.
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
bool
|
||||
JSObject::is<js::ArrayBufferViewObject>() const
|
||||
|
|
|
@ -247,12 +247,17 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
uint8_t *oldDataPointer, BufferContents newContents);
|
||||
void setFirstView(ArrayBufferViewObject *view);
|
||||
|
||||
uint8_t *inlineDataPointer() const;
|
||||
|
||||
public:
|
||||
uint8_t *dataPointer() const;
|
||||
size_t byteLength() const;
|
||||
BufferContents contents() const {
|
||||
return BufferContents(dataPointer(), bufferKind());
|
||||
}
|
||||
bool hasInlineData() const {
|
||||
return dataPointer() == inlineDataPointer();
|
||||
}
|
||||
|
||||
void releaseData(FreeOp *fop);
|
||||
|
||||
|
@ -325,16 +330,6 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared
|
|||
|
||||
class ArrayBufferViewObject : public JSObject
|
||||
{
|
||||
protected:
|
||||
/* Offset of view in underlying ArrayBufferObject */
|
||||
static const size_t BYTEOFFSET_SLOT = JS_BUFVIEW_SLOT_BYTEOFFSET;
|
||||
|
||||
/* Byte length of view */
|
||||
static const size_t LENGTH_SLOT = JS_BUFVIEW_SLOT_LENGTH;
|
||||
|
||||
/* Underlying ArrayBufferObject */
|
||||
static const size_t BUFFER_SLOT = JS_BUFVIEW_SLOT_OWNER;
|
||||
|
||||
public:
|
||||
static ArrayBufferObject *bufferObject(JSContext *cx, Handle<ArrayBufferViewObject *> obj);
|
||||
|
||||
|
@ -343,6 +338,7 @@ class ArrayBufferViewObject : public JSObject
|
|||
uint8_t *dataPointer() {
|
||||
return static_cast<uint8_t *>(getPrivate());
|
||||
}
|
||||
static void trace(JSTracer *trc, JSObject *obj);
|
||||
};
|
||||
|
||||
bool
|
||||
|
|
|
@ -92,8 +92,8 @@ TypedArrayLayout::dataOffset()
|
|||
void
|
||||
TypedArrayObject::neuter(void *newData)
|
||||
{
|
||||
setSlot(LENGTH_SLOT, Int32Value(0));
|
||||
setSlot(BYTEOFFSET_SLOT, Int32Value(0));
|
||||
setSlot(TypedArrayLayout::LENGTH_SLOT, Int32Value(0));
|
||||
setSlot(TypedArrayLayout::BYTEOFFSET_SLOT, Int32Value(0));
|
||||
setPrivate(newData);
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ TypedArrayObject::ensureHasBuffer(JSContext *cx, Handle<TypedArrayObject *> tarr
|
|||
memcpy(buffer->dataPointer(), tarray->viewData(), tarray->byteLength());
|
||||
InitArrayBufferViewDataPointer(tarray, buffer, 0);
|
||||
|
||||
tarray->setSlot(BUFFER_SLOT, ObjectValue(*buffer));
|
||||
tarray->setSlot(TypedArrayLayout::BUFFER_SLOT, ObjectValue(*buffer));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -348,7 +348,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
if (!obj)
|
||||
return nullptr;
|
||||
|
||||
obj->setSlot(BUFFER_SLOT, ObjectOrNullValue(buffer));
|
||||
obj->setSlot(TypedArrayLayout::BUFFER_SLOT, ObjectOrNullValue(buffer));
|
||||
|
||||
if (buffer) {
|
||||
InitArrayBufferViewDataPointer(obj, buffer, byteOffset);
|
||||
|
@ -358,8 +358,8 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
memset(data, 0, len * sizeof(NativeType));
|
||||
}
|
||||
|
||||
obj->setSlot(LENGTH_SLOT, Int32Value(len));
|
||||
obj->setSlot(BYTEOFFSET_SLOT, Int32Value(byteOffset));
|
||||
obj->setSlot(TypedArrayLayout::LENGTH_SLOT, Int32Value(len));
|
||||
obj->setSlot(TypedArrayLayout::BYTEOFFSET_SLOT, Int32Value(byteOffset));
|
||||
|
||||
#ifdef DEBUG
|
||||
if (buffer) {
|
||||
|
@ -372,7 +372,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||
}
|
||||
|
||||
// Verify that the private slot is at the expected place
|
||||
JS_ASSERT(obj->numFixedSlots() == DATA_SLOT);
|
||||
JS_ASSERT(obj->numFixedSlots() == TypedArrayLayout::DATA_SLOT);
|
||||
#endif
|
||||
|
||||
if (buffer) {
|
||||
|
@ -950,14 +950,14 @@ DataViewObject::create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength,
|
|||
}
|
||||
|
||||
DataViewObject &dvobj = obj->as<DataViewObject>();
|
||||
dvobj.setFixedSlot(BYTEOFFSET_SLOT, Int32Value(byteOffset));
|
||||
dvobj.setFixedSlot(LENGTH_SLOT, Int32Value(byteLength));
|
||||
dvobj.setFixedSlot(BUFFER_SLOT, ObjectValue(*arrayBuffer));
|
||||
dvobj.setFixedSlot(TypedArrayLayout::BYTEOFFSET_SLOT, Int32Value(byteOffset));
|
||||
dvobj.setFixedSlot(TypedArrayLayout::LENGTH_SLOT, Int32Value(byteLength));
|
||||
dvobj.setFixedSlot(TypedArrayLayout::BUFFER_SLOT, ObjectValue(*arrayBuffer));
|
||||
InitArrayBufferViewDataPointer(&dvobj, arrayBuffer, byteOffset);
|
||||
JS_ASSERT(byteOffset + byteLength <= arrayBuffer->byteLength());
|
||||
|
||||
// Verify that the private slot is at the expected place
|
||||
JS_ASSERT(dvobj.numFixedSlots() == DATA_SLOT);
|
||||
JS_ASSERT(dvobj.numFixedSlots() == TypedArrayLayout::DATA_SLOT);
|
||||
|
||||
if (!arrayBuffer->addView(cx, &dvobj))
|
||||
return nullptr;
|
||||
|
@ -1722,7 +1722,7 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
|
|||
#define IMPL_TYPED_ARRAY_CLASS(_typedArray) \
|
||||
{ \
|
||||
#_typedArray, \
|
||||
JSCLASS_HAS_RESERVED_SLOTS(TypedArrayObject::RESERVED_SLOTS) | \
|
||||
JSCLASS_HAS_RESERVED_SLOTS(TypedArrayLayout::RESERVED_SLOTS) | \
|
||||
JSCLASS_HAS_PRIVATE | JSCLASS_IMPLEMENTS_BARRIERS | \
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_##_typedArray), \
|
||||
JS_PropertyStub, /* addProperty */ \
|
||||
|
@ -1736,7 +1736,7 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
|
|||
nullptr, /* call */ \
|
||||
nullptr, /* hasInstance */ \
|
||||
nullptr, /* construct */ \
|
||||
nullptr, /* trace */ \
|
||||
ArrayBufferViewObject::trace, /* trace */ \
|
||||
TYPED_ARRAY_CLASS_SPEC(_typedArray), \
|
||||
{ \
|
||||
nullptr, /* outerObject */ \
|
||||
|
@ -1895,7 +1895,7 @@ const Class DataViewObject::class_ = {
|
|||
nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
ArrayBufferViewObject::trace, /* trace */
|
||||
};
|
||||
|
||||
const JSFunctionSpec DataViewObject::jsfuncs[] = {
|
||||
|
@ -2003,8 +2003,8 @@ DataViewObject::initClass(JSContext *cx)
|
|||
void
|
||||
DataViewObject::neuter(void *newData)
|
||||
{
|
||||
setSlot(LENGTH_SLOT, Int32Value(0));
|
||||
setSlot(BYTEOFFSET_SLOT, Int32Value(0));
|
||||
setSlot(TypedArrayLayout::LENGTH_SLOT, Int32Value(0));
|
||||
setSlot(TypedArrayLayout::BYTEOFFSET_SLOT, Int32Value(0));
|
||||
setPrivate(newData);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,20 +69,14 @@ class TypedArrayLayout
|
|||
bool isNeuterable() const { return isNeuterable_; }
|
||||
const Class *addressOfFirstClass() const { return firstClass_; }
|
||||
const Class *addressOfMaxClass() const { return maxClass_; }
|
||||
|
||||
protected:
|
||||
static_assert(js::detail::TypedArrayLengthSlot == LENGTH_SLOT,
|
||||
"bad inlined constant in jsfriendapi.h");
|
||||
};
|
||||
|
||||
class TypedArrayObject : public ArrayBufferViewObject
|
||||
{
|
||||
protected:
|
||||
// Typed array properties stored in slots, beyond those shared by all
|
||||
// ArrayBufferViews.
|
||||
static const size_t DATA_SLOT = TypedArrayLayout::DATA_SLOT;
|
||||
|
||||
static const size_t RESERVED_SLOTS = TypedArrayLayout::RESERVED_SLOTS;
|
||||
|
||||
static_assert(js::detail::TypedArrayLengthSlot == LENGTH_SLOT,
|
||||
"bad inlined constant in jsfriendapi.h");
|
||||
|
||||
public:
|
||||
typedef TypedArrayObject AnyTypedArray;
|
||||
typedef ArrayBufferObject BufferType;
|
||||
|
@ -107,7 +101,7 @@ class TypedArrayObject : public ArrayBufferViewObject
|
|||
return &protoClasses[type];
|
||||
}
|
||||
|
||||
static const size_t FIXED_DATA_START = DATA_SLOT + 1;
|
||||
static const size_t FIXED_DATA_START = TypedArrayLayout::DATA_SLOT + 1;
|
||||
|
||||
// For typed arrays which can store their data inline, the array buffer
|
||||
// object is created lazily.
|
||||
|
@ -128,16 +122,16 @@ class TypedArrayObject : public ArrayBufferViewObject
|
|||
inline size_t bytesPerElement() const;
|
||||
|
||||
static Value bufferValue(TypedArrayObject *tarr) {
|
||||
return tarr->getFixedSlot(BUFFER_SLOT);
|
||||
return tarr->getFixedSlot(TypedArrayLayout::BUFFER_SLOT);
|
||||
}
|
||||
static Value byteOffsetValue(TypedArrayObject *tarr) {
|
||||
return tarr->getFixedSlot(BYTEOFFSET_SLOT);
|
||||
return tarr->getFixedSlot(TypedArrayLayout::BYTEOFFSET_SLOT);
|
||||
}
|
||||
static Value byteLengthValue(TypedArrayObject *tarr) {
|
||||
return Int32Value(tarr->getFixedSlot(LENGTH_SLOT).toInt32() * tarr->bytesPerElement());
|
||||
return Int32Value(tarr->getFixedSlot(TypedArrayLayout::LENGTH_SLOT).toInt32() * tarr->bytesPerElement());
|
||||
}
|
||||
static Value lengthValue(TypedArrayObject *tarr) {
|
||||
return tarr->getFixedSlot(LENGTH_SLOT);
|
||||
return tarr->getFixedSlot(TypedArrayLayout::LENGTH_SLOT);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -164,7 +158,7 @@ class TypedArrayObject : public ArrayBufferViewObject
|
|||
|
||||
void *viewData() const {
|
||||
// Keep synced with js::Get<Type>ArrayLengthAndData in jsfriendapi.h!
|
||||
return static_cast<void*>(getPrivate(DATA_SLOT));
|
||||
return static_cast<void*>(getPrivate(TypedArrayLayout::DATA_SLOT));
|
||||
}
|
||||
|
||||
Value getElement(uint32_t index);
|
||||
|
@ -339,19 +333,19 @@ class DataViewObject : public ArrayBufferViewObject
|
|||
static const Class class_;
|
||||
|
||||
static Value byteOffsetValue(DataViewObject *view) {
|
||||
Value v = view->getReservedSlot(BYTEOFFSET_SLOT);
|
||||
Value v = view->getReservedSlot(TypedArrayLayout::BYTEOFFSET_SLOT);
|
||||
JS_ASSERT(v.toInt32() >= 0);
|
||||
return v;
|
||||
}
|
||||
|
||||
static Value byteLengthValue(DataViewObject *view) {
|
||||
Value v = view->getReservedSlot(LENGTH_SLOT);
|
||||
Value v = view->getReservedSlot(TypedArrayLayout::LENGTH_SLOT);
|
||||
JS_ASSERT(v.toInt32() >= 0);
|
||||
return v;
|
||||
}
|
||||
|
||||
static Value bufferValue(DataViewObject *view) {
|
||||
return view->getReservedSlot(BUFFER_SLOT);
|
||||
return view->getReservedSlot(TypedArrayLayout::BUFFER_SLOT);
|
||||
}
|
||||
|
||||
uint32_t byteOffset() const {
|
||||
|
|
Загрузка…
Ссылка в новой задаче