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 } | |
161 } | |
162 } // namespace | |
163 | |
164 // Macros that build nodes only if there is a graph and the current SSA | 149 // Macros that build nodes only if there is a graph and the current SSA |
165 // environment is reachable from start. This avoids problems with malformed | 150 // environment is reachable from start. This avoids problems with malformed |
166 // TF graphs when decoding inputs that have unreachable code. | 151 // TF graphs when decoding inputs that have unreachable code. |
167 #define BUILD(func, ...) \ | 152 #define BUILD(func, ...) \ |
168 (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr) | 153 (build() ? CheckForException(builder_->func(__VA_ARGS__)) : nullptr) |
169 #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr) | 154 #define BUILD0(func) (build() ? CheckForException(builder_->func()) : nullptr) |
170 | 155 |
171 // Generic Wasm bytecode decoder with utilities for decoding operands, | 156 // Generic Wasm bytecode decoder with utilities for decoding operands, |
172 // lengths, etc. | 157 // lengths, etc. |
173 class WasmDecoder : public Decoder { | 158 class WasmDecoder : public Decoder { |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 break; | 399 break; |
415 } | 400 } |
416 if (operand.shift < 0 || operand.shift >= max_shift) { | 401 if (operand.shift < 0 || operand.shift >= max_shift) { |
417 error(pc_ + 2, "invalid shift amount"); | 402 error(pc_ + 2, "invalid shift amount"); |
418 return false; | 403 return false; |
419 } else { | 404 } else { |
420 return true; | 405 return true; |
421 } | 406 } |
422 } | 407 } |
423 | 408 |
424 inline bool Validate(const byte* pc, WasmOpcode opcode, | 409 inline bool Validate(const byte* pc, Simd8x16ShuffleOperand<true>& operand) { |
425 SimdShuffleOperand<true>& operand) { | |
426 unsigned lanes = GetShuffleMaskSize(opcode); | |
427 uint8_t max_lane = 0; | 410 uint8_t max_lane = 0; |
428 for (unsigned i = 0; i < lanes; i++) | 411 for (uint32_t i = 0; i < kSimd128Size; ++i) |
429 max_lane = std::max(max_lane, operand.shuffle[i]); | 412 max_lane = std::max(max_lane, operand.shuffle[i]); |
430 if (operand.lanes != lanes || max_lane > 2 * lanes) { | 413 // Shuffle indices must be in [0..31] for a 16 lane shuffle. |
| 414 if (max_lane > 2 * kSimd128Size) { |
431 error(pc_ + 2, "invalid shuffle mask"); | 415 error(pc_ + 2, "invalid shuffle mask"); |
432 return false; | 416 return false; |
433 } else { | 417 } else { |
434 return true; | 418 return true; |
435 } | 419 } |
436 } | 420 } |
437 | 421 |
438 static unsigned OpcodeLength(Decoder* decoder, const byte* pc) { | 422 static unsigned OpcodeLength(Decoder* decoder, const byte* pc) { |
439 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); | 423 WasmOpcode opcode = static_cast<WasmOpcode>(*pc); |
440 switch (opcode) { | 424 switch (opcode) { |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 #undef DECLARE_OPCODE_CASE | 497 #undef DECLARE_OPCODE_CASE |
514 { | 498 { |
515 return 2; | 499 return 2; |
516 } | 500 } |
517 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: | 501 #define DECLARE_OPCODE_CASE(name, opcode, sig) case kExpr##name: |
518 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) | 502 FOREACH_SIMD_1_OPERAND_OPCODE(DECLARE_OPCODE_CASE) |
519 #undef DECLARE_OPCODE_CASE | 503 #undef DECLARE_OPCODE_CASE |
520 { | 504 { |
521 return 3; | 505 return 3; |
522 } | 506 } |
523 // Shuffles contain a byte array to determine the shuffle. | 507 // Shuffles require a byte per lane, or 16 immediate bytes. |
524 case kExprS32x4Shuffle: | |
525 case kExprS16x8Shuffle: | |
526 case kExprS8x16Shuffle: | 508 case kExprS8x16Shuffle: |
527 return 2 + GetShuffleMaskSize(opcode); | 509 return 2 + kSimd128Size; |
528 default: | 510 default: |
529 decoder->error(pc, "invalid SIMD opcode"); | 511 decoder->error(pc, "invalid SIMD opcode"); |
530 return 2; | 512 return 2; |
531 } | 513 } |
532 } | 514 } |
533 default: | 515 default: |
534 return 1; | 516 return 1; |
535 } | 517 } |
536 } | 518 } |
537 | 519 |
(...skipping 1013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1551 SimdShiftOperand<true> operand(this, pc_); | 1533 SimdShiftOperand<true> operand(this, pc_); |
1552 if (Validate(pc_, opcode, operand)) { | 1534 if (Validate(pc_, opcode, operand)) { |
1553 compiler::NodeVector inputs(1, zone_); | 1535 compiler::NodeVector inputs(1, zone_); |
1554 inputs[0] = Pop(0, ValueType::kSimd128).node; | 1536 inputs[0] = Pop(0, ValueType::kSimd128).node; |
1555 TFNode* node = BUILD(SimdShiftOp, opcode, operand.shift, inputs); | 1537 TFNode* node = BUILD(SimdShiftOp, opcode, operand.shift, inputs); |
1556 Push(ValueType::kSimd128, node); | 1538 Push(ValueType::kSimd128, node); |
1557 } | 1539 } |
1558 return operand.length; | 1540 return operand.length; |
1559 } | 1541 } |
1560 | 1542 |
1561 unsigned SimdShuffleOp(WasmOpcode opcode) { | 1543 unsigned Simd8x16ShuffleOp() { |
1562 SimdShuffleOperand<true> operand(this, pc_, GetShuffleMaskSize(opcode)); | 1544 Simd8x16ShuffleOperand<true> operand(this, pc_); |
1563 if (Validate(pc_, opcode, operand)) { | 1545 if (Validate(pc_, operand)) { |
1564 compiler::NodeVector inputs(2, zone_); | 1546 compiler::NodeVector inputs(2, zone_); |
1565 inputs[1] = Pop(1, ValueType::kSimd128).node; | 1547 inputs[1] = Pop(1, ValueType::kSimd128).node; |
1566 inputs[0] = Pop(0, ValueType::kSimd128).node; | 1548 inputs[0] = Pop(0, ValueType::kSimd128).node; |
1567 TFNode* node = | 1549 TFNode* node = BUILD(Simd8x16ShuffleOp, operand.shuffle, inputs); |
1568 BUILD(SimdShuffleOp, operand.shuffle, operand.lanes, inputs); | |
1569 Push(ValueType::kSimd128, node); | 1550 Push(ValueType::kSimd128, node); |
1570 } | 1551 } |
1571 return operand.lanes; | 1552 return 16; |
1572 } | 1553 } |
1573 | 1554 |
1574 unsigned DecodeSimdOpcode(WasmOpcode opcode) { | 1555 unsigned DecodeSimdOpcode(WasmOpcode opcode) { |
1575 unsigned len = 0; | 1556 unsigned len = 0; |
1576 switch (opcode) { | 1557 switch (opcode) { |
1577 case kExprF32x4ExtractLane: { | 1558 case kExprF32x4ExtractLane: { |
1578 len = SimdExtractLane(opcode, ValueType::kFloat32); | 1559 len = SimdExtractLane(opcode, ValueType::kFloat32); |
1579 break; | 1560 break; |
1580 } | 1561 } |
1581 case kExprI32x4ExtractLane: | 1562 case kExprI32x4ExtractLane: |
(...skipping 17 matching lines...) Expand all Loading... |
1599 case kExprI32x4ShrU: | 1580 case kExprI32x4ShrU: |
1600 case kExprI16x8Shl: | 1581 case kExprI16x8Shl: |
1601 case kExprI16x8ShrS: | 1582 case kExprI16x8ShrS: |
1602 case kExprI16x8ShrU: | 1583 case kExprI16x8ShrU: |
1603 case kExprI8x16Shl: | 1584 case kExprI8x16Shl: |
1604 case kExprI8x16ShrS: | 1585 case kExprI8x16ShrS: |
1605 case kExprI8x16ShrU: { | 1586 case kExprI8x16ShrU: { |
1606 len = SimdShiftOp(opcode); | 1587 len = SimdShiftOp(opcode); |
1607 break; | 1588 break; |
1608 } | 1589 } |
1609 case kExprS32x4Shuffle: | |
1610 case kExprS16x8Shuffle: | |
1611 case kExprS8x16Shuffle: { | 1590 case kExprS8x16Shuffle: { |
1612 len = SimdShuffleOp(opcode); | 1591 len = Simd8x16ShuffleOp(); |
1613 break; | 1592 break; |
1614 } | 1593 } |
1615 default: { | 1594 default: { |
1616 FunctionSig* sig = WasmOpcodes::Signature(opcode); | 1595 FunctionSig* sig = WasmOpcodes::Signature(opcode); |
1617 if (sig != nullptr) { | 1596 if (sig != nullptr) { |
1618 compiler::NodeVector inputs(sig->parameter_count(), zone_); | 1597 compiler::NodeVector inputs(sig->parameter_count(), zone_); |
1619 for (size_t i = sig->parameter_count(); i > 0; i--) { | 1598 for (size_t i = sig->parameter_count(); i > 0; i--) { |
1620 Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1)); | 1599 Value val = Pop(static_cast<int>(i - 1), sig->GetParam(i - 1)); |
1621 inputs[i - 1] = val.node; | 1600 inputs[i - 1] = val.node; |
1622 } | 1601 } |
(...skipping 661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2284 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 2263 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
2285 const byte* start, const byte* end) { | 2264 const byte* start, const byte* end) { |
2286 Decoder decoder(start, end); | 2265 Decoder decoder(start, end); |
2287 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, | 2266 return WasmDecoder::AnalyzeLoopAssignment(&decoder, start, |
2288 static_cast<int>(num_locals), zone); | 2267 static_cast<int>(num_locals), zone); |
2289 } | 2268 } |
2290 | 2269 |
2291 } // namespace wasm | 2270 } // namespace wasm |
2292 } // namespace internal | 2271 } // namespace internal |
2293 } // namespace v8 | 2272 } // namespace v8 |
OLD | NEW |