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