OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |