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 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
490 break; | 490 break; |
491 case wasm::kExprI64And: | 491 case wasm::kExprI64And: |
492 op = m->Word64And(); | 492 op = m->Word64And(); |
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 // kExprI64Sub: | 497 // kExprI64Sub: |
498 // kExprI64Mul: | 498 // kExprI64Mul: |
499 // kExprI64DivS: | 499 // kExprI64DivS: |
500 case wasm::kExprI64DivS: | |
501 return BuildI64DivS(left, right); | |
500 // kExprI64DivU: | 502 // kExprI64DivU: |
503 case wasm::kExprI64DivU: | |
504 return BuildI64DivU(left, right); | |
501 // kExprI64RemS: | 505 // kExprI64RemS: |
506 case wasm::kExprI64RemS: | |
507 return BuildI64RemS(left, right); | |
502 // kExprI64RemU: | 508 // kExprI64RemU: |
509 case wasm::kExprI64RemU: | |
510 return BuildI64RemU(left, right); | |
503 case wasm::kExprI64Ior: | 511 case wasm::kExprI64Ior: |
504 op = m->Word64Or(); | 512 op = m->Word64Or(); |
505 break; | 513 break; |
506 // kExprI64Xor: | 514 // kExprI64Xor: |
507 case wasm::kExprI64Xor: | 515 case wasm::kExprI64Xor: |
508 op = m->Word64Xor(); | 516 op = m->Word64Xor(); |
509 break; | 517 break; |
510 // kExprI64Shl: | 518 // kExprI64Shl: |
511 case wasm::kExprI64Shl: | 519 case wasm::kExprI64Shl: |
512 op = m->Word64Shl(); | 520 op = m->Word64Shl(); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
561 // TODO(titzer): query the machine operator builder here instead of #ifdef. | 569 // TODO(titzer): query the machine operator builder here instead of #ifdef. |
562 case wasm::kExprI64Add: | 570 case wasm::kExprI64Add: |
563 op = m->Int64Add(); | 571 op = m->Int64Add(); |
564 break; | 572 break; |
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 1145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1764 trap_->ZeroCheck32(kTrapFloatUnrepresentable, | 1734 trap_->ZeroCheck32(kTrapFloatUnrepresentable, |
1765 BuildCCall(sig_builder.Build(), args)); | 1735 BuildCCall(sig_builder.Build(), args)); |
1766 const Operator* load_op = jsgraph()->machine()->Load(result_type); | 1736 const Operator* load_op = jsgraph()->machine()->Load(result_type); |
1767 Node* load = | 1737 Node* load = |
1768 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), | 1738 graph()->NewNode(load_op, stack_slot_result, jsgraph()->Int32Constant(0), |
1769 *effect_, *control_); | 1739 *effect_, *control_); |
1770 *effect_ = load; | 1740 *effect_ = load; |
1771 return load; | 1741 return load; |
1772 } | 1742 } |
1773 | 1743 |
1744 Node* WasmGraphBuilder::BuildI64DivS(Node* left, Node* right) { | |
1745 if (jsgraph()->machine()->Is32()) { | |
1746 return BuildDiv64Call( | |
1747 left, right, ExternalReference::wasm_int64_div(jsgraph()->isolate()), | |
1748 MachineType::Int64(), kTrapDivByZero); | |
1749 } else { | |
1750 trap_->ZeroCheck64(kTrapDivByZero, right); | |
titzer
2016/03/14 11:03:22
Style nit: leave the else clause unnested.
ahaas
2016/03/14 12:38:12
Done.
| |
1751 Node* before = *control_; | |
1752 Node* denom_is_m1; | |
1753 Node* denom_is_not_m1; | |
1754 Branch(graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, | |
1755 jsgraph()->Int64Constant(-1)), | |
1756 &denom_is_m1, &denom_is_not_m1); | |
1757 *control_ = denom_is_m1; | |
1758 trap_->TrapIfEq64(kTrapDivUnrepresentable, left, | |
1759 std::numeric_limits<int64_t>::min()); | |
1760 if (*control_ != denom_is_m1) { | |
1761 *control_ = graph()->NewNode(jsgraph()->common()->Merge(2), | |
1762 denom_is_not_m1, *control_); | |
1763 } else { | |
1764 *control_ = before; | |
1765 } | |
1766 return graph()->NewNode(jsgraph()->machine()->Int64Div(), left, right, | |
1767 *control_); | |
1768 } | |
1769 } | |
1770 | |
1771 Node* WasmGraphBuilder::BuildI64RemS(Node* left, Node* right) { | |
1772 if (jsgraph()->machine()->Is32()) { | |
1773 return BuildDiv64Call( | |
1774 left, right, ExternalReference::wasm_int64_mod(jsgraph()->isolate()), | |
1775 MachineType::Int64(), kTrapRemByZero); | |
1776 } else { | |
1777 trap_->ZeroCheck64(kTrapRemByZero, right); | |
1778 Diamond d(jsgraph()->graph(), jsgraph()->common(), | |
1779 graph()->NewNode(jsgraph()->machine()->Word64Equal(), right, | |
1780 jsgraph()->Int64Constant(-1))); | |
1781 | |
1782 Node* rem = graph()->NewNode(jsgraph()->machine()->Int64Mod(), left, right, | |
1783 d.if_false); | |
1784 | |
1785 return d.Phi(MachineRepresentation::kWord64, jsgraph()->Int64Constant(0), | |
1786 rem); | |
1787 } | |
1788 } | |
1789 | |
1790 Node* WasmGraphBuilder::BuildI64DivU(Node* left, Node* right) { | |
1791 if (jsgraph()->machine()->Is32()) { | |
1792 return BuildDiv64Call( | |
1793 left, right, ExternalReference::wasm_uint64_div(jsgraph()->isolate()), | |
1794 MachineType::Int64(), kTrapDivByZero); | |
1795 } else { | |
1796 return graph()->NewNode(jsgraph()->machine()->Uint64Div(), left, right, | |
1797 trap_->ZeroCheck64(kTrapDivByZero, right)); | |
1798 } | |
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 } else { | |
1806 return graph()->NewNode(jsgraph()->machine()->Uint64Mod(), left, right, | |
1807 trap_->ZeroCheck64(kTrapRemByZero, right)); | |
1808 } | |
1809 } | |
1810 | |
1811 Node* WasmGraphBuilder::BuildDiv64Call(Node* left, Node* right, | |
1812 ExternalReference ref, | |
1813 MachineType result_type, int trap_zero) { | |
1814 Node* stack_slot_dst = graph()->NewNode( | |
1815 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); | |
1816 Node* stack_slot_src = graph()->NewNode( | |
1817 jsgraph()->machine()->StackSlot(MachineRepresentation::kWord64)); | |
1818 | |
1819 const Operator* store_op = jsgraph()->machine()->Store( | |
1820 StoreRepresentation(MachineRepresentation::kWord64, kNoWriteBarrier)); | |
1821 *effect_ = | |
1822 graph()->NewNode(store_op, stack_slot_dst, jsgraph()->Int32Constant(0), | |
1823 left, *effect_, *control_); | |
1824 *effect_ = | |
1825 graph()->NewNode(store_op, stack_slot_src, jsgraph()->Int32Constant(0), | |
1826 right, *effect_, *control_); | |
1827 | |
1828 MachineSignature::Builder sig_builder(jsgraph()->zone(), 1, 2); | |
1829 sig_builder.AddReturn(MachineType::Int32()); | |
1830 sig_builder.AddParam(MachineType::Pointer()); | |
1831 sig_builder.AddParam(MachineType::Pointer()); | |
1832 | |
1833 Node* function = graph()->NewNode(jsgraph()->common()->ExternalConstant(ref)); | |
1834 Node* args[] = {function, stack_slot_dst, stack_slot_src}; | |
1835 | |
1836 Node* call = BuildCCall(sig_builder.Build(), args); | |
1837 trap_->ZeroCheck32(static_cast<TrapReason>(trap_zero), call); | |
titzer
2016/03/14 11:03:22
Can you leave a TODO here? This can get simpler if
ahaas
2016/03/14 12:38:12
Done.
| |
1838 trap_->TrapIfEq32(kTrapDivUnrepresentable, call, -1); | |
1839 const Operator* load_op = jsgraph()->machine()->Load(result_type); | |
1840 Node* load = | |
1841 graph()->NewNode(load_op, stack_slot_dst, jsgraph()->Int32Constant(0), | |
1842 *effect_, *control_); | |
1843 *effect_ = load; | |
1844 return load; | |
1845 } | |
1846 | |
1774 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { | 1847 Node* WasmGraphBuilder::BuildCCall(MachineSignature* sig, Node** args) { |
1775 const size_t params = sig->parameter_count(); | 1848 const size_t params = sig->parameter_count(); |
1776 const size_t extra = 2; // effect and control inputs. | 1849 const size_t extra = 2; // effect and control inputs. |
1777 const size_t count = 1 + params + extra; | 1850 const size_t count = 1 + params + extra; |
1778 | 1851 |
1779 // Reallocate the buffer to make space for extra inputs. | 1852 // Reallocate the buffer to make space for extra inputs. |
1780 args = Realloc(args, count); | 1853 args = Realloc(args, count); |
1781 | 1854 |
1782 // Add effect and control inputs. | 1855 // Add effect and control inputs. |
1783 args[params + 1] = *effect_; | 1856 args[params + 1] = *effect_; |
(...skipping 787 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2571 static_cast<int>(function.code_end_offset - function.code_start_offset), | 2644 static_cast<int>(function.code_end_offset - function.code_start_offset), |
2572 decode_ms, compile_ms); | 2645 decode_ms, compile_ms); |
2573 } | 2646 } |
2574 return code; | 2647 return code; |
2575 } | 2648 } |
2576 | 2649 |
2577 | 2650 |
2578 } // namespace compiler | 2651 } // namespace compiler |
2579 } // namespace internal | 2652 } // namespace internal |
2580 } // namespace v8 | 2653 } // namespace v8 |
OLD | NEW |