Chromium Code Reviews| 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 |