mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Back out b80f97b00d2f (bug 979480), it's in the way of more immediately important work. r=backout
This commit is contained in:
parent
bd66f5b3ad
commit
398b26dd19
@ -3816,7 +3816,8 @@ nsXMLHttpRequestXPCOMifier::GetInterface(const nsIID & aIID, void **aResult)
|
|||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
ArrayBufferBuilder::ArrayBufferBuilder()
|
ArrayBufferBuilder::ArrayBufferBuilder()
|
||||||
: mDataPtr(nullptr),
|
: mRawContents(nullptr),
|
||||||
|
mDataPtr(nullptr),
|
||||||
mCapacity(0),
|
mCapacity(0),
|
||||||
mLength(0)
|
mLength(0)
|
||||||
{
|
{
|
||||||
@ -3830,22 +3831,20 @@ ArrayBufferBuilder::~ArrayBufferBuilder()
|
|||||||
void
|
void
|
||||||
ArrayBufferBuilder::reset()
|
ArrayBufferBuilder::reset()
|
||||||
{
|
{
|
||||||
if (mDataPtr) {
|
if (mRawContents) {
|
||||||
JS_free(nullptr, mDataPtr);
|
JS_free(nullptr, mRawContents);
|
||||||
}
|
}
|
||||||
mDataPtr = nullptr;
|
mRawContents = mDataPtr = nullptr;
|
||||||
mCapacity = mLength = 0;
|
mCapacity = mLength = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ArrayBufferBuilder::setCapacity(uint32_t aNewCap)
|
ArrayBufferBuilder::setCapacity(uint32_t aNewCap)
|
||||||
{
|
{
|
||||||
uint8_t *newdata = (uint8_t *) JS_ReallocateArrayBufferContents(nullptr, aNewCap, mDataPtr, mCapacity);
|
if (!JS_ReallocateArrayBufferContents(nullptr, aNewCap, &mRawContents, &mDataPtr)) {
|
||||||
if (!newdata) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDataPtr = newdata;
|
|
||||||
mCapacity = aNewCap;
|
mCapacity = aNewCap;
|
||||||
if (mLength > aNewCap) {
|
if (mLength > aNewCap) {
|
||||||
mLength = aNewCap;
|
mLength = aNewCap;
|
||||||
@ -3903,12 +3902,12 @@ ArrayBufferBuilder::getArrayBuffer(JSContext* aCx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSObject* obj = JS_NewArrayBufferWithContents(aCx, mLength, mDataPtr);
|
JSObject* obj = JS_NewArrayBufferWithContents(aCx, mRawContents);
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
mDataPtr = nullptr;
|
mRawContents = mDataPtr = nullptr;
|
||||||
mLength = mCapacity = 0;
|
mLength = mCapacity = 0;
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
|
@ -62,6 +62,7 @@ namespace mozilla {
|
|||||||
// or it can be reset explicitly at any point by calling reset().
|
// or it can be reset explicitly at any point by calling reset().
|
||||||
class ArrayBufferBuilder
|
class ArrayBufferBuilder
|
||||||
{
|
{
|
||||||
|
void* mRawContents;
|
||||||
uint8_t* mDataPtr;
|
uint8_t* mDataPtr;
|
||||||
uint32_t mCapacity;
|
uint32_t mCapacity;
|
||||||
uint32_t mLength;
|
uint32_t mLength;
|
||||||
|
@ -198,11 +198,12 @@ StealJSArrayDataIntoThreadSharedFloatArrayBufferList(JSContext* aJSContext,
|
|||||||
for (uint32_t i = 0; i < aJSArrays.Length(); ++i) {
|
for (uint32_t i = 0; i < aJSArrays.Length(); ++i) {
|
||||||
JS::Rooted<JSObject*> arrayBuffer(aJSContext,
|
JS::Rooted<JSObject*> arrayBuffer(aJSContext,
|
||||||
JS_GetArrayBufferViewBuffer(aJSArrays[i]));
|
JS_GetArrayBufferViewBuffer(aJSArrays[i]));
|
||||||
uint8_t* stolenData = arrayBuffer
|
void* dataToFree = nullptr;
|
||||||
? (uint8_t*) JS_StealArrayBufferContents(aJSContext, arrayBuffer)
|
uint8_t* stolenData = nullptr;
|
||||||
: nullptr;
|
if (arrayBuffer &&
|
||||||
if (stolenData) {
|
JS_StealArrayBufferContents(aJSContext, arrayBuffer, &dataToFree,
|
||||||
result->SetData(i, stolenData, reinterpret_cast<float*>(stolenData));
|
&stolenData)) {
|
||||||
|
result->SetData(i, dataToFree, reinterpret_cast<float*>(stolenData));
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1406,6 +1406,7 @@ TypedObject::createUnattachedWithClass(JSContext *cx,
|
|||||||
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_BYTELENGTH, Int32Value(0));
|
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_BYTELENGTH, Int32Value(0));
|
||||||
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_OWNER, NullValue());
|
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_OWNER, NullValue());
|
||||||
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_NEXT_VIEW, PrivateValue(nullptr));
|
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_NEXT_VIEW, PrivateValue(nullptr));
|
||||||
|
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_NEXT_BUFFER, PrivateValue(UNSET_BUFFER_LINK));
|
||||||
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_LENGTH, Int32Value(length));
|
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_LENGTH, Int32Value(length));
|
||||||
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR, ObjectValue(*type));
|
obj->initReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR, ObjectValue(*type));
|
||||||
|
|
||||||
@ -1507,7 +1508,7 @@ TypedObject::createZeroed(JSContext *cx,
|
|||||||
{
|
{
|
||||||
size_t totalSize = descr->as<SizedTypeDescr>().size();
|
size_t totalSize = descr->as<SizedTypeDescr>().size();
|
||||||
Rooted<ArrayBufferObject*> buffer(cx);
|
Rooted<ArrayBufferObject*> buffer(cx);
|
||||||
buffer = ArrayBufferObject::create(cx, totalSize);
|
buffer = ArrayBufferObject::create(cx, totalSize, false);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
typeRepr->asSized()->initInstance(cx->runtime(), buffer->dataPointer(), 1);
|
typeRepr->asSized()->initInstance(cx->runtime(), buffer->dataPointer(), 1);
|
||||||
@ -1528,7 +1529,7 @@ TypedObject::createZeroed(JSContext *cx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Rooted<ArrayBufferObject*> buffer(cx);
|
Rooted<ArrayBufferObject*> buffer(cx);
|
||||||
buffer = ArrayBufferObject::create(cx, totalSize);
|
buffer = ArrayBufferObject::create(cx, totalSize, false);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -1722,10 +1723,11 @@ TypedObject::obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index,
|
|||||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
|
PropertyOp getter, StrictPropertyOp setter, unsigned attrs)
|
||||||
{
|
{
|
||||||
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
|
||||||
Rooted<jsid> id(cx);
|
|
||||||
if (!IndexToId(cx, index, &id))
|
RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
|
||||||
|
if (!delegate)
|
||||||
return false;
|
return false;
|
||||||
return obj_defineGeneric(cx, obj, id, v, getter, setter, attrs);
|
return baseops::DefineElement(cx, delegate, index, v, getter, setter, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -109,14 +109,15 @@
|
|||||||
#define JS_TYPEDOBJ_SLOT_BYTELENGTH 1
|
#define JS_TYPEDOBJ_SLOT_BYTELENGTH 1
|
||||||
#define JS_TYPEDOBJ_SLOT_OWNER 2
|
#define JS_TYPEDOBJ_SLOT_OWNER 2
|
||||||
#define JS_TYPEDOBJ_SLOT_NEXT_VIEW 3
|
#define JS_TYPEDOBJ_SLOT_NEXT_VIEW 3
|
||||||
|
#define JS_TYPEDOBJ_SLOT_NEXT_BUFFER 4
|
||||||
|
|
||||||
#define JS_DATAVIEW_SLOTS 4 // Number of slots for data views
|
#define JS_DATAVIEW_SLOTS 5 // Number of slots for data views
|
||||||
|
|
||||||
#define JS_TYPEDOBJ_SLOT_LENGTH 4 // Length of array (see (*) below)
|
#define JS_TYPEDOBJ_SLOT_LENGTH 5 // Length of array (see (*) below)
|
||||||
#define JS_TYPEDOBJ_SLOT_TYPE_DESCR 5 // For typed objects, type descr
|
#define JS_TYPEDOBJ_SLOT_TYPE_DESCR 6 // For typed objects, type descr
|
||||||
|
|
||||||
#define JS_TYPEDOBJ_SLOT_DATA 7 // private slot, based on alloc kind
|
#define JS_TYPEDOBJ_SLOT_DATA 7 // private slot, based on alloc kind
|
||||||
#define JS_TYPEDOBJ_SLOTS 6 // Number of slots for typed objs
|
#define JS_TYPEDOBJ_SLOTS 7 // Number of slots for typed objs
|
||||||
|
|
||||||
// (*) The JS_TYPEDOBJ_SLOT_LENGTH slot stores the length for typed objects of
|
// (*) The JS_TYPEDOBJ_SLOT_LENGTH slot stores the length for typed objects of
|
||||||
// sized and unsized array type. The slot contains 0 for non-arrays.
|
// sized and unsized array type. The slot contains 0 for non-arrays.
|
||||||
|
@ -277,6 +277,24 @@ js::Nursery::notifyInitialSlots(Cell *cell, HeapSlot *slots)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
js::Nursery::notifyNewElements(gc::Cell *cell, ObjectElements *elements)
|
||||||
|
{
|
||||||
|
JS_ASSERT(!isInside(elements));
|
||||||
|
notifyInitialSlots(cell, reinterpret_cast<HeapSlot *>(elements));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
js::Nursery::notifyRemovedElements(gc::Cell *cell, ObjectElements *oldElements)
|
||||||
|
{
|
||||||
|
JS_ASSERT(cell);
|
||||||
|
JS_ASSERT(oldElements);
|
||||||
|
JS_ASSERT(!isInside(oldElements));
|
||||||
|
|
||||||
|
if (isInside(cell))
|
||||||
|
hugeSlots.remove(reinterpret_cast<HeapSlot *>(oldElements));
|
||||||
|
}
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
namespace gc {
|
namespace gc {
|
||||||
|
|
||||||
@ -601,6 +619,25 @@ js::Nursery::moveElementsToTenured(JSObject *dst, JSObject *src, AllocKind dstKi
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ArrayBuffer stores byte-length, not Value count. */
|
||||||
|
if (src->is<ArrayBufferObject>()) {
|
||||||
|
size_t nbytes;
|
||||||
|
if (src->hasDynamicElements()) {
|
||||||
|
nbytes = sizeof(ObjectElements) + srcHeader->initializedLength;
|
||||||
|
dstHeader = static_cast<ObjectElements *>(zone->malloc_(nbytes));
|
||||||
|
if (!dstHeader)
|
||||||
|
CrashAtUnhandlableOOM("Failed to allocate array buffer elements while tenuring.");
|
||||||
|
} else {
|
||||||
|
dst->setFixedElements();
|
||||||
|
nbytes = GetGCKindSlots(dst->tenuredGetAllocKind()) * sizeof(HeapSlot);
|
||||||
|
dstHeader = dst->getElementsHeader();
|
||||||
|
}
|
||||||
|
js_memcpy(dstHeader, srcHeader, nbytes);
|
||||||
|
setElementsForwardingPointer(srcHeader, dstHeader, nbytes / sizeof(HeapSlot));
|
||||||
|
dst->elements = dstHeader->elements();
|
||||||
|
return src->hasDynamicElements() ? nbytes : 0;
|
||||||
|
}
|
||||||
|
|
||||||
size_t nslots = ObjectElements::VALUES_PER_HEADER + srcHeader->capacity;
|
size_t nslots = ObjectElements::VALUES_PER_HEADER + srcHeader->capacity;
|
||||||
|
|
||||||
/* Unlike other objects, Arrays can have fixed elements. */
|
/* Unlike other objects, Arrays can have fixed elements. */
|
||||||
@ -746,7 +783,7 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList
|
|||||||
// Update the array buffer object's view lists.
|
// Update the array buffer object's view lists.
|
||||||
TIME_START(sweepArrayBufferViewList);
|
TIME_START(sweepArrayBufferViewList);
|
||||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
|
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
|
||||||
if (!c->gcLiveArrayBuffers.empty())
|
if (c->gcLiveArrayBuffers)
|
||||||
ArrayBufferObject::sweep(c);
|
ArrayBufferObject::sweep(c);
|
||||||
}
|
}
|
||||||
TIME_END(sweepArrayBufferViewList);
|
TIME_END(sweepArrayBufferViewList);
|
||||||
|
@ -104,6 +104,12 @@ class Nursery
|
|||||||
/* Add a slots to our tracking list if it is out-of-line. */
|
/* Add a slots to our tracking list if it is out-of-line. */
|
||||||
void notifyInitialSlots(gc::Cell *cell, HeapSlot *slots);
|
void notifyInitialSlots(gc::Cell *cell, HeapSlot *slots);
|
||||||
|
|
||||||
|
/* Add elements to our tracking list if it is out-of-line. */
|
||||||
|
void notifyNewElements(gc::Cell *cell, ObjectElements *elements);
|
||||||
|
|
||||||
|
/* Remove elements to our tracking list if it is out-of-line. */
|
||||||
|
void notifyRemovedElements(gc::Cell *cell, ObjectElements *oldElements);
|
||||||
|
|
||||||
typedef Vector<types::TypeObject *, 0, SystemAllocPolicy> TypeObjectList;
|
typedef Vector<types::TypeObject *, 0, SystemAllocPolicy> TypeObjectList;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -51,7 +51,8 @@ BEGIN_TEST(testArrayBuffer_bug720949_steal)
|
|||||||
CHECK_SAME(v, INT_TO_JSVAL(MAGIC_VALUE_2));
|
CHECK_SAME(v, INT_TO_JSVAL(MAGIC_VALUE_2));
|
||||||
|
|
||||||
// Steal the contents
|
// Steal the contents
|
||||||
void *contents = JS_StealArrayBufferContents(cx, obj);
|
void *contents;
|
||||||
|
CHECK(JS_StealArrayBufferContents(cx, obj, &contents, &data));
|
||||||
CHECK(contents != nullptr);
|
CHECK(contents != nullptr);
|
||||||
CHECK(data != nullptr);
|
CHECK(data != nullptr);
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ BEGIN_TEST(testArrayBuffer_bug720949_steal)
|
|||||||
CHECK_SAME(v, JSVAL_VOID);
|
CHECK_SAME(v, JSVAL_VOID);
|
||||||
|
|
||||||
// Transfer to a new ArrayBuffer
|
// Transfer to a new ArrayBuffer
|
||||||
JS::RootedObject dst(cx, JS_NewArrayBufferWithContents(cx, size, contents));
|
JS::RootedObject dst(cx, JS_NewArrayBufferWithContents(cx, contents));
|
||||||
CHECK(JS_IsArrayBufferObject(dst));
|
CHECK(JS_IsArrayBufferObject(dst));
|
||||||
data = JS_GetStableArrayBufferData(cx, obj);
|
data = JS_GetStableArrayBufferData(cx, obj);
|
||||||
|
|
||||||
@ -104,8 +105,11 @@ BEGIN_TEST(testArrayBuffer_bug720949_viewList)
|
|||||||
{
|
{
|
||||||
buffer = JS_NewArrayBuffer(cx, 2000);
|
buffer = JS_NewArrayBuffer(cx, 2000);
|
||||||
JS::RootedObject view(cx, JS_NewUint8ArrayWithBuffer(cx, buffer, 0, -1));
|
JS::RootedObject view(cx, JS_NewUint8ArrayWithBuffer(cx, buffer, 0, -1));
|
||||||
void *contents = JS_StealArrayBufferContents(cx, buffer);
|
void *contents;
|
||||||
|
uint8_t *data;
|
||||||
|
CHECK(JS_StealArrayBufferContents(cx, buffer, &contents, &data));
|
||||||
CHECK(contents != nullptr);
|
CHECK(contents != nullptr);
|
||||||
|
CHECK(data != nullptr);
|
||||||
JS_free(nullptr, contents);
|
JS_free(nullptr, contents);
|
||||||
GC(cx);
|
GC(cx);
|
||||||
CHECK(isNeutered(view));
|
CHECK(isNeutered(view));
|
||||||
@ -129,8 +133,11 @@ BEGIN_TEST(testArrayBuffer_bug720949_viewList)
|
|||||||
view2 = JS_NewUint8ArrayWithBuffer(cx, buffer, 1, 200);
|
view2 = JS_NewUint8ArrayWithBuffer(cx, buffer, 1, 200);
|
||||||
|
|
||||||
// Neuter
|
// Neuter
|
||||||
void *contents = JS_StealArrayBufferContents(cx, buffer);
|
void *contents;
|
||||||
|
uint8_t *data;
|
||||||
|
CHECK(JS_StealArrayBufferContents(cx, buffer, &contents, &data));
|
||||||
CHECK(contents != nullptr);
|
CHECK(contents != nullptr);
|
||||||
|
CHECK(data != nullptr);
|
||||||
JS_free(nullptr, contents);
|
JS_free(nullptr, contents);
|
||||||
|
|
||||||
CHECK(isNeutered(view1));
|
CHECK(isNeutered(view1));
|
||||||
|
@ -64,11 +64,11 @@ BEGIN_TEST(testMappedArrayBuffer_bug945152)
|
|||||||
JSObject *CreateNewObject(const int offset, const int length)
|
JSObject *CreateNewObject(const int offset, const int length)
|
||||||
{
|
{
|
||||||
int fd = open(test_filename, O_RDONLY);
|
int fd = open(test_filename, O_RDONLY);
|
||||||
|
void *ptr;
|
||||||
int new_fd;
|
int new_fd;
|
||||||
void *ptr = JS_CreateMappedArrayBufferContents(fd, &new_fd, offset, length);
|
if (!JS_CreateMappedArrayBufferContents(fd, &new_fd, offset, length, &ptr))
|
||||||
if (!ptr)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
JSObject *obj = JS_NewArrayBufferWithContents(cx, length, ptr, /* mapped = */ true);
|
JSObject *obj = JS_NewArrayBufferWithContents(cx, ptr);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
@ -109,9 +109,9 @@ bool TestCreateObject(const int offset, const int length)
|
|||||||
bool TestReleaseContents()
|
bool TestReleaseContents()
|
||||||
{
|
{
|
||||||
int fd = open(test_filename, O_RDONLY);
|
int fd = open(test_filename, O_RDONLY);
|
||||||
|
void *ptr;
|
||||||
int new_fd;
|
int new_fd;
|
||||||
void *ptr = JS_CreateMappedArrayBufferContents(fd, &new_fd, 0, 12);
|
if (!JS_CreateMappedArrayBufferContents(fd, &new_fd, 0, 12, &ptr))
|
||||||
if (!ptr)
|
|
||||||
return false;
|
return false;
|
||||||
CHECK(fd_is_valid(new_fd));
|
CHECK(fd_is_valid(new_fd));
|
||||||
JS_ReleaseMappedArrayBufferContents(new_fd, ptr, 12);
|
JS_ReleaseMappedArrayBufferContents(new_fd, ptr, 12);
|
||||||
|
@ -3119,39 +3119,47 @@ JS_PUBLIC_API(void)
|
|||||||
JS_SetAllNonReservedSlotsToUndefined(JSContext *cx, JSObject *objArg);
|
JS_SetAllNonReservedSlotsToUndefined(JSContext *cx, JSObject *objArg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new array buffer with the given contents. The new array buffer
|
* Create a new array buffer with the given contents, which must have been
|
||||||
* takes ownership: after calling this function, do not free |contents| or use
|
* returned by JS_AllocateArrayBufferContents or JS_StealArrayBufferContents.
|
||||||
* |contents| from another thread. |mapped| indicates whether the contents were
|
* The new array buffer takes ownership. After calling this function, do not
|
||||||
* created using JS_CreateMappedArrayBufferContents.
|
* free |contents| or use |contents| from another thread.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API(JSObject *)
|
extern JS_PUBLIC_API(JSObject *)
|
||||||
JS_NewArrayBufferWithContents(JSContext *cx, size_t nbytes, void *contents, bool mapped = false);
|
JS_NewArrayBufferWithContents(JSContext *cx, void *contents);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Steal the contents of the given array buffer. The array buffer has its
|
* Steal the contents of the given array buffer. The array buffer has its
|
||||||
* length set to 0 and its contents array cleared. The caller takes ownership
|
* length set to 0 and its contents array cleared. The caller takes ownership
|
||||||
* of the return value and must free it or transfer ownership via
|
* of |*contents| and must free it or transfer ownership via
|
||||||
* JS_NewArrayBufferWithContents when done using it.
|
* JS_NewArrayBufferWithContents when done using it.
|
||||||
|
* To free |*contents|, call free().
|
||||||
|
* A pointer to the buffer's data is returned in |*data|. This pointer can
|
||||||
|
* be used until |*contents| is freed or has its ownership transferred.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API(void *)
|
extern JS_PUBLIC_API(bool)
|
||||||
JS_StealArrayBufferContents(JSContext *cx, JS::HandleObject obj);
|
JS_StealArrayBufferContents(JSContext *cx, JS::HandleObject obj, void **contents, uint8_t **data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate memory that may be eventually passed to
|
* Allocate memory that may be eventually passed to
|
||||||
* JS_NewArrayBufferWithContents. |maybecx| is optional; if a non-nullptr cx is
|
* JS_NewArrayBufferWithContents. |maybecx| is optional; if a non-nullptr cx is
|
||||||
* given, it will be used for memory accounting and OOM reporting. |nbytes| is
|
* given, it will be used for memory accounting and OOM reporting. |nbytes| is
|
||||||
* the number of payload bytes required.
|
* the number of payload bytes required. The pointer to pass to
|
||||||
|
* JS_NewArrayBufferWithContents is returned in |contents|. The pointer to the
|
||||||
|
* |nbytes| of usable memory is returned in |data|. (*|contents| will contain a
|
||||||
|
* header before |data|.) The only legal operations on *|contents| are to pass
|
||||||
|
* it to either JS_NewArrayBufferWithContents or
|
||||||
|
* JS_ReallocateArrayBufferContents, or free it with js_free or JS_free.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API(void *)
|
extern JS_PUBLIC_API(bool)
|
||||||
JS_AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes);
|
JS_AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void **contents, uint8_t **data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Reallocate memory allocated by JS_AllocateArrayBufferContents, growing or
|
* Reallocate memory allocated by JS_AllocateArrayBufferContents, growing or
|
||||||
* shrinking it as appropriate. If oldContents is null then this behaves like
|
* shrinking it as appropriate. The new data pointer will be returned in data.
|
||||||
* JS_AllocateArrayBufferContents.
|
* If *contents is nullptr, behaves like JS_AllocateArrayBufferContents.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API(void *)
|
extern JS_PUBLIC_API(bool)
|
||||||
JS_ReallocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void *oldContents, uint32_t oldNbytes);
|
JS_ReallocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void **contents, uint8_t **data);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create memory mapped array buffer contents.
|
* Create memory mapped array buffer contents.
|
||||||
@ -3159,8 +3167,9 @@ JS_ReallocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void *oldConten
|
|||||||
* take care of closing fd after calling this function.
|
* take care of closing fd after calling this function.
|
||||||
* A new duplicated fd used by the mapping is returned in new_fd.
|
* A new duplicated fd used by the mapping is returned in new_fd.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API(void *)
|
extern JS_PUBLIC_API(bool)
|
||||||
JS_CreateMappedArrayBufferContents(int fd, int *new_fd, size_t offset, size_t length);
|
JS_CreateMappedArrayBufferContents(int fd, int *new_fd, size_t offset,
|
||||||
|
size_t length, void **contents);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Release the allocated resource of mapped array buffer contents before the
|
* Release the allocated resource of mapped array buffer contents before the
|
||||||
|
@ -58,6 +58,7 @@ JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options =
|
|||||||
propertyTree(thisForCtor()),
|
propertyTree(thisForCtor()),
|
||||||
selfHostingScriptSource(nullptr),
|
selfHostingScriptSource(nullptr),
|
||||||
gcIncomingGrayPointers(nullptr),
|
gcIncomingGrayPointers(nullptr),
|
||||||
|
gcLiveArrayBuffers(nullptr),
|
||||||
gcWeakMapList(nullptr),
|
gcWeakMapList(nullptr),
|
||||||
debugModeBits(runtime_->debugMode ? DebugFromC : 0),
|
debugModeBits(runtime_->debugMode ? DebugFromC : 0),
|
||||||
rngState(0),
|
rngState(0),
|
||||||
|
@ -280,8 +280,8 @@ struct JSCompartment
|
|||||||
*/
|
*/
|
||||||
JSObject *gcIncomingGrayPointers;
|
JSObject *gcIncomingGrayPointers;
|
||||||
|
|
||||||
/* During GC, list of live array buffers with >1 view accumulated during tracing. */
|
/* Linked list of live array buffers with >1 view. */
|
||||||
js::ArrayBufferVector gcLiveArrayBuffers;
|
js::ArrayBufferObject *gcLiveArrayBuffers;
|
||||||
|
|
||||||
/* Linked list of live weakmaps in this compartment. */
|
/* Linked list of live weakmaps in this compartment. */
|
||||||
js::WeakMapBase *gcWeakMapList;
|
js::WeakMapBase *gcWeakMapList;
|
||||||
|
@ -3001,7 +3001,7 @@ BeginMarkPhase(JSRuntime *rt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
|
for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
|
||||||
JS_ASSERT(c->gcLiveArrayBuffers.empty());
|
JS_ASSERT(!c->gcLiveArrayBuffers);
|
||||||
c->marked = false;
|
c->marked = false;
|
||||||
if (ShouldPreserveJITCode(c, currentTime))
|
if (ShouldPreserveJITCode(c, currentTime))
|
||||||
c->zone()->setPreservingCode(true);
|
c->zone()->setPreservingCode(true);
|
||||||
@ -4253,7 +4253,7 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool lastGC)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
|
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
|
||||||
JS_ASSERT(!c->gcIncomingGrayPointers);
|
JS_ASSERT(!c->gcIncomingGrayPointers);
|
||||||
JS_ASSERT(c->gcLiveArrayBuffers.empty());
|
JS_ASSERT(!c->gcLiveArrayBuffers);
|
||||||
|
|
||||||
for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
|
for (JSCompartment::WrapperEnum e(c); !e.empty(); e.popFront()) {
|
||||||
if (e.front().key().kind != CrossCompartmentKey::StringWrapper)
|
if (e.front().key().kind != CrossCompartmentKey::StringWrapper)
|
||||||
@ -4468,7 +4468,7 @@ ResetIncrementalGC(JSRuntime *rt, const char *reason)
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
|
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next())
|
||||||
JS_ASSERT(c->gcLiveArrayBuffers.empty());
|
JS_ASSERT(!c->gcLiveArrayBuffers);
|
||||||
|
|
||||||
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) {
|
||||||
JS_ASSERT(!zone->needsBarrier());
|
JS_ASSERT(!zone->needsBarrier());
|
||||||
|
@ -5900,8 +5900,20 @@ JSObject::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::Objects
|
|||||||
|
|
||||||
if (hasDynamicElements()) {
|
if (hasDynamicElements()) {
|
||||||
js::ObjectElements *elements = getElementsHeader();
|
js::ObjectElements *elements = getElementsHeader();
|
||||||
|
if (MOZ_UNLIKELY(elements->isAsmJSArrayBuffer())) {
|
||||||
|
#if defined (JS_CPU_X64)
|
||||||
|
// On x64, ArrayBufferObject::prepareForAsmJS switches the
|
||||||
|
// ArrayBufferObject to use mmap'd storage.
|
||||||
|
sizes->nonHeapElementsAsmJS += as<ArrayBufferObject>().byteLength();
|
||||||
|
#else
|
||||||
|
sizes->mallocHeapElementsAsmJS += mallocSizeOf(elements);
|
||||||
|
#endif
|
||||||
|
} else if (MOZ_UNLIKELY(elements->isMappedArrayBuffer())) {
|
||||||
|
sizes->nonHeapElementsMapped += as<ArrayBufferObject>().byteLength();
|
||||||
|
} else {
|
||||||
sizes->mallocHeapElementsNonAsmJS += mallocSizeOf(elements);
|
sizes->mallocHeapElementsNonAsmJS += mallocSizeOf(elements);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Other things may be measured in the future if DMD indicates it is worthwhile.
|
// Other things may be measured in the future if DMD indicates it is worthwhile.
|
||||||
if (is<JSFunction>() ||
|
if (is<JSFunction>() ||
|
||||||
@ -5927,8 +5939,6 @@ JSObject::addSizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::Objects
|
|||||||
sizes->mallocHeapRegExpStatics += as<RegExpStaticsObject>().sizeOfData(mallocSizeOf);
|
sizes->mallocHeapRegExpStatics += as<RegExpStaticsObject>().sizeOfData(mallocSizeOf);
|
||||||
} else if (is<PropertyIteratorObject>()) {
|
} else if (is<PropertyIteratorObject>()) {
|
||||||
sizes->mallocHeapPropertyIteratorData += as<PropertyIteratorObject>().sizeOfMisc(mallocSizeOf);
|
sizes->mallocHeapPropertyIteratorData += as<PropertyIteratorObject>().sizeOfMisc(mallocSizeOf);
|
||||||
} else if (is<ArrayBufferObject>() || is<SharedArrayBufferObject>()) {
|
|
||||||
ArrayBufferObject::addSizeOfExcludingThis(this, mallocSizeOf, sizes);
|
|
||||||
#ifdef JS_ION
|
#ifdef JS_ION
|
||||||
} else if (is<AsmJSModuleObject>()) {
|
} else if (is<AsmJSModuleObject>()) {
|
||||||
as<AsmJSModuleObject>().addSizeOfMisc(mallocSizeOf, &sizes->nonHeapCodeAsmJS,
|
as<AsmJSModuleObject>().addSizeOfMisc(mallocSizeOf, &sizes->nonHeapCodeAsmJS,
|
||||||
|
@ -527,7 +527,7 @@ JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::Initi
|
|||||||
obj->privateRef(shape->numFixedSlots()) = nullptr;
|
obj->privateRef(shape->numFixedSlots()) = nullptr;
|
||||||
|
|
||||||
size_t span = shape->slotSpan();
|
size_t span = shape->slotSpan();
|
||||||
if (span)
|
if (span && clasp != &js::ArrayBufferObject::class_)
|
||||||
obj->initializeSlotRange(0, span);
|
obj->initializeSlotRange(0, span);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
@ -573,9 +573,13 @@ JSObject::finish(js::FreeOp *fop)
|
|||||||
{
|
{
|
||||||
if (hasDynamicSlots())
|
if (hasDynamicSlots())
|
||||||
fop->free_(slots);
|
fop->free_(slots);
|
||||||
|
|
||||||
if (hasDynamicElements()) {
|
if (hasDynamicElements()) {
|
||||||
js::ObjectElements *elements = getElementsHeader();
|
js::ObjectElements *elements = getElementsHeader();
|
||||||
|
if (MOZ_UNLIKELY(elements->isAsmJSArrayBuffer()))
|
||||||
|
js::ArrayBufferObject::releaseAsmJSArrayBuffer(fop, this);
|
||||||
|
else if (MOZ_UNLIKELY(elements->isMappedArrayBuffer()))
|
||||||
|
js::ArrayBufferObject::releaseMappedArrayBuffer(fop, this);
|
||||||
|
else
|
||||||
fop->free_(elements);
|
fop->free_(elements);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -939,17 +943,6 @@ NewBuiltinClassInstance(ExclusiveContext *cx, NewObjectKind newKind = GenericObj
|
|||||||
return &obj->as<T>();
|
return &obj->as<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
inline T *
|
|
||||||
NewBuiltinClassInstance(ExclusiveContext *cx, gc::AllocKind allocKind, NewObjectKind newKind = GenericObject)
|
|
||||||
{
|
|
||||||
JSObject *obj = NewBuiltinClassInstance(cx, &T::class_, allocKind, newKind);
|
|
||||||
if (!obj)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return &obj->as<T>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to optimize calls to (new Object())
|
// Used to optimize calls to (new Object())
|
||||||
bool
|
bool
|
||||||
NewObjectScriptedCall(JSContext *cx, MutableHandleObject obj);
|
NewObjectScriptedCall(JSContext *cx, MutableHandleObject obj);
|
||||||
|
@ -1025,6 +1025,7 @@ CacheEntry_setBytecode(JSContext *cx, HandleObject cache, uint8_t *buffer, uint3
|
|||||||
if (!arrayBuffer || !ArrayBufferObject::ensureNonInline(cx, arrayBuffer))
|
if (!arrayBuffer || !ArrayBufferObject::ensureNonInline(cx, arrayBuffer))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
memcpy(arrayBuffer->dataPointer(), buffer, length);
|
||||||
SetReservedSlot(cache, CacheEntry_BYTECODE, OBJECT_TO_JSVAL(arrayBuffer));
|
SetReservedSlot(cache, CacheEntry_BYTECODE, OBJECT_TO_JSVAL(arrayBuffer));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1283,8 +1284,6 @@ Evaluate(JSContext *cx, unsigned argc, jsval *vp)
|
|||||||
|
|
||||||
if (!CacheEntry_setBytecode(cx, cacheEntry, saveBuffer, saveLength))
|
if (!CacheEntry_setBytecode(cx, cacheEntry, saveBuffer, saveLength))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
saveBuffer.forget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return JS_WrapValue(cx, args.rval());
|
return JS_WrapValue(cx, args.rval());
|
||||||
@ -6221,11 +6220,6 @@ main(int argc, char **argv, char **envp)
|
|||||||
PR_JoinThread(workerThreads[i]);
|
PR_JoinThread(workerThreads[i]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef JSGC_GENERATIONAL
|
|
||||||
if (!noggc.empty())
|
|
||||||
noggc.destroy();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
JS_DestroyRuntime(rt);
|
JS_DestroyRuntime(rt);
|
||||||
JS_ShutDown();
|
JS_ShutDown();
|
||||||
return result;
|
return result;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -23,11 +23,6 @@ struct MappingInfoHeader
|
|||||||
{
|
{
|
||||||
uint32_t fd;
|
uint32_t fd;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
|
|
||||||
void init(uint32_t fd, uint32_t offset) {
|
|
||||||
this->fd = fd;
|
|
||||||
this->offset = offset;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// The inheritance hierarchy for the various classes relating to typed arrays
|
// The inheritance hierarchy for the various classes relating to typed arrays
|
||||||
@ -65,13 +60,6 @@ class ArrayBufferObject : public JSObject
|
|||||||
static bool fun_slice_impl(JSContext *cx, CallArgs args);
|
static bool fun_slice_impl(JSContext *cx, CallArgs args);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const uint8_t DATA_SLOT = 0;
|
|
||||||
static const uint8_t BYTE_LENGTH_SLOT = 1;
|
|
||||||
static const uint8_t VIEW_LIST_SLOT = 2;
|
|
||||||
static const uint8_t FLAGS_SLOT = 3;
|
|
||||||
|
|
||||||
static const uint8_t RESERVED_SLOTS = 4;
|
|
||||||
|
|
||||||
static const Class class_;
|
static const Class class_;
|
||||||
|
|
||||||
static const Class protoClass;
|
static const Class protoClass;
|
||||||
@ -86,9 +74,8 @@ class ArrayBufferObject : public JSObject
|
|||||||
|
|
||||||
static bool class_constructor(JSContext *cx, unsigned argc, Value *vp);
|
static bool class_constructor(JSContext *cx, unsigned argc, Value *vp);
|
||||||
|
|
||||||
static ArrayBufferObject *create(JSContext *cx, uint32_t nbytes, void *contents = nullptr,
|
static ArrayBufferObject *create(JSContext *cx, uint32_t nbytes, bool clear = true,
|
||||||
NewObjectKind newKind = GenericObject,
|
NewObjectKind newKind = GenericObject);
|
||||||
bool mapped = false);
|
|
||||||
|
|
||||||
static JSObject *createSlice(JSContext *cx, Handle<ArrayBufferObject*> arrayBuffer,
|
static JSObject *createSlice(JSContext *cx, Handle<ArrayBufferObject*> arrayBuffer,
|
||||||
uint32_t begin, uint32_t end);
|
uint32_t begin, uint32_t end);
|
||||||
@ -104,28 +91,106 @@ class ArrayBufferObject : public JSObject
|
|||||||
|
|
||||||
static void obj_trace(JSTracer *trc, JSObject *obj);
|
static void obj_trace(JSTracer *trc, JSObject *obj);
|
||||||
|
|
||||||
|
static bool obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||||
|
MutableHandleObject objp, MutableHandleShape propp);
|
||||||
|
static bool obj_lookupProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||||
|
MutableHandleObject objp, MutableHandleShape propp);
|
||||||
|
static bool obj_lookupElement(JSContext *cx, HandleObject obj, uint32_t index,
|
||||||
|
MutableHandleObject objp, MutableHandleShape propp);
|
||||||
|
|
||||||
|
static bool obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
|
||||||
|
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||||
|
static bool obj_defineProperty(JSContext *cx, HandleObject obj,
|
||||||
|
HandlePropertyName name, HandleValue v,
|
||||||
|
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||||
|
static bool obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v,
|
||||||
|
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||||
|
|
||||||
|
static bool obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||||
|
HandleId id, MutableHandleValue vp);
|
||||||
|
static bool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||||
|
HandlePropertyName name, MutableHandleValue vp);
|
||||||
|
static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
|
||||||
|
uint32_t index, MutableHandleValue vp);
|
||||||
|
|
||||||
|
static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
|
||||||
|
MutableHandleValue vp, bool strict);
|
||||||
|
static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||||
|
MutableHandleValue vp, bool strict);
|
||||||
|
static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
|
||||||
|
MutableHandleValue vp, bool strict);
|
||||||
|
|
||||||
|
static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
|
||||||
|
HandleId id, unsigned *attrsp);
|
||||||
|
static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
|
||||||
|
HandleId id, unsigned *attrsp);
|
||||||
|
|
||||||
|
static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||||
|
bool *succeeded);
|
||||||
|
static bool obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
|
||||||
|
bool *succeeded);
|
||||||
|
|
||||||
|
static bool obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
|
||||||
|
MutableHandleValue statep, MutableHandleId idp);
|
||||||
|
|
||||||
static void sweep(JSCompartment *rt);
|
static void sweep(JSCompartment *rt);
|
||||||
|
|
||||||
static void resetArrayBufferList(JSCompartment *rt);
|
static void resetArrayBufferList(JSCompartment *rt);
|
||||||
static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
|
static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
|
||||||
static void restoreArrayBufferLists(ArrayBufferVector &vector);
|
static void restoreArrayBufferLists(ArrayBufferVector &vector);
|
||||||
|
|
||||||
static void *stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffer);
|
static bool stealContents(JSContext *cx, Handle<ArrayBufferObject*> buffer, void **contents,
|
||||||
|
uint8_t **data);
|
||||||
|
|
||||||
static void addSizeOfExcludingThis(JSObject *obj, mozilla::MallocSizeOf mallocSizeOf,
|
static void updateElementsHeader(js::ObjectElements *header, uint32_t bytes) {
|
||||||
JS::ObjectsExtraSizes *sizes);
|
header->initializedLength = bytes;
|
||||||
|
|
||||||
MappingInfoHeader *getMappingInfoHeader() const {
|
// NB: one or both of these fields is clobbered by GetViewList to store
|
||||||
JS_ASSERT(isMappedArrayBuffer());
|
// the 'views' link. Set them to 0 to effectively initialize 'views'
|
||||||
return reinterpret_cast<MappingInfoHeader *>(dataPointer() - sizeof(MappingInfoHeader));
|
// to nullptr.
|
||||||
|
header->length = 0;
|
||||||
|
header->capacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getMappingFD() const { return getMappingInfoHeader()->fd; }
|
static void initElementsHeader(js::ObjectElements *header, uint32_t bytes) {
|
||||||
uint32_t getMappingOffset() const { return getMappingInfoHeader()->offset; }
|
header->flags = 0;
|
||||||
|
updateElementsHeader(header, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initMappedElementsHeader(js::ObjectElements *header, uint32_t fd,
|
||||||
|
uint32_t offset, uint32_t bytes) {
|
||||||
|
initElementsHeader(header, bytes);
|
||||||
|
header->setIsMappedArrayBuffer();
|
||||||
|
MappingInfoHeader *mh = getMappingInfoHeader(header);
|
||||||
|
mh->fd = fd;
|
||||||
|
mh->offset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static MappingInfoHeader *getMappingInfoHeader(js::ObjectElements *header) {
|
||||||
|
MOZ_ASSERT(header->isMappedArrayBuffer());
|
||||||
|
return reinterpret_cast<MappingInfoHeader *>(uintptr_t(header) -
|
||||||
|
sizeof(MappingInfoHeader));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getMappingFD() {
|
||||||
|
MOZ_ASSERT(getElementsHeader()->isMappedArrayBuffer());
|
||||||
|
MappingInfoHeader *mh = getMappingInfoHeader(getElementsHeader());
|
||||||
|
return mh->fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t getMappingOffset() const {
|
||||||
|
MOZ_ASSERT(getElementsHeader()->isMappedArrayBuffer());
|
||||||
|
MappingInfoHeader *mh = getMappingInfoHeader(getElementsHeader());
|
||||||
|
return mh->offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t headerInitializedLength(const js::ObjectElements *header) {
|
||||||
|
return header->initializedLength;
|
||||||
|
}
|
||||||
|
|
||||||
void addView(ArrayBufferViewObject *view);
|
void addView(ArrayBufferViewObject *view);
|
||||||
|
|
||||||
void changeContents(JSContext *cx, void *newData);
|
void changeContents(JSContext *cx, ObjectElements *newHeader);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure data is not stored inline in the object. Used when handing back a
|
* Ensure data is not stored inline in the object. Used when handing back a
|
||||||
@ -133,15 +198,22 @@ class ArrayBufferObject : public JSObject
|
|||||||
*/
|
*/
|
||||||
static bool ensureNonInline(JSContext *cx, Handle<ArrayBufferObject*> buffer);
|
static bool ensureNonInline(JSContext *cx, Handle<ArrayBufferObject*> buffer);
|
||||||
|
|
||||||
bool canNeuter(JSContext *cx);
|
uint32_t byteLength() const {
|
||||||
|
return getElementsHeader()->initializedLength;
|
||||||
|
}
|
||||||
|
|
||||||
/* Neuter this buffer and all its views. */
|
/*
|
||||||
static void neuter(JSContext *cx, Handle<ArrayBufferObject*> buffer);
|
* Neuter all views of an ArrayBuffer.
|
||||||
|
*/
|
||||||
|
static bool neuterViews(JSContext *cx, Handle<ArrayBufferObject*> buffer);
|
||||||
|
|
||||||
uint8_t * dataPointer() const;
|
uint8_t * dataPointer() const;
|
||||||
size_t byteLength() const;
|
|
||||||
|
|
||||||
void releaseData(FreeOp *fop);
|
/*
|
||||||
|
* Discard the ArrayBuffer contents. For asm.js buffers, at least, should
|
||||||
|
* be called after neuterViews().
|
||||||
|
*/
|
||||||
|
void neuter(JSContext *cx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the arrayBuffer contains any data. This will return false for
|
* Check if the arrayBuffer contains any data. This will return false for
|
||||||
@ -151,74 +223,28 @@ class ArrayBufferObject : public JSObject
|
|||||||
return getClass() == &class_;
|
return getClass() == &class_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isAsmJSArrayBuffer() const { return flags() & ASMJS_BUFFER; }
|
bool isSharedArrayBuffer() const {
|
||||||
bool isSharedArrayBuffer() const { return flags() & SHARED_BUFFER; }
|
return getElementsHeader()->isSharedArrayBuffer();
|
||||||
bool isMappedArrayBuffer() const { return flags() & MAPPED_BUFFER; }
|
}
|
||||||
bool isNeutered() const { return flags() & NEUTERED_BUFFER; }
|
|
||||||
|
|
||||||
|
bool isAsmJSArrayBuffer() const {
|
||||||
|
return getElementsHeader()->isAsmJSArrayBuffer();
|
||||||
|
}
|
||||||
|
bool isNeutered() const {
|
||||||
|
return getElementsHeader()->isNeuteredBuffer();
|
||||||
|
}
|
||||||
static bool prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buffer);
|
static bool prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buffer);
|
||||||
static bool canNeuterAsmJSArrayBuffer(JSContext *cx, ArrayBufferObject &buffer);
|
static bool neuterAsmJSArrayBuffer(JSContext *cx, ArrayBufferObject &buffer);
|
||||||
|
static void releaseAsmJSArrayBuffer(FreeOp *fop, JSObject *obj);
|
||||||
static void finalize(FreeOp *fop, JSObject *obj);
|
|
||||||
|
|
||||||
|
bool isMappedArrayBuffer() const {
|
||||||
|
return getElementsHeader()->isMappedArrayBuffer();
|
||||||
|
}
|
||||||
|
void setIsMappedArrayBuffer() {
|
||||||
|
getElementsHeader()->setIsMappedArrayBuffer();
|
||||||
|
}
|
||||||
static void *createMappedArrayBuffer(int fd, int *new_fd, size_t offset, size_t length);
|
static void *createMappedArrayBuffer(int fd, int *new_fd, size_t offset, size_t length);
|
||||||
|
static void releaseMappedArrayBuffer(FreeOp *fop, JSObject *obj);
|
||||||
protected:
|
|
||||||
enum OwnsState {
|
|
||||||
DoesntOwnData = 0,
|
|
||||||
OwnsData = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
void setDataPointer(void *data, OwnsState ownsState);
|
|
||||||
void setByteLength(size_t length);
|
|
||||||
|
|
||||||
ArrayBufferViewObject *viewList() const;
|
|
||||||
void setViewList(ArrayBufferViewObject *viewsHead);
|
|
||||||
void setViewListNoBarrier(ArrayBufferViewObject *viewsHead);
|
|
||||||
|
|
||||||
enum ArrayBufferFlags {
|
|
||||||
// In the gcLiveArrayBuffers list.
|
|
||||||
IN_LIVE_LIST = 0x1,
|
|
||||||
|
|
||||||
// The dataPointer() is owned by this buffer and should be released
|
|
||||||
// when no longer in use. Releasing the pointer may be done by either
|
|
||||||
// freeing or unmapping it, and how to do this is determined by the
|
|
||||||
// buffer's other flags (e.g. ASMJS_BUFFER and MAPPED_BUFFER).
|
|
||||||
OWNS_DATA = 0x2,
|
|
||||||
|
|
||||||
ASMJS_BUFFER = 0x4,
|
|
||||||
SHARED_BUFFER = 0x8,
|
|
||||||
MAPPED_BUFFER = 0x10,
|
|
||||||
NEUTERED_BUFFER = 0x20
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t flags() const;
|
|
||||||
void setFlags(uint32_t flags);
|
|
||||||
|
|
||||||
bool inLiveList() const { return flags() & IN_LIVE_LIST; }
|
|
||||||
void setInLiveList(bool value) {
|
|
||||||
setFlags(value ? (flags() | IN_LIVE_LIST) : (flags() & ~IN_LIVE_LIST));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ownsData() const { return flags() & OWNS_DATA; }
|
|
||||||
void setOwnsData(OwnsState owns) {
|
|
||||||
setFlags(owns ? (flags() | OWNS_DATA) : (flags() & ~OWNS_DATA));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setIsAsmJSArrayBuffer() { setFlags(flags() | ASMJS_BUFFER); }
|
|
||||||
void setIsSharedArrayBuffer() { setFlags(flags() | SHARED_BUFFER); }
|
|
||||||
void setIsMappedArrayBuffer() { setFlags(flags() | MAPPED_BUFFER); }
|
|
||||||
void setIsNeutered() { setFlags(flags() | NEUTERED_BUFFER); }
|
|
||||||
|
|
||||||
void initialize(size_t byteLength, void *data, OwnsState ownsState) {
|
|
||||||
setByteLength(byteLength);
|
|
||||||
setFlags(0);
|
|
||||||
setViewListNoBarrier(nullptr);
|
|
||||||
setDataPointer(data, ownsState);
|
|
||||||
}
|
|
||||||
|
|
||||||
void releaseAsmJSArray(FreeOp *fop);
|
|
||||||
void releaseMappedArray();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -242,24 +268,35 @@ class ArrayBufferViewObject : public JSObject
|
|||||||
/* ArrayBufferObjects point to a linked list of views, chained through this slot */
|
/* ArrayBufferObjects point to a linked list of views, chained through this slot */
|
||||||
static const size_t NEXT_VIEW_SLOT = JS_TYPEDOBJ_SLOT_NEXT_VIEW;
|
static const size_t NEXT_VIEW_SLOT = JS_TYPEDOBJ_SLOT_NEXT_VIEW;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When ArrayBufferObjects are traced during GC, they construct a linked
|
||||||
|
* list of ArrayBufferObjects with more than one view, chained through this
|
||||||
|
* slot of the first view of each ArrayBufferObject.
|
||||||
|
*/
|
||||||
|
static const size_t NEXT_BUFFER_SLOT = JS_TYPEDOBJ_SLOT_NEXT_BUFFER;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
JSObject *bufferObject() const {
|
JSObject *bufferObject() const {
|
||||||
return &getFixedSlot(BUFFER_SLOT).toObject();
|
return &getFixedSlot(BUFFER_SLOT).toObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ArrayBufferObject *bufferLink() {
|
||||||
|
return static_cast<ArrayBufferObject*>(getFixedSlot(NEXT_BUFFER_SLOT).toPrivate());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setBufferLink(ArrayBufferObject *buffer);
|
||||||
|
|
||||||
ArrayBufferViewObject *nextView() const {
|
ArrayBufferViewObject *nextView() const {
|
||||||
return static_cast<ArrayBufferViewObject*>(getFixedSlot(NEXT_VIEW_SLOT).toPrivate());
|
return static_cast<ArrayBufferViewObject*>(getFixedSlot(NEXT_VIEW_SLOT).toPrivate());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setNextView(ArrayBufferViewObject *view);
|
inline void setNextView(ArrayBufferViewObject *view);
|
||||||
|
|
||||||
|
void prependToViews(ArrayBufferViewObject *viewsHead);
|
||||||
|
|
||||||
void neuter(JSContext *cx);
|
void neuter(JSContext *cx);
|
||||||
|
|
||||||
static void trace(JSTracer *trc, JSObject *obj);
|
static void trace(JSTracer *trc, JSObject *obj);
|
||||||
|
|
||||||
uint8_t *dataPointer() {
|
|
||||||
return static_cast<uint8_t *>(getPrivate());
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -298,6 +335,13 @@ bool IsArrayBuffer(JSObject *obj);
|
|||||||
ArrayBufferObject &AsArrayBuffer(HandleObject obj);
|
ArrayBufferObject &AsArrayBuffer(HandleObject obj);
|
||||||
ArrayBufferObject &AsArrayBuffer(JSObject *obj);
|
ArrayBufferObject &AsArrayBuffer(JSObject *obj);
|
||||||
|
|
||||||
|
inline void
|
||||||
|
ArrayBufferViewObject::setBufferLink(ArrayBufferObject *buffer)
|
||||||
|
{
|
||||||
|
setFixedSlot(NEXT_BUFFER_SLOT, PrivateValue(buffer));
|
||||||
|
PostBarrierTypedArrayObject(this);
|
||||||
|
}
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
ArrayBufferViewObject::setNextView(ArrayBufferViewObject *view)
|
ArrayBufferViewObject::setNextView(ArrayBufferViewObject *view)
|
||||||
{
|
{
|
||||||
|
@ -383,6 +383,20 @@ js::ObjectImpl::markChildren(JSTracer *trc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSObject *
|
||||||
|
js::ArrayBufferDelegate(JSContext *cx, Handle<ObjectImpl*> obj)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(obj->hasClass(&ArrayBufferObject::class_) ||
|
||||||
|
obj->hasClass(&SharedArrayBufferObject::class_));
|
||||||
|
|
||||||
|
if (obj->getPrivate())
|
||||||
|
return static_cast<JSObject *>(obj->getPrivate());
|
||||||
|
JSObject *delegate = NewObjectWithGivenProto(cx, &JSObject::class_,
|
||||||
|
obj->getTaggedProto(), nullptr);
|
||||||
|
obj->setPrivateGCThing(delegate);
|
||||||
|
return delegate;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AutoPropDescRooter::trace(JSTracer *trc)
|
AutoPropDescRooter::trace(JSTracer *trc)
|
||||||
{
|
{
|
||||||
|
@ -168,16 +168,24 @@ class ObjectElements
|
|||||||
public:
|
public:
|
||||||
enum Flags {
|
enum Flags {
|
||||||
CONVERT_DOUBLE_ELEMENTS = 0x1,
|
CONVERT_DOUBLE_ELEMENTS = 0x1,
|
||||||
|
ASMJS_ARRAY_BUFFER = 0x2,
|
||||||
|
NEUTERED_BUFFER = 0x4,
|
||||||
|
SHARED_ARRAY_BUFFER = 0x8,
|
||||||
|
MAPPED_ARRAY_BUFFER = 0x10,
|
||||||
|
|
||||||
// Present only if these elements correspond to an array with
|
// Present only if these elements correspond to an array with
|
||||||
// non-writable length; never present for non-arrays.
|
// non-writable length; never present for non-arrays.
|
||||||
NONWRITABLE_ARRAY_LENGTH = 0x2
|
NONWRITABLE_ARRAY_LENGTH = 0x20,
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class ::JSObject;
|
friend class ::JSObject;
|
||||||
friend class ObjectImpl;
|
friend class ObjectImpl;
|
||||||
friend class ArrayObject;
|
friend class ArrayObject;
|
||||||
|
friend class ArrayBufferObject;
|
||||||
|
friend class ArrayBufferViewObject;
|
||||||
|
friend class SharedArrayBufferObject;
|
||||||
|
friend class TypedArrayObject;
|
||||||
friend class Nursery;
|
friend class Nursery;
|
||||||
|
|
||||||
template <ExecutionMode mode>
|
template <ExecutionMode mode>
|
||||||
@ -224,6 +232,30 @@ class ObjectElements
|
|||||||
void clearShouldConvertDoubleElements() {
|
void clearShouldConvertDoubleElements() {
|
||||||
flags &= ~CONVERT_DOUBLE_ELEMENTS;
|
flags &= ~CONVERT_DOUBLE_ELEMENTS;
|
||||||
}
|
}
|
||||||
|
bool isAsmJSArrayBuffer() const {
|
||||||
|
return flags & ASMJS_ARRAY_BUFFER;
|
||||||
|
}
|
||||||
|
void setIsAsmJSArrayBuffer() {
|
||||||
|
flags |= ASMJS_ARRAY_BUFFER;
|
||||||
|
}
|
||||||
|
bool isNeuteredBuffer() const {
|
||||||
|
return flags & NEUTERED_BUFFER;
|
||||||
|
}
|
||||||
|
void setIsNeuteredBuffer() {
|
||||||
|
flags |= NEUTERED_BUFFER;
|
||||||
|
}
|
||||||
|
bool isSharedArrayBuffer() const {
|
||||||
|
return flags & SHARED_ARRAY_BUFFER;
|
||||||
|
}
|
||||||
|
void setIsSharedArrayBuffer() {
|
||||||
|
flags |= SHARED_ARRAY_BUFFER;
|
||||||
|
}
|
||||||
|
bool isMappedArrayBuffer() const {
|
||||||
|
return flags & MAPPED_ARRAY_BUFFER;
|
||||||
|
}
|
||||||
|
void setIsMappedArrayBuffer() {
|
||||||
|
flags |= MAPPED_ARRAY_BUFFER;
|
||||||
|
}
|
||||||
bool hasNonwritableArrayLength() const {
|
bool hasNonwritableArrayLength() const {
|
||||||
return flags & NONWRITABLE_ARRAY_LENGTH;
|
return flags & NONWRITABLE_ARRAY_LENGTH;
|
||||||
}
|
}
|
||||||
@ -1014,6 +1046,9 @@ IsObjectValueInCompartment(js::Value v, JSCompartment *comp)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern JSObject *
|
||||||
|
ArrayBufferDelegate(JSContext *cx, Handle<ObjectImpl*> obj);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
#endif /* vm_ObjectImpl_h */
|
#endif /* vm_ObjectImpl_h */
|
||||||
|
@ -23,6 +23,8 @@ using namespace js;
|
|||||||
using mozilla::IsNaN;
|
using mozilla::IsNaN;
|
||||||
using mozilla::PodCopy;
|
using mozilla::PodCopy;
|
||||||
|
|
||||||
|
#define SHAREDARRAYBUFFER_RESERVED_SLOTS 15
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* SharedArrayRawBuffer
|
* SharedArrayRawBuffer
|
||||||
*/
|
*/
|
||||||
@ -177,26 +179,53 @@ SharedArrayBufferObject::New(JSContext *cx, uint32_t length)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedArrayRawBuffer *buffer = SharedArrayRawBuffer::New(length);
|
RootedObject obj(cx, NewBuiltinClassInstance(cx, &class_));
|
||||||
if (!buffer)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return New(cx, buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSObject *
|
|
||||||
SharedArrayBufferObject::New(JSContext *cx, SharedArrayRawBuffer *buffer)
|
|
||||||
{
|
|
||||||
Rooted<SharedArrayBufferObject*> obj(cx, NewBuiltinClassInstance<SharedArrayBufferObject>(cx));
|
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
JS_ASSERT(obj->getClass() == &class_);
|
JS_ASSERT(obj->getClass() == &class_);
|
||||||
|
|
||||||
obj->initialize(buffer->byteLength(), nullptr, DoesntOwnData);
|
Rooted<js::Shape*> empty(cx);
|
||||||
|
empty = EmptyShape::getInitialShape(cx, &class_, obj->getProto(), obj->getParent(),
|
||||||
|
obj->getMetadata(), gc::FINALIZE_OBJECT16_BACKGROUND);
|
||||||
|
if (!empty)
|
||||||
|
return nullptr;
|
||||||
|
obj->setLastPropertyInfallible(empty);
|
||||||
|
|
||||||
obj->acceptRawBuffer(buffer);
|
obj->setFixedElements();
|
||||||
obj->setIsSharedArrayBuffer();
|
obj->as<SharedArrayBufferObject>().initElementsHeader(obj->getElementsHeader(), length);
|
||||||
|
obj->getElementsHeader()->setIsSharedArrayBuffer();
|
||||||
|
|
||||||
|
SharedArrayRawBuffer *buffer = SharedArrayRawBuffer::New(length);
|
||||||
|
if (!buffer)
|
||||||
|
return nullptr;
|
||||||
|
obj->as<SharedArrayBufferObject>().acceptRawBuffer(buffer);
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject *
|
||||||
|
SharedArrayBufferObject::New(JSContext *cx, SharedArrayRawBuffer *buffer)
|
||||||
|
{
|
||||||
|
RootedObject obj(cx, NewBuiltinClassInstance(cx, &class_));
|
||||||
|
if (!obj)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
JS_ASSERT(obj->getClass() == &class_);
|
||||||
|
|
||||||
|
Rooted<js::Shape*> empty(cx);
|
||||||
|
empty = EmptyShape::getInitialShape(cx, &class_, obj->getProto(), obj->getParent(),
|
||||||
|
obj->getMetadata(), gc::FINALIZE_OBJECT16_BACKGROUND);
|
||||||
|
if (!empty)
|
||||||
|
return nullptr;
|
||||||
|
obj->setLastPropertyInfallible(empty);
|
||||||
|
|
||||||
|
obj->setFixedElements();
|
||||||
|
obj->as<SharedArrayBufferObject>().initElementsHeader(obj->getElementsHeader(),
|
||||||
|
buffer->byteLength());
|
||||||
|
obj->getElementsHeader()->setIsSharedArrayBuffer();
|
||||||
|
|
||||||
|
obj->as<SharedArrayBufferObject>().acceptRawBuffer(buffer);
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
@ -254,6 +283,8 @@ SharedArrayBufferObject::Finalize(FreeOp *fop, JSObject *obj)
|
|||||||
|
|
||||||
const Class SharedArrayBufferObject::protoClass = {
|
const Class SharedArrayBufferObject::protoClass = {
|
||||||
"SharedArrayBufferPrototype",
|
"SharedArrayBufferPrototype",
|
||||||
|
JSCLASS_HAS_PRIVATE |
|
||||||
|
JSCLASS_HAS_RESERVED_SLOTS(SHAREDARRAYBUFFER_RESERVED_SLOTS) |
|
||||||
JSCLASS_HAS_CACHED_PROTO(JSProto_SharedArrayBuffer),
|
JSCLASS_HAS_CACHED_PROTO(JSProto_SharedArrayBuffer),
|
||||||
JS_PropertyStub, /* addProperty */
|
JS_PropertyStub, /* addProperty */
|
||||||
JS_DeletePropertyStub, /* delProperty */
|
JS_DeletePropertyStub, /* delProperty */
|
||||||
@ -266,8 +297,10 @@ const Class SharedArrayBufferObject::protoClass = {
|
|||||||
|
|
||||||
const Class SharedArrayBufferObject::class_ = {
|
const Class SharedArrayBufferObject::class_ = {
|
||||||
"SharedArrayBuffer",
|
"SharedArrayBuffer",
|
||||||
|
JSCLASS_HAS_PRIVATE |
|
||||||
JSCLASS_IMPLEMENTS_BARRIERS |
|
JSCLASS_IMPLEMENTS_BARRIERS |
|
||||||
JSCLASS_HAS_RESERVED_SLOTS(SharedArrayBufferObject::RESERVED_SLOTS) |
|
Class::NON_NATIVE |
|
||||||
|
JSCLASS_HAS_RESERVED_SLOTS(SHAREDARRAYBUFFER_RESERVED_SLOTS) |
|
||||||
JSCLASS_HAS_CACHED_PROTO(JSProto_SharedArrayBuffer),
|
JSCLASS_HAS_CACHED_PROTO(JSProto_SharedArrayBuffer),
|
||||||
JS_PropertyStub, /* addProperty */
|
JS_PropertyStub, /* addProperty */
|
||||||
JS_DeletePropertyStub, /* delProperty */
|
JS_DeletePropertyStub, /* delProperty */
|
||||||
@ -282,7 +315,29 @@ const Class SharedArrayBufferObject::class_ = {
|
|||||||
nullptr, /* construct */
|
nullptr, /* construct */
|
||||||
ArrayBufferObject::obj_trace,
|
ArrayBufferObject::obj_trace,
|
||||||
JS_NULL_CLASS_SPEC,
|
JS_NULL_CLASS_SPEC,
|
||||||
JS_NULL_CLASS_EXT
|
JS_NULL_CLASS_EXT,
|
||||||
|
{
|
||||||
|
ArrayBufferObject::obj_lookupGeneric,
|
||||||
|
ArrayBufferObject::obj_lookupProperty,
|
||||||
|
ArrayBufferObject::obj_lookupElement,
|
||||||
|
ArrayBufferObject::obj_defineGeneric,
|
||||||
|
ArrayBufferObject::obj_defineProperty,
|
||||||
|
ArrayBufferObject::obj_defineElement,
|
||||||
|
ArrayBufferObject::obj_getGeneric,
|
||||||
|
ArrayBufferObject::obj_getProperty,
|
||||||
|
ArrayBufferObject::obj_getElement,
|
||||||
|
ArrayBufferObject::obj_setGeneric,
|
||||||
|
ArrayBufferObject::obj_setProperty,
|
||||||
|
ArrayBufferObject::obj_setElement,
|
||||||
|
ArrayBufferObject::obj_getGenericAttributes,
|
||||||
|
ArrayBufferObject::obj_setGenericAttributes,
|
||||||
|
ArrayBufferObject::obj_deleteProperty,
|
||||||
|
ArrayBufferObject::obj_deleteElement,
|
||||||
|
nullptr, nullptr, /* watch/unwatch */
|
||||||
|
nullptr, /* slice */
|
||||||
|
ArrayBufferObject::obj_enumerate,
|
||||||
|
nullptr, /* thisObject */
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
JSObject *
|
JSObject *
|
||||||
|
@ -74,9 +74,8 @@ class SharedArrayBufferObject : public ArrayBufferObject
|
|||||||
static const Class protoClass;
|
static const Class protoClass;
|
||||||
|
|
||||||
// Slot used for storing a pointer to the SharedArrayRawBuffer.
|
// Slot used for storing a pointer to the SharedArrayRawBuffer.
|
||||||
static const uint8_t RAWBUF_SLOT = ArrayBufferObject::RESERVED_SLOTS;
|
// First two slots hold the ObjectElements.
|
||||||
|
static const int32_t RAWBUF_SLOT = 2;
|
||||||
static const uint8_t RESERVED_SLOTS = ArrayBufferObject::RESERVED_SLOTS + 1;
|
|
||||||
|
|
||||||
static bool class_constructor(JSContext *cx, unsigned argc, Value *vp);
|
static bool class_constructor(JSContext *cx, unsigned argc, Value *vp);
|
||||||
|
|
||||||
|
@ -985,8 +985,6 @@ JSStructuredCloneWriter::writeTransferMap()
|
|||||||
return false;
|
return false;
|
||||||
if (!out.writePtr(nullptr)) // Pointer to ArrayBuffer contents or to SharedArrayRawBuffer.
|
if (!out.writePtr(nullptr)) // Pointer to ArrayBuffer contents or to SharedArrayRawBuffer.
|
||||||
return false;
|
return false;
|
||||||
if (!out.write(0)) // |byteLength| for an ArrayBuffer, 0 for SharedArrayBuffer
|
|
||||||
return false;
|
|
||||||
if (!out.write(0)) // |userdata|, intended to be passed to callbacks.
|
if (!out.write(0)) // |userdata|, intended to be passed to callbacks.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1016,15 +1014,14 @@ JSStructuredCloneWriter::transferOwnership()
|
|||||||
MOZ_ASSERT(uint32_t(LittleEndian::readUint64(point)) == SCTAG_TM_UNFILLED);
|
MOZ_ASSERT(uint32_t(LittleEndian::readUint64(point)) == SCTAG_TM_UNFILLED);
|
||||||
|
|
||||||
if (obj->is<ArrayBufferObject>()) {
|
if (obj->is<ArrayBufferObject>()) {
|
||||||
size_t nbytes = obj->as<ArrayBufferObject>().byteLength();
|
void *content;
|
||||||
void *contents = JS_StealArrayBufferContents(context(), obj);
|
uint8_t *data;
|
||||||
if (!contents)
|
if (!JS_StealArrayBufferContents(context(), obj, &content, &data))
|
||||||
return false; // Destructor will clean up the already-transferred data
|
return false; // Destructor will clean up the already-transferred data
|
||||||
|
|
||||||
uint64_t entryTag = PairToUInt64(SCTAG_TRANSFER_MAP_ENTRY, SCTAG_TM_ALLOC_DATA);
|
uint64_t entryTag = PairToUInt64(SCTAG_TRANSFER_MAP_ENTRY, SCTAG_TM_ALLOC_DATA);
|
||||||
LittleEndian::writeUint64(point++, entryTag);
|
LittleEndian::writeUint64(point++, entryTag);
|
||||||
LittleEndian::writeUint64(point++, reinterpret_cast<uint64_t>(contents));
|
LittleEndian::writeUint64(point++, reinterpret_cast<uint64_t>(content));
|
||||||
LittleEndian::writeUint64(point++, nbytes);
|
|
||||||
LittleEndian::writeUint64(point++, 0);
|
LittleEndian::writeUint64(point++, 0);
|
||||||
} else {
|
} else {
|
||||||
SharedArrayRawBuffer *rawbuf = obj->as<SharedArrayBufferObject>().rawBufferObject();
|
SharedArrayRawBuffer *rawbuf = obj->as<SharedArrayBufferObject>().rawBufferObject();
|
||||||
@ -1037,7 +1034,6 @@ JSStructuredCloneWriter::transferOwnership()
|
|||||||
LittleEndian::writeUint64(point++, entryTag);
|
LittleEndian::writeUint64(point++, entryTag);
|
||||||
LittleEndian::writeUint64(point++, reinterpret_cast<uint64_t>(rawbuf));
|
LittleEndian::writeUint64(point++, reinterpret_cast<uint64_t>(rawbuf));
|
||||||
LittleEndian::writeUint64(point++, 0);
|
LittleEndian::writeUint64(point++, 0);
|
||||||
LittleEndian::writeUint64(point++, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1244,13 +1240,13 @@ bool
|
|||||||
JSStructuredCloneReader::readMappedArrayBuffer(Value *vp, uint32_t fd,
|
JSStructuredCloneReader::readMappedArrayBuffer(Value *vp, uint32_t fd,
|
||||||
uint32_t offset, uint32_t length)
|
uint32_t offset, uint32_t length)
|
||||||
{
|
{
|
||||||
|
void *ptr;
|
||||||
int new_fd;
|
int new_fd;
|
||||||
void *ptr = JS_CreateMappedArrayBufferContents(fd, &new_fd, offset, length);
|
if(!JS_CreateMappedArrayBufferContents(fd, &new_fd, offset, length, &ptr)) {
|
||||||
if (!ptr) {
|
|
||||||
JS_ReportError(context(), "Failed to create mapped array buffer contents");
|
JS_ReportError(context(), "Failed to create mapped array buffer contents");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
JSObject *obj = JS_NewArrayBufferWithContents(context(), length, ptr, /* mapped = */ true);
|
JSObject *obj = JS_NewArrayBufferWithContents(context(), ptr);
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
JS_ReleaseMappedArrayBufferContents(new_fd, ptr, length);
|
JS_ReleaseMappedArrayBufferContents(new_fd, ptr, length);
|
||||||
return false;
|
return false;
|
||||||
@ -1552,10 +1548,6 @@ JSStructuredCloneReader::readTransferMap()
|
|||||||
if (!in.readPtr(&content))
|
if (!in.readPtr(&content))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint64_t nbytes;
|
|
||||||
if (!in.read(&nbytes))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
uint64_t userdata;
|
uint64_t userdata;
|
||||||
if (!in.read(&userdata))
|
if (!in.read(&userdata))
|
||||||
return false;
|
return false;
|
||||||
@ -1563,7 +1555,7 @@ JSStructuredCloneReader::readTransferMap()
|
|||||||
RootedObject obj(context());
|
RootedObject obj(context());
|
||||||
|
|
||||||
if (data == SCTAG_TM_ALLOC_DATA)
|
if (data == SCTAG_TM_ALLOC_DATA)
|
||||||
obj = JS_NewArrayBufferWithContents(context(), nbytes, content);
|
obj = JS_NewArrayBufferWithContents(context(), content);
|
||||||
else if (data == SCTAG_TM_SHARED_BUFFER)
|
else if (data == SCTAG_TM_SHARED_BUFFER)
|
||||||
obj = SharedArrayBufferObject::New(context(), (SharedArrayRawBuffer *)content);
|
obj = SharedArrayBufferObject::New(context(), (SharedArrayRawBuffer *)content);
|
||||||
|
|
||||||
|
@ -349,6 +349,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
|
|||||||
obj->setSlot(BYTEOFFSET_SLOT, Int32Value(byteOffset));
|
obj->setSlot(BYTEOFFSET_SLOT, Int32Value(byteOffset));
|
||||||
obj->setSlot(BYTELENGTH_SLOT, Int32Value(len * sizeof(NativeType)));
|
obj->setSlot(BYTELENGTH_SLOT, Int32Value(len * sizeof(NativeType)));
|
||||||
obj->setSlot(NEXT_VIEW_SLOT, PrivateValue(nullptr));
|
obj->setSlot(NEXT_VIEW_SLOT, PrivateValue(nullptr));
|
||||||
|
obj->setSlot(NEXT_BUFFER_SLOT, PrivateValue(UNSET_BUFFER_LINK));
|
||||||
|
|
||||||
js::Shape *empty = EmptyShape::getInitialShape(cx, fastClass(),
|
js::Shape *empty = EmptyShape::getInitialShape(cx, fastClass(),
|
||||||
obj->getProto(), obj->getParent(), obj->getMetadata(),
|
obj->getProto(), obj->getParent(), obj->getMetadata(),
|
||||||
@ -1337,6 +1338,7 @@ DataViewObject::create(JSContext *cx, uint32_t byteOffset, uint32_t byteLength,
|
|||||||
dvobj.setFixedSlot(BYTELENGTH_SLOT, Int32Value(byteLength));
|
dvobj.setFixedSlot(BYTELENGTH_SLOT, Int32Value(byteLength));
|
||||||
dvobj.setFixedSlot(BUFFER_SLOT, ObjectValue(*arrayBuffer));
|
dvobj.setFixedSlot(BUFFER_SLOT, ObjectValue(*arrayBuffer));
|
||||||
dvobj.setFixedSlot(NEXT_VIEW_SLOT, PrivateValue(nullptr));
|
dvobj.setFixedSlot(NEXT_VIEW_SLOT, PrivateValue(nullptr));
|
||||||
|
dvobj.setFixedSlot(NEXT_BUFFER_SLOT, PrivateValue(UNSET_BUFFER_LINK));
|
||||||
InitArrayBufferViewDataPointer(&dvobj, arrayBuffer, byteOffset);
|
InitArrayBufferViewDataPointer(&dvobj, arrayBuffer, byteOffset);
|
||||||
JS_ASSERT(byteOffset + byteLength <= arrayBuffer->byteLength());
|
JS_ASSERT(byteOffset + byteLength <= arrayBuffer->byteLength());
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ ClampIntForUint8Array(int32_t x)
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ToDoubleForTypedArray(JSContext *cx, JS::HandleValue vp, double *d);
|
extern js::ArrayBufferObject * const UNSET_BUFFER_LINK;
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user