Skip to content

Commit

Permalink
Replace wasm engine with walrus
Browse files Browse the repository at this point in the history
Signed-off-by: HyukWoo Park <[email protected]>
  • Loading branch information
clover2123 committed Jul 17, 2023
1 parent 2cc4dc0 commit f5061f6
Show file tree
Hide file tree
Showing 21 changed files with 61 additions and 1,389 deletions.
10 changes: 0 additions & 10 deletions .github/workflows/es-actions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,6 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y ninja-build gcc-multilib g++-multilib libicu-dev
- name: Patch WABT
working-directory: ./third_party/wasm/wabt
run: |
cp ../../../tools/test/wasm-js/wabt_patch .
patch -p0 < wabt_patch
- name: Build x86
env:
BUILD_OPTIONS: -DCMAKE_SYSTEM_NAME=Linux -DCMAKE_SYSTEM_PROCESSOR=x86 -DESCARGOT_MODE=debug -DESCARGOT_WASM=ON -DESCARGOT_TEMPORAL=ON -DESCARGOT_TCO=ON -DESCARGOT_TEST=ON -DESCARGOT_OUTPUT=shell -GNinja
Expand Down Expand Up @@ -540,11 +535,6 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y ninja-build gcc-multilib g++-multilib
- name: Patch WABT
working-directory: ./third_party/wasm/wabt
run: |
cp ../../../tools/test/wasm-js/wabt_patch .
patch -p0 < wabt_patch
- name: Build x86
env:
BUILD_OPTIONS: -DCMAKE_SYSTEM_NAME=Linux -DCMAKE_SYSTEM_PROCESSOR=x86 -DESCARGOT_MODE=debug -DESCARGOT_WASM=ON -DESCARGOT_TEMPORAL=ON -DESCARGOT_TCO=ON -DESCARGOT_TEST=ON -DESCARGOT_OUTPUT=shell -GNinja
Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,3 @@ cmake_install.cmake
#etc
.vscode
EscargotInfo.h
third_party/wasm/config.h
8 changes: 4 additions & 4 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
path = third_party/googletest
url = https://github.com/google/googletest.git
ignore = untracked
[submodule "third_party/wasm/wabt"]
path = third_party/wasm/wabt
url = https://github.com/WebAssembly/wabt
ignore = untracked
[submodule "third_party/walrus"]
path = third_party/walrus
url = https://github.com/Samsung/walrus.git
ignore = untracked
16 changes: 10 additions & 6 deletions build/escargot.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -135,20 +135,24 @@ IF (ESCARGOT_LIBICU_SUPPORT_WITH_DLOPEN)
SET (ESCARGOT_LIBRARIES ${ESCARGOT_LIBRARIES} runtime-icu-binder-static)
ENDIF()

# WebAssembly (wabt)
# WebAssembly (walrus)
IF (ESCARGOT_WASM)
SET (WASM_CXX_FLAGS
SET (WALRUS_CXXFLAGS
${ESCARGOT_THIRDPARTY_CFLAGS} # we can share flags with gcutil
)
-g3)
SET (WASM_ARCH ${ESCARGOT_ARCH})
SET (WALRUS_HOST ${ESCARGOT_HOST})
SET (WALRUS_ARCH ${ESCARGOT_ARCH})
SET (WALRUS_MODE ${ESCARGOT_MODE})
SET (WALRUS_OUTPUT "shared_lib")

IF (${ESCARGOT_MODE} STREQUAL "release")
SET (WASM_CXX_FLAGS ${WASM_CXX_FLAGS} ${ESCARGOT_CXXFLAGS_RELEASE})
SET (WALRUS_CXXFLAGS ${WALRUS_CXXFLAGS} ${ESCARGOT_CXXFLAGS_RELEASE})
ENDIF()

ADD_SUBDIRECTORY (third_party/wasm)
ADD_SUBDIRECTORY (third_party/walrus)

SET (ESCARGOT_LIBRARIES ${ESCARGOT_LIBRARIES} wasm)
SET (ESCARGOT_LIBRARIES ${ESCARGOT_LIBRARIES} walrus)
ENDIF()

