Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(406)

Side by Side Diff: src/compiler/wasm-compiler.cc

Issue 1839333002: [wasm] Fix asm.js semantics for divide by zero in WASM translation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Small code simplifications. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/wasm/wasm-opcodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « src/compiler/wasm-compiler.h ('k') | src/wasm/wasm-opcodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698