Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support SharedArrayBuffer in WASM Memory #1366

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions build/config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,10 @@ ENDIF()

IF (ESCARGOT_WASM)
SET (ESCARGOT_DEFINITIONS ${ESCARGOT_DEFINITIONS} -DENABLE_WASM)
IF (NOT DEFINED ESCARGOT_THREADING)
# threading should be enabled for WASM (WASM threading feature)
SET (ESCARGOT_THREADING ON)
ENDIF()
ENDIF()

IF (ESCARGOT_THREADING)
Expand Down
1 change: 1 addition & 0 deletions build/escargot.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ IF (ESCARGOT_WASM)
SET (WALRUS_MODE ${ESCARGOT_MODE})
SET (WALRUS_OUTPUT "shared_lib")
SET (WALRUS_WASI OFF) # WASI should be OFF
SET (WALRUS_EXTENDED_FEATURES ON) # enable extended features

IF (${ESCARGOT_MODE} STREQUAL "release")
SET (WALRUS_CXXFLAGS ${WALRUS_CXXFLAGS} ${ESCARGOT_CXXFLAGS_RELEASE})
Expand Down
2 changes: 1 addition & 1 deletion src/Escargot.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ if (f.type == Type::B) { puts("failed in msvc."); }
#endif

// FIXME arm devices raise SIGBUS when using unaligned address to __atomic_* functions
#if (defined(COMPILER_GCC) || defined(COMPILER_CLANG)) && !defined(CPU_ARM32) && !defined(CPU_ARM64)
#if defined(COMPILER_GCC) && !defined(CPU_ARM32) && !defined(CPU_ARM64)
#define HAVE_BUILTIN_ATOMIC_FUNCTIONS
#endif

Expand Down
4 changes: 2 additions & 2 deletions src/api/EscargotPublic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ class PlatformBridge : public Platform {
return m_platform->onMallocArrayBufferObjectDataBuffer(sizeInByte);
}

virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte) override
virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte, void* deleterData) override
{
m_platform->onFreeArrayBufferObjectDataBuffer(buffer, sizeInByte);
m_platform->onFreeArrayBufferObjectDataBuffer(buffer, sizeInByte, deleterData);
}

virtual void* onReallocArrayBufferObjectDataBuffer(void* oldBuffer, size_t oldSizeInByte, size_t newSizeInByte) override
Expand Down
2 changes: 1 addition & 1 deletion src/api/EscargotPublic.h
Original file line number Diff line number Diff line change
Expand Up @@ -2169,7 +2169,7 @@ class ESCARGOT_EXPORT PlatformRef {
{
return calloc(sizeInByte, 1);
}
virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte)
virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte, void* deleterData)
{
return free(buffer);
}
Expand Down
23 changes: 23 additions & 0 deletions src/runtime/ArrayBufferObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ ArrayBufferObject* ArrayBufferObject::allocateArrayBuffer(ExecutionState& state,
return obj;
}

ArrayBufferObject* ArrayBufferObject::allocateExternalArrayBuffer(ExecutionState& state, void* dataBlock, size_t byteLength)
{
if (UNLIKELY(byteLength >= ArrayBuffer::maxArrayBufferSize)) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, state.context()->staticStrings().ArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferSize);
}

// creating a fixed length memory buffer from memaddr.
// NOTE) deleter do nothing, dataBlock will be freed in external module
BackingStore* backingStore = BackingStore::createNonSharedBackingStore(dataBlock, byteLength,
[](void* data, size_t length, void* deleterData) {}, nullptr);

return new ArrayBufferObject(state, backingStore);
}