# BUILD
Expand Down
11 changes: 0 additions & 11 deletions src/api/EscargotPublic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4578,11 +4578,6 @@ ObjectRef* WASMOperationsRef::instantiatePromiseOfModuleWithImportObject(Executi
{
return toRef(WASMOperations::instantiatePromiseOfModuleWithImportObject(*toImpl(state), toImpl(promiseOfModule), toImpl(importObj)));
}

void WASMOperationsRef::collectHeap()
{
WASMOperations::collectHeap();
}
#else
ValueRef* WASMOperationsRef::copyStableBufferBytes(ExecutionStateRef* state, ValueRef* source)
{
Expand All @@ -4604,12 +4599,6 @@ ObjectRef* WASMOperationsRef::instantiatePromiseOfModuleWithImportObject(Executi
RELEASE_ASSERT_NOT_REACHED();
return nullptr;
}

void WASMOperationsRef::collectHeap()
{
ESCARGOT_LOG_ERROR("If you want to use this function, you should enable WASM");
RELEASE_ASSERT_NOT_REACHED();
}
#endif

} // namespace Escargot
1 change: 0 additions & 1 deletion src/api/EscargotPublic.h
Original file line number Diff line number Diff line change
Expand Up @@ -2197,7 +2197,6 @@ class ESCARGOT_EXPORT WASMOperationsRef {
static ValueRef* copyStableBufferBytes(ExecutionStateRef* state, ValueRef* source);
static ObjectRef* asyncCompileModule(ExecutionStateRef* state, ValueRef* source);
static ObjectRef* instantiatePromiseOfModuleWithImportObject(ExecutionStateRef* state, PromiseObjectRef* promiseOfModule, ValueRef* importObj);
static void collectHeap();
};

} // namespace Escargot
Expand Down
9 changes: 0 additions & 9 deletions src/runtime/ThreadLocal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,4 @@ void ThreadLocal::finalize()
inited = false;
}

#if defined(ENABLE_WASM)
void ThreadLocal::wasmGC(uint64_t lastCheckTime)
{
ASSERT(inited && !!g_wasmContext.store);
wasm_store_gc(g_wasmContext.store);
g_wasmContext.lastGCCheckTime = lastCheckTime;
}
#endif

} // namespace Escargot
8 changes: 0 additions & 8 deletions src/runtime/ThreadLocal.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,11 @@ class ThreadLocal {
}

#if defined(ENABLE_WASM)
static void wasmGC(uint64_t lastCheckTime);

static wasm_store_t* wasmStore()
{
ASSERT(inited && !!g_wasmContext.store);
return g_wasmContext.store;
}

static uint64_t wasmLastGCCheckTime()
{
ASSERT(inited && !!g_wasmContext.store);
return g_wasmContext.lastGCCheckTime;
}
#endif

static GCEventListenerSet& gcEventListenerSet()
Expand Down
11 changes: 0 additions & 11 deletions src/runtime/VMInstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,6 @@ NT_TIB* getTIB()

namespace Escargot {

#if defined(ENABLE_WASM)
#ifndef ESCARGOT_WASM_GC_CHECK_INTERVAL
#define ESCARGOT_WASM_GC_CHECK_INTERVAL 10000
#endif
#endif

Value VMInstance::functionPrototypeNativeGetter(ExecutionState& state, Object* self, const Value& receiver, const EncodedValue& privateDataFromObjectPrivateArea)
{
ASSERT(self->isFunctionObject());
Expand Down Expand Up @@ -245,11 +239,6 @@ void vmReclaimEndCallback(void* data)
self->m_lastCompressibleStringsTestTime = currentTick;
}
#endif
#if defined(ENABLE_WASM)
if (currentTick - ThreadLocal::wasmLastGCCheckTime() > ESCARGOT_WASM_GC_CHECK_INTERVAL) {
ThreadLocal::wasmGC(currentTick);
}
#endif
#endif

auto& currentCodeSizeTotal = self->compiledByteCodeSize();
Expand Down
2 changes: 1 addition & 1 deletion src/wasm/BuiltinWASM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ static Value builtinWASMInstanceConstructor(ExecutionState& state, Value thisVal

// Instantiate the core of a WebAssembly module module with imports, and let instance be the result.
own wasm_trap_t* trap = nullptr;
own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, imports.data, &trap);
own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, &imports, &trap);
wasm_extern_vec_delete(&imports);

