зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1529298 - Remove JS_ExternalizeArrayBufferContents because it has no users except in tests, implements complicated ownership semantics, and is definite implementation complexity. r=sfink
This commit is contained in:
Родитель
851c01dd7e
Коммит
7be1e6c028
|
@ -159,73 +159,6 @@ bool hasDetachedBuffer(JS::HandleObject obj) {
|
|||
|
||||
END_TEST(testArrayBuffer_bug720949_viewList)
|
||||
|
||||
BEGIN_TEST(testArrayBuffer_externalize) {
|
||||
if (!testWithSize(cx, 2)) { // ArrayBuffer data stored inline in the object.
|
||||
return false;
|
||||
}
|
||||
if (!testWithSize(cx, 2000)) { // ArrayBuffer data stored out-of-line in a
|
||||
// separate heap allocation.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool testWithSize(JSContext* cx, size_t n) {
|
||||
JS::RootedObject buffer(cx, JS_NewArrayBuffer(cx, n));
|
||||
CHECK(buffer != nullptr);
|
||||
|
||||
JS::RootedObject view(cx, JS_NewUint8ArrayWithBuffer(cx, buffer, 0, -1));
|
||||
CHECK(view != nullptr);
|
||||
|
||||
void* contents = JS_ExternalizeArrayBufferContents(cx, buffer);
|
||||
CHECK(contents != nullptr);
|
||||
uint32_t actualLength;
|
||||
CHECK(hasExpectedLength(cx, view, &actualLength));
|
||||
CHECK(actualLength == n);
|
||||
CHECK(!JS_IsDetachedArrayBufferObject(buffer));
|
||||
CHECK(JS_GetArrayBufferByteLength(buffer) == uint32_t(n));
|
||||
|
||||
uint8_t* uint8Contents = static_cast<uint8_t*>(contents);
|
||||
CHECK(*uint8Contents == 0);
|
||||
uint8_t randomByte(rand() % UINT8_MAX);
|
||||
*uint8Contents = randomByte;
|
||||
|
||||
JS::RootedValue v(cx);
|
||||
CHECK(JS_GetElement(cx, view, 0, &v));
|
||||
CHECK(v.toInt32() == randomByte);
|
||||
|
||||
view = nullptr;
|
||||
GC(cx);
|
||||
|
||||
CHECK(JS_DetachArrayBuffer(cx, buffer));
|
||||
GC(cx);
|
||||
CHECK(*uint8Contents == randomByte);
|
||||
JS_free(cx, contents);
|
||||
GC(cx);
|
||||
buffer = nullptr;
|
||||
GC(cx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void GC(JSContext* cx) {
|
||||
JS_GC(cx);
|
||||
JS_GC(cx); // Trigger another to wait for background finalization to end
|
||||
}
|
||||
|
||||
static bool hasExpectedLength(JSContext* cx, JS::HandleObject obj,
|
||||
uint32_t* len) {
|
||||
JS::RootedValue v(cx);
|
||||
if (!JS_GetProperty(cx, obj, "byteLength", &v)) {
|
||||
return false;
|
||||
}
|
||||
*len = v.toInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
END_TEST(testArrayBuffer_externalize)
|
||||
|
||||
BEGIN_TEST(testArrayBuffer_customFreeFunc) {
|
||||
ExternalData data("One two three four");
|
||||
|
||||
|
|
|
@ -2082,30 +2082,6 @@ extern JS_PUBLIC_API JSObject* JS_NewArrayBufferWithUserOwnedContents(
|
|||
extern JS_PUBLIC_API void* JS_StealArrayBufferContents(JSContext* cx,
|
||||
JS::HandleObject obj);
|
||||
|
||||
/**
|
||||
* Returns a pointer to the ArrayBuffer |obj|'s data. |obj| and its views will
|
||||
* store and expose the data in the returned pointer: assigning into the
|
||||
* returned pointer will affect values exposed by views of |obj| and vice versa.
|
||||
* Writes into the pointer must be synchronized with the current thread,
|
||||
* typically by occurring *only on* the current thread.
|
||||
*
|
||||
* The caller must ultimately deallocate the returned pointer to avoid leaking.
|
||||
* The memory is *not* garbage-collected with |obj|. These steps must be
|
||||
* followed to deallocate:
|
||||
*
|
||||
* 1. The ArrayBuffer |obj| must be detached using JS_DetachArrayBuffer.
|
||||
* 2. The returned pointer must be freed using JS_free.
|
||||
*
|
||||
* To perform step 1, callers *must* hold a reference to |obj| until they finish
|
||||
* using the returned pointer. They *must not* attempt to let |obj| be GC'd,
|
||||
* then JS_free the pointer.
|
||||
*
|
||||
* If |obj| isn't an ArrayBuffer, this function returns null and reports an
|
||||
* error.
|
||||
*/
|
||||
extern JS_PUBLIC_API void* JS_ExternalizeArrayBufferContents(
|
||||
JSContext* cx, JS::HandleObject obj);
|
||||
|
||||
/**
|
||||
* Create a new mapped array buffer with the given memory mapped contents. It
|
||||
* must be legal to free the contents pointer by unmapping it. On success,
|
||||
|
|
|
@ -1318,73 +1318,6 @@ ArrayBufferObject* ArrayBufferObject::createFromNewRawBuffer(
|
|||
return obj;
|
||||
}
|
||||
|
||||
/* static */ void*
|
||||
ArrayBufferObject::exposeMallocedContents(JSContext* cx,
|
||||
Handle<ArrayBufferObject*> buffer) {
|
||||
// A detached ArrayBuffer lacks contents to expose.
|
||||
if (buffer->isDetached()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_TYPED_ARRAY_DETACHED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// The contents must be malloc'd or stored inline, because this function
|
||||
// returns a JS_free-able pointer.
|
||||
//
|
||||
// Mapped and wasm ArrayBufferObjects' memory is not so allocated, and we
|
||||
// can't blithely allocate a copy of the data and swap it into |buffer|
|
||||
// because JIT code may hold pointers into the mapped/wasm data.
|
||||
//
|
||||
// We also don't support replacing user-owned data (with malloced data)
|
||||
// because such ArrayBuffers must be passed to JS_DetachArrayBuffer before
|
||||
// the associated memory is freed, and that call is guaranteed to succeed
|
||||
// -- but malloced data can be used with asm.js, and JS_DetachArrayBuffer
|
||||
// will fail on an ArrayBuffer used with asm.js.
|
||||
//
|
||||
// These restrictions are very hoary. Possibly, in a future where
|
||||
// ArrayBuffer's contents are not represented so trickily, we might relax
|
||||
// them -- maybe by returning something that has the ability to release the
|
||||
// returned memory.
|
||||
if (!buffer->isMalloced() && !buffer->isInlineData()) {
|
||||
MOZ_ASSERT(buffer->hasUserOwnedData() || buffer->isWasm() ||
|
||||
buffer->isMapped() || buffer->isExternal());
|
||||
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT_IF(buffer->isInlineData(), !buffer->ownsData());
|
||||
MOZ_ASSERT_IF(buffer->ownsData(), buffer->isMalloced());
|
||||
|
||||
BufferContents contents = buffer->contents();
|
||||
|
||||
// If the buffer owns its data and the data isn't needed for an asm.js
|
||||
// compilation, we can just mark the data as unowned and return it -- no need
|
||||
// to actively replace.
|
||||
if (buffer->ownsData() && !buffer->isPreparedForAsmJS()) {
|
||||
MOZ_ASSERT(buffer->hasStealableContents());
|
||||
buffer->setOwnsData(DoesntOwnData);
|
||||
return contents.data();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!buffer->hasStealableContents());
|
||||
|
||||
// Otherwise we must allocate new contents, fill them with the old contents,
|
||||
// slot them into place as unowned contents (freeing the old contents in the
|
||||
// process), then return an owning pointer to the new contents.
|
||||
BufferContents newContents =
|
||||
AllocateArrayBufferContents(cx, buffer->byteLength());
|
||||
if (!newContents) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
memcpy(newContents.data(), contents.data(), buffer->byteLength());
|
||||
buffer->changeContents(cx, newContents, DoesntOwnData);
|
||||
|
||||
return newContents.data();
|
||||
}
|
||||
|
||||
/* static */ ArrayBufferObject::BufferContents ArrayBufferObject::stealContents(
|
||||
JSContext* cx, Handle<ArrayBufferObject*> buffer,
|
||||
bool hasStealableContents) {
|
||||
|
@ -1785,22 +1718,6 @@ JS_FRIEND_API JSObject* js::UnwrapSharedArrayBuffer(JSObject* obj) {
|
|||
return obj->maybeUnwrapIf<SharedArrayBufferObject>();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API void* JS_ExternalizeArrayBufferContents(JSContext* cx,
|
||||
HandleObject obj) {
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(obj);
|
||||
|
||||
if (!obj->is<ArrayBufferObject>()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
|
||||
JSMSG_TYPED_ARRAY_BAD_ARGS);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Handle<ArrayBufferObject*> buffer = obj.as<ArrayBufferObject>();
|
||||
return ArrayBufferObject::exposeMallocedContents(cx, buffer);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API void* JS_StealArrayBufferContents(JSContext* cx,
|
||||
HandleObject objArg) {
|
||||
AssertHeapIsIdle();
|
||||
|
|
|
@ -339,17 +339,6 @@ class ArrayBufferObject : public ArrayBufferObjectMaybeShared {
|
|||
|
||||
static size_t objectMoved(JSObject* obj, JSObject* old);
|
||||
|
||||
// Convert this ArrayBuffer's storage to memory allocated using the standard
|
||||
// SpiderMonkey allocator (if the storage *is* memory so allocated, this will
|
||||
// be a no-op), then return a pointer to that memory *that the caller now
|
||||
// owns*, for same-thread manipulation by the caller. The caller must at a
|
||||
// later time call |JS_DetachArrayBuffer| on |buffer|, then free the
|
||||
// SpiderMonkey-allocated pointer in the usual way.
|
||||
//
|
||||
// Returns null leaving |buffer| unaltered on failure.
|
||||
static void* exposeMallocedContents(JSContext* cx,
|
||||
Handle<ArrayBufferObject*> buffer);
|
||||
|
||||
static BufferContents stealContents(JSContext* cx,
|
||||
Handle<ArrayBufferObject*> buffer,
|
||||
bool hasStealableContents);
|
||||
|
|
Загрузка…
Ссылка в новой задаче