LCOV - code coverage report
Current view: top level - src/wasm - function-body-decoder-impl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 91 98 92.9 %
Date: 2017-04-26 Functions: 18 19 94.7 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
       6             : #define V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_
       7             : 
       8             : #include "src/wasm/decoder.h"
       9             : #include "src/wasm/wasm-opcodes.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : namespace wasm {
      14             : 
      15             : struct WasmGlobal;
      16             : 
      17             : // Use this macro to check a condition if checked == true, and DCHECK the
      18             : // condition otherwise.
      19             : #define CHECKED_COND(cond)   \
      20             :   (checked ? (cond) : ([&] { \
      21             :     DCHECK(cond);            \
      22             :     return true;             \
      23             :   })())
      24             : 
      25             : // Helpers for decoding different kinds of operands which follow bytecodes.
      26             : template <bool checked>
      27             : struct LocalIndexOperand {
      28             :   uint32_t index;
      29             :   ValueType type = kWasmStmt;
      30             :   unsigned length;
      31             : 
      32     7019012 :   inline LocalIndexOperand(Decoder* decoder, const byte* pc) {
      33     8161725 :     index = decoder->read_u32v<checked>(pc + 1, &length, "local index");
      34             :   }
      35             : };
      36             : 
      37             : template <bool checked>
      38             : struct ImmI32Operand {
      39             :   int32_t value;
      40             :   unsigned length;
      41      571633 :   inline ImmI32Operand(Decoder* decoder, const byte* pc) {
      42     2863600 :     value = decoder->read_i32v<checked>(pc + 1, &length, "immi32");
      43      571633 :   }
      44             : };
      45             : 
      46             : template <bool checked>
      47             : struct ImmI64Operand {
      48             :   int64_t value;
      49             :   unsigned length;
      50       11585 :   inline ImmI64Operand(Decoder* decoder, const byte* pc) {
      51       43884 :     value = decoder->read_i64v<checked>(pc + 1, &length, "immi64");
      52       11585 :   }
      53             : };
      54             : 
      55             : template <bool checked>
      56             : struct ImmF32Operand {
      57             :   float value;
      58             :   unsigned length = 4;
      59      442092 :   inline ImmF32Operand(Decoder* decoder, const byte* pc) {
      60             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
      61      884184 :     uint32_t tmp = decoder->read_u32<checked>(pc + 1, "immf32");
      62      442092 :     memcpy(&value, &tmp, sizeof(value));
      63      442092 :   }
      64             : };
      65             : 
      66             : template <bool checked>
      67             : struct ImmF64Operand {
      68             :   double value;
      69             :   unsigned length = 8;
      70       11307 :   inline ImmF64Operand(Decoder* decoder, const byte* pc) {
      71             :     // Avoid bit_cast because it might not preserve the signalling bit of a NaN.
      72       22614 :     uint64_t tmp = decoder->read_u64<checked>(pc + 1, "immf64");
      73       11307 :     memcpy(&value, &tmp, sizeof(value));
      74       11307 :   }
      75             : };
      76             : 
      77             : template <bool checked>
      78             : struct GlobalIndexOperand {
      79             :   uint32_t index;
      80             :   ValueType type = kWasmStmt;
      81             :   const WasmGlobal* global = nullptr;
      82             :   unsigned length;
      83             : 
      84       22571 :   inline GlobalIndexOperand(Decoder* decoder, const byte* pc) {
      85       44214 :     index = decoder->read_u32v<checked>(pc + 1, &length, "global index");
      86             :   }
      87             : };
      88             : 
      89             : template <bool checked>
      90             : struct BlockTypeOperand {
      91             :   uint32_t arity = 0;
      92             :   const byte* types = nullptr;  // pointer to encoded types for the block.
      93             :   unsigned length = 1;
      94             : 
      95     2521128 :   inline BlockTypeOperand(Decoder* decoder, const byte* pc) {
      96     2521128 :     uint8_t val = decoder->read_u8<checked>(pc + 1, "block type");
      97     2521128 :     ValueType type = kWasmStmt;
      98     2521128 :     if (decode_local_type(val, &type)) {
      99     2459771 :       arity = type == kWasmStmt ? 0 : 1;
     100     2459771 :       types = pc + 1;
     101             :     } else {
     102             :       // Handle multi-value blocks.
     103         100 :       if (!CHECKED_COND(FLAG_wasm_mv_prototype)) {
     104             :         decoder->error(pc + 1, "invalid block arity > 1");
     105          51 :         return;
     106             :       }
     107          49 :       if (!CHECKED_COND(val == kMultivalBlock)) {
     108             :         decoder->error(pc + 1, "invalid block type");
     109             :         return;
     110             :       }
     111             :       // Decode and check the types vector of the block.
     112          49 :       unsigned len = 0;
     113       61306 :       uint32_t count = decoder->read_u32v<checked>(pc + 2, &len, "block arity");
     114             :       // {count} is encoded as {arity-2}, so that a {0} count here corresponds
     115             :       // to a block with 2 values. This makes invalid/redundant encodings
     116             :       // impossible.
     117       61306 :       arity = count + 2;
     118       61306 :       length = 1 + len + arity;
     119       61306 :       types = pc + 1 + 1 + len;
     120             : 
     121      183918 :       for (uint32_t i = 0; i < arity; i++) {
     122      122612 :         uint32_t offset = 1 + 1 + len + i;
     123      122612 :         val = decoder->read_u8<checked>(pc + offset, "block type");
     124      122612 :         decode_local_type(val, &type);
     125          98 :         if (!CHECKED_COND(type != kWasmStmt)) {
     126             :           decoder->error(pc + offset, "invalid block type");
     127             :           return;
     128             :         }
     129             :       }
     130             :     }
     131             :   }
     132             : 
     133             :   // Decode a byte representing a local type. Return {false} if the encoded
     134             :   // byte was invalid or {kMultivalBlock}.
     135     2650504 :   inline bool decode_local_type(uint8_t val, ValueType* result) {
     136     2650504 :     switch (static_cast<ValueTypeCode>(val)) {
     137             :       case kLocalVoid:
     138     2438485 :         *result = kWasmStmt;
     139             :         return true;
     140             :       case kLocalI32:
     141      145794 :         *result = kWasmI32;
     142             :         return true;
     143             :       case kLocalI64:
     144          68 :         *result = kWasmI64;
     145             :         return true;
     146             :       case kLocalF32:
     147        1823 :         *result = kWasmF32;
     148             :         return true;
     149             :       case kLocalF64:
     150        2977 :         *result = kWasmF64;
     151             :         return true;
     152             :       case kLocalS128:
     153           0 :         *result = kWasmS128;
     154             :         return true;
     155             :       case kLocalS1x4:
     156           0 :         *result = kWasmS1x4;
     157             :         return true;
     158             :       case kLocalS1x8:
     159           0 :         *result = kWasmS1x8;
     160             :         return true;
     161             :       case kLocalS1x16:
     162           0 :         *result = kWasmS1x16;
     163             :         return true;
     164             :       default:
     165       61357 :         *result = kWasmStmt;
     166             :         return false;
     167             :     }
     168             :   }
     169        6764 :   ValueType read_entry(unsigned index) {
     170             :     DCHECK_LT(index, arity);
     171             :     ValueType result;
     172        6764 :     CHECK(decode_local_type(types[index], &result));
     173        6764 :     return result;
     174             :   }
     175             : };
     176             : 
     177             : struct Control;
     178             : template <bool checked>
     179             : struct BreakDepthOperand {
     180             :   uint32_t depth;
     181             :   Control* target = nullptr;
     182             :   unsigned length;
     183      161179 :   inline BreakDepthOperand(Decoder* decoder, const byte* pc) {
     184      323158 :     depth = decoder->read_u32v<checked>(pc + 1, &length, "break depth");
     185             :   }
     186             : };
     187             : 
     188             : template <bool checked>
     189             : struct CallIndirectOperand {
     190             :   uint32_t table_index;
     191             :   uint32_t index;
     192             :   FunctionSig* sig = nullptr;
     193             :   unsigned length;
     194        3630 :   inline CallIndirectOperand(Decoder* decoder, const byte* pc) {
     195        3195 :     unsigned len = 0;
     196        7260 :     index = decoder->read_u32v<checked>(pc + 1, &len, "signature index");
     197        6825 :     table_index = decoder->read_u8<checked>(pc + 1 + len, "table index");
     198        3195 :     if (!CHECKED_COND(table_index == 0)) {
     199           0 :       decoder->errorf(pc + 1 + len, "expected table index 0, found %u",
     200           0 :                       table_index);
     201             :     }
     202        3630 :     length = 1 + len;
     203        3630 :   }
     204             : };
     205             : 
     206             : template <bool checked>
     207             : struct CallFunctionOperand {
     208             :   uint32_t index;
     209             :   FunctionSig* sig = nullptr;
     210             :   unsigned length;
     211     1210777 :   inline CallFunctionOperand(Decoder* decoder, const byte* pc) {
     212     1429232 :     index = decoder->read_u32v<checked>(pc + 1, &length, "function index");
     213             :   }
     214             : };
     215             : 
     216             : template <bool checked>
     217             : struct MemoryIndexOperand {
     218             :   uint32_t index;
     219             :   unsigned length = 1;
     220        1547 :   inline MemoryIndexOperand(Decoder* decoder, const byte* pc) {
     221        3189 :     index = decoder->read_u8<checked>(pc + 1, "memory index");
     222        1547 :     if (!CHECKED_COND(index == 0)) {
     223          15 :       decoder->errorf(pc + 1, "expected memory index 0, found %u", index);
     224             :     }
     225        1547 :   }
     226             : };
     227             : 
     228             : template <bool checked>
     229             : struct BranchTableOperand {
     230             :   uint32_t table_count;
     231             :   const byte* start;
     232             :   const byte* table;
     233       15428 :   inline BranchTableOperand(Decoder* decoder, const byte* pc) {
     234             :     DCHECK_EQ(kExprBrTable, decoder->read_u8<checked>(pc, "opcode"));
     235      411038 :     start = pc + 1;
     236       15428 :     unsigned len = 0;
     237       15428 :     table_count = decoder->read_u32v<checked>(pc + 1, &len, "table count");
     238       22783 :     table = pc + 1 + len;
     239       15428 :   }
     240             : };
     241             : 
     242             : // A helper to iterate over a branch table.
     243             : template <bool checked>
     244             : class BranchTableIterator {
     245             :  public:
     246             :   unsigned cur_index() { return index_; }
     247      258664 :   bool has_next() { return decoder_->ok() && index_ <= table_count_; }
     248       88158 :   uint32_t next() {
     249             :     DCHECK(has_next());
     250      117447 :     index_++;
     251             :     unsigned length;
     252             :     uint32_t result =
     253       88158 :         decoder_->read_u32v<checked>(pc_, &length, "branch table entry");
     254      117447 :     pc_ += length;
     255       88158 :     return result;
     256             :   }
     257             :   // length, including the length of the {BranchTableOperand}, but not the
     258             :   // opcode.
     259       15337 :   unsigned length() {
     260       62479 :     while (has_next()) next();
     261       15337 :     return static_cast<unsigned>(pc_ - start_);
     262             :   }
     263             :   const byte* pc() { return pc_; }
     264             : 
     265             :   BranchTableIterator(Decoder* decoder, BranchTableOperand<checked>& operand)
     266             :       : decoder_(decoder),
     267             :         start_(operand.start),
     268             :         pc_(operand.table),
     269             :         index_(0),
     270      403683 :         table_count_(operand.table_count) {}
     271             : 
     272             :  private:
     273             :   Decoder* decoder_;
     274             :   const byte* start_;
     275             :   const byte* pc_;
     276             :   uint32_t index_;        // the current index.
     277             :   uint32_t table_count_;  // the count of entries, not including default.
     278             : };
     279             : 
     280             : template <bool checked>
     281             : struct MemoryAccessOperand {
     282             :   uint32_t alignment;
     283             :   uint32_t offset;
     284             :   unsigned length;
     285      168199 :   inline MemoryAccessOperand(Decoder* decoder, const byte* pc,
     286             :                              uint32_t max_alignment) {
     287             :     unsigned alignment_length;
     288      336398 :     alignment =
     289             :         decoder->read_u32v<checked>(pc + 1, &alignment_length, "alignment");
     290       28869 :     if (!CHECKED_COND(alignment <= max_alignment)) {
     291          38 :       decoder->errorf(pc + 1,
     292             :                       "invalid alignment; expected maximum alignment is %u, "
     293             :                       "actual alignment is %u",
     294             :                       max_alignment, alignment);
     295             :     }
     296             :     unsigned offset_length;
     297      336398 :     offset = decoder->read_u32v<checked>(pc + 1 + alignment_length,
     298             :                                          &offset_length, "offset");
     299      168199 :     length = alignment_length + offset_length;
     300      168199 :   }
     301             : };
     302             : 
     303             : // Operand for SIMD lane operations.
     304             : template <bool checked>
     305             : struct SimdLaneOperand {
     306             :   uint8_t lane;
     307             :   unsigned length = 1;
     308             : 
     309        5390 :   inline SimdLaneOperand(Decoder* decoder, const byte* pc) {
     310       10780 :     lane = decoder->read_u8<checked>(pc + 2, "lane");
     311             :   }
     312             : };
     313             : 
     314             : // Operand for SIMD shift operations.
     315             : template <bool checked>
     316             : struct SimdShiftOperand {
     317             :   uint8_t shift;
     318             :   unsigned length = 1;
     319             : 
     320          42 :   inline SimdShiftOperand(Decoder* decoder, const byte* pc) {
     321          84 :     shift = decoder->read_u8<checked>(pc + 2, "shift");
     322             :   }
     323             : };
     324             : 
     325             : // Operand for SIMD concatenation operations.
     326             : template <bool checked>
     327             : struct SimdConcatOperand {
     328             :   uint8_t bytes;
     329             :   unsigned length;
     330             : 
     331             :   inline SimdConcatOperand(Decoder* decoder, const byte* pc) {
     332           0 :     bytes = decoder->read_u8<checked>(pc + 2, "bytes");
     333             :     length = 1;
     334             :   }
     335             : };
     336             : 
     337             : #undef CHECKED_COND
     338             : 
     339             : }  // namespace wasm
     340             : }  // namespace internal
     341             : }  // namespace v8
     342             : 
     343             : #endif  // V8_WASM_FUNCTION_BODY_DECODER_IMPL_H_

Generated by: LCOV version 1.10