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

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

Issue 2438603003: [wasm] Track in the interpreter if a NaN could have been produced. (Closed)
Patch Set: Created 4 years, 2 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
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/wasm/wasm-interpreter.h" 5 #include "src/wasm/wasm-interpreter.h"
6 6
7 #include "src/utils.h" 7 #include "src/utils.h"
8 #include "src/wasm/ast-decoder.h" 8 #include "src/wasm/ast-decoder.h"
9 #include "src/wasm/decoder.h" 9 #include "src/wasm/decoder.h"
10 #include "src/wasm/wasm-external-refs.h" 10 #include "src/wasm/wasm-external-refs.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 V(I64LtU, uint64_t, <) \ 56 V(I64LtU, uint64_t, <) \
57 V(I64LeU, uint64_t, <=) \ 57 V(I64LeU, uint64_t, <=) \
58 V(I64GtU, uint64_t, >) \ 58 V(I64GtU, uint64_t, >) \
59 V(I64GeU, uint64_t, >=) \ 59 V(I64GeU, uint64_t, >=) \
60 V(I64LtS, int64_t, <) \ 60 V(I64LtS, int64_t, <) \
61 V(I64LeS, int64_t, <=) \ 61 V(I64LeS, int64_t, <=) \
62 V(I64GtS, int64_t, >) \ 62 V(I64GtS, int64_t, >) \
63 V(I64GeS, int64_t, >=) \ 63 V(I64GeS, int64_t, >=) \
64 V(F32Add, float, +) \ 64 V(F32Add, float, +) \
65 V(F32Mul, float, *) \ 65 V(F32Mul, float, *) \
66 V(F32Div, float, /) \
67 V(F32Eq, float, ==) \ 66 V(F32Eq, float, ==) \
68 V(F32Ne, float, !=) \ 67 V(F32Ne, float, !=) \
69 V(F32Lt, float, <) \ 68 V(F32Lt, float, <) \
70 V(F32Le, float, <=) \ 69 V(F32Le, float, <=) \
71 V(F32Gt, float, >) \ 70 V(F32Gt, float, >) \
72 V(F32Ge, float, >=) \ 71 V(F32Ge, float, >=) \
73 V(F64Add, double, +) \ 72 V(F64Add, double, +) \
74 V(F64Mul, double, *) \ 73 V(F64Mul, double, *) \
75 V(F64Div, double, /) \
76 V(F64Eq, double, ==) \ 74 V(F64Eq, double, ==) \
77 V(F64Ne, double, !=) \ 75 V(F64Ne, double, !=) \
78 V(F64Lt, double, <) \ 76 V(F64Lt, double, <) \
79 V(F64Le, double, <=) \ 77 V(F64Le, double, <=) \
80 V(F64Gt, double, >) \ 78 V(F64Gt, double, >) \
81 V(F64Ge, double, >=) 79 V(F64Ge, double, >=)
82 80
81 #define FOREACH_SIMPLE_BINOP_NAN(V) \
82 V(F32Div, float, /) \
83 V(F64Div, double, /)
84
83 #define FOREACH_OTHER_BINOP(V) \ 85 #define FOREACH_OTHER_BINOP(V) \
84 V(I32DivS, int32_t) \ 86 V(I32DivS, int32_t) \
85 V(I32DivU, uint32_t) \ 87 V(I32DivU, uint32_t) \
86 V(I32RemS, int32_t) \ 88 V(I32RemS, int32_t) \
87 V(I32RemU, uint32_t) \ 89 V(I32RemU, uint32_t) \
88 V(I32Shl, uint32_t) \ 90 V(I32Shl, uint32_t) \
89 V(I32ShrU, uint32_t) \ 91 V(I32ShrU, uint32_t) \
90 V(I32ShrS, int32_t) \ 92 V(I32ShrS, int32_t) \
91 V(I64DivS, int64_t) \ 93 V(I64DivS, int64_t) \
92 V(I64DivU, uint64_t) \ 94 V(I64DivU, uint64_t) \
(...skipping 27 matching lines...) Expand all
120 V(I64Clz, uint64_t) \ 122 V(I64Clz, uint64_t) \
121 V(I64Ctz, uint64_t) \ 123 V(I64Ctz, uint64_t) \
122 V(I64Popcnt, uint64_t) \ 124 V(I64Popcnt, uint64_t) \
123 V(I64Eqz, uint64_t) \ 125 V(I64Eqz, uint64_t) \
124 V(F32Abs, float) \ 126 V(F32Abs, float) \
125 V(F32Neg, float) \ 127 V(F32Neg, float) \
126 V(F32Ceil, float) \ 128 V(F32Ceil, float) \
127 V(F32Floor, float) \ 129 V(F32Floor, float) \
128 V(F32Trunc, float) \ 130 V(F32Trunc, float) \
129 V(F32NearestInt, float) \ 131 V(F32NearestInt, float) \
130 V(F32Sqrt, float) \
131 V(F64Abs, double) \ 132 V(F64Abs, double) \
132 V(F64Neg, double) \ 133 V(F64Neg, double) \
133 V(F64Ceil, double) \ 134 V(F64Ceil, double) \
134 V(F64Floor, double) \ 135 V(F64Floor, double) \
135 V(F64Trunc, double) \ 136 V(F64Trunc, double) \
136 V(F64NearestInt, double) \ 137 V(F64NearestInt, double) \
137 V(F64Sqrt, double) \
138 V(I32SConvertF32, float) \ 138 V(I32SConvertF32, float) \
139 V(I32SConvertF64, double) \ 139 V(I32SConvertF64, double) \
140 V(I32UConvertF32, float) \ 140 V(I32UConvertF32, float) \
141 V(I32UConvertF64, double) \ 141 V(I32UConvertF64, double) \
142 V(I32ConvertI64, int64_t) \ 142 V(I32ConvertI64, int64_t) \
143 V(I64SConvertF32, float) \ 143 V(I64SConvertF32, float) \
144 V(I64SConvertF64, double) \ 144 V(I64SConvertF64, double) \
145 V(I64UConvertF32, float) \ 145 V(I64UConvertF32, float) \
146 V(I64UConvertF64, double) \ 146 V(I64UConvertF64, double) \
147 V(I64SConvertI32, int32_t) \ 147 V(I64SConvertI32, int32_t) \
(...skipping 10 matching lines...) Expand all
158 V(F64UConvertI64, uint64_t) \ 158 V(F64UConvertI64, uint64_t) \
159 V(F64ConvertF32, float) \ 159 V(F64ConvertF32, float) \
160 V(F64ReinterpretI64, int64_t) \ 160 V(F64ReinterpretI64, int64_t) \
161 V(I32ReinterpretF32, float) \ 161 V(I32ReinterpretF32, float) \
162 V(I64ReinterpretF64, double) \ 162 V(I64ReinterpretF64, double) \
163 V(I32AsmjsSConvertF32, float) \ 163 V(I32AsmjsSConvertF32, float) \
164 V(I32AsmjsUConvertF32, float) \ 164 V(I32AsmjsUConvertF32, float) \
165 V(I32AsmjsSConvertF64, double) \ 165 V(I32AsmjsSConvertF64, double) \
166 V(I32AsmjsUConvertF64, double) 166 V(I32AsmjsUConvertF64, double)
167 167
168 #define FOREACH_OTHER_UNOP_NAN(V) \
169 V(F32Sqrt, float) \
170 V(F64Sqrt, double)
171
168 static inline int32_t ExecuteI32DivS(int32_t a, int32_t b, TrapReason* trap) { 172 static inline int32_t ExecuteI32DivS(int32_t a, int32_t b, TrapReason* trap) {
169 if (b == 0) { 173 if (b == 0) {
170 *trap = kTrapDivByZero; 174 *trap = kTrapDivByZero;
171 return 0; 175 return 0;
172 } 176 }
173 if (b == -1 && a == std::numeric_limits<int32_t>::min()) { 177 if (b == -1 && a == std::numeric_limits<int32_t>::min()) {
174 *trap = kTrapDivUnrepresentable; 178 *trap = kTrapDivUnrepresentable;
175 return 0; 179 return 0;
176 } 180 }
177 return a / b; 181 return a / b;
(...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after
968 class ThreadImpl : public WasmInterpreter::Thread { 972 class ThreadImpl : public WasmInterpreter::Thread {
969 public: 973 public:
970 ThreadImpl(Zone* zone, CodeMap* codemap, WasmInstance* instance) 974 ThreadImpl(Zone* zone, CodeMap* codemap, WasmInstance* instance)
971 : codemap_(codemap), 975 : codemap_(codemap),
972 instance_(instance), 976 instance_(instance),
973 stack_(zone), 977 stack_(zone),
974 frames_(zone), 978 frames_(zone),
975 blocks_(zone), 979 blocks_(zone),
976 state_(WasmInterpreter::STOPPED), 980 state_(WasmInterpreter::STOPPED),
977 break_pc_(kInvalidPc), 981 break_pc_(kInvalidPc),
978 trap_reason_(kTrapCount) {} 982 trap_reason_(kTrapCount),
983 may_produced_nan_(false) {}
979 984
980 virtual ~ThreadImpl() {} 985 virtual ~ThreadImpl() {}
981 986
982 //========================================================================== 987 //==========================================================================
983 // Implementation of public interface for WasmInterpreter::Thread. 988 // Implementation of public interface for WasmInterpreter::Thread.
984 //========================================================================== 989 //==========================================================================
985 990
986 virtual WasmInterpreter::State state() { return state_; } 991 virtual WasmInterpreter::State state() { return state_; }
987 992
988 virtual void PushFrame(const WasmFunction* function, WasmVal* args) { 993 virtual void PushFrame(const WasmFunction* function, WasmVal* args) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 } 1028 }
1024 1029
1025 virtual void Pause() { UNIMPLEMENTED(); } 1030 virtual void Pause() { UNIMPLEMENTED(); }
1026 1031
1027 virtual void Reset() { 1032 virtual void Reset() {
1028 TRACE("----- RESET -----\n"); 1033 TRACE("----- RESET -----\n");
1029 stack_.clear(); 1034 stack_.clear();
1030 frames_.clear(); 1035 frames_.clear();
1031 state_ = WasmInterpreter::STOPPED; 1036 state_ = WasmInterpreter::STOPPED;
1032 trap_reason_ = kTrapCount; 1037 trap_reason_ = kTrapCount;
1038 may_produced_nan_ = false;
1033 } 1039 }
1034 1040
1035 virtual int GetFrameCount() { return static_cast<int>(frames_.size()); } 1041 virtual int GetFrameCount() { return static_cast<int>(frames_.size()); }
1036 1042
1037 virtual const WasmFrame* GetFrame(int index) { 1043 virtual const WasmFrame* GetFrame(int index) {
1038 UNIMPLEMENTED(); 1044 UNIMPLEMENTED();
1039 return nullptr; 1045 return nullptr;
1040 } 1046 }
1041 1047
1042 virtual WasmFrame* GetMutableFrame(int index) { 1048 virtual WasmFrame* GetMutableFrame(int index) {
1043 UNIMPLEMENTED(); 1049 UNIMPLEMENTED();
1044 return nullptr; 1050 return nullptr;
1045 } 1051 }
1046 1052
1047 virtual WasmVal GetReturnValue(int index) { 1053 virtual WasmVal GetReturnValue(int index) {
1048 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef); 1054 if (state_ == WasmInterpreter::TRAPPED) return WasmVal(0xdeadbeef);
1049 CHECK_EQ(WasmInterpreter::FINISHED, state_); 1055 CHECK_EQ(WasmInterpreter::FINISHED, state_);
1050 CHECK_LT(static_cast<size_t>(index), stack_.size()); 1056 CHECK_LT(static_cast<size_t>(index), stack_.size());
1051 return stack_[index]; 1057 return stack_[index];
1052 } 1058 }
1053 1059
1054 virtual pc_t GetBreakpointPc() { return break_pc_; } 1060 virtual pc_t GetBreakpointPc() { return break_pc_; }
1055 1061
1062 virtual bool MayProducedNaN() { return may_produced_nan_; }
1063
1056 bool Terminated() { 1064 bool Terminated() {
1057 return state_ == WasmInterpreter::TRAPPED || 1065 return state_ == WasmInterpreter::TRAPPED ||
1058 state_ == WasmInterpreter::FINISHED; 1066 state_ == WasmInterpreter::FINISHED;
1059 } 1067 }
1060 1068
1061 private: 1069 private:
1062 // Entries on the stack of functions being evaluated. 1070 // Entries on the stack of functions being evaluated.
1063 struct Frame { 1071 struct Frame {
1064 InterpreterCode* code; 1072 InterpreterCode* code;
1065 pc_t call_pc; 1073 pc_t call_pc;
(...skipping 14 matching lines...) Expand all
1080 }; 1088 };
1081 1089
1082 CodeMap* codemap_; 1090 CodeMap* codemap_;
1083 WasmInstance* instance_; 1091 WasmInstance* instance_;
1084 ZoneVector<WasmVal> stack_; 1092 ZoneVector<WasmVal> stack_;
1085 ZoneVector<Frame> frames_; 1093 ZoneVector<Frame> frames_;
1086 ZoneVector<Block> blocks_; 1094 ZoneVector<Block> blocks_;
1087 WasmInterpreter::State state_; 1095 WasmInterpreter::State state_;
1088 pc_t break_pc_; 1096 pc_t break_pc_;
1089 TrapReason trap_reason_; 1097 TrapReason trap_reason_;
1098 bool may_produced_nan_;
1090 1099
1091 CodeMap* codemap() { return codemap_; } 1100 CodeMap* codemap() { return codemap_; }
1092 WasmInstance* instance() { return instance_; } 1101 WasmInstance* instance() { return instance_; }
1093 const WasmModule* module() { return instance_->module; } 1102 const WasmModule* module() { return instance_->module; }
1094 1103
1095 void DoTrap(TrapReason trap, pc_t pc) { 1104 void DoTrap(TrapReason trap, pc_t pc) {
1096 state_ = WasmInterpreter::TRAPPED; 1105 state_ = WasmInterpreter::TRAPPED;
1097 trap_reason_ = trap; 1106 trap_reason_ = trap;
1098 CommitPc(pc); 1107 CommitPc(pc);
1099 } 1108 }
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
1595 case kExpr##name: { \ 1604 case kExpr##name: { \
1596 WasmVal rval = Pop(); \ 1605 WasmVal rval = Pop(); \
1597 WasmVal lval = Pop(); \ 1606 WasmVal lval = Pop(); \
1598 WasmVal result(lval.to<ctype>() op rval.to<ctype>()); \ 1607 WasmVal result(lval.to<ctype>() op rval.to<ctype>()); \
1599 Push(pc, result); \ 1608 Push(pc, result); \
1600 break; \ 1609 break; \
1601 } 1610 }
1602 FOREACH_SIMPLE_BINOP(EXECUTE_SIMPLE_BINOP) 1611 FOREACH_SIMPLE_BINOP(EXECUTE_SIMPLE_BINOP)
1603 #undef EXECUTE_SIMPLE_BINOP 1612 #undef EXECUTE_SIMPLE_BINOP
1604 1613
1614 #define EXECUTE_SIMPLE_BINOP_NAN(name, ctype, op) \
1615 case kExpr##name: { \
1616 may_produced_nan_ |= true; \
titzer 2016/10/20 10:53:24 Don't we want to set this flag only if the result
ahaas 2016/10/20 13:43:23 Done.
1617 WasmVal rval = Pop(); \
1618 WasmVal lval = Pop(); \
1619 WasmVal result(lval.to<ctype>() op rval.to<ctype>()); \
1620 Push(pc, result); \
1621 break; \
1622 }
1623 FOREACH_SIMPLE_BINOP_NAN(EXECUTE_SIMPLE_BINOP_NAN)
1624 #undef EXECUTE_SIMPLE_BINOP_NAN
1625
1605 #define EXECUTE_OTHER_BINOP(name, ctype) \ 1626 #define EXECUTE_OTHER_BINOP(name, ctype) \
1606 case kExpr##name: { \ 1627 case kExpr##name: { \
1607 TrapReason trap = kTrapCount; \ 1628 TrapReason trap = kTrapCount; \
1608 volatile ctype rval = Pop().to<ctype>(); \ 1629 volatile ctype rval = Pop().to<ctype>(); \
1609 volatile ctype lval = Pop().to<ctype>(); \ 1630 volatile ctype lval = Pop().to<ctype>(); \
1610 WasmVal result(Execute##name(lval, rval, &trap)); \ 1631 WasmVal result(Execute##name(lval, rval, &trap)); \
1611 if (trap != kTrapCount) return DoTrap(trap, pc); \ 1632 if (trap != kTrapCount) return DoTrap(trap, pc); \
1612 Push(pc, result); \ 1633 Push(pc, result); \
1613 break; \ 1634 break; \
1614 } 1635 }
1615 FOREACH_OTHER_BINOP(EXECUTE_OTHER_BINOP) 1636 FOREACH_OTHER_BINOP(EXECUTE_OTHER_BINOP)
1616 #undef EXECUTE_OTHER_BINOP 1637 #undef EXECUTE_OTHER_BINOP
1617 1638
1618 #define EXECUTE_OTHER_UNOP(name, ctype) \ 1639 #define EXECUTE_OTHER_UNOP(name, ctype) \
1619 case kExpr##name: { \ 1640 case kExpr##name: { \
1620 TrapReason trap = kTrapCount; \ 1641 TrapReason trap = kTrapCount; \
1621 volatile ctype val = Pop().to<ctype>(); \ 1642 volatile ctype val = Pop().to<ctype>(); \
1622 WasmVal result(Execute##name(val, &trap)); \ 1643 WasmVal result(Execute##name(val, &trap)); \
1623 if (trap != kTrapCount) return DoTrap(trap, pc); \ 1644 if (trap != kTrapCount) return DoTrap(trap, pc); \
1624 Push(pc, result); \ 1645 Push(pc, result); \
1625 break; \ 1646 break; \
1626 } 1647 }
1627 FOREACH_OTHER_UNOP(EXECUTE_OTHER_UNOP) 1648 FOREACH_OTHER_UNOP(EXECUTE_OTHER_UNOP)
1628 #undef EXECUTE_OTHER_UNOP 1649 #undef EXECUTE_OTHER_UNOP
1629 1650
1651 #define EXECUTE_OTHER_UNOP_NAN(name, ctype) \
1652 case kExpr##name: { \
1653 may_produced_nan_ |= true; \
1654 TrapReason trap = kTrapCount; \
1655 volatile ctype val = Pop().to<ctype>(); \
1656 WasmVal result(Execute##name(val, &trap)); \
1657 if (trap != kTrapCount) return DoTrap(trap, pc); \
1658 Push(pc, result); \
1659 break; \
1660 }
1661 FOREACH_OTHER_UNOP_NAN(EXECUTE_OTHER_UNOP_NAN)
1662 #undef EXECUTE_OTHER_UNOP_NAN
1663
1630 default: 1664 default:
1631 V8_Fatal(__FILE__, __LINE__, "Unknown or unimplemented opcode #%d:%s", 1665 V8_Fatal(__FILE__, __LINE__, "Unknown or unimplemented opcode #%d:%s",
1632 code->start[pc], OpcodeName(code->start[pc])); 1666 code->start[pc], OpcodeName(code->start[pc]));
1633 UNREACHABLE(); 1667 UNREACHABLE();
1634 } 1668 }
1635 1669
1636 pc += len; 1670 pc += len;
1637 } 1671 }
1638 UNREACHABLE(); // above decoding loop should run forever. 1672 UNREACHABLE(); // above decoding loop should run forever.
1639 } 1673 }
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1844 1878
1845 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting( 1879 ControlTransferMap WasmInterpreter::ComputeControlTransfersForTesting(
1846 Zone* zone, const byte* start, const byte* end) { 1880 Zone* zone, const byte* start, const byte* end) {
1847 ControlTransfers targets(zone, nullptr, nullptr, start, end); 1881 ControlTransfers targets(zone, nullptr, nullptr, start, end);
1848 return targets.map_; 1882 return targets.map_;
1849 } 1883 }
1850 1884
1851 } // namespace wasm 1885 } // namespace wasm
1852 } // namespace internal 1886 } // namespace internal
1853 } // namespace v8 1887 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698