| 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 <type_traits> |
| 6 |
| 5 #include "src/wasm/wasm-interpreter.h" | 7 #include "src/wasm/wasm-interpreter.h" |
| 6 | 8 |
| 7 #include "src/utils.h" | 9 #include "src/utils.h" |
| 8 #include "src/wasm/decoder.h" | 10 #include "src/wasm/decoder.h" |
| 9 #include "src/wasm/function-body-decoder.h" | 11 #include "src/wasm/function-body-decoder.h" |
| 10 #include "src/wasm/wasm-external-refs.h" | 12 #include "src/wasm/wasm-external-refs.h" |
| 11 #include "src/wasm/wasm-limits.h" | 13 #include "src/wasm/wasm-limits.h" |
| 12 #include "src/wasm/wasm-module.h" | 14 #include "src/wasm/wasm-module.h" |
| 13 | 15 |
| 14 #include "src/zone/accounting-allocator.h" | 16 #include "src/zone/accounting-allocator.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 V(F32Le, float, <=) \ | 72 V(F32Le, float, <=) \ |
| 71 V(F32Gt, float, >) \ | 73 V(F32Gt, float, >) \ |
| 72 V(F32Ge, float, >=) \ | 74 V(F32Ge, float, >=) \ |
| 73 V(F64Add, double, +) \ | 75 V(F64Add, double, +) \ |
| 74 V(F64Sub, double, -) \ | 76 V(F64Sub, double, -) \ |
| 75 V(F64Eq, double, ==) \ | 77 V(F64Eq, double, ==) \ |
| 76 V(F64Ne, double, !=) \ | 78 V(F64Ne, double, !=) \ |
| 77 V(F64Lt, double, <) \ | 79 V(F64Lt, double, <) \ |
| 78 V(F64Le, double, <=) \ | 80 V(F64Le, double, <=) \ |
| 79 V(F64Gt, double, >) \ | 81 V(F64Gt, double, >) \ |
| 80 V(F64Ge, double, >=) | 82 V(F64Ge, double, >=) \ |
| 81 | 83 V(F32Mul, float, *) \ |
| 82 #define FOREACH_SIMPLE_BINOP_NAN(V) \ | 84 V(F64Mul, double, *) \ |
| 83 V(F32Mul, float, *) \ | 85 V(F32Div, float, /) \ |
| 84 V(F64Mul, double, *) \ | |
| 85 V(F32Div, float, /) \ | |
| 86 V(F64Div, double, /) | 86 V(F64Div, double, /) |
| 87 | 87 |
| 88 #define FOREACH_OTHER_BINOP(V) \ | 88 #define FOREACH_OTHER_BINOP(V) \ |
| 89 V(I32DivS, int32_t) \ | 89 V(I32DivS, int32_t) \ |
| 90 V(I32DivU, uint32_t) \ | 90 V(I32DivU, uint32_t) \ |
| 91 V(I32RemS, int32_t) \ | 91 V(I32RemS, int32_t) \ |
| 92 V(I32RemU, uint32_t) \ | 92 V(I32RemU, uint32_t) \ |
| 93 V(I32Shl, uint32_t) \ | 93 V(I32Shl, uint32_t) \ |
| 94 V(I32ShrU, uint32_t) \ | 94 V(I32ShrU, uint32_t) \ |
| 95 V(I32ShrS, int32_t) \ | 95 V(I32ShrS, int32_t) \ |
| 96 V(I64DivS, int64_t) \ | 96 V(I64DivS, int64_t) \ |
| 97 V(I64DivU, uint64_t) \ | 97 V(I64DivU, uint64_t) \ |
| 98 V(I64RemS, int64_t) \ | 98 V(I64RemS, int64_t) \ |
| 99 V(I64RemU, uint64_t) \ | 99 V(I64RemU, uint64_t) \ |
| 100 V(I64Shl, uint64_t) \ | 100 V(I64Shl, uint64_t) \ |
| 101 V(I64ShrU, uint64_t) \ | 101 V(I64ShrU, uint64_t) \ |
| 102 V(I64ShrS, int64_t) \ | 102 V(I64ShrS, int64_t) \ |
| 103 V(I32Ror, int32_t) \ | 103 V(I32Ror, int32_t) \ |
| 104 V(I32Rol, int32_t) \ | 104 V(I32Rol, int32_t) \ |
| 105 V(I64Ror, int64_t) \ | 105 V(I64Ror, int64_t) \ |
| 106 V(I64Rol, int64_t) \ | 106 V(I64Rol, int64_t) \ |
| 107 V(F32Min, float) \ | 107 V(F32Min, float) \ |
| 108 V(F32Max, float) \ | 108 V(F32Max, float) \ |
| 109 V(F32CopySign, float) \ | |
| 110 V(F64Min, double) \ | 109 V(F64Min, double) \ |
| 111 V(F64Max, double) \ | 110 V(F64Max, double) \ |
| 112 V(F64CopySign, double) \ | |
| 113 V(I32AsmjsDivS, int32_t) \ | 111 V(I32AsmjsDivS, int32_t) \ |
| 114 V(I32AsmjsDivU, uint32_t) \ | 112 V(I32AsmjsDivU, uint32_t) \ |
| 115 V(I32AsmjsRemS, int32_t) \ | 113 V(I32AsmjsRemS, int32_t) \ |
| 116 V(I32AsmjsRemU, uint32_t) | 114 V(I32AsmjsRemU, uint32_t) |
| 117 | 115 |
| 118 #define FOREACH_OTHER_UNOP(V) \ | 116 #define FOREACH_OTHER_UNOP(V) \ |
| 119 V(I32Clz, uint32_t) \ | 117 V(I32Clz, uint32_t) \ |
| 120 V(I32Ctz, uint32_t) \ | 118 V(I32Ctz, uint32_t) \ |
| 121 V(I32Popcnt, uint32_t) \ | 119 V(I32Popcnt, uint32_t) \ |
| 122 V(I32Eqz, uint32_t) \ | 120 V(I32Eqz, uint32_t) \ |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 V(F32ReinterpretI32, int32_t) \ | 153 V(F32ReinterpretI32, int32_t) \ |
| 156 V(F64SConvertI32, int32_t) \ | 154 V(F64SConvertI32, int32_t) \ |
| 157 V(F64UConvertI32, uint32_t) \ | 155 V(F64UConvertI32, uint32_t) \ |
| 158 V(F64SConvertI64, int64_t) \ | 156 V(F64SConvertI64, int64_t) \ |
| 159 V(F64UConvertI64, uint64_t) \ | 157 V(F64UConvertI64, uint64_t) \ |
| 160 V(F64ConvertF32, float) \ | 158 V(F64ConvertF32, float) \ |
| 161 V(F64ReinterpretI64, int64_t) \ | 159 V(F64ReinterpretI64, int64_t) \ |
| 162 V(I32AsmjsSConvertF32, float) \ | 160 V(I32AsmjsSConvertF32, float) \ |
| 163 V(I32AsmjsUConvertF32, float) \ | 161 V(I32AsmjsUConvertF32, float) \ |
| 164 V(I32AsmjsSConvertF64, double) \ | 162 V(I32AsmjsSConvertF64, double) \ |
| 165 V(I32AsmjsUConvertF64, double) | 163 V(I32AsmjsUConvertF64, double) \ |
| 166 | 164 V(F32Sqrt, float) \ |
| 167 #define FOREACH_OTHER_UNOP_NAN(V) \ | |
| 168 V(F32Sqrt, float) \ | |
| 169 V(F64Sqrt, double) | 165 V(F64Sqrt, double) |
| 170 | 166 |
| 171 static inline int32_t ExecuteI32DivS(int32_t a, int32_t b, TrapReason* trap) { | 167 static inline int32_t ExecuteI32DivS(int32_t a, int32_t b, TrapReason* trap) { |
| 172 if (b == 0) { | 168 if (b == 0) { |
| 173 *trap = kTrapDivByZero; | 169 *trap = kTrapDivByZero; |
| 174 return 0; | 170 return 0; |
| 175 } | 171 } |
| 176 if (b == -1 && a == std::numeric_limits<int32_t>::min()) { | 172 if (b == -1 && a == std::numeric_limits<int32_t>::min()) { |
| 177 *trap = kTrapDivUnrepresentable; | 173 *trap = kTrapDivUnrepresentable; |
| 178 return 0; | 174 return 0; |
| (...skipping 990 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1169 // ^ 0 ^ stack_.size() | 1165 // ^ 0 ^ stack_.size() |
| 1170 DCHECK_LE(dest, stack_.size()); | 1166 DCHECK_LE(dest, stack_.size()); |
| 1171 DCHECK_LE(dest + arity, stack_.size()); | 1167 DCHECK_LE(dest + arity, stack_.size()); |
| 1172 size_t pop_count = stack_.size() - dest - arity; | 1168 size_t pop_count = stack_.size() - dest - arity; |
| 1173 for (size_t i = 0; i < arity; i++) { | 1169 for (size_t i = 0; i < arity; i++) { |
| 1174 stack_[dest + i] = stack_[dest + pop_count + i]; | 1170 stack_[dest + i] = stack_[dest + pop_count + i]; |
| 1175 } | 1171 } |
| 1176 stack_.resize(stack_.size() - pop_count); | 1172 stack_.resize(stack_.size() - pop_count); |
| 1177 } | 1173 } |
| 1178 | 1174 |
| 1175 template <typename ctype, typename mtype> |
| 1176 bool ExecuteLoad(Decoder* decoder, InterpreterCode* code, pc_t pc, int& len) { |
| 1177 MemoryAccessOperand operand(decoder, code->at(pc), sizeof(ctype)); |
| 1178 uint32_t index = Pop().to<uint32_t>(); |
| 1179 size_t effective_mem_size = instance()->mem_size - sizeof(mtype); |
| 1180 if (operand.offset > effective_mem_size || |
| 1181 index > (effective_mem_size - operand.offset)) { |
| 1182 DoTrap(kTrapMemOutOfBounds, pc); |
| 1183 return false; |
| 1184 } |
| 1185 byte* addr = instance()->mem_start + operand.offset + index; |
| 1186 WasmVal result(static_cast<ctype>(ReadLittleEndianValue<mtype>(addr))); |
| 1187 |
| 1188 Push(pc, result); |
| 1189 len = 1 + operand.length; |
| 1190 return true; |
| 1191 } |
| 1192 |
| 1193 template <typename ctype, typename mtype> |
| 1194 bool ExecuteStore(Decoder* decoder, InterpreterCode* code, pc_t pc, |
| 1195 int& len) { |
| 1196 MemoryAccessOperand operand(decoder, code->at(pc), sizeof(ctype)); |
| 1197 WasmVal val = Pop(); |
| 1198 |
| 1199 uint32_t index = Pop().to<uint32_t>(); |
| 1200 size_t effective_mem_size = instance()->mem_size - sizeof(mtype); |
| 1201 if (operand.offset > effective_mem_size || |
| 1202 index > (effective_mem_size - operand.offset)) { |
| 1203 DoTrap(kTrapMemOutOfBounds, pc); |
| 1204 return false; |
| 1205 } |
| 1206 byte* addr = instance()->mem_start + operand.offset + index; |
| 1207 WriteLittleEndianValue<mtype>(addr, static_cast<mtype>(val.to<ctype>())); |
| 1208 len = 1 + operand.length; |
| 1209 |
| 1210 if (std::is_same<float, ctype>::value) { |
| 1211 possible_nondeterminism_ |= std::isnan(val.to<float>()); |
| 1212 } else if (std::is_same<double, ctype>::value) { |
| 1213 possible_nondeterminism_ |= std::isnan(val.to<double>()); |
| 1214 } |
| 1215 return true; |
| 1216 } |
| 1217 |
| 1179 void Execute(InterpreterCode* code, pc_t pc, int max) { | 1218 void Execute(InterpreterCode* code, pc_t pc, int max) { |
| 1180 Decoder decoder(code->start, code->end); | 1219 Decoder decoder(code->start, code->end); |
| 1181 pc_t limit = code->end - code->start; | 1220 pc_t limit = code->end - code->start; |
| 1182 while (--max >= 0) { | 1221 while (--max >= 0) { |
| 1183 #define PAUSE_IF_BREAK_FLAG(flag) \ | 1222 #define PAUSE_IF_BREAK_FLAG(flag) \ |
| 1184 if (V8_UNLIKELY(break_flags_ & WasmInterpreter::BreakFlag::flag)) max = 0; | 1223 if (V8_UNLIKELY(break_flags_ & WasmInterpreter::BreakFlag::flag)) max = 0; |
| 1185 | 1224 |
| 1186 DCHECK_GT(limit, pc); | 1225 DCHECK_GT(limit, pc); |
| 1187 | 1226 |
| 1188 const char* skip = " "; | 1227 const char* skip = " "; |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1420 *reinterpret_cast<float*>(ptr) = val.to<float>(); | 1459 *reinterpret_cast<float*>(ptr) = val.to<float>(); |
| 1421 } else if (type == kWasmF64) { | 1460 } else if (type == kWasmF64) { |
| 1422 *reinterpret_cast<double*>(ptr) = val.to<double>(); | 1461 *reinterpret_cast<double*>(ptr) = val.to<double>(); |
| 1423 } else { | 1462 } else { |
| 1424 UNREACHABLE(); | 1463 UNREACHABLE(); |
| 1425 } | 1464 } |
| 1426 len = 1 + operand.length; | 1465 len = 1 + operand.length; |
| 1427 break; | 1466 break; |
| 1428 } | 1467 } |
| 1429 | 1468 |
| 1430 #define LOAD_CASE(name, ctype, mtype) \ | 1469 #define LOAD_CASE(name, ctype, mtype) \ |
| 1431 case kExpr##name: { \ | 1470 case kExpr##name: { \ |
| 1432 MemoryAccessOperand operand(&decoder, code->at(pc), sizeof(ctype)); \ | 1471 if (!ExecuteLoad<ctype, mtype>(&decoder, code, pc, len)) return; \ |
| 1433 uint32_t index = Pop().to<uint32_t>(); \ | 1472 break; \ |
| 1434 size_t effective_mem_size = instance()->mem_size - sizeof(mtype); \ | |
| 1435 if (operand.offset > effective_mem_size || \ | |
| 1436 index > (effective_mem_size - operand.offset)) { \ | |
| 1437 return DoTrap(kTrapMemOutOfBounds, pc); \ | |
| 1438 } \ | |
| 1439 byte* addr = instance()->mem_start + operand.offset + index; \ | |
| 1440 WasmVal result(static_cast<ctype>(ReadLittleEndianValue<mtype>(addr))); \ | |
| 1441 Push(pc, result); \ | |
| 1442 len = 1 + operand.length; \ | |
| 1443 break; \ | |
| 1444 } | 1473 } |
| 1445 | 1474 |
| 1446 LOAD_CASE(I32LoadMem8S, int32_t, int8_t); | 1475 LOAD_CASE(I32LoadMem8S, int32_t, int8_t); |
| 1447 LOAD_CASE(I32LoadMem8U, int32_t, uint8_t); | 1476 LOAD_CASE(I32LoadMem8U, int32_t, uint8_t); |
| 1448 LOAD_CASE(I32LoadMem16S, int32_t, int16_t); | 1477 LOAD_CASE(I32LoadMem16S, int32_t, int16_t); |
| 1449 LOAD_CASE(I32LoadMem16U, int32_t, uint16_t); | 1478 LOAD_CASE(I32LoadMem16U, int32_t, uint16_t); |
| 1450 LOAD_CASE(I64LoadMem8S, int64_t, int8_t); | 1479 LOAD_CASE(I64LoadMem8S, int64_t, int8_t); |
| 1451 LOAD_CASE(I64LoadMem8U, int64_t, uint8_t); | 1480 LOAD_CASE(I64LoadMem8U, int64_t, uint8_t); |
| 1452 LOAD_CASE(I64LoadMem16S, int64_t, int16_t); | 1481 LOAD_CASE(I64LoadMem16S, int64_t, int16_t); |
| 1453 LOAD_CASE(I64LoadMem16U, int64_t, uint16_t); | 1482 LOAD_CASE(I64LoadMem16U, int64_t, uint16_t); |
| 1454 LOAD_CASE(I64LoadMem32S, int64_t, int32_t); | 1483 LOAD_CASE(I64LoadMem32S, int64_t, int32_t); |
| 1455 LOAD_CASE(I64LoadMem32U, int64_t, uint32_t); | 1484 LOAD_CASE(I64LoadMem32U, int64_t, uint32_t); |
| 1456 LOAD_CASE(I32LoadMem, int32_t, int32_t); | 1485 LOAD_CASE(I32LoadMem, int32_t, int32_t); |
| 1457 LOAD_CASE(I64LoadMem, int64_t, int64_t); | 1486 LOAD_CASE(I64LoadMem, int64_t, int64_t); |
| 1458 LOAD_CASE(F32LoadMem, float, float); | 1487 LOAD_CASE(F32LoadMem, float, float); |
| 1459 LOAD_CASE(F64LoadMem, double, double); | 1488 LOAD_CASE(F64LoadMem, double, double); |
| 1460 #undef LOAD_CASE | 1489 #undef LOAD_CASE |
| 1461 | 1490 |
| 1462 #define STORE_CASE(name, ctype, mtype) \ | 1491 #define STORE_CASE(name, ctype, mtype) \ |
| 1463 case kExpr##name: { \ | 1492 case kExpr##name: { \ |
| 1464 MemoryAccessOperand operand(&decoder, code->at(pc), sizeof(ctype)); \ | 1493 if (!ExecuteStore<ctype, mtype>(&decoder, code, pc, len)) return; \ |
| 1465 WasmVal val = Pop(); \ | 1494 break; \ |
| 1466 uint32_t index = Pop().to<uint32_t>(); \ | |
| 1467 size_t effective_mem_size = instance()->mem_size - sizeof(mtype); \ | |
| 1468 if (operand.offset > effective_mem_size || \ | |
| 1469 index > (effective_mem_size - operand.offset)) { \ | |
| 1470 return DoTrap(kTrapMemOutOfBounds, pc); \ | |
| 1471 } \ | |
| 1472 byte* addr = instance()->mem_start + operand.offset + index; \ | |
| 1473 WriteLittleEndianValue<mtype>(addr, static_cast<mtype>(val.to<ctype>())); \ | |
| 1474 len = 1 + operand.length; \ | |
| 1475 break; \ | |
| 1476 } | 1495 } |
| 1477 | 1496 |
| 1478 STORE_CASE(I32StoreMem8, int32_t, int8_t); | 1497 STORE_CASE(I32StoreMem8, int32_t, int8_t); |
| 1479 STORE_CASE(I32StoreMem16, int32_t, int16_t); | 1498 STORE_CASE(I32StoreMem16, int32_t, int16_t); |
| 1480 STORE_CASE(I64StoreMem8, int64_t, int8_t); | 1499 STORE_CASE(I64StoreMem8, int64_t, int8_t); |
| 1481 STORE_CASE(I64StoreMem16, int64_t, int16_t); | 1500 STORE_CASE(I64StoreMem16, int64_t, int16_t); |
| 1482 STORE_CASE(I64StoreMem32, int64_t, int32_t); | 1501 STORE_CASE(I64StoreMem32, int64_t, int32_t); |
| 1483 STORE_CASE(I32StoreMem, int32_t, int32_t); | 1502 STORE_CASE(I32StoreMem, int32_t, int32_t); |
| 1484 STORE_CASE(I64StoreMem, int64_t, int64_t); | 1503 STORE_CASE(I64StoreMem, int64_t, int64_t); |
| 1485 STORE_CASE(F32StoreMem, float, float); | 1504 STORE_CASE(F32StoreMem, float, float); |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1541 MemoryIndexOperand operand(&decoder, code->at(pc)); | 1560 MemoryIndexOperand operand(&decoder, code->at(pc)); |
| 1542 Push(pc, WasmVal(static_cast<uint32_t>(instance()->mem_size / | 1561 Push(pc, WasmVal(static_cast<uint32_t>(instance()->mem_size / |
| 1543 WasmModule::kPageSize))); | 1562 WasmModule::kPageSize))); |
| 1544 len = 1 + operand.length; | 1563 len = 1 + operand.length; |
| 1545 break; | 1564 break; |
| 1546 } | 1565 } |
| 1547 // We need to treat kExprI32ReinterpretF32 and kExprI64ReinterpretF64 | 1566 // We need to treat kExprI32ReinterpretF32 and kExprI64ReinterpretF64 |
| 1548 // specially to guarantee that the quiet bit of a NaN is preserved on | 1567 // specially to guarantee that the quiet bit of a NaN is preserved on |
| 1549 // ia32 by the reinterpret casts. | 1568 // ia32 by the reinterpret casts. |
| 1550 case kExprI32ReinterpretF32: { | 1569 case kExprI32ReinterpretF32: { |
| 1551 WasmVal result(ExecuteI32ReinterpretF32(Pop())); | 1570 WasmVal val = Pop(); |
| 1571 WasmVal result(ExecuteI32ReinterpretF32(val)); |
| 1552 Push(pc, result); | 1572 Push(pc, result); |
| 1573 possible_nondeterminism_ |= std::isnan(val.to<float>()); |
| 1553 break; | 1574 break; |
| 1554 } | 1575 } |
| 1555 case kExprI64ReinterpretF64: { | 1576 case kExprI64ReinterpretF64: { |
| 1556 WasmVal result(ExecuteI64ReinterpretF64(Pop())); | 1577 WasmVal val = Pop(); |
| 1578 WasmVal result(ExecuteI64ReinterpretF64(val)); |
| 1557 Push(pc, result); | 1579 Push(pc, result); |
| 1580 possible_nondeterminism_ |= std::isnan(val.to<double>()); |
| 1558 break; | 1581 break; |
| 1559 } | 1582 } |
| 1560 #define EXECUTE_SIMPLE_BINOP(name, ctype, op) \ | 1583 #define EXECUTE_SIMPLE_BINOP(name, ctype, op) \ |
| 1561 case kExpr##name: { \ | 1584 case kExpr##name: { \ |
| 1562 WasmVal rval = Pop(); \ | 1585 WasmVal rval = Pop(); \ |
| 1563 WasmVal lval = Pop(); \ | 1586 WasmVal lval = Pop(); \ |
| 1564 WasmVal result(lval.to<ctype>() op rval.to<ctype>()); \ | 1587 WasmVal result(lval.to<ctype>() op rval.to<ctype>()); \ |
| 1565 Push(pc, result); \ | 1588 Push(pc, result); \ |
| 1566 break; \ | 1589 break; \ |
| 1567 } | 1590 } |
| 1568 FOREACH_SIMPLE_BINOP(EXECUTE_SIMPLE_BINOP) | 1591 FOREACH_SIMPLE_BINOP(EXECUTE_SIMPLE_BINOP) |
| 1569 #undef EXECUTE_SIMPLE_BINOP | 1592 #undef EXECUTE_SIMPLE_BINOP |
| 1570 | 1593 |
| 1571 #define EXECUTE_SIMPLE_BINOP_NAN(name, ctype, op) \ | |
| 1572 case kExpr##name: { \ | |
| 1573 WasmVal rval = Pop(); \ | |
| 1574 WasmVal lval = Pop(); \ | |
| 1575 ctype result = lval.to<ctype>() op rval.to<ctype>(); \ | |
| 1576 possible_nondeterminism_ |= std::isnan(result); \ | |
| 1577 WasmVal result_val(result); \ | |
| 1578 Push(pc, result_val); \ | |
| 1579 break; \ | |
| 1580 } | |
| 1581 FOREACH_SIMPLE_BINOP_NAN(EXECUTE_SIMPLE_BINOP_NAN) | |
| 1582 #undef EXECUTE_SIMPLE_BINOP_NAN | |
| 1583 | |
| 1584 #define EXECUTE_OTHER_BINOP(name, ctype) \ | 1594 #define EXECUTE_OTHER_BINOP(name, ctype) \ |
| 1585 case kExpr##name: { \ | 1595 case kExpr##name: { \ |
| 1586 TrapReason trap = kTrapCount; \ | 1596 TrapReason trap = kTrapCount; \ |
| 1587 volatile ctype rval = Pop().to<ctype>(); \ | 1597 volatile ctype rval = Pop().to<ctype>(); \ |
| 1588 volatile ctype lval = Pop().to<ctype>(); \ | 1598 volatile ctype lval = Pop().to<ctype>(); \ |
| 1589 WasmVal result(Execute##name(lval, rval, &trap)); \ | 1599 WasmVal result(Execute##name(lval, rval, &trap)); \ |
| 1590 if (trap != kTrapCount) return DoTrap(trap, pc); \ | 1600 if (trap != kTrapCount) return DoTrap(trap, pc); \ |
| 1591 Push(pc, result); \ | 1601 Push(pc, result); \ |
| 1592 break; \ | 1602 break; \ |
| 1593 } | 1603 } |
| 1594 FOREACH_OTHER_BINOP(EXECUTE_OTHER_BINOP) | 1604 FOREACH_OTHER_BINOP(EXECUTE_OTHER_BINOP) |
| 1595 #undef EXECUTE_OTHER_BINOP | 1605 #undef EXECUTE_OTHER_BINOP |
| 1596 | 1606 |
| 1607 case kExprF32CopySign: { |
| 1608 // Handle kExprF32CopySign separately because it may introduce |
| 1609 // observable non-determinism. |
| 1610 TrapReason trap = kTrapCount; |
| 1611 volatile float rval = Pop().to<float>(); |
| 1612 volatile float lval = Pop().to<float>(); |
| 1613 WasmVal result(ExecuteF32CopySign(lval, rval, &trap)); |
| 1614 Push(pc, result); |
| 1615 possible_nondeterminism_ |= std::isnan(rval); |
| 1616 break; |
| 1617 } |
| 1618 case kExprF64CopySign: { |
| 1619 // Handle kExprF32CopySign separately because it may introduce |
| 1620 // observable non-determinism. |
| 1621 TrapReason trap = kTrapCount; |
| 1622 volatile double rval = Pop().to<double>(); |
| 1623 volatile double lval = Pop().to<double>(); |
| 1624 WasmVal result(ExecuteF64CopySign(lval, rval, &trap)); |
| 1625 Push(pc, result); |
| 1626 possible_nondeterminism_ |= std::isnan(rval); |
| 1627 break; |
| 1628 } |
| 1597 #define EXECUTE_OTHER_UNOP(name, ctype) \ | 1629 #define EXECUTE_OTHER_UNOP(name, ctype) \ |
| 1598 case kExpr##name: { \ | 1630 case kExpr##name: { \ |
| 1599 TrapReason trap = kTrapCount; \ | 1631 TrapReason trap = kTrapCount; \ |
| 1600 volatile ctype val = Pop().to<ctype>(); \ | 1632 volatile ctype val = Pop().to<ctype>(); \ |
| 1601 WasmVal result(Execute##name(val, &trap)); \ | 1633 WasmVal result(Execute##name(val, &trap)); \ |
| 1602 if (trap != kTrapCount) return DoTrap(trap, pc); \ | 1634 if (trap != kTrapCount) return DoTrap(trap, pc); \ |
| 1603 Push(pc, result); \ | 1635 Push(pc, result); \ |
| 1604 break; \ | 1636 break; \ |
| 1605 } | 1637 } |
| 1606 FOREACH_OTHER_UNOP(EXECUTE_OTHER_UNOP) | 1638 FOREACH_OTHER_UNOP(EXECUTE_OTHER_UNOP) |
| 1607 #undef EXECUTE_OTHER_UNOP | 1639 #undef EXECUTE_OTHER_UNOP |
| 1608 | 1640 |
| 1609 #define EXECUTE_OTHER_UNOP_NAN(name, ctype) \ | |
| 1610 case kExpr##name: { \ | |
| 1611 TrapReason trap = kTrapCount; \ | |
| 1612 volatile ctype val = Pop().to<ctype>(); \ | |
| 1613 ctype result = Execute##name(val, &trap); \ | |
| 1614 possible_nondeterminism_ |= std::isnan(result); \ | |
| 1615 WasmVal result_val(result); \ | |
| 1616 if (trap != kTrapCount) return DoTrap(trap, pc); \ | |
| 1617 Push(pc, result_val); \ | |
| 1618 break; \ | |
| 1619 } | |
| 1620 FOREACH_OTHER_UNOP_NAN(EXECUTE_OTHER_UNOP_NAN) | |
| 1621 #undef EXECUTE_OTHER_UNOP_NAN | |
| 1622 | |
| 1623 default: | 1641 default: |
| 1624 V8_Fatal(__FILE__, __LINE__, "Unknown or unimplemented opcode #%d:%s", | 1642 V8_Fatal(__FILE__, __LINE__, "Unknown or unimplemented opcode #%d:%s", |
| 1625 code->start[pc], OpcodeName(code->start[pc])); | 1643 code->start[pc], OpcodeName(code->start[pc])); |
| 1626 UNREACHABLE(); | 1644 UNREACHABLE(); |
| 1627 } | 1645 } |
| 1628 | 1646 |
| 1629 pc += len; | 1647 pc += len; |
| 1630 if (pc == limit) { | 1648 if (pc == limit) { |
| 1631 // Fell off end of code; do an implicit return. | 1649 // Fell off end of code; do an implicit return. |
| 1632 TRACE("@%-3zu: ImplicitReturn\n", pc); | 1650 TRACE("@%-3zu: ImplicitReturn\n", pc); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1922 return none; | 1940 return none; |
| 1923 } | 1941 } |
| 1924 | 1942 |
| 1925 void InterpretedFrame::SetLocalVal(int index, WasmVal val) { UNIMPLEMENTED(); } | 1943 void InterpretedFrame::SetLocalVal(int index, WasmVal val) { UNIMPLEMENTED(); } |
| 1926 | 1944 |
| 1927 void InterpretedFrame::SetExprVal(int pc, WasmVal val) { UNIMPLEMENTED(); } | 1945 void InterpretedFrame::SetExprVal(int pc, WasmVal val) { UNIMPLEMENTED(); } |
| 1928 | 1946 |
| 1929 } // namespace wasm | 1947 } // namespace wasm |
| 1930 } // namespace internal | 1948 } // namespace internal |
| 1931 } // namespace v8 | 1949 } // namespace v8 |
| OLD | NEW |