ArrayBufferObject* ArrayBufferObject::cloneArrayBuffer(ExecutionState& state, ArrayBuffer* srcBuffer, size_t srcByteOffset, uint64_t srcLength, Object* constructor)
{
// https://www.ecma-international.org/ecma-262/10.0/#sec-clonearraybuffer
Expand All @@ -84,6 +98,15 @@ ArrayBufferObject::ArrayBufferObject(ExecutionState& state, Object* proto)
{
}

ArrayBufferObject::ArrayBufferObject(ExecutionState& state, BackingStore* backingStore)
: ArrayBufferObject(state)
{
// BackingStore should be valid and non-shared
ASSERT(!!backingStore && !backingStore->isShared());

updateBackingStore(backingStore);
}

void ArrayBufferObject::allocateBuffer(ExecutionState& state, size_t byteLength)
{
detachArrayBuffer();
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/ArrayBufferObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ class ArrayBufferObject : public ArrayBuffer {
public:
explicit ArrayBufferObject(ExecutionState& state);
explicit ArrayBufferObject(ExecutionState& state, Object* proto);
explicit ArrayBufferObject(ExecutionState& state, BackingStore* backingStore);

static ArrayBufferObject* allocateArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength,
Optional<uint64_t> maxByteLength = Optional<uint64_t>(), bool resizeable = true);
static ArrayBufferObject* allocateExternalArrayBuffer(ExecutionState& state, void* dataBlock, size_t byteLength);
static ArrayBufferObject* cloneArrayBuffer(ExecutionState& state, ArrayBuffer* srcBuffer, size_t srcByteOffset, uint64_t srcLength, Object* constructor);

void allocateBuffer(ExecutionState& state, size_t bytelength);
Expand Down
26 changes: 14 additions & 12 deletions src/runtime/BackingStore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace Escargot {
static void backingStorePlatformDeleter(void* data, size_t length, void* deleterData)
{
if (!!data) {
Global::platform()->onFreeArrayBufferObjectDataBuffer(data, length);
Global::platform()->onFreeArrayBufferObjectDataBuffer(data, length, deleterData);
}
}

Expand All @@ -46,15 +46,15 @@ BackingStore* BackingStore::createDefaultResizableNonSharedBackingStore(size_t b
byteLength, backingStorePlatformDeleter, maxByteLength, true);
}

BackingStore* BackingStore::createNonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback callback, void* callbackData)
BackingStore* BackingStore::createNonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback deleter, void* callbackData)
{
return new NonSharedBackingStore(data, byteLength, callback, callbackData, false);
return new NonSharedBackingStore(data, byteLength, deleter, callbackData, false);
}

NonSharedBackingStore::NonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback callback, void* callbackData, bool isAllocatedByPlatform)
NonSharedBackingStore::NonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback deleter, void* callbackData, bool isAllocatedByPlatform)
: m_data(data)
, m_byteLength(byteLength)
, m_deleter(callback)
, m_deleter(deleter)
, m_deleterData(callbackData)
, m_isAllocatedByPlatform(isAllocatedByPlatform)
, m_isResizable(false)
Expand All @@ -67,10 +67,10 @@ NonSharedBackingStore::NonSharedBackingStore(void* data, size_t byteLength, Back
nullptr, nullptr, nullptr);
}

NonSharedBackingStore::NonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback callback, size_t maxByteLength, bool isAllocatedByPlatform)
NonSharedBackingStore::NonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback deleter, size_t maxByteLength, bool isAllocatedByPlatform)
: m_data(data)
, m_byteLength(byteLength)
, m_deleter(callback)
, m_deleter(deleter)
, m_maxByteLength(maxByteLength)
, m_isAllocatedByPlatform(isAllocatedByPlatform)
, m_isResizable(true)
Expand Down Expand Up @@ -138,21 +138,23 @@ BackingStore* BackingStore::createDefaultSharedBackingStore(size_t byteLength)
{
SharedDataBlockInfo* sharedInfo = new SharedDataBlockInfo(
Global::platform()->onMallocArrayBufferObjectDataBuffer(byteLength),
byteLength);
byteLength,
backingStorePlatformDeleter);
return new SharedBackingStore(sharedInfo);
}

BackingStore* BackingStore::createDefaultGrowableSharedBackingStore(size_t byteLength, size_t maxByteLength)
{
SharedDataBlockInfo* sharedInfo = new GrowableSharedDataBlockInfo(
Global::platform()->onMallocArrayBufferObjectDataBuffer(maxByteLength),
byteLength, maxByteLength);
byteLength, maxByteLength,
backingStorePlatformDeleter);
return new SharedBackingStore(sharedInfo);
}

