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 |