summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asm2wasm-main.cpp7
-rw-r--r--src/binaryen-shell.cpp4
-rw-r--r--src/s2wasm.h17
-rw-r--r--src/wasm-binary.h23
-rw-r--r--src/wasm-interpreter.h2
-rw-r--r--src/wasm-js.cpp16
-rw-r--r--src/wasm.h4
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) {}