Diff
Modified: trunk/JSTests/ChangeLog (209475 => 209476)
--- trunk/JSTests/ChangeLog 2016-12-07 21:33:37 UTC (rev 209475)
+++ trunk/JSTests/ChangeLog 2016-12-07 21:43:58 UTC (rev 209476)
@@ -1,3 +1,19 @@
+2016-12-06 Keith Miller <keith_mil...@apple.com>
+
+ Add support for truncation operators
+ https://bugs.webkit.org/show_bug.cgi?id=165519
+
+ Reviewed by Geoffrey Garen.
+
+ * wasm/function-tests/i32-trunc-s-f32.js: Added.
+ * wasm/function-tests/i32-trunc-s-f64.js: Added.
+ * wasm/function-tests/i32-trunc-u-f32.js: Added.
+ * wasm/function-tests/i32-trunc-u-f64.js: Added.
+ * wasm/function-tests/i64-trunc-s-f32.js: Added.
+ * wasm/function-tests/i64-trunc-s-f64.js: Added.
+ * wasm/function-tests/i64-trunc-u-f32.js: Added.
+ * wasm/function-tests/i64-trunc-u-f64.js: Added.
+
2016-12-06 Mark Lam <mark....@apple.com>
Introduce the concept of Immutable Prototype Exotic Objects to comply with the spec.
Added: trunk/JSTests/wasm/function-tests/i32-trunc-s-f32.js (0 => 209476)
--- trunk/JSTests/wasm/function-tests/i32-trunc-s-f32.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/i32-trunc-s-f32.js 2016-12-07 21:43:58 UTC (rev 209476)
@@ -0,0 +1,31 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+ .Function().End()
+ .Code()
+ .Function({ params: ["f32"], ret: "i32" }, [])
+ .GetLocal(0)
+ .I32TruncSF32()
+ .End()
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 1,
+ [[{ type: "i32", value: "0" }, [{ type: "f32", value: "0.0" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f32", value: "-0.0" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f32", value: "0x1p-149" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f32", value: "-0x1p-149" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f32", value: "1.0" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f32", value: "0x1.19999ap+0" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f32", value: "1.5" }]],
+ [{ type: "i32", value: "-1" }, [{ type: "f32", value: "-1.0" }]],
+ [{ type: "i32", value: "-1" }, [{ type: "f32", value: "-0x1.19999ap+0" }]],
+ [{ type: "i32", value: "-1" }, [{ type: "f32", value: "-1.5" }]],
+ [{ type: "i32", value: "-1" }, [{ type: "f32", value: "-1.9" }]],
+ [{ type: "i32", value: "-2" }, [{ type: "f32", value: "-2.0" }]],
+ [{ type: "i32", value: "2147483520" }, [{ type: "f32", value: "2147483520.0" }]],
+ [{ type: "i32", value: "-2147483648" }, [{ type: "f32", value: "-2147483648.0" }]],
+ ],
+
+ );
Added: trunk/JSTests/wasm/function-tests/i32-trunc-s-f64.js (0 => 209476)
--- trunk/JSTests/wasm/function-tests/i32-trunc-s-f64.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/i32-trunc-s-f64.js 2016-12-07 21:43:58 UTC (rev 209476)
@@ -0,0 +1,31 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+ .Function().End()
+ .Code()
+ .Function({ params: ["f64"], ret: "i32" }, [])
+ .GetLocal(0)
+ .I32TruncSF64()
+ .End()
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 1,
+ [[{ type: "i32", value: "0" }, [{ type: "f64", value: "0.0" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f64", value: "-0.0" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f64", value: "0x0.0000000000001p-1022" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f64", value: "-0x0.0000000000001p-1022" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f64", value: "1.0" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f64", value: "0x1.199999999999ap+0" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f64", value: "1.5" }]],
+ [{ type: "i32", value: "-1" }, [{ type: "f64", value: "-1.0" }]],
+ [{ type: "i32", value: "-1" }, [{ type: "f64", value: "-0x1.199999999999ap+0" }]],
+ [{ type: "i32", value: "-1" }, [{ type: "f64", value: "-1.5" }]],
+ [{ type: "i32", value: "-1" }, [{ type: "f64", value: "-1.9" }]],
+ [{ type: "i32", value: "-2" }, [{ type: "f64", value: "-2.0" }]],
+ [{ type: "i32", value: "2147483647" }, [{ type: "f64", value: "2147483647.0" }]],
+ [{ type: "i32", value: "-2147483648" }, [{ type: "f64", value: "-2147483648.0" }]],
+ ],
+
+ );
Added: trunk/JSTests/wasm/function-tests/i32-trunc-u-f32.js (0 => 209476)
--- trunk/JSTests/wasm/function-tests/i32-trunc-u-f32.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/i32-trunc-u-f32.js 2016-12-07 21:43:58 UTC (rev 209476)
@@ -0,0 +1,29 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+ .Function().End()
+ .Code()
+ .Function({ params: ["f32"], ret: "i32" }, [])
+ .GetLocal(0)
+ .I32TruncUF32()
+ .End()
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 1,
+ [[{ type: "i32", value: "0" }, [{ type: "f32", value: "0.0" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f32", value: "-0.0" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f32", value: "0x1p-149" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f32", value: "-0x1p-149" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f32", value: "1.0" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f32", value: "0x1.19999ap+0" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f32", value: "1.5" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f32", value: "1.9" }]],
+ [{ type: "i32", value: "2" }, [{ type: "f32", value: "2.0" }]],
+ [{ type: "i32", value: "-2147483648" }, [{ type: "f32", value: "2147483648" }]],
+ [{ type: "i32", value: "-256" }, [{ type: "f32", value: "4294967040.0" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f32", value: "-0x1.ccccccp-1" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f32", value: "-0x1.fffffep-1" }]],
+ ],
+ );
Added: trunk/JSTests/wasm/function-tests/i32-trunc-u-f64.js (0 => 209476)
--- trunk/JSTests/wasm/function-tests/i32-trunc-u-f64.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/i32-trunc-u-f64.js 2016-12-07 21:43:58 UTC (rev 209476)
@@ -0,0 +1,30 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+ .Function().End()
+ .Code()
+ .Function({ params: ["f64"], ret: "i32" }, [])
+ .GetLocal(0)
+ .I32TruncUF64()
+ .End()
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 1,
+ [[{ type: "i32", value: "0" }, [{ type: "f64", value: "0.0" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f64", value: "-0.0" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f64", value: "0x0.0000000000001p-1022" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f64", value: "-0x0.0000000000001p-1022" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f64", value: "1.0" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f64", value: "0x1.199999999999ap+0" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f64", value: "1.5" }]],
+ [{ type: "i32", value: "1" }, [{ type: "f64", value: "1.9" }]],
+ [{ type: "i32", value: "2" }, [{ type: "f64", value: "2.0" }]],
+ [{ type: "i32", value: "-2147483648" }, [{ type: "f64", value: "2147483648" }]],
+ [{ type: "i32", value: "-1" }, [{ type: "f64", value: "4294967295.0" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f64", value: "-0x1.ccccccccccccdp-1" }]],
+ [{ type: "i32", value: "0" }, [{ type: "f64", value: "-0x1.fffffffffffffp-1" }]],
+ [{ type: "i32", value: "100000000" }, [{ type: "f64", value: "1e8" }]],
+ ],
+ );
Added: trunk/JSTests/wasm/function-tests/i64-trunc-s-f32.js (0 => 209476)
--- trunk/JSTests/wasm/function-tests/i64-trunc-s-f32.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/i64-trunc-s-f32.js 2016-12-07 21:43:58 UTC (rev 209476)
@@ -0,0 +1,33 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+ .Function().End()
+ .Code()
+ .Function({ params: ["f32"], ret: "i64" }, [])
+ .GetLocal(0)
+ .I64TruncSF32()
+ .End()
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 1,
+ [[{ type: "i64", value: "0" }, [{ type: "f32", value: "0.0" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f32", value: "-0.0" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f32", value: "0x1p-149" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f32", value: "-0x1p-149" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f32", value: "1.0" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f32", value: "0x1.19999ap+0" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f32", value: "1.5" }]],
+ [{ type: "i64", value: "-1" }, [{ type: "f32", value: "-1.0" }]],
+ [{ type: "i64", value: "-1" }, [{ type: "f32", value: "-0x1.19999ap+0" }]],
+ [{ type: "i64", value: "-1" }, [{ type: "f32", value: "-1.5" }]],
+ [{ type: "i64", value: "-1" }, [{ type: "f32", value: "-1.9" }]],
+ [{ type: "i64", value: "-2" }, [{ type: "f32", value: "-2.0" }]],
+ [{ type: "i64", value: "4294967296" }, [{ type: "f32", value: "4294967296" }]],
+ [{ type: "i64", value: "-4294967296" }, [{ type: "f32", value: "-4294967296" }]],
+ [{ type: "i64", value: "9223371487098961920" }, [{ type: "f32", value: "9223371487098961920.0" }]],
+ [{ type: "i64", value: "-9223372036854775808" }, [{ type: "f32", value: "-9223372036854775808.0" }]],
+ ],
+
+ );
Added: trunk/JSTests/wasm/function-tests/i64-trunc-s-f64.js (0 => 209476)
--- trunk/JSTests/wasm/function-tests/i64-trunc-s-f64.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/i64-trunc-s-f64.js 2016-12-07 21:43:58 UTC (rev 209476)
@@ -0,0 +1,33 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+ .Function().End()
+ .Code()
+ .Function({ params: ["f64"], ret: "i64" }, [])
+ .GetLocal(0)
+ .I64TruncSF64()
+ .End()
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 1,
+ [[{ type: "i64", value: "0" }, [{ type: "f64", value: "0.0" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f64", value: "-0.0" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f64", value: "0x0.0000000000001p-1022" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f64", value: "-0x0.0000000000001p-1022" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f64", value: "1.0" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f64", value: "0x1.199999999999ap+0" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f64", value: "1.5" }]],
+ [{ type: "i64", value: "-1" }, [{ type: "f64", value: "-1.0" }]],
+ [{ type: "i64", value: "-1" }, [{ type: "f64", value: "-0x1.199999999999ap+0" }]],
+ [{ type: "i64", value: "-1" }, [{ type: "f64", value: "-1.5" }]],
+ [{ type: "i64", value: "-1" }, [{ type: "f64", value: "-1.9" }]],
+ [{ type: "i64", value: "-2" }, [{ type: "f64", value: "-2.0" }]],
+ [{ type: "i64", value: "4294967296" }, [{ type: "f64", value: "4294967296" }]],
+ [{ type: "i64", value: "-4294967296" }, [{ type: "f64", value: "-4294967296" }]],
+ [{ type: "i64", value: "9223372036854774784" }, [{ type: "f64", value: "9223372036854774784.0" }]],
+ [{ type: "i64", value: "-9223372036854775808" }, [{ type: "f64", value: "-9223372036854775808.0" }]],
+ ],
+
+ );
Added: trunk/JSTests/wasm/function-tests/i64-trunc-u-f32.js (0 => 209476)
--- trunk/JSTests/wasm/function-tests/i64-trunc-u-f32.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/i64-trunc-u-f32.js 2016-12-07 21:43:58 UTC (rev 209476)
@@ -0,0 +1,27 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+ .Function().End()
+ .Code()
+ .Function({ params: ["f32"], ret: "i64" }, [])
+ .GetLocal(0)
+ .I64TruncUF32()
+ .End()
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 1,
+ [[{ type: "i64", value: "0" }, [{ type: "f32", value: "0.0" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f32", value: "-0.0" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f32", value: "0x1p-149" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f32", value: "-0x1p-149" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f32", value: "1.0" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f32", value: "0x1.19999ap+0" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f32", value: "1.5" }]],
+ [{ type: "i64", value: "4294967296" }, [{ type: "f32", value: "4294967296" }]],
+ [{ type: "i64", value: "-1099511627776" }, [{ type: "f32", value: "18446742974197923840.0" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f32", value: "-0x1.ccccccp-1" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f32", value: "-0x1.fffffep-1" }]],[{ type: "i64", value: "0" }, [{ type: "f32", value: "0.0" }]],
+ ],
+ );
Added: trunk/JSTests/wasm/function-tests/i64-trunc-u-f64.js (0 => 209476)
--- trunk/JSTests/wasm/function-tests/i64-trunc-u-f64.js (rev 0)
+++ trunk/JSTests/wasm/function-tests/i64-trunc-u-f64.js 2016-12-07 21:43:58 UTC (rev 209476)
@@ -0,0 +1,32 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+ .Function().End()
+ .Code()
+ .Function({ params: ["f64"], ret: "i64" }, [])
+ .GetLocal(0)
+ .I64TruncUF64()
+ .End()
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 1,
+ [[{ type: "i64", value: "0" }, [{ type: "f64", value: "0.0" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f64", value: "-0.0" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f64", value: "0x0.0000000000001p-1022" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f64", value: "-0x0.0000000000001p-1022" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f64", value: "1.0" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f64", value: "0x1.199999999999ap+0" }]],
+ [{ type: "i64", value: "1" }, [{ type: "f64", value: "1.5" }]],
+ [{ type: "i64", value: "0xffffffff" }, [{ type: "f64", value: "4294967295" }]],
+ [{ type: "i64", value: "0x100000000" }, [{ type: "f64", value: "4294967296" }]],
+ [{ type: "i64", value: "-2048" }, [{ type: "f64", value: "18446744073709549568.0" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f64", value: "-0x1.ccccccccccccdp-1" }]],
+ [{ type: "i64", value: "0" }, [{ type: "f64", value: "-0x1.fffffffffffffp-1" }]],
+ [{ type: "i64", value: "100000000" }, [{ type: "f64", value: "1e8" }]],
+ [{ type: "i64", value: "10000000000000000" }, [{ type: "f64", value: "1e16" }]],
+ [{ type: "i64", value: "-9223372036854775808" }, [{ type: "f64", value: "9223372036854775808" }]],
+ ],
+
+ );
Modified: trunk/Source/_javascript_Core/ChangeLog (209475 => 209476)
--- trunk/Source/_javascript_Core/ChangeLog 2016-12-07 21:33:37 UTC (rev 209475)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-12-07 21:43:58 UTC (rev 209476)
@@ -1,3 +1,48 @@
+2016-12-06 Keith Miller <keith_mil...@apple.com>
+
+ Add support for truncation operators
+ https://bugs.webkit.org/show_bug.cgi?id=165519
+
+ Reviewed by Geoffrey Garen.
+
+ This patch adds initial support for truncation operators. The current patch
+ does range based out of bounds checking, in the future we should use system
+ register flags on ARM and other tricks on X86 improve the performance of
+ these opcodes.
+
+ * assembler/MacroAssemblerARM64.h:
+ (JSC::MacroAssemblerARM64::branchTruncateDoubleToInt32):
+ (JSC::MacroAssemblerARM64::truncateDoubleToInt64):
+ (JSC::MacroAssemblerARM64::truncateDoubleToUint64):
+ (JSC::MacroAssemblerARM64::truncateFloatToInt32):
+ (JSC::MacroAssemblerARM64::truncateFloatToUint32):
+ (JSC::MacroAssemblerARM64::truncateFloatToInt64):
+ (JSC::MacroAssemblerARM64::truncateFloatToUint64):
+ * assembler/MacroAssemblerX86Common.h:
+ (JSC::MacroAssemblerX86Common::truncateFloatToInt32):
+ (JSC::MacroAssemblerX86Common::truncateDoubleToUint32): Deleted.
+ * assembler/MacroAssemblerX86_64.h:
+ (JSC::MacroAssemblerX86_64::truncateDoubleToUint32):
+ (JSC::MacroAssemblerX86_64::truncateDoubleToInt64):
+ (JSC::MacroAssemblerX86_64::truncateDoubleToUint64):
+ (JSC::MacroAssemblerX86_64::truncateFloatToUint32):
+ (JSC::MacroAssemblerX86_64::truncateFloatToInt64):
+ (JSC::MacroAssemblerX86_64::truncateFloatToUint64):
+ * assembler/X86Assembler.h:
+ (JSC::X86Assembler::cvttss2si_rr):
+ (JSC::X86Assembler::cvttss2siq_rr):
+ * wasm/WasmB3IRGenerator.cpp:
+ (JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncSF64>):
+ (JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncSF32>):
+ (JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncUF64>):
+ (JSC::Wasm::B3IRGenerator::addOp<OpType::I32TruncUF32>):
+ (JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncSF64>):
+ (JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncUF64>):
+ (JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncSF32>):
+ (JSC::Wasm::B3IRGenerator::addOp<OpType::I64TruncUF32>):
+ * wasm/WasmFunctionParser.h:
+ (JSC::Wasm::FunctionParser<Context>::parseExpression):
+
2016-12-07 Joseph Pecoraro <pecor...@apple.com>
Web Inspector: Remove unused and mostly untested Page domain commands and events
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h (209475 => 209476)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h 2016-12-07 21:33:37 UTC (rev 209475)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerARM64.h 2016-12-07 21:43:58 UTC (rev 209476)
@@ -1655,7 +1655,7 @@
// Truncate to a 64-bit integer in dataTempRegister, copy the low 32-bit to dest.
m_assembler.fcvtzs<64, 64>(getCachedDataTempRegisterIDAndInvalidate(), src);
zeroExtend32ToPtr(dataTempRegister, dest);
- // Check thlow 32-bits sign extend to be equal to the full value.
+ // Check the low 32-bits sign extend to be equal to the full value.
m_assembler.cmp<64>(dataTempRegister, dataTempRegister, ARM64Assembler::SXTW, 0);
return Jump(makeBranch(branchType == BranchIfTruncateSuccessful ? Equal : NotEqual));
}
@@ -2041,7 +2041,46 @@
m_assembler.fcvtzu<32, 64>(dest, src);
}
+ void truncateDoubleToInt64(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.fcvtzs<64, 64>(dest, src);
+ }
+ void truncateDoubleToUint64(FPRegisterID src, RegisterID dest, FPRegisterID, FPRegisterID)
+ {
+ truncateDoubleToUint64(src, dest);
+ }
+
+ void truncateDoubleToUint64(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.fcvtzu<64, 64>(dest, src);
+ }
+
+ void truncateFloatToInt32(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.fcvtzs<32, 32>(dest, src);
+ }
+
+ void truncateFloatToUint32(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.fcvtzu<32, 32>(dest, src);
+ }
+
+ void truncateFloatToInt64(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.fcvtzs<64, 32>(dest, src);
+ }
+
+ void truncateFloatToUint64(FPRegisterID src, RegisterID dest, FPRegisterID, FPRegisterID)
+ {
+ truncateFloatToUint64(src, dest);
+ }
+
+ void truncateFloatToUint64(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.fcvtzu<64, 32>(dest, src);
+ }
+
// Stack manipulation operations:
//
// The ABI is assumed to provide a stack abstraction to memory,
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h (209475 => 209476)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2016-12-07 21:33:37 UTC (rev 209475)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86Common.h 2016-12-07 21:43:58 UTC (rev 209476)
@@ -1678,15 +1678,13 @@
ASSERT(isSSE2Present());
m_assembler.cvttsd2si_rr(src, dest);
}
-
-#if CPU(X86_64)
- void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
+
+ void truncateFloatToInt32(FPRegisterID src, RegisterID dest)
{
ASSERT(isSSE2Present());
- m_assembler.cvttsd2siq_rr(src, dest);
+ m_assembler.cvttss2si_rr(src, dest);
}
-#endif
-
+
// Convert 'src' to an integer, and places the resulting 'dest'.
// If the result is not representable as a 32 bit value, branch.
// May also branch for some values that are representable in 32 bits
Modified: trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h (209475 => 209476)
--- trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h 2016-12-07 21:33:37 UTC (rev 209475)
+++ trunk/Source/_javascript_Core/assembler/MacroAssemblerX86_64.h 2016-12-07 21:43:58 UTC (rev 209476)
@@ -1295,6 +1295,72 @@
return MacroAssemblerX86Common::branchTest8(cond, Address(scratchRegister()), mask8);
}
+ void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.cvttsd2siq_rr(src, dest);
+ }
+
+ void truncateDoubleToInt64(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.cvttsd2siq_rr(src, dest);
+ }
+
+ // int64Min should contain exactly 0x43E0000000000000 == static_cast<double>(int64_t::min()). scratch may
+ // be the same FPR as src.
+ void truncateDoubleToUint64(FPRegisterID src, RegisterID dest, FPRegisterID scratch, FPRegisterID int64Min)
+ {
+ ASSERT(scratch != int64Min);
+
+ // Since X86 does not have a floating point to unsigned integer instruction, we need to use the signed
+ // integer conversion instruction. If the src is less than int64_t::min() then the results of the two
+ // instructions are the same. Otherwise, we need to: subtract int64_t::min(); truncate double to
+ // uint64_t; then add back int64_t::min() in the destination gpr.
+
+ Jump large = branchDouble(DoubleGreaterThanOrEqual, src, int64Min);
+ m_assembler.cvttsd2siq_rr(src, dest);
+ Jump done = jump();
+ large.link(this);
+ moveDouble(src, scratch);
+ m_assembler.subsd_rr(int64Min, scratch);
+ m_assembler.movq_i64r(0x8000000000000000, scratchRegister());
+ m_assembler.cvttsd2siq_rr(scratch, dest);
+ m_assembler.orq_rr(scratchRegister(), dest);
+ done.link(this);
+ }
+
+ void truncateFloatToUint32(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.cvttss2siq_rr(src, dest);
+ }
+
+ void truncateFloatToInt64(FPRegisterID src, RegisterID dest)
+ {
+ m_assembler.cvttss2siq_rr(src, dest);
+ }
+
+ // int64Min should contain exactly 0x5f000000 == static_cast<float>(int64_t::min()). scratch may be the
+ // same FPR as src.
+ void truncateFloatToUint64(FPRegisterID src, RegisterID dest, FPRegisterID scratch, FPRegisterID int64Min)
+ {
+ ASSERT(scratch != int64Min);
+
+ // Since X86 does not have a floating point to unsigned integer instruction, we need to use the signed
+ // integer conversion instruction. If the src is less than int64_t::min() then the results of the two
+ // instructions are the same. Otherwise, we need to: subtract int64_t::min(); truncate double to
+ // uint64_t; then add back int64_t::min() in the destination gpr.
+
+ Jump large = branchFloat(DoubleGreaterThanOrEqual, src, int64Min);
+ m_assembler.cvttss2siq_rr(src, dest);
+ Jump done = jump();
+ large.link(this);
+ moveDouble(src, scratch);
+ m_assembler.subss_rr(int64Min, scratch);
+ m_assembler.movq_i64r(0x8000000000000000, scratchRegister());
+ m_assembler.cvttss2siq_rr(scratch, dest);
+ m_assembler.orq_rr(scratchRegister(), dest);
+ done.link(this);
+ }
+
void convertInt64ToDouble(RegisterID src, FPRegisterID dest)
{
m_assembler.cvtsi2sdq_rr(src, dest);
Modified: trunk/Source/_javascript_Core/assembler/X86Assembler.h (209475 => 209476)
--- trunk/Source/_javascript_Core/assembler/X86Assembler.h 2016-12-07 21:33:37 UTC (rev 209475)
+++ trunk/Source/_javascript_Core/assembler/X86Assembler.h 2016-12-07 21:43:58 UTC (rev 209476)
@@ -267,6 +267,7 @@
OP2_MOVAPS_VpdWpd = 0x28,
OP2_CVTSI2SD_VsdEd = 0x2A,
OP2_CVTTSD2SI_GdWsd = 0x2C,
+ OP2_CVTTSS2SI_GdWsd = 0x2C,
OP2_UCOMISD_VsdWsd = 0x2E,
OP2_3BYTE_ESCAPE_3A = 0x3A,
OP2_CMOVCC = 0x40,
@@ -2293,6 +2294,20 @@
m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
}
+ void cvttss2si_rr(XMMRegisterID src, RegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F3);
+ m_formatter.twoByteOp(OP2_CVTTSS2SI_GdWsd, dst, (RegisterID)src);
+ }
+
+#if CPU(X86_64)
+ void cvttss2siq_rr(XMMRegisterID src, RegisterID dst)
+ {
+ m_formatter.prefix(PRE_SSE_F3);
+ m_formatter.twoByteOp64(OP2_CVTTSS2SI_GdWsd, dst, (RegisterID)src);
+ }
+#endif
+
void cvtsd2ss_rr(XMMRegisterID src, XMMRegisterID dst)
{
m_formatter.prefix(PRE_SSE_F2);
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (209475 => 209476)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2016-12-07 21:33:37 UTC (rev 209475)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2016-12-07 21:43:58 UTC (rev 209476)
@@ -905,6 +905,229 @@
return true;
}
+template<>
+bool B3IRGenerator::addOp<OpType::I32TruncSF64>(ExpressionType arg, ExpressionType& result)
+{
+ Value* max = m_currentBlock->appendNew<ConstDoubleValue>(m_proc, Origin(), -static_cast<double>(std::numeric_limits<int32_t>::min()));
+ Value* min = m_currentBlock->appendNew<ConstDoubleValue>(m_proc, Origin(), static_cast<double>(std::numeric_limits<int32_t>::min()));
+ Value* outOfBounds = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(),
+ m_currentBlock->appendNew<Value>(m_proc, LessThan, Origin(), arg, max),
+ m_currentBlock->appendNew<Value>(m_proc, GreaterEqual, Origin(), arg, min));
+ outOfBounds = m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(), outOfBounds, zeroForType(I32));
+ CheckValue* trap = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(), outOfBounds);
+ trap->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
+ jit.breakpoint();
+ });
+ PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Int32, Origin());
+ patchpoint->append(arg, ValueRep::SomeRegister);
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ jit.truncateDoubleToInt32(params[1].fpr(), params[0].gpr());
+ });
+ patchpoint->effects = Effects::none();
+ result = patchpoint;
+ return true;
+}
+
+template<>
+bool B3IRGenerator::addOp<OpType::I32TruncSF32>(ExpressionType arg, ExpressionType& result)
+{
+ Value* max = m_currentBlock->appendNew<ConstFloatValue>(m_proc, Origin(), -static_cast<float>(std::numeric_limits<int32_t>::min()));
+ Value* min = m_currentBlock->appendNew<ConstFloatValue>(m_proc, Origin(), static_cast<float>(std::numeric_limits<int32_t>::min()));
+ Value* outOfBounds = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(),
+ m_currentBlock->appendNew<Value>(m_proc, LessThan, Origin(), arg, max),
+ m_currentBlock->appendNew<Value>(m_proc, GreaterEqual, Origin(), arg, min));
+ outOfBounds = m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(), outOfBounds, zeroForType(I32));
+ CheckValue* trap = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(), outOfBounds);
+ trap->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
+ jit.breakpoint();
+ });
+ PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Int32, Origin());
+ patchpoint->append(arg, ValueRep::SomeRegister);
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ jit.truncateFloatToInt32(params[1].fpr(), params[0].gpr());
+ });
+ patchpoint->effects = Effects::none();
+ result = patchpoint;
+ return true;
+}
+
+
+template<>
+bool B3IRGenerator::addOp<OpType::I32TruncUF64>(ExpressionType arg, ExpressionType& result)
+{
+ Value* max = m_currentBlock->appendNew<ConstDoubleValue>(m_proc, Origin(), static_cast<double>(std::numeric_limits<int32_t>::min()) * -2.0);
+ Value* min = m_currentBlock->appendNew<ConstDoubleValue>(m_proc, Origin(), -1.0);
+ Value* outOfBounds = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(),
+ m_currentBlock->appendNew<Value>(m_proc, LessThan, Origin(), arg, max),
+ m_currentBlock->appendNew<Value>(m_proc, GreaterThan, Origin(), arg, min));
+ outOfBounds = m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(), outOfBounds, zeroForType(I32));
+ CheckValue* trap = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(), outOfBounds);
+ trap->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
+ jit.breakpoint();
+ });
+ PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Int32, Origin());
+ patchpoint->append(arg, ValueRep::SomeRegister);
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ jit.truncateDoubleToUint32(params[1].fpr(), params[0].gpr());
+ });
+ patchpoint->effects = Effects::none();
+ result = patchpoint;
+ return true;
+}
+
+template<>
+bool B3IRGenerator::addOp<OpType::I32TruncUF32>(ExpressionType arg, ExpressionType& result)
+{
+ Value* max = m_currentBlock->appendNew<ConstFloatValue>(m_proc, Origin(), static_cast<float>(std::numeric_limits<int32_t>::min()) * -2.0);
+ Value* min = m_currentBlock->appendNew<ConstFloatValue>(m_proc, Origin(), -1.0);
+ Value* outOfBounds = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(),
+ m_currentBlock->appendNew<Value>(m_proc, LessThan, Origin(), arg, max),
+ m_currentBlock->appendNew<Value>(m_proc, GreaterThan, Origin(), arg, min));
+ outOfBounds = m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(), outOfBounds, zeroForType(I32));
+ CheckValue* trap = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(), outOfBounds);
+ trap->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
+ jit.breakpoint();
+ });
+ PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Int32, Origin());
+ patchpoint->append(arg, ValueRep::SomeRegister);
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ jit.truncateFloatToUint32(params[1].fpr(), params[0].gpr());
+ });
+ patchpoint->effects = Effects::none();
+ result = patchpoint;
+ return true;
+}
+
+template<>
+bool B3IRGenerator::addOp<OpType::I64TruncSF64>(ExpressionType arg, ExpressionType& result)
+{
+ Value* max = m_currentBlock->appendNew<ConstDoubleValue>(m_proc, Origin(), -static_cast<double>(std::numeric_limits<int64_t>::min()));
+ Value* min = m_currentBlock->appendNew<ConstDoubleValue>(m_proc, Origin(), static_cast<double>(std::numeric_limits<int64_t>::min()));
+ Value* outOfBounds = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(),
+ m_currentBlock->appendNew<Value>(m_proc, LessThan, Origin(), arg, max),
+ m_currentBlock->appendNew<Value>(m_proc, GreaterEqual, Origin(), arg, min));
+ outOfBounds = m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(), outOfBounds, zeroForType(I32));
+ CheckValue* trap = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(), outOfBounds);
+ trap->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
+ jit.breakpoint();
+ });
+ PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Int64, Origin());
+ patchpoint->append(arg, ValueRep::SomeRegister);
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ jit.truncateDoubleToInt64(params[1].fpr(), params[0].gpr());
+ });
+ patchpoint->effects = Effects::none();
+ result = patchpoint;
+ return true;
+}
+
+template<>
+bool B3IRGenerator::addOp<OpType::I64TruncUF64>(ExpressionType arg, ExpressionType& result)
+{
+ Value* max = m_currentBlock->appendNew<ConstDoubleValue>(m_proc, Origin(), static_cast<double>(std::numeric_limits<int64_t>::min()) * -2.0);
+ Value* min = m_currentBlock->appendNew<ConstDoubleValue>(m_proc, Origin(), -1.0);
+ Value* outOfBounds = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(),
+ m_currentBlock->appendNew<Value>(m_proc, LessThan, Origin(), arg, max),
+ m_currentBlock->appendNew<Value>(m_proc, GreaterThan, Origin(), arg, min));
+ outOfBounds = m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(), outOfBounds, zeroForType(I32));
+ CheckValue* trap = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(), outOfBounds);
+ trap->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
+ jit.breakpoint();
+ });
+
+ Value* constant;
+ if (isX86()) {
+ // Since x86 doesn't have an instruction to convert floating points to unsigned integers, we at least try to do the smart thing if
+ // the numbers are would be positive anyway as a signed integer. Since we cannot materialize constants into fprs we have b3 do it
+ // so we can pool them if needed.
+ constant = m_currentBlock->appendNew<ConstDoubleValue>(m_proc, Origin(), static_cast<double>(std::numeric_limits<uint64_t>::max() - std::numeric_limits<int64_t>::max()));
+ }
+ PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Int64, Origin());
+ patchpoint->append(arg, ValueRep::SomeRegister);
+ if (isX86()) {
+ patchpoint->append(constant, ValueRep::SomeRegister);
+ patchpoint->numFPScratchRegisters = 1;
+ }
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ AllowMacroScratchRegisterUsage allowScratch(jit);
+ FPRReg scratch = InvalidFPRReg;
+ FPRReg constant = InvalidFPRReg;
+ if (isX86()) {
+ scratch = params.fpScratch(0);
+ constant = params[2].fpr();
+ }
+ jit.truncateDoubleToUint64(params[1].fpr(), params[0].gpr(), scratch, constant);
+ });
+ patchpoint->effects = Effects::none();
+ result = patchpoint;
+ return true;
+}
+
+template<>
+bool B3IRGenerator::addOp<OpType::I64TruncSF32>(ExpressionType arg, ExpressionType& result)
+{
+ Value* max = m_currentBlock->appendNew<ConstFloatValue>(m_proc, Origin(), -static_cast<float>(std::numeric_limits<int64_t>::min()));
+ Value* min = m_currentBlock->appendNew<ConstFloatValue>(m_proc, Origin(), static_cast<float>(std::numeric_limits<int64_t>::min()));
+ Value* outOfBounds = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(),
+ m_currentBlock->appendNew<Value>(m_proc, LessThan, Origin(), arg, max),
+ m_currentBlock->appendNew<Value>(m_proc, GreaterEqual, Origin(), arg, min));
+ outOfBounds = m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(), outOfBounds, zeroForType(I32));
+ CheckValue* trap = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(), outOfBounds);
+ trap->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
+ jit.breakpoint();
+ });
+ PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Int64, Origin());
+ patchpoint->append(arg, ValueRep::SomeRegister);
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ jit.truncateFloatToInt64(params[1].fpr(), params[0].gpr());
+ });
+ patchpoint->effects = Effects::none();
+ result = patchpoint;
+ return true;
+}
+
+template<>
+bool B3IRGenerator::addOp<OpType::I64TruncUF32>(ExpressionType arg, ExpressionType& result)
+{
+ Value* max = m_currentBlock->appendNew<ConstFloatValue>(m_proc, Origin(), static_cast<float>(std::numeric_limits<int64_t>::min()) * -2.0);
+ Value* min = m_currentBlock->appendNew<ConstFloatValue>(m_proc, Origin(), -1.0);
+ Value* outOfBounds = m_currentBlock->appendNew<Value>(m_proc, BitAnd, Origin(),
+ m_currentBlock->appendNew<Value>(m_proc, LessThan, Origin(), arg, max),
+ m_currentBlock->appendNew<Value>(m_proc, GreaterThan, Origin(), arg, min));
+ outOfBounds = m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(), outOfBounds, zeroForType(I32));
+ CheckValue* trap = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(), outOfBounds);
+ trap->setGenerator([] (CCallHelpers& jit, const StackmapGenerationParams&) {
+ jit.breakpoint();
+ });
+
+ Value* constant;
+ if (isX86()) {
+ // Since x86 doesn't have an instruction to convert floating points to unsigned integers, we at least try to do the smart thing if
+ // the numbers are would be positive anyway as a signed integer. Since we cannot materialize constants into fprs we have b3 do it
+ // so we can pool them if needed.
+ constant = m_currentBlock->appendNew<ConstFloatValue>(m_proc, Origin(), static_cast<float>(std::numeric_limits<uint64_t>::max() - std::numeric_limits<int64_t>::max()));
+ }
+ PatchpointValue* patchpoint = m_currentBlock->appendNew<PatchpointValue>(m_proc, Int64, Origin());
+ patchpoint->append(arg, ValueRep::SomeRegister);
+ if (isX86()) {
+ patchpoint->append(constant, ValueRep::SomeRegister);
+ patchpoint->numFPScratchRegisters = 1;
+ }
+ patchpoint->setGenerator([=] (CCallHelpers& jit, const StackmapGenerationParams& params) {
+ AllowMacroScratchRegisterUsage allowScratch(jit);
+ FPRReg scratch = InvalidFPRReg;
+ FPRReg constant = InvalidFPRReg;
+ if (isX86()) {
+ scratch = params.fpScratch(0);
+ constant = params[2].fpr();
+ }
+ jit.truncateFloatToUint64(params[1].fpr(), params[0].gpr(), scratch, constant);
+ });
+ patchpoint->effects = Effects::none();
+ result = patchpoint;
+ return true;
+}
+
} } // namespace JSC::Wasm
#include "WasmB3IRGeneratorInlines.h"
Modified: trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h (209475 => 209476)
--- trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2016-12-07 21:33:37 UTC (rev 209475)
+++ trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h 2016-12-07 21:43:58 UTC (rev 209476)
@@ -221,6 +221,14 @@
case OpType::I64Ctz: return unaryCase<OpType::I64Ctz>();
case OpType::I32Popcnt: return unaryCase<OpType::I32Popcnt>();
case OpType::I64Popcnt: return unaryCase<OpType::I64Popcnt>();
+ case OpType::I32TruncSF32: return unaryCase<OpType::I32TruncSF32>();
+ case OpType::I32TruncUF32: return unaryCase<OpType::I32TruncUF32>();
+ case OpType::I32TruncSF64: return unaryCase<OpType::I32TruncSF64>();
+ case OpType::I32TruncUF64: return unaryCase<OpType::I32TruncUF64>();
+ case OpType::I64TruncSF32: return unaryCase<OpType::I64TruncSF32>();
+ case OpType::I64TruncUF32: return unaryCase<OpType::I64TruncUF32>();
+ case OpType::I64TruncSF64: return unaryCase<OpType::I64TruncSF64>();
+ case OpType::I64TruncUF64: return unaryCase<OpType::I64TruncUF64>();
#define CREATE_CASE(name, id, b3op, inc) case OpType::name: return unaryCase<OpType::name>();
FOR_EACH_WASM_SIMPLE_UNARY_OP(CREATE_CASE)
#undef CREATE_CASE