Kaido Kert | f309f9a | 2021-04-30 12:09:15 -0700 | [diff] [blame] | 1 | // Copyright 2019 the V8 project authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | // Flags: --expose-wasm --experimental-wasm-reftypes |
| 6 | |
| 7 | load("test/mjsunit/wasm/wasm-module-builder.js"); |
| 8 | |
| 9 | (function TestGetAndSet() { |
| 10 | function addTableWithAccessors(builder, type, size, name) { |
| 11 | const table = builder.addTable(type, size); |
| 12 | const set_sig = makeSig([kWasmI32, type], []); |
| 13 | builder.addFunction('set_' + name, set_sig) |
| 14 | .addBody([kExprLocalGet, 0, |
| 15 | kExprLocalGet, 1, |
| 16 | kExprTableSet, table.index]) |
| 17 | .exportFunc(); |
| 18 | |
| 19 | const get_sig = makeSig([kWasmI32], [type]); |
| 20 | builder.addFunction('get_' + name, get_sig) |
| 21 | .addBody([kExprLocalGet, 0, kExprTableGet, table.index]) |
| 22 | .exportFunc(); |
| 23 | } |
| 24 | |
| 25 | const builder = new WasmModuleBuilder(); |
| 26 | |
| 27 | addTableWithAccessors(builder, kWasmAnyFunc, 10, 'table_func1'); |
| 28 | addTableWithAccessors(builder, kWasmExternRef, 20, 'table_ref1'); |
| 29 | addTableWithAccessors(builder, kWasmExternRef, 9, 'table_ref2'); |
| 30 | addTableWithAccessors(builder, kWasmAnyFunc, 12, 'table_func2'); |
| 31 | |
| 32 | let exports = builder.instantiate().exports; |
| 33 | const dummy_ref = {foo : 1, bar : 3}; |
| 34 | const dummy_func = exports.set_table_func1; |
| 35 | |
| 36 | (function testTableGetInitialValue() { |
| 37 | print(arguments.callee.name); |
| 38 | // Tables are initialized with `null`. |
| 39 | assertSame(null, exports.get_table_func1(1)); |
| 40 | assertSame(null, exports.get_table_func2(2)); |
| 41 | assertSame(null, exports.get_table_ref1(3)); |
| 42 | assertSame(null, exports.get_table_ref2(4)); |
| 43 | })(); |
| 44 | |
| 45 | (function testTableGetOOB() { |
| 46 | print(arguments.callee.name); |
| 47 | assertSame(null, exports.get_table_func2(11)); |
| 48 | assertTraps(kTrapTableOutOfBounds, () => exports.get_table_func1(11)); |
| 49 | assertTraps(kTrapTableOutOfBounds, () => exports.get_table_func2(21)); |
| 50 | assertTraps(kTrapTableOutOfBounds, () => exports.get_table_func1(-1)); |
| 51 | assertTraps(kTrapTableOutOfBounds, () => exports.get_table_func2(-2)); |
| 52 | assertSame(null, exports.get_table_ref1(14)); |
| 53 | assertTraps(kTrapTableOutOfBounds, () => exports.get_table_ref2(14)); |
| 54 | assertTraps(kTrapTableOutOfBounds, () => exports.get_table_ref1(44)); |
| 55 | assertTraps(kTrapTableOutOfBounds, () => exports.get_table_ref2(-1)); |
| 56 | assertTraps(kTrapTableOutOfBounds, () => exports.get_table_ref1(-4)); |
| 57 | })(); |
| 58 | |
| 59 | (function testTableSetOOB() { |
| 60 | print(arguments.callee.name); |
| 61 | exports.set_table_func2(11, dummy_func); |
| 62 | assertTraps(kTrapTableOutOfBounds, () => exports.set_table_func1(11, dummy_func)); |
| 63 | assertTraps(kTrapTableOutOfBounds, () => exports.set_table_func2(21, dummy_func)); |
| 64 | exports.set_table_ref1(14, dummy_ref); |
| 65 | assertTraps(kTrapTableOutOfBounds, () => exports.set_table_ref2(14, dummy_ref)); |
| 66 | assertTraps(kTrapTableOutOfBounds, () => exports.set_table_ref1(44, dummy_ref)); |
| 67 | })(); |
| 68 | |
| 69 | (function testTableSet() { |
| 70 | print(arguments.callee.name); |
| 71 | assertSame(null, exports.get_table_func1(3)); |
| 72 | exports.set_table_func1(3, dummy_func); |
| 73 | assertSame(dummy_func, exports.get_table_func1(3)); |
| 74 | assertSame(null, exports.get_table_func2(3)); |
| 75 | |
| 76 | assertSame(null, exports.get_table_func2(7)); |
| 77 | exports.set_table_func2(7, dummy_func); |
| 78 | assertSame(dummy_func, exports.get_table_func2(7)); |
| 79 | assertSame(null, exports.get_table_func1(7)); |
| 80 | |
| 81 | assertSame(null, exports.get_table_ref1(3)); |
| 82 | exports.set_table_ref1(3, dummy_ref); |
| 83 | assertSame(dummy_ref, exports.get_table_ref1(3)); |
| 84 | assertSame(null, exports.get_table_ref2(3)); |
| 85 | |
| 86 | assertSame(null, exports.get_table_ref2(7)); |
| 87 | exports.set_table_ref2(7, dummy_ref); |
| 88 | assertSame(dummy_ref, exports.get_table_ref2(7)); |
| 89 | assertSame(null, exports.get_table_ref1(7)); |
| 90 | })(); |
| 91 | |
| 92 | (function testSetFunctionTableInvalidType() { |
| 93 | print(arguments.callee.name); |
| 94 | assertThrows(() => exports.set_table_func2(7, dummy_ref), TypeError); |
| 95 | })(); |
| 96 | })(); |
| 97 | |
| 98 | (function testGetFunctionFromInitializedTable() { |
| 99 | print(arguments.callee.name); |
| 100 | const value1 = 11; |
| 101 | const value2 = 22; |
| 102 | const value3 = 13; |
| 103 | |
| 104 | const builder = new WasmModuleBuilder(); |
| 105 | const t1 = builder.addTable(kWasmAnyFunc, 10).index; |
| 106 | const t2 = builder.addTable(kWasmAnyFunc, 12).index; |
| 107 | |
| 108 | const f1 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, value1]); |
| 109 | const f2 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, value2]); |
| 110 | const f3 = builder.addFunction('f', kSig_i_v).addBody([kExprI32Const, value3]); |
| 111 | builder.addFunction('get_t1', kSig_a_i) |
| 112 | .addBody([kExprLocalGet, 0, kExprTableGet, t1]) |
| 113 | .exportFunc(); |
| 114 | builder.addFunction('get_t2', kSig_a_i) |
| 115 | .addBody([kExprLocalGet, 0, kExprTableGet, t2]) |
| 116 | .exportFunc(); |
| 117 | |
| 118 | const offset1 = 3; |
| 119 | const offset2 = 9; |
| 120 | builder.addElementSegment(t1, offset1, false, [f1.index, f2.index]); |
| 121 | builder.addElementSegment(t2, offset2, false, [f3.index, f1.index]); |
| 122 | |
| 123 | const instance = builder.instantiate(); |
| 124 | |
| 125 | assertEquals(value1, instance.exports.get_t1(offset1)()); |
| 126 | assertEquals(value2, instance.exports.get_t1(offset1 + 1)()); |
| 127 | assertEquals(value3, instance.exports.get_t2(offset2)()); |
| 128 | assertEquals(value1, instance.exports.get_t2(offset2 + 1)()); |
| 129 | })(); |
| 130 | |
| 131 | (function testRefFuncInTableIsCallable() { |
| 132 | print(arguments.callee.name); |
| 133 | const expected = 54; |
| 134 | const index = 3; |
| 135 | const builder = new WasmModuleBuilder(); |
| 136 | const table_index = builder.addTable(kWasmAnyFunc, 15, 15).index; |
| 137 | const sig_index = builder.addType(kSig_i_v); |
| 138 | const function_index = builder.addFunction('hidden', sig_index) |
| 139 | .addBody([kExprI32Const, expected]) |
| 140 | .index; |
| 141 | builder.addDeclarativeElementSegment([function_index]); |
| 142 | |
| 143 | builder.addFunction('main', kSig_i_v) |
| 144 | .addBody([ |
| 145 | kExprI32Const, index, // entry index |
| 146 | kExprRefFunc, function_index, // function reference |
| 147 | kExprTableSet, table_index, // -- |
| 148 | kExprI32Const, index, // entry index |
| 149 | kExprCallIndirect, sig_index, table_index // -- |
| 150 | |
| 151 | ]) |
| 152 | .exportFunc(); |
| 153 | |
| 154 | const instance = builder.instantiate(); |
| 155 | assertEquals(expected, instance.exports.main()); |
| 156 | })(); |