LCOV - code coverage report
Current view: top level - src/wasm - graph-builder-interface.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 349 365 95.6 %
Date: 2019-02-19 Functions: 70 74 94.6 %

          Line data    Source code
       1             : // Copyright 2018 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/wasm/graph-builder-interface.h"
       6             : 
       7             : #include "src/compiler/wasm-compiler.h"
       8             : #include "src/flags.h"
       9             : #include "src/handles.h"
      10             : #include "src/objects-inl.h"
      11             : #include "src/ostreams.h"
      12             : #include "src/wasm/decoder.h"
      13             : #include "src/wasm/function-body-decoder-impl.h"
      14             : #include "src/wasm/function-body-decoder.h"
      15             : #include "src/wasm/wasm-limits.h"
      16             : #include "src/wasm/wasm-linkage.h"
      17             : #include "src/wasm/wasm-module.h"
      18             : #include "src/wasm/wasm-opcodes.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : namespace wasm {
      23             : 
      24             : namespace {
      25             : 
      26             : // An SsaEnv environment carries the current local variable renaming
      27             : // as well as the current effect and control dependency in the TF graph.
      28             : // It maintains a control state that tracks whether the environment
      29             : // is reachable, has reached a control end, or has been merged.
      30             : struct SsaEnv {
      31             :   enum State { kControlEnd, kUnreachable, kReached, kMerged };
      32             : 
      33             :   State state;
      34             :   TFNode* control;
      35             :   TFNode* effect;
      36             :   compiler::WasmInstanceCacheNodes instance_cache;
      37             :   TFNode** locals;
      38             : 
      39             :   void Kill(State new_state = kControlEnd) {
      40      595359 :     state = new_state;
      41      595359 :     locals = nullptr;
      42      595359 :     control = nullptr;
      43      595359 :     effect = nullptr;
      44      595359 :     instance_cache = {};
      45             :   }
      46             :   void SetNotMerged() {
      47       35532 :     if (state == kMerged) state = kReached;
      48             :   }
      49             : };
      50             : 
      51             : #define BUILD(func, ...)                                            \
      52             :   ([&] {                                                            \
      53             :     DCHECK(decoder->ok());                                          \
      54             :     return CheckForException(decoder, builder_->func(__VA_ARGS__)); \
      55             :   })()
      56             : 
      57             : constexpr uint32_t kNullCatch = static_cast<uint32_t>(-1);
      58             : 
      59             : class WasmGraphBuildingInterface {
      60             :  public:
      61             :   static constexpr Decoder::ValidateFlag validate = Decoder::kValidate;
      62             :   using FullDecoder = WasmFullDecoder<validate, WasmGraphBuildingInterface>;
      63             : 
      64             :   struct Value : public ValueBase {
      65             :     TFNode* node = nullptr;
      66             : 
      67             :     template <typename... Args>
      68             :     explicit Value(Args&&... args) V8_NOEXCEPT
      69     7634592 :         : ValueBase(std::forward<Args>(args)...) {}
      70             :   };
      71             : 
      72             :   struct TryInfo : public ZoneObject {
      73             :     SsaEnv* catch_env;
      74             :     TFNode* exception = nullptr;
      75             : 
      76             :     bool might_throw() const { return exception != nullptr; }
      77             : 
      78             :     MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TryInfo);
      79             : 
      80         520 :     explicit TryInfo(SsaEnv* c) : catch_env(c) {}
      81             :   };
      82             : 
      83             :   struct Control : public ControlBase<Value> {
      84             :     SsaEnv* end_env = nullptr;    // end environment for the construct.
      85             :     SsaEnv* false_env = nullptr;  // false environment (only for if).
      86             :     TryInfo* try_info = nullptr;  // information about try statements.
      87             :     int32_t previous_catch = -1;  // previous Control with a catch.
      88             : 
      89             :     MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Control);
      90             : 
      91             :     template <typename... Args>
      92             :     explicit Control(Args&&... args) V8_NOEXCEPT
      93     1258036 :         : ControlBase(std::forward<Args>(args)...) {}
      94             :   };
      95             : 
      96             :   explicit WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder)
      97      503594 :       : builder_(builder) {}
      98             : 
      99      590934 :   void StartFunction(FullDecoder* decoder) {
     100             :     SsaEnv* ssa_env =
     101      503707 :         reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
     102             :     uint32_t num_locals = decoder->num_locals();
     103             :     uint32_t env_count = num_locals;
     104      503730 :     size_t size = sizeof(TFNode*) * env_count;
     105      503730 :     ssa_env->state = SsaEnv::kReached;
     106             :     ssa_env->locals =
     107             :         size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
     108      590957 :                  : nullptr;
     109             : 
     110             :     // The first '+ 1' is needed by TF Start node, the second '+ 1' is for the
     111             :     // instance parameter.
     112             :     TFNode* start = builder_->Start(
     113     1201680 :         static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
     114      503651 :     ssa_env->effect = start;
     115      503651 :     ssa_env->control = start;
     116             :     // Initialize effect and control before initializing the locals default
     117             :     // values (which might require instance loads) or loading the context.
     118      503651 :     builder_->set_effect_ptr(&ssa_env->effect);
     119      503651 :     builder_->set_control_ptr(&ssa_env->control);
     120             :     // Initialize the instance parameter (index 0).
     121      503651 :     builder_->set_instance_node(builder_->Param(kWasmInstanceParameterIndex));
     122             :     // Initialize local variables. Parameters are shifted by 1 because of the
     123             :     // the instance parameter.
     124             :     uint32_t index = 0;
     125     1899551 :     for (; index < decoder->sig_->parameter_count(); ++index) {
     126      194264 :       ssa_env->locals[index] = builder_->Param(index + 1);
     127             :     }
     128      524164 :     while (index < num_locals) {
     129             :       ValueType type = decoder->GetLocalType(index);
     130       20465 :       TFNode* node = DefaultValue(type);
     131      740962 :       while (index < num_locals && decoder->GetLocalType(index) == type) {
     132             :         // Do a whole run of like-typed locals at a time.
     133      349042 :         ssa_env->locals[index++] = node;
     134             :       }
     135             :     }
     136             :     LoadContextIntoSsa(ssa_env);
     137             :     SetEnv(ssa_env);
     138      503711 :   }
     139             : 
     140             :   // Reload the instance cache entries into the Ssa Environment.
     141             :   void LoadContextIntoSsa(SsaEnv* ssa_env) {
     142      537232 :     if (ssa_env) builder_->InitInstanceCache(&ssa_env->instance_cache);
     143             :   }
     144             : 
     145             :   void StartFunctionBody(FullDecoder* decoder, Control* block) {}
     146             : 
     147      496947 :   void FinishFunction(FullDecoder*) { builder_->PatchInStackCheckIfNeeded(); }
     148             : 
     149             :   void OnFirstError(FullDecoder*) {}
     150             : 
     151             :   void NextInstruction(FullDecoder*, WasmOpcode) {}
     152             : 
     153      118832 :   void Block(FullDecoder* decoder, Control* block) {
     154             :     // The branch environment is the outer environment.
     155       59416 :     block->end_env = ssa_env_;
     156      118832 :     SetEnv(Steal(decoder->zone(), ssa_env_));
     157       59415 :   }
     158             : 
     159       18180 :   void Loop(FullDecoder* decoder, Control* block) {
     160       18180 :     SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
     161        9090 :     block->end_env = finish_try_env;
     162             :     // The continue environment is the inner environment.
     163        9090 :     SetEnv(PrepareForLoop(decoder, finish_try_env));
     164        9089 :     ssa_env_->SetNotMerged();
     165       18178 :     if (!decoder->ok()) return;
     166             :     // Wrap input merge into phis.
     167          32 :     for (uint32_t i = 0; i < block->start_merge.arity; ++i) {
     168             :       Value& val = block->start_merge[i];
     169          32 :       val.node = builder_->Phi(val.type, 1, &val.node, block->end_env->control);
     170             :     }
     171             :   }
     172             : 
     173        1559 :   void Try(FullDecoder* decoder, Control* block) {
     174         519 :     SsaEnv* outer_env = ssa_env_;
     175         519 :     SsaEnv* catch_env = Split(decoder, outer_env);
     176             :     // Mark catch environment as unreachable, since only accessable
     177             :     // through catch unwinding (i.e. landing pads).
     178         520 :     catch_env->state = SsaEnv::kUnreachable;
     179         520 :     SsaEnv* try_env = Steal(decoder->zone(), outer_env);
     180             :     SetEnv(try_env);
     181             :     TryInfo* try_info = new (decoder->zone()) TryInfo(catch_env);
     182         520 :     block->end_env = outer_env;
     183         520 :     block->try_info = try_info;
     184         520 :     block->previous_catch = current_catch_;
     185         520 :     current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
     186         520 :   }
     187             : 
     188       56244 :   void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
     189       56244 :     TFNode* if_true = nullptr;
     190       56244 :     TFNode* if_false = nullptr;
     191      112488 :     BUILD(BranchNoHint, cond.node, &if_true, &if_false);
     192       56249 :     SsaEnv* end_env = ssa_env_;
     193      112493 :     SsaEnv* false_env = Split(decoder, ssa_env_);
     194       56244 :     false_env->control = if_false;
     195      112488 :     SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
     196       56245 :     true_env->control = if_true;
     197       56245 :     if_block->end_env = end_env;
     198       56245 :     if_block->false_env = false_env;
     199             :     SetEnv(true_env);
     200       56245 :   }
     201             : 
     202       32563 :   void FallThruTo(FullDecoder* decoder, Control* c) {
     203             :     DCHECK(!c->is_loop());
     204       65126 :     MergeValuesInto(decoder, c, &c->end_merge);
     205             :   }
     206             : 
     207      160719 :   void PopControl(FullDecoder* decoder, Control* block) {
     208             :     // A loop just continues with the end environment. There is no merge.
     209      358973 :     if (block->is_loop()) return;
     210             :     // Any other block falls through to the parent block.
     211      113753 :     if (block->reachable()) FallThruTo(decoder, block);
     212      113751 :     if (block->is_onearmed_if()) {
     213             :       // Merge the else branch into the end merge.
     214       38107 :       SetEnv(block->false_env);
     215       76214 :       MergeValuesInto(decoder, block, &block->end_merge);
     216             :     }
     217             :     // Now continue with the merged environment.
     218      113751 :     SetEnv(block->end_env);
     219             :   }
     220             : 
     221             :   void EndControl(FullDecoder* decoder, Control* block) { ssa_env_->Kill(); }
     222             : 
     223             :   void UnOp(FullDecoder* decoder, WasmOpcode opcode, const Value& value,
     224             :             Value* result) {
     225      326410 :     result->node = BUILD(Unop, opcode, value.node, decoder->position());
     226             :   }
     227             : 
     228             :   void BinOp(FullDecoder* decoder, WasmOpcode opcode, const Value& lhs,
     229             :              const Value& rhs, Value* result) {
     230     2253465 :     auto node = BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
     231      751122 :     if (result) result->node = node;
     232             :   }
     233             : 
     234             :   void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
     235     1642277 :     result->node = builder_->Int32Constant(value);
     236             :   }
     237             : 
     238             :   void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
     239       20701 :     result->node = builder_->Int64Constant(value);
     240             :   }
     241             : 
     242             :   void F32Const(FullDecoder* decoder, Value* result, float value) {
     243        3203 :     result->node = builder_->Float32Constant(value);
     244             :   }
     245             : 
     246             :   void F64Const(FullDecoder* decoder, Value* result, double value) {
     247        9170 :     result->node = builder_->Float64Constant(value);
     248             :   }
     249             : 
     250             :   void RefNull(FullDecoder* decoder, Value* result) {
     251          80 :     result->node = builder_->RefNull();
     252             :   }
     253             : 
     254             :   void Drop(FullDecoder* decoder, const Value& value) {}
     255             : 
     256      540814 :   void DoReturn(FullDecoder* decoder, Vector<Value> values) {
     257      540894 :     TFNode** nodes = GetNodes(values);
     258     1081789 :     BUILD(Return, static_cast<uint32_t>(values.size()), nodes);
     259      540848 :   }
     260             : 
     261             :   void GetLocal(FullDecoder* decoder, Value* result,
     262             :                 const LocalIndexImmediate<validate>& imm) {
     263      600067 :     if (!ssa_env_->locals) return;  // unreachable
     264      600082 :     result->node = ssa_env_->locals[imm.index];
     265             :   }
     266             : 
     267             :   void SetLocal(FullDecoder* decoder, const Value& value,
     268             :                 const LocalIndexImmediate<validate>& imm) {
     269      357212 :     if (!ssa_env_->locals) return;  // unreachable
     270      357213 :     ssa_env_->locals[imm.index] = value.node;
     271             :   }
     272             : 
     273             :   void TeeLocal(FullDecoder* decoder, const Value& value, Value* result,
     274             :                 const LocalIndexImmediate<validate>& imm) {
     275       98399 :     result->node = value.node;
     276       98399 :     if (!ssa_env_->locals) return;  // unreachable
     277       98399 :     ssa_env_->locals[imm.index] = value.node;
     278             :   }
     279             : 
     280             :   void GetGlobal(FullDecoder* decoder, Value* result,
     281             :                  const GlobalIndexImmediate<validate>& imm) {
     282       72497 :     result->node = BUILD(GetGlobal, imm.index);
     283             :   }
     284             : 
     285             :   void SetGlobal(FullDecoder* decoder, const Value& value,
     286             :                  const GlobalIndexImmediate<validate>& imm) {
     287       30892 :     BUILD(SetGlobal, imm.index, value.node);
     288             :   }
     289             : 
     290             :   void GetTable(FullDecoder* decoder, const Value& index, Value* result,
     291             :                 const TableIndexImmediate<validate>& imm) {
     292           0 :     result->node = BUILD(GetTable, imm.index, index.node, decoder->position());
     293             :   }
     294             : 
     295             :   void SetTable(FullDecoder* decoder, const Value& index, const Value& value,
     296             :                 const TableIndexImmediate<validate>& imm) {
     297           0 :     BUILD(SetTable, imm.index, index.node, value.node, decoder->position());
     298             :   }
     299             : 
     300             :   void Unreachable(FullDecoder* decoder) {
     301        4623 :     BUILD(Unreachable, decoder->position());
     302             :   }
     303             : 
     304         818 :   void Select(FullDecoder* decoder, const Value& cond, const Value& fval,
     305             :               const Value& tval, Value* result) {
     306             :     TFNode* controls[2];
     307        1636 :     BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
     308        1640 :     TFNode* merge = BUILD(Merge, 2, controls);
     309         820 :     TFNode* vals[2] = {tval.node, fval.node};
     310        1640 :     TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
     311         819 :     result->node = phi;
     312         819 :     ssa_env_->control = merge;
     313         819 :   }
     314             : 
     315      242922 :   void BrOrRet(FullDecoder* decoder, uint32_t depth) {
     316      485580 :     if (depth == decoder->control_depth() - 1) {
     317         212 :       uint32_t ret_count = static_cast<uint32_t>(decoder->sig_->return_count());
     318             :       TFNode** values =
     319             :           ret_count == 0 ? nullptr
     320         344 :                          : GetNodes(decoder->stack_value(ret_count), ret_count);
     321         424 :       BUILD(Return, ret_count, values);
     322             :     } else {
     323             :       Br(decoder, decoder->control_at(depth));
     324             :     }
     325      242796 :   }
     326             : 
     327      265316 :   void Br(FullDecoder* decoder, Control* target) {
     328      265316 :     MergeValuesInto(decoder, target, target->br_merge());
     329             :   }
     330             : 
     331       26443 :   void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) {
     332       26443 :     SsaEnv* fenv = ssa_env_;
     333       26443 :     SsaEnv* tenv = Split(decoder, fenv);
     334       26443 :     fenv->SetNotMerged();
     335       52886 :     BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
     336       26443 :     SetEnv(tenv);
     337       26443 :     BrOrRet(decoder, depth);
     338       26443 :     SetEnv(fenv);
     339       26443 :   }
     340             : 
     341        5303 :   void BrTable(FullDecoder* decoder, const BranchTableImmediate<validate>& imm,
     342             :                const Value& key) {
     343        5303 :     if (imm.table_count == 0) {
     344             :       // Only a default target. Do the equivalent of br.
     345        5754 :       uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
     346         451 :       BrOrRet(decoder, target);
     347        5754 :       return;
     348             :     }
     349             : 
     350        4852 :     SsaEnv* branch_env = ssa_env_;
     351             :     // Build branches to the various blocks based on the table.
     352        9704 :     TFNode* sw = BUILD(Switch, imm.table_count + 1, key.node);
     353             : 
     354        9704 :     SsaEnv* copy = Steal(decoder->zone(), branch_env);
     355             :     SetEnv(copy);
     356        4853 :     BranchTableIterator<validate> iterator(decoder, imm);
     357      220378 :     while (iterator.has_next()) {
     358      215526 :       uint32_t i = iterator.cur_index();
     359      215526 :       uint32_t target = iterator.next();
     360      215526 :       SetEnv(Split(decoder, copy));
     361             :       ssa_env_->control =
     362      431048 :           (i == imm.table_count) ? BUILD(IfDefault, sw) : BUILD(IfValue, i, sw);
     363      215525 :       BrOrRet(decoder, target);
     364             :     }
     365             :     DCHECK(decoder->ok());
     366             :     SetEnv(branch_env);
     367             :   }
     368             : 
     369       32569 :   void Else(FullDecoder* decoder, Control* if_block) {
     370       17834 :     if (if_block->reachable()) {
     371             :       // Merge the if branch into the end merge.
     372       29470 :       MergeValuesInto(decoder, if_block, &if_block->end_merge);
     373             :     }
     374       17834 :     SetEnv(if_block->false_env);
     375       17834 :   }
     376             : 
     377             :   void LoadMem(FullDecoder* decoder, LoadType type,
     378             :                const MemoryAccessImmediate<validate>& imm, const Value& index,
     379             :                Value* result) {
     380             :     result->node =
     381      471320 :         BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
     382       94262 :               imm.offset, imm.alignment, decoder->position());
     383             :   }
     384             : 
     385             :   void StoreMem(FullDecoder* decoder, StoreType type,
     386             :                 const MemoryAccessImmediate<validate>& imm, const Value& index,
     387             :                 const Value& value) {
     388      864904 :     BUILD(StoreMem, type.mem_rep(), index.node, imm.offset, imm.alignment,
     389      144163 :           value.node, decoder->position(), type.value_type());
     390             :   }
     391             : 
     392             :   void CurrentMemoryPages(FullDecoder* decoder, Value* result) {
     393         736 :     result->node = BUILD(CurrentMemoryPages);
     394             :   }
     395             : 
     396        1120 :   void MemoryGrow(FullDecoder* decoder, const Value& value, Value* result) {
     397        2240 :     result->node = BUILD(MemoryGrow, value.node);
     398             :     // Always reload the instance cache after growing memory.
     399        1120 :     LoadContextIntoSsa(ssa_env_);
     400        1120 :   }
     401             : 
     402             :   void CallDirect(FullDecoder* decoder,
     403             :                   const CallFunctionImmediate<validate>& imm,
     404             :                   const Value args[], Value returns[]) {
     405       29126 :     DoCall(decoder, nullptr, imm.sig, imm.index, args, returns);
     406             :   }
     407             : 
     408           0 :   void ReturnCall(FullDecoder* decoder,
     409             :                   const CallFunctionImmediate<validate>& imm,
     410             :                   const Value args[]) {
     411           0 :     UNIMPLEMENTED();
     412             :   }
     413             : 
     414             :   void CallIndirect(FullDecoder* decoder, const Value& index,
     415             :                     const CallIndirectImmediate<validate>& imm,
     416             :                     const Value args[], Value returns[]) {
     417        3285 :     DoCall(decoder, index.node, imm.sig, imm.sig_index, args, returns);
     418             :   }
     419             : 
     420           0 :   void ReturnCallIndirect(FullDecoder* decoder, const Value& index,
     421             :                           const CallIndirectImmediate<validate>& imm,
     422             :                           const Value args[]) {
     423           0 :     UNIMPLEMENTED();
     424             :   }
     425             : 
     426        4164 :   void SimdOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
     427             :               Value* result) {
     428        4164 :     TFNode** inputs = GetNodes(args);
     429        8328 :     TFNode* node = BUILD(SimdOp, opcode, inputs);
     430        4164 :     if (result) result->node = node;
     431        4164 :   }
     432             : 
     433       18676 :   void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
     434             :                   const SimdLaneImmediate<validate> imm, Vector<Value> inputs,
     435             :                   Value* result) {
     436       18676 :     TFNode** nodes = GetNodes(inputs);
     437       37352 :     result->node = BUILD(SimdLaneOp, opcode, imm.lane, nodes);
     438       18676 :   }
     439             : 
     440             :   void SimdShiftOp(FullDecoder* decoder, WasmOpcode opcode,
     441             :                    const SimdShiftImmediate<validate> imm, const Value& input,
     442             :                    Value* result) {
     443        1272 :     TFNode* inputs[] = {input.node};
     444        2544 :     result->node = BUILD(SimdShiftOp, opcode, imm.shift, inputs);
     445             :   }
     446             : 
     447             :   void Simd8x16ShuffleOp(FullDecoder* decoder,
     448             :                          const Simd8x16ShuffleImmediate<validate>& imm,
     449             :                          const Value& input0, const Value& input1,
     450             :                          Value* result) {
     451       14544 :     TFNode* input_nodes[] = {input0.node, input1.node};
     452       29088 :     result->node = BUILD(Simd8x16ShuffleOp, imm.shuffle, input_nodes);
     453             :   }
     454             : 
     455         502 :   void Throw(FullDecoder* decoder, const ExceptionIndexImmediate<validate>& imm,
     456         766 :              const Vector<Value>& value_args) {
     457             :     int count = value_args.length();
     458         502 :     ZoneVector<TFNode*> args(count, decoder->zone());
     459         768 :     for (int i = 0; i < count; ++i) {
     460         528 :       args[i] = value_args[i].node;
     461             :     }
     462        1512 :     BUILD(Throw, imm.index, imm.exception, VectorOf(args));
     463         504 :     builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
     464         503 :   }
     465             : 
     466         423 :   void Rethrow(FullDecoder* decoder, const Value& exception) {
     467         846 :     BUILD(Rethrow, exception.node);
     468         424 :     builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
     469         423 :   }
     470             : 
     471         376 :   void BrOnException(FullDecoder* decoder, const Value& exception,
     472             :                      const ExceptionIndexImmediate<validate>& imm,
     473             :                      uint32_t depth, Vector<Value> values) {
     474         376 :     TFNode* if_match = nullptr;
     475         376 :     TFNode* if_no_match = nullptr;
     476             : 
     477             :     // Get the exception tag and see if it matches the expected one.
     478         752 :     TFNode* caught_tag = BUILD(GetExceptionTag, exception.node);
     479         752 :     TFNode* exception_tag = BUILD(LoadExceptionTagFromTable, imm.index);
     480         752 :     TFNode* compare = BUILD(ExceptionTagEqual, caught_tag, exception_tag);
     481         752 :     BUILD(BranchNoHint, compare, &if_match, &if_no_match);
     482         752 :     SsaEnv* if_no_match_env = Split(decoder, ssa_env_);
     483         752 :     SsaEnv* if_match_env = Steal(decoder->zone(), ssa_env_);
     484         376 :     if_no_match_env->control = if_no_match;
     485         376 :     if_match_env->control = if_match;
     486             : 
     487             :     // If the tags match we extract the values from the exception object and
     488             :     // push them onto the operand stack using the passed {values} vector.
     489             :     SetEnv(if_match_env);
     490             :     // TODO(mstarzinger): Can't use BUILD() here, GetExceptionValues() returns
     491             :     // TFNode** rather than TFNode*. Fix to add landing pads.
     492             :     TFNode** caught_values =
     493         376 :         builder_->GetExceptionValues(exception.node, imm.exception);
     494         623 :     for (size_t i = 0, e = values.size(); i < e; ++i) {
     495         496 :       values[i].node = caught_values[i];
     496             :     }
     497         375 :     BrOrRet(decoder, depth);
     498             : 
     499             :     // If the tags don't match we fall-through here.
     500             :     SetEnv(if_no_match_env);
     501         375 :   }
     502             : 
     503             :   void Catch(FullDecoder* decoder, Control* block, Value* exception) {
     504             :     DCHECK(block->is_try_catch());
     505             : 
     506         520 :     current_catch_ = block->previous_catch;  // Pop try scope.
     507             : 
     508             :     // The catch block is unreachable if no possible throws in the try block
     509             :     // exist. We only build a landing pad if some node in the try block can
     510             :     // (possibly) throw. Otherwise the catch environments remain empty.
     511         520 :     if (!block->try_info->might_throw()) {
     512           8 :       block->reachability = kSpecOnlyReachable;
     513             :       return;
     514             :     }
     515             : 
     516         512 :     SetEnv(block->try_info->catch_env);
     517             :     DCHECK_NOT_NULL(block->try_info->exception);
     518         512 :     exception->node = block->try_info->exception;
     519             :   }
     520             : 
     521       32606 :   void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
     522             :                 const MemoryAccessImmediate<validate>& imm, Value* result) {
     523       32660 :     TFNode** inputs = GetNodes(args);
     524       97952 :     TFNode* node = BUILD(AtomicOp, opcode, inputs, imm.alignment, imm.offset,
     525             :                          decoder->position());
     526       32683 :     if (result) result->node = node;
     527       32683 :   }
     528             : 
     529             :   void MemoryInit(FullDecoder* decoder,
     530             :                   const MemoryInitImmediate<validate>& imm, const Value& dst,
     531             :                   const Value& src, const Value& size) {
     532         160 :     BUILD(MemoryInit, imm.data_segment_index, dst.node, src.node, size.node,
     533          40 :           decoder->position());
     534             :   }
     535             :   void DataDrop(FullDecoder* decoder, const DataDropImmediate<validate>& imm) {
     536          72 :     BUILD(DataDrop, imm.index, decoder->position());
     537             :   }
     538             :   void MemoryCopy(FullDecoder* decoder,
     539             :                   const MemoryCopyImmediate<validate>& imm, const Value& dst,
     540             :                   const Value& src, const Value& size) {
     541          72 :     BUILD(MemoryCopy, dst.node, src.node, size.node, decoder->position());
     542             :   }
     543             :   void MemoryFill(FullDecoder* decoder,
     544             :                   const MemoryIndexImmediate<validate>& imm, const Value& dst,
     545             :                   const Value& value, const Value& size) {
     546          72 :     BUILD(MemoryFill, dst.node, value.node, size.node, decoder->position());
     547             :   }
     548             :   void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm,
     549             :                  Vector<Value> args) {
     550         125 :     BUILD(TableInit, imm.table.index, imm.elem_segment_index, args[0].node,
     551          31 :           args[1].node, args[2].node, decoder->position());
     552             :   }
     553             :   void ElemDrop(FullDecoder* decoder, const ElemDropImmediate<validate>& imm) {
     554          48 :     BUILD(ElemDrop, imm.index, decoder->position());
     555             :   }
     556             :   void TableCopy(FullDecoder* decoder, const TableCopyImmediate<validate>& imm,
     557             :                  Vector<Value> args) {
     558         256 :     BUILD(TableCopy, imm.table_src.index, imm.table_dst.index, args[0].node,
     559          64 :           args[1].node, args[2].node, decoder->position());
     560             :   }
     561             : 
     562             :  private:
     563             :   SsaEnv* ssa_env_;
     564             :   compiler::WasmGraphBuilder* builder_;
     565             :   uint32_t current_catch_ = kNullCatch;
     566             : 
     567             :   TryInfo* current_try_info(FullDecoder* decoder) {
     568         648 :     return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
     569         648 :         ->try_info;
     570             :   }
     571             : 
     572      596387 :   TFNode** GetNodes(Value* values, size_t count) {
     573      596387 :     TFNode** nodes = builder_->Buffer(count);
     574      602710 :     for (size_t i = 0; i < count; ++i) {
     575      602710 :       nodes[i] = values[i].node;
     576             :     }
     577      596520 :     return nodes;
     578             :   }
     579             : 
     580      596260 :   TFNode** GetNodes(Vector<Value> values) {
     581      596260 :     return GetNodes(values.start(), values.size());
     582             :   }
     583             : 
     584             :   void SetEnv(SsaEnv* env) {
     585             : #if DEBUG
     586             :     if (FLAG_trace_wasm_decoder) {
     587             :       char state = 'X';
     588             :       if (env) {
     589             :         switch (env->state) {
     590             :           case SsaEnv::kReached:
     591             :             state = 'R';
     592             :             break;
     593             :           case SsaEnv::kUnreachable:
     594             :             state = 'U';
     595             :             break;
     596             :           case SsaEnv::kMerged:
     597             :             state = 'M';
     598             :             break;
     599             :           case SsaEnv::kControlEnd:
     600             :             state = 'E';
     601             :             break;
     602             :         }
     603             :       }
     604             :       PrintF("{set_env = %p, state = %c", static_cast<void*>(env), state);
     605             :       if (env && env->control) {
     606             :         PrintF(", control = ");
     607             :         compiler::WasmGraphBuilder::PrintDebugName(env->control);
     608             :       }
     609             :       PrintF("}\n");
     610             :     }
     611             : #endif
     612     1078698 :     ssa_env_ = env;
     613             :     // TODO(wasm): combine the control and effect pointers with instance cache.
     614     1078698 :     builder_->set_control_ptr(&env->control);
     615     1078698 :     builder_->set_effect_ptr(&env->effect);
     616     1078698 :     builder_->set_instance_cache(&env->instance_cache);
     617             :   }
     618             : 
     619     2107178 :   TFNode* CheckForException(FullDecoder* decoder, TFNode* node) {
     620     2105882 :     if (node == nullptr) return nullptr;
     621             : 
     622     2104362 :     const bool inside_try_scope = current_catch_ != kNullCatch;
     623             : 
     624     2104362 :     if (!inside_try_scope) return node;
     625             : 
     626        1272 :     TFNode* if_success = nullptr;
     627        1272 :     TFNode* if_exception = nullptr;
     628        1272 :     if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
     629             :       return node;
     630             :     }
     631             : 
     632        1296 :     SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
     633         646 :     success_env->control = if_success;
     634             : 
     635         646 :     SsaEnv* exception_env = Split(decoder, success_env);
     636         648 :     exception_env->control = if_exception;
     637             :     TryInfo* try_info = current_try_info(decoder);
     638         648 :     Goto(decoder, exception_env, try_info->catch_env);
     639         648 :     TFNode* exception = try_info->exception;
     640         648 :     if (exception == nullptr) {
     641             :       DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
     642         512 :       try_info->exception = if_exception;
     643             :     } else {
     644             :       DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
     645             :       try_info->exception = builder_->CreateOrMergeIntoPhi(
     646             :           MachineRepresentation::kWord32, try_info->catch_env->control,
     647         136 :           try_info->exception, if_exception);
     648             :     }
     649             : 
     650             :     SetEnv(success_env);
     651         648 :     return node;
     652             :   }
     653             : 
     654       20465 :   TFNode* DefaultValue(ValueType type) {
     655       20465 :     switch (type) {
     656             :       case kWasmI32:
     657       10165 :         return builder_->Int32Constant(0);
     658             :       case kWasmI64:
     659        6367 :         return builder_->Int64Constant(0);
     660             :       case kWasmF32:
     661         416 :         return builder_->Float32Constant(0);
     662             :       case kWasmF64:
     663        1241 :         return builder_->Float64Constant(0);
     664             :       case kWasmS128:
     665        2156 :         return builder_->S128Zero();
     666             :       case kWasmAnyRef:
     667             :       case kWasmAnyFunc:
     668             :       case kWasmExceptRef:
     669         120 :         return builder_->RefNull();
     670             :       default:
     671           0 :         UNREACHABLE();
     672             :     }
     673             :   }
     674             : 
     675      350715 :   void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge) {
     676             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
     677             : 
     678      350715 :     SsaEnv* target = c->end_env;
     679      350715 :     const bool first = target->state == SsaEnv::kUnreachable;
     680      350715 :     Goto(decoder, ssa_env_, target);
     681             : 
     682      701449 :     if (merge->arity == 0) return;
     683             : 
     684             :     uint32_t avail =
     685       16751 :         decoder->stack_size() - decoder->control_at(0)->stack_depth;
     686             :     DCHECK_GE(avail, merge->arity);
     687       16751 :     uint32_t start = avail >= merge->arity ? 0 : merge->arity - avail;
     688             :     Value* stack_values = decoder->stack_value(merge->arity);
     689       16826 :     for (uint32_t i = start; i < merge->arity; ++i) {
     690       16823 :       Value& val = stack_values[i];
     691             :       Value& old = (*merge)[i];
     692             :       DCHECK_NOT_NULL(val.node);
     693             :       DCHECK(val.type == old.type || val.type == kWasmVar);
     694             :       old.node = first ? val.node
     695             :                        : builder_->CreateOrMergeIntoPhi(
     696             :                              ValueTypes::MachineRepresentationFor(old.type),
     697       16823 :                              target->control, old.node, val.node);
     698             :     }
     699             :   }
     700             : 
     701      351371 :   void Goto(FullDecoder* decoder, SsaEnv* from, SsaEnv* to) {
     702             :     DCHECK_NOT_NULL(to);
     703      351371 :     switch (to->state) {
     704             :       case SsaEnv::kUnreachable: {  // Overwrite destination.
     705      103373 :         to->state = SsaEnv::kReached;
     706      103373 :         to->locals = from->locals;
     707      103373 :         to->control = from->control;
     708      103373 :         to->effect = from->effect;
     709      103373 :         to->instance_cache = from->instance_cache;
     710             :         break;
     711             :       }
     712             :       case SsaEnv::kReached: {  // Create a new merge.
     713       34469 :         to->state = SsaEnv::kMerged;
     714             :         // Merge control.
     715       34469 :         TFNode* controls[] = {to->control, from->control};
     716       34469 :         TFNode* merge = builder_->Merge(2, controls);
     717       34470 :         to->control = merge;
     718             :         // Merge effects.
     719       34470 :         if (from->effect != to->effect) {
     720       21966 :           TFNode* effects[] = {to->effect, from->effect, merge};
     721       21966 :           to->effect = builder_->EffectPhi(2, effects, merge);
     722             :         }
     723             :         // Merge SSA values.
     724      719808 :         for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     725      685336 :           TFNode* a = to->locals[i];
     726      685336 :           TFNode* b = from->locals[i];
     727      685336 :           if (a != b) {
     728       60497 :             TFNode* vals[] = {a, b};
     729             :             to->locals[i] =
     730      120994 :                 builder_->Phi(decoder->GetLocalType(i), 2, vals, merge);
     731             :           }
     732             :         }
     733             :         // Start a new merge from the instance cache.
     734             :         builder_->NewInstanceCacheMerge(&to->instance_cache,
     735       34472 :                                         &from->instance_cache, merge);
     736             :         break;
     737             :       }
     738             :       case SsaEnv::kMerged: {
     739      213529 :         TFNode* merge = to->control;
     740             :         // Extend the existing merge control node.
     741      213529 :         builder_->AppendToMerge(merge, from->control);
     742             :         // Merge effects.
     743             :         to->effect = builder_->CreateOrMergeIntoEffectPhi(merge, to->effect,
     744      213530 :                                                           from->effect);
     745             :         // Merge locals.
     746      772355 :         for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     747             :           to->locals[i] = builder_->CreateOrMergeIntoPhi(
     748      558826 :               ValueTypes::MachineRepresentationFor(decoder->GetLocalType(i)),
     749     1117652 :               merge, to->locals[i], from->locals[i]);
     750             :         }
     751             :         // Merge the instance caches.
     752             :         builder_->MergeInstanceCacheInto(&to->instance_cache,
     753      213529 :                                          &from->instance_cache, merge);
     754             :         break;
     755             :       }
     756             :       default:
     757           0 :         UNREACHABLE();
     758             :     }
     759      351373 :     return from->Kill();
     760             :   }
     761             : 
     762       27261 :   SsaEnv* PrepareForLoop(FullDecoder* decoder, SsaEnv* env) {
     763        9090 :     env->state = SsaEnv::kMerged;
     764             : 
     765        9090 :     env->control = builder_->Loop(env->control);
     766        9089 :     env->effect = builder_->EffectPhi(1, &env->effect, env->control);
     767        9091 :     builder_->TerminateLoop(env->effect, env->control);
     768             :     // The '+ 1' here is to be able to set the instance cache as assigned.
     769             :     BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
     770       27262 :         decoder, decoder->pc(), decoder->total_locals() + 1, decoder->zone());
     771        9090 :     if (decoder->failed()) return env;
     772        9082 :     if (assigned != nullptr) {
     773             :       // Only introduce phis for variables assigned in this loop.
     774        9082 :       int instance_cache_index = decoder->total_locals();
     775      184638 :       for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     776      175556 :         if (!assigned->Contains(i)) continue;
     777       36742 :         env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
     778       73484 :                                        &env->locals[i], env->control);
     779             :       }
     780             :       // Introduce phis for instance cache pointers if necessary.
     781        9082 :       if (assigned->Contains(instance_cache_index)) {
     782             :         builder_->PrepareInstanceCacheForLoop(&env->instance_cache,
     783        4259 :                                               env->control);
     784             :       }
     785             : 
     786        9082 :       SsaEnv* loop_body_env = Split(decoder, env);
     787             :       builder_->StackCheck(decoder->position(), &(loop_body_env->effect),
     788       18162 :                            &(loop_body_env->control));
     789             :       return loop_body_env;
     790             :     }
     791             : 
     792             :     // Conservatively introduce phis for all local variables.
     793           0 :     for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     794           0 :       env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
     795           0 :                                      &env->locals[i], env->control);
     796             :     }
     797             : 
     798             :     // Conservatively introduce phis for instance cache.
     799           0 :     builder_->PrepareInstanceCacheForLoop(&env->instance_cache, env->control);
     800             : 
     801           0 :     SsaEnv* loop_body_env = Split(decoder, env);
     802             :     builder_->StackCheck(decoder->position(), &loop_body_env->effect,
     803           0 :                          &loop_body_env->control);
     804             :     return loop_body_env;
     805             :   }
     806             : 
     807             :   // Create a complete copy of {from}.
     808      613403 :   SsaEnv* Split(FullDecoder* decoder, SsaEnv* from) {
     809             :     DCHECK_NOT_NULL(from);
     810             :     SsaEnv* result =
     811      308836 :         reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
     812      308842 :     size_t size = sizeof(TFNode*) * decoder->num_locals();
     813      308842 :     result->control = from->control;
     814      308842 :     result->effect = from->effect;
     815             : 
     816      308842 :     result->state = SsaEnv::kReached;
     817      308842 :     if (size > 0) {
     818      304567 :       result->locals = reinterpret_cast<TFNode**>(decoder->zone()->New(size));
     819      304564 :       memcpy(result->locals, from->locals, size);
     820             :     } else {
     821        4275 :       result->locals = nullptr;
     822             :     }
     823      308839 :     result->instance_cache = from->instance_cache;
     824             : 
     825      308839 :     return result;
     826             :   }
     827             : 
     828             :   // Create a copy of {from} that steals its state and leaves {from}
     829             :   // unreachable.
     830      131145 :   SsaEnv* Steal(Zone* zone, SsaEnv* from) {
     831             :     DCHECK_NOT_NULL(from);
     832      131145 :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
     833      131144 :     result->state = SsaEnv::kReached;
     834      131144 :     result->locals = from->locals;
     835      131144 :     result->control = from->control;
     836      131144 :     result->effect = from->effect;
     837      131144 :     result->instance_cache = from->instance_cache;
     838             :     from->Kill(SsaEnv::kUnreachable);
     839      131144 :     return result;
     840             :   }
     841             : 
     842             :   // Create an unreachable environment.
     843             :   SsaEnv* UnreachableEnv(Zone* zone) {
     844             :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
     845             :     result->state = SsaEnv::kUnreachable;
     846             :     result->control = nullptr;
     847             :     result->effect = nullptr;
     848             :     result->locals = nullptr;
     849             :     result->instance_cache = {};
     850             :     return result;
     851             :   }
     852             : 
     853       64822 :   void DoCall(FullDecoder* decoder, TFNode* index_node, FunctionSig* sig,
     854             :               uint32_t index, const Value args[], Value returns[]) {
     855       32409 :     int param_count = static_cast<int>(sig->parameter_count());
     856       32409 :     TFNode** arg_nodes = builder_->Buffer(param_count + 1);
     857       32409 :     TFNode** return_nodes = nullptr;
     858       32409 :     arg_nodes[0] = index_node;
     859      103702 :     for (int i = 0; i < param_count; ++i) {
     860       71293 :       arg_nodes[i + 1] = args[i].node;
     861             :     }
     862       32409 :     if (index_node) {
     863        9855 :       BUILD(CallIndirect, index, arg_nodes, &return_nodes, decoder->position());
     864             :     } else {
     865       87370 :       BUILD(CallDirect, index, arg_nodes, &return_nodes, decoder->position());
     866             :     }
     867       32413 :     int return_count = static_cast<int>(sig->return_count());
     868       50447 :     for (int i = 0; i < return_count; ++i) {
     869       18034 :       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       32413 :     LoadContextIntoSsa(ssa_env_);
     874       32416 :   }
     875             : };
     876             : 
     877             : }  // namespace
     878             : 
     879      503585 : DecodeResult BuildTFGraph(AccountingAllocator* allocator,
     880             :                           const WasmFeatures& enabled,
     881             :                           const wasm::WasmModule* module,
     882             :                           compiler::WasmGraphBuilder* builder,
     883             :                           WasmFeatures* detected, const FunctionBody& body,
     884             :                           compiler::NodeOriginTable* node_origins) {
     885      503585 :   Zone zone(allocator, ZONE_NAME);
     886             :   WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
     887      503606 :       &zone, module, enabled, detected, body, builder);
     888      503591 :   if (node_origins) {
     889           0 :     builder->AddBytecodePositionDecorator(node_origins, &decoder);
     890             :   }
     891      503591 :   decoder.Decode();
     892      503488 :   if (node_origins) {
     893           0 :     builder->RemoveBytecodePositionDecorator();
     894             :   }
     895     1510619 :   return decoder.toResult(nullptr);
     896             : }
     897             : 
     898             : #undef BUILD
     899             : 
     900             : }  // namespace wasm
     901             : }  // namespace internal
     902      178779 : }  // namespace v8

Generated by: LCOV version 1.10