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 // Explicit check for x % 0. |
| 1770 Diamond z( |
| 1771 graph(), jsgraph()->common(), |
| 1772 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
| 1773 BranchHint::kFalse); |
| 1774 |
| 1775 // Explicit check for x % -1. |
| 1776 Diamond d( |
| 1777 graph(), jsgraph()->common(), |
| 1778 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
| 1779 BranchHint::kFalse); |
| 1780 d.Chain(z.if_false); |
| 1781 |
| 1782 return z.Phi( |
| 1783 MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
| 1784 d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
| 1785 graph()->NewNode(m->Int32Mod(), left, right, d.if_false))); |
| 1786 } |
| 1787 |
| 1788 trap_->ZeroCheck32(kTrapRemByZero, right); |
| 1789 |
| 1790 Diamond d( |
| 1791 graph(), jsgraph()->common(), |
| 1792 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(-1)), |
| 1793 BranchHint::kFalse); |
| 1794 d.Chain(*control_); |
| 1795 |
| 1796 return d.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
| 1797 graph()->NewNode(m->Int32Mod(), left, right, d.if_false)); |
| 1798 } |
| 1799 |
| 1800 Node* WasmGraphBuilder::BuildI32DivU(Node* left, Node* right) { |
| 1801 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1802 if (module_ && module_->asm_js()) { |
| 1803 // asm.js semantics return 0 on divide or mod by zero. |
| 1804 if (m->Uint32DivIsSafe()) { |
| 1805 // The hardware instruction does the right thing (e.g. arm). |
| 1806 return graph()->NewNode(m->Uint32Div(), left, right, graph()->start()); |
| 1807 } |
| 1808 |
| 1809 // Explicit check for x % 0. |
| 1810 Diamond z( |
| 1811 graph(), jsgraph()->common(), |
| 1812 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
| 1813 BranchHint::kFalse); |
| 1814 |
| 1815 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
| 1816 graph()->NewNode(jsgraph()->machine()->Uint32Div(), left, |
| 1817 right, z.if_false)); |
| 1818 } |
| 1819 return graph()->NewNode(m->Uint32Div(), left, right, |
| 1820 trap_->ZeroCheck32(kTrapDivByZero, right)); |
| 1821 } |
| 1822 |
| 1823 Node* WasmGraphBuilder::BuildI32RemU(Node* left, Node* right) { |
| 1824 MachineOperatorBuilder* m = jsgraph()->machine(); |
| 1825 if (module_ && module_->asm_js()) { |
| 1826 // asm.js semantics return 0 on divide or mod by zero. |
| 1827 // Explicit check for x % 0. |
| 1828 Diamond z( |
| 1829 graph(), jsgraph()->common(), |
| 1830 graph()->NewNode(m->Word32Equal(), right, jsgraph()->Int32Constant(0)), |
| 1831 BranchHint::kFalse); |
| 1832 |
| 1833 Node* rem = graph()->NewNode(jsgraph()->machine()->Uint32Mod(), left, right, |
| 1834 z.if_false); |
| 1835 return z.Phi(MachineRepresentation::kWord32, jsgraph()->Int32Constant(0), |
| 1836 rem); |
| 1837 } |
| 1838 |
| 1839 return graph()->NewNode(m->Uint32Mod(), left, right, |
| 1840 trap_->ZeroCheck32(kTrapRemByZero, right)); |
| 1841 } |
| 1842 |
1746 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { | 1843 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { |
1747 if (jsgraph()->machine()->Is32()) { | 1844 if (jsgraph()->machine()->Is32()) { |
1748 return BuildDiv64Call( | 1845 return BuildDiv64Call( |
1749 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), | 1846 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), |
1750 MachineType::Int64(), kTrapDivByZero); | 1847 MachineType::Int64(), kTrapDivByZero); |
1751 } | 1848 } |
1752 trap_->ZeroCheck64(kTrapDivByZero, right); | 1849 trap_->ZeroCheck64(kTrapDivByZero, right); |
1753 Node* before = *control_; | 1850 Node* before = *control_; |
1754 Node* denom_is_m1; | 1851 Node* denom_is_m1; |
1755 Node* denom_is_not_m1; | 1852 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), | 2763 static_cast<int>(function.code_end_offset - function.code_start_offset), |
2667 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); | 2764 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); |
2668 } | 2765 } |
2669 return code; | 2766 return code; |
2670 } | 2767 } |
2671 | 2768 |
2672 | 2769 |
2673 } // namespace compiler | 2770 } // namespace compiler |
2674 } // namespace internal | 2771 } // namespace internal |
2675 } // namespace v8 | 2772 } // namespace v8 |
OLD | NEW |