OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/wasm-compiler.h" | 5 #include "src/compiler/wasm-compiler.h" |
6 | 6 |
7 #include "src/isolate-inl.h" | 7 #include "src/isolate-inl.h" |
8 | 8 |
9 #include "src/base/platform/elapsed-timer.h" | 9 #include "src/base/platform/elapsed-timer.h" |
10 #include "src/base/platform/platform.h" | 10 #include "src/base/platform/platform.h" |
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
386 switch (opcode) { | 386 switch (opcode) { |
387 case wasm::kExprI32Add: | 387 case wasm::kExprI32Add: |
388 op = m->Int32Add(); | 388 op = m->Int32Add(); |
389 break; | 389 break; |
390 case wasm::kExprI32Sub: | 390 case wasm::kExprI32Sub: |
391 op = m->Int32Sub(); | 391 op = m->Int32Sub(); |
392 break; | 392 break; |
393 case wasm::kExprI32Mul: | 393 case wasm::kExprI32Mul: |
394 op = m->Int32Mul(); | 394 op = m->Int32Mul(); |
395 break; | 395 break; |
396 case wasm::kExprI32DivS: { | 396 case wasm::kExprI32DivS: |
397 trap_->ZeroCheck32(kTrapDivByZero, right); | 397 return BuildI32DivS(left, right); |
398 Node* before = *control_; | |
399 Node* denom_is_m1; | |
400 Node* denom_is_not_m1; | |
401 Branch(graph()->NewNode(jsgraph()->machine()->Word32Equal(), right, | |
402 jsgraph()->Int32Constant(-1)), | |
403 &denom_is_m1, &denom_is_not_m1); | |
404 *control_ = denom_is_m1; | |
405 trap_->TrapIfEq32(kTrapDivUnrepresentable, left, kMinInt); | |
406 if (*control_ != denom_is_m1) { | |
407 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), | |
408 denom_is_not_m1, *control_); | |
409 } else { | |
410 *control_ = before; | |
411 } | |
412 return graph()->NewNode(m->Int32Div(), left, right, *control_); | |
413 } | |
414 case wasm::kExprI32DivU: | 398 case wasm::kExprI32DivU: |
415 op = m->Uint32Div(); | 399 return BuildI32DivU(left, right); |
416 return graph()->NewNode(op, left, right, | 400 case wasm::kExprI32RemS: |
417 trap_->ZeroCheck32(kTrapDivByZero, right)); | 401 return BuildI32RemS(left, right); |
418 case wasm::kExprI32RemS: { | |
419 trap_->ZeroCheck32(kTrapRemByZero, right); | |
420 Diamond d(graph(), jsgraph()->common(), | |
421 graph()->NewNode(jsgraph()->machine()->Word32Equal(), right, | |
422 jsgraph()->Int32Constant(-1))); | |
423 | |
424 Node* rem = graph()->NewNode(m->Int32Mod(), left, right, d.if_false); | |
425 | |
426 return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | |
427 rem); | |
428 } | |
429 case wasm::kExprI32RemU: | 402 case wasm::kExprI32RemU: |
430 op = m->Uint32Mod(); | 403 return BuildI32RemU(left, right); |
431 return graph()->NewNode(op, left, right, | |
432 trap_->ZeroCheck32(kTrapRemByZero, right)); | |
433 case wasm::kExprI32And: | 404 case wasm::kExprI32And: |
434 op = m->Word32And(); | 405 op = m->Word32And(); |
435 break; | 406 break; |
436 case wasm::kExprI32Ior: | 407 case wasm::kExprI32Ior: |
437 op = m->Word32Or(); | 408 op = m->Word32Or(); |
438 break; | 409 break; |
439 case wasm::kExprI32Xor: | 410 case wasm::kExprI32Xor: |
440 op = m->Word32Xor(); | 411 op = m->Word32Xor(); |
441 break; | 412 break; |
442 case wasm::kExprI32Shl: | 413 case wasm::kExprI32Shl: |
(...skipping 1293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1736 trap_->ZeroCheck32(kTrapFloatUnrepresentable, | 1707 trap_->ZeroCheck32(kTrapFloatUnrepresentable, |
1737 BuildCCall(sig_builder.Build(), args)); | 1708 BuildCCall(sig_builder.Build(), args)); |
1738 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1709 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
1739 Node* load = | 1710 Node* load = |
1740 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), | 1711 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), |
1741 *effect_, *control_); | 1712 *effect_, *control_); |
1742 *effect_ = load; | 1713 *effect_ = load; |
1743 return load; | 1714 return load; |
1744 } | 1715 } |
1745 | 1716 |
1717 Node* WasmGraphBuilder::BuildI32DivS(Node* left, Node* right) { | |
1718 MachineOperatorBuilder* m = jsgraph()->machine(); | |
1719 if (module_ && module_->asm_js()) { | |
1720 // asm.js semantics return 0 on divide or mod by zero. | |
1721 if (m->Int32DivIsSafe()) { | |
1722 // The hardware instruction does the right thing (e.g. arm). | |
1723 return graph()->NewNode(m->Int32Div(), left, right, graph()->start()); | |
1724 } | |
1725 | |
1726 // Check denominator for zero. | |
1727 Diamond z( | |
1728 graph(), jsgraph()->common(), | |
1729 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | |
1730 BranchHint::kFalse); | |
1731 | |
1732 // Check numerator for -1. (avoid minint / -1 case). | |
1733 Diamond n( | |
1734 graph(), jsgraph()->common(), | |
1735 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | |
1736 BranchHint::kFalse); | |
1737 | |
1738 Node* div = graph()->NewNode(m->Int32Div(), left, right, z.if_false); | |
1739 Node* neg = | |
1740 graph()->NewNode(m->Int32Sub(), jsgraph()->Int32Constant(0), left); | |
1741 | |
1742 return n.Phi(MachineRepresentation::kWord32, neg, | |
1743 z.Phi(MachineRepresentation::kWord32, | |
1744 jsgraph()->Int32Constant(0), div)); | |
1745 } | |
1746 | |
1747 trap_->ZeroCheck32(kTrapDivByZero, right); | |
1748 Node* before = *control_; | |
1749 Node* denom_is_m1; | |
1750 Node* denom_is_not_m1; | |
1751 Branch( | |
1752 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | |
1753 &denom_is_m1, &denom_is_not_m1); | |
1754 *control_ = denom_is_m1; | |
1755 trap_->TrapIfEq32(kTrapDivUnrepresentable, left, kMinInt); | |
1756 if (*control_ != denom_is_m1) { | |
1757 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, | |
1758 *control_); | |
1759 } else { | |
1760 *control_ = before; | |
1761 } | |
1762 return graph()->NewNode(m->Int32Div(), left, right, *control_); | |
1763 } | |
1764 | |
1765 Node* WasmGraphBuilder::BuildI32RemS(Node* left, Node* right) { | |
1766 MachineOperatorBuilder* m = jsgraph()->machine(); | |
1767 if (module_ && module_->asm_js()) { | |
1768 // asm.js semantics return 0 on divide or mod by zero. | |
1769 if (m->Int32DivIsSafe()) { | |
1770 // The hardware instruction does the right thing (e.g. arm). | |
1771 return graph()->NewNode(m->Int32Mod(), left, right, graph()->start()); | |
1772 } | |
1773 | |
1774 // Explicit check for x % 0. | |
1775 Diamond z( | |
1776 graph(), jsgraph()->common(), | |
1777 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | |
1778 BranchHint::kFalse); | |
1779 | |
1780 // Explicit check for x % -1. | |
1781 Diamond d( | |
1782 graph(), jsgraph()->common(), | |
1783 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | |
1784 BranchHint::kFalse); | |
1785 d.Chain(z.if_false); | |
1786 | |
1787 Node* rem = | |
1788 d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | |
1789 graph()->NewNode(m->Int32Mod(), left, right, d.if_false)); | |
1790 | |
1791 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | |
1792 rem); | |
1793 } | |
1794 | |
1795 trap_->ZeroCheck32(kTrapRemByZero, right); | |
1796 | |
1797 Diamond d( | |
1798 graph(), jsgraph()->common(), | |
1799 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), | |
1800 BranchHint::kFalse); | |
1801 d.Chain(*control_); | |
1802 | |
1803 Node* rem = d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | |
ahaas
2016/03/30 11:00:38
Is it necessary to introduce "rem" here?
titzer
2016/03/30 11:15:32
Done.
| |
1804 graph()->NewNode(m->Int32Mod(), left, right, d.if_false)); | |
1805 return rem; | |
1806 } | |
1807 | |
1808 Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right) { | |
1809 MachineOperatorBuilder* m = jsgraph()->machine(); | |
1810 if (module_ && module_->asm_js()) { | |
1811 // asm.js semantics return 0 on divide or mod by zero. | |
1812 if (m->Uint32DivIsSafe()) { | |
1813 // The hardware instruction does the right thing (e.g. arm). | |
1814 return graph()->NewNode(m->Uint32Mod(), left, right, graph()->start()); | |
ahaas
2016/03/30 11:00:37
m->Uint32Div()?
titzer
2016/03/30 11:15:32
Done.
| |
1815 } | |
1816 | |
1817 // Explicit check for x % 0. | |
1818 Diamond z( | |
1819 graph(), jsgraph()->common(), | |
1820 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | |
1821 BranchHint::kFalse); | |
1822 | |
ahaas
2016/03/30 11:00:37
z.Chain(*control_)?
titzer
2016/03/30 11:15:32
It's not necessary to chain the diamond here, beca
| |
1823 Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, right, | |
1824 z.if_false); | |
1825 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | |
1826 rem); | |
1827 } | |
1828 return graph()->NewNode(m->Uint32Div(), left, right, | |
1829 trap_->ZeroCheck32(kTrapDivByZero, right)); | |
1830 } | |
1831 | |
1832 Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right) { | |
1833 MachineOperatorBuilder* m = jsgraph()->machine(); | |
1834 if (module_ && module_->asm_js()) { | |
1835 // asm.js semantics return 0 on divide or mod by zero. | |
1836 if (m->Uint32DivIsSafe()) { | |
1837 // The hardware instruction does the right thing (e.g. arm). | |
1838 return graph()->NewNode(m->Uint32Mod(), left, right, graph()->start()); | |
1839 } | |
1840 | |
1841 // Explicit check for x % 0. | |
1842 Diamond z( | |
1843 graph(), jsgraph()->common(), | |
1844 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), | |
1845 BranchHint::kFalse); | |
1846 | |
ahaas
2016/03/30 11:00:38
z.Chain(*control_)?
titzer
2016/03/30 11:15:32
Same as above.
| |
1847 Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right, | |
1848 z.if_false); | |
1849 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), | |
1850 rem); | |
1851 } | |
1852 | |
1853 return graph()->NewNode(m->Uint32Mod(), left, right, | |
1854 trap_->ZeroCheck32(kTrapRemByZero, right)); | |
1855 } | |
1856 | |
1746 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { | 1857 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { |
1747 if (jsgraph()->machine()->Is32()) { | 1858 if (jsgraph()->machine()->Is32()) { |
1748 return BuildDiv64Call( | 1859 return BuildDiv64Call( |
1749 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), | 1860 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), |
1750 MachineType::Int64(), kTrapDivByZero); | 1861 MachineType::Int64(), kTrapDivByZero); |
1751 } | 1862 } |
1752 trap_->ZeroCheck64(kTrapDivByZero, right); | 1863 trap_->ZeroCheck64(kTrapDivByZero, right); |
1753 Node* before = *control_; | 1864 Node* before = *control_; |
1754 Node* denom_is_m1; | 1865 Node* denom_is_m1; |
1755 Node* denom_is_not_m1; | 1866 Node* denom_is_not_m1; |
(...skipping 910 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2666 static_cast<int>(function.code_end_offset - function.code_start_offset), | 2777 static_cast<int>(function.code_end_offset - function.code_start_offset), |
2667 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); | 2778 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); |
2668 } | 2779 } |
2669 return code; | 2780 return code; |
2670 } | 2781 } |
2671 | 2782 |
2672 | 2783 |
2673 } // namespace compiler | 2784 } // namespace compiler |
2674 } // namespace internal | 2785 } // namespace internal |
2675 } // namespace v8 | 2786 } // namespace v8 |
OLD | NEW |