widening-i32-after-call.js (2800B)
1 // |jit-test| skip-if: !hasDisassembler() || !(wasmCompileMode() == "baseline" || wasmCompileMode() == "ion") || !(getBuildConfiguration("x64") && !getBuildConfiguration("arm-simulator") && !getBuildConfiguration("arm64-simulator") && !getBuildConfiguration("mips64-simulator") && !getBuildConfiguration("riscv64-simulator")) 2 3 // We widen i32 results after calls on 64-bit platforms for two reasons: 4 // 5 // - it's a cheap mitigation for certain spectre problems, and 6 // - it makes the high bits of the 64-bit register conform to platform 7 // conventions, which they might not if the call was to C++ code 8 // especially. 9 // 10 // This is a whitebox test that explicit widening instructions are inserted 11 // after calls on x64. The widening is platform-specific; on x64, the upper 12 // bits are zeroed. 13 14 // What we can't test here is the direct-call-from-JIT path, as the generated 15 // code is not available to wasmDis. 16 17 var ins = wasmEvalText(` 18 (module 19 (import "" "wasm2import" (func $g (result i32))) 20 (memory 1) 21 (type $ty (func (result i32))) 22 (table $t 1 1 funcref) 23 (func $f (result i32) 24 (i32.const 37)) 25 (func (export "wasm2wasm") (result i32) 26 (call $f)) 27 (func (export "wasm2import") (result i32) 28 (call $g)) 29 (func (export "wasmIndirect") (result i32) 30 (call_indirect $t (type $ty) (i32.const 0))) 31 (func (export "instanceCall") (result i32) 32 (memory.size)) 33 )`, {'':{'wasm2import': function() {}}}); 34 35 switch (wasmCompileMode()) { 36 case "ion": 37 assertEq(wasmDis(ins.exports.wasm2wasm, {tier:'stable', asString:true}).match(/call.*\n(?:.*lea.*%rsp\n)?.*mov %eax, %eax/).length, 1); 38 assertEq(wasmDis(ins.exports.wasm2import, {tier:'stable', asString:true}).match(/call.*\n(?:.*or \$0x00, %r14\n)?(?:.*movq.*\n)*(?:.*lea.*%rsp\n)?.*mov %eax, %eax/).length, 1); 39 assertEq(wasmDis(ins.exports.wasmIndirect, {tier:'stable', asString:true}).match(/call.*\n(?:.*movq.*\n)*(?:.*lea.*%rsp\n)?.*mov %eax, %eax/).length, 1); 40 assertEq(wasmDis(ins.exports.instanceCall, {tier:'stable', asString:true}).match(/call.*\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1); 41 break; 42 case "baseline": 43 assertEq(wasmDis(ins.exports.wasm2wasm, {tier:'stable', asString:true}).match(/call.*\n.*lea.*%rsp\n.*mov %eax, %eax/).length, 1); 44 assertEq(wasmDis(ins.exports.wasm2import, {tier:'stable', asString:true}).match(/call.*\n(?:.*or \$0x00, %r14\n)?.*lea.*%rsp\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1); 45 assertEq(wasmDis(ins.exports.wasmIndirect, {tier:'stable', asString:true}).match(/call.*\n.*lea.*%rsp\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1); 46 assertEq(wasmDis(ins.exports.instanceCall, {tier:'stable', asString:true}).match(/call.*\n.*lea.*%rsp\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1); 47 break; 48 default: 49 throw "Unexpected compile mode"; 50 }