 Chromium Code Reviews
 Chromium Code Reviews Issue 2345593003:
  [wasm] Master CL for Binary 0xC changes.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master
    
  
    Issue 2345593003:
  [wasm] Master CL for Binary 0xC changes.  (Closed) 
  Base URL: https://chromium.googlesource.com/v8/v8.git@master| Index: src/wasm/ast-decoder.h | 
| diff --git a/src/wasm/ast-decoder.h b/src/wasm/ast-decoder.h | 
| index a6424f75be940e86a251c6d9a064e9e864d47dc7..32b9bd1a8aa104bf7c274ecaabbd240128a5b7c2 100644 | 
| --- a/src/wasm/ast-decoder.h | 
| +++ b/src/wasm/ast-decoder.h | 
| @@ -22,6 +22,7 @@ class WasmGraphBuilder; | 
| namespace wasm { | 
| const uint32_t kMaxNumWasmLocals = 8000000; | 
| +struct WasmGlobal; | 
| // Helpers for decoding different kinds of operands which follow bytecodes. | 
| struct LocalIndexOperand { | 
| @@ -81,39 +82,111 @@ struct ImmF64Operand { | 
| struct GlobalIndexOperand { | 
| uint32_t index; | 
| LocalType type; | 
| + const WasmGlobal* global; | 
| unsigned length; | 
| inline GlobalIndexOperand(Decoder* decoder, const byte* pc) { | 
| index = decoder->checked_read_u32v(pc, 1, &length, "global index"); | 
| + global = nullptr; | 
| type = kAstStmt; | 
| } | 
| }; | 
| +struct BlockTypeOperand { | 
| + uint32_t arity; | 
| + const byte* types; // pointer to encoded types for the block. | 
| + unsigned length; | 
| + | 
| + inline BlockTypeOperand(Decoder* decoder, const byte* pc) { | 
| + uint8_t val = decoder->checked_read_u8(pc, 1, "block type"); | 
| + LocalType type = kAstStmt; | 
| + length = 1; | 
| + arity = 0; | 
| + types = nullptr; | 
| + if (decode_local_type(val, &type)) { | 
| + arity = type == kAstStmt ? 0 : 1; | 
| + types = pc + 1; | 
| + } else { | 
| + // Handle multi-value blocks. | 
| + if (!FLAG_wasm_mv_prototype) { | 
| + decoder->error(pc, pc + 1, "invalid block arity > 1"); | 
| + return; | 
| + } | 
| + if (val != kMultivalBlock) { | 
| + decoder->error(pc, pc + 1, "invalid block type"); | 
| + return; | 
| + } | 
| + // Decode and check the types vector of the block. | 
| + unsigned len = 0; | 
| + uint32_t count = decoder->checked_read_u32v(pc, 2, &len, "block arity"); | 
| + // {count} is encoded as {arity-2}, so that a {0} count here corresponds | 
| + // to a block with 2 values. This makes invalid/redundant encodings | 
| + // impossible. | 
| + arity = count + 2; | 
| + length = 1 + len + arity; | 
| + types = pc + 1 + 1 + len; | 
| + | 
| + for (uint32_t i = 0; i < arity; i++) { | 
| + uint32_t offset = 1 + 1 + len + i; | 
| + val = decoder->checked_read_u8(pc, offset, "block type"); | 
| + decode_local_type(val, &type); | 
| 
bradnelson
2016/09/23 11:36:00
This function has a weird calling convention.
Migh
 
titzer
2016/09/23 12:07:30
Yeah, it is weird. The problem is that it can't ha
 
bradn
2016/09/23 15:18:43
Yeah true.
Many to few is hard.
 | 
| + if (type == kAstStmt) { | 
| + decoder->error(pc, pc + offset, "invalid block type"); | 
| + return; | 
| + } | 
| + } | 
| + } | 
| + } | 
| + // Decode a byte representing a local type. Return {false} if the encoded | 
| + // byte was invalid. | 
| 
bradnelson
2016/09/23 11:36:01
Rather invalid or kMultivalBlock ?
 
titzer
2016/09/23 12:07:30
Done.
 | 
| + bool decode_local_type(uint8_t val, LocalType* result) { | 
| + switch (static_cast<LocalTypeCode>(val)) { | 
| + case kLocalVoid: | 
| + *result = kAstStmt; | 
| + return true; | 
| + case kLocalI32: | 
| + *result = kAstI32; | 
| + return true; | 
| + case kLocalI64: | 
| + *result = kAstI64; | 
| + return true; | 
| + case kLocalF32: | 
| + *result = kAstF32; | 
| + return true; | 
| + case kLocalF64: | 
| + *result = kAstF64; | 
| + return true; | 
| + default: | 
| + *result = kAstStmt; | 
| + return false; | 
| + } | 
| + } | 
| + LocalType read_entry(unsigned index) { | 
| + DCHECK_LT(index, arity); | 
| + LocalType result; | 
| + CHECK(decode_local_type(types[index], &result)); | 
| + return result; | 
| + } | 
| +}; | 
| + | 
| struct Control; | 
| struct BreakDepthOperand { | 
| - uint32_t arity; | 
| uint32_t depth; | 
| Control* target; | 
| unsigned length; | 
| inline BreakDepthOperand(Decoder* decoder, const byte* pc) { | 
| - unsigned len1 = 0; | 
| - unsigned len2 = 0; | 
| - arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); | 
| - depth = decoder->checked_read_u32v(pc, 1 + len1, &len2, "break depth"); | 
| - length = len1 + len2; | 
| + depth = decoder->checked_read_u32v(pc, 1, &length, "break depth"); | 
| target = nullptr; | 
| } | 
| }; | 
| struct CallIndirectOperand { | 
| - uint32_t arity; | 
| uint32_t index; | 
| FunctionSig* sig; | 
| unsigned length; | 
| inline CallIndirectOperand(Decoder* decoder, const byte* pc) { | 
| unsigned len1 = 0; | 
| unsigned len2 = 0; | 
| - arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); | 
| index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "signature index"); | 
| length = len1 + len2; | 
| sig = nullptr; | 
| @@ -121,59 +194,32 @@ struct CallIndirectOperand { | 
| }; | 
| struct CallFunctionOperand { | 
| - uint32_t arity; | 
| uint32_t index; | 
| FunctionSig* sig; | 
| unsigned length; | 
| inline CallFunctionOperand(Decoder* decoder, const byte* pc) { | 
| unsigned len1 = 0; | 
| unsigned len2 = 0; | 
| - arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); | 
| index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "function index"); | 
| length = len1 + len2; | 
| sig = nullptr; | 
| } | 
| }; | 
| -struct CallImportOperand { | 
| - uint32_t arity; | 
| - uint32_t index; | 
| - FunctionSig* sig; | 
| - unsigned length; | 
| - inline CallImportOperand(Decoder* decoder, const byte* pc) { | 
| - unsigned len1 = 0; | 
| - unsigned len2 = 0; | 
| - arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); | 
| - index = decoder->checked_read_u32v(pc, 1 + len1, &len2, "import index"); | 
| - length = len1 + len2; | 
| - sig = nullptr; | 
| - } | 
| -}; | 
| - | 
| struct BranchTableOperand { | 
| - uint32_t arity; | 
| uint32_t table_count; | 
| + const byte* start; | 
| const byte* table; | 
| - unsigned length; | 
| inline BranchTableOperand(Decoder* decoder, const byte* pc) { | 
| + DCHECK_EQ(kExprBrTable, decoder->checked_read_u8(pc, 0, "opcode")); | 
| + start = pc + 1; | 
| unsigned len1 = 0; | 
| - unsigned len2 = 0; | 
| - arity = decoder->checked_read_u32v(pc, 1, &len1, "argument count"); | 
| - table_count = | 
| - decoder->checked_read_u32v(pc, 1 + len1, &len2, "table count"); | 
| + table_count = decoder->checked_read_u32v(pc, 1, &len1, "table count"); | 
| if (table_count > (UINT_MAX / sizeof(uint32_t)) - 1 || | 
| - len1 + len2 > UINT_MAX - (table_count + 1) * sizeof(uint32_t)) { | 
| + len1 > UINT_MAX - (table_count + 1) * sizeof(uint32_t)) { | 
| decoder->error(pc, "branch table size overflow"); | 
| } | 
| - length = len1 + len2 + (table_count + 1) * sizeof(uint32_t); | 
| - | 
| - uint32_t table_start = 1 + len1 + len2; | 
| - if (decoder->check(pc, table_start, (table_count + 1) * sizeof(uint32_t), | 
| - "expected <table entries>")) { | 
| - table = pc + table_start; | 
| - } else { | 
| - table = nullptr; | 
| - } | 
| + table = pc + 1 + len1; | 
| } | 
| inline uint32_t read_entry(Decoder* decoder, unsigned i) { | 
| DCHECK(i <= table_count); | 
| @@ -181,6 +227,43 @@ struct BranchTableOperand { | 
| } | 
| }; | 
| +// A helper to iterate over a branch table. | 
| +class BranchTableIterator { | 
| + public: | 
| + unsigned cur_index() { return index_; } | 
| + bool has_next() { return index_ <= table_count_; } | 
| + uint32_t next() { | 
| + DCHECK(has_next()); | 
| + index_++; | 
| + unsigned length = 0; | 
| + uint32_t result = | 
| + decoder_->checked_read_u32v(pc_, 0, &length, "branch table entry"); | 
| + pc_ += length; | 
| + return result; | 
| + } | 
| + // length, including the length of the {BranchTableOperand}, but not the | 
| + // opcode. | 
| + unsigned length() { | 
| + while (has_next()) next(); | 
| + return static_cast<unsigned>(pc_ - start_); | 
| + } | 
| + const byte* pc() { return pc_; } | 
| + | 
| + BranchTableIterator(Decoder* decoder, BranchTableOperand& operand) | 
| + : decoder_(decoder), | 
| + start_(operand.start), | 
| + pc_(operand.table), | 
| + index_(0), | 
| + table_count_(operand.table_count) {} | 
| + | 
| + private: | 
| + Decoder* decoder_; | 
| + const byte* start_; | 
| + const byte* pc_; | 
| + uint32_t index_; // the current index. | 
| + uint32_t table_count_; // the count of entries, not including default. | 
| +}; | 
| + | 
| struct MemoryAccessOperand { | 
| uint32_t alignment; | 
| uint32_t offset; | 
| @@ -203,15 +286,6 @@ struct MemoryAccessOperand { | 
| } | 
| }; | 
| -struct ReturnArityOperand { | 
| - uint32_t arity; | 
| - unsigned length; | 
| - | 
| - inline ReturnArityOperand(Decoder* decoder, const byte* pc) { | 
| - arity = decoder->checked_read_u32v(pc, 1, &length, "return count"); | 
| - } | 
| -}; | 
| - | 
| typedef compiler::WasmGraphBuilder TFBuilder; | 
| struct ModuleEnv; // forward declaration of module interface. | 
| @@ -284,9 +358,6 @@ BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals, | 
| // Computes the length of the opcode at the given address. | 
| unsigned OpcodeLength(const byte* pc, const byte* end); | 
| -// Computes the arity (number of sub-nodes) of the opcode at the given address. | 
| -unsigned OpcodeArity(const byte* pc, const byte* end); | 
| - | 
| // A simple forward iterator for bytecodes. | 
| class BytecodeIterator : public Decoder { | 
| public: |