diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/asm2wasm-main.cpp | 7 | ||||
-rw-r--r-- | src/binaryen-shell.cpp | 4 | ||||
-rw-r--r-- | src/s2wasm.h | 17 | ||||
-rw-r--r-- | src/wasm-binary.h | 23 | ||||
-rw-r--r-- | src/wasm-interpreter.h | 2 | ||||
-rw-r--r-- | src/wasm-js.cpp | 16 | ||||
-rw-r--r-- | src/wasm.h | 4 |
7 files changed, 43 insertions, 30 deletions
diff --git a/src/asm2wasm-main.cpp b/src/asm2wasm-main.cpp index 5ab8bb0cf..73f6853d8 100644 --- a/src/asm2wasm-main.cpp +++ b/src/asm2wasm-main.cpp @@ -58,6 +58,11 @@ int main(int argc, const char *argv[]) { const auto &tm_it = options.extra.find("total memory"); size_t totalMemory = tm_it == options.extra.end() ? 16 * 1024 * 1024 : atoi(tm_it->second.c_str()); + if (totalMemory & ~Memory::kPageMask) { + std::cerr << "Error: total memory size " << totalMemory << + " is not a multiple of the 64k wasm page size\n"; + exit(EXIT_FAILURE); + } Asm2WasmPreProcessor pre; auto input( @@ -75,7 +80,7 @@ int main(int argc, const char *argv[]) { if (options.debug) std::cerr << "wasming..." << std::endl; AllocatingModule wasm; - wasm.memory.initial = wasm.memory.max = totalMemory; + wasm.memory.initial = wasm.memory.max = totalMemory / Memory::kPageSize; Asm2WasmBuilder asm2wasm(wasm, pre.memoryGrowth, options.debug); asm2wasm.processAsm(asmjs); diff --git a/src/binaryen-shell.cpp b/src/binaryen-shell.cpp index 61cab723c..bfed8277e 100644 --- a/src/binaryen-shell.cpp +++ b/src/binaryen-shell.cpp @@ -111,10 +111,10 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface { ShellExternalInterface() : memory() {} void init(Module& wasm) override { - memory.resize(wasm.memory.initial); + memory.resize(wasm.memory.initial * wasm::Memory::kPageSize); // apply memory segments for (auto segment : wasm.memory.segments) { - assert(segment.offset + segment.size <= wasm.memory.initial); + assert(segment.offset + segment.size <= wasm.memory.initial * wasm::Memory::kPageSize); for (size_t i = 0; i != segment.size; ++i) { memory.set(segment.offset + i, segment.data[i]); } diff --git a/src/s2wasm.h b/src/s2wasm.h index b1c5f7c54..f87742bd0 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -55,7 +55,8 @@ class S2WasmBuilder { ignoreUnknownSymbols(ignoreUnknownSymbols), startFunction(startFunction), globalBase(globalBase), - nextStatic(globalBase) { + nextStatic(globalBase), + initialMemory(0) { s = input; scan(); s = input; @@ -75,6 +76,7 @@ class S2WasmBuilder { size_t globalBase, // where globals can start to be statically allocated, i.e., the data segment nextStatic; // location of next static allocation std::map<Name, int32_t> staticAddresses; // name => address + size_t initialMemory; // Initial size (in bytes) of memory (after linking, this is rounded and set on the wasm object in pages) struct Relocation { uint32_t* data; @@ -396,7 +398,7 @@ class S2WasmBuilder { addressSegments[nextStatic] = wasm.memory.segments.size(); wasm.memory.segments.emplace_back( nextStatic, reinterpret_cast<char*>(raw), pointerSize); - wasm.memory.initial = nextStatic + pointerSize; + initialMemory = nextStatic + pointerSize; } nextStatic += pointerSize; } @@ -407,7 +409,7 @@ class S2WasmBuilder { nextStatic = (nextStatic + 15) & static_cast<size_t>(-16); staticAddresses[".stack"] = nextStatic; nextStatic += stackAllocation; - wasm.memory.initial = nextStatic; + initialMemory = nextStatic; } void process() { @@ -1154,7 +1156,7 @@ class S2WasmBuilder { wasm.memory.segments.emplace_back(nextStatic, (const char*)&(*raw)[0], size); } nextStatic += size; - wasm.memory.initial = nextStatic; + initialMemory = nextStatic; } void parseLcomm(Name name, size_t align=1) { @@ -1168,7 +1170,7 @@ class S2WasmBuilder { while (nextStatic % align) nextStatic++; staticAddresses[name] = nextStatic; nextStatic += size; - wasm.memory.initial = nextStatic; + initialMemory = nextStatic; } void skipImports() { @@ -1183,6 +1185,11 @@ class S2WasmBuilder { } void fix() { + // Round the memory size up to a page, and update the page-increment versions + // of initial and max + wasm.memory.initial = ((initialMemory + Memory::kPageSize - 1) & Memory::kPageMask) / + Memory::kPageSize; + auto ensureFunctionIndex = [&](Name name) { if (functionIndexes.count(name) == 0) { functionIndexes[name] = wasm.table.names.size(); diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 8a03ca843..47da374c1 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -402,18 +402,10 @@ public: void writeMemory() { if (wasm->memory.max == 0) return; if (debug) std::cerr << "== writeMemory" << std::endl; - o << int8_t(BinaryConsts::Memory); - if (wasm->memory.initial == 0) { // XXX diverge from v8, 0 means 0, 1 and above are powers of 2 starting at 0 - o << int8_t(0); - } else { - o << int8_t(std::min(ceil(log2(wasm->memory.initial)), 31.0) + 1); // up to 31 bits, don't let ceil get us to UINT_MAX which can overflow - } - if (wasm->memory.max == 0) { - o << int8_t(0); - } else { - o << int8_t(std::min(ceil(log2(wasm->memory.max)), 31.0) + 1); - } - o << int8_t(1); // export memory + o << int8_t(BinaryConsts::Memory) + << LEB128(wasm->memory.initial) + << LEB128(wasm->memory.max) + << int8_t(1); // export memory } void writeSignatures() { @@ -1088,10 +1080,8 @@ public: void readMemory() { if (debug) std::cerr << "== readMemory" << std::endl; - size_t initial = getInt8(); - wasm.memory.initial = initial == 0 ? 0 : std::pow<size_t>(2, initial - 1); - size_t max = getInt8(); - wasm.memory.max = max == 0 ? 0 : std::pow<size_t>(2, max - 1); + wasm.memory.initial = getLEB128(); + wasm.memory.max = getLEB128(); verifyInt8(1); // export memory } @@ -1671,4 +1661,3 @@ public: } // namespace wasm #endif // wasm_wasm_binary_h - diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 223a9e1a5..2edaad846 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -102,7 +102,7 @@ public: Module& wasm; ModuleInstance(Module& wasm, ExternalInterface* externalInterface) : wasm(wasm), externalInterface(externalInterface) { - memorySize = wasm.memory.initial; + memorySize = wasm.memory.initial * Memory::kPageSize; externalInterface->init(wasm); if (wasm.start.is()) { LiteralList arguments; diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp index 7b9afab30..000092da8 100644 --- a/src/wasm-js.cpp +++ b/src/wasm-js.cpp @@ -67,9 +67,14 @@ 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"; @@ -114,9 +119,14 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_s_expr2wasm(char *input, char *mappedG abort(); }); - 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 = (module->exportsMap.find(GROW_WASM_MEMORY) != module->exportsMap.end()) ? -1 : module->memory.initial; // global mapping is done in js in post.js @@ -151,7 +161,7 @@ extern "C" void EMSCRIPTEN_KEEPALIVE instantiate() { // create a new buffer here, just like native wasm support would. EM_ASM_({ Module['outside']['newBuffer'] = new ArrayBuffer($0); - }, wasm.memory.initial); + }, wasm.memory.initial * Memory::kPageSize); for (auto segment : wasm.memory.segments) { EM_ASM_({ var source = Module['HEAP8'].subarray($1, $1 + $2); diff --git a/src/wasm.h b/src/wasm.h index 6cbe93e3b..ce6b9d294 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1074,6 +1074,8 @@ public: class Memory { public: + static const size_t kPageSize = 64 * 1024; + static const size_t kPageMask = ~(kPageSize - 1); struct Segment { size_t offset; const char* data; @@ -1082,7 +1084,7 @@ public: Segment(size_t offset, const char *data, size_t size) : offset(offset), data(data), size(size) {} }; - size_t initial, max; + size_t initial, max; // sizes are in pages std::vector<Segment> segments; Memory() : initial(0), max((uint32_t)-1) {} |