diff --git a/src/wasm2js.h b/src/wasm2js.h index b92a7f851e5..2ae0b85e021 100644 --- a/src/wasm2js.h +++ b/src/wasm2js.h @@ -2531,17 +2531,25 @@ void Wasm2JSBuilder::addMemoryGrowFunc(Ref ast, Module* wasm) { JsType::JS_INT)); Ref block = ValueBuilder::makeBlock(); - memoryGrowFunc[3]->push_back(ValueBuilder::makeIf( - ValueBuilder::makeBinary( - ValueBuilder::makeBinary(ValueBuilder::makeName(IString("oldPages")), - LT, - ValueBuilder::makeName(IString("newPages"))), + Ref condition = ValueBuilder::makeBinary( + ValueBuilder::makeBinary(ValueBuilder::makeName(IString("oldPages")), + LT, + ValueBuilder::makeName(IString("newPages"))), + IString("&&"), + ValueBuilder::makeBinary(ValueBuilder::makeName(IString("newPages")), + LT, + ValueBuilder::makeInt(Memory::kMaxSize32))); + // Also enforce the module's declared memory maximum, if one exists. + if (!wasm->memories.empty() && wasm->memories[0]->hasMax()) { + condition = ValueBuilder::makeBinary( + condition, IString("&&"), ValueBuilder::makeBinary(ValueBuilder::makeName(IString("newPages")), - LT, - ValueBuilder::makeInt(Memory::kMaxSize32))), - block, - NULL)); + LE, + ValueBuilder::makeInt(static_cast( + wasm->memories[0]->max.addr)))); + } + memoryGrowFunc[3]->push_back(ValueBuilder::makeIf(condition, block, NULL)); Ref newBuffer = ValueBuilder::makeVar(); ValueBuilder::appendToBlock(block, newBuffer); diff --git a/test/wasm2js/emscripten-grow-yes.2asm.js b/test/wasm2js/emscripten-grow-yes.2asm.js index 6ab56747baf..d48f0deaa15 100644 --- a/test/wasm2js/emscripten-grow-yes.2asm.js +++ b/test/wasm2js/emscripten-grow-yes.2asm.js @@ -64,7 +64,7 @@ function asmFunc(imports) { pagesToAdd = pagesToAdd | 0; var oldPages = __wasm_memory_size() | 0; var newPages = oldPages + pagesToAdd | 0; - if ((oldPages < newPages) && (newPages < 65536)) { + if ((oldPages < newPages) && (newPages < 65536) && (newPages <= 1024)) { var newBuffer = new ArrayBuffer(Math_imul(newPages, 65536)); var newHEAP8 = new Int8Array(newBuffer); newHEAP8.set(HEAP8); diff --git a/test/wasm2js/emscripten-grow-yes.2asm.js.opt b/test/wasm2js/emscripten-grow-yes.2asm.js.opt index 6ab56747baf..d48f0deaa15 100644 --- a/test/wasm2js/emscripten-grow-yes.2asm.js.opt +++ b/test/wasm2js/emscripten-grow-yes.2asm.js.opt @@ -64,7 +64,7 @@ function asmFunc(imports) { pagesToAdd = pagesToAdd | 0; var oldPages = __wasm_memory_size() | 0; var newPages = oldPages + pagesToAdd | 0; - if ((oldPages < newPages) && (newPages < 65536)) { + if ((oldPages < newPages) && (newPages < 65536) && (newPages <= 1024)) { var newBuffer = new ArrayBuffer(Math_imul(newPages, 65536)); var newHEAP8 = new Int8Array(newBuffer); newHEAP8.set(HEAP8); diff --git a/test/wasm2js/grow-memory-max.2asm.js b/test/wasm2js/grow-memory-max.2asm.js new file mode 100644 index 00000000000..bd73dfa3985 --- /dev/null +++ b/test/wasm2js/grow-memory-max.2asm.js @@ -0,0 +1,77 @@ + +function asmFunc(imports) { + var buffer = new ArrayBuffer(65536); + var HEAP8 = new Int8Array(buffer); + var HEAP16 = new Int16Array(buffer); + var HEAP32 = new Int32Array(buffer); + var HEAPU8 = new Uint8Array(buffer); + var HEAPU16 = new Uint16Array(buffer); + var HEAPU32 = new Uint32Array(buffer); + var HEAPF32 = new Float32Array(buffer); + var HEAPF64 = new Float64Array(buffer); + var Math_imul = Math.imul; + var Math_fround = Math.fround; + var Math_abs = Math.abs; + var Math_clz32 = Math.clz32; + var Math_min = Math.min; + var Math_max = Math.max; + var Math_floor = Math.floor; + var Math_ceil = Math.ceil; + var Math_trunc = Math.trunc; + var Math_sqrt = Math.sqrt; + function grow($0) { + $0 = $0 | 0; + return __wasm_memory_grow($0 | 0) | 0; + } + + function size() { + return __wasm_memory_size() | 0; + } + + function __wasm_memory_size() { + return buffer.byteLength / 65536 | 0; + } + + function __wasm_memory_grow(pagesToAdd) { + pagesToAdd = pagesToAdd | 0; + var oldPages = __wasm_memory_size() | 0; + var newPages = oldPages + pagesToAdd | 0; + if ((oldPages < newPages) && (newPages < 65536) && (newPages <= 2)) { + var newBuffer = new ArrayBuffer(Math_imul(newPages, 65536)); + var newHEAP8 = new Int8Array(newBuffer); + newHEAP8.set(HEAP8); + HEAP8 = new Int8Array(newBuffer); + HEAP16 = new Int16Array(newBuffer); + HEAP32 = new Int32Array(newBuffer); + HEAPU8 = new Uint8Array(newBuffer); + HEAPU16 = new Uint16Array(newBuffer); + HEAPU32 = new Uint32Array(newBuffer); + HEAPF32 = new Float32Array(newBuffer); + HEAPF64 = new Float64Array(newBuffer); + buffer = newBuffer; + } + return oldPages; + } + + return { + "memory": Object.create(Object.prototype, { + "grow": { + "value": __wasm_memory_grow + }, + "buffer": { + "get": function () { + return buffer; + } + + } + }), + "grow": grow, + "size": size + }; +} + +var retasmFunc = asmFunc({ +}); +export var memory = retasmFunc.memory; +export var grow = retasmFunc.grow; +export var size = retasmFunc.size; diff --git a/test/wasm2js/grow-memory-max.2asm.js.opt b/test/wasm2js/grow-memory-max.2asm.js.opt new file mode 100644 index 00000000000..bd73dfa3985 --- /dev/null +++ b/test/wasm2js/grow-memory-max.2asm.js.opt @@ -0,0 +1,77 @@ + +function asmFunc(imports) { + var buffer = new ArrayBuffer(65536); + var HEAP8 = new Int8Array(buffer); + var HEAP16 = new Int16Array(buffer); + var HEAP32 = new Int32Array(buffer); + var HEAPU8 = new Uint8Array(buffer); + var HEAPU16 = new Uint16Array(buffer); + var HEAPU32 = new Uint32Array(buffer); + var HEAPF32 = new Float32Array(buffer); + var HEAPF64 = new Float64Array(buffer); + var Math_imul = Math.imul; + var Math_fround = Math.fround; + var Math_abs = Math.abs; + var Math_clz32 = Math.clz32; + var Math_min = Math.min; + var Math_max = Math.max; + var Math_floor = Math.floor; + var Math_ceil = Math.ceil; + var Math_trunc = Math.trunc; + var Math_sqrt = Math.sqrt; + function grow($0) { + $0 = $0 | 0; + return __wasm_memory_grow($0 | 0) | 0; + } + + function size() { + return __wasm_memory_size() | 0; + } + + function __wasm_memory_size() { + return buffer.byteLength / 65536 | 0; + } + + function __wasm_memory_grow(pagesToAdd) { + pagesToAdd = pagesToAdd | 0; + var oldPages = __wasm_memory_size() | 0; + var newPages = oldPages + pagesToAdd | 0; + if ((oldPages < newPages) && (newPages < 65536) && (newPages <= 2)) { + var newBuffer = new ArrayBuffer(Math_imul(newPages, 65536)); + var newHEAP8 = new Int8Array(newBuffer); + newHEAP8.set(HEAP8); + HEAP8 = new Int8Array(newBuffer); + HEAP16 = new Int16Array(newBuffer); + HEAP32 = new Int32Array(newBuffer); + HEAPU8 = new Uint8Array(newBuffer); + HEAPU16 = new Uint16Array(newBuffer); + HEAPU32 = new Uint32Array(newBuffer); + HEAPF32 = new Float32Array(newBuffer); + HEAPF64 = new Float64Array(newBuffer); + buffer = newBuffer; + } + return oldPages; + } + + return { + "memory": Object.create(Object.prototype, { + "grow": { + "value": __wasm_memory_grow + }, + "buffer": { + "get": function () { + return buffer; + } + + } + }), + "grow": grow, + "size": size + }; +} + +var retasmFunc = asmFunc({ +}); +export var memory = retasmFunc.memory; +export var grow = retasmFunc.grow; +export var size = retasmFunc.size; diff --git a/test/wasm2js/grow-memory-max.wast b/test/wasm2js/grow-memory-max.wast new file mode 100644 index 00000000000..36697055517 --- /dev/null +++ b/test/wasm2js/grow-memory-max.wast @@ -0,0 +1,24 @@ +(module + (memory $0 1 2) + (export "memory" (memory $0)) + (export "grow" (func $grow)) + (export "size" (func $size)) + + (func $grow (param i32) (result i32) + (memory.grow (local.get 0)) + ) + + (func $size (result i32) + (memory.size) + ) +) + +;; The initial size is 1 page, max is 2 pages. +;; Growing by 1 should succeed (1+1=2 <= max). +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "size") (i32.const 2)) +;; Growing by 1 more should fail (2+1=3 > max). +;; The size should remain at 2. +(assert_return (invoke "grow" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "size") (i32.const 2))