Chromium Code Reviews| 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 |