Bug 1081379 - change BufferKind from a bit field to a dense enum (r=sfink)
--- a/js/src/asmjs/AsmJSModule.cpp
+++ b/js/src/asmjs/AsmJSModule.cpp
@@ -779,18 +779,17 @@ AsmJSModule::staticallyLink(ExclusiveCon
}
MOZ_ASSERT(isStaticallyLinked());
}
void
AsmJSModule::initHeap(Handle<ArrayBufferObjectMaybeShared *> heap, JSContext *cx)
{
- MOZ_ASSERT_IF(heap->is<ArrayBufferObject>(),
- heap->as<ArrayBufferObject>().isAsmJSArrayBuffer());
+ MOZ_ASSERT_IF(heap->is<ArrayBufferObject>(), heap->as<ArrayBufferObject>().isAsmJS());
MOZ_ASSERT(IsValidAsmJSHeapLength(heap->byteLength()));
MOZ_ASSERT(dynamicallyLinked_);
MOZ_ASSERT(!maybeHeap_);
maybeHeap_ = heap;
heapDatum() = heap->dataPointer();
#if defined(JS_CODEGEN_X86)
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1062,17 +1062,17 @@ CacheEntry_getBytecode(HandleObject cach
}
static bool
CacheEntry_setBytecode(JSContext *cx, HandleObject cache, uint8_t *buffer, uint32_t length)
{
MOZ_ASSERT(CacheEntry_isCacheEntry(cache));
ArrayBufferObject::BufferContents contents =
- ArrayBufferObject::BufferContents::create<ArrayBufferObject::PLAIN_BUFFER>(buffer);
+ ArrayBufferObject::BufferContents::create<ArrayBufferObject::PLAIN>(buffer);
Rooted<ArrayBufferObject*> arrayBuffer(cx, ArrayBufferObject::create(cx, length, contents));
if (!arrayBuffer)
return false;
SetReservedSlot(cache, CacheEntry_BYTECODE, OBJECT_TO_JSVAL(arrayBuffer));
return true;
}
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -269,34 +269,34 @@ ArrayBufferObject::class_constructor(JSC
static ArrayBufferObject::BufferContents
AllocateArrayBufferContents(JSContext *cx, uint32_t nbytes)
{
uint8_t *p = cx->runtime()->pod_callocCanGC<uint8_t>(nbytes);
if (!p)
js_ReportOutOfMemory(cx);
- return ArrayBufferObject::BufferContents::create<ArrayBufferObject::PLAIN_BUFFER>(p);
+ return ArrayBufferObject::BufferContents::create<ArrayBufferObject::PLAIN>(p);
}
void
ArrayBufferObject::neuterView(JSContext *cx, ArrayBufferViewObject *view,
BufferContents newContents)
{
view->neuter(newContents.data());
// Notify compiled jit code that the base pointer has moved.
MarkObjectStateChange(cx, view);
}
/* static */ bool
ArrayBufferObject::neuter(JSContext *cx, Handle<ArrayBufferObject*> buffer,
BufferContents newContents)
{
- if (buffer->isAsmJSArrayBuffer() && !OnDetachAsmJSArrayBuffer(cx, buffer))
+ if (buffer->isAsmJS() && !OnDetachAsmJSArrayBuffer(cx, buffer))
return false;
// Neuter all views on the buffer, clear out the list of views and the
// buffer's data.
if (InnerViewTable::ViewVector *views = cx->compartment()->innerViews.maybeViewsUnbarriered(buffer)) {
for (size_t i = 0; i < views->length(); i++)
buffer->neuterView(cx, (*views)[i], newContents);
@@ -312,18 +312,16 @@ ArrayBufferObject::neuter(JSContext *cx,
buffer->setByteLength(0);
buffer->setIsNeutered();
return true;
}
void
ArrayBufferObject::setNewOwnedData(FreeOp* fop, BufferContents newContents)
{
- MOZ_ASSERT(!isAsmJSArrayBuffer());
-
if (ownsData()) {
MOZ_ASSERT(newContents.data() != dataPointer());
releaseData(fop);
}
setDataPointer(newContents, OwnsData);
}
@@ -360,50 +358,46 @@ ArrayBufferObject::changeContents(JSCont
}
if (firstView())
changeViewContents(cx, firstView(), oldDataPointer, newContents);
}
/* static */ bool
ArrayBufferObject::prepareForAsmJSNoSignals(JSContext *cx, Handle<ArrayBufferObject*> buffer)
{
- if (buffer->isAsmJSArrayBuffer())
- return true;
-
if (!buffer->ownsData()) {
BufferContents contents = AllocateArrayBufferContents(cx, buffer->byteLength());
if (!contents)
return false;
memcpy(contents.data(), buffer->dataPointer(), buffer->byteLength());
buffer->changeContents(cx, contents);
}
- buffer->setIsAsmJSArrayBuffer();
+ buffer->setIsAsmJSMalloced();
return true;
}
-void
-ArrayBufferObject::releaseAsmJSArrayNoSignals(FreeOp *fop)
-{
- MOZ_ASSERT(!(bufferKind() & MAPPED_BUFFER));
- fop->free_(dataPointer());
-}
-
#ifdef JS_CODEGEN_X64
/* static */ bool
ArrayBufferObject::prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buffer,
bool usesSignalHandlers)
{
// If we can't use signal handlers, just do it like on other platforms.
if (!usesSignalHandlers)
return prepareForAsmJSNoSignals(cx, buffer);
- if (buffer->isAsmJSArrayBuffer())
+ if (buffer->isAsmJSMapped())
return true;
+ // This can't happen except via the shell toggling signals.enabled.
+ if (buffer->isAsmJSMalloced()) {
+ JS_ReportError(cx, "can't access same buffer with and without signals enabled");
+ return false;
+ }
+
// Get the entire reserved region (with all pages inaccessible).
void *data;
# ifdef XP_WIN
data = VirtualAlloc(nullptr, AsmJSMappedSize, MEM_RESERVE, PAGE_NOACCESS);
if (!data)
return false;
# else
data = MozTaggedAnonymousMmap(nullptr, AsmJSMappedSize, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0, "asm-js-reserved");
@@ -431,80 +425,58 @@ ArrayBufferObject::prepareForAsmJS(JSCon
# endif
# endif
// Copy over the current contents of the typed array.
memcpy(data, buffer->dataPointer(), buffer->byteLength());
// Swap the new elements into the ArrayBufferObject. Mark the
// ArrayBufferObject so we don't do this again.
- BufferContents newContents = BufferContents::create<BufferKind(ASMJS_BUFFER|MAPPED_BUFFER)>(data);
+ BufferContents newContents = BufferContents::create<ASMJS_MAPPED>(data);
buffer->changeContents(cx, newContents);
MOZ_ASSERT(data == buffer->dataPointer());
return true;
}
-void
-ArrayBufferObject::releaseAsmJSArray(FreeOp *fop)
+static void
+ReleaseAsmJSMappedData(void *base)
{
- if (!(bufferKind() & MAPPED_BUFFER)) {
- releaseAsmJSArrayNoSignals(fop);
- return;
- }
-
- void *data = dataPointer();
-
- MOZ_ASSERT(uintptr_t(data) % AsmJSPageSize == 0);
-# ifdef XP_WIN
- VirtualFree(data, 0, MEM_RELEASE);
-# else
- munmap(data, AsmJSMappedSize);
-# if defined(MOZ_VALGRIND) && defined(VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE)
+ MOZ_ASSERT(uintptr_t(base) % AsmJSPageSize == 0);
+#ifdef XP_WIN
+ VirtualFree(base, 0, MEM_RELEASE);
+#else
+ munmap(base, AsmJSMappedSize);
+# if defined(MOZ_VALGRIND) && defined(VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE)
// Tell Valgrind/Memcheck to recommence reporting accesses in the
// previously-inaccessible region.
if (AsmJSMappedSize > 0) {
- VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(data, AsmJSMappedSize);
+ VALGRIND_ENABLE_ADDR_ERROR_REPORTING_IN_RANGE(base, AsmJSMappedSize);
}
-# endif
# endif
+#endif
}
+
#else // JS_CODEGEN_X64
bool
ArrayBufferObject::prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buffer,
bool usesSignalHandlers)
{
// Platforms other than x64 don't use signalling for bounds checking, so
// just use the variant with no signals.
MOZ_ASSERT(!usesSignalHandlers);
return prepareForAsmJSNoSignals(cx, buffer);
}
-
-void
-ArrayBufferObject::releaseAsmJSArray(FreeOp *fop)
-{
- // See comment above.
- releaseAsmJSArrayNoSignals(fop);
-}
#endif
ArrayBufferObject::BufferContents
ArrayBufferObject::createMappedContents(int fd, size_t offset, size_t length)
{
void *data = AllocateMappedContent(fd, offset, length, ARRAY_BUFFER_ALIGNMENT);
- return BufferContents::create<MAPPED_BUFFER>(data);
-}
-
-void
-ArrayBufferObject::releaseMappedArray()
-{
- if(!isMappedArrayBuffer() || isNeutered())
- return;
-
- DeallocateMappedContent(dataPointer(), byteLength());
+ return BufferContents::create<MAPPED>(data);
}
uint8_t *
ArrayBufferObject::inlineDataPointer() const
{
return static_cast<uint8_t *>(fixedData(JSCLASS_RESERVED_SLOTS(&class_)));
}
@@ -514,23 +486,28 @@ ArrayBufferObject::dataPointer() const
return static_cast<uint8_t *>(getSlot(DATA_SLOT).toPrivate());
}
void
ArrayBufferObject::releaseData(FreeOp *fop)
{
MOZ_ASSERT(ownsData());
- BufferKind bufkind = bufferKind();
- if (bufkind & ASMJS_BUFFER)
- releaseAsmJSArray(fop);
- else if (bufkind & MAPPED_BUFFER)
- releaseMappedArray();
- else
+ switch (bufferKind()) {
+ case PLAIN:
+ case ASMJS_MALLOCED:
fop->free_(dataPointer());
+ break;
+ case MAPPED:
+ DeallocateMappedContent(dataPointer(), byteLength());
+ break;
+ case ASMJS_MAPPED:
+ ReleaseAsmJSMappedData(dataPointer());
+ break;
+ }
}
void
ArrayBufferObject::setDataPointer(BufferContents contents, OwnsState ownsData)
{
setSlot(DATA_SLOT, PrivateValue(contents.data()));
setOwnsData(ownsData);
setFlags((flags() & ~KIND_MASK) | contents.kind());
@@ -559,30 +536,30 @@ ArrayBufferObject::setFlags(uint32_t fla
{
setSlot(FLAGS_SLOT, Int32Value(flags));
}
ArrayBufferObject *
ArrayBufferObject::create(JSContext *cx, uint32_t nbytes, BufferContents contents,
NewObjectKind newKind /* = GenericObject */)
{
- MOZ_ASSERT_IF(contents.kind() & MAPPED_BUFFER, contents);
+ MOZ_ASSERT_IF(contents.kind() == MAPPED, contents);
// If we need to allocate data, try to use a larger object size class so
// that the array buffer's data can be allocated inline with the object.
// The extra space will be left unused by the object's fixed slots and
// available for the buffer's data, see NewObject().
size_t reservedSlots = JSCLASS_RESERVED_SLOTS(&class_);
size_t nslots = reservedSlots;
bool allocated = false;
if (contents) {
// The ABO is taking ownership, so account the bytes against the zone.
size_t nAllocated = nbytes;
- if (contents.kind() & MAPPED_BUFFER)
+ if (contents.kind() == MAPPED)
nAllocated = JS_ROUNDUP(nbytes, js::gc::SystemPageSize());
cx->zone()->updateMallocCounter(nAllocated);
} else {
size_t usableSlots = NativeObject::MAX_FIXED_SLOTS - reservedSlots;
if (nbytes <= usableSlots * sizeof(Value)) {
int newSlots = (nbytes - 1) / sizeof(Value) + 1;
MOZ_ASSERT(int(nbytes) <= newSlots * int(sizeof(Value)));
nslots = reservedSlots + newSlots;
@@ -716,27 +693,29 @@ ArrayBufferObject::stealContents(JSConte
ArrayBufferObject::addSizeOfExcludingThis(JSObject *obj, mozilla::MallocSizeOf mallocSizeOf,
JS::ClassInfo *info)
{
ArrayBufferObject &buffer = AsArrayBuffer(obj);
if (!buffer.ownsData())
return;
- if (MOZ_UNLIKELY(buffer.bufferKind() & ASMJS_BUFFER)) {
- // On x64, ArrayBufferObject::prepareForAsmJS switches the
- // ArrayBufferObject to use mmap'd storage.
- if (buffer.bufferKind() & MAPPED_BUFFER)
- info->objectsNonHeapElementsAsmJS += buffer.byteLength();
- else
- info->objectsMallocHeapElementsAsmJS += mallocSizeOf(buffer.dataPointer());
- } else if (MOZ_UNLIKELY(buffer.bufferKind() & MAPPED_BUFFER)) {
+ switch (buffer.bufferKind()) {
+ case PLAIN:
+ info->objectsMallocHeapElementsNonAsmJS += mallocSizeOf(buffer.dataPointer());
+ break;
+ case MAPPED:
info->objectsNonHeapElementsMapped += buffer.byteLength();
- } else if (buffer.dataPointer()) {
- info->objectsMallocHeapElementsNonAsmJS += mallocSizeOf(buffer.dataPointer());
+ break;
+ case ASMJS_MALLOCED:
+ info->objectsMallocHeapElementsAsmJS += mallocSizeOf(buffer.dataPointer());
+ break;
+ case ASMJS_MAPPED:
+ info->objectsNonHeapElementsAsmJS += buffer.byteLength();
+ break;
}
}
/* static */ void
ArrayBufferObject::finalize(FreeOp *fop, JSObject *obj)
{
ArrayBufferObject &buffer = obj->as<ArrayBufferObject>();
@@ -1003,17 +982,17 @@ ArrayBufferViewObject::bufferObject(JSCo
}
/* JS Friend API */
JS_FRIEND_API(bool)
JS_IsArrayBufferViewObject(JSObject *obj)
{
obj = CheckedUnwrap(obj);
- return obj ? obj->is<ArrayBufferViewObject>() : false;
+ return obj && obj->is<ArrayBufferViewObject>();
}
JS_FRIEND_API(JSObject *)
js::UnwrapArrayBufferView(JSObject *obj)
{
if (JSObject *unwrapped = CheckedUnwrap(obj))
return unwrapped->is<ArrayBufferViewObject>() ? unwrapped : nullptr;
return nullptr;
@@ -1065,42 +1044,40 @@ JS_NeuterArrayBuffer(JSContext *cx, Hand
JS_FRIEND_API(bool)
JS_IsNeuteredArrayBufferObject(JSObject *obj)
{
obj = CheckedUnwrap(obj);
if (!obj)
return false;
- return obj->is<ArrayBufferObject>()
- ? obj->as<ArrayBufferObject>().isNeutered()
- : false;
+ return obj->is<ArrayBufferObject>() && obj->as<ArrayBufferObject>().isNeutered();
}
JS_FRIEND_API(JSObject *)
JS_NewArrayBuffer(JSContext *cx, uint32_t nbytes)
{
MOZ_ASSERT(nbytes <= INT32_MAX);
return ArrayBufferObject::create(cx, nbytes);
}
JS_PUBLIC_API(JSObject *)
JS_NewArrayBufferWithContents(JSContext *cx, size_t nbytes, void *data)
{
MOZ_ASSERT(data);
ArrayBufferObject::BufferContents contents =
- ArrayBufferObject::BufferContents::create<ArrayBufferObject::PLAIN_BUFFER>(data);
+ ArrayBufferObject::BufferContents::create<ArrayBufferObject::PLAIN>(data);
return ArrayBufferObject::create(cx, nbytes, contents, TenuredObject);
}
JS_FRIEND_API(bool)
JS_IsArrayBufferObject(JSObject *obj)
{
obj = CheckedUnwrap(obj);
- return obj ? obj->is<ArrayBufferObject>() : false;
+ return obj && obj->is<ArrayBufferObject>();
}
JS_FRIEND_API(bool)
JS_ArrayBufferHasData(JSObject *obj)
{
return CheckedUnwrap(obj)->as<ArrayBufferObject>().hasData();
}
@@ -1129,28 +1106,27 @@ JS_StealArrayBufferContents(JSContext *c
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_TYPED_ARRAY_DETACHED);
return nullptr;
}
// The caller assumes that a plain malloc'd buffer is returned.
// hasStealableContents is true for mapped buffers, so we must additionally
// require that the buffer is plain. In the future, we could consider
// returning something that handles releasing the memory.
- bool hasStealableContents = buffer->hasStealableContents() &&
- buffer->bufferKind() == ArrayBufferObject::PLAIN_BUFFER;
+ bool hasStealableContents = buffer->hasStealableContents() && buffer->isPlain();
return ArrayBufferObject::stealContents(cx, buffer, hasStealableContents).data();
}
JS_PUBLIC_API(JSObject *)
JS_NewMappedArrayBufferWithContents(JSContext *cx, size_t nbytes, void *data)
{
MOZ_ASSERT(data);
ArrayBufferObject::BufferContents contents =
- ArrayBufferObject::BufferContents::create<ArrayBufferObject::MAPPED_BUFFER>(data);
+ ArrayBufferObject::BufferContents::create<ArrayBufferObject::MAPPED>(data);
return ArrayBufferObject::create(cx, nbytes, contents, TenuredObject);
}
JS_PUBLIC_API(void *)
JS_CreateMappedArrayBufferContents(int fd, size_t offset, size_t length)
{
return ArrayBufferObject::createMappedContents(fd, offset, length).data();
}
@@ -1163,19 +1139,17 @@ JS_ReleaseMappedArrayBufferContents(void
JS_FRIEND_API(bool)
JS_IsMappedArrayBufferObject(JSObject *obj)
{
obj = CheckedUnwrap(obj);
if (!obj)
return false;
- return obj->is<ArrayBufferObject>()
- ? obj->as<ArrayBufferObject>().isMappedArrayBuffer()
- : false;
+ return obj->is<ArrayBufferObject>() && obj->as<ArrayBufferObject>().isMapped();
}
JS_FRIEND_API(void *)
JS_GetArrayBufferViewData(JSObject *obj, const JS::AutoCheckCannotGC&)
{
obj = CheckedUnwrap(obj);
if (!obj)
return nullptr;
--- a/js/src/vm/ArrayBufferObject.h
+++ b/js/src/vm/ArrayBufferObject.h
@@ -100,29 +100,31 @@ class ArrayBufferObject : public ArrayBu
static const uint8_t RESERVED_SLOTS = 4;
static const size_t ARRAY_BUFFER_ALIGNMENT = 8;
public:
enum BufferKind {
- PLAIN_BUFFER = 0, // malloced or inline data
- ASMJS_BUFFER = 0x1,
- MAPPED_BUFFER = 0x2,
- KIND_MASK = ASMJS_BUFFER | MAPPED_BUFFER
+ PLAIN = 0, // malloced or inline data
+ ASMJS_MALLOCED = 1,
+ ASMJS_MAPPED = 2,
+ MAPPED = 3,
+
+ KIND_MASK = 0x3
};
protected:
enum ArrayBufferFlags {
// The flags also store the BufferKind
BUFFER_KIND_MASK = BufferKind::KIND_MASK,
- NEUTERED_BUFFER = 0x4,
+ NEUTERED = 0x4,
// 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.
OWNS_DATA = 0x8,
};
@@ -146,17 +148,17 @@ class ArrayBufferObject : public ArrayBu
template<BufferKind Kind>
static BufferContents create(void *data)
{
return BufferContents(static_cast<uint8_t*>(data), Kind);
}
static BufferContents createUnowned(void *data)
{
- return BufferContents(static_cast<uint8_t*>(data), PLAIN_BUFFER);
+ return BufferContents(static_cast<uint8_t*>(data), PLAIN);
}
uint8_t *data() const { return data_; }
BufferKind kind() const { return kind_; }
operator ConvertibleToBool() const { return data_ ? &BufferContents::nonNull : nullptr; }
};
@@ -200,17 +202,17 @@ class ArrayBufferObject : public ArrayBu
bool hasStealableContents() const {
// Inline elements strictly adhere to the corresponding buffer.
if (!ownsData())
return false;
// asm.js buffer contents are transferred by copying, just like inline
// elements.
- if (isAsmJSArrayBuffer())
+ if (isAsmJS())
return false;
// Neutered contents aren't transferrable because we want a neutered
// array's contents to be backed by zeroed memory equal in length to
// the original buffer contents. Transferring these contents would
// allocate new ones based on the current byteLength, which is 0 for a
// neutered array -- not the original byteLength.
return !isNeutered();
@@ -266,36 +268,39 @@ class ArrayBufferObject : public ArrayBu
* Check if the arrayBuffer contains any data. This will return false for
* ArrayBuffer.prototype and neutered ArrayBuffers.
*/
bool hasData() const {
return getClass() == &class_;
}
BufferKind bufferKind() const { return BufferKind(flags() & BUFFER_KIND_MASK); }
- bool isAsmJSArrayBuffer() const { return flags() & ASMJS_BUFFER; }
- bool isMappedArrayBuffer() const { return flags() & MAPPED_BUFFER; }
- bool isNeutered() const { return flags() & NEUTERED_BUFFER; }
+ bool isPlain() const { return bufferKind() == PLAIN; }
+ bool isAsmJSMapped() const { return bufferKind() == ASMJS_MAPPED; }
+ bool isAsmJSMalloced() const { return bufferKind() == ASMJS_MALLOCED; }
+ bool isAsmJS() const { return isAsmJSMapped() || isAsmJSMalloced(); }
+ bool isMapped() const { return bufferKind() == MAPPED; }
+ bool isNeutered() const { return flags() & NEUTERED; }
static bool prepareForAsmJS(JSContext *cx, Handle<ArrayBufferObject*> buffer,
bool usesSignalHandlers);
static bool prepareForAsmJSNoSignals(JSContext *cx, Handle<ArrayBufferObject*> buffer);
static void finalize(FreeOp *fop, JSObject *obj);
static BufferContents createMappedContents(int fd, size_t offset, size_t length);
static size_t offsetOfFlagsSlot() {
return getFixedSlotOffset(FLAGS_SLOT);
}
static size_t offsetOfDataSlot() {
return getFixedSlotOffset(DATA_SLOT);
}
- static uint32_t neuteredFlag() { return NEUTERED_BUFFER; }
+ static uint32_t neuteredFlag() { return NEUTERED; }
protected:
enum OwnsState {
DoesntOwnData = 0,
OwnsData = 1,
};
void setDataPointer(BufferContents contents, OwnsState ownsState);
@@ -304,30 +309,25 @@ class ArrayBufferObject : public ArrayBu
uint32_t flags() const;
void setFlags(uint32_t flags);
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 setIsMappedArrayBuffer() { setFlags(flags() | MAPPED_BUFFER); }
- void setIsNeutered() { setFlags(flags() | NEUTERED_BUFFER); }
+ void setIsAsmJSMalloced() { setFlags((flags() & ~KIND_MASK) | ASMJS_MALLOCED); }
+ void setIsNeutered() { setFlags(flags() | NEUTERED); }
void initialize(size_t byteLength, BufferContents contents, OwnsState ownsState) {
setByteLength(byteLength);
setFlags(0);
setFirstView(nullptr);
setDataPointer(contents, ownsState);
}
-
- void releaseAsmJSArray(FreeOp *fop);
- void releaseAsmJSArrayNoSignals(FreeOp *fop);
- void releaseMappedArray();
};
/*
* ArrayBufferViewObject
*
* Common definitions shared by all array buffer views.
*/
--- a/js/src/vm/StructuredClone.cpp
+++ b/js/src/vm/StructuredClone.cpp
@@ -1171,17 +1171,17 @@ JSStructuredCloneWriter::transferOwnersh
size_t nbytes = arrayBuffer->byteLength();
bool hasStealableContents = arrayBuffer->hasStealableContents();
ArrayBufferObject::BufferContents bufContents =
ArrayBufferObject::stealContents(context(), arrayBuffer, hasStealableContents);
if (!bufContents)
return false; // Destructor will clean up the already-transferred data.
content = bufContents.data();
tag = SCTAG_TRANSFER_MAP_ARRAY_BUFFER;
- if (bufContents.kind() & ArrayBufferObject::MAPPED_BUFFER)
+ if (bufContents.kind() == ArrayBufferObject::MAPPED)
ownership = JS::SCTAG_TMO_MAPPED_DATA;
else
ownership = JS::SCTAG_TMO_ALLOC_DATA;
extraData = nbytes;
} else if (ObjectClassIs(obj, ESClass_SharedArrayBuffer, context())) {
Rooted<SharedArrayBufferObject *> sharedArrayBuffer(context(), &CheckedUnwrap(obj)->as<SharedArrayBufferObject>());
SharedArrayRawBuffer *rawbuf = sharedArrayBuffer->rawBufferObject();