| 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 482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 493 break; | 493 break; |
| 494 // todo(ahaas): I added a list of missing instructions here to make merging | 494 // todo(ahaas): I added a list of missing instructions here to make merging |
| 495 // easier when I do them one by one. | 495 // easier when I do them one by one. |
| 496 // kExprI64Add: | 496 // kExprI64Add: |
| 497 case wasm::kExprI64Add: | 497 case wasm::kExprI64Add: |
| 498 op = m->Int64Add(); | 498 op = m->Int64Add(); |
| 499 break; | 499 break; |
| 500 // kExprI64Sub: | 500 // kExprI64Sub: |
| 501 // kExprI64Mul: | 501 // kExprI64Mul: |
| 502 // kExprI64DivS: | 502 // kExprI64DivS: |
| 503 case wasm::kExprI64DivS: |
| 504 return BuildI64DivS(left, right); |
| 503 // kExprI64DivU: | 505 // kExprI64DivU: |
| 506 case wasm::kExprI64DivU: |
| 507 return BuildI64DivU(left, right); |
| 504 // kExprI64RemS: | 508 // kExprI64RemS: |
| 509 case wasm::kExprI64RemS: |
| 510 return BuildI64RemS(left, right); |
| 505 // kExprI64RemU: | 511 // kExprI64RemU: |
| 512 case wasm::kExprI64RemU: |
| 513 return BuildI64RemU(left, right); |
| 506 case wasm::kExprI64Ior: | 514 case wasm::kExprI64Ior: |
| 507 op = m->Word64Or(); | 515 op = m->Word64Or(); |
| 508 break; | 516 break; |
| 509 // kExprI64Xor: | 517 // kExprI64Xor: |
| 510 case wasm::kExprI64Xor: | 518 case wasm::kExprI64Xor: |
| 511 op = m->Word64Xor(); | 519 op = m->Word64Xor(); |
| 512 break; | 520 break; |
| 513 // kExprI64Shl: | 521 // kExprI64Shl: |
| 514 case wasm::kExprI64Shl: | 522 case wasm::kExprI64Shl: |
| 515 op = m->Word64Shl(); | 523 op = m->Word64Shl(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 | 569 |
| 562 #if WASM_64 | 570 #if WASM_64 |
| 563 // Opcodes only supported on 64-bit platforms. | 571 // Opcodes only supported on 64-bit platforms. |
| 564 // TODO(titzer): query the machine operator builder here instead of #ifdef. | 572 // TODO(titzer): query the machine operator builder here instead of #ifdef. |
| 565 case wasm::kExprI64Sub: | 573 case wasm::kExprI64Sub: |
| 566 op = m->Int64Sub(); | 574 op = m->Int64Sub(); |
| 567 break; | 575 break; |
| 568 case wasm::kExprI64Mul: | 576 case wasm::kExprI64Mul: |
| 569 op = m->Int64Mul(); | 577 op = m->Int64Mul(); |
| 570 break; | 578 break; |
| 571 case wasm::kExprI64DivS: { | |
| 572 trap_->ZeroCheck64(kTrapDivByZero, right); | |
| 573 Node* before = *control_; | |
| 574 Node* denom_is_m1; | |
| 575 Node* denom_is_not_m1; | |
| 576 Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, | |
| 577 jsgraph()->Int64Constant(-1)), | |
| 578 &denom_is_m1, &denom_is_not_m1); | |
| 579 *control_ = denom_is_m1; | |
| 580 trap_->TrapIfEq64(kTrapDivUnrepresentable, left, | |
| 581 std::numeric_limits<int64_t>::min()); | |
| 582 if (*control_ != denom_is_m1) { | |
| 583 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), | |
| 584 denom_is_not_m1, *control_); | |
| 585 } else { | |
| 586 *control_ = before; | |
| 587 } | |
| 588 return graph()->NewNode(m->Int64Div(), left, right, *control_); | |
| 589 } | |
| 590 case wasm::kExprI64DivU: | |
| 591 op = m->Uint64Div(); | |
| 592 return graph()->NewNode(op, left, right, | |
| 593 trap_->ZeroCheck64(kTrapDivByZero, right)); | |
| 594 case wasm::kExprI64RemS: { | |
| 595 trap_->ZeroCheck64(kTrapRemByZero, right); | |
| 596 Diamond d(jsgraph()->graph(), jsgraph()->common(), | |
| 597 graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, | |
| 598 jsgraph()->Int64Constant(-1))); | |
| 599 | |
| 600 Node* rem = graph()->NewNode(m->Int64Mod(), left, right, d.if_false); | |
| 601 | |
| 602 return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), | |
| 603 rem); | |
| 604 } | |
| 605 case wasm::kExprI64RemU: | |
| 606 op = m->Uint64Mod(); | |
| 607 return graph()->NewNode(op, left, right, | |
| 608 trap_->ZeroCheck64(kTrapRemByZero, right)); | |
| 609 case wasm::kExprI64Ror: | 579 case wasm::kExprI64Ror: |
| 610 op = m->Word64Ror(); | 580 op = m->Word64Ror(); |
| 611 break; | 581 break; |
| 612 case wasm::kExprI64Rol: | 582 case wasm::kExprI64Rol: |
| 613 return BuildI64Rol(left, right); | 583 return BuildI64Rol(left, right); |
| 614 #endif | 584 #endif |
| 615 | 585 |
| 616 case wasm::kExprF32CopySign: | 586 case wasm::kExprF32CopySign: |
| 617 return BuildF32CopySign(left, right); | 587 return BuildF32CopySign(left, right); |
| 618 case wasm::kExprF64CopySign: | 588 case wasm::kExprF64CopySign: |
| (...skipping 1148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1767 trap_->ZeroCheck32(kTrapFloatUnrepresentable, | 1737 trap_->ZeroCheck32(kTrapFloatUnrepresentable, |
| 1768 BuildCCall(sig_builder.Build(), args)); | 1738 BuildCCall(sig_builder.Build(), args)); |
| 1769 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1739 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
| 1770 Node* load = | 1740 Node* load = |
| 1771 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), | 1741 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), |
| 1772 *effect_, *control_); | 1742 *effect_, *control_); |
| 1773 *effect_ = load; | 1743 *effect_ = load; |
| 1774 return load; | 1744 return load; |
| 1775 } | 1745 } |
| 1776 | 1746 |
| 1747 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { |
| 1748 if (jsgraph()->machine()->Is32()) { |
| 1749 return BuildDiv64Call( |
| 1750 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), |
| 1751 MachineType::Int64(), kTrapDivByZero); |
| 1752 } |
| 1753 trap_->ZeroCheck64(kTrapDivByZero, right); |
| 1754 Node* before = *control_; |
| 1755 Node* denom_is_m1; |
| 1756 Node* denom_is_not_m1; |
| 1757 Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
| 1758 jsgraph()->Int64Constant(-1)), |
| 1759 &denom_is_m1, &denom_is_not_m1); |
| 1760 *control_ = denom_is_m1; |
| 1761 trap_->TrapIfEq64(kTrapDivUnrepresentable, left, |
| 1762 std::numeric_limits<int64_t>::min()); |
| 1763 if (*control_ != denom_is_m1) { |
| 1764 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), denom_is_not_m1, |
| 1765 *control_); |
| 1766 } else { |
| 1767 *control_ = before; |
| 1768 } |
| 1769 return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right, |
| 1770 *control_); |
| 1771 } |
| 1772 |
| 1773 Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right) { |
| 1774 if (jsgraph()->machine()->Is32()) { |
| 1775 return BuildDiv64Call( |
| 1776 left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()), |
| 1777 MachineType::Int64(), kTrapRemByZero); |
| 1778 } |
| 1779 trap_->ZeroCheck64(kTrapRemByZero, right); |
| 1780 Diamond d(jsgraph()->graph(), jsgraph()->common(), |
| 1781 graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, |
| 1782 jsgraph()->Int64Constant(-1))); |
| 1783 |
| 1784 Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right, |
| 1785 d.if_false); |
| 1786 |
| 1787 return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), |
| 1788 rem); |
| 1789 } |
| 1790 |
| 1791 Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right) { |
| 1792 if (jsgraph()->machine()->Is32()) { |
| 1793 return BuildDiv64Call( |
| 1794 left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()), |
| 1795 MachineType::Int64(), kTrapDivByZero); |
| 1796 } |
| 1797 return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right, |
| 1798 trap_->ZeroCheck64(kTrapDivByZero, right)); |
| 1799 } |
| 1800 Node* WasmGraphBuilder::BuildI64RemU(Node* left, Node* right) { |
| 1801 if (jsgraph()->machine()->Is32()) { |
| 1802 return BuildDiv64Call( |
| 1803 left, right, ExternalReference::wasm_uint64_mod(jsgraph()->isolate()), |
| 1804 MachineType::Int64(), kTrapRemByZero); |
| 1805 } |
| 1806 return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right, |
| 1807 trap_->ZeroCheck64(kTrapRemByZero, right)); |
| 1808 } |
| 1809 |
| 1810 Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right, |
| 1811 ExternalReference ref, |
| 1812 MachineType result_type, int trap_zero) { |
| 1813 Node* stack_slot_dst = graph()->NewNode( |
| 1814 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); |
| 1815 Node* stack_slot_src = graph()->NewNode( |
| 1816 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); |
| 1817 |
| 1818 const Operator* store_op = jsgraph()->machine()->Store( |
| 1819 StoreRepresentation(MachineRepresentation::kWord64, kNoWriteBarrier)); |
| 1820 *effect_ = |
| 1821 graph()->NewNode(store_op, stack_slot_dst, jsgraph()->Int32Constant(0), |
| 1822 left, *effect_, *control_); |
| 1823 *effect_ = |
| 1824 graph()->NewNode(store_op, stack_slot_src, jsgraph()->Int32Constant(0), |
| 1825 right, *effect_, *control_); |
| 1826 |
| 1827 MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); |
| 1828 sig_builder.AddReturn(MachineType::Int32()); |
| 1829 sig_builder.AddParam(MachineType::Pointer()); |
| 1830 sig_builder.AddParam(MachineType::Pointer()); |
| 1831 |
| 1832 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); |
| 1833 Node* args[] = {function, stack_slot_dst, stack_slot_src}; |
| 1834 |
| 1835 Node* call = BuildCCall(sig_builder.Build(), args); |
| 1836 |
| 1837 // TODO(wasm): This can get simpler if we have a specialized runtime call to |
| 1838 // throw WASM exceptions by trap code instead of by string. |
| 1839 trap_->ZeroCheck32(static_cast<TrapReason>(trap_zero), call); |
| 1840 trap_->TrapIfEq32(kTrapDivUnrepresentable, call, -1); |
| 1841 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
| 1842 Node* load = |
| 1843 graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0), |
| 1844 *effect_, *control_); |
| 1845 *effect_ = load; |
| 1846 return load; |
| 1847 } |
| 1848 |
| 1777 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { | 1849 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { |
| 1778 const size_t params = sig->parameter_count(); | 1850 const size_t params = sig->parameter_count(); |
| 1779 const size_t extra = 2; // effect and control inputs. | 1851 const size_t extra = 2; // effect and control inputs. |
| 1780 const size_t count = 1 + params + extra; | 1852 const size_t count = 1 + params + extra; |
| 1781 | 1853 |
| 1782 // Reallocate the buffer to make space for extra inputs. | 1854 // Reallocate the buffer to make space for extra inputs. |
| 1783 args = Realloc(args, count); | 1855 args = Realloc(args, count); |
| 1784 | 1856 |
| 1785 // Add effect and control inputs. | 1857 // Add effect and control inputs. |
| 1786 args[params + 1] = *effect_; | 1858 args[params + 1] = *effect_; |
| (...skipping 788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2575 static_cast<int>(function.code_end_offset - function.code_start_offset), | 2647 static_cast<int>(function.code_end_offset - function.code_start_offset), |
| 2576 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); | 2648 decode_ms, static_cast<int>(graph.NodeCount()), compile_ms); |
| 2577 } | 2649 } |
| 2578 return code; | 2650 return code; |
| 2579 } | 2651 } |
| 2580 | 2652 |
| 2581 | 2653 |
| 2582 } // namespace compiler | 2654 } // namespace compiler |
| 2583 } // namespace internal | 2655 } // namespace internal |
| 2584 } // namespace v8 | 2656 } // namespace v8 |
| OLD | NEW |