| OLD | NEW |
| 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/signature.h" | 5 #include "src/signature.h" |
| 6 | 6 |
| 7 #include "src/base/platform/elapsed-timer.h" | 7 #include "src/base/platform/elapsed-timer.h" |
| 8 #include "src/bit-vector.h" | 8 #include "src/bit-vector.h" |
| 9 #include "src/flags.h" | 9 #include "src/flags.h" |
| 10 #include "src/handles.h" | 10 #include "src/handles.h" |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 | 139 |
| 140 static Control Try(const byte* pc, size_t stack_depth, SsaEnv* end_env, | 140 static Control Try(const byte* pc, size_t stack_depth, SsaEnv* end_env, |
| 141 Zone* zone, SsaEnv* catch_env, int32_t previous_catch) { | 141 Zone* zone, SsaEnv* catch_env, int32_t previous_catch) { |
| 142 DCHECK_NOT_NULL(catch_env); | 142 DCHECK_NOT_NULL(catch_env); |
| 143 TryInfo* try_info = new (zone) TryInfo(catch_env); | 143 TryInfo* try_info = new (zone) TryInfo(catch_env); |
| 144 return {pc, kControlTry, stack_depth, end_env, nullptr, | 144 return {pc, kControlTry, stack_depth, end_env, nullptr, |
| 145 try_info, previous_catch, false, {0, {NO_VALUE}}}; | 145 try_info, previous_catch, false, {0, {NO_VALUE}}}; |
| 146 } | 146 } |
| 147 }; | 147 }; |
| 148 | 148 |
| 149 namespace { |
| 150 inline unsigned GetShuffleMaskSize(WasmOpcode opcode) { |
| 151 switch (opcode) { |
| 152 case kExprS32x4Shuffle: |
| 153 return 4; |
| 154 case kExprS16x8Shuffle: |
| 155 return 8; |
| 156 case kExprS8x16Shuffle: |
| 157 return 16; |
| 158 default: |
| 159 UNREACHABLE(); |
| 160 return 0; |
| 161 } |
| 162 } |
| 163 } // namespace |
| 164 |
| 149 // Macros that build nodes only if there is a graph and the current SSA | 165 // Macros that build nodes only if there is a graph and the current SSA |
| 150 // environment is reachable from start. This avoids problems with malformed | 166 // environment is reachable from start. This avoids problems with malformed |
| 151 // TF graphs when decoding inputs that have unreachable code. | 167 // TF graphs when decoding inputs that have unreachable code. |
| 152 #define BUILD(func, ...) \ | 168 #define BUILD(func, ...) \ |
| 153 (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr) | 169 (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr) |
| 154 #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr) | 170 #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr) |
| 155 | 171 |
| 156 // Generic Wasm bytecode decoder with utilities for decoding operands, | 172 // Generic Wasm bytecode decoder with utilities for decoding operands, |
| 157 // lengths, etc. | 173 // lengths, etc. |
| 158 class WasmDecoder : public Decoder { | 174 class WasmDecoder : public Decoder { |
| (...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 } | 421 } |
| 406 if (operand.shift < 0 || operand.shift >= max_shift) { | 422 if (operand.shift < 0 || operand.shift >= max_shift) { |
| 407 error(pc_ + 2, "invalid shift amount"); | 423 error(pc_ + 2, "invalid shift amount"); |
| 408 return false; | 424 return false; |
| 409 } else { | 425 } else { |
| 410 return true; | 426 return true; |
| 411 } | 427 } |
| 412 } | 428 } |
| 413 | 429 |
| 414 inline bool Validate(const byte* pc, WasmOpcode opcode, | 430 inline bool Validate(const byte* pc, WasmOpcode opcode, |
| 415 SimdConcatOperand<true>& operand) { | 431 SimdShuffleOperand<true>& operand) { |
| 416 DCHECK_EQ(wasm::kExprS8x16Concat, opcode); | 432 unsigned lanes = GetShuffleMaskSize(opcode); |
| 417 if (operand.bytes <= 0 || operand.bytes >= kSimd128Size) { | 433 uint8_t max_lane = 0; |
| 418 error(pc_ + 2, "invalid byte amount"); | 434 for (unsigned i = 0; i < lanes; i++) |
| 435 max_lane = std::max(max_lane, operand.shuffle[i]); |
| 436 if (operand.lanes != lanes || max_lane > 2 * lanes) { |
| 437 error(pc_ + 2, "invalid shuffle mask"); |
| 419 return false; | 438 return false; |
| 420 } else { | 439 } else { |
| 421 return true; | 440 return true; |
| 422 } | 441 } |
| 423 } | 442 } |
| 424 | 443 |
| 425 static unsigned OpcodeLength(Decoder* decoder, const byte* pc) { | 444 static unsigned OpcodeLength(Decoder* decoder, const byte* pc) { |
| 426 switch (static_cast<byte>(*pc)) { | 445 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); |
| 446 switch (opcode) { |
| 427 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: | 447 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: |
| 428 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) | 448 FOREACH_LOAD_MEM_OPCODE(DECLARE_OPCODE_CASE) |
| 429 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) | 449 FOREACH_STORE_MEM_OPCODE(DECLARE_OPCODE_CASE) |
| 430 #undef DECLARE_OPCODE_CASE | 450 #undef DECLARE_OPCODE_CASE |
| 431 { | 451 { |
| 432 MemoryAccessOperand<true> operand(decoder, pc, UINT32_MAX); | 452 MemoryAccessOperand<true> operand(decoder, pc, UINT32_MAX); |
| 433 return 1 + operand.length; | 453 return 1 + operand.length; |
| 434 } | 454 } |
| 435 case kExprBr: | 455 case kExprBr: |
| 436 case kExprBrIf: { | 456 case kExprBrIf: { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 #undef DECLARE_OPCODE_CASE | 519 #undef DECLARE_OPCODE_CASE |
| 500 { | 520 { |
| 501 return 2; | 521 return 2; |
| 502 } | 522 } |
| 503 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: | 523 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: |
| 504 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) | 524 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) |
| 505 #undef DECLARE_OPCODE_CASE | 525 #undef DECLARE_OPCODE_CASE |
| 506 { | 526 { |
| 507 return 3; | 527 return 3; |
| 508 } | 528 } |
| 529 // Shuffles contain a byte array to determine the shuffle. |
| 530 case kExprS32x4Shuffle: |
| 531 case kExprS16x8Shuffle: |
| 532 case kExprS8x16Shuffle: |
| 533 return 2 + GetShuffleMaskSize(opcode); |
| 509 default: | 534 default: |
| 510 decoder->error(pc, "invalid SIMD opcode"); | 535 decoder->error(pc, "invalid SIMD opcode"); |
| 511 return 2; | 536 return 2; |
| 512 } | 537 } |
| 513 } | 538 } |
| 514 default: | 539 default: |
| 515 return 1; | 540 return 1; |
| 516 } | 541 } |
| 517 } | 542 } |
| 518 | 543 |
| (...skipping 1022 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1541 SimdShiftOperand<true> operand(this, pc_); | 1566 SimdShiftOperand<true> operand(this, pc_); |
| 1542 if (Validate(pc_, opcode, operand)) { | 1567 if (Validate(pc_, opcode, operand)) { |
| 1543 compiler::NodeVector inputs(1, zone_); | 1568 compiler::NodeVector inputs(1, zone_); |
| 1544 inputs[0] = Pop(0, ValueType::kSimd128).node; | 1569 inputs[0] = Pop(0, ValueType::kSimd128).node; |
| 1545 TFNode* node = BUILD(SimdShiftOp, opcode, operand.shift, inputs); | 1570 TFNode* node = BUILD(SimdShiftOp, opcode, operand.shift, inputs); |
| 1546 Push(ValueType::kSimd128, node); | 1571 Push(ValueType::kSimd128, node); |
| 1547 } | 1572 } |
| 1548 return operand.length; | 1573 return operand.length; |
| 1549 } | 1574 } |
| 1550 | 1575 |
| 1551 unsigned SimdConcatOp(WasmOpcode opcode) { | 1576 unsigned SimdShuffleOp(WasmOpcode opcode) { |
| 1552 DCHECK_EQ(wasm::kExprS8x16Concat, opcode); | 1577 SimdShuffleOperand<true> operand(this, pc_, GetShuffleMaskSize(opcode)); |
| 1553 SimdConcatOperand<true> operand(this, pc_); | |
| 1554 if (Validate(pc_, opcode, operand)) { | 1578 if (Validate(pc_, opcode, operand)) { |
| 1555 compiler::NodeVector inputs(2, zone_); | 1579 compiler::NodeVector inputs(2, zone_); |
| 1556 inputs[1] = Pop(1, ValueType::kSimd128).node; | 1580 inputs[1] = Pop(1, ValueType::kSimd128).node; |
| 1557 inputs[0] = Pop(0, ValueType::kSimd128).node; | 1581 inputs[0] = Pop(0, ValueType::kSimd128).node; |
| 1558 TFNode* node = BUILD(SimdConcatOp, operand.bytes, inputs); | 1582 TFNode* node = |
| 1583 BUILD(SimdShuffleOp, operand.shuffle, operand.lanes, inputs); |
| 1559 Push(ValueType::kSimd128, node); | 1584 Push(ValueType::kSimd128, node); |
| 1560 } | 1585 } |
| 1561 return operand.length; | 1586 return operand.lanes; |
| 1562 } | 1587 } |
| 1563 | 1588 |
| 1564 unsigned DecodeSimdOpcode(WasmOpcode opcode) { | 1589 unsigned DecodeSimdOpcode(WasmOpcode opcode) { |
| 1565 unsigned len = 0; | 1590 unsigned len = 0; |
| 1566 switch (opcode) { | 1591 switch (opcode) { |
| 1567 case kExprF32x4ExtractLane: { | 1592 case kExprF32x4ExtractLane: { |
| 1568 len = SimdExtractLane(opcode, ValueType::kFloat32); | 1593 len = SimdExtractLane(opcode, ValueType::kFloat32); |
| 1569 break; | 1594 break; |
| 1570 } | 1595 } |
| 1571 case kExprI32x4ExtractLane: | 1596 case kExprI32x4ExtractLane: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1589 case kExprI32x4ShrU: | 1614 case kExprI32x4ShrU: |
| 1590 case kExprI16x8Shl: | 1615 case kExprI16x8Shl: |
| 1591 case kExprI16x8ShrS: | 1616 case kExprI16x8ShrS: |
| 1592 case kExprI16x8ShrU: | 1617 case kExprI16x8ShrU: |
| 1593 case kExprI8x16Shl: | 1618 case kExprI8x16Shl: |
| 1594 case kExprI8x16ShrS: | 1619 case kExprI8x16ShrS: |
| 1595 case kExprI8x16ShrU: { | 1620 case kExprI8x16ShrU: { |
| 1596 len = SimdShiftOp(opcode); | 1621 len = SimdShiftOp(opcode); |
| 1597 break; | 1622 break; |
| 1598 } | 1623 } |
| 1599 case kExprS8x16Concat: { | 1624 case kExprS32x4Shuffle: |
| 1600 len = SimdConcatOp(opcode); | 1625 case kExprS16x8Shuffle: |
| 1626 case kExprS8x16Shuffle: { |
| 1627 len = SimdShuffleOp(opcode); |
| 1601 break; | 1628 break; |
| 1602 } | 1629 } |
| 1603 default: { | 1630 default: { |
| 1604 FunctionSig* sig = WasmOpcodes::Signature(opcode); | 1631 FunctionSig* sig = WasmOpcodes::Signature(opcode); |
| 1605 if (sig != nullptr) { | 1632 if (sig != nullptr) { |
| 1606 compiler::NodeVector inputs(sig->parameter_count(), zone_); | 1633 compiler::NodeVector inputs(sig->parameter_count(), zone_); |
| 1607 for (size_t i = sig->parameter_count(); i > 0; i--) { | 1634 for (size_t i = sig->parameter_count(); i > 0; i--) { |
| 1608 Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1)); | 1635 Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1)); |
| 1609 inputs[i - 1] = val.node; | 1636 inputs[i - 1] = val.node; |
| 1610 } | 1637 } |
| (...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2272 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 2299 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
| 2273 const byte* start, const byte* end) { | 2300 const byte* start, const byte* end) { |
| 2274 Decoder decoder(start, end); | 2301 Decoder decoder(start, end); |
| 2275 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, | 2302 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, |
| 2276 static_cast<int>(num_locals), zone); | 2303 static_cast<int>(num_locals), zone); |
| 2277 } | 2304 } |
| 2278 | 2305 |
| 2279 } // namespace wasm | 2306 } // namespace wasm |
| 2280 } // namespace internal | 2307 } // namespace internal |
| 2281 } // namespace v8 | 2308 } // namespace v8 |
| OLD | NEW |