summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2015-11-06 09:08:21 -0800
committerAlon Zakai <alonzakai@gmail.com>2015-11-06 09:08:21 -0800
commit38b6e18b5b563ee235f426d695a89c20cb08ada5 (patch)
treefaf22c0d978f783e359244c2b961385551db4ec6
parent034596930c9d4ca3e771e78e03e06efc026fadff (diff)
downloadbinaryen-38b6e18b5b563ee235f426d695a89c20cb08ada5.tar.gz
binaryen-38b6e18b5b563ee235f426d695a89c20cb08ada5.tar.bz2
binaryen-38b6e18b5b563ee235f426d695a89c20cb08ada5.zip
host ops
-rw-r--r--src/wasm-interpreter.h12
-rw-r--r--src/wasm-js.cpp4
-rw-r--r--src/wasm-s-parser.h9
-rw-r--r--src/wasm-shell.cpp7
4 files changed, 28 insertions, 4 deletions
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 0ca4d9674..5279e8a35 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -43,6 +43,7 @@ public:
virtual Literal callImport(Import* import, LiteralList& arguments) = 0;
virtual Literal load(Load* load, size_t addr) = 0;
virtual void store(Store* store, size_t addr, Literal value) = 0;
+ virtual void growMemory(size_t oldSize, size_t newSize) = 0;
virtual void trap() = 0;
};
@@ -634,11 +635,18 @@ public:
}
Flow visitHost(Host *curr) override {
NOTE_ENTER("Host");
-
switch (curr->op) {
case PageSize: return Literal(64*1024);
case MemorySize: return Literal(instance.memorySize);
- case GrowMemory: abort();
+ case GrowMemory: {
+ Flow flow = visit(curr->operands[0]);
+ if (flow.breaking()) return flow;
+ size_t newSize = flow.value.getInteger();
+ if (newSize > instance.wasm.memory.max) trap();
+ instance.externalInterface->growMemory(instance.memorySize, newSize);
+ instance.memorySize = newSize;
+ return Literal();
+ }
case HasFeature: {
IString id = curr->nameOperand;
if (id == WASM) return Literal(1);
diff --git a/src/wasm-js.cpp b/src/wasm-js.cpp
index 44c5cb099..ddb31b33d 100644
--- a/src/wasm-js.cpp
+++ b/src/wasm-js.cpp
@@ -173,6 +173,10 @@ extern "C" void EMSCRIPTEN_KEEPALIVE load_asm(char *input) {
}
}
+ void growMemory(size_t oldSize, size_t newSize) override {
+ abort();
+ }
+
void trap() override {
EM_ASM({
abort("wasm trap!");
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index b81800ad2..58f316075 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -500,6 +500,7 @@ public:
}
case 'g': {
if (str[1] == 'e') return makeGetLocal(s);
+ if (str[1] == 'r') return makeHost(s, HostOp::GrowMemory);
abort_on(str);
}
case 'h': {
@@ -515,10 +516,18 @@ public:
if (str[1] == 'o') return makeLoop(s);
abort_on(str);
}
+ case 'm': {
+ if (str[1] == 'e') return makeHost(s, HostOp::MemorySize);
+ abort_on(str);
+ }
case 'n': {
if (str[1] == 'o') return allocator.alloc<Nop>();
abort_on(str);
}
+ case 'p': {
+ if (str[1] == 'a') return makeHost(s, HostOp::PageSize);
+ abort_on(str);
+ }
case 's': {
if (str[1] == 'e') return makeSetLocal(s);
abort_on(str);
diff --git a/src/wasm-shell.cpp b/src/wasm-shell.cpp
index c37ba79a3..5f9fafd8f 100644
--- a/src/wasm-shell.cpp
+++ b/src/wasm-shell.cpp
@@ -24,13 +24,11 @@ IString ASSERT_RETURN("assert_return"),
struct ShellExternalInterface : ModuleInstance::ExternalInterface {
char *memory;
- size_t memorySize;
ShellExternalInterface() : memory(nullptr) {}
void init(Module& wasm) override {
memory = new char[wasm.memory.initial];
- memorySize = wasm.memory.initial;
// apply memory segments
for (auto segment : wasm.memory.segments) {
memcpy(memory + segment.offset, segment.data, segment.size);
@@ -104,6 +102,11 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
}
}
+ void growMemory(size_t oldSize, size_t newSize) override {
+ delete memory;
+ memory = new char[newSize];
+ }
+
jmp_buf trapState;
void trap() override {