BackingStore* BackingStore::createSharedBackingStore(SharedDataBlockInfo* sharedInfo)
{
ASSERT(sharedInfo->hasValidReference());
// ASSERT(sharedInfo->hasValidReference());
return new SharedBackingStore(sharedInfo);
}

Expand All @@ -163,9 +165,9 @@ void SharedDataBlockInfo::deref()
auto oldValue = m_refCount.fetch_sub(1);
if (oldValue == 1) {
if (isGrowable()) {
Global::platform()->onFreeArrayBufferObjectDataBuffer(m_data, maxByteLength());
m_deleter(m_data, maxByteLength(), nullptr);
} else {
Global::platform()->onFreeArrayBufferObjectDataBuffer(m_data, m_byteLength);
m_deleter(m_data, m_byteLength, nullptr);
}

m_data = nullptr;
Expand Down
32 changes: 26 additions & 6 deletions src/runtime/BackingStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ class BackingStore : public gc, public BufferAddressObserverManager<BackingStore
public:
static BackingStore* createDefaultNonSharedBackingStore(size_t byteLength);
static BackingStore* createDefaultResizableNonSharedBackingStore(size_t byteLength, size_t maxByteLength);
static BackingStore* createNonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback callback, void* callbackData);
static BackingStore* createNonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback deleter, void* callbackData);

#if defined(ENABLE_THREADING)
static BackingStore* createDefaultSharedBackingStore(size_t byteLength);
Expand All @@ -153,6 +153,12 @@ class BackingStore : public gc, public BufferAddressObserverManager<BackingStore
virtual void* deleterData() const = 0;
virtual bool isResizable() const = 0;

virtual size_t byteLengthRMW(size_t newByteLength) // special function used only for WASMMemoryObject
{
ASSERT_NOT_REACHED();
return 0;
}

virtual SharedDataBlockInfo* sharedDataBlockInfo() const
{
ASSERT_NOT_REACHED();
Expand Down Expand Up @@ -221,8 +227,8 @@ class NonSharedBackingStore : public BackingStore {
void* operator new[](size_t size) = delete;

private:
NonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback callback, void* callbackData, bool isAllocatedByPlatform);
NonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback callback, size_t maxByteLength, bool isAllocatedByPlatform);
NonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback deleter, void* callbackData, bool isAllocatedByPlatform);
NonSharedBackingStore(void* data, size_t byteLength, BackingStoreDeleterCallback deleter, size_t maxByteLength, bool isAllocatedByPlatform);

