LCOV - code coverage report
Current view: top level - src/wasm - graph-builder-interface.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 371 380 97.6 %
Date: 2019-04-17 Functions: 73 73 100.0 %

          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      967398 :     state = new_state;
      41      967398 :     locals = nullptr;
      42      967398 :     control = nullptr;
      43      967398 :     effect = nullptr;
      44      967398 :     instance_cache = {};
      45             :   }
      46             :   void SetNotMerged() {
      47      140477 :     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     5138902 :         : 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         498 :     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      844424 :         : ControlBase(std::forward<Args>(args)...) {}
      94             :   };
      95             : 
      96             :   explicit WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder)
      97      628435 :       : builder_(builder) {}
      98             : 
      99      628867 :   void StartFunction(FullDecoder* decoder) {
     100             :     SsaEnv* ssa_env =
     101             :         reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
     102             :     uint32_t num_locals = decoder->num_locals();
     103             :     uint32_t env_count = num_locals;
     104      629382 :     size_t size = sizeof(TFNode*) * env_count;
     105      629382 :     ssa_env->state = SsaEnv::kReached;
     106             :     ssa_env->locals =
     107             :         size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
     108      629382 :                  : nullptr;
     109             : 
     110             :     // The first '+ 1' is needed by TF Start node, the second '+ 1' is for the
     111             :     // instance parameter.
     112      629324 :     TFNode* start = builder_->Start(
     113     1258648 :         static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
     114      628106 :     ssa_env->effect = start;
     115      628106 :     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      628106 :     builder_->set_effect_ptr(&ssa_env->effect);
     119      628106 :     builder_->set_control_ptr(&ssa_env->control);
     120             :     // Initialize the instance parameter (index 0).
     121      628106 :     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     1102037 :     for (; index < decoder->sig_->parameter_count(); ++index) {
     126      236382 :       ssa_env->locals[index] = builder_->Param(index + 1);
     127             :     }
     128      650210 :     while (index < num_locals) {
     129             :       ValueType type = decoder->GetLocalType(index);
     130       21196 :       TFNode* node = DefaultValue(type);
     131     1088045 :       while (index < num_locals && decoder->GetLocalType(index) == type) {
     132             :         // Do a whole run of like-typed locals at a time.
     133      354958 :         ssa_env->locals[index++] = node;
     134             :       }
     135             :     }
     136             :     LoadContextIntoSsa(ssa_env);
     137             :     SetEnv(ssa_env);
     138      628828 :   }
     139             : 
     140             :   // Reload the instance cache entries into the Ssa Environment.
     141             :   void LoadContextIntoSsa(SsaEnv* ssa_env) {
     142      775200 :     if (ssa_env) builder_->InitInstanceCache(&ssa_env->instance_cache);
     143             :   }
     144             : 
     145             :   void StartFunctionBody(FullDecoder* decoder, Control* block) {}
     146             : 
     147      618503 :   void FinishFunction(FullDecoder*) { builder_->PatchInStackCheckIfNeeded(); }
     148             : 
     149             :   void OnFirstError(FullDecoder*) {}
     150             : 
     151             :   void NextInstruction(FullDecoder*, WasmOpcode) {}
     152             : 
     153             :   void Block(FullDecoder* decoder, Control* block) {
     154             :     // The branch environment is the outer environment.
     155      167220 :     block->end_env = ssa_env_;
     156      167220 :     SetEnv(Steal(decoder->zone(), ssa_env_));
     157             :   }
     158             : 
     159        9610 :   void Loop(FullDecoder* decoder, Control* block) {
     160        9610 :     SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
     161        9611 :     block->end_env = finish_try_env;
     162             :     // The continue environment is the inner environment.
     163        9611 :     SetEnv(PrepareForLoop(decoder, finish_try_env));
     164        9607 :     ssa_env_->SetNotMerged();
     165        9607 :     if (!decoder->ok()) return;
     166             :     // Wrap input merge into phis.
     167        9670 :     for (uint32_t i = 0; i < block->start_merge.arity; ++i) {
     168             :       Value& val = block->start_merge[i];
     169          38 :       val.node = builder_->Phi(val.type, 1, &val.node, block->end_env->control);
     170             :     }
     171             :   }
     172             : 
     173         499 :   void Try(FullDecoder* decoder, Control* block) {
     174         499 :     SsaEnv* outer_env = ssa_env_;
     175         499 :     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         499 :     catch_env->state = SsaEnv::kUnreachable;
     179         499 :     SsaEnv* try_env = Steal(decoder->zone(), outer_env);
     180             :     SetEnv(try_env);
     181             :     TryInfo* try_info = new (decoder->zone()) TryInfo(catch_env);
     182         498 :     block->end_env = outer_env;
     183         498 :     block->try_info = try_info;
     184         498 :     block->previous_catch = current_catch_;
     185         498 :     current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
     186         498 :   }
     187             : 
     188       39130 :   void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
     189       39130 :     TFNode* if_true = nullptr;
     190       39130 :     TFNode* if_false = nullptr;
     191       78255 :     BUILD(BranchNoHint, cond.node, &if_true, &if_false);
     192       39136 :     SsaEnv* end_env = ssa_env_;
     193       39136 :     SsaEnv* false_env = Split(decoder, ssa_env_);
     194       39136 :     false_env->control = if_false;
     195       39136 :     SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
     196       39132 :     true_env->control = if_true;
     197       39132 :     if_block->end_env = end_env;
     198       39132 :     if_block->false_env = false_env;
     199             :     SetEnv(true_env);
     200       39132 :   }
     201             : 
     202             :   void FallThruTo(FullDecoder* decoder, Control* c) {
     203             :     DCHECK(!c->is_loop());
     204       32914 :     MergeValuesInto(decoder, c, &c->end_merge);
     205             :   }
     206             : 
     207      212450 :   void PopControl(FullDecoder* decoder, Control* block) {
     208             :     // A loop just continues with the end environment. There is no merge.
     209      212450 :     if (block->is_loop()) return;
     210             :     // Any other block falls through to the parent block.
     211      203249 :     if (block->reachable()) FallThruTo(decoder, block);
     212      203239 :     if (block->is_onearmed_if()) {
     213             :       // Merge the else branch into the end merge.
     214       20451 :       SetEnv(block->false_env);
     215       20451 :       MergeValuesInto(decoder, block, &block->end_merge);
     216             :     }
     217             :     // Now continue with the merged environment.
     218      203244 :     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      950769 :     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     3354248 :     auto node = BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
     231     1117802 :     if (result) result->node = node;
     232             :   }
     233             : 
     234             :   void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
     235     1950100 :     result->node = builder_->Int32Constant(value);
     236             :   }
     237             : 
     238             :   void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
     239       50917 :     result->node = builder_->Int64Constant(value);
     240             :   }
     241             : 
     242             :   void F32Const(FullDecoder* decoder, Value* result, float value) {
     243      118448 :     result->node = builder_->Float32Constant(value);
     244             :   }
     245             : 
     246             :   void F64Const(FullDecoder* decoder, Value* result, double value) {
     247      125403 :     result->node = builder_->Float64Constant(value);
     248             :   }
     249             : 
     250             :   void RefNull(FullDecoder* decoder, Value* result) {
     251         110 :     result->node = builder_->RefNull();
     252             :   }
     253             : 
     254             :   void Drop(FullDecoder* decoder, const Value& value) {}
     255             : 
     256      644633 :   void DoReturn(FullDecoder* decoder, Vector<Value> values) {
     257      644769 :     TFNode** nodes = GetNodes(values);
     258     1289568 :     BUILD(Return, static_cast<uint32_t>(values.size()), nodes);
     259      644341 :   }
     260             : 
     261             :   void GetLocal(FullDecoder* decoder, Value* result,
     262             :                 const LocalIndexImmediate<validate>& imm) {
     263      606971 :     if (!ssa_env_->locals) return;  // unreachable
     264      607049 :     result->node = ssa_env_->locals[imm.index];
     265             :   }
     266             : 
     267             :   void SetLocal(FullDecoder* decoder, const Value& value,
     268             :                 const LocalIndexImmediate<validate>& imm) {
     269      356924 :     if (!ssa_env_->locals) return;  // unreachable
     270      356925 :     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       98464 :     result->node = value.node;
     276       98464 :     if (!ssa_env_->locals) return;  // unreachable
     277       98464 :     ssa_env_->locals[imm.index] = value.node;
     278             :   }
     279             : 
     280             :   void GetGlobal(FullDecoder* decoder, Value* result,
     281             :                  const GlobalIndexImmediate<validate>& imm) {
     282       73197 :     result->node = BUILD(GetGlobal, imm.index);
     283             :   }
     284             : 
     285             :   void SetGlobal(FullDecoder* decoder, const Value& value,
     286             :                  const GlobalIndexImmediate<validate>& imm) {
     287       35246 :     BUILD(SetGlobal, imm.index, value.node);
     288             :   }
     289             : 
     290             :   void GetTable(FullDecoder* decoder, const Value& index, Value* result,
     291             :                 const TableIndexImmediate<validate>& imm) {
     292         195 :     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         132 :     BUILD(SetTable, imm.index, index.node, value.node, decoder->position());
     298             :   }
     299             : 
     300             :   void Unreachable(FullDecoder* decoder) {
     301      318494 :     BUILD(Unreachable, decoder->position());
     302             :   }
     303             : 
     304         854 :   void Select(FullDecoder* decoder, const Value& cond, const Value& fval,
     305             :               const Value& tval, Value* result) {
     306             :     TFNode* controls[2];
     307        1709 :     BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
     308        1708 :     TFNode* merge = BUILD(Merge, 2, controls);
     309         858 :     TFNode* vals[2] = {tval.node, fval.node};
     310        1717 :     TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
     311         857 :     result->node = phi;
     312         857 :     ssa_env_->control = merge;
     313         857 :   }
     314             : 
     315      347240 :   void BrOrRet(FullDecoder* decoder, uint32_t depth) {
     316      694480 :     if (depth == decoder->control_depth() - 1) {
     317         254 :       uint32_t ret_count = static_cast<uint32_t>(decoder->sig_->return_count());
     318             :       TFNode** values =
     319             :           ret_count == 0 ? nullptr
     320         398 :                          : GetNodes(decoder->stack_value(ret_count), ret_count);
     321         508 :       BUILD(Return, ret_count, values);
     322             :     } else {
     323             :       Br(decoder, decoder->control_at(depth));
     324             :     }
     325      347223 :   }
     326             : 
     327             :   void Br(FullDecoder* decoder, Control* target) {
     328      370044 :     MergeValuesInto(decoder, target, target->br_merge());
     329             :   }
     330             : 
     331      130872 :   void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) {
     332      130872 :     SsaEnv* fenv = ssa_env_;
     333      130872 :     SsaEnv* tenv = Split(decoder, fenv);
     334      130870 :     fenv->SetNotMerged();
     335      261742 :     BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
     336      130930 :     SetEnv(tenv);
     337      130930 :     BrOrRet(decoder, depth);
     338      130863 :     SetEnv(fenv);
     339      130863 :   }
     340             : 
     341        5318 :   void BrTable(FullDecoder* decoder, const BranchTableImmediate<validate>& imm,
     342             :                const Value& key) {
     343        5318 :     if (imm.table_count == 0) {
     344             :       // Only a default target. Do the equivalent of br.
     345         920 :       uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
     346         460 :       BrOrRet(decoder, target);
     347         461 :       return;
     348             :     }
     349             : 
     350        4858 :     SsaEnv* branch_env = ssa_env_;
     351             :     // Build branches to the various blocks based on the table.
     352        9717 :     TFNode* sw = BUILD(Switch, imm.table_count + 1, key.node);
     353             : 
     354        4860 :     SsaEnv* copy = Steal(decoder->zone(), branch_env);
     355             :     SetEnv(copy);
     356        4861 :     BranchTableIterator<validate> iterator(decoder, imm);
     357      435999 :     while (iterator.has_next()) {
     358      215570 :       uint32_t i = iterator.cur_index();
     359      215570 :       uint32_t target = iterator.next();
     360      215572 :       SetEnv(Split(decoder, copy));
     361      215572 :       ssa_env_->control =
     362      431144 :           (i == imm.table_count) ? BUILD(IfDefault, sw) : BUILD(IfValue, i, sw);
     363      215571 :       BrOrRet(decoder, target);
     364             :     }
     365             :     DCHECK(decoder->ok());
     366             :     SetEnv(branch_env);
     367             :   }
     368             : 
     369       18188 :   void Else(FullDecoder* decoder, Control* if_block) {
     370       18188 :     if (if_block->reachable()) {
     371             :       // Merge the if branch into the end merge.
     372       15055 :       MergeValuesInto(decoder, if_block, &if_block->end_merge);
     373             :     }
     374       18188 :     SetEnv(if_block->false_env);
     375       18188 :   }
     376             : 
     377             :   void LoadMem(FullDecoder* decoder, LoadType type,
     378             :                const MemoryAccessImmediate<validate>& imm, const Value& index,
     379             :                Value* result) {
     380             :     result->node =
     381      486283 :         BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
     382       97353 :               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      859271 :     BUILD(StoreMem, type.mem_rep(), index.node, imm.offset, imm.alignment,
     389      143241 :           value.node, decoder->position(), type.value_type());
     390             :   }
     391             : 
     392             :   void CurrentMemoryPages(FullDecoder* decoder, Value* result) {
     393         982 :     result->node = BUILD(CurrentMemoryPages);
     394             :   }
     395             : 
     396        1307 :   void MemoryGrow(FullDecoder* decoder, const Value& value, Value* result) {
     397        2614 :     result->node = BUILD(MemoryGrow, value.node);
     398             :     // Always reload the instance cache after growing memory.
     399        1306 :     LoadContextIntoSsa(ssa_env_);
     400        1309 :   }
     401             : 
     402             :   void CallDirect(FullDecoder* decoder,
     403             :                   const CallFunctionImmediate<validate>& imm,
     404             :                   const Value args[], Value returns[]) {
     405      141083 :     DoCall(decoder, 0, nullptr, imm.sig, imm.index, args, returns);
     406             :   }
     407             : 
     408             :   void ReturnCall(FullDecoder* decoder,
     409             :                   const CallFunctionImmediate<validate>& imm,
     410             :                   const Value args[]) {
     411         147 :     DoReturnCall(decoder, 0, nullptr, imm.sig, imm.index, args);
     412             :   }
     413             : 
     414             :   void CallIndirect(FullDecoder* decoder, const Value& index,
     415             :                     const CallIndirectImmediate<validate>& imm,
     416             :                     const Value args[], Value returns[]) {
     417             :     DoCall(decoder, imm.table_index, index.node, imm.sig, imm.sig_index, args,
     418        3871 :            returns);
     419             :   }
     420             : 
     421             :   void ReturnCallIndirect(FullDecoder* decoder, const Value& index,
     422             :                           const CallIndirectImmediate<validate>& imm,
     423             :                           const Value args[]) {
     424             :     DoReturnCall(decoder, imm.table_index, index.node, imm.sig, imm.sig_index,
     425          71 :                  args);
     426             :   }
     427             : 
     428        4320 :   void SimdOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
     429             :               Value* result) {
     430        4320 :     TFNode** inputs = GetNodes(args);
     431        8640 :     TFNode* node = BUILD(SimdOp, opcode, inputs);
     432        4320 :     if (result) result->node = node;
     433        4320 :   }
     434             : 
     435         784 :   void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
     436             :                   const SimdLaneImmediate<validate> imm, Vector<Value> inputs,
     437             :                   Value* result) {
     438         784 :     TFNode** nodes = GetNodes(inputs);
     439        1568 :     result->node = BUILD(SimdLaneOp, opcode, imm.lane, nodes);
     440         784 :   }
     441             : 
     442             :   void SimdShiftOp(FullDecoder* decoder, WasmOpcode opcode,
     443             :                    const SimdShiftImmediate<validate> imm, const Value& input,
     444             :                    Value* result) {
     445        1272 :     TFNode* inputs[] = {input.node};
     446        2544 :     result->node = BUILD(SimdShiftOp, opcode, imm.shift, inputs);
     447             :   }
     448             : 
     449             :   void Simd8x16ShuffleOp(FullDecoder* decoder,
     450             :                          const Simd8x16ShuffleImmediate<validate>& imm,
     451             :                          const Value& input0, const Value& input1,
     452             :                          Value* result) {
     453       14448 :     TFNode* input_nodes[] = {input0.node, input1.node};
     454       28896 :     result->node = BUILD(Simd8x16ShuffleOp, imm.shuffle, input_nodes);
     455             :   }
     456             : 
     457         551 :   void Throw(FullDecoder* decoder, const ExceptionIndexImmediate<validate>& imm,
     458             :              const Vector<Value>& value_args) {
     459             :     int count = value_args.length();
     460         551 :     ZoneVector<TFNode*> args(count, decoder->zone());
     461        1124 :     for (int i = 0; i < count; ++i) {
     462         572 :       args[i] = value_args[i].node;
     463             :     }
     464        1656 :     BUILD(Throw, imm.index, imm.exception, VectorOf(args));
     465         551 :     builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
     466         552 :   }
     467             : 
     468         405 :   void Rethrow(FullDecoder* decoder, const Value& exception) {
     469         810 :     BUILD(Rethrow, exception.node);
     470         406 :     builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
     471         407 :   }
     472             : 
     473         328 :   void BrOnException(FullDecoder* decoder, const Value& exception,
     474             :                      const ExceptionIndexImmediate<validate>& imm,
     475             :                      uint32_t depth, Vector<Value> values) {
     476         328 :     TFNode* if_match = nullptr;
     477         328 :     TFNode* if_no_match = nullptr;
     478             : 
     479             :     // Get the exception tag and see if it matches the expected one.
     480         656 :     TFNode* caught_tag = BUILD(GetExceptionTag, exception.node);
     481         660 :     TFNode* exception_tag = BUILD(LoadExceptionTagFromTable, imm.index);
     482         660 :     TFNode* compare = BUILD(ExceptionTagEqual, caught_tag, exception_tag);
     483         656 :     BUILD(BranchNoHint, compare, &if_match, &if_no_match);
     484         330 :     SsaEnv* if_no_match_env = Split(decoder, ssa_env_);
     485         329 :     SsaEnv* if_match_env = Steal(decoder->zone(), ssa_env_);
     486         329 :     if_no_match_env->control = if_no_match;
     487         329 :     if_match_env->control = if_match;
     488             : 
     489             :     // If the tags match we extract the values from the exception object and
     490             :     // push them onto the operand stack using the passed {values} vector.
     491             :     SetEnv(if_match_env);
     492             :     // TODO(mstarzinger): Can't use BUILD() here, GetExceptionValues() returns
     493             :     // TFNode** rather than TFNode*. Fix to add landing pads.
     494             :     TFNode** caught_values =
     495         329 :         builder_->GetExceptionValues(exception.node, imm.exception);
     496         748 :     for (size_t i = 0, e = values.size(); i < e; ++i) {
     497         209 :       values[i].node = caught_values[i];
     498             :     }
     499         330 :     BrOrRet(decoder, depth);
     500             : 
     501             :     // If the tags don't match we fall-through here.
     502             :     SetEnv(if_no_match_env);
     503         330 :   }
     504             : 
     505             :   void Catch(FullDecoder* decoder, Control* block, Value* exception) {
     506             :     DCHECK(block->is_try_catch());
     507             : 
     508         499 :     current_catch_ = block->previous_catch;  // Pop try scope.
     509             : 
     510             :     // The catch block is unreachable if no possible throws in the try block
     511             :     // exist. We only build a landing pad if some node in the try block can
     512             :     // (possibly) throw. Otherwise the catch environments remain empty.
     513         499 :     if (!block->try_info->might_throw()) {
     514          11 :       block->reachability = kSpecOnlyReachable;
     515             :       return;
     516             :     }
     517             : 
     518         488 :     SetEnv(block->try_info->catch_env);
     519             :     DCHECK_NOT_NULL(block->try_info->exception);
     520         488 :     exception->node = block->try_info->exception;
     521             :   }
     522             : 
     523       32506 :   void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
     524             :                 const MemoryAccessImmediate<validate>& imm, Value* result) {
     525       32645 :     TFNode** inputs = GetNodes(args);
     526       97885 :     TFNode* node = BUILD(AtomicOp, opcode, inputs, imm.alignment, imm.offset,
     527             :                          decoder->position());
     528       32955 :     if (result) result->node = node;
     529       32955 :   }
     530             : 
     531             :   void MemoryInit(FullDecoder* decoder,
     532             :                   const MemoryInitImmediate<validate>& imm, const Value& dst,
     533             :                   const Value& src, const Value& size) {
     534         304 :     BUILD(MemoryInit, imm.data_segment_index, dst.node, src.node, size.node,
     535          76 :           decoder->position());
     536             :   }
     537             :   void DataDrop(FullDecoder* decoder, const DataDropImmediate<validate>& imm) {
     538         147 :     BUILD(DataDrop, imm.index, decoder->position());
     539             :   }
     540             :   void MemoryCopy(FullDecoder* decoder,
     541             :                   const MemoryCopyImmediate<validate>& imm, const Value& dst,
     542             :                   const Value& src, const Value& size) {
     543         129 :     BUILD(MemoryCopy, dst.node, src.node, size.node, decoder->position());
     544             :   }
     545             :   void MemoryFill(FullDecoder* decoder,
     546             :                   const MemoryIndexImmediate<validate>& imm, const Value& dst,
     547             :                   const Value& value, const Value& size) {
     548         129 :     BUILD(MemoryFill, dst.node, value.node, size.node, decoder->position());
     549             :   }
     550             :   void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm,
     551             :                  Vector<Value> args) {
     552          96 :     BUILD(TableInit, imm.table.index, imm.elem_segment_index, args[0].node,
     553          24 :           args[1].node, args[2].node, decoder->position());
     554             :   }
     555             :   void ElemDrop(FullDecoder* decoder, const ElemDropImmediate<validate>& imm) {
     556          81 :     BUILD(ElemDrop, imm.index, decoder->position());
     557             :   }
     558             :   void TableCopy(FullDecoder* decoder, const TableCopyImmediate<validate>& imm,
     559             :                  Vector<Value> args) {
     560         204 :     BUILD(TableCopy, imm.table_src.index, imm.table_dst.index, args[0].node,
     561          51 :           args[1].node, args[2].node, decoder->position());
     562             :   }
     563             : 
     564             :  private:
     565             :   SsaEnv* ssa_env_;
     566             :   compiler::WasmGraphBuilder* builder_;
     567             :   uint32_t current_catch_ = kNullCatch;
     568             : 
     569             :   TryInfo* current_try_info(FullDecoder* decoder) {
     570         610 :     return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
     571         610 :         ->try_info;
     572             :   }
     573             : 
     574      682341 :   TFNode** GetNodes(Value* values, size_t count) {
     575      682341 :     TFNode** nodes = builder_->Buffer(count);
     576     1841956 :     for (size_t i = 0; i < count; ++i) {
     577      579677 :       nodes[i] = values[i].node;
     578             :     }
     579      682602 :     return nodes;
     580             :   }
     581             : 
     582             :   TFNode** GetNodes(Vector<Value> values) {
     583      682243 :     return GetNodes(values.start(), values.size());
     584             :   }
     585             : 
     586             :   void SetEnv(SsaEnv* env) {
     587             : #if DEBUG
     588             :     if (FLAG_trace_wasm_decoder) {
     589             :       char state = 'X';
     590             :       if (env) {
     591             :         switch (env->state) {
     592             :           case SsaEnv::kReached:
     593             :             state = 'R';
     594             :             break;
     595             :           case SsaEnv::kUnreachable:
     596             :             state = 'U';
     597             :             break;
     598             :           case SsaEnv::kMerged:
     599             :             state = 'M';
     600             :             break;
     601             :           case SsaEnv::kControlEnd:
     602             :             state = 'E';
     603             :             break;
     604             :         }
     605             :       }
     606             :       PrintF("{set_env = %p, state = %c", static_cast<void*>(env), state);
     607             :       if (env && env->control) {
     608             :         PrintF(", control = ");
     609             :         compiler::WasmGraphBuilder::PrintDebugName(env->control);
     610             :       }
     611             :       PrintF("}\n");
     612             :     }
     613             : #endif
     614     1575983 :     ssa_env_ = env;
     615             :     // TODO(wasm): combine the control and effect pointers with instance cache.
     616     1575983 :     builder_->set_control_ptr(&env->control);
     617     1575983 :     builder_->set_effect_ptr(&env->effect);
     618     1575983 :     builder_->set_instance_cache(&env->instance_cache);
     619             :   }
     620             : 
     621     3075979 :   TFNode* CheckForException(FullDecoder* decoder, TFNode* node) {
     622     3075979 :     if (node == nullptr) return nullptr;
     623             : 
     624     2969899 :     const bool inside_try_scope = current_catch_ != kNullCatch;
     625             : 
     626     2969899 :     if (!inside_try_scope) return node;
     627             : 
     628        1194 :     TFNode* if_success = nullptr;
     629        1194 :     TFNode* if_exception = nullptr;
     630        1194 :     if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
     631             :       return node;
     632             :     }
     633             : 
     634         610 :     SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
     635         610 :     success_env->control = if_success;
     636             : 
     637         610 :     SsaEnv* exception_env = Split(decoder, success_env);
     638         610 :     exception_env->control = if_exception;
     639             :     TryInfo* try_info = current_try_info(decoder);
     640         610 :     Goto(decoder, exception_env, try_info->catch_env);
     641         610 :     TFNode* exception = try_info->exception;
     642         610 :     if (exception == nullptr) {
     643             :       DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
     644         489 :       try_info->exception = if_exception;
     645             :     } else {
     646             :       DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
     647         242 :       try_info->exception = builder_->CreateOrMergeIntoPhi(
     648         121 :           MachineRepresentation::kWord32, try_info->catch_env->control,
     649         121 :           try_info->exception, if_exception);
     650             :     }
     651             : 
     652             :     SetEnv(success_env);
     653         610 :     return node;
     654             :   }
     655             : 
     656       21194 :   TFNode* DefaultValue(ValueType type) {
     657       21194 :     switch (type) {
     658             :       case kWasmI32:
     659       10387 :         return builder_->Int32Constant(0);
     660             :       case kWasmI64:
     661        6712 :         return builder_->Int64Constant(0);
     662             :       case kWasmF32:
     663         476 :         return builder_->Float32Constant(0);
     664             :       case kWasmF64:
     665        1300 :         return builder_->Float64Constant(0);
     666             :       case kWasmS128:
     667        2177 :         return builder_->S128Zero();
     668             :       case kWasmAnyRef:
     669             :       case kWasmAnyFunc:
     670             :       case kWasmExceptRef:
     671         142 :         return builder_->RefNull();
     672             :       default:
     673           0 :         UNREACHABLE();
     674             :     }
     675             :   }
     676             : 
     677      438430 :   void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge) {
     678             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
     679             : 
     680      438430 :     SsaEnv* target = c->end_env;
     681      438430 :     const bool first = target->state == SsaEnv::kUnreachable;
     682      438430 :     Goto(decoder, ssa_env_, target);
     683             : 
     684      438430 :     if (merge->arity == 0) return;
     685             : 
     686             :     uint32_t avail =
     687       17174 :         decoder->stack_size() - decoder->control_at(0)->stack_depth;
     688             :     DCHECK_GE(avail, merge->arity);
     689       17174 :     uint32_t start = avail >= merge->arity ? 0 : merge->arity - avail;
     690             :     Value* stack_values = decoder->stack_value(merge->arity);
     691       51724 :     for (uint32_t i = start; i < merge->arity; ++i) {
     692       17271 :       Value& val = stack_values[i];
     693             :       Value& old = (*merge)[i];
     694             :       DCHECK_NOT_NULL(val.node);
     695             :       DCHECK(val.type == old.type || val.type == kWasmVar);
     696             :       old.node = first ? val.node
     697       14072 :                        : builder_->CreateOrMergeIntoPhi(
     698        7036 :                              ValueTypes::MachineRepresentationFor(old.type),
     699       24307 :                              target->control, old.node, val.node);
     700             :     }
     701             :   }
     702             : 
     703      439058 :   void Goto(FullDecoder* decoder, SsaEnv* from, SsaEnv* to) {
     704             :     DCHECK_NOT_NULL(to);
     705      439058 :     switch (to->state) {
     706             :       case SsaEnv::kUnreachable: {  // Overwrite destination.
     707      190666 :         to->state = SsaEnv::kReached;
     708      190666 :         to->locals = from->locals;
     709      190666 :         to->control = from->control;
     710      190666 :         to->effect = from->effect;
     711      190666 :         to->instance_cache = from->instance_cache;
     712             :         break;
     713             :       }
     714             :       case SsaEnv::kReached: {  // Create a new merge.
     715       34692 :         to->state = SsaEnv::kMerged;
     716             :         // Merge control.
     717       34692 :         TFNode* controls[] = {to->control, from->control};
     718       34692 :         TFNode* merge = builder_->Merge(2, controls);
     719       34697 :         to->control = merge;
     720             :         // Merge effects.
     721       34697 :         if (from->effect != to->effect) {
     722       22105 :           TFNode* effects[] = {to->effect, from->effect, merge};
     723       22105 :           to->effect = builder_->EffectPhi(2, effects, merge);
     724             :         }
     725             :         // Merge SSA values.
     726      720360 :         for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     727      685661 :           TFNode* a = to->locals[i];
     728      685661 :           TFNode* b = from->locals[i];
     729      685661 :           if (a != b) {
     730       60532 :             TFNode* vals[] = {a, b};
     731             :             to->locals[i] =
     732      121064 :                 builder_->Phi(decoder->GetLocalType(i), 2, vals, merge);
     733             :           }
     734             :         }
     735             :         // Start a new merge from the instance cache.
     736       34699 :         builder_->NewInstanceCacheMerge(&to->instance_cache,
     737       34699 :                                         &from->instance_cache, merge);
     738             :         break;
     739             :       }
     740             :       case SsaEnv::kMerged: {
     741      213700 :         TFNode* merge = to->control;
     742             :         // Extend the existing merge control node.
     743      213700 :         builder_->AppendToMerge(merge, from->control);
     744             :         // Merge effects.
     745      213698 :         to->effect = builder_->CreateOrMergeIntoEffectPhi(merge, to->effect,
     746      213702 :                                                           from->effect);
     747             :         // Merge locals.
     748      772833 :         for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     749     2236528 :           to->locals[i] = builder_->CreateOrMergeIntoPhi(
     750      559132 :               ValueTypes::MachineRepresentationFor(decoder->GetLocalType(i)),
     751     1677395 :               merge, to->locals[i], from->locals[i]);
     752             :         }
     753             :         // Merge the instance caches.
     754      213701 :         builder_->MergeInstanceCacheInto(&to->instance_cache,
     755      213701 :                                          &from->instance_cache, merge);
     756             :         break;
     757             :       }
     758             :       default:
     759           0 :         UNREACHABLE();
     760             :     }
     761      439062 :     return from->Kill();
     762             :   }
     763             : 
     764        9611 :   SsaEnv* PrepareForLoop(FullDecoder* decoder, SsaEnv* env) {
     765        9611 :     env->state = SsaEnv::kMerged;
     766             : 
     767        9611 :     env->control = builder_->Loop(env->control);
     768        9611 :     env->effect = builder_->EffectPhi(1, &env->effect, env->control);
     769        9613 :     builder_->TerminateLoop(env->effect, env->control);
     770             :     // The '+ 1' here is to be able to set the instance cache as assigned.
     771        9609 :     BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
     772        9609 :         decoder, decoder->pc(), decoder->total_locals() + 1, decoder->zone());
     773        9611 :     if (decoder->failed()) return env;
     774        9595 :     if (assigned != nullptr) {
     775             :       // Only introduce phis for variables assigned in this loop.
     776        9595 :       int instance_cache_index = decoder->total_locals();
     777      185670 :       for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     778      176074 :         if (!assigned->Contains(i)) continue;
     779       73812 :         env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
     780       36907 :                                        &env->locals[i], env->control);
     781             :       }
     782             :       // Introduce phis for instance cache pointers if necessary.
     783        9596 :       if (assigned->Contains(instance_cache_index)) {
     784        4381 :         builder_->PrepareInstanceCacheForLoop(&env->instance_cache,
     785        4381 :                                               env->control);
     786             :       }
     787             : 
     788        9597 :       SsaEnv* loop_body_env = Split(decoder, env);
     789       19196 :       builder_->StackCheck(decoder->position(), &(loop_body_env->effect),
     790        9598 :                            &(loop_body_env->control));
     791             :       return loop_body_env;
     792             :     }
     793             : 
     794             :     // Conservatively introduce phis for all local variables.
     795           0 :     for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     796           0 :       env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
     797           0 :                                      &env->locals[i], env->control);
     798             :     }
     799             : 
     800             :     // Conservatively introduce phis for instance cache.
     801           0 :     builder_->PrepareInstanceCacheForLoop(&env->instance_cache, env->control);
     802             : 
     803           0 :     SsaEnv* loop_body_env = Split(decoder, env);
     804           0 :     builder_->StackCheck(decoder->position(), &loop_body_env->effect,
     805           0 :                          &loop_body_env->control);
     806             :     return loop_body_env;
     807             :   }
     808             : 
     809             :   // Create a complete copy of {from}.
     810      396603 :   SsaEnv* Split(FullDecoder* decoder, SsaEnv* from) {
     811             :     DCHECK_NOT_NULL(from);
     812             :     SsaEnv* result =
     813             :         reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
     814      396614 :     size_t size = sizeof(TFNode*) * decoder->num_locals();
     815      396614 :     result->control = from->control;
     816      396614 :     result->effect = from->effect;
     817             : 
     818      396614 :     result->state = SsaEnv::kReached;
     819      396614 :     if (size > 0) {
     820      287474 :       result->locals = reinterpret_cast<TFNode**>(decoder->zone()->New(size));
     821      287473 :       memcpy(result->locals, from->locals, size);
     822             :     } else {
     823      109140 :       result->locals = nullptr;
     824             :     }
     825      396613 :     result->instance_cache = from->instance_cache;
     826             : 
     827      396613 :     return result;
     828             :   }
     829             : 
     830             :   // Create a copy of {from} that steals its state and leaves {from}
     831             :   // unreachable.
     832      222241 :   SsaEnv* Steal(Zone* zone, SsaEnv* from) {
     833             :     DCHECK_NOT_NULL(from);
     834             :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
     835      222241 :     result->state = SsaEnv::kReached;
     836      222241 :     result->locals = from->locals;
     837      222241 :     result->control = from->control;
     838      222241 :     result->effect = from->effect;
     839      222241 :     result->instance_cache = from->instance_cache;
     840             :     from->Kill(SsaEnv::kUnreachable);
     841      222241 :     return result;
     842             :   }
     843             : 
     844             :   // Create an unreachable environment.
     845             :   SsaEnv* UnreachableEnv(Zone* zone) {
     846             :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
     847             :     result->state = SsaEnv::kUnreachable;
     848             :     result->control = nullptr;
     849             :     result->effect = nullptr;
     850             :     result->locals = nullptr;
     851             :     result->instance_cache = {};
     852             :     return result;
     853             :   }
     854             : 
     855      144870 :   void DoCall(FullDecoder* decoder, uint32_t table_index, TFNode* index_node,
     856             :               FunctionSig* sig, uint32_t sig_index, const Value args[],
     857             :               Value returns[]) {
     858      144870 :     int param_count = static_cast<int>(sig->parameter_count());
     859      144870 :     TFNode** arg_nodes = builder_->Buffer(param_count + 1);
     860      144890 :     TFNode** return_nodes = nullptr;
     861      144890 :     arg_nodes[0] = index_node;
     862      749096 :     for (int i = 0; i < param_count; ++i) {
     863      302103 :       arg_nodes[i + 1] = args[i].node;
     864             :     }
     865      144890 :     if (index_node) {
     866       15517 :       BUILD(CallIndirect, table_index, sig_index, arg_nodes, &return_nodes,
     867        3870 :             decoder->position());
     868             :     } else {
     869      564023 :       BUILD(CallDirect, sig_index, arg_nodes, &return_nodes,
     870      141020 :             decoder->position());
     871             :     }
     872      144880 :     int return_count = static_cast<int>(sig->return_count());
     873      397542 :     for (int i = 0; i < return_count; ++i) {
     874      126331 :       returns[i].node = return_nodes[i];
     875             :     }
     876             :     // The invoked function could have used grow_memory, so we need to
     877             :     // reload mem_size and mem_start.
     878      144880 :     LoadContextIntoSsa(ssa_env_);
     879      144991 :   }
     880             : 
     881         218 :   void DoReturnCall(FullDecoder* decoder, uint32_t table_index,
     882             :                     TFNode* index_node, FunctionSig* sig, uint32_t sig_index,
     883             :                     const Value args[]) {
     884         218 :     int arg_count = static_cast<int>(sig->parameter_count());
     885         218 :     TFNode** arg_nodes = builder_->Buffer(arg_count + 1);
     886         218 :     arg_nodes[0] = index_node;
     887        1180 :     for (int i = 0; i < arg_count; ++i) {
     888         481 :       arg_nodes[i + 1] = args[i].node;
     889             :     }
     890         218 :     if (index_node) {
     891         284 :       BUILD(ReturnCallIndirect, table_index, sig_index, arg_nodes,
     892          71 :             decoder->position());
     893             :     } else {
     894         443 :       BUILD(ReturnCall, sig_index, arg_nodes, decoder->position());
     895             :     }
     896         218 :   }
     897             : };
     898             : 
     899             : }  // namespace
     900             : 
     901      628730 : DecodeResult BuildTFGraph(AccountingAllocator* allocator,
     902             :                           const WasmFeatures& enabled, const WasmModule* module,
     903             :                           compiler::WasmGraphBuilder* builder,
     904             :                           WasmFeatures* detected, const FunctionBody& body,
     905             :                           compiler::NodeOriginTable* node_origins) {
     906     1256351 :   Zone zone(allocator, ZONE_NAME);
     907             :   WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
     908             :       &zone, module, enabled, detected, body, builder);
     909      628435 :   if (node_origins) {
     910           8 :     builder->AddBytecodePositionDecorator(node_origins, &decoder);
     911             :   }
     912      628435 :   decoder.Decode();
     913      627534 :   if (node_origins) {
     914           8 :     builder->RemoveBytecodePositionDecorator();
     915             :   }
     916     1883613 :   return decoder.toResult(nullptr);
     917             : }
     918             : 
     919             : #undef BUILD
     920             : 
     921             : }  // namespace wasm
     922             : }  // namespace internal
     923      122004 : }  // namespace v8

Generated by: LCOV version 1.10