summaryrefslogtreecommitdiff
path: root/src/wasm-js.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm-js.cpp')
-rw-r--r--src/wasm-js.cpp82
1 files changed, 62 insertions, 20 deletions
diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp
index 9c9096ad8..d978e4a2a 100644
--- a/src/wasm-js.cpp
+++ b/src/wasm-js.cpp
@@ -26,6 +26,7 @@
#include "asm2wasm.h"
#include "wasm-interpreter.h"
#include "wasm-s-parser.h"
+#include "wasm-binary.h"
#include "wasm-printing.h"
using namespace cashew;
@@ -67,13 +68,18 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_asm2wasm(char *input) {
Ref asmjs = builder.parseToplevel(input);
module = new AllocatingModule();
- module->memory.initial = EM_ASM_INT_V({
+ uint32_t providedMemory = EM_ASM_INT_V({
return Module['providedTotalMemory']; // we receive the size of memory from emscripten
});
+ if (providedMemory & ~Memory::kPageMask) {
+ std::cerr << "Error: provided memory is not a multiple of the 64k wasm page size\n";
+ exit(EXIT_FAILURE);
+ }
+ module->memory.initial = providedMemory / Memory::kPageSize;
module->memory.max = pre.memoryGrowth ? -1 : module->memory.initial;
if (wasmJSDebug) std::cerr << "wasming...\n";
- asm2wasm = new Asm2WasmBuilder(*module, pre.memoryGrowth, debug);
+ asm2wasm = new Asm2WasmBuilder(*module, pre.memoryGrowth, debug, false /* TODO: support imprecise? */);
asm2wasm->processAsm(asmjs);
if (wasmJSDebug) std::cerr << "optimizing...\n";
@@ -95,8 +101,22 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_asm2wasm(char *input) {
}
}
+void finalizeModule() {
+ uint32_t providedMemory = EM_ASM_INT_V({
+ return Module['providedTotalMemory']; // we receive the size of memory from emscripten
+ });
+ if (providedMemory & ~Memory::kPageMask) {
+ std::cerr << "Error: provided memory is not a multiple of the 64k wasm page size\n";
+ exit(EXIT_FAILURE);
+ }
+ module->memory.initial = providedMemory / Memory::kPageSize;
+ module->memory.max = (module->exportsMap.find(GROW_WASM_MEMORY) != module->exportsMap.end()) ? -1 : module->memory.initial;
+
+ // global mapping is done in js in post.js
+}
+
// loads wasm code in s-expression format
-extern "C" void EMSCRIPTEN_KEEPALIVE load_s_expr2wasm(char *input, char *mappedGlobals) {
+extern "C" void EMSCRIPTEN_KEEPALIVE load_s_expr2wasm(char *input) {
prepare2wasm();
if (wasmJSDebug) std::cerr << "wasm-s-expression parsing...\n";
@@ -114,12 +134,25 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_s_expr2wasm(char *input, char *mappedG
abort();
});
- module->memory.initial = EM_ASM_INT_V({
- return Module['providedTotalMemory']; // we receive the size of memory from emscripten
- });
- module->memory.max = (module->exportsMap.find(GROW_WASM_MEMORY) != module->exportsMap.end()) ? -1 : module->memory.initial;
+ finalizeModule();
+}
- // global mapping is done in js in post.js
+// loads wasm code in binary format
+extern "C" void EMSCRIPTEN_KEEPALIVE load_binary2wasm(char *raw, int32_t size) {
+ prepare2wasm();
+
+ if (wasmJSDebug) std::cerr << "wasm-binary parsing...\n";
+
+ module = new AllocatingModule();
+ std::vector<char> input;
+ input.resize(size);
+ for (int32_t i = 0; i < size; i++) {
+ input[i] = raw[i];
+ }
+ WasmBinaryBuilder parser(*module, input, debug);
+ parser.read();
+
+ finalizeModule();
}
// instantiates the loaded wasm (which might be from asm2wasm, or
@@ -148,19 +181,16 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
struct JSExternalInterface : ModuleInstance::ExternalInterface {
void init(Module& wasm) override {
- // if we have memory segments, create a new buffer here, just like native wasm support would.
- // otherwise, no need to.
- if (wasm.memory.segments.size() > 0) {
+ // create a new buffer here, just like native wasm support would.
+ EM_ASM_({
+ Module['outside']['newBuffer'] = new ArrayBuffer($0);
+ }, wasm.memory.initial * Memory::kPageSize);
+ for (auto segment : wasm.memory.segments) {
EM_ASM_({
- Module['outside']['newBuffer'] = new ArrayBuffer($0);
- }, wasm.memory.initial);
- for (auto segment : wasm.memory.segments) {
- EM_ASM_({
- var source = Module['HEAP8'].subarray($1, $1 + $2);
- var target = new Int8Array(Module['outside']['newBuffer']);
- target.set(source, $0);
- }, segment.offset, segment.data, segment.size);
- }
+ var source = Module['HEAP8'].subarray($1, $1 + $2);
+ var target = new Int8Array(Module['outside']['newBuffer']);
+ target.set(source, $0);
+ }, segment.offset, segment.data, segment.size);
}
}
@@ -352,6 +382,18 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() {
};
instance = new ModuleInstance(*module, new JSExternalInterface());
+
+ // stack trace hooks
+ EM_ASM({
+ Module['outside']['extraStackTrace'] = function() {
+ return Pointer_stringify(Module['_interpreter_stack_trace']());
+ };
+ });
+}
+
+extern "C" int EMSCRIPTEN_KEEPALIVE interpreter_stack_trace() {
+ std::string stack = instance->printFunctionStack();
+ return (int)strdup(stack.c_str()); // XXX leak
}
// Does a call from js into an export of the module.