mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-29 02:27:30 +09:00
Implement growable SharedArrayBuffer
This commit is contained in:
parent
f92b3d152e
commit
4d11dcb096
5 changed files with 246 additions and 19 deletions
|
|
@ -561,6 +561,7 @@ MSG_DEF(JSMSG_SHORT_TYPED_ARRAY_RETURNED, 2, JSEXN_TYPEERR, "expected TypedArray
|
||||||
|
|
||||||
// Shared array buffer
|
// Shared array buffer
|
||||||
MSG_DEF(JSMSG_SHARED_ARRAY_BAD_LENGTH, 0, JSEXN_RANGEERR, "length argument out of range")
|
MSG_DEF(JSMSG_SHARED_ARRAY_BAD_LENGTH, 0, JSEXN_RANGEERR, "length argument out of range")
|
||||||
|
MSG_DEF(JSMSG_SHARED_ARRAY_NOT_GROWABLE, 0, JSEXN_TYPEERR, "SharedArrayBuffer is not growable")
|
||||||
MSG_DEF(JSMSG_NON_SHARED_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected SharedArrayBuffer, but species constructor returned non-SharedArrayBuffer")
|
MSG_DEF(JSMSG_NON_SHARED_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected SharedArrayBuffer, but species constructor returned non-SharedArrayBuffer")
|
||||||
MSG_DEF(JSMSG_SAME_SHARED_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected different SharedArrayBuffer, but species constructor returned same SharedArrayBuffer")
|
MSG_DEF(JSMSG_SAME_SHARED_ARRAY_BUFFER_RETURNED, 0, JSEXN_TYPEERR, "expected different SharedArrayBuffer, but species constructor returned same SharedArrayBuffer")
|
||||||
MSG_DEF(JSMSG_SHORT_SHARED_ARRAY_BUFFER_RETURNED, 2, JSEXN_TYPEERR, "expected SharedArrayBuffer with at least {0} bytes, but species constructor returns SharedArrayBuffer with {1} bytes")
|
MSG_DEF(JSMSG_SHORT_SHARED_ARRAY_BUFFER_RETURNED, 2, JSEXN_TYPEERR, "expected SharedArrayBuffer with at least {0} bytes, but species constructor returns SharedArrayBuffer with {1} bytes")
|
||||||
|
|
|
||||||
40
js/src/tests/non262/SharedArrayBuffer/growable.js
Normal file
40
js/src/tests/non262/SharedArrayBuffer/growable.js
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
// |reftest| skip-if(!this.SharedArrayBuffer)
|
||||||
|
|
||||||
|
if (typeof SharedArrayBuffer === "function") {
|
||||||
|
const fixed = new SharedArrayBuffer(4);
|
||||||
|
assertEq(fixed.byteLength, 4);
|
||||||
|
assertEq(fixed.maxByteLength, 4);
|
||||||
|
assertEq(fixed.growable, false);
|
||||||
|
assertThrowsInstanceOf(() => fixed.grow(4), TypeError);
|
||||||
|
|
||||||
|
assertThrowsInstanceOf(() => new SharedArrayBuffer(-1), RangeError);
|
||||||
|
assertThrowsInstanceOf(() => new SharedArrayBuffer(8, {maxByteLength: 4}), RangeError);
|
||||||
|
|
||||||
|
let optionGetterCalled = false;
|
||||||
|
const growable = new SharedArrayBuffer(4, {
|
||||||
|
get maxByteLength() {
|
||||||
|
optionGetterCalled = true;
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assertEq(optionGetterCalled, true);
|
||||||
|
assertEq(growable.byteLength, 4);
|
||||||
|
assertEq(growable.maxByteLength, 16);
|
||||||
|
assertEq(growable.growable, true);
|
||||||
|
|
||||||
|
const before = new Uint8Array(growable);
|
||||||
|
before[0] = 37;
|
||||||
|
assertEq(growable.grow(12), undefined);
|
||||||
|
assertEq(growable.byteLength, 12);
|
||||||
|
assertEq(growable.maxByteLength, 16);
|
||||||
|
|
||||||
|
const after = new Uint8Array(growable);
|
||||||
|
assertEq(after.length, 12);
|
||||||
|
assertEq(after[0], 37);
|
||||||
|
|
||||||
|
assertThrowsInstanceOf(() => growable.grow(11), RangeError);
|
||||||
|
assertThrowsInstanceOf(() => growable.grow(17), RangeError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(true, true);
|
||||||
|
|
@ -1245,7 +1245,7 @@ js::WasmArrayBufferMaxSize(const ArrayBufferObjectMaybeShared* buf)
|
||||||
if (buf->is<ArrayBufferObject>())
|
if (buf->is<ArrayBufferObject>())
|
||||||
return buf->as<ArrayBufferObject>().wasmMaxSize();
|
return buf->as<ArrayBufferObject>().wasmMaxSize();
|
||||||
|
|
||||||
return Some(buf->as<SharedArrayBufferObject>().byteLength());
|
return Some(buf->as<SharedArrayBufferObject>().maxByteLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "mozilla/Atomics.h"
|
#include "mozilla/Atomics.h"
|
||||||
|
|
||||||
#include "jsfriendapi.h"
|
#include "jsfriendapi.h"
|
||||||
|
#include "jsnum.h"
|
||||||
#include "jsprf.h"
|
#include "jsprf.h"
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
|
|
@ -104,15 +105,18 @@ SharedArrayAllocSize(uint32_t length)
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedArrayRawBuffer*
|
SharedArrayRawBuffer*
|
||||||
SharedArrayRawBuffer::New(JSContext* cx, uint32_t length)
|
SharedArrayRawBuffer::New(JSContext* cx, uint32_t length, uint32_t maxLength, bool growable)
|
||||||
{
|
{
|
||||||
// The value (uint32_t)-1 is used as a signal in various places,
|
// The value (uint32_t)-1 is used as a signal in various places,
|
||||||
// so guard against it on principle.
|
// so guard against it on principle.
|
||||||
MOZ_ASSERT(length != (uint32_t)-1);
|
MOZ_ASSERT(length != (uint32_t)-1);
|
||||||
|
MOZ_ASSERT(maxLength != (uint32_t)-1);
|
||||||
|
MOZ_ASSERT(maxLength >= length);
|
||||||
|
|
||||||
// Add a page for the header and round to a page boundary.
|
// Add a page for the header and round to a page boundary.
|
||||||
uint32_t allocSize = SharedArrayAllocSize(length);
|
uint32_t allocationLength = growable ? maxLength : length;
|
||||||
if (allocSize <= length)
|
uint32_t allocSize = SharedArrayAllocSize(allocationLength);
|
||||||
|
if (allocSize <= allocationLength)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Test >= to guard against the case where multiple extant runtimes
|
// Test >= to guard against the case where multiple extant runtimes
|
||||||
|
|
@ -127,7 +131,8 @@ SharedArrayRawBuffer::New(JSContext* cx, uint32_t length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool preparedForAsmJS = jit::JitOptions.asmJSAtomicsEnable && IsValidAsmJSHeapLength(length);
|
bool preparedForAsmJS =
|
||||||
|
!growable && jit::JitOptions.asmJSAtomicsEnable && IsValidAsmJSHeapLength(length);
|
||||||
|
|
||||||
void* p = nullptr;
|
void* p = nullptr;
|
||||||
if (preparedForAsmJS) {
|
if (preparedForAsmJS) {
|
||||||
|
|
@ -161,8 +166,9 @@ SharedArrayRawBuffer::New(JSContext* cx, uint32_t length)
|
||||||
|
|
||||||
uint8_t* buffer = reinterpret_cast<uint8_t*>(p) + gc::SystemPageSize();
|
uint8_t* buffer = reinterpret_cast<uint8_t*>(p) + gc::SystemPageSize();
|
||||||
uint8_t* base = buffer - sizeof(SharedArrayRawBuffer);
|
uint8_t* base = buffer - sizeof(SharedArrayRawBuffer);
|
||||||
SharedArrayRawBuffer* rawbuf = new (base) SharedArrayRawBuffer(buffer, length, preparedForAsmJS);
|
SharedArrayRawBuffer* rawbuf =
|
||||||
MOZ_ASSERT(rawbuf->length == length); // Deallocation needs this
|
new (base) SharedArrayRawBuffer(buffer, length, maxLength, growable, preparedForAsmJS);
|
||||||
|
MOZ_ASSERT(rawbuf->allocatedByteLength() == allocationLength); // Deallocation needs this.
|
||||||
return rawbuf;
|
return rawbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -201,7 +207,7 @@ SharedArrayRawBuffer::dropReference()
|
||||||
MOZ_ASSERT(p.asValue() % gc::SystemPageSize() == 0);
|
MOZ_ASSERT(p.asValue() % gc::SystemPageSize() == 0);
|
||||||
|
|
||||||
uint8_t* address = p.unwrap(/*safe - only reference*/);
|
uint8_t* address = p.unwrap(/*safe - only reference*/);
|
||||||
uint32_t allocSize = SharedArrayAllocSize(this->length);
|
uint32_t allocSize = SharedArrayAllocSize(this->allocatedByteLength());
|
||||||
|
|
||||||
if (this->preparedForAsmJS) {
|
if (this->preparedForAsmJS) {
|
||||||
uint32_t mappedSize = SharedArrayMappedSize(allocSize);
|
uint32_t mappedSize = SharedArrayMappedSize(allocSize);
|
||||||
|
|
@ -221,6 +227,23 @@ SharedArrayRawBuffer::dropReference()
|
||||||
numLive--;
|
numLive--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SharedArrayRawBuffer::growTo(uint32_t newLength)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(growable);
|
||||||
|
MOZ_ASSERT(newLength <= maxLength);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
uint32_t oldLength = length;
|
||||||
|
if (newLength < oldLength)
|
||||||
|
return false;
|
||||||
|
if (newLength == oldLength)
|
||||||
|
return true;
|
||||||
|
if (length.compareExchange(oldLength, newLength))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
MOZ_ALWAYS_INLINE bool
|
MOZ_ALWAYS_INLINE bool
|
||||||
SharedArrayBufferObject::byteLengthGetterImpl(JSContext* cx, const CallArgs& args)
|
SharedArrayBufferObject::byteLengthGetterImpl(JSContext* cx, const CallArgs& args)
|
||||||
|
|
@ -237,6 +260,112 @@ SharedArrayBufferObject::byteLengthGetter(JSContext* cx, unsigned argc, Value* v
|
||||||
return CallNonGenericMethod<IsSharedArrayBuffer, byteLengthGetterImpl>(cx, args);
|
return CallNonGenericMethod<IsSharedArrayBuffer, byteLengthGetterImpl>(cx, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE bool
|
||||||
|
SharedArrayBufferObject::maxByteLengthGetterImpl(JSContext* cx, const CallArgs& args)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsSharedArrayBuffer(args.thisv()));
|
||||||
|
args.rval().setInt32(args.thisv().toObject().as<SharedArrayBufferObject>().maxByteLength());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SharedArrayBufferObject::maxByteLengthGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
return CallNonGenericMethod<IsSharedArrayBuffer, maxByteLengthGetterImpl>(cx, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE bool
|
||||||
|
SharedArrayBufferObject::growableGetterImpl(JSContext* cx, const CallArgs& args)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsSharedArrayBuffer(args.thisv()));
|
||||||
|
args.rval().setBoolean(args.thisv().toObject().as<SharedArrayBufferObject>().isGrowable());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SharedArrayBufferObject::growableGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
return CallNonGenericMethod<IsSharedArrayBuffer, growableGetterImpl>(cx, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ReportSharedArrayBufferNotGrowable(JSContext* cx)
|
||||||
|
{
|
||||||
|
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SHARED_ARRAY_NOT_GROWABLE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
ReportSharedArrayBufferLengthOutOfRange(JSContext* cx)
|
||||||
|
{
|
||||||
|
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SHARED_ARRAY_BAD_LENGTH);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
GetSharedArrayBufferMaxByteLengthOption(JSContext* cx, HandleValue options,
|
||||||
|
uint32_t byteLength, uint32_t* maxByteLength,
|
||||||
|
bool* growable)
|
||||||
|
{
|
||||||
|
*maxByteLength = byteLength;
|
||||||
|
*growable = false;
|
||||||
|
|
||||||
|
if (!options.isObject())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
RootedObject opts(cx, &options.toObject());
|
||||||
|
RootedValue maxByteLengthValue(cx);
|
||||||
|
if (!GetProperty(cx, opts, opts, cx->names().maxByteLength, &maxByteLengthValue))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (maxByteLengthValue.isUndefined())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
uint64_t max;
|
||||||
|
if (!ToIndex(cx, maxByteLengthValue, &max))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (max > INT32_MAX || max < byteLength)
|
||||||
|
return ReportSharedArrayBufferLengthOutOfRange(cx);
|
||||||
|
|
||||||
|
*maxByteLength = uint32_t(max);
|
||||||
|
*growable = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ALWAYS_INLINE bool
|
||||||
|
SharedArrayBufferObject::fun_grow_impl(JSContext* cx, const CallArgs& args)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsSharedArrayBuffer(args.thisv()));
|
||||||
|
|
||||||
|
Rooted<SharedArrayBufferObject*> buffer(cx,
|
||||||
|
&args.thisv().toObject().as<SharedArrayBufferObject>());
|
||||||
|
if (!buffer->isGrowable())
|
||||||
|
return ReportSharedArrayBufferNotGrowable(cx);
|
||||||
|
|
||||||
|
uint64_t newByteLength;
|
||||||
|
if (!ToIndex(cx, args.get(0), &newByteLength))
|
||||||
|
return false;
|
||||||
|
if (newByteLength > INT32_MAX)
|
||||||
|
return ReportSharedArrayBufferLengthOutOfRange(cx);
|
||||||
|
|
||||||
|
uint32_t newLength = uint32_t(newByteLength);
|
||||||
|
if (newLength > buffer->maxByteLength() || !buffer->growTo(newLength))
|
||||||
|
return ReportSharedArrayBufferLengthOutOfRange(cx);
|
||||||
|
|
||||||
|
args.rval().setUndefined();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
SharedArrayBufferObject::fun_grow(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
return CallNonGenericMethod<IsSharedArrayBuffer, fun_grow_impl>(cx, args);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
|
SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value* vp)
|
||||||
{
|
{
|
||||||
|
|
@ -245,11 +374,19 @@ SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value*
|
||||||
if (!ThrowIfNotConstructing(cx, args, "SharedArrayBuffer"))
|
if (!ThrowIfNotConstructing(cx, args, "SharedArrayBuffer"))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
uint64_t length64;
|
||||||
|
if (!ToIndex(cx, args.get(0), &length64))
|
||||||
|
return false;
|
||||||
// Bugs 1068458, 1161298: Limit length to 2^31-1.
|
// Bugs 1068458, 1161298: Limit length to 2^31-1.
|
||||||
uint32_t length;
|
if (length64 > INT32_MAX)
|
||||||
bool overflow_unused;
|
return ReportSharedArrayBufferLengthOutOfRange(cx);
|
||||||
if (!ToLengthClamped(cx, args.get(0), &length, &overflow_unused) || length > INT32_MAX) {
|
uint32_t length = uint32_t(length64);
|
||||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_SHARED_ARRAY_BAD_LENGTH);
|
|
||||||
|
uint32_t maxByteLength;
|
||||||
|
bool growable;
|
||||||
|
if (!GetSharedArrayBufferMaxByteLengthOption(cx, args.get(1), length,
|
||||||
|
&maxByteLength, &growable))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -258,7 +395,7 @@ SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value*
|
||||||
if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
|
if (!GetPrototypeFromConstructor(cx, newTarget, &proto))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
JSObject* bufobj = New(cx, length, proto);
|
JSObject* bufobj = New(cx, length, maxByteLength, growable, proto);
|
||||||
if (!bufobj)
|
if (!bufobj)
|
||||||
return false;
|
return false;
|
||||||
args.rval().setObject(*bufobj);
|
args.rval().setObject(*bufobj);
|
||||||
|
|
@ -266,9 +403,10 @@ SharedArrayBufferObject::class_constructor(JSContext* cx, unsigned argc, Value*
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedArrayBufferObject*
|
SharedArrayBufferObject*
|
||||||
SharedArrayBufferObject::New(JSContext* cx, uint32_t length, HandleObject proto)
|
SharedArrayBufferObject::New(JSContext* cx, uint32_t length, uint32_t maxLength, bool growable,
|
||||||
|
HandleObject proto)
|
||||||
{
|
{
|
||||||
SharedArrayRawBuffer* buffer = SharedArrayRawBuffer::New(cx, length);
|
SharedArrayRawBuffer* buffer = SharedArrayRawBuffer::New(cx, length, maxLength, growable);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
|
@ -341,7 +479,7 @@ SharedArrayBufferObject::addSizeOfExcludingThis(JSObject* obj, mozilla::MallocSi
|
||||||
// just live with the risk.
|
// just live with the risk.
|
||||||
const SharedArrayBufferObject& buf = obj->as<SharedArrayBufferObject>();
|
const SharedArrayBufferObject& buf = obj->as<SharedArrayBufferObject>();
|
||||||
info->objectsNonHeapElementsShared +=
|
info->objectsNonHeapElementsShared +=
|
||||||
buf.byteLength() / buf.rawBufferObject()->refcount();
|
buf.rawBufferObject()->allocatedByteLength() / buf.rawBufferObject()->refcount();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
|
|
@ -409,12 +547,15 @@ static const JSPropertySpec static_properties[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const JSFunctionSpec prototype_functions[] = {
|
static const JSFunctionSpec prototype_functions[] = {
|
||||||
|
JS_FN("grow", SharedArrayBufferObject::fun_grow, 1, 0),
|
||||||
JS_SELF_HOSTED_FN("slice", "SharedArrayBufferSlice", 2, 0),
|
JS_SELF_HOSTED_FN("slice", "SharedArrayBufferSlice", 2, 0),
|
||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
static const JSPropertySpec prototype_properties[] = {
|
static const JSPropertySpec prototype_properties[] = {
|
||||||
JS_PSG("byteLength", SharedArrayBufferObject::byteLengthGetter, 0),
|
JS_PSG("byteLength", SharedArrayBufferObject::byteLengthGetter, 0),
|
||||||
|
JS_PSG("growable", SharedArrayBufferObject::growableGetter, 0),
|
||||||
|
JS_PSG("maxByteLength", SharedArrayBufferObject::maxByteLengthGetter, 0),
|
||||||
JS_STRING_SYM_PS(toStringTag, "SharedArrayBuffer", JSPROP_READONLY),
|
JS_STRING_SYM_PS(toStringTag, "SharedArrayBuffer", JSPROP_READONLY),
|
||||||
JS_PS_END
|
JS_PS_END
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,9 @@ class SharedArrayRawBuffer
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> refcount_;
|
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> refcount_;
|
||||||
uint32_t length;
|
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> length;
|
||||||
|
uint32_t maxLength;
|
||||||
|
bool growable;
|
||||||
bool preparedForAsmJS;
|
bool preparedForAsmJS;
|
||||||
|
|
||||||
// A list of structures representing tasks waiting on some
|
// A list of structures representing tasks waiting on some
|
||||||
|
|
@ -52,9 +54,12 @@ class SharedArrayRawBuffer
|
||||||
FutexWaiter* waiters_;
|
FutexWaiter* waiters_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
SharedArrayRawBuffer(uint8_t* buffer, uint32_t length, bool preparedForAsmJS)
|
SharedArrayRawBuffer(uint8_t* buffer, uint32_t length, uint32_t maxLength, bool growable,
|
||||||
|
bool preparedForAsmJS)
|
||||||
: refcount_(1),
|
: refcount_(1),
|
||||||
length(length),
|
length(length),
|
||||||
|
maxLength(maxLength),
|
||||||
|
growable(growable),
|
||||||
preparedForAsmJS(preparedForAsmJS),
|
preparedForAsmJS(preparedForAsmJS),
|
||||||
waiters_(nullptr)
|
waiters_(nullptr)
|
||||||
{
|
{
|
||||||
|
|
@ -62,7 +67,11 @@ class SharedArrayRawBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static SharedArrayRawBuffer* New(JSContext* cx, uint32_t length);
|
static SharedArrayRawBuffer* New(JSContext* cx, uint32_t length, uint32_t maxLength,
|
||||||
|
bool growable);
|
||||||
|
static SharedArrayRawBuffer* New(JSContext* cx, uint32_t length) {
|
||||||
|
return New(cx, length, length, false);
|
||||||
|
}
|
||||||
|
|
||||||
// This may be called from multiple threads. The caller must take
|
// This may be called from multiple threads. The caller must take
|
||||||
// care of mutual exclusion.
|
// care of mutual exclusion.
|
||||||
|
|
@ -85,6 +94,20 @@ class SharedArrayRawBuffer
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t maxByteLength() const {
|
||||||
|
return growable ? maxLength : byteLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t allocatedByteLength() const {
|
||||||
|
return growable ? maxLength : byteLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isGrowable() const {
|
||||||
|
return growable;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool growTo(uint32_t newLength);
|
||||||
|
|
||||||
bool isPreparedForAsmJS() const {
|
bool isPreparedForAsmJS() const {
|
||||||
return preparedForAsmJS;
|
return preparedForAsmJS;
|
||||||
}
|
}
|
||||||
|
|
@ -117,6 +140,9 @@ class SharedArrayRawBuffer
|
||||||
class SharedArrayBufferObject : public ArrayBufferObjectMaybeShared
|
class SharedArrayBufferObject : public ArrayBufferObjectMaybeShared
|
||||||
{
|
{
|
||||||
static bool byteLengthGetterImpl(JSContext* cx, const CallArgs& args);
|
static bool byteLengthGetterImpl(JSContext* cx, const CallArgs& args);
|
||||||
|
static bool maxByteLengthGetterImpl(JSContext* cx, const CallArgs& args);
|
||||||
|
static bool growableGetterImpl(JSContext* cx, const CallArgs& args);
|
||||||
|
static bool fun_grow_impl(JSContext* cx, const CallArgs& args);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// RAWBUF_SLOT holds a pointer (as "private" data) to the
|
// RAWBUF_SLOT holds a pointer (as "private" data) to the
|
||||||
|
|
@ -128,13 +154,23 @@ class SharedArrayBufferObject : public ArrayBufferObjectMaybeShared
|
||||||
static const Class class_;
|
static const Class class_;
|
||||||
|
|
||||||
static bool byteLengthGetter(JSContext* cx, unsigned argc, Value* vp);
|
static bool byteLengthGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
static bool maxByteLengthGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
static bool growableGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
static bool fun_grow(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
|
||||||
static bool class_constructor(JSContext* cx, unsigned argc, Value* vp);
|
static bool class_constructor(JSContext* cx, unsigned argc, Value* vp);
|
||||||
|
|
||||||
// Create a SharedArrayBufferObject with a new SharedArrayRawBuffer.
|
// Create a SharedArrayBufferObject with a new SharedArrayRawBuffer.
|
||||||
static SharedArrayBufferObject* New(JSContext* cx,
|
static SharedArrayBufferObject* New(JSContext* cx,
|
||||||
uint32_t length,
|
uint32_t length,
|
||||||
|
uint32_t maxLength,
|
||||||
|
bool growable,
|
||||||
HandleObject proto = nullptr);
|
HandleObject proto = nullptr);
|
||||||
|
static SharedArrayBufferObject* New(JSContext* cx,
|
||||||
|
uint32_t length,
|
||||||
|
HandleObject proto = nullptr) {
|
||||||
|
return New(cx, length, length, false, proto);
|
||||||
|
}
|
||||||
|
|
||||||
// Create a SharedArrayBufferObject using an existing SharedArrayRawBuffer.
|
// Create a SharedArrayBufferObject using an existing SharedArrayRawBuffer.
|
||||||
static SharedArrayBufferObject* New(JSContext* cx,
|
static SharedArrayBufferObject* New(JSContext* cx,
|
||||||
|
|
@ -164,6 +200,15 @@ class SharedArrayBufferObject : public ArrayBufferObjectMaybeShared
|
||||||
uint32_t byteLength() const {
|
uint32_t byteLength() const {
|
||||||
return rawBufferObject()->byteLength();
|
return rawBufferObject()->byteLength();
|
||||||
}
|
}
|
||||||
|
uint32_t maxByteLength() const {
|
||||||
|
return rawBufferObject()->maxByteLength();
|
||||||
|
}
|
||||||
|
bool isGrowable() const {
|
||||||
|
return rawBufferObject()->isGrowable();
|
||||||
|
}
|
||||||
|
[[nodiscard]] bool growTo(uint32_t newLength) {
|
||||||
|
return rawBufferObject()->growTo(newLength);
|
||||||
|
}
|
||||||
bool isPreparedForAsmJS() const {
|
bool isPreparedForAsmJS() const {
|
||||||
return rawBufferObject()->isPreparedForAsmJS();
|
return rawBufferObject()->isPreparedForAsmJS();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue