| 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 #ifndef V8_WASM_AST_DECODER_H_ | 5 #ifndef V8_WASM_AST_DECODER_H_ |
| 6 #define V8_WASM_AST_DECODER_H_ | 6 #define V8_WASM_AST_DECODER_H_ |
| 7 | 7 |
| 8 #include "src/signature.h" | 8 #include "src/signature.h" |
| 9 #include "src/wasm/decoder.h" | 9 #include "src/wasm/decoder.h" |
| 10 #include "src/wasm/wasm-opcodes.h" | 10 #include "src/wasm/wasm-opcodes.h" |
| 11 #include "src/wasm/wasm-result.h" | 11 #include "src/wasm/wasm-result.h" |
| 12 | 12 |
| 13 namespace v8 { | 13 namespace v8 { |
| 14 namespace internal { | 14 namespace internal { |
| 15 | 15 |
| 16 class BitVector; // forward declaration | 16 class BitVector; // forward declaration |
| 17 | 17 |
| 18 namespace compiler { // external declarations from compiler. | 18 namespace compiler { // external declarations from compiler. |
| 19 class WasmGraphBuilder; | 19 class WasmGraphBuilder; |
| 20 } | 20 } |
| 21 | 21 |
| 22 namespace wasm { | 22 namespace wasm { |
| 23 | 23 |
| 24 const uint32_t kMaxNumWasmLocals = 8000000; | 24 const uint32_t kMaxNumWasmLocals = 8000000; |
| 25 struct WasmGlobal; |
| 25 | 26 |
| 26 // Helpers for decoding different kinds of operands which follow bytecodes. | 27 // Helpers for decoding different kinds of operands which follow bytecodes. |
| 27 struct LocalIndexOperand { | 28 struct LocalIndexOperand { |
| 28 uint32_t index; | 29 uint32_t index; |
| 29 LocalType type; | 30 LocalType type; |
| 30 unsigned length; | 31 unsigned length; |
| 31 | 32 |
| 32 inline LocalIndexOperand(Decoder* decoder, const byte* pc) { | 33 inline LocalIndexOperand(Decoder* decoder, const byte* pc) { |
| 33 index = decoder->checked_read_u32v(pc, 1, &length, "local index"); | 34 index = decoder->checked_read_u32v(pc, 1, &length, "local index"); |
| 34 type = kAstStmt; | 35 type = kAstStmt; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 unsigned length; | 75 unsigned length; |
| 75 inline ImmF64Operand(Decoder* decoder, const byte* pc) { | 76 inline ImmF64Operand(Decoder* decoder, const byte* pc) { |
| 76 value = bit_cast<double>(decoder->checked_read_u64(pc, 1, "immf64")); | 77 value = bit_cast<double>(decoder->checked_read_u64(pc, 1, "immf64")); |
| 77 length = 8; | 78 length = 8; |
| 78 } | 79 } |
| 79 }; | 80 }; |
| 80 | 81 |
| 81 struct GlobalIndexOperand { | 82 struct GlobalIndexOperand { |
| 82 uint32_t index; | 83 uint32_t index; |
| 83 LocalType type; | 84 LocalType type; |
| 85 const WasmGlobal* global; |
| 84 unsigned length; | 86 unsigned length; |
| 85 | 87 |
| 86 inline GlobalIndexOperand(Decoder* decoder, const byte* pc) { | 88 inline GlobalIndexOperand(Decoder* decoder, const byte* pc) { |
| 87 index = decoder->checked_read_u32v(pc, 1, &length, "global index"); | 89 index = decoder->checked_read_u32v(pc, 1, &length, "global index"); |
| 90 global = nullptr; |
| 88 type = kAstStmt; | 91 type = kAstStmt; |
| 89 } | 92 } |
| 90 }; | 93 }; |
| 91 | 94 |
| 95 struct BlockTypeOperand { |
| 96 uint32_t arity; |
| 97 const byte* types; |
| 98 unsigned length; |
| 99 |
| 100 inline BlockTypeOperand(Decoder* decoder, const byte* pc) { |
| 101 uint8_t val = decoder->checked_read_u8(pc, 1, "block type"); |
| 102 LocalType type; |
| 103 length = 1; |
| 104 arity = 0; |
| 105 types = nullptr; |
| 106 if (decode_local_type(val, &type)) { |
| 107 arity = type == kAstStmt ? 0 : 1; |
| 108 types = pc + 1; |
| 109 } else { |
| 110 if (!FLAG_wasm_mv_prototype) { |
| 111 decoder->error(pc, pc + 1, "invalid block arity > 1"); |
| 112 return; |
| 113 } |
| 114 if (val != kMultivalBlock) { |
| 115 decoder->error(pc, pc + 1, "invalid block type"); |
| 116 return; |
| 117 } |
| 118 unsigned len = 0; |
| 119 uint32_t count = decoder->checked_read_u32v(pc, 2, &len, "block arity"); |
| 120 arity = count + 2; |
| 121 length = 1 + len + arity; |
| 122 types = pc + 1 + 1 + len; |
| 123 |
| 124 for (uint32_t i = 0; i < arity; i++) { |
| 125 uint32_t offset = 1 + 1 + len + i; |
| 126 val = decoder->checked_read_u8(pc, offset, "block type"); |
| 127 decode_local_type(val, &type); |
| 128 if (type == kAstStmt) { |
| 129 decoder->error(pc, pc + offset, "invalid block type"); |
| 130 return; |
| 131 } |
| 132 } |
| 133 } |
| 134 } |
| 135 bool decode_local_type(uint8_t val, LocalType* result) { |
| 136 switch (static_cast<LocalTypeCode>(val)) { |
| 137 case kLocalVoid: |
| 138 *result = kAstStmt; |
| 139 return true; |
| 140 case kLocalI32: |
| 141 *result = kAstI32; |
| 142 return true; |
| 143 case kLocalI64: |
| 144 *result = kAstI64; |
| 145 return true; |
| 146 case kLocalF32: |
| 147 *result = kAstF32; |
| 148 return true; |
| 149 case kLocalF64: |
| 150 *result = kAstF64; |
| 151 return true; |
| 152 default: |
| 153 *result = kAstStmt; |
| 154 return false; |
| 155 } |
| 156 } |
| 157 LocalType read_entry(unsigned index) { |
| 158 DCHECK_LT(index, arity); |
| 159 LocalType result; |
| 160 CHECK(decode_local_type(types[index], &result)); |
| 161 return result; |
| 162 } |
| 163 }; |
| 164 |
| 92 struct Control; | 165 struct Control; |
| 93 struct BreakDepthOperand { | 166 struct BreakDepthOperand { |
| 94 uint32_t arity; | |
| 95 uint32_t depth; | 167 uint32_t depth; |
| 96 Control* target; | 168 Control* target; |
| 97 unsigned length; | 169 unsigned length; |
| 98 inline BreakDepthOperand(Decoder* decoder, const byte* pc) { | 170 inline BreakDepthOperand(Decoder* decoder, const byte* pc) { |
| 99 unsigned len1 = 0; | 171 depth = decoder->checked_read_u32v(pc, 1, &length, "break depth"); |
| 100 unsigned len2 = 0; | |
| 101 arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); | |
| 102 depth = decoder->checked_read_u32v(pc, 1 + len1, &len2, "break depth"); | |
| 103 length = len1 + len2; | |
| 104 target = nullptr; | 172 target = nullptr; |
| 105 } | 173 } |
| 106 }; | 174 }; |
| 107 | 175 |
| 108 struct CallIndirectOperand { | 176 struct CallIndirectOperand { |
| 109 uint32_t arity; | |
| 110 uint32_t index; | 177 uint32_t index; |
| 111 FunctionSig* sig; | 178 FunctionSig* sig; |
| 112 unsigned length; | 179 unsigned length; |
| 113 inline CallIndirectOperand(Decoder* decoder, const byte* pc) { | 180 inline CallIndirectOperand(Decoder* decoder, const byte* pc) { |
| 114 unsigned len1 = 0; | 181 unsigned len1 = 0; |
| 115 unsigned len2 = 0; | 182 unsigned len2 = 0; |
| 116 arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); | |
| 117 index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "signature index"); | 183 index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "signature index"); |
| 118 length = len1 + len2; | 184 length = len1 + len2; |
| 119 sig = nullptr; | 185 sig = nullptr; |
| 120 } | 186 } |
| 121 }; | 187 }; |
| 122 | 188 |
| 123 struct CallFunctionOperand { | 189 struct CallFunctionOperand { |
| 124 uint32_t arity; | |
| 125 uint32_t index; | 190 uint32_t index; |
| 126 FunctionSig* sig; | 191 FunctionSig* sig; |
| 127 unsigned length; | 192 unsigned length; |
| 128 inline CallFunctionOperand(Decoder* decoder, const byte* pc) { | 193 inline CallFunctionOperand(Decoder* decoder, const byte* pc) { |
| 129 unsigned len1 = 0; | 194 unsigned len1 = 0; |
| 130 unsigned len2 = 0; | 195 unsigned len2 = 0; |
| 131 arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); | |
| 132 index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "function index"); | 196 index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "function index"); |
| 133 length = len1 + len2; | 197 length = len1 + len2; |
| 134 sig = nullptr; | 198 sig = nullptr; |
| 135 } | 199 } |
| 136 }; | 200 }; |
| 137 | 201 |
| 138 struct CallImportOperand { | |
| 139 uint32_t arity; | |
| 140 uint32_t index; | |
| 141 FunctionSig* sig; | |
| 142 unsigned length; | |
| 143 inline CallImportOperand(Decoder* decoder, const byte* pc) { | |
| 144 unsigned len1 = 0; | |
| 145 unsigned len2 = 0; | |
| 146 arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); | |
| 147 index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "import index"); | |
| 148 length = len1 + len2; | |
| 149 sig = nullptr; | |
| 150 } | |
| 151 }; | |
| 152 | |
| 153 struct BranchTableOperand { | 202 struct BranchTableOperand { |
| 154 uint32_t arity; | |
| 155 uint32_t table_count; | 203 uint32_t table_count; |
| 156 const byte* table; | 204 const byte* table; |
| 157 unsigned length; | 205 unsigned length; |
| 158 inline BranchTableOperand(Decoder* decoder, const byte* pc) { | 206 inline BranchTableOperand(Decoder* decoder, const byte* pc) { |
| 159 unsigned len1 = 0; | 207 unsigned len1 = 0; |
| 160 unsigned len2 = 0; | 208 table_count = decoder->checked_read_u32v(pc, 1, &len1, "table count"); |
| 161 arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); | |
| 162 table_count = | |
| 163 decoder->checked_read_u32v(pc, 1 + len1, &len2, "table count"); | |
| 164 if (table_count > (UINT_MAX / sizeof(uint32_t)) - 1 || | 209 if (table_count > (UINT_MAX / sizeof(uint32_t)) - 1 || |
| 165 len1 + len2 > UINT_MAX - (table_count + 1) * sizeof(uint32_t)) { | 210 len1 > UINT_MAX - (table_count + 1) * sizeof(uint32_t)) { |
| 166 decoder->error(pc, "branch table size overflow"); | 211 decoder->error(pc, "branch table size overflow"); |
| 167 } | 212 } |
| 168 length = len1 + len2 + (table_count + 1) * sizeof(uint32_t); | 213 length = len1 + (table_count + 1) * sizeof(uint32_t); |
| 169 | 214 |
| 170 uint32_t table_start = 1 + len1 + len2; | 215 uint32_t table_start = 1 + len1; |
| 171 if (decoder->check(pc, table_start, (table_count + 1) * sizeof(uint32_t), | 216 if (decoder->check(pc, table_start, (table_count + 1) * sizeof(uint32_t), |
| 172 "expected <table entries>")) { | 217 "expected <table entries>")) { |
| 173 table = pc + table_start; | 218 table = pc + table_start; |
| 174 } else { | 219 } else { |
| 175 table = nullptr; | 220 table = nullptr; |
| 176 } | 221 } |
| 177 } | 222 } |
| 178 inline uint32_t read_entry(Decoder* decoder, unsigned i) { | 223 inline uint32_t read_entry(Decoder* decoder, unsigned i) { |
| 179 DCHECK(i <= table_count); | 224 DCHECK(i <= table_count); |
| 180 return table ? decoder->read_u32(table + i * sizeof(uint32_t)) : 0; | 225 return table ? decoder->read_u32(table + i * sizeof(uint32_t)) : 0; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 196 "actual alignment is %u", | 241 "actual alignment is %u", |
| 197 max_alignment, alignment); | 242 max_alignment, alignment); |
| 198 } | 243 } |
| 199 unsigned offset_length; | 244 unsigned offset_length; |
| 200 offset = decoder->checked_read_u32v(pc, 1 + alignment_length, | 245 offset = decoder->checked_read_u32v(pc, 1 + alignment_length, |
| 201 &offset_length, "offset"); | 246 &offset_length, "offset"); |
| 202 length = alignment_length + offset_length; | 247 length = alignment_length + offset_length; |
| 203 } | 248 } |
| 204 }; | 249 }; |
| 205 | 250 |
| 206 struct ReturnArityOperand { | |
| 207 uint32_t arity; | |
| 208 unsigned length; | |
| 209 | |
| 210 inline ReturnArityOperand(Decoder* decoder, const byte* pc) { | |
| 211 arity = decoder->checked_read_u32v(pc, 1, &length, "return count"); | |
| 212 } | |
| 213 }; | |
| 214 | |
| 215 typedef compiler::WasmGraphBuilder TFBuilder; | 251 typedef compiler::WasmGraphBuilder TFBuilder; |
| 216 struct ModuleEnv; // forward declaration of module interface. | 252 struct ModuleEnv; // forward declaration of module interface. |
| 217 | 253 |
| 218 // All of the various data structures necessary to decode a function body. | 254 // All of the various data structures necessary to decode a function body. |
| 219 struct FunctionBody { | 255 struct FunctionBody { |
| 220 ModuleEnv* module; // module environment | 256 ModuleEnv* module; // module environment |
| 221 FunctionSig* sig; // function signature | 257 FunctionSig* sig; // function signature |
| 222 const byte* base; // base of the module bytes, for error reporting | 258 const byte* base; // base of the module bytes, for error reporting |
| 223 const byte* start; // start of the function body | 259 const byte* start; // start of the function body |
| 224 const byte* end; // end of the function body | 260 const byte* end; // end of the function body |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 278 : decls_encoded_size(0), total_local_count(0), local_types(zone) {} | 314 : decls_encoded_size(0), total_local_count(0), local_types(zone) {} |
| 279 }; | 315 }; |
| 280 | 316 |
| 281 bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start, const byte* end); | 317 bool DecodeLocalDecls(AstLocalDecls& decls, const byte* start, const byte* end); |
| 282 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 318 BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, |
| 283 const byte* start, const byte* end); | 319 const byte* start, const byte* end); |
| 284 | 320 |
| 285 // Computes the length of the opcode at the given address. | 321 // Computes the length of the opcode at the given address. |
| 286 unsigned OpcodeLength(const byte* pc, const byte* end); | 322 unsigned OpcodeLength(const byte* pc, const byte* end); |
| 287 | 323 |
| 288 // Computes the arity (number of sub-nodes) of the opcode at the given address. | |
| 289 unsigned OpcodeArity(const byte* pc, const byte* end); | |
| 290 | |
| 291 // A simple forward iterator for bytecodes. | 324 // A simple forward iterator for bytecodes. |
| 292 class BytecodeIterator : public Decoder { | 325 class BytecodeIterator : public Decoder { |
| 293 public: | 326 public: |
| 294 // If one wants to iterate over the bytecode without looking at {pc_offset()}. | 327 // If one wants to iterate over the bytecode without looking at {pc_offset()}. |
| 295 class iterator { | 328 class iterator { |
| 296 public: | 329 public: |
| 297 inline iterator& operator++() { | 330 inline iterator& operator++() { |
| 298 DCHECK_LT(ptr_, end_); | 331 DCHECK_LT(ptr_, end_); |
| 299 ptr_ += OpcodeLength(ptr_, end_); | 332 ptr_ += OpcodeLength(ptr_, end_); |
| 300 return *this; | 333 return *this; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 } | 372 } |
| 340 | 373 |
| 341 bool has_next() { return pc_ < end_; } | 374 bool has_next() { return pc_ < end_; } |
| 342 }; | 375 }; |
| 343 | 376 |
| 344 } // namespace wasm | 377 } // namespace wasm |
| 345 } // namespace internal | 378 } // namespace internal |
| 346 } // namespace v8 | 379 } // namespace v8 |
| 347 | 380 |
| 348 #endif // V8_WASM_AST_DECODER_H_ | 381 #endif // V8_WASM_AST_DECODER_H_ |
| OLD | NEW |