mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1412852 - Structured clone WebAssembly.Memory objects. r=sfink
--HG-- extra : rebase_source : 0f96caf022c5d0ec51e5c9710468ed8015acf4aa
This commit is contained in:
parent
770a864e0b
commit
3f9a90d355
@ -364,7 +364,7 @@ class JS_PUBLIC_API(JSAutoStructuredCloneBuffer) {
|
||||
#define JS_SCERR_TRANSFERABLE 1
|
||||
#define JS_SCERR_DUP_TRANSFERABLE 2
|
||||
#define JS_SCERR_UNSUPPORTED_TYPE 3
|
||||
#define JS_SCERR_SAB_TRANSFERABLE 4
|
||||
#define JS_SCERR_SHMEM_TRANSFERABLE 4
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ReadUint32Pair(JSStructuredCloneReader* r, uint32_t* p1, uint32_t* p2);
|
||||
|
@ -435,9 +435,9 @@ MSG_DEF(JSMSG_SC_DUP_TRANSFERABLE, 0, JSEXN_TYPEERR, "duplicate transferable
|
||||
MSG_DEF(JSMSG_SC_NOT_TRANSFERABLE, 0, JSEXN_TYPEERR, "invalid transferable array for structured clone")
|
||||
MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE, 0, JSEXN_TYPEERR, "unsupported type for structured data")
|
||||
MSG_DEF(JSMSG_SC_NOT_CLONABLE, 1, JSEXN_TYPEERR, "{0} cannot be cloned in this context")
|
||||
MSG_DEF(JSMSG_SC_SAB_TRANSFERABLE, 0, JSEXN_TYPEERR, "SharedArrayBuffer must not be in the transfer list")
|
||||
MSG_DEF(JSMSG_SC_SAB_DISABLED, 0, JSEXN_TYPEERR, "SharedArrayBuffer not cloned - shared memory disabled in receiver")
|
||||
MSG_DEF(JSMSG_SC_SAB_REFCNT_OFLO, 0, JSEXN_TYPEERR, "SharedArrayBuffer has too many references")
|
||||
MSG_DEF(JSMSG_SC_SHMEM_TRANSFERABLE, 0, JSEXN_TYPEERR, "Shared memory objects must not be in the transfer list")
|
||||
|
||||
// Debugger
|
||||
MSG_DEF(JSMSG_ASSIGN_FUNCTION_OR_NULL, 1, JSEXN_TYPEERR, "value assigned to {0} must be a function or null")
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "vm/SharedArrayObject.h"
|
||||
#include "vm/TypedArrayObject.h"
|
||||
#include "vm/WrapperObject.h"
|
||||
#include "wasm/WasmJS.h"
|
||||
|
||||
#include "jscntxtinlines.h"
|
||||
#include "jsobjinlines.h"
|
||||
@ -106,6 +107,7 @@ enum StructuredDataType : uint32_t {
|
||||
SCTAG_RECONSTRUCTED_SAVED_FRAME_PRINCIPALS_IS_NOT_SYSTEM,
|
||||
|
||||
SCTAG_SHARED_ARRAY_BUFFER_OBJECT,
|
||||
SCTAG_SHARED_WASM_MEMORY_OBJECT,
|
||||
|
||||
SCTAG_TYPED_ARRAY_V1_MIN = 0xFFFF0100,
|
||||
SCTAG_TYPED_ARRAY_V1_INT8 = SCTAG_TYPED_ARRAY_V1_MIN + Scalar::Int8,
|
||||
@ -409,6 +411,7 @@ struct JSStructuredCloneReader {
|
||||
MOZ_MUST_USE bool readDataView(uint32_t byteLength, MutableHandleValue vp);
|
||||
MOZ_MUST_USE bool readArrayBuffer(uint32_t nbytes, MutableHandleValue vp);
|
||||
MOZ_MUST_USE bool readSharedArrayBuffer(uint32_t nbytes, MutableHandleValue vp);
|
||||
MOZ_MUST_USE bool readSharedWasmMemory(uint32_t nbytes, MutableHandleValue vp);
|
||||
MOZ_MUST_USE bool readV1ArrayBuffer(uint32_t arrayType, uint32_t nelems, MutableHandleValue vp);
|
||||
JSObject* readSavedFrame(uint32_t principalsTag);
|
||||
MOZ_MUST_USE bool startRead(MutableHandleValue vp);
|
||||
@ -501,6 +504,7 @@ struct JSStructuredCloneWriter {
|
||||
bool writeTypedArray(HandleObject obj);
|
||||
bool writeDataView(HandleObject obj);
|
||||
bool writeSharedArrayBuffer(HandleObject obj);
|
||||
bool writeSharedWasmMemory(HandleObject obj);
|
||||
bool startObject(HandleObject obj, bool* backref);
|
||||
bool startWrite(HandleValue v);
|
||||
bool traverseObject(HandleObject obj);
|
||||
@ -599,8 +603,8 @@ ReportDataCloneError(JSContext* cx,
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SC_UNSUPPORTED_TYPE);
|
||||
break;
|
||||
|
||||
case JS_SCERR_SAB_TRANSFERABLE:
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SC_SAB_TRANSFERABLE);
|
||||
case JS_SCERR_SHMEM_TRANSFERABLE:
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SC_SHMEM_TRANSFERABLE);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1097,8 +1101,15 @@ JSStructuredCloneWriter::parseTransferable()
|
||||
return reportDataCloneError(JS_SCERR_TRANSFERABLE);
|
||||
tObj = &v.toObject();
|
||||
|
||||
// Shared memory cannot be transferred because it is not possible (nor
|
||||
// desirable) to detach the memory in agents that already hold a
|
||||
// reference to it.
|
||||
|
||||
if (tObj->is<SharedArrayBufferObject>())
|
||||
return reportDataCloneError(JS_SCERR_SAB_TRANSFERABLE);
|
||||
return reportDataCloneError(JS_SCERR_SHMEM_TRANSFERABLE);
|
||||
|
||||
if (tObj->is<WasmMemoryObject>() && tObj->as<WasmMemoryObject>().isShared())
|
||||
return reportDataCloneError(JS_SCERR_SHMEM_TRANSFERABLE);
|
||||
|
||||
// No duplicates allowed
|
||||
auto p = transferableObjects.lookupForAdd(tObj);
|
||||
@ -1228,6 +1239,8 @@ JSStructuredCloneWriter::writeArrayBuffer(HandleObject obj)
|
||||
bool
|
||||
JSStructuredCloneWriter::writeSharedArrayBuffer(HandleObject obj)
|
||||
{
|
||||
MOZ_ASSERT(CheckedUnwrap(obj) && CheckedUnwrap(obj)->is<SharedArrayBufferObject>());
|
||||
|
||||
if (!cloneDataPolicy.isSharedArrayBufferAllowed()) {
|
||||
JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_NOT_CLONABLE,
|
||||
"SharedArrayBuffer");
|
||||
@ -1245,11 +1258,39 @@ JSStructuredCloneWriter::writeSharedArrayBuffer(HandleObject obj)
|
||||
if (!refsHeld.acquire(context(), rawbuf))
|
||||
return false;
|
||||
|
||||
// We must serialize the length so that the buffer object arrives in the
|
||||
// receiver with the same length, and not with the length read from the
|
||||
// rawbuf - that length can be different, and it can change at any time.
|
||||
|
||||
intptr_t p = reinterpret_cast<intptr_t>(rawbuf);
|
||||
uint32_t byteLength = sharedArrayBuffer->byteLength();
|
||||
return out.writePair(SCTAG_SHARED_ARRAY_BUFFER_OBJECT, static_cast<uint32_t>(sizeof(p))) &&
|
||||
out.writeBytes(&byteLength, sizeof(byteLength)) &&
|
||||
out.writeBytes(&p, sizeof(p));
|
||||
}
|
||||
|
||||
bool
|
||||
JSStructuredCloneWriter::writeSharedWasmMemory(HandleObject obj)
|
||||
{
|
||||
MOZ_ASSERT(CheckedUnwrap(obj) && CheckedUnwrap(obj)->is<WasmMemoryObject>());
|
||||
|
||||
// Check the policy here so that we can report a sane error.
|
||||
if (!cloneDataPolicy.isSharedArrayBufferAllowed()) {
|
||||
JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_NOT_CLONABLE,
|
||||
"WebAssembly.Memory");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this changes, might need to change what we write.
|
||||
MOZ_ASSERT(WasmMemoryObject::RESERVED_SLOTS == 2);
|
||||
|
||||
Rooted<WasmMemoryObject*> memoryObj(context(), &CheckedUnwrap(obj)->as<WasmMemoryObject>());
|
||||
Rooted<SharedArrayBufferObject*> sab(context(), &memoryObj->buffer().as<SharedArrayBufferObject>());
|
||||
|
||||
return out.writePair(SCTAG_SHARED_WASM_MEMORY_OBJECT, 0) &&
|
||||
writeSharedArrayBuffer(sab);
|
||||
}
|
||||
|
||||
bool
|
||||
JSStructuredCloneWriter::startObject(HandleObject obj, bool* backref)
|
||||
{
|
||||
@ -1513,6 +1554,8 @@ JSStructuredCloneWriter::startWrite(HandleValue v)
|
||||
return writeArrayBuffer(obj);
|
||||
} else if (JS_IsSharedArrayBufferObject(obj)) {
|
||||
return writeSharedArrayBuffer(obj);
|
||||
} else if (wasm::IsSharedWasmMemoryObject(obj)) {
|
||||
return writeSharedWasmMemory(obj);
|
||||
} else if (cls == ESClass::Object) {
|
||||
return traverseObject(obj);
|
||||
} else if (cls == ESClass::Array) {
|
||||
@ -1963,6 +2006,10 @@ JSStructuredCloneReader::readArrayBuffer(uint32_t nbytes, MutableHandleValue vp)
|
||||
bool
|
||||
JSStructuredCloneReader::readSharedArrayBuffer(uint32_t nbytes, MutableHandleValue vp)
|
||||
{
|
||||
uint32_t byteLength;
|
||||
if (!in.readBytes(&byteLength, sizeof(byteLength)))
|
||||
return in.reportTruncated();
|
||||
|
||||
intptr_t p;
|
||||
if (!in.readBytes(&p, sizeof(p)))
|
||||
return in.reportTruncated();
|
||||
@ -1991,8 +2038,7 @@ JSStructuredCloneReader::readSharedArrayBuffer(uint32_t nbytes, MutableHandleVal
|
||||
return false;
|
||||
}
|
||||
|
||||
SharedArrayRawBuffer::Lock l(rawbuf);
|
||||
JSObject* obj = SharedArrayBufferObject::New(context(), rawbuf, rawbuf->byteLength(l));
|
||||
JSObject* obj = SharedArrayBufferObject::New(context(), rawbuf, byteLength);
|
||||
if (!obj) {
|
||||
rawbuf->dropReference();
|
||||
return false;
|
||||
@ -2002,6 +2048,31 @@ JSStructuredCloneReader::readSharedArrayBuffer(uint32_t nbytes, MutableHandleVal
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSStructuredCloneReader::readSharedWasmMemory(uint32_t nbytes, MutableHandleValue vp)
|
||||
{
|
||||
MOZ_ASSERT(nbytes == 0);
|
||||
|
||||
JSContext* cx = context();
|
||||
|
||||
// Read the SharedArrayBuffer object.
|
||||
RootedValue payload(cx);
|
||||
if (!startRead(&payload))
|
||||
return false;
|
||||
|
||||
Rooted<ArrayBufferObjectMaybeShared*> sab(
|
||||
cx, &payload.toObject().as<SharedArrayBufferObject>());
|
||||
|
||||
// Construct the memory.
|
||||
RootedObject proto(cx, &cx->global()->getPrototype(JSProto_WasmMemory).toObject());
|
||||
RootedObject memory(cx, WasmMemoryObject::create(cx, sab, proto));
|
||||
if (!memory)
|
||||
return false;
|
||||
|
||||
vp.setObject(*memory);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read in the data for a structured clone version 1 ArrayBuffer, performing
|
||||
* endianness-conversion while reading.
|
||||
@ -2183,6 +2254,11 @@ JSStructuredCloneReader::startRead(MutableHandleValue vp)
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SCTAG_SHARED_WASM_MEMORY_OBJECT:
|
||||
if (!readSharedWasmMemory(data, vp))
|
||||
return false;
|
||||
break;
|
||||
|
||||
case SCTAG_TYPED_ARRAY_OBJECT: {
|
||||
// readTypedArray adds the array to allObjs.
|
||||
uint64_t arrayType;
|
||||
|
@ -1558,6 +1558,13 @@ WasmMemoryObject::grow(HandleWasmMemoryObject memory, uint32_t delta, JSContext*
|
||||
return oldNumPages;
|
||||
}
|
||||
|
||||
bool
|
||||
js::wasm::IsSharedWasmMemoryObject(JSObject* obj)
|
||||
{
|
||||
obj = CheckedUnwrap(obj);
|
||||
return obj && obj->is<WasmMemoryObject>() && obj->as<WasmMemoryObject>().isShared();
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// WebAssembly.Table class and methods
|
||||
|
||||
|
@ -71,6 +71,9 @@ ExportedFunctionToInstanceObject(JSFunction* fun);
|
||||
extern uint32_t
|
||||
ExportedFunctionToFuncIndex(JSFunction* fun);
|
||||
|
||||
extern bool
|
||||
IsSharedWasmMemoryObject(JSObject* obj);
|
||||
|
||||
} // namespace wasm
|
||||
|
||||
// The class of the WebAssembly global namespace object.
|
||||
|
Loading…
Reference in New Issue
Block a user