LCOV - code coverage report
Current view: top level - src/wasm - graph-builder-interface.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 347 357 97.2 %
Date: 2019-01-20 Functions: 70 70 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      800514 :     state = new_state;
      41      800514 :     locals = nullptr;
      42      800514 :     control = nullptr;
      43      800514 :     effect = nullptr;
      44      800514 :     instance_cache = {};
      45             :   }
      46             :   void SetNotMerged() {
      47       42165 :     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    13264585 :         : 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         502 :     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     2510630 :         : ControlBase(std::forward<Args>(args)...) {}
      94             :   };
      95             : 
      96             :   explicit WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder)
      97     1067446 :       : builder_(builder) {}
      98             : 
      99     1193305 :   void StartFunction(FullDecoder* decoder) {
     100             :     SsaEnv* ssa_env =
     101     1067540 :         reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
     102             :     uint32_t num_locals = decoder->num_locals();
     103             :     uint32_t env_count = num_locals;
     104     1067642 :     size_t size = sizeof(TFNode*) * env_count;
     105     1067642 :     ssa_env->state = SsaEnv::kReached;
     106             :     ssa_env->locals =
     107             :         size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
     108     1193407 :                  : 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     2385359 :         static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
     114     1067498 :     ssa_env->effect = start;
     115     1067498 :     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     1067498 :     builder_->set_effect_ptr(&ssa_env->effect);
     119     1067498 :     builder_->set_control_ptr(&ssa_env->control);
     120             :     // Initialize the instance parameter (index 0).
     121     1067498 :     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     3702945 :     for (; index < decoder->sig_->parameter_count(); ++index) {
     126      250219 :       ssa_env->locals[index] = builder_->Param(index + 1);
     127             :     }
     128     1108279 :     while (index < num_locals) {
     129             :       ValueType type = decoder->GetLocalType(index);
     130       40743 :       TFNode* node = DefaultValue(type);
     131     1086128 :       while (index < num_locals && decoder->GetLocalType(index) == type) {
     132             :         // Do a whole run of like-typed locals at a time.
     133      501145 :         ssa_env->locals[index++] = node;
     134             :       }
     135             :     }
     136             :     LoadContextIntoSsa(ssa_env);
     137             :     SetEnv(ssa_env);
     138     1067507 :   }
     139             : 
     140             :   // Reload the instance cache entries into the Ssa Environment.
     141             :   void LoadContextIntoSsa(SsaEnv* ssa_env) {
     142     1108320 :     if (ssa_env) builder_->InitInstanceCache(&ssa_env->instance_cache);
     143             :   }
     144             : 
     145             :   void StartFunctionBody(FullDecoder* decoder, Control* block) {}
     146             : 
     147     1060701 :   void FinishFunction(FullDecoder*) { builder_->PatchInStackCheckIfNeeded(); }
     148             : 
     149             :   void OnFirstError(FullDecoder*) {}
     150             : 
     151             :   void NextInstruction(FullDecoder*, WasmOpcode) {}
     152             : 
     153      195416 :   void Block(FullDecoder* decoder, Control* block) {
     154             :     // The branch environment is the outer environment.
     155       97708 :     block->end_env = ssa_env_;
     156      195416 :     SetEnv(Steal(decoder->zone(), ssa_env_));
     157       97708 :   }
     158             : 
     159       21348 :   void Loop(FullDecoder* decoder, Control* block) {
     160       21348 :     SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
     161       10675 :     block->end_env = finish_try_env;
     162             :     // The continue environment is the inner environment.
     163       10675 :     SetEnv(PrepareForLoop(decoder, finish_try_env));
     164       10677 :     ssa_env_->SetNotMerged();
     165       21354 :     if (!decoder->ok()) return;
     166             :     // Wrap input merge into phis.
     167          36 :     for (uint32_t i = 0; i < block->start_merge.arity; ++i) {
     168             :       Value& val = block->start_merge[i];
     169          36 :       val.node = builder_->Phi(val.type, 1, &val.node, block->end_env->control);
     170             :     }
     171             :   }
     172             : 
     173        1510 :   void Try(FullDecoder* decoder, Control* block) {
     174         504 :     SsaEnv* outer_env = ssa_env_;
     175         504 :     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         504 :     catch_env->state = SsaEnv::kUnreachable;
     179         504 :     SsaEnv* try_env = Steal(decoder->zone(), outer_env);
     180             :     SetEnv(try_env);
     181             :     TryInfo* try_info = new (decoder->zone()) TryInfo(catch_env);
     182         502 :     block->end_env = outer_env;
     183         502 :     block->try_info = try_info;
     184         502 :     block->previous_catch = current_catch_;
     185         502 :     current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
     186         502 :   }
     187             : 
     188       78755 :   void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
     189       78755 :     TFNode* if_true = nullptr;
     190       78755 :     TFNode* if_false = nullptr;
     191      157510 :     BUILD(BranchNoHint, cond.node, &if_true, &if_false);
     192       78760 :     SsaEnv* end_env = ssa_env_;
     193      157520 :     SsaEnv* false_env = Split(decoder, ssa_env_);
     194       78760 :     false_env->control = if_false;
     195      157520 :     SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
     196       78759 :     true_env->control = if_true;
     197       78759 :     if_block->end_env = end_env;
     198       78759 :     if_block->false_env = false_env;
     199             :     SetEnv(true_env);
     200       78759 :   }
     201             : 
     202       38274 :   void FallThruTo(FullDecoder* decoder, Control* c) {
     203             :     DCHECK(!c->is_loop());
     204       76548 :     MergeValuesInto(decoder, c, &c->end_merge);
     205             :   }
     206             : 
     207      242452 :   void PopControl(FullDecoder* decoder, Control* block) {
     208             :     // A loop just continues with the end environment. There is no merge.
     209      544704 :     if (block->is_loop()) return;
     210             :     // Any other block falls through to the parent block.
     211      174587 :     if (block->reachable()) FallThruTo(decoder, block);
     212      174591 :     if (block->is_onearmed_if()) {
     213             :       // Merge the else branch into the end merge.
     214       57397 :       SetEnv(block->false_env);
     215      114794 :       MergeValuesInto(decoder, block, &block->end_merge);
     216             :     }
     217             :     // Now continue with the merged environment.
     218      174590 :     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      377178 :     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     4058420 :     auto node = BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
     231     1352807 :     if (result) result->node = node;
     232             :   }
     233             : 
     234             :   void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
     235     3048088 :     result->node = builder_->Int32Constant(value);
     236             :   }
     237             : 
     238             :   void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
     239       24881 :     result->node = builder_->Int64Constant(value);
     240             :   }
     241             : 
     242             :   void F32Const(FullDecoder* decoder, Value* result, float value) {
     243        3978 :     result->node = builder_->Float32Constant(value);
     244             :   }
     245             : 
     246             :   void F64Const(FullDecoder* decoder, Value* result, double value) {
     247       11786 :     result->node = builder_->Float64Constant(value);
     248             :   }
     249             : 
     250             :   void RefNull(FullDecoder* decoder, Value* result) {
     251          45 :     result->node = builder_->RefNull();
     252             :   }
     253             : 
     254             :   void Drop(FullDecoder* decoder, const Value& value) {}
     255             : 
     256     1134917 :   void DoReturn(FullDecoder* decoder, Vector<Value> values) {
     257     1135031 :     TFNode** nodes = GetNodes(values);
     258     2270042 :     BUILD(Return, static_cast<uint32_t>(values.size()), nodes);
     259     1134985 :   }
     260             : 
     261             :   void GetLocal(FullDecoder* decoder, Value* result,
     262             :                 const LocalIndexImmediate<validate>& imm) {
     263      853883 :     if (!ssa_env_->locals) return;  // unreachable
     264      853880 :     result->node = ssa_env_->locals[imm.index];
     265             :   }
     266             : 
     267             :   void SetLocal(FullDecoder* decoder, const Value& value,
     268             :                 const LocalIndexImmediate<validate>& imm) {
     269      512163 :     if (!ssa_env_->locals) return;  // unreachable
     270      512167 :     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      115521 :     result->node = value.node;
     276      115521 :     if (!ssa_env_->locals) return;  // unreachable
     277      115521 :     ssa_env_->locals[imm.index] = value.node;
     278             :   }
     279             : 
     280             :   void GetGlobal(FullDecoder* decoder, Value* result,
     281             :                  const GlobalIndexImmediate<validate>& imm) {
     282      127348 :     result->node = BUILD(GetGlobal, imm.index);
     283             :   }
     284             : 
     285             :   void SetGlobal(FullDecoder* decoder, const Value& value,
     286             :                  const GlobalIndexImmediate<validate>& imm) {
     287       45440 :     BUILD(SetGlobal, imm.index, value.node);
     288             :   }
     289             : 
     290             :   void Unreachable(FullDecoder* decoder) {
     291        5382 :     BUILD(Unreachable, decoder->position());
     292             :   }
     293             : 
     294         943 :   void Select(FullDecoder* decoder, const Value& cond, const Value& fval,
     295             :               const Value& tval, Value* result) {
     296             :     TFNode* controls[2];
     297        1886 :     BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
     298        1892 :     TFNode* merge = BUILD(Merge, 2, controls);
     299         948 :     TFNode* vals[2] = {tval.node, fval.node};
     300        1896 :     TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
     301         948 :     result->node = phi;
     302         948 :     ssa_env_->control = merge;
     303         948 :   }
     304             : 
     305      298060 :   void BrOrRet(FullDecoder* decoder, uint32_t depth) {
     306      595768 :     if (depth == decoder->control_depth() - 1) {
     307         266 :       uint32_t ret_count = static_cast<uint32_t>(decoder->sig_->return_count());
     308             :       TFNode** values =
     309             :           ret_count == 0 ? nullptr
     310         442 :                          : GetNodes(decoder->stack_value(ret_count), ret_count);
     311         532 :       BUILD(Return, ret_count, values);
     312             :     } else {
     313             :       Br(decoder, decoder->control_at(depth));
     314             :     }
     315      297894 :   }
     316             : 
     317      324607 :   void Br(FullDecoder* decoder, Control* target) {
     318      324607 :     MergeValuesInto(decoder, target, target->br_merge());
     319             :   }
     320             : 
     321       31488 :   void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) {
     322       31488 :     SsaEnv* fenv = ssa_env_;
     323       31488 :     SsaEnv* tenv = Split(decoder, fenv);
     324       31488 :     fenv->SetNotMerged();
     325       62974 :     BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
     326       31488 :     SetEnv(tenv);
     327       31488 :     BrOrRet(decoder, depth);
     328       31490 :     SetEnv(fenv);
     329       31490 :   }
     330             : 
     331       11742 :   void BrTable(FullDecoder* decoder, const BranchTableImmediate<validate>& imm,
     332             :                const Value& key) {
     333       11742 :     if (imm.table_count == 0) {
     334             :       // Only a default target. Do the equivalent of br.
     335       12266 :       uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
     336         525 :       BrOrRet(decoder, target);
     337       12267 :       return;
     338             :     }
     339             : 
     340       11217 :     SsaEnv* branch_env = ssa_env_;
     341             :     // Build branches to the various blocks based on the table.
     342       22434 :     TFNode* sw = BUILD(Switch, imm.table_count + 1, key.node);
     343             : 
     344       22432 :     SsaEnv* copy = Steal(decoder->zone(), branch_env);
     345             :     SetEnv(copy);
     346       11216 :     BranchTableIterator<validate> iterator(decoder, imm);
     347      276672 :     while (iterator.has_next()) {
     348      265455 :       uint32_t i = iterator.cur_index();
     349      265455 :       uint32_t target = iterator.next();
     350      265455 :       SetEnv(Split(decoder, copy));
     351             :       ssa_env_->control =
     352      530902 :           (i == imm.table_count) ? BUILD(IfDefault, sw) : BUILD(IfValue, i, sw);
     353      265454 :       BrOrRet(decoder, target);
     354             :     }
     355             :     DCHECK(decoder->ok());
     356             :     SetEnv(branch_env);
     357             :   }
     358             : 
     359       38489 :   void Else(FullDecoder* decoder, Control* if_block) {
     360       21073 :     if (if_block->reachable()) {
     361             :       // Merge the if branch into the end merge.
     362       34832 :       MergeValuesInto(decoder, if_block, &if_block->end_merge);
     363             :     }
     364       21073 :     SetEnv(if_block->false_env);
     365       21073 :   }
     366             : 
     367             :   void LoadMem(FullDecoder* decoder, LoadType type,
     368             :                const MemoryAccessImmediate<validate>& imm, const Value& index,
     369             :                Value* result) {
     370             :     result->node =
     371      992805 :         BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
     372      198560 :               imm.offset, imm.alignment, decoder->position());
     373             :   }
     374             : 
     375             :   void StoreMem(FullDecoder* decoder, StoreType type,
     376             :                 const MemoryAccessImmediate<validate>& imm, const Value& index,
     377             :                 const Value& value) {
     378     1547581 :     BUILD(StoreMem, type.mem_rep(), index.node, imm.offset, imm.alignment,
     379      257933 :           value.node, decoder->position(), type.value_type());
     380             :   }
     381             : 
     382             :   void CurrentMemoryPages(FullDecoder* decoder, Value* result) {
     383         828 :     result->node = BUILD(CurrentMemoryPages);
     384             :   }
     385             : 
     386        1280 :   void MemoryGrow(FullDecoder* decoder, const Value& value, Value* result) {
     387        2560 :     result->node = BUILD(MemoryGrow, value.node);
     388             :     // Always reload the instance cache after growing memory.
     389        1280 :     LoadContextIntoSsa(ssa_env_);
     390        1280 :   }
     391             : 
     392             :   void CallDirect(FullDecoder* decoder,
     393             :                   const CallFunctionImmediate<validate>& imm,
     394             :                   const Value args[], Value returns[]) {
     395       35540 :     DoCall(decoder, nullptr, imm.sig, imm.index, args, returns);
     396             :   }
     397             : 
     398             :   void CallIndirect(FullDecoder* decoder, const Value& index,
     399             :                     const CallIndirectImmediate<validate>& imm,
     400             :                     const Value args[], Value returns[]) {
     401        3969 :     DoCall(decoder, index.node, imm.sig, imm.sig_index, args, returns);
     402             :   }
     403             : 
     404        7685 :   void SimdOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
     405             :               Value* result) {
     406        7685 :     TFNode** inputs = GetNodes(args);
     407       15370 :     TFNode* node = BUILD(SimdOp, opcode, inputs);
     408        7685 :     if (result) result->node = node;
     409        7685 :   }
     410             : 
     411       34880 :   void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
     412             :                   const SimdLaneImmediate<validate> imm, Vector<Value> inputs,
     413             :                   Value* result) {
     414       34880 :     TFNode** nodes = GetNodes(inputs);
     415       69760 :     result->node = BUILD(SimdLaneOp, opcode, imm.lane, nodes);
     416       34880 :   }
     417             : 
     418             :   void SimdShiftOp(FullDecoder* decoder, WasmOpcode opcode,
     419             :                    const SimdShiftImmediate<validate> imm, const Value& input,
     420             :                    Value* result) {
     421        2385 :     TFNode* inputs[] = {input.node};
     422        4770 :     result->node = BUILD(SimdShiftOp, opcode, imm.shift, inputs);
     423             :   }
     424             : 
     425             :   void Simd8x16ShuffleOp(FullDecoder* decoder,
     426             :                          const Simd8x16ShuffleImmediate<validate>& imm,
     427             :                          const Value& input0, const Value& input1,
     428             :                          Value* result) {
     429       33780 :     TFNode* input_nodes[] = {input0.node, input1.node};
     430       67560 :     result->node = BUILD(Simd8x16ShuffleOp, imm.shuffle, input_nodes);
     431             :   }
     432             : 
     433         538 :   void Throw(FullDecoder* decoder, const ExceptionIndexImmediate<validate>& imm,
     434         835 :              const Vector<Value>& value_args) {
     435             :     int count = value_args.length();
     436         538 :     ZoneVector<TFNode*> args(count, decoder->zone());
     437         835 :     for (int i = 0; i < count; ++i) {
     438         594 :       args[i] = value_args[i].node;
     439             :     }
     440        1614 :     BUILD(Throw, imm.index, imm.exception, VectorOf(args));
     441         539 :     builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
     442         540 :   }
     443             : 
     444         477 :   void Rethrow(FullDecoder* decoder, const Value& exception) {
     445         954 :     BUILD(Rethrow, exception.node);
     446         477 :     builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
     447         477 :   }
     448             : 
     449         423 :   void BrOnException(FullDecoder* decoder, const Value& exception,
     450             :                      const ExceptionIndexImmediate<validate>& imm,
     451             :                      uint32_t depth, Vector<Value> values) {
     452         423 :     TFNode* if_match = nullptr;
     453         423 :     TFNode* if_no_match = nullptr;
     454             : 
     455             :     // Get the exception tag and see if it matches the expected one.
     456         846 :     TFNode* caught_tag = BUILD(GetExceptionTag, exception.node);
     457         846 :     TFNode* exception_tag = BUILD(LoadExceptionTagFromTable, imm.index);
     458         846 :     TFNode* compare = BUILD(ExceptionTagEqual, caught_tag, exception_tag);
     459         846 :     BUILD(BranchNoHint, compare, &if_match, &if_no_match);
     460         846 :     SsaEnv* if_no_match_env = Split(decoder, ssa_env_);
     461         846 :     SsaEnv* if_match_env = Steal(decoder->zone(), ssa_env_);
     462         423 :     if_no_match_env->control = if_no_match;
     463         423 :     if_match_env->control = if_match;
     464             : 
     465             :     // If the tags match we extract the values from the exception object and
     466             :     // push them onto the operand stack using the passed {values} vector.
     467             :     SetEnv(if_match_env);
     468             :     // TODO(mstarzinger): Can't use BUILD() here, GetExceptionValues() returns
     469             :     // TFNode** rather than TFNode*. Fix to add landing pads.
     470             :     TFNode** caught_values =
     471         423 :         builder_->GetExceptionValues(exception.node, imm.exception);
     472         702 :     for (size_t i = 0, e = values.size(); i < e; ++i) {
     473         558 :       values[i].node = caught_values[i];
     474             :     }
     475         423 :     BrOrRet(decoder, depth);
     476             : 
     477             :     // If the tags don't match we fall-through here.
     478             :     SetEnv(if_no_match_env);
     479         423 :   }
     480             : 
     481             :   void Catch(FullDecoder* decoder, Control* block, Value* exception) {
     482             :     DCHECK(block->is_try_catch());
     483             : 
     484         504 :     current_catch_ = block->previous_catch;  // Pop try scope.
     485             : 
     486             :     // The catch block is unreachable if no possible throws in the try block
     487             :     // exist. We only build a landing pad if some node in the try block can
     488             :     // (possibly) throw. Otherwise the catch environments remain empty.
     489         504 :     if (!block->try_info->might_throw()) {
     490           9 :       block->reachability = kSpecOnlyReachable;
     491             :       return;
     492             :     }
     493             : 
     494         495 :     SetEnv(block->try_info->catch_env);
     495             :     DCHECK_NOT_NULL(block->try_info->exception);
     496         495 :     exception->node = block->try_info->exception;
     497             :   }
     498             : 
     499       33530 :   void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
     500             :                 const MemoryAccessImmediate<validate>& imm, Value* result) {
     501       33543 :     TFNode** inputs = GetNodes(args);
     502      100619 :     TFNode* node = BUILD(AtomicOp, opcode, inputs, imm.alignment, imm.offset,
     503             :                          decoder->position());
     504       33576 :     if (result) result->node = node;
     505       33576 :   }
     506             : 
     507             :   void MemoryInit(FullDecoder* decoder,
     508             :                   const MemoryInitImmediate<validate>& imm, const Value& dst,
     509             :                   const Value& src, const Value& size) {
     510         180 :     BUILD(MemoryInit, imm.data_segment_index, dst.node, src.node, size.node,
     511          45 :           decoder->position());
     512             :   }
     513             :   void MemoryDrop(FullDecoder* decoder,
     514             :                   const MemoryDropImmediate<validate>& imm) {
     515          81 :     BUILD(MemoryDrop, imm.index, decoder->position());
     516             :   }
     517             :   void MemoryCopy(FullDecoder* decoder,
     518             :                   const MemoryIndexImmediate<validate>& imm, const Value& dst,
     519             :                   const Value& src, const Value& size) {
     520          81 :     BUILD(MemoryCopy, dst.node, src.node, size.node, decoder->position());
     521             :   }
     522             :   void MemoryFill(FullDecoder* decoder,
     523             :                   const MemoryIndexImmediate<validate>& imm, const Value& dst,
     524             :                   const Value& value, const Value& size) {
     525          81 :     BUILD(MemoryFill, dst.node, value.node, size.node, decoder->position());
     526             :   }
     527             :   void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm,
     528             :                  Vector<Value> args) {
     529          36 :     BUILD(TableInit, imm.table.index, imm.elem_segment_index, args[0].node,
     530           9 :           args[1].node, args[2].node, decoder->position());
     531             :   }
     532             :   void TableDrop(FullDecoder* decoder,
     533             :                  const TableDropImmediate<validate>& imm) {
     534          54 :     BUILD(TableDrop, imm.index, decoder->position());
     535             :   }
     536             :   void TableCopy(FullDecoder* decoder, const TableIndexImmediate<validate>& imm,
     537             :                  Vector<Value> args) {
     538         288 :     BUILD(TableCopy, imm.index, args[0].node, args[1].node, args[2].node,
     539          72 :           decoder->position());
     540             :   }
     541             : 
     542             :  private:
     543             :   SsaEnv* ssa_env_;
     544             :   compiler::WasmGraphBuilder* builder_;
     545             :   uint32_t current_catch_ = kNullCatch;
     546             : 
     547             :   TryInfo* current_try_info(FullDecoder* decoder) {
     548         648 :     return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
     549         648 :         ->try_info;
     550             :   }
     551             : 
     552     1211168 :   TFNode** GetNodes(Value* values, size_t count) {
     553     1211168 :     TFNode** nodes = builder_->Buffer(count);
     554     1217860 :     for (size_t i = 0; i < count; ++i) {
     555     1217860 :       nodes[i] = values[i].node;
     556             :     }
     557     1211305 :     return nodes;
     558             :   }
     559             : 
     560     1211012 :   TFNode** GetNodes(Vector<Value> values) {
     561     1211012 :     return GetNodes(values.start(), values.size());
     562             :   }
     563             : 
     564             :   void SetEnv(SsaEnv* env) {
     565             : #if DEBUG
     566             :     if (FLAG_trace_wasm_decoder) {
     567             :       char state = 'X';
     568             :       if (env) {
     569             :         switch (env->state) {
     570             :           case SsaEnv::kReached:
     571             :             state = 'R';
     572             :             break;
     573             :           case SsaEnv::kUnreachable:
     574             :             state = 'U';
     575             :             break;
     576             :           case SsaEnv::kMerged:
     577             :             state = 'M';
     578             :             break;
     579             :           case SsaEnv::kControlEnd:
     580             :             state = 'E';
     581             :             break;
     582             :         }
     583             :       }
     584             :       PrintF("{set_env = %p, state = %c", static_cast<void*>(env), state);
     585             :       if (env && env->control) {
     586             :         PrintF(", control = ");
     587             :         compiler::WasmGraphBuilder::PrintDebugName(env->control);
     588             :       }
     589             :       PrintF("}\n");
     590             :     }
     591             : #endif
     592     1861063 :     ssa_env_ = env;
     593             :     // TODO(wasm): combine the control and effect pointers with instance cache.
     594     1861063 :     builder_->set_control_ptr(&env->control);
     595     1861063 :     builder_->set_effect_ptr(&env->effect);
     596     1861063 :     builder_->set_instance_cache(&env->instance_cache);
     597             :   }
     598             : 
     599     3705693 :   TFNode* CheckForException(FullDecoder* decoder, TFNode* node) {
     600     3704397 :     if (node == nullptr) return nullptr;
     601             : 
     602     3702634 :     const bool inside_try_scope = current_catch_ != kNullCatch;
     603             : 
     604     3702634 :     if (!inside_try_scope) return node;
     605             : 
     606        1187 :     TFNode* if_success = nullptr;
     607        1187 :     TFNode* if_exception = nullptr;
     608        1187 :     if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
     609             :       return node;
     610             :     }
     611             : 
     612        1296 :     SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
     613         648 :     success_env->control = if_success;
     614             : 
     615         648 :     SsaEnv* exception_env = Split(decoder, success_env);
     616         648 :     exception_env->control = if_exception;
     617             :     TryInfo* try_info = current_try_info(decoder);
     618         648 :     Goto(decoder, exception_env, try_info->catch_env);
     619         647 :     TFNode* exception = try_info->exception;
     620         647 :     if (exception == nullptr) {
     621             :       DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
     622         494 :       try_info->exception = if_exception;
     623             :     } else {
     624             :       DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
     625             :       try_info->exception = builder_->CreateOrMergeIntoPhi(
     626             :           MachineRepresentation::kWord32, try_info->catch_env->control,
     627         153 :           try_info->exception, if_exception);
     628             :     }
     629             : 
     630             :     SetEnv(success_env);
     631         647 :     return node;
     632             :   }
     633             : 
     634       40742 :   TFNode* DefaultValue(ValueType type) {
     635       40742 :     switch (type) {
     636             :       case kWasmI32:
     637       19552 :         return builder_->Int32Constant(0);
     638             :       case kWasmI64:
     639       14929 :         return builder_->Int64Constant(0);
     640             :       case kWasmF32:
     641         587 :         return builder_->Float32Constant(0);
     642             :       case kWasmF64:
     643        1582 :         return builder_->Float64Constant(0);
     644             :       case kWasmS128:
     645        3993 :         return builder_->S128Zero();
     646             :       case kWasmAnyRef:
     647             :       case kWasmExceptRef:
     648          99 :         return builder_->RefNull();
     649             :       default:
     650           0 :         UNREACHABLE();
     651             :     }
     652             :   }
     653             : 
     654      437684 :   void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge) {
     655             :     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
     656             : 
     657      437684 :     SsaEnv* target = c->end_env;
     658      437684 :     const bool first = target->state == SsaEnv::kUnreachable;
     659      437684 :     Goto(decoder, ssa_env_, target);
     660             : 
     661      875391 :     if (merge->arity == 0) return;
     662             : 
     663             :     uint32_t avail =
     664       19990 :         decoder->stack_size() - decoder->control_at(0)->stack_depth;
     665             :     DCHECK_GE(avail, merge->arity);
     666       19990 :     uint32_t start = avail >= merge->arity ? 0 : merge->arity - avail;
     667             :     Value* stack_values = decoder->stack_value(merge->arity);
     668       20096 :     for (uint32_t i = start; i < merge->arity; ++i) {
     669       20093 :       Value& val = stack_values[i];
     670             :       Value& old = (*merge)[i];
     671             :       DCHECK_NOT_NULL(val.node);
     672             :       DCHECK(val.type == old.type || val.type == kWasmVar);
     673             :       old.node = first ? val.node
     674             :                        : builder_->CreateOrMergeIntoPhi(
     675             :                              ValueTypes::MachineRepresentationFor(old.type),
     676       20093 :                              target->control, old.node, val.node);
     677             :     }
     678             :   }
     679             : 
     680      438343 :   void Goto(FullDecoder* decoder, SsaEnv* from, SsaEnv* to) {
     681             :     DCHECK_NOT_NULL(to);
     682      438343 :     switch (to->state) {
     683             :       case SsaEnv::kUnreachable: {  // Overwrite destination.
     684      149802 :         to->state = SsaEnv::kReached;
     685      149802 :         to->locals = from->locals;
     686      149802 :         to->control = from->control;
     687      149802 :         to->effect = from->effect;
     688      149802 :         to->instance_cache = from->instance_cache;
     689             :         break;
     690             :       }
     691             :       case SsaEnv::kReached: {  // Create a new merge.
     692       46261 :         to->state = SsaEnv::kMerged;
     693             :         // Merge control.
     694       46261 :         TFNode* controls[] = {to->control, from->control};
     695       46261 :         TFNode* merge = builder_->Merge(2, controls);
     696       46264 :         to->control = merge;
     697             :         // Merge effects.
     698       46264 :         if (from->effect != to->effect) {
     699       25558 :           TFNode* effects[] = {to->effect, from->effect, merge};
     700       25558 :           to->effect = builder_->EffectPhi(2, effects, merge);
     701             :         }
     702             :         // Merge SSA values.
     703      857179 :         for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     704      810913 :           TFNode* a = to->locals[i];
     705      810913 :           TFNode* b = from->locals[i];
     706      810913 :           if (a != b) {
     707       71235 :             TFNode* vals[] = {a, b};
     708             :             to->locals[i] =
     709      142470 :                 builder_->Phi(decoder->GetLocalType(i), 2, vals, merge);
     710             :           }
     711             :         }
     712             :         // Start a new merge from the instance cache.
     713             :         builder_->NewInstanceCacheMerge(&to->instance_cache,
     714       46266 :                                         &from->instance_cache, merge);
     715             :         break;
     716             :       }
     717             :       case SsaEnv::kMerged: {
     718      242280 :         TFNode* merge = to->control;
     719             :         // Extend the existing merge control node.
     720      242280 :         builder_->AppendToMerge(merge, from->control);
     721             :         // Merge effects.
     722             :         to->effect = builder_->CreateOrMergeIntoEffectPhi(merge, to->effect,
     723      242280 :                                                           from->effect);
     724             :         // Merge locals.
     725      888061 :         for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     726             :           to->locals[i] = builder_->CreateOrMergeIntoPhi(
     727      645778 :               ValueTypes::MachineRepresentationFor(decoder->GetLocalType(i)),
     728     1291556 :               merge, to->locals[i], from->locals[i]);
     729             :         }
     730             :         // Merge the instance caches.
     731             :         builder_->MergeInstanceCacheInto(&to->instance_cache,
     732      242283 :                                          &from->instance_cache, merge);
     733             :         break;
     734             :       }
     735             :       default:
     736           0 :         UNREACHABLE();
     737             :     }
     738      438348 :     return from->Kill();
     739             :   }
     740             : 
     741       32014 :   SsaEnv* PrepareForLoop(FullDecoder* decoder, SsaEnv* env) {
     742       10675 :     env->state = SsaEnv::kMerged;
     743             : 
     744       10675 :     env->control = builder_->Loop(env->control);
     745       10675 :     env->effect = builder_->EffectPhi(1, &env->effect, env->control);
     746       10676 :     builder_->TerminateLoop(env->effect, env->control);
     747             :     // The '+ 1' here is to be able to set the instance cache as assigned.
     748             :     BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
     749       32016 :         decoder, decoder->pc(), decoder->total_locals() + 1, decoder->zone());
     750       10678 :     if (decoder->failed()) return env;
     751       10668 :     if (assigned != nullptr) {
     752             :       // Only introduce phis for variables assigned in this loop.
     753       10668 :       int instance_cache_index = decoder->total_locals();
     754      215828 :       for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     755      205161 :         if (!assigned->Contains(i)) continue;
     756       43095 :         env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
     757       86190 :                                        &env->locals[i], env->control);
     758             :       }
     759             :       // Introduce phis for instance cache pointers if necessary.
     760       10667 :       if (assigned->Contains(instance_cache_index)) {
     761             :         builder_->PrepareInstanceCacheForLoop(&env->instance_cache,
     762        4911 :                                               env->control);
     763             :       }
     764             : 
     765       10667 :       SsaEnv* loop_body_env = Split(decoder, env);
     766             :       builder_->StackCheck(decoder->position(), &(loop_body_env->effect),
     767       21330 :                            &(loop_body_env->control));
     768             :       return loop_body_env;
     769             :     }
     770             : 
     771             :     // Conservatively introduce phis for all local variables.
     772           0 :     for (int i = decoder->num_locals() - 1; i >= 0; i--) {
     773           0 :       env->locals[i] = builder_->Phi(decoder->GetLocalType(i), 1,
     774           0 :                                      &env->locals[i], env->control);
     775             :     }
     776             : 
     777             :     // Conservatively introduce phis for instance cache.
     778           0 :     builder_->PrepareInstanceCacheForLoop(&env->instance_cache, env->control);
     779             : 
     780           0 :     SsaEnv* loop_body_env = Split(decoder, env);
     781             :     builder_->StackCheck(decoder->position(), &loop_body_env->effect,
     782           0 :                          &loop_body_env->control);
     783             :     return loop_body_env;
     784             :   }
     785             : 
     786             :   // Create a complete copy of {from}.
     787      771047 :   SsaEnv* Split(FullDecoder* decoder, SsaEnv* from) {
     788             :     DCHECK_NOT_NULL(from);
     789             :     SsaEnv* result =
     790      387939 :         reinterpret_cast<SsaEnv*>(decoder->zone()->New(sizeof(SsaEnv)));
     791      387940 :     size_t size = sizeof(TFNode*) * decoder->num_locals();
     792      387940 :     result->control = from->control;
     793      387940 :     result->effect = from->effect;
     794             : 
     795      387940 :     result->state = SsaEnv::kReached;
     796             :     result->locals =
     797             :         size > 0 ? reinterpret_cast<TFNode**>(decoder->zone()->New(size))
     798      771048 :                  : nullptr;
     799      387944 :     memcpy(result->locals, from->locals, size);
     800      387944 :     result->instance_cache = from->instance_cache;
     801             : 
     802      387944 :     return result;
     803             :   }
     804             : 
     805             :   // Create a copy of {from} that steals its state and leaves {from}
     806             :   // unreachable.
     807      199933 :   SsaEnv* Steal(Zone* zone, SsaEnv* from) {
     808             :     DCHECK_NOT_NULL(from);
     809      199933 :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
     810      199931 :     result->state = SsaEnv::kReached;
     811      199931 :     result->locals = from->locals;
     812      199931 :     result->control = from->control;
     813      199931 :     result->effect = from->effect;
     814      199931 :     result->instance_cache = from->instance_cache;
     815             :     from->Kill(SsaEnv::kUnreachable);
     816      199931 :     return result;
     817             :   }
     818             : 
     819             :   // Create an unreachable environment.
     820             :   SsaEnv* UnreachableEnv(Zone* zone) {
     821             :     SsaEnv* result = reinterpret_cast<SsaEnv*>(zone->New(sizeof(SsaEnv)));
     822             :     result->state = SsaEnv::kUnreachable;
     823             :     result->control = nullptr;
     824             :     result->effect = nullptr;
     825             :     result->locals = nullptr;
     826             :     result->instance_cache = {};
     827             :     return result;
     828             :   }
     829             : 
     830       79002 :   void DoCall(FullDecoder* decoder, TFNode* index_node, FunctionSig* sig,
     831             :               uint32_t index, const Value args[], Value returns[]) {
     832       39498 :     int param_count = static_cast<int>(sig->parameter_count());
     833       39498 :     TFNode** arg_nodes = builder_->Buffer(param_count + 1);
     834       39504 :     TFNode** return_nodes = nullptr;
     835       39504 :     arg_nodes[0] = index_node;
     836      142426 :     for (int i = 0; i < param_count; ++i) {
     837      102922 :       arg_nodes[i + 1] = args[i].node;
     838             :     }
     839       39504 :     if (index_node) {
     840       11904 :       BUILD(CallIndirect, index, arg_nodes, &return_nodes, decoder->position());
     841             :     } else {
     842      106604 :       BUILD(CallDirect, index, arg_nodes, &return_nodes, decoder->position());
     843             :     }
     844       39504 :     int return_count = static_cast<int>(sig->return_count());
     845       63202 :     for (int i = 0; i < return_count; ++i) {
     846       23698 :       returns[i].node = return_nodes[i];
     847             :     }
     848             :     // The invoked function could have used grow_memory, so we need to
     849             :     // reload mem_size and mem_start.
     850       39504 :     LoadContextIntoSsa(ssa_env_);
     851       39516 :   }
     852             : };
     853             : 
     854             : }  // namespace
     855             : 
     856     1067464 : DecodeResult BuildTFGraph(AccountingAllocator* allocator,
     857             :                           const WasmFeatures& enabled,
     858             :                           const wasm::WasmModule* module,
     859             :                           compiler::WasmGraphBuilder* builder,
     860             :                           WasmFeatures* detected, const FunctionBody& body,
     861             :                           compiler::NodeOriginTable* node_origins) {
     862     1067464 :   Zone zone(allocator, ZONE_NAME);
     863             :   WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
     864     1067456 :       &zone, module, enabled, detected, body, builder);
     865     1067439 :   if (node_origins) {
     866           0 :     builder->AddBytecodePositionDecorator(node_origins, &decoder);
     867             :   }
     868     1067439 :   decoder.Decode();
     869     1067296 :   if (node_origins) {
     870           0 :     builder->RemoveBytecodePositionDecorator();
     871             :   }
     872     3202070 :   return decoder.toResult(nullptr);
     873             : }
     874             : 
     875             : #undef BUILD
     876             : 
     877             : }  // namespace wasm
     878             : }  // namespace internal
     879      183867 : }  // namespace v8

Generated by: LCOV version 1.10