LCOV - code coverage report
Current view: top level - src/wasm - function-body-decoder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 390 479 81.4 %
Date: 2017-10-20 Functions: 66 72 91.7 %

          Line data    Source code
       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
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/signature.h"
       6             : 
       7             : #include "src/base/platform/elapsed-timer.h"
       8             : #include "src/flags.h"
       9             : #include "src/handles.h"
      10             : #include "src/objects-inl.h"
      11             : #include "src/zone/zone-containers.h"
      12             : 
      13             : #include "src/wasm/decoder.h"
      14             : #include "src/wasm/function-body-decoder-impl.h"
      15             : #include "src/wasm/function-body-decoder.h"
      16             : #include "src/wasm/wasm-limits.h"
      17             : #include "src/wasm/wasm-module.h"
      18             : #include "src/wasm/wasm-opcodes.h"
      19             : 
      20             : #include "src/ostreams.h"
      21             : 
      22             : #include "src/compiler/wasm-compiler.h"
      23             : 
      24             : namespace v8 {
      25             : namespace internal {
      26             : namespace wasm {
      27             : 
      28             : namespace {
      29             : 
      30             : template <typename T>
      31             : Vector<T> vec2vec(ZoneVector<T>& vec) {
      32         140 :   return Vector<T>(vec.data(), vec.size());
      33             : }
      34             : 
      35             : // An SsaEnv environment carries the current local variable renaming
      36             : // as well as the current effect and control dependency in the TF graph.
      37             : // It maintains a control state that tracks whether the environment
      38             : // is reachable, has reached a control end, or has been merged.
      39             : struct SsaEnv {
      40             :   enum State { kControlEnd, kUnreachable, kReached, kMerged };
      41             : 
      42             :   State state;
      43             :   TFNode* control;
      44             :   TFNode* effect;
      45             :   TFNode* mem_size;
      46             :   TFNode* mem_start;
      47             :   TFNode** locals;
      48             : 
      49     2865827 :   bool go() { return state >= kReached; }
      50             :   void Kill(State new_state = kControlEnd) {
      51     1691442 :     state = new_state;
      52     1691442 :     locals = nullptr;
      53     1691442 :     control = nullptr;
      54     1691442 :     effect = nullptr;
      55     1691442 :     mem_size = nullptr;
      56     1691442 :     mem_start = nullptr;
      57             :   }
      58             :   void SetNotMerged() {
      59      175112 :     if (state == kMerged) state = kReached;
      60             :   }
      61             : };
      62             : 
      63             : #define BUILD(func, ...)                                            \
      64             :   ([&] {                                                            \
      65             :     DCHECK(ssa_env_->go());                                         \
      66             :     DCHECK(decoder->ok());                                          \
      67             :     return CheckForException(decoder, builder_->func(__VA_ARGS__)); \
      68             :   })()
      69             : 
      70             : constexpr uint32_t kNullCatch = static_cast<uint32_t>(-1);
      71             : 
      72             : class WasmGraphBuildingInterface {
      73             :  public:
      74             :   static constexpr wasm::Decoder::ValidateFlag validate =
      75             :       wasm::Decoder::kValidate;
      76             :   using Decoder = WasmFullDecoder<validate, WasmGraphBuildingInterface>;
      77             : 
      78             :   struct Value : public ValueWithNamedConstructors<Value> {
      79             :     TFNode* node;
      80             :   };
      81             : 
      82             :   struct TryInfo : public ZoneObject {
      83             :     SsaEnv* catch_env;
      84             :     TFNode* exception;
      85             : 
      86          70 :     explicit TryInfo(SsaEnv* c) : catch_env(c), exception(nullptr) {}
      87             :   };
      88             : 
      89             :   struct Control : public ControlWithNamedConstructors<Control, Value> {
      90             :     SsaEnv* end_env;         // end environment for the construct.
      91             :     SsaEnv* false_env;       // false environment (only for if).
      92             :     TryInfo* try_info;       // information used for compiling try statements.
      93             :     int32_t previous_catch;  // previous Control (on the stack) with a catch.
      94             :   };
      95             : 
      96      234351 :   explicit WasmGraphBuildingInterface(TFBuilder* builder) : builder_(builder) {}
      97             : 
      98      468877 :   void StartFunction(Decoder* decoder) {
      99             :     SsaEnv* ssa_env =
     100      234441 :         reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
     101             :     uint32_t num_locals = decoder->NumLocals();
     102             :     // The '+ 2' here is to accommodate for mem_size and mem_start nodes.
     103      234456 :     uint32_t env_count = num_locals + 2;
     104      234456 :     size_t size = sizeof(TFNode*) * env_count;
     105      234456 :     ssa_env->state = SsaEnv::kReached;
     106             :     ssa_env->locals =
     107             :         size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
     108      468892 :                  : nullptr;
     109             : 
     110             :     // The first '+ 1' is needed by TF Start node, the second '+ 1' is for the
     111             :     // wasm_context parameter.
     112             :     TFNode* start = builder_->Start(
     113      654877 :         static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
     114             :     // Initialize the wasm_context (the paramater at index 0).
     115             :     builder_->set_wasm_context(
     116      234443 :         builder_->Param(compiler::kWasmContextParameterIndex));
     117             :     // Initialize local variables. Parameters are shifted by 1 because of the
     118             :     // the wasm_context.
     119             :     uint32_t index = 0;
     120     1075239 :     for (; index < decoder->sig_->parameter_count(); ++index) {
     121      186023 :       ssa_env->locals[index] = builder_->Param(index + 1);
     122             :     }
     123      244685 :     while (index < num_locals) {
     124             :       ValueType type = decoder->GetLocalType(index);
     125       10287 :       TFNode* node = DefaultValue(type);
     126      113516 :       while (index < num_locals && decoder->GetLocalType(index) == type) {
     127             :         // Do a whole run of like-typed locals at a time.
     128       45194 :         ssa_env->locals[index++] = node;
     129             :       }
     130             :     }
     131      234398 :     ssa_env->effect = start;
     132      234398 :     ssa_env->control = start;
     133             :     // Initialize effect and control before loading the context.
     134      234398 :     builder_->set_effect_ptr(&ssa_env->effect);
     135      234398 :     builder_->set_control_ptr(&ssa_env->control);
     136             :     // Always load mem_size and mem_start from the WasmContext into the ssa.
     137      234398 :     LoadContextIntoSsa(ssa_env);
     138             :     SetEnv(ssa_env);
     139      234442 :   }
     140             : 
     141             :   // Reload the wasm context variables from the WasmContext structure attached
     142             :   // to the memory object into the Ssa Environment. This does not automatically
     143             :   // set the mem_size_ and mem_start_ pointers in WasmGraphBuilder.
     144      822597 :   void LoadContextIntoSsa(SsaEnv* ssa_env) {
     145     1233917 :     if (!ssa_env || !ssa_env->go()) return;
     146             :     DCHECK_NOT_NULL(builder_->Effect());
     147             :     DCHECK_NOT_NULL(builder_->Control());
     148      411338 :     ssa_env->mem_size = builder_->LoadMemSize();
     149      411316 :     ssa_env->mem_start = builder_->LoadMemStart();
     150             :   }
     151             : 
     152      468424 :   void StartFunctionBody(Decoder* decoder, Control* block) {
     153      234212 :     SsaEnv* break_env = ssa_env_;
     154      234212 :     SetEnv(Steal(decoder->zone(), break_env));
     155      234228 :     block->end_env = break_env;
     156      234228 :   }
     157             : 
     158             :   void FinishFunction(Decoder* decoder) {
     159      228618 :     builder_->PatchInStackCheckIfNeeded();
     160             :   }
     161             : 
     162             :   void OnFirstError(Decoder* decoder) {}
     163             : 
     164      483294 :   void Block(Decoder* decoder, Control* block) {
     165             :     // The break environment is the outer environment.
     166      241647 :     block->end_env = ssa_env_;
     167      483294 :     SetEnv(Steal(decoder->zone(), ssa_env_));
     168      241645 :   }
     169             : 
     170       23246 :   void Loop(Decoder* decoder, Control* block) {
     171       23246 :     SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
     172       11623 :     block->end_env = finish_try_env;
     173             :     // The continue environment is the inner environment.
     174       11623 :     SetEnv(PrepareForLoop(decoder, finish_try_env));
     175       11624 :     ssa_env_->SetNotMerged();
     176       11624 :   }
     177             : 
     178         210 :   void Try(Decoder* decoder, Control* block) {
     179          70 :     SsaEnv* outer_env = ssa_env_;
     180          70 :     SsaEnv* catch_env = Split(decoder, outer_env);
     181             :     // Mark catch environment as unreachable, since only accessable
     182             :     // through catch unwinding (i.e. landing pads).
     183          70 :     catch_env->state = SsaEnv::kUnreachable;
     184          70 :     SsaEnv* try_env = Steal(decoder->zone(), outer_env);
     185             :     SetEnv(try_env);
     186             :     TryInfo* try_info = new (decoder->zone()) TryInfo(catch_env);
     187          70 :     block->end_env = outer_env;
     188          70 :     block->try_info = try_info;
     189          70 :     block->previous_catch = current_catch_;
     190          70 :     current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
     191          70 :   }
     192             : 
     193       62057 :   void If(Decoder* decoder, const Value& cond, Control* if_block) {
     194       62057 :     TFNode* if_true = nullptr;
     195       62057 :     TFNode* if_false = nullptr;
     196      186171 :     if (ssa_env_->go()) BUILD(BranchNoHint, cond.node, &if_true, &if_false);
     197       62060 :     SsaEnv* end_env = ssa_env_;
     198      124120 :     SsaEnv* false_env = Split(decoder, ssa_env_);
     199       62060 :     false_env->control = if_false;
     200      124120 :     SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
     201       62055 :     true_env->control = if_true;
     202       62055 :     if_block->end_env = end_env;
     203       62055 :     if_block->false_env = false_env;
     204             :     SetEnv(true_env);
     205       62055 :   }
     206             : 
     207             :   void FallThruTo(Decoder* decoder, Control* c) {
     208             :     DCHECK(!c->is_loop());
     209      135591 :     MergeValuesInto(decoder, c);
     210             :   }
     211             : 
     212      542063 :   void PopControl(Decoder* decoder, Control* block) {
     213     1084126 :     if (!block->is_loop()) SetEnv(block->end_env);
     214      542063 :     if (block->is_onearmed_if()) {
     215       38193 :       Goto(decoder, block->false_env, block->end_env);
     216             :     }
     217      542063 :   }
     218             : 
     219             :   void EndControl(Decoder* decoder, Control* block) { ssa_env_->Kill(); }
     220             : 
     221             :   void UnOp(Decoder* decoder, WasmOpcode opcode, FunctionSig* sig,
     222             :             const Value& value, Value* result) {
     223     1101566 :     result->node = BUILD(Unop, opcode, value.node, decoder->position());
     224             :   }
     225             : 
     226             :   void BinOp(Decoder* decoder, WasmOpcode opcode, FunctionSig* sig,
     227             :              const Value& lhs, const Value& rhs, Value* result) {
     228             :     result->node =
     229     2905520 :         BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
     230             :   }
     231             : 
     232             :   void I32Const(Decoder* decoder, Value* result, int32_t value) {
     233      967330 :     result->node = builder_->Int32Constant(value);
     234             :   }
     235             : 
     236             :   void I64Const(Decoder* decoder, Value* result, int64_t value) {
     237       46084 :     result->node = builder_->Int64Constant(value);
     238             :   }
     239             : 
     240             :   void F32Const(Decoder* decoder, Value* result, float value) {
     241      146674 :     result->node = builder_->Float32Constant(value);
     242             :   }
     243             : 
     244             :   void F64Const(Decoder* decoder, Value* result, double value) {
     245      157475 :     result->node = builder_->Float64Constant(value);
     246             :   }
     247             : 
     248             :   void Drop(Decoder* decoder, const Value& value) {}
     249             : 
     250      288483 :   void DoReturn(Decoder* decoder, Vector<Value> values, bool implicit) {
     251      288483 :     if (implicit) {
     252             :       DCHECK_EQ(1, decoder->control_depth());
     253      151574 :       SetEnv(decoder->control_at(0)->end_env);
     254             :     }
     255      288483 :     size_t num_values = values.size();
     256      288499 :     TFNode** buffer = GetNodes(values);
     257      433460 :     for (size_t i = 0; i < num_values; ++i) {
     258      289922 :       buffer[i] = values[i].node;
     259             :     }
     260      576996 :     BUILD(Return, static_cast<unsigned>(values.size()), buffer);
     261      288477 :   }
     262             : 
     263             :   void GetLocal(Decoder* decoder, Value* result,
     264             :                 const LocalIndexOperand<validate>& operand) {
     265      567861 :     if (!ssa_env_->locals) return;  // unreachable
     266      567847 :     result->node = ssa_env_->locals[operand.index];
     267             :   }
     268             : 
     269             :   void SetLocal(Decoder* decoder, const Value& value,
     270             :                 const LocalIndexOperand<validate>& operand) {
     271       48441 :     if (!ssa_env_->locals) return;  // unreachable
     272       48443 :     ssa_env_->locals[operand.index] = value.node;
     273             :   }
     274             : 
     275             :   void TeeLocal(Decoder* decoder, const Value& value, Value* result,
     276             :                 const LocalIndexOperand<validate>& operand) {
     277      131961 :     result->node = value.node;
     278      131961 :     if (!ssa_env_->locals) return;  // unreachable
     279      131961 :     ssa_env_->locals[operand.index] = value.node;
     280             :   }
     281             : 
     282             :   void GetGlobal(Decoder* decoder, Value* result,
     283             :                  const GlobalIndexOperand<validate>& operand) {
     284       39322 :     result->node = BUILD(GetGlobal, operand.index);
     285             :   }
     286             : 
     287             :   void SetGlobal(Decoder* decoder, const Value& value,
     288             :                  const GlobalIndexOperand<validate>& operand) {
     289       23892 :     BUILD(SetGlobal, operand.index, value.node);
     290             :   }
     291             : 
     292             :   void Unreachable(Decoder* decoder) {
     293      389997 :     BUILD(Unreachable, decoder->position());
     294             :   }
     295             : 
     296         398 :   void Select(Decoder* decoder, const Value& cond, const Value& fval,
     297             :               const Value& tval, Value* result) {
     298             :     TFNode* controls[2];
     299         797 :     BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
     300         800 :     TFNode* merge = BUILD(Merge, 2, controls);
     301         397 :     TFNode* vals[2] = {tval.node, fval.node};
     302         797 :     TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
     303         400 :     result->node = phi;
     304         400 :     ssa_env_->control = merge;
     305         400 :   }
     306             : 
     307      492372 :   void BreakTo(Decoder* decoder, Control* target) {
     308      492372 :     if (target->is_loop()) {
     309       11146 :       Goto(decoder, ssa_env_, target->end_env);
     310             :     } else {
     311      481226 :       MergeValuesInto(decoder, target);
     312             :     }
     313      492369 :   }
     314             : 
     315      163490 :   void BrIf(Decoder* decoder, const Value& cond, Control* target) {
     316      163490 :     SsaEnv* fenv = ssa_env_;
     317      163490 :     SsaEnv* tenv = Split(decoder, fenv);
     318      163488 :     fenv->SetNotMerged();
     319      326976 :     BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
     320      163491 :     ssa_env_ = tenv;
     321      163491 :     BreakTo(decoder, target);
     322      163486 :     ssa_env_ = fenv;
     323      163486 :   }
     324             : 
     325       13610 :   void BrTable(Decoder* decoder, const BranchTableOperand<validate>& operand,
     326             :                const Value& key) {
     327       13610 :     if (operand.table_count == 0) {
     328             :       // Only a default target. Do the equivalent of br.
     329       14146 :       uint32_t target = BranchTableIterator<validate>(decoder, operand).next();
     330        1072 :       BreakTo(decoder, decoder->control_at(target));
     331       14146 :       return;
     332             :     }
     333             : 
     334       13074 :     SsaEnv* break_env = ssa_env_;
     335             :     // Build branches to the various blocks based on the table.
     336       26148 :     TFNode* sw = BUILD(Switch, operand.table_count + 1, key.node);
     337             : 
     338       26148 :     SsaEnv* copy = Steal(decoder->zone(), break_env);
     339       13075 :     ssa_env_ = copy;
     340       13075 :     BranchTableIterator<validate> iterator(decoder, operand);
     341      310844 :     while (iterator.has_next()) {
     342      297770 :       uint32_t i = iterator.cur_index();
     343      297770 :       uint32_t target = iterator.next();
     344      297770 :       ssa_env_ = Split(decoder, copy);
     345      634761 :       ssa_env_->control = (i == operand.table_count) ? BUILD(IfDefault, sw)
     346      880235 :                                                      : BUILD(IfValue, i, sw);
     347      595538 :       BreakTo(decoder, decoder->control_at(target));
     348             :     }
     349             :     DCHECK(decoder->ok());
     350       13074 :     ssa_env_ = break_env;
     351             :   }
     352             : 
     353             :   void Else(Decoder* decoder, Control* if_block) {
     354             :     SetEnv(if_block->false_env);
     355             :   }
     356             : 
     357             :   void LoadMem(Decoder* decoder, ValueType type, MachineType mem_type,
     358             :                const MemoryAccessOperand<validate>& operand, const Value& index,
     359             :                Value* result) {
     360      132323 :     result->node = BUILD(LoadMem, type, mem_type, index.node, operand.offset,
     361       33081 :                          operand.alignment, decoder->position());
     362             :   }
     363             : 
     364             :   void StoreMem(Decoder* decoder, ValueType type, MachineType mem_type,
     365             :                 const MemoryAccessOperand<validate>& operand,
     366             :                 const Value& index, const Value& value) {
     367       58251 :     BUILD(StoreMem, mem_type, index.node, operand.offset, operand.alignment,
     368       14567 :           value.node, decoder->position(), type);
     369             :   }
     370             : 
     371             :   void CurrentMemoryPages(Decoder* decoder, Value* result) {
     372        1136 :     result->node = BUILD(CurrentMemoryPages);
     373             :   }
     374             : 
     375        1106 :   void GrowMemory(Decoder* decoder, const Value& value, Value* result) {
     376        2212 :     result->node = BUILD(GrowMemory, value.node);
     377             :     // Reload mem_size and mem_start after growing memory.
     378        1106 :     LoadContextIntoSsa(ssa_env_);
     379        1106 :   }
     380             : 
     381             :   void CallDirect(Decoder* decoder,
     382             :                   const CallFunctionOperand<validate>& operand,
     383             :                   const Value args[], Value returns[]) {
     384      172532 :     DoCall(decoder, nullptr, operand, args, returns, false);
     385             :   }
     386             : 
     387             :   void CallIndirect(Decoder* decoder, const Value& index,
     388             :                     const CallIndirectOperand<validate>& operand,
     389             :                     const Value args[], Value returns[]) {
     390        3290 :     DoCall(decoder, index.node, operand, args, returns, true);
     391             :   }
     392             : 
     393        2694 :   void SimdOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args,
     394             :               Value* result) {
     395        2694 :     TFNode** inputs = GetNodes(args);
     396        5388 :     TFNode* node = BUILD(SimdOp, opcode, inputs);
     397        2694 :     if (result) result->node = node;
     398        2694 :   }
     399             : 
     400       12654 :   void SimdLaneOp(Decoder* decoder, WasmOpcode opcode,
     401             :                   const SimdLaneOperand<validate> operand, Vector<Value> inputs,
     402             :                   Value* result) {
     403       12654 :     TFNode** nodes = GetNodes(inputs);
     404       25308 :     result->node = BUILD(SimdLaneOp, opcode, operand.lane, nodes);
     405       12654 :   }
     406             : 
     407             :   void SimdShiftOp(Decoder* decoder, WasmOpcode opcode,
     408             :                    const SimdShiftOperand<validate> operand, const Value& input,
     409             :                    Value* result) {
     410          72 :     TFNode* inputs[] = {input.node};
     411         144 :     result->node = BUILD(SimdShiftOp, opcode, operand.shift, inputs);
     412             :   }
     413             : 
     414             :   void Simd8x16ShuffleOp(Decoder* decoder,
     415             :                          const Simd8x16ShuffleOperand<validate>& operand,
     416             :                          const Value& input0, const Value& input1,
     417             :                          Value* result) {
     418           0 :     TFNode* input_nodes[] = {input0.node, input1.node};
     419           0 :     result->node = BUILD(Simd8x16ShuffleOp, operand.shuffle, input_nodes);
     420             :   }
     421             : 
     422             :   TFNode* GetExceptionTag(Decoder* decoder,
     423             :                           const ExceptionIndexOperand<validate>& operand) {
     424             :     // TODO(kschimpf): Need to get runtime exception tag values. This
     425             :     // code only handles non-imported/exported exceptions.
     426             :     return BUILD(Int32Constant, operand.index);
     427             :   }
     428             : 
     429         140 :   void Throw(Decoder* decoder, const ExceptionIndexOperand<validate>& operand,
     430         380 :              Control* block, const Vector<Value>& value_args) {
     431             :     int count = value_args.length();
     432         140 :     ZoneVector<TFNode*> args(count, decoder->zone());
     433         100 :     for (int i = 0; i < count; ++i) {
     434         200 :       args[i] = value_args[i].node;
     435             :     }
     436         420 :     BUILD(Throw, operand.index, operand.exception, vec2vec(args));
     437         140 :     Unreachable(decoder);
     438             :     EndControl(decoder, block);
     439         140 :   }
     440             : 
     441          70 :   void CatchException(Decoder* decoder,
     442             :                       const ExceptionIndexOperand<validate>& operand,
     443          70 :                       Control* block, Vector<Value> values) {
     444             :     DCHECK(block->is_try_catch());
     445          70 :     current_catch_ = block->previous_catch;
     446          70 :     SsaEnv* catch_env = block->try_info->catch_env;
     447             :     SetEnv(catch_env);
     448             : 
     449          70 :     TFNode* compare_i32 = nullptr;
     450          70 :     if (block->try_info->exception == nullptr) {
     451             :       // Catch not applicable, no possible throws in the try
     452             :       // block. Create dummy code so that body of catch still
     453             :       // compiles. Note: This only happens because the current
     454             :       // implementation only builds a landing pad if some node in the
     455             :       // try block can (possibly) throw.
     456             :       //
     457             :       // TODO(kschimpf): Always generate a landing pad for a try block.
     458           0 :       compare_i32 = BUILD(Int32Constant, 0);
     459             :     } else {
     460             :       // Get the exception and see if wanted exception.
     461         140 :       TFNode* caught_tag = BUILD(GetExceptionRuntimeId);
     462             :       TFNode* exception_tag =
     463         140 :           BUILD(ConvertExceptionTagToRuntimeId, operand.index);
     464         140 :       compare_i32 = BUILD(Binop, kExprI32Eq, caught_tag, exception_tag);
     465             :     }
     466             : 
     467          70 :     TFNode* if_catch = nullptr;
     468          70 :     TFNode* if_no_catch = nullptr;
     469         140 :     BUILD(BranchNoHint, compare_i32, &if_catch, &if_no_catch);
     470             : 
     471         140 :     SsaEnv* if_no_catch_env = Split(decoder, ssa_env_);
     472          70 :     if_no_catch_env->control = if_no_catch;
     473         140 :     SsaEnv* if_catch_env = Steal(decoder->zone(), ssa_env_);
     474          70 :     if_catch_env->control = if_catch;
     475             : 
     476             :     // TODO(kschimpf): Generalize to allow more catches. Will force
     477             :     // moving no_catch code to END opcode.
     478             :     SetEnv(if_no_catch_env);
     479         140 :     BUILD(Rethrow);
     480          70 :     Unreachable(decoder);
     481             :     EndControl(decoder, block);
     482             : 
     483             :     SetEnv(if_catch_env);
     484             : 
     485          70 :     if (block->try_info->exception == nullptr) {
     486             :       // No caught value, make up filler nodes so that catch block still
     487             :       // compiles.
     488           0 :       for (Value& value : values) {
     489           0 :         value.node = DefaultValue(value.type);
     490             :       }
     491             :     } else {
     492             :       // TODO(kschimpf): Can't use BUILD() here, GetExceptionValues() returns
     493             :       // TFNode** rather than TFNode*. Fix to add landing pads.
     494          70 :       TFNode** caught_values = builder_->GetExceptionValues(operand.exception);
     495          40 :       for (size_t i = 0, e = values.size(); i < e; ++i) {
     496          40 :         values[i].node = caught_values[i];
     497             :       }
     498             :     }
     499          70 :   }
     500             : 
     501         512 :   void AtomicOp(Decoder* decoder, WasmOpcode opcode, Vector<Value> args,
     502             :                 const MemoryAccessOperand<validate>& operand, Value* result) {
     503         512 :     TFNode** inputs = GetNodes(args);
     504        1536 :     TFNode* node = BUILD(AtomicOp, opcode, inputs, operand.alignment,
     505             :                          operand.offset, decoder->position());
     506         512 :     if (result) result->node = node;
     507         512 :   }
     508             : 
     509             :  private:
     510             :   SsaEnv* ssa_env_;
     511             :   TFBuilder* builder_;
     512             :   uint32_t current_catch_ = kNullCatch;
     513             : 
     514             :   TryInfo* current_try_info(Decoder* decoder) {
     515          90 :     return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
     516          90 :         ->try_info;
     517             :   }
     518             : 
     519      304325 :   TFNode** GetNodes(Value* values, size_t count) {
     520      304325 :     TFNode** nodes = builder_->Buffer(count);
     521      162608 :     for (size_t i = 0; i < count; ++i) {
     522      162608 :       nodes[i] = values[i].node;
     523             :     }
     524      304356 :     return nodes;
     525             :   }
     526             : 
     527      304343 :   TFNode** GetNodes(Vector<Value> values) {
     528      304343 :     return GetNodes(values.start(), values.size());
     529             :   }
     530             : 
     531             :   void SetEnv(SsaEnv* env) {
     532             : #if DEBUG
     533             :     if (FLAG_trace_wasm_decoder) {
     534             :       char state = 'X';
     535             :       if (env) {
     536             :         switch (env->state) {
     537             :           case SsaEnv::kReached:
     538             :             state = 'R';
     539             :             break;
     540             :           case SsaEnv::kUnreachable:
     541             :             state = 'U';
     542             :             break;
     543             :           case SsaEnv::kMerged:
     544             :             state = 'M';
     545             :             break;
     546             :           case SsaEnv::kControlEnd:
     547             :             state = 'E';
     548             :             break;
     549             :         }
     550             :       }
     551             :       PrintF("{set_env = %p, state = %c", static_cast<void*>(env), state);
     552             :       if (env && env->control) {
     553             :         PrintF(", control = ");
     554             :         compiler::WasmGraphBuilder::PrintDebugName(env->control);
     555             :       }
     556             :       PrintF("}\n");
     557             :     }
     558             : #endif
     559     1414418 :     ssa_env_ = env;
     560             :     // TODO(wasm): Create a WasmEnv class with control, effect, mem_size and
     561             :     // mem_start. SsaEnv can inherit from it. This way WasmEnv can be passed
     562             :     // directly to WasmGraphBuilder instead of always copying four pointers.
     563     1414418 :     builder_->set_control_ptr(&env->control);
     564     1414418 :     builder_->set_effect_ptr(&env->effect);
     565     1414418 :     builder_->set_mem_size(&env->mem_size);
     566     1414418 :     builder_->set_mem_start(&env->mem_start);
     567             :   }
     568             : 
     569     2389176 :   TFNode* CheckForException(Decoder* decoder, TFNode* node) {
     570     2388996 :     if (node == nullptr) return nullptr;
     571             : 
     572     2259056 :     const bool inside_try_scope = current_catch_ != kNullCatch;
     573             : 
     574     2259056 :     if (!inside_try_scope) return node;
     575             : 
     576         190 :     TFNode* if_success = nullptr;
     577         190 :     TFNode* if_exception = nullptr;
     578         190 :     if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
     579             :       return node;
     580             :     }
     581             : 
     582         180 :     SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
     583          90 :     success_env->control = if_success;
     584             : 
     585          90 :     SsaEnv* exception_env = Split(decoder, success_env);
     586          90 :     exception_env->control = if_exception;
     587             :     TryInfo* try_info = current_try_info(decoder);
     588          90 :     Goto(decoder, exception_env, try_info->catch_env);
     589          90 :     TFNode* exception = try_info->exception;
     590          90 :     if (exception == nullptr) {
     591             :       DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
     592          70 :       try_info->exception = if_exception;
     593             :     } else {
     594             :       DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
     595             :       try_info->exception =
     596             :           CreateOrMergeIntoPhi(kWasmI32, try_info->catch_env->control,
     597          20 :                                try_info->exception, if_exception);
     598             :     }
     599             : 
     600             :     SetEnv(success_env);
     601          90 :     return node;
     602             :   }
     603             : 
     604       10284 :   TFNode* DefaultValue(ValueType type) {
     605       10284 :     switch (type) {
     606             :       case kWasmI32:
     607        6081 :         return builder_->Int32Constant(0);
     608             :       case kWasmI64:
     609         689 :         return builder_->Int64Constant(0);
     610             :       case kWasmF32:
     611         678 :         return builder_->Float32Constant(0);
     612             :       case kWasmF64:
     613        1840 :         return builder_->Float64Constant(0);
     614             :       case kWasmS128:
     615         996 :         return builder_->S128Zero();
     616             :       default:
     617           0 :         UNREACHABLE();
     618             :     }
     619             :   }
     620             : 
     621      616752 :   void MergeValuesInto(Decoder* decoder, Control* c) {
     622     1850158 :     if (!ssa_env_->go()) return;
     623             : 
     624      616781 :     SsaEnv* target = c->end_env;
     625      616781 :     const bool first = target->state == SsaEnv::kUnreachable;
     626      616781 :     Goto(decoder, ssa_env_, target);
     627             : 
     628             :     uint32_t avail =
     629      616610 :         decoder->stack_size() - decoder->control_at(0)->stack_depth;
     630      616610 :     uint32_t start = avail >= c->merge.arity ? 0 : c->merge.arity - avail;
     631      702162 :     for (uint32_t i = start; i < c->merge.arity; ++i) {
     632             :       auto& val = decoder->GetMergeValueFromStack(c, i);
     633             :       auto& old = c->merge[i];
     634             :       DCHECK_NOT_NULL(val.node);
     635             :       DCHECK(val.type == old.type || val.type == kWasmVar);
     636             :       old.node = first ? val.node
     637             :                        : CreateOrMergeIntoPhi(old.type, target->control,
     638       85479 :                                               old.node, val.node);
     639             :     }
     640             :   }
     641             : 
     642      666098 :   void Goto(Decoder* decoder, SsaEnv* from, SsaEnv* to) {
     643             :     DCHECK_NOT_NULL(to);
     644      666098 :     if (!from->go()) return;
     645      665978 :     switch (to->state) {
     646             :       case SsaEnv::kUnreachable: {  // Overwrite destination.
     647      345213 :         to->state = SsaEnv::kReached;
     648      345213 :         to->locals = from->locals;
     649      345213 :         to->control = from->control;
     650      345213 :         to->effect = from->effect;
     651      345213 :         to->mem_size = from->mem_size;
     652      345213 :         to->mem_start = from->mem_start;
     653      345213 :         break;
     654             :       }
     655             :       case SsaEnv::kReached: {  // Create a new merge.
     656       51205 :         to->state = SsaEnv::kMerged;
     657             :         // Merge control.
     658       51205 :         TFNode* controls[] = {to->control, from->control};
     659       51205 :         TFNode* merge = builder_->Merge(2, controls);
     660       51203 :         to->control = merge;
     661             :         // Merge effects.
     662       51203 :         if (from->effect != to->effect) {
     663       28100 :           TFNode* effects[] = {to->effect, from->effect, merge};
     664       28100 :           to->effect = builder_->EffectPhi(2, effects, merge);
     665             :         }
     666             :         // Merge SSA values.
     667      980474 :         for (int i = decoder->NumLocals() - 1; i >= 0; i--) {
     668      929271 :           TFNode* a = to->locals[i];
     669      929271 :           TFNode* b = from->locals[i];
     670      929271 :           if (a != b) {
     671       81292 :             TFNode* vals[] = {a, b};
     672             :             to->locals[i] =
     673      162584 :                 builder_->Phi(decoder->GetLocalType(i), 2, vals, merge);
     674             :           }
     675             :         }
     676             :         // Merge mem_size and mem_start.
     677       51203 :         if (to->mem_size != from->mem_size) {
     678       16545 :           TFNode* vals[] = {to->mem_size, from->mem_size};
     679             :           to->mem_size =
     680       16545 :               builder_->Phi(MachineRepresentation::kWord32, 2, vals, merge);
     681             :         }
     682       51203 :         if (to->mem_start != from->mem_start) {
     683       16545 :           TFNode* vals[] = {to->mem_start, from->mem_start};
     684             :           to->mem_start = builder_->Phi(MachineType::PointerRepresentation(), 2,
     685       16545 :                                         vals, merge);
     686             :         }
     687             :         break;
     688             :       }
     689             :       case SsaEnv::kMerged: {
     690      269560 :         TFNode* merge = to->control;
     691             :         // Extend the existing merge.
     692      269560 :         builder_->AppendToMerge(merge, from->control);
     693             :         // Merge effects.
     694      269559 :         if (builder_->IsPhiWithMerge(to->effect, merge)) {
     695       17649 :           builder_->AppendToPhi(to->effect, from->effect);
     696      251912 :         } else if (to->effect != from->effect) {
     697         164 :           uint32_t count = builder_->InputCount(merge);
     698         164 :           TFNode** effects = builder_->Buffer(count);
     699         643 :           for (uint32_t j = 0; j < count - 1; j++) {
     700         479 :             effects[j] = to->effect;
     701             :           }
     702         164 :           effects[count - 1] = from->effect;
     703         164 :           to->effect = builder_->EffectPhi(count, effects, merge);
     704             :         }
     705             :         // Merge locals.
     706      999942 :         for (int i = decoder->NumLocals() - 1; i >= 0; i--) {
     707             :           to->locals[i] = CreateOrMergeIntoPhi(decoder->GetLocalType(i), merge,
     708     1460760 :                                                to->locals[i], from->locals[i]);
     709             :         }
     710             :         // Merge mem_size and mem_start.
     711             :         to->mem_size =
     712             :             CreateOrMergeIntoPhi(MachineRepresentation::kWord32, merge,
     713      269562 :                                  to->mem_size, from->mem_size);
     714             :         to->mem_start =
     715             :             CreateOrMergeIntoPhi(MachineType::PointerRepresentation(), merge,
     716      269562 :                                  to->mem_start, from->mem_start);
     717      269561 :         break;
     718             :       }
     719             :       default:
     720           0 :         UNREACHABLE();
     721             :     }
     722             :     return from->Kill();
     723             :   }
     724             : 
     725     1277456 :   TFNode* CreateOrMergeIntoPhi(ValueType type, TFNode* merge, TFNode* tnode,
     726             :                                TFNode* fnode) {
     727     1277456 :     if (builder_->IsPhiWithMerge(tnode, merge)) {
     728      126706 :       builder_->AppendToPhi(tnode, fnode);
     729     1150752 :     } else if (tnode != fnode) {
     730       16633 :       uint32_t count = builder_->InputCount(merge);
     731       16633 :       TFNode** vals = builder_->Buffer(count);
     732       34377 :       for (uint32_t j = 0; j < count - 1; j++) vals[j] = tnode;
     733       16634 :       vals[count - 1] = fnode;
     734       16634 :       return builder_->Phi(type, count, vals, merge);
     735             :     }
     736             :     return tnode;
     737             :   }
     738             : 
     739       34867 :   SsaEnv* PrepareForLoop(Decoder* decoder, SsaEnv* env) {
     740       11622 :     if (!env->go()) return Split(decoder, env);
     741       11622 :     env->state = SsaEnv::kMerged;
     742             : 
     743       11622 :     env->control = builder_->Loop(env->control);
     744       11622 :     env->effect = builder_->EffectPhi(1, &env->effect, env->control);
     745       11622 :     builder_->Terminate(env->effect, env->control);
     746             :     // The '+ 2' here is to be able to set mem_size and mem_start as assigned.
     747             :     BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
     748       34868 :         decoder, decoder->pc(), decoder->total_locals() + 2, decoder->zone());
     749       11625 :     if (decoder->failed()) return env;
     750       11620 :     if (assigned != nullptr) {
     751             :       // Only introduce phis for variables assigned in this loop.
     752       11620 :       int mem_size_index = decoder->total_locals();
     753       11620 :       int mem_start_index = decoder->total_locals() + 1;
     754      245715 :       for (int i = decoder->NumLocals() - 1; i >= 0; i--) {
     755      234094 :         if (!assigned->Contains(i)) continue;
     756             :         env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
     757       98786 :                                        &env->locals[i], env->control);
     758             :       }
     759             :       // Introduce phis for mem_size and mem_start if necessary.
     760       11621 :       if (assigned->Contains(mem_size_index)) {
     761             :         env->mem_size = builder_->Phi(MachineRepresentation::kWord32, 1,
     762        5350 :                                       &env->mem_size, env->control);
     763             :       }
     764       11621 :       if (assigned->Contains(mem_start_index)) {
     765             :         env->mem_start = builder_->Phi(MachineType::PointerRepresentation(), 1,
     766        5350 :                                        &env->mem_start, env->control);
     767             :       }
     768             : 
     769       11621 :       SsaEnv* loop_body_env = Split(decoder, env);
     770             :       builder_->StackCheck(decoder->position(), &(loop_body_env->effect),
     771       23242 :                            &(loop_body_env->control));
     772             :       return loop_body_env;
     773             :     }
     774             : 
     775             :     // Conservatively introduce phis for all local variables.
     776           0 :     for (int i = decoder->NumLocals() - 1; i >= 0; i--) {
     777             :       env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
     778           0 :                                      &env->locals[i], env->control);
     779             :     }
     780             : 
     781             :     // Conservatively introduce phis for mem_size and mem_start.
     782             :     env->mem_size = builder_->Phi(MachineRepresentation::kWord32, 1,
     783           0 :                                   &env->mem_size, env->control);
     784             :     env->mem_start = builder_->Phi(MachineType::PointerRepresentation(), 1,
     785           0 :                                    &env->mem_start, env->control);
     786             : 
     787           0 :     SsaEnv* loop_body_env = Split(decoder, env);
     788             :     builder_->StackCheck(decoder->position(), &loop_body_env->effect,
     789           0 :                          &loop_body_env->control);
     790             :     return loop_body_env;
     791             :   }
     792             : 
     793             :   // Create a complete copy of the {from}.
     794     1605505 :   SsaEnv* Split(Decoder* decoder, SsaEnv* from) {
     795             :     DCHECK_NOT_NULL(from);
     796             :     SsaEnv* result =
     797      535171 :         reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
     798             :     // The '+ 2' here is to accommodate for mem_size and mem_start nodes.
     799      535167 :     size_t size = sizeof(TFNode*) * (decoder->NumLocals() + 2);
     800      535167 :     result->control = from->control;
     801      535167 :     result->effect = from->effect;
     802             : 
     803      535167 :     if (from->go()) {
     804      535167 :       result->state = SsaEnv::kReached;
     805             :       result->locals =
     806             :           size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
     807     1070334 :                    : nullptr;
     808      535169 :       memcpy(result->locals, from->locals, size);
     809      535169 :       result->mem_size = from->mem_size;
     810      535169 :       result->mem_start = from->mem_start;
     811             :     } else {
     812           0 :       result->state = SsaEnv::kUnreachable;
     813           0 :       result->locals = nullptr;
     814           0 :       result->mem_size = nullptr;
     815           0 :       result->mem_start = nullptr;
     816             :     }
     817             : 
     818      535169 :     return result;
     819             :   }
     820             : 
     821             :   // Create a copy of {from} that steals its state and leaves {from}
     822             :   // unreachable.
     823      562819 :   SsaEnv* Steal(Zone* zone, SsaEnv* from) {
     824             :     DCHECK_NOT_NULL(from);
     825      562819 :     if (!from->go()) return UnreachableEnv(zone);
     826      562819 :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
     827      562845 :     result->state = SsaEnv::kReached;
     828      562845 :     result->locals = from->locals;
     829      562845 :     result->control = from->control;
     830      562845 :     result->effect = from->effect;
     831      562845 :     result->mem_size = from->mem_size;
     832      562845 :     result->mem_start = from->mem_start;
     833             :     from->Kill(SsaEnv::kUnreachable);
     834             :     return result;
     835             :   }
     836             : 
     837             :   // Create an unreachable environment.
     838           0 :   SsaEnv* UnreachableEnv(Zone* zone) {
     839           0 :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
     840           0 :     result->state = SsaEnv::kUnreachable;
     841           0 :     result->control = nullptr;
     842           0 :     result->effect = nullptr;
     843           0 :     result->locals = nullptr;
     844           0 :     result->mem_size = nullptr;
     845           0 :     result->mem_start = nullptr;
     846           0 :     return result;
     847             :   }
     848             : 
     849             :   template <typename Operand>
     850      351644 :   void DoCall(WasmFullDecoder<validate, WasmGraphBuildingInterface>* decoder,
     851             :               TFNode* index_node, const Operand& operand, const Value args[],
     852             :               Value returns[], bool is_indirect) {
     853      351635 :     int param_count = static_cast<int>(operand.sig->parameter_count());
     854      175819 :     TFNode** arg_nodes = builder_->Buffer(param_count + 1);
     855      175825 :     TFNode** return_nodes = nullptr;
     856      175825 :     arg_nodes[0] = index_node;
     857      393875 :     for (int i = 0; i < param_count; ++i) {
     858      393875 :       arg_nodes[i + 1] = args[i].node;
     859             :     }
     860      175825 :     if (is_indirect) {
     861        3290 :       builder_->CallIndirect(operand.index, arg_nodes, &return_nodes,
     862             :                              decoder->position());
     863             :     } else {
     864      172535 :       builder_->CallDirect(operand.index, arg_nodes, &return_nodes,
     865             :                            decoder->position());
     866             :     }
     867      351632 :     int return_count = static_cast<int>(operand.sig->return_count());
     868      155041 :     for (int i = 0; i < return_count; ++i) {
     869      155041 :       returns[i].node = return_nodes[i];
     870             :     }
     871             :     // The invoked function could have used grow_memory, so we need to
     872             :     // reload mem_size and mem_start
     873      175816 :     LoadContextIntoSsa(ssa_env_);
     874      175826 :   }
     875             : };
     876             : 
     877             : }  // namespace
     878             : 
     879       20521 : bool DecodeLocalDecls(BodyLocalDecls* decls, const byte* start,
     880             :                       const byte* end) {
     881             :   Decoder decoder(start, end);
     882       20521 :   if (WasmDecoder<Decoder::kValidate>::DecodeLocals(&decoder, nullptr,
     883       20521 :                                                     &decls->type_list)) {
     884             :     DCHECK(decoder.ok());
     885       20490 :     decls->encoded_size = decoder.pc_offset();
     886       20490 :     return true;
     887             :   }
     888             :   return false;
     889             : }
     890             : 
     891       20432 : BytecodeIterator::BytecodeIterator(const byte* start, const byte* end,
     892             :                                    BodyLocalDecls* decls)
     893       20432 :     : Decoder(start, end) {
     894       20432 :   if (decls != nullptr) {
     895       20429 :     if (DecodeLocalDecls(decls, start, end)) {
     896       20399 :       pc_ += decls->encoded_size;
     897       20399 :       if (pc_ > end_) pc_ = end_;
     898             :     }
     899             :   }
     900       20432 : }
     901             : 
     902      171110 : DecodeResult VerifyWasmCode(AccountingAllocator* allocator,
     903             :                             const wasm::WasmModule* module,
     904             :                             FunctionBody& body) {
     905      171110 :   Zone zone(allocator, ZONE_NAME);
     906             :   WasmFullDecoder<Decoder::kValidate, EmptyInterface> decoder(&zone, module,
     907             :                                                               body);
     908      171110 :   decoder.Decode();
     909      513330 :   return decoder.toResult(nullptr);
     910             : }
     911             : 
     912      157413 : DecodeResult VerifyWasmCodeWithStats(AccountingAllocator* allocator,
     913             :                                      const wasm::WasmModule* module,
     914             :                                      FunctionBody& body, bool is_wasm,
     915             :                                      Counters* counters) {
     916      157413 :   CHECK_LE(0, body.end - body.start);
     917             :   auto time_counter = is_wasm ? counters->wasm_decode_wasm_function_time()
     918      157413 :                               : counters->wasm_decode_asm_function_time();
     919             :   TimedHistogramScope wasm_decode_function_time_scope(time_counter);
     920      472239 :   return VerifyWasmCode(allocator, module, body);
     921             : }
     922             : 
     923      234381 : DecodeResult BuildTFGraph(AccountingAllocator* allocator, TFBuilder* builder,
     924             :                           FunctionBody& body) {
     925      234381 :   Zone zone(allocator, ZONE_NAME);
     926             :   WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
     927      234351 :       &zone, builder->module(), body, builder);
     928      234351 :   decoder.Decode();
     929      702688 :   return decoder.toResult(nullptr);
     930             : }
     931             : 
     932      214306 : unsigned OpcodeLength(const byte* pc, const byte* end) {
     933             :   Decoder decoder(pc, end);
     934      428612 :   return WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, pc);
     935             : }
     936             : 
     937      179323 : std::pair<uint32_t, uint32_t> StackEffect(const WasmModule* module,
     938             :                                           FunctionSig* sig, const byte* pc,
     939             :                                           const byte* end) {
     940             :   WasmDecoder<Decoder::kNoValidate> decoder(module, sig, pc, end);
     941      358646 :   return decoder.StackEffect(pc);
     942             : }
     943             : 
     944           0 : void PrintRawWasmCode(const byte* start, const byte* end) {
     945           0 :   AccountingAllocator allocator;
     946           0 :   PrintRawWasmCode(&allocator, FunctionBodyForTesting(start, end), nullptr);
     947           0 : }
     948             : 
     949             : namespace {
     950           0 : const char* RawOpcodeName(WasmOpcode opcode) {
     951           0 :   switch (opcode) {
     952             : #define DECLARE_NAME_CASE(name, opcode, sig) \
     953             :   case kExpr##name:                          \
     954             :     return "kExpr" #name;
     955           0 :     FOREACH_OPCODE(DECLARE_NAME_CASE)
     956             : #undef DECLARE_NAME_CASE
     957             :     default:
     958             :       break;
     959             :   }
     960           0 :   return "Unknown";
     961             : }
     962             : }  // namespace
     963             : 
     964           0 : bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
     965             :                       const wasm::WasmModule* module) {
     966           0 :   OFStream os(stdout);
     967           0 :   Zone zone(allocator, ZONE_NAME);
     968             :   WasmDecoder<Decoder::kNoValidate> decoder(module, body.sig, body.start,
     969           0 :                                             body.end);
     970             :   int line_nr = 0;
     971             : 
     972             :   // Print the function signature.
     973           0 :   if (body.sig) {
     974           0 :     os << "// signature: " << *body.sig << std::endl;
     975             :     ++line_nr;
     976             :   }
     977             : 
     978             :   // Print the local declarations.
     979             :   BodyLocalDecls decls(&zone);
     980           0 :   BytecodeIterator i(body.start, body.end, &decls);
     981           0 :   if (body.start != i.pc() && !FLAG_wasm_code_fuzzer_gen_test) {
     982           0 :     os << "// locals: ";
     983           0 :     if (!decls.type_list.empty()) {
     984           0 :       ValueType type = decls.type_list[0];
     985             :       uint32_t count = 0;
     986           0 :       for (size_t pos = 0; pos < decls.type_list.size(); ++pos) {
     987           0 :         if (decls.type_list[pos] == type) {
     988           0 :           ++count;
     989             :         } else {
     990           0 :           os << " " << count << " " << WasmOpcodes::TypeName(type);
     991           0 :           type = decls.type_list[pos];
     992             :           count = 1;
     993             :         }
     994             :       }
     995             :     }
     996             :     os << std::endl;
     997             :     ++line_nr;
     998             : 
     999           0 :     for (const byte* locals = body.start; locals < i.pc(); locals++) {
    1000           0 :       os << (locals == body.start ? "0x" : " 0x") << AsHex(*locals, 2) << ",";
    1001             :     }
    1002             :     os << std::endl;
    1003             :     ++line_nr;
    1004             :   }
    1005             : 
    1006           0 :   os << "// body: " << std::endl;
    1007             :   ++line_nr;
    1008             :   unsigned control_depth = 0;
    1009           0 :   for (; i.has_next(); i.next()) {
    1010             :     unsigned length =
    1011           0 :         WasmDecoder<Decoder::kNoValidate>::OpcodeLength(&decoder, i.pc());
    1012             : 
    1013           0 :     WasmOpcode opcode = i.current();
    1014           0 :     if (opcode == kExprElse) control_depth--;
    1015             : 
    1016           0 :     int num_whitespaces = control_depth < 32 ? 2 * control_depth : 64;
    1017             : 
    1018             :     // 64 whitespaces
    1019             :     const char* padding =
    1020             :         "                                                                ";
    1021           0 :     os.write(padding, num_whitespaces);
    1022             : 
    1023           0 :     os << RawOpcodeName(opcode) << ",";
    1024             : 
    1025           0 :     for (unsigned j = 1; j < length; ++j) {
    1026           0 :       os << " 0x" << AsHex(i.pc()[j], 2) << ",";
    1027             :     }
    1028             : 
    1029           0 :     switch (opcode) {
    1030             :       case kExprElse:
    1031           0 :         os << "   // @" << i.pc_offset();
    1032           0 :         control_depth++;
    1033           0 :         break;
    1034             :       case kExprLoop:
    1035             :       case kExprIf:
    1036             :       case kExprBlock:
    1037             :       case kExprTry: {
    1038           0 :         BlockTypeOperand<Decoder::kNoValidate> operand(&i, i.pc());
    1039           0 :         os << "   // @" << i.pc_offset();
    1040           0 :         for (unsigned i = 0; i < operand.out_arity(); i++) {
    1041           0 :           os << " " << WasmOpcodes::TypeName(operand.out_type(i));
    1042             :         }
    1043           0 :         control_depth++;
    1044             :         break;
    1045             :       }
    1046             :       case kExprEnd:
    1047           0 :         os << "   // @" << i.pc_offset();
    1048           0 :         control_depth--;
    1049           0 :         break;
    1050             :       case kExprBr: {
    1051           0 :         BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
    1052           0 :         os << "   // depth=" << operand.depth;
    1053             :         break;
    1054             :       }
    1055             :       case kExprBrIf: {
    1056           0 :         BreakDepthOperand<Decoder::kNoValidate> operand(&i, i.pc());
    1057           0 :         os << "   // depth=" << operand.depth;
    1058             :         break;
    1059             :       }
    1060             :       case kExprBrTable: {
    1061           0 :         BranchTableOperand<Decoder::kNoValidate> operand(&i, i.pc());
    1062           0 :         os << " // entries=" << operand.table_count;
    1063             :         break;
    1064             :       }
    1065             :       case kExprCallIndirect: {
    1066           0 :         CallIndirectOperand<Decoder::kNoValidate> operand(&i, i.pc());
    1067           0 :         os << "   // sig #" << operand.index;
    1068           0 :         if (decoder.Complete(i.pc(), operand)) {
    1069           0 :           os << ": " << *operand.sig;
    1070             :         }
    1071             :         break;
    1072             :       }
    1073             :       case kExprCallFunction: {
    1074           0 :         CallFunctionOperand<Decoder::kNoValidate> operand(&i, i.pc());
    1075           0 :         os << " // function #" << operand.index;
    1076           0 :         if (decoder.Complete(i.pc(), operand)) {
    1077           0 :           os << ": " << *operand.sig;
    1078             :         }
    1079             :         break;
    1080             :       }
    1081             :       default:
    1082             :         break;
    1083             :     }
    1084             :     os << std::endl;
    1085             :     ++line_nr;
    1086             :   }
    1087             : 
    1088           0 :   return decoder.ok();
    1089             : }
    1090             : 
    1091          78 : BitVector* AnalyzeLoopAssignmentForTesting(Zone* zone, size_t num_locals,
    1092             :                                            const byte* start, const byte* end) {
    1093             :   Decoder decoder(start, end);
    1094             :   return WasmDecoder<Decoder::kValidate>::AnalyzeLoopAssignment(
    1095         156 :       &decoder, start, static_cast<uint32_t>(num_locals), zone);
    1096             : }
    1097             : 
    1098             : #undef BUILD
    1099             : 
    1100             : }  // namespace wasm
    1101             : }  // namespace internal
    1102             : }  // namespace v8

Generated by: LCOV version 1.10