resizing.js (8132B)
1 const Module = WebAssembly.Module; 2 const Instance = WebAssembly.Instance; 3 const Table = WebAssembly.Table; 4 const Memory = WebAssembly.Memory; 5 const RuntimeError = WebAssembly.RuntimeError; 6 7 // ====== 8 // MEMORY 9 // ====== 10 11 // Test for stale heap pointers after resize 12 13 // Grow directly from builtin call: 14 wasmFullPass(`(module 15 (memory 1) 16 (func $test (result i32) 17 (i32.store (i32.const 0) (i32.const 1)) 18 (i32.store (i32.const 65532) (i32.const 10)) 19 (drop (memory.grow (i32.const 99))) 20 (i32.store (i32.const 6553596) (i32.const 100)) 21 (i32.add 22 (i32.load (i32.const 0)) 23 (i32.add 24 (i32.load (i32.const 65532)) 25 (i32.load (i32.const 6553596))))) 26 (export "run" (func $test)) 27 )`, 111); 28 29 // Grow during import call: 30 var exports = wasmEvalText(`(module 31 (import "" "imp" (func $imp)) 32 (memory 1) 33 (func $grow (drop (memory.grow (i32.const 99)))) 34 (export "grow" (func $grow)) 35 (func $test (result i32) 36 (i32.store (i32.const 0) (i32.const 1)) 37 (i32.store (i32.const 65532) (i32.const 10)) 38 (call $imp) 39 (i32.store (i32.const 6553596) (i32.const 100)) 40 (i32.add 41 (i32.load (i32.const 0)) 42 (i32.add 43 (i32.load (i32.const 65532)) 44 (i32.load (i32.const 6553596))))) 45 (export "test" (func $test)) 46 )`, {"":{imp() { exports.grow() }}}).exports; 47 48 setJitCompilerOption("baseline.warmup.trigger", 2); 49 setJitCompilerOption("ion.warmup.trigger", 4); 50 for (var i = 0; i < 10; i++) 51 assertEq(exports.test(), 111); 52 53 // Grow during call_indirect: 54 var mem = new Memory({initial:1}); 55 var tbl = new Table({initial:1, element:"anyfunc"}); 56 var exports1 = wasmEvalText(`(module 57 (import "" "mem" (memory 1)) 58 (func $grow 59 (i32.store (i32.const 65532) (i32.const 10)) 60 (drop (memory.grow (i32.const 99))) 61 (i32.store (i32.const 6553596) (i32.const 100))) 62 (export "grow" (func $grow)) 63 )`, {"":{mem}}).exports; 64 var exports2 = wasmEvalText(`(module 65 (import "" "tbl" (table 1 funcref)) 66 (import "" "mem" (memory 1)) 67 (type $v2v (func)) 68 (func $test (result i32) 69 (i32.store (i32.const 0) (i32.const 1)) 70 (call_indirect (type $v2v) (i32.const 0)) 71 (i32.add 72 (i32.load (i32.const 0)) 73 (i32.add 74 (i32.load (i32.const 65532)) 75 (i32.load (i32.const 6553596))))) 76 (export "test" (func $test)) 77 )`, {"":{tbl, mem}}).exports; 78 tbl.set(0, exports1.grow); 79 assertEq(exports2.test(), 111); 80 81 // Test for coherent length/contents 82 83 var mem = new Memory({initial:1}); 84 new Int32Array(mem.buffer)[0] = 42; 85 var mod = new Module(wasmTextToBinary(`(module 86 (import "" "mem" (memory 1)) 87 (func $gm (param i32) (result i32) (memory.grow (local.get 0))) 88 (export "grow_memory" (func $gm)) 89 (func $cm (result i32) (memory.size)) 90 (export "current_memory" (func $cm)) 91 (func $ld (param i32) (result i32) (i32.load (local.get 0))) 92 (export "load" (func $ld)) 93 (func $st (param i32) (param i32) (i32.store (local.get 0) (local.get 1))) 94 (export "store" (func $st)) 95 )`)); 96 var exp1 = new Instance(mod, {"":{mem}}).exports; 97 var exp2 = new Instance(mod, {"":{mem}}).exports; 98 assertEq(exp1.current_memory(), 1); 99 assertEq(exp1.load(0), 42); 100 assertEq(exp2.current_memory(), 1); 101 assertEq(exp2.load(0), 42); 102 mem.grow(1); 103 assertEq(mem.buffer.byteLength, 2*64*1024); 104 new Int32Array(mem.buffer)[64*1024/4] = 13; 105 assertEq(exp1.current_memory(), 2); 106 assertEq(exp1.load(0), 42); 107 assertEq(exp1.load(64*1024), 13); 108 assertEq(exp2.current_memory(), 2); 109 assertEq(exp2.load(0), 42); 110 assertEq(exp2.load(64*1024), 13); 111 exp1.grow_memory(2); 112 assertEq(exp1.current_memory(), 4); 113 exp1.store(3*64*1024, 99); 114 assertEq(exp2.current_memory(), 4); 115 assertEq(exp2.load(3*64*1024), 99); 116 assertEq(mem.buffer.byteLength, 4*64*1024); 117 assertEq(new Int32Array(mem.buffer)[3*64*1024/4], 99); 118 119 // Fail at maximum 120 121 var mem = new Memory({initial:1, maximum:2}); 122 assertEq(mem.buffer.byteLength, 1 * 64*1024); 123 assertEq(mem.grow(1), 1); 124 assertEq(mem.buffer.byteLength, 2 * 64*1024); 125 assertErrorMessage(() => mem.grow(1), RangeError, /failed to grow memory/); 126 assertEq(mem.buffer.byteLength, 2 * 64*1024); 127 128 // Do not misinterpret the maximum @ max for the current size. 129 130 (new WebAssembly.Memory({initial: 1, maximum: 65536})).grow(1) 131 132 // ====== 133 // TABLE 134 // ====== 135 136 // Test for stale table base pointers after resize 137 138 // Grow during import call: 139 var exports = wasmEvalText(`(module 140 (type $v2i (func (result i32))) 141 (import "" "grow" (func $grow)) 142 (table (export "tbl") 1 funcref) 143 (func $test (result i32) 144 (i32.add 145 (call_indirect (type $v2i) (i32.const 0)) 146 (block (result i32) 147 (call $grow) 148 (call_indirect (type $v2i) (i32.const 1))))) 149 (func $one (result i32) (i32.const 1)) 150 (elem (i32.const 0) $one) 151 (func $two (result i32) (i32.const 2)) 152 (export "test" (func $test)) 153 (export "two" (func $two)) 154 )`, {"":{grow() { exports.tbl.grow(1); exports.tbl.set(1, exports.two) }}}).exports; 155 156 setJitCompilerOption("baseline.warmup.trigger", 2); 157 setJitCompilerOption("ion.warmup.trigger", 4); 158 for (var i = 0; i < 10; i++) 159 assertEq(exports.test(), 3); 160 assertEq(exports.tbl.length, 11); 161 162 // Grow during call_indirect: 163 var exports1 = wasmEvalText(`(module 164 (import "" "grow" (func $grow)) 165 (func $exp (call $grow)) 166 (export "exp" (func $exp)) 167 )`, {"":{grow() { exports2.tbl.grow(1); exports2.tbl.set(2, exports2.eleven) }}}).exports; 168 var exports2 = wasmEvalText(`(module 169 (type $v2v (func)) 170 (type $v2i (func (result i32))) 171 (import "" "imp" (func $imp)) 172 (elem (i32.const 0) $imp) 173 (table 2 funcref) 174 (func $test (result i32) 175 (i32.add 176 (call_indirect (type $v2i) (i32.const 1)) 177 (block (result i32) 178 (call_indirect (type $v2v) (i32.const 0)) 179 (call_indirect (type $v2i) (i32.const 2))))) 180 (func $ten (result i32) (i32.const 10)) 181 (elem (i32.const 1) $ten) 182 (func $eleven (result i32) (i32.const 11)) 183 (export "tbl" (table 0)) 184 (export "test" (func $test)) 185 (export "eleven" (func $eleven)) 186 )`, {"":{imp:exports1.exp}}).exports; 187 assertEq(exports2.test(), 21); 188 189 // Test for coherent length/contents 190 191 var src = wasmEvalText(`(module 192 (func $one (result i32) (i32.const 1)) 193 (export "one" (func $one)) 194 (func $two (result i32) (i32.const 2)) 195 (export "two" (func $two)) 196 (func $three (result i32) (i32.const 3)) 197 (export "three" (func $three)) 198 )`).exports; 199 var tbl = new Table({element:"anyfunc", initial:1}); 200 tbl.set(0, src.one); 201 202 var mod = new Module(wasmTextToBinary(`(module 203 (type $v2i (func (result i32))) 204 (table (import "" "tbl") 1 funcref) 205 (func $ci (param i32) (result i32) (call_indirect (type $v2i) (local.get 0))) 206 (export "call_indirect" (func $ci)) 207 )`)); 208 var exp1 = new Instance(mod, {"":{tbl}}).exports; 209 var exp2 = new Instance(mod, {"":{tbl}}).exports; 210 assertEq(exp1.call_indirect(0), 1); 211 assertErrorMessage(() => exp1.call_indirect(1), RuntimeError, /index out of bounds/); 212 assertEq(exp2.call_indirect(0), 1); 213 assertErrorMessage(() => exp2.call_indirect(1), RuntimeError, /index out of bounds/); 214 assertEq(tbl.grow(1), 1); 215 assertEq(tbl.length, 2); 216 assertEq(exp1.call_indirect(0), 1); 217 assertErrorMessage(() => exp1.call_indirect(1), Error, /indirect call to null/); 218 tbl.set(1, src.two); 219 assertEq(exp1.call_indirect(1), 2); 220 assertErrorMessage(() => exp1.call_indirect(2), RuntimeError, /index out of bounds/); 221 assertEq(tbl.grow(2), 2); 222 assertEq(tbl.length, 4); 223 assertEq(exp2.call_indirect(0), 1); 224 assertEq(exp2.call_indirect(1), 2); 225 assertErrorMessage(() => exp2.call_indirect(2), Error, /indirect call to null/); 226 assertErrorMessage(() => exp2.call_indirect(3), Error, /indirect call to null/); 227 228 // Fail at maximum 229 230 var tbl = new Table({initial:1, maximum:2, element:"anyfunc"}); 231 assertEq(tbl.length, 1); 232 assertEq(tbl.grow(1), 1); 233 assertEq(tbl.length, 2); 234 assertErrorMessage(() => tbl.grow(1), RangeError, /failed to grow table/); 235 assertEq(tbl.length, 2);