Bug 1069680 - Restore array buffer view trace hook, clean up use of typed array layout constants, r=sfink.

This commit is contained in:
Brian Hackett 2014-09-23 15:45:24 -07:00
Родитель a495f0231b
Коммит 0eb54db50c
6 изменённых файлов: 68 добавлений и 52 удалений

Просмотреть файл

@ -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 {