void* m_data;
size_t m_byteLength;
Expand All @@ -238,11 +244,13 @@ class NonSharedBackingStore : public BackingStore {
#if defined(ENABLE_THREADING)
class SharedDataBlockInfo {
public:
SharedDataBlockInfo(void* data, size_t byteLength)
SharedDataBlockInfo(void* data, size_t byteLength, BackingStoreDeleterCallback deleter)
: m_data(data)
, m_byteLength(byteLength)
, m_refCount(0)
, m_deleter(deleter)
{
ASSERT(!!deleter);
}

virtual ~SharedDataBlockInfo() {}
Expand Down Expand Up @@ -276,6 +284,12 @@ class SharedDataBlockInfo {
return m_byteLength.load();
}

size_t byteLengthRMW(size_t newByteLength)
{
ASSERT(hasValidReference());
return m_byteLength.exchange(newByteLength);
}

void ref()
{
m_refCount++;
Expand All @@ -293,12 +307,13 @@ class SharedDataBlockInfo {
// defined as atomic value to not to use a lock
std::atomic<size_t> m_byteLength;
std::atomic<size_t> m_refCount;
BackingStoreDeleterCallback m_deleter;
};

class GrowableSharedDataBlockInfo : public SharedDataBlockInfo {
public:
GrowableSharedDataBlockInfo(void* data, size_t byteLength, size_t maxByteLength)
: SharedDataBlockInfo(data, byteLength)
GrowableSharedDataBlockInfo(void* data, size_t byteLength, size_t maxByteLength, BackingStoreDeleterCallback deleter)
: SharedDataBlockInfo(data, byteLength, deleter)
, m_maxByteLength(maxByteLength)
{
}
Expand Down Expand Up @@ -368,6 +383,11 @@ class SharedBackingStore : public BackingStore {
return m_sharedDataBlockInfo->isGrowable();
}

virtual size_t byteLengthRMW(size_t newByteLength) override
{
return m_sharedDataBlockInfo->byteLengthRMW(newByteLength);
}

virtual void resize(size_t newByteLength) override;

void* operator new(size_t size);
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Platform {
virtual ~Platform() {}
// ArrayBuffer
virtual void* onMallocArrayBufferObjectDataBuffer(size_t sizeInByte) = 0;
virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte) = 0;
virtual void onFreeArrayBufferObjectDataBuffer(void* buffer, size_t sizeInByte, void* deleterData) = 0;
virtual void* onReallocArrayBufferObjectDataBuffer(void* oldBuffer, size_t oldSizeInByte, size_t newSizeInByte) = 0;

// Promise
Expand Down
20 changes: 20 additions & 0 deletions src/runtime/SharedArrayBufferObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,20 @@ SharedArrayBufferObject* SharedArrayBufferObject::allocateSharedArrayBuffer(Exec
return new SharedArrayBufferObject(state, proto, byteLength);
}

SharedArrayBufferObject* SharedArrayBufferObject::allocateExternalSharedArrayBuffer(ExecutionState& state, void* dataBlock, size_t byteLength)
{
if (UNLIKELY(byteLength >= ArrayBuffer::maxArrayBufferSize)) {
ErrorObject::throwBuiltinError(state, ErrorCode::RangeError, state.context()->staticStrings().SharedArrayBuffer.string(), false, String::emptyString, ErrorObject::Messages::GlobalObject_InvalidArrayBufferSize);
}

// creating a fixed length memory buffer from memaddr.
// NOTE) deleter do nothing, dataBlock will be freed in external module
SharedDataBlockInfo* sharedInfo = new SharedDataBlockInfo(dataBlock, byteLength,
[](void* data, size_t length, void* deleterData) {});

return new SharedArrayBufferObject(state, state.context()->globalObject()->sharedArrayBufferPrototype(), sharedInfo);
}

void* SharedArrayBufferObject::operator new(size_t size)
{
static MAY_THREAD_LOCAL bool typeInited = false;
Expand Down Expand Up @@ -272,6 +286,12 @@ void SharedArrayBufferObject::setValueInBuffer(ExecutionState& state, size_t byt
}
#endif
}

size_t SharedArrayBufferObject::byteLengthRMW(size_t newByteLength)
{
ASSERT(m_backingStore.hasValue());
return m_backingStore->byteLengthRMW(newByteLength);
}
} // namespace Escargot

#endif
3 changes: 3 additions & 0 deletions src/runtime/SharedArrayBufferObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class SharedArrayBufferObject : public ArrayBuffer {
SharedArrayBufferObject(ExecutionState& state, Object* proto, SharedDataBlockInfo* sharedInfo);

static SharedArrayBufferObject* allocateSharedArrayBuffer(ExecutionState& state, Object* constructor, uint64_t byteLength, Optional<uint64_t> maxByteLength);
static SharedArrayBufferObject* allocateExternalSharedArrayBuffer(ExecutionState& state, void* dataBlock, size_t byteLength);

virtual bool isSharedArrayBufferObject() const override
{
Expand All @@ -47,6 +48,8 @@ class SharedArrayBufferObject : public ArrayBuffer {

void* operator new(size_t size);
void* operator new[](size_t size) = delete;

size_t byteLengthRMW(size_t newByteLength);
};
} // namespace Escargot

Expand Down
1 change: 1 addition & 0 deletions src/runtime/StaticStrings.h
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,7 @@ namespace Escargot {
F(memory) \
F(module) \
F(table) \
F(shared) \
F(v128) \
F(validate)
#else
Expand Down
Loading
Loading