current-memory-tls.js (2293B)
1 // Bug 1341650: 2 // - when compiled with Ion, pass the TLS register to memory.size; 3 // - when compiled with Baseline, don't clobber the last stack slot when 4 // calling into memory.size/memory.grow; 5 6 // This toy module starts with an empty memory, then tries to set values at different 7 // indexes, automatically growing memory when that would trigger an out of 8 // bounds access, for the exact right amount of pages. Note it's not made for 9 // efficiency, but optimizing it doesn't trigger the bugs mentioned above. 10 11 let i = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(` 12 (module 13 (memory $mem (export "mem") 0 65535) 14 15 (func (export "cur_mem") (result i32) (memory.size)) 16 17 (func $maybeGrow (param $i i32) (local $smem i32) 18 ;; get memory.size in number of bytes, not pages. 19 memory.size 20 i64.extend_i32_u 21 i64.const 65536 22 i64.mul 23 24 ;; get the last byte index accessed by an int32 access. 25 local.get $i 26 i32.const 3 27 i32.add 28 local.tee $i 29 i64.extend_i32_u 30 31 ;; if the memory is too small, grow it. 32 i64.le_u 33 if 34 ;; get the floor of the accessed *page* index. 35 local.get $i 36 i64.extend_i32_u 37 i64.const 65536 38 i64.div_u 39 40 ;; subtract to that the size of the current memory in pages; 41 ;; that's the amount of pages we want to grow, minus one. 42 memory.size 43 i64.extend_i32_u 44 45 i64.sub 46 47 ;; add 1 to that amount. 48 i64.const 1 49 i64.add 50 51 ;; get back to i32 and grow memory. 52 i32.wrap_i64 53 memory.grow 54 drop 55 end 56 ) 57 58 (func (export "set") (param $i i32) (param $v i32) 59 local.get $i 60 call $maybeGrow 61 local.get $i 62 local.get $v 63 i32.store 64 ) 65 66 (func (export "get") (param $i i32) (result i32) 67 local.get $i 68 i32.load 69 ) 70 ) 71 `))).exports; 72 73 assertEq(i.cur_mem(), 0); 74 75 i.set(0, 1); 76 assertEq(i.get(0), 1); 77 78 assertEq(i.cur_mem(), 1); 79 80 i.set(1234, 1); 81 assertEq(i.get(1234), 1); 82 83 assertEq(i.cur_mem(), 1); 84 85 i.set(65532, 1); 86 assertEq(i.get(65532), 1); 87 88 assertErrorMessage(() => i.get(65533), WebAssembly.RuntimeError, /index out of bounds/); 89 90 assertEq(i.cur_mem(), 1); 91 92 i.set(65533, 1); 93 assertEq(i.get(65533), 1); 94 95 assertEq(i.cur_mem(), 2);