if (!instance) {
Expand Down
2 changes: 1 addition & 1 deletion src/wasm/ExportedFunctionObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ static Value callExportedFunction(ExecutionState& state, Value thisValue, size_t
wasm_functype_delete(functype);

// Let (store, ret) be the result of func_invoke(store, funcaddr, args).
own wasm_trap_t* trap = wasm_func_call(funcaddr, args.data, ret.data);
own wasm_trap_t* trap = wasm_func_call(funcaddr, &args, &ret);

// If ret is error, throw an exception. This exception should be a WebAssembly RuntimeError exception, unless otherwise indicated by the WebAssembly error mapping.
if (trap) {
Expand Down
52 changes: 34 additions & 18 deletions src/wasm/WASMOperations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

namespace Escargot {

static own wasm_trap_t* callbackHostFunction(void* env, const wasm_val_t args[], wasm_val_t results[])
static own wasm_trap_t* callbackHostFunction(void* env, const wasm_val_vec_t* args, wasm_val_vec_t* results)
{
WASMHostFunctionEnvironment* funcEnv = (WASMHostFunctionEnvironment*)env;

Expand All @@ -63,11 +63,37 @@ static own wasm_trap_t* callbackHostFunction(void* env, const wasm_val_t args[],
// For each arg of arguments,
for (size_t i = 0; i < argSize; i++) {
// Append ! ToJSValue(arg) to jsArguments.
jsArguments[i] = WASMValueConverter::wasmToJSValue(state, args[i]);
jsArguments[i] = WASMValueConverter::wasmToJSValue(state, args->data[i]);
}

// Let ret be ? Call(func, undefined, jsArguments).
Value ret = Object::call(state, func, Value(), argSize, jsArguments);
SandBox sb(funcEnv->realm);

struct CallBackData {
Object* func;
size_t argSize;
Value* arguments;
} callBackData;
callBackData.func = func;
callBackData.argSize = argSize;
callBackData.arguments = jsArguments;

auto result = sb.run([](ExecutionState& state, void* data) -> Value {
CallBackData* callBackData = (CallBackData*)data;
return Object::call(state, callBackData->func, Value(), callBackData->argSize, callBackData->arguments);
},
&callBackData);

// Assert: result.[[Type]] is throw or normal.
// If result.[[Type]] is throw, then trigger a WebAssembly trap, and propagate result.[[Value]] to the enclosing JavaScript.
// Otherwise, return result.[[Value]].
if (UNLIKELY(!result.error.isEmpty())) {
std::string errMessage = result.error.toStringWithoutException(state)->toNonGCUTF8StringData();
// throw a WASM exception
wasm_trap_trigger(errMessage.data(), errMessage.length());
ASSERT_NOT_REACHED();
return nullptr;
}

// Let resultsSize be results?s size.
size_t resultsSize = res->size;
Expand All @@ -76,9 +102,10 @@ static own wasm_trap_t* callbackHostFunction(void* env, const wasm_val_t args[],
return nullptr;
}

Value ret = result.result;
if (resultsSize == 1) {
// Otherwise, if resultsSize is 1, return << ToWebAssemblyValue(ret, results[0]) >>
results[0] = WASMValueConverter::wasmToWebAssemblyValue(state, ret, wasm_valtype_kind(res->data[0]));
results->data[0] = WASMValueConverter::wasmToWebAssemblyValue(state, ret, wasm_valtype_kind(res->data[0]));
} else {
// Otherwise,
// Let method be ? GetMethod(ret, @@iterator).
Expand All @@ -98,15 +125,10 @@ static own wasm_trap_t* callbackHostFunction(void* env, const wasm_val_t args[],
// For each value and resultType in values and results, paired linearly,
// Append ToWebAssemblyValue(value, resultType) to wasmValues.
for (size_t i = 0; i < resultsSize; i++) {
results[i] = WASMValueConverter::wasmToWebAssemblyValue(state, values[i], wasm_valtype_kind(res->data[i]));
results->data[i] = WASMValueConverter::wasmToWebAssemblyValue(state, values[i], wasm_valtype_kind(res->data[i]));
}
}

// TODO
// Assert: result.[[Type]] is throw or normal.
// If result.[[Type]] is throw, then trigger a WebAssembly trap, and propagate result.[[Value]] to the enclosing JavaScript.
// Otherwise, return result.[[Value]].

return nullptr;
}

Expand Down Expand Up @@ -146,7 +168,7 @@ static Value wasmInstantiateModule(ExecutionState& state, Value thisValue, size_

// Instantiate the core of a WebAssembly module module with imports, and let instance be the result.
own wasm_trap_t* trap = nullptr;
own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, imports.data, &trap);
own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, &imports, &trap);
wasm_extern_vec_delete(&imports);

if (!instance) {
Expand Down Expand Up @@ -526,7 +548,7 @@ Value WASMOperations::instantiateCoreModule(ExecutionState& state, Value thisVal

// Instantiate the core of a WebAssembly module module with imports, and let instance be the result.
own wasm_trap_t* trap = nullptr;
own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, imports.data, &trap);
own wasm_instance_t* instance = wasm_instance_new(ThreadLocal::wasmStore(), module, &imports, &trap);
wasm_extern_vec_delete(&imports);

if (!instance) {
Expand Down Expand Up @@ -558,12 +580,6 @@ Object* WASMOperations::instantiatePromiseOfModuleWithImportObject(ExecutionStat
return promiseOfModule->then(state, moduleInstantiator);
}

void WASMOperations::collectHeap()
{
// collect (GC) WASM Objects allocated inside WASM heap
wasm_store_gc(ThreadLocal::wasmStore());
}

} // namespace Escargot

#endif // ENABLE_WASM
2 changes: 0 additions & 2 deletions src/wasm/WASMOperations.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ class WASMOperations {
static void readImportsOfModule(ExecutionState& state, wasm_module_t* module, const Value& importObj, wasm_extern_vec_t* imports);
static Value instantiateCoreModule(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget);
static Object* instantiatePromiseOfModuleWithImportObject(ExecutionState& state, PromiseObject* promiseOfModule, Value importObj);

static void collectHeap();
};

} // namespace Escargot
Expand Down
45 changes: 10 additions & 35 deletions src/wasm/WASMValueConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,31 +28,6 @@

namespace Escargot {

#define WASM_I32_VAL(result, i) \
result.kind = WASM_I32; \
result.of.i32 = i;

#define WASM_I64_VAL(result, i) \
result.kind = WASM_I64; \
result.of.i64 = i

#define WASM_F32_VAL(result, z) \
result.kind = WASM_F32; \
result.of.f32 = z;

#define WASM_F64_VAL(result, z) \
result.kind = WASM_F64; \
result.of.f64 = z

#define WASM_REF_VAL(result, r) \
result.kind = WASM_ANYREF; \
result.of.ref = r

#define WASM_INIT_VAL(result) \
wasm_val_t result{}; \
result.kind = WASM_ANYREF; \
result.of.ref = NULL;

Value WASMValueConverter::wasmToJSValue(ExecutionState& state, const wasm_val_t& value)
{
Value result;
Expand Down Expand Up @@ -84,27 +59,27 @@ Value WASMValueConverter::wasmToJSValue(ExecutionState& state, const wasm_val_t&

wasm_val_t WASMValueConverter::wasmToWebAssemblyValue(ExecutionState& state, const Value& value, wasm_valkind_t type)
{
WASM_INIT_VAL(result);
wasm_val_t result = WASM_INIT_VAL;
switch (type) {
case WASM_I32: {
int32_t val = value.toInt32(state);
WASM_I32_VAL(result, val);
result = WASM_I32_VAL(val);
break;
}
case WASM_F32: {
// FIXME Let f32 be ? ToNumber(v) rounded to the nearest representable value using IEEE 754-2019 round to nearest, ties to even mode.
float32_t val = value.toNumber(state);
WASM_F32_VAL(result, val);
result = WASM_F32_VAL(val);
break;
}
case WASM_F64: {
float64_t val = value.toNumber(state);
WASM_F64_VAL(result, val);
result = WASM_F64_VAL(val);
break;
}
case WASM_I64: {
int64_t val = value.toBigInt(state)->toInt64();
WASM_I64_VAL(result, val);
result = WASM_I64_VAL(val);
break;
}
default: {
Expand All @@ -118,22 +93,22 @@ wasm_val_t WASMValueConverter::wasmToWebAssemblyValue(ExecutionState& state, con

wasm_val_t WASMValueConverter::wasmDefaultValue(wasm_valkind_t type)
{
WASM_INIT_VAL(result);
wasm_val_t result = WASM_INIT_VAL;
switch (type) {
case WASM_I32: {
WASM_I32_VAL(result, 0);
result = WASM_I32_VAL(0);
break;
}
case WASM_I64: {
WASM_I64_VAL(result, 0);
result = WASM_I64_VAL(0);
break;
}
case WASM_F32: {
WASM_F32_VAL(result, 0);
result = WASM_F32_VAL(0);
break;
}
case WASM_F64: {
WASM_F64_VAL(result, 0);
result = WASM_F64_VAL(0);
break;
}
default: {
Expand Down
1 change: 1 addition & 0 deletions third_party/walrus
Submodule walrus added at 8f4e6e
Loading

0 comments on commit f5061f6

Please sign in to comment.