• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/flags.h"
9 #include "src/handles/handles.h"
10 #include "src/objects/objects-inl.h"
11 #include "src/utils/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/value-type.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-inl.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 : public ZoneObject {
32   enum State { kControlEnd, kUnreachable, kReached, kMerged };
33 
34   State state;
35   TFNode* control;
36   TFNode* effect;
37   compiler::WasmInstanceCacheNodes instance_cache;
38   ZoneVector<TFNode*> locals;
39 
SsaEnvv8::internal::wasm::__anonfc9fbc4f0111::SsaEnv40   SsaEnv(Zone* zone, State state, TFNode* control, TFNode* effect,
41          uint32_t locals_size)
42       : state(state), control(control), effect(effect), locals(zone) {
43     if (locals_size > 0) locals.resize(locals_size);
44   }
45 
46   SsaEnv(const SsaEnv& other) V8_NOEXCEPT = default;
SsaEnvv8::internal::wasm::__anonfc9fbc4f0111::SsaEnv47   SsaEnv(SsaEnv&& other) V8_NOEXCEPT : state(other.state),
48                                        control(other.control),
49                                        effect(other.effect),
50                                        instance_cache(other.instance_cache),
51                                        locals(std::move(other.locals)) {
52     other.Kill(kUnreachable);
53   }
54 
Killv8::internal::wasm::__anonfc9fbc4f0111::SsaEnv55   void Kill(State new_state = kControlEnd) {
56     state = new_state;
57     locals.clear();
58     control = nullptr;
59     effect = nullptr;
60     instance_cache = {};
61   }
SetNotMergedv8::internal::wasm::__anonfc9fbc4f0111::SsaEnv62   void SetNotMerged() {
63     if (state == kMerged) state = kReached;
64   }
65 };
66 
67 #define BUILD(func, ...)                                            \
68   ([&] {                                                            \
69     DCHECK(decoder->ok());                                          \
70     return CheckForException(decoder, builder_->func(__VA_ARGS__)); \
71   })()
72 
73 constexpr uint32_t kNullCatch = static_cast<uint32_t>(-1);
74 
75 class WasmGraphBuildingInterface {
76  public:
77   static constexpr Decoder::ValidateFlag validate = Decoder::kFullValidation;
78   using FullDecoder = WasmFullDecoder<validate, WasmGraphBuildingInterface>;
79   using CheckForNull = compiler::WasmGraphBuilder::CheckForNull;
80 
81   struct Value : public ValueBase<validate> {
82     TFNode* node = nullptr;
83 
84     template <typename... Args>
Valuev8::internal::wasm::__anonfc9fbc4f0111::WasmGraphBuildingInterface::Value85     explicit Value(Args&&... args) V8_NOEXCEPT
86         : ValueBase(std::forward<Args>(args)...) {}
87   };
88 
89   struct TryInfo : public ZoneObject {
90     SsaEnv* catch_env;
91     TFNode* exception = nullptr;
92 
might_throwv8::internal::wasm::__anonfc9fbc4f0111::WasmGraphBuildingInterface::TryInfo93     bool might_throw() const { return exception != nullptr; }
94 
95     MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TryInfo);
96 
TryInfov8::internal::wasm::__anonfc9fbc4f0111::WasmGraphBuildingInterface::TryInfo97     explicit TryInfo(SsaEnv* c) : catch_env(c) {}
98   };
99 
100   struct Control : public ControlBase<Value, validate> {
101     SsaEnv* end_env = nullptr;    // end environment for the construct.
102     SsaEnv* false_env = nullptr;  // false environment (only for if).
103     TryInfo* try_info = nullptr;  // information about try statements.
104     int32_t previous_catch = -1;  // previous Control with a catch.
105 
106     MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Control);
107 
108     template <typename... Args>
Controlv8::internal::wasm::__anonfc9fbc4f0111::WasmGraphBuildingInterface::Control109     explicit Control(Args&&... args) V8_NOEXCEPT
110         : ControlBase(std::forward<Args>(args)...) {}
111   };
112 
WasmGraphBuildingInterface(compiler::WasmGraphBuilder * builder)113   explicit WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder)
114       : builder_(builder) {}
115 
StartFunction(FullDecoder * decoder)116   void StartFunction(FullDecoder* decoder) {
117     // The first '+ 1' is needed by TF Start node, the second '+ 1' is for the
118     // instance parameter.
119     TFNode* start = builder_->Start(
120         static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
121     uint32_t num_locals = decoder->num_locals();
122     SsaEnv* ssa_env = decoder->zone()->New<SsaEnv>(
123         decoder->zone(), SsaEnv::kReached, start, start, num_locals);
124 
125     // Initialize effect and control before initializing the locals default
126     // values (which might require instance loads) or loading the context.
127     builder_->SetEffectControl(start);
128     // Initialize the instance parameter (index 0).
129     builder_->set_instance_node(builder_->Param(kWasmInstanceParameterIndex));
130     // Initialize local variables. Parameters are shifted by 1 because of the
131     // the instance parameter.
132     uint32_t index = 0;
133     for (; index < decoder->sig_->parameter_count(); ++index) {
134       ssa_env->locals[index] = builder_->Param(index + 1);
135     }
136     while (index < num_locals) {
137       ValueType type = decoder->local_type(index);
138       TFNode* node = DefaultValue(type);
139       while (index < num_locals && decoder->local_type(index) == type) {
140         // Do a whole run of like-typed locals at a time.
141         ssa_env->locals[index++] = node;
142       }
143     }
144     SetEnv(ssa_env);
145     LoadContextIntoSsa(ssa_env);
146 
147     if (FLAG_trace_wasm) BUILD(TraceFunctionEntry, decoder->position());
148   }
149 
150   // Reload the instance cache entries into the Ssa Environment.
LoadContextIntoSsa(SsaEnv * ssa_env)151   void LoadContextIntoSsa(SsaEnv* ssa_env) {
152     if (ssa_env) builder_->InitInstanceCache(&ssa_env->instance_cache);
153   }
154 
StartFunctionBody(FullDecoder * decoder,Control * block)155   void StartFunctionBody(FullDecoder* decoder, Control* block) {}
156 
FinishFunction(FullDecoder *)157   void FinishFunction(FullDecoder*) { builder_->PatchInStackCheckIfNeeded(); }
158 
OnFirstError(FullDecoder *)159   void OnFirstError(FullDecoder*) {}
160 
NextInstruction(FullDecoder *,WasmOpcode)161   void NextInstruction(FullDecoder*, WasmOpcode) {}
162 
Block(FullDecoder * decoder,Control * block)163   void Block(FullDecoder* decoder, Control* block) {
164     // The branch environment is the outer environment.
165     block->end_env = ssa_env_;
166     SetEnv(Steal(decoder->zone(), ssa_env_));
167   }
168 
Loop(FullDecoder * decoder,Control * block)169   void Loop(FullDecoder* decoder, Control* block) {
170     SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
171     block->end_env = finish_try_env;
172     SetEnv(finish_try_env);
173     // The continue environment is the inner environment.
174     PrepareForLoop(decoder);
175     ssa_env_->SetNotMerged();
176     if (!decoder->ok()) return;
177     // Wrap input merge into phis.
178     for (uint32_t i = 0; i < block->start_merge.arity; ++i) {
179       Value& val = block->start_merge[i];
180       TFNode* inputs[] = {val.node, block->end_env->control};
181       val.node = builder_->Phi(val.type, 1, inputs);
182     }
183   }
184 
Try(FullDecoder * decoder,Control * block)185   void Try(FullDecoder* decoder, Control* block) {
186     SsaEnv* outer_env = ssa_env_;
187     SsaEnv* catch_env = Split(decoder->zone(), outer_env);
188     // Mark catch environment as unreachable, since only accessable
189     // through catch unwinding (i.e. landing pads).
190     catch_env->state = SsaEnv::kUnreachable;
191     SsaEnv* try_env = Steal(decoder->zone(), outer_env);
192     SetEnv(try_env);
193     TryInfo* try_info = decoder->zone()->New<TryInfo>(catch_env);
194     block->end_env = outer_env;
195     block->try_info = try_info;
196     block->previous_catch = current_catch_;
197     current_catch_ = static_cast<int32_t>(decoder->control_depth() - 1);
198   }
199 
If(FullDecoder * decoder,const Value & cond,Control * if_block)200   void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
201     TFNode* if_true = nullptr;
202     TFNode* if_false = nullptr;
203     BUILD(BranchNoHint, cond.node, &if_true, &if_false);
204     SsaEnv* end_env = ssa_env_;
205     SsaEnv* false_env = Split(decoder->zone(), ssa_env_);
206     false_env->control = if_false;
207     SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
208     true_env->control = if_true;
209     if_block->end_env = end_env;
210     if_block->false_env = false_env;
211     SetEnv(true_env);
212   }
213 
FallThruTo(FullDecoder * decoder,Control * c)214   void FallThruTo(FullDecoder* decoder, Control* c) {
215     DCHECK(!c->is_loop());
216     MergeValuesInto(decoder, c, &c->end_merge);
217   }
218 
PopControl(FullDecoder * decoder,Control * block)219   void PopControl(FullDecoder* decoder, Control* block) {
220     // A loop just continues with the end environment. There is no merge.
221     if (block->is_loop()) return;
222     // Any other block falls through to the parent block.
223     if (block->reachable()) FallThruTo(decoder, block);
224     if (block->is_onearmed_if()) {
225       // Merge the else branch into the end merge.
226       SetEnv(block->false_env);
227       DCHECK_EQ(block->start_merge.arity, block->end_merge.arity);
228       Value* values =
229           block->start_merge.arity > 0 ? &block->start_merge[0] : nullptr;
230       MergeValuesInto(decoder, block, &block->end_merge, values);
231     }
232     // Now continue with the merged environment.
233     SetEnv(block->end_env);
234   }
235 
EndControl(FullDecoder * decoder,Control * block)236   void EndControl(FullDecoder* decoder, Control* block) { ssa_env_->Kill(); }
237 
UnOp(FullDecoder * decoder,WasmOpcode opcode,const Value & value,Value * result)238   void UnOp(FullDecoder* decoder, WasmOpcode opcode, const Value& value,
239             Value* result) {
240     result->node = BUILD(Unop, opcode, value.node, decoder->position());
241   }
242 
BinOp(FullDecoder * decoder,WasmOpcode opcode,const Value & lhs,const Value & rhs,Value * result)243   void BinOp(FullDecoder* decoder, WasmOpcode opcode, const Value& lhs,
244              const Value& rhs, Value* result) {
245     TFNode* node =
246         BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
247     if (result) result->node = node;
248   }
249 
I32Const(FullDecoder * decoder,Value * result,int32_t value)250   void I32Const(FullDecoder* decoder, Value* result, int32_t value) {
251     result->node = builder_->Int32Constant(value);
252   }
253 
I64Const(FullDecoder * decoder,Value * result,int64_t value)254   void I64Const(FullDecoder* decoder, Value* result, int64_t value) {
255     result->node = builder_->Int64Constant(value);
256   }
257 
F32Const(FullDecoder * decoder,Value * result,float value)258   void F32Const(FullDecoder* decoder, Value* result, float value) {
259     result->node = builder_->Float32Constant(value);
260   }
261 
F64Const(FullDecoder * decoder,Value * result,double value)262   void F64Const(FullDecoder* decoder, Value* result, double value) {
263     result->node = builder_->Float64Constant(value);
264   }
265 
S128Const(FullDecoder * decoder,const Simd128Immediate<validate> & imm,Value * result)266   void S128Const(FullDecoder* decoder, const Simd128Immediate<validate>& imm,
267                  Value* result) {
268     result->node = builder_->Simd128Constant(imm.value);
269   }
270 
RefNull(FullDecoder * decoder,ValueType type,Value * result)271   void RefNull(FullDecoder* decoder, ValueType type, Value* result) {
272     result->node = builder_->RefNull();
273   }
274 
RefFunc(FullDecoder * decoder,uint32_t function_index,Value * result)275   void RefFunc(FullDecoder* decoder, uint32_t function_index, Value* result) {
276     result->node = BUILD(RefFunc, function_index);
277   }
278 
RefAsNonNull(FullDecoder * decoder,const Value & arg,Value * result)279   void RefAsNonNull(FullDecoder* decoder, const Value& arg, Value* result) {
280     result->node = BUILD(RefAsNonNull, arg.node, decoder->position());
281   }
282 
Drop(FullDecoder * decoder,const Value & value)283   void Drop(FullDecoder* decoder, const Value& value) {}
284 
DoReturn(FullDecoder * decoder,Vector<Value> values)285   void DoReturn(FullDecoder* decoder, Vector<Value> values) {
286     base::SmallVector<TFNode*, 8> nodes(values.size());
287     GetNodes(nodes.begin(), values);
288     if (FLAG_trace_wasm) {
289       BUILD(TraceFunctionExit, VectorOf(nodes), decoder->position());
290     }
291     BUILD(Return, VectorOf(nodes));
292   }
293 
LocalGet(FullDecoder * decoder,Value * result,const LocalIndexImmediate<validate> & imm)294   void LocalGet(FullDecoder* decoder, Value* result,
295                 const LocalIndexImmediate<validate>& imm) {
296     result->node = ssa_env_->locals[imm.index];
297   }
298 
LocalSet(FullDecoder * decoder,const Value & value,const LocalIndexImmediate<validate> & imm)299   void LocalSet(FullDecoder* decoder, const Value& value,
300                 const LocalIndexImmediate<validate>& imm) {
301     ssa_env_->locals[imm.index] = value.node;
302   }
303 
LocalTee(FullDecoder * decoder,const Value & value,Value * result,const LocalIndexImmediate<validate> & imm)304   void LocalTee(FullDecoder* decoder, const Value& value, Value* result,
305                 const LocalIndexImmediate<validate>& imm) {
306     result->node = value.node;
307     ssa_env_->locals[imm.index] = value.node;
308   }
309 
AllocateLocals(FullDecoder * decoder,Vector<Value> local_values)310   void AllocateLocals(FullDecoder* decoder, Vector<Value> local_values) {
311     ZoneVector<TFNode*>* locals = &ssa_env_->locals;
312     locals->insert(locals->begin(), local_values.size(), nullptr);
313     for (uint32_t i = 0; i < local_values.size(); i++) {
314       (*locals)[i] = local_values[i].node;
315     }
316   }
317 
DeallocateLocals(FullDecoder * decoder,uint32_t count)318   void DeallocateLocals(FullDecoder* decoder, uint32_t count) {
319     ZoneVector<TFNode*>* locals = &ssa_env_->locals;
320     locals->erase(locals->begin(), locals->begin() + count);
321   }
322 
GlobalGet(FullDecoder * decoder,Value * result,const GlobalIndexImmediate<validate> & imm)323   void GlobalGet(FullDecoder* decoder, Value* result,
324                  const GlobalIndexImmediate<validate>& imm) {
325     result->node = BUILD(GlobalGet, imm.index);
326   }
327 
GlobalSet(FullDecoder * decoder,const Value & value,const GlobalIndexImmediate<validate> & imm)328   void GlobalSet(FullDecoder* decoder, const Value& value,
329                  const GlobalIndexImmediate<validate>& imm) {
330     BUILD(GlobalSet, imm.index, value.node);
331   }
332 
TableGet(FullDecoder * decoder,const Value & index,Value * result,const TableIndexImmediate<validate> & imm)333   void TableGet(FullDecoder* decoder, const Value& index, Value* result,
334                 const TableIndexImmediate<validate>& imm) {
335     result->node = BUILD(TableGet, imm.index, index.node, decoder->position());
336   }
337 
TableSet(FullDecoder * decoder,const Value & index,const Value & value,const TableIndexImmediate<validate> & imm)338   void TableSet(FullDecoder* decoder, const Value& index, const Value& value,
339                 const TableIndexImmediate<validate>& imm) {
340     BUILD(TableSet, imm.index, index.node, value.node, decoder->position());
341   }
342 
Unreachable(FullDecoder * decoder)343   void Unreachable(FullDecoder* decoder) {
344     BUILD(Trap, wasm::TrapReason::kTrapUnreachable, decoder->position());
345   }
346 
Select(FullDecoder * decoder,const Value & cond,const Value & fval,const Value & tval,Value * result)347   void Select(FullDecoder* decoder, const Value& cond, const Value& fval,
348               const Value& tval, Value* result) {
349     TFNode* controls[2];
350     BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
351     TFNode* merge = BUILD(Merge, 2, controls);
352     TFNode* inputs[] = {tval.node, fval.node, merge};
353     TFNode* phi = BUILD(Phi, tval.type, 2, inputs);
354     result->node = phi;
355     builder_->SetControl(merge);
356   }
357 
BrOrRet(FullDecoder * decoder,uint32_t depth)358   void BrOrRet(FullDecoder* decoder, uint32_t depth) {
359     if (depth == decoder->control_depth() - 1) {
360       uint32_t ret_count = static_cast<uint32_t>(decoder->sig_->return_count());
361       base::SmallVector<TFNode*, 8> values(ret_count);
362       if (ret_count > 0) {
363         GetNodes(values.begin(), decoder->stack_value(ret_count), ret_count);
364       }
365       BUILD(Return, VectorOf(values));
366     } else {
367       Br(decoder, decoder->control_at(depth));
368     }
369   }
370 
Br(FullDecoder * decoder,Control * target)371   void Br(FullDecoder* decoder, Control* target) {
372     MergeValuesInto(decoder, target, target->br_merge());
373   }
374 
BrIf(FullDecoder * decoder,const Value & cond,uint32_t depth)375   void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) {
376     SsaEnv* fenv = ssa_env_;
377     SsaEnv* tenv = Split(decoder->zone(), fenv);
378     fenv->SetNotMerged();
379     BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
380     builder_->SetControl(fenv->control);
381     SetEnv(tenv);
382     BrOrRet(decoder, depth);
383     SetEnv(fenv);
384   }
385 
BrTable(FullDecoder * decoder,const BranchTableImmediate<validate> & imm,const Value & key)386   void BrTable(FullDecoder* decoder, const BranchTableImmediate<validate>& imm,
387                const Value& key) {
388     if (imm.table_count == 0) {
389       // Only a default target. Do the equivalent of br.
390       uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
391       BrOrRet(decoder, target);
392       return;
393     }
394 
395     SsaEnv* branch_env = ssa_env_;
396     // Build branches to the various blocks based on the table.
397     TFNode* sw = BUILD(Switch, imm.table_count + 1, key.node);
398 
399     SsaEnv* copy = Steal(decoder->zone(), branch_env);
400     SetEnv(copy);
401     BranchTableIterator<validate> iterator(decoder, imm);
402     while (iterator.has_next()) {
403       uint32_t i = iterator.cur_index();
404       uint32_t target = iterator.next();
405       SetEnv(Split(decoder->zone(), copy));
406       builder_->SetControl(i == imm.table_count ? BUILD(IfDefault, sw)
407                                                 : BUILD(IfValue, i, sw));
408       BrOrRet(decoder, target);
409     }
410     DCHECK(decoder->ok());
411     SetEnv(branch_env);
412   }
413 
Else(FullDecoder * decoder,Control * if_block)414   void Else(FullDecoder* decoder, Control* if_block) {
415     if (if_block->reachable()) {
416       // Merge the if branch into the end merge.
417       MergeValuesInto(decoder, if_block, &if_block->end_merge);
418     }
419     SetEnv(if_block->false_env);
420   }
421 
LoadMem(FullDecoder * decoder,LoadType type,const MemoryAccessImmediate<validate> & imm,const Value & index,Value * result)422   void LoadMem(FullDecoder* decoder, LoadType type,
423                const MemoryAccessImmediate<validate>& imm, const Value& index,
424                Value* result) {
425     result->node =
426         BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
427               imm.offset, imm.alignment, decoder->position());
428   }
429 
LoadTransform(FullDecoder * decoder,LoadType type,LoadTransformationKind transform,const MemoryAccessImmediate<validate> & imm,const Value & index,Value * result)430   void LoadTransform(FullDecoder* decoder, LoadType type,
431                      LoadTransformationKind transform,
432                      const MemoryAccessImmediate<validate>& imm,
433                      const Value& index, Value* result) {
434     result->node =
435         BUILD(LoadTransform, type.value_type(), type.mem_type(), transform,
436               index.node, imm.offset, imm.alignment, decoder->position());
437   }
438 
LoadLane(FullDecoder * decoder,LoadType type,const Value & value,const Value & index,const MemoryAccessImmediate<validate> & imm,const uint8_t laneidx,Value * result)439   void LoadLane(FullDecoder* decoder, LoadType type, const Value& value,
440                 const Value& index, const MemoryAccessImmediate<validate>& imm,
441                 const uint8_t laneidx, Value* result) {
442     result->node = BUILD(LoadLane, type.mem_type(), value.node, index.node,
443                          imm.offset, laneidx, decoder->position());
444   }
445 
StoreMem(FullDecoder * decoder,StoreType type,const MemoryAccessImmediate<validate> & imm,const Value & index,const Value & value)446   void StoreMem(FullDecoder* decoder, StoreType type,
447                 const MemoryAccessImmediate<validate>& imm, const Value& index,
448                 const Value& value) {
449     BUILD(StoreMem, type.mem_rep(), index.node, imm.offset, imm.alignment,
450           value.node, decoder->position(), type.value_type());
451   }
452 
StoreLane(FullDecoder * decoder,StoreType type,const MemoryAccessImmediate<validate> & imm,const Value & index,const Value & value,const uint8_t laneidx)453   void StoreLane(FullDecoder* decoder, StoreType type,
454                  const MemoryAccessImmediate<validate>& imm, const Value& index,
455                  const Value& value, const uint8_t laneidx) {
456     BUILD(StoreLane, type.mem_rep(), index.node, imm.offset, imm.alignment,
457           value.node, laneidx, decoder->position(), type.value_type());
458   }
459 
CurrentMemoryPages(FullDecoder * decoder,Value * result)460   void CurrentMemoryPages(FullDecoder* decoder, Value* result) {
461     result->node = BUILD(CurrentMemoryPages);
462   }
463 
MemoryGrow(FullDecoder * decoder,const Value & value,Value * result)464   void MemoryGrow(FullDecoder* decoder, const Value& value, Value* result) {
465     result->node = BUILD(MemoryGrow, value.node);
466     // Always reload the instance cache after growing memory.
467     LoadContextIntoSsa(ssa_env_);
468   }
469 
470   enum CallMode { kDirect, kIndirect, kRef };
471 
CallDirect(FullDecoder * decoder,const CallFunctionImmediate<validate> & imm,const Value args[],Value returns[])472   void CallDirect(FullDecoder* decoder,
473                   const CallFunctionImmediate<validate>& imm,
474                   const Value args[], Value returns[]) {
475     DoCall(decoder, kDirect, 0, CheckForNull::kWithoutNullCheck, nullptr,
476            imm.sig, imm.index, args, returns);
477   }
478 
ReturnCall(FullDecoder * decoder,const CallFunctionImmediate<validate> & imm,const Value args[])479   void ReturnCall(FullDecoder* decoder,
480                   const CallFunctionImmediate<validate>& imm,
481                   const Value args[]) {
482     DoReturnCall(decoder, kDirect, 0, CheckForNull::kWithoutNullCheck, nullptr,
483                  imm.sig, imm.index, args);
484   }
485 
CallIndirect(FullDecoder * decoder,const Value & index,const CallIndirectImmediate<validate> & imm,const Value args[],Value returns[])486   void CallIndirect(FullDecoder* decoder, const Value& index,
487                     const CallIndirectImmediate<validate>& imm,
488                     const Value args[], Value returns[]) {
489     DoCall(decoder, kIndirect, imm.table_index, CheckForNull::kWithoutNullCheck,
490            index.node, imm.sig, imm.sig_index, args, returns);
491   }
492 
ReturnCallIndirect(FullDecoder * decoder,const Value & index,const CallIndirectImmediate<validate> & imm,const Value args[])493   void ReturnCallIndirect(FullDecoder* decoder, const Value& index,
494                           const CallIndirectImmediate<validate>& imm,
495                           const Value args[]) {
496     DoReturnCall(decoder, kIndirect, imm.table_index,
497                  CheckForNull::kWithoutNullCheck, index.node, imm.sig,
498                  imm.sig_index, args);
499   }
500 
CallRef(FullDecoder * decoder,const Value & func_ref,const FunctionSig * sig,uint32_t sig_index,const Value args[],Value returns[])501   void CallRef(FullDecoder* decoder, const Value& func_ref,
502                const FunctionSig* sig, uint32_t sig_index, const Value args[],
503                Value returns[]) {
504     CheckForNull null_check = func_ref.type.is_nullable()
505                                   ? CheckForNull::kWithNullCheck
506                                   : CheckForNull::kWithoutNullCheck;
507     DoCall(decoder, kRef, 0, null_check, func_ref.node, sig, sig_index, args,
508            returns);
509   }
510 
ReturnCallRef(FullDecoder * decoder,const Value & func_ref,const FunctionSig * sig,uint32_t sig_index,const Value args[])511   void ReturnCallRef(FullDecoder* decoder, const Value& func_ref,
512                      const FunctionSig* sig, uint32_t sig_index,
513                      const Value args[]) {
514     CheckForNull null_check = func_ref.type.is_nullable()
515                                   ? CheckForNull::kWithNullCheck
516                                   : CheckForNull::kWithoutNullCheck;
517     DoReturnCall(decoder, kRef, 0, null_check, func_ref.node, sig, sig_index,
518                  args);
519   }
520 
BrOnNull(FullDecoder * decoder,const Value & ref_object,uint32_t depth)521   void BrOnNull(FullDecoder* decoder, const Value& ref_object, uint32_t depth) {
522     SsaEnv* non_null_env = ssa_env_;
523     SsaEnv* null_env = Split(decoder->zone(), non_null_env);
524     non_null_env->SetNotMerged();
525     BUILD(BrOnNull, ref_object.node, &null_env->control,
526           &non_null_env->control);
527     builder_->SetControl(non_null_env->control);
528     SetEnv(null_env);
529     BrOrRet(decoder, depth);
530     SetEnv(non_null_env);
531   }
532 
SimdOp(FullDecoder * decoder,WasmOpcode opcode,Vector<Value> args,Value * result)533   void SimdOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
534               Value* result) {
535     base::SmallVector<TFNode*, 8> inputs(args.size());
536     GetNodes(inputs.begin(), args);
537     TFNode* node = BUILD(SimdOp, opcode, inputs.begin());
538     if (result) result->node = node;
539   }
540 
SimdLaneOp(FullDecoder * decoder,WasmOpcode opcode,const SimdLaneImmediate<validate> & imm,Vector<Value> inputs,Value * result)541   void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
542                   const SimdLaneImmediate<validate>& imm, Vector<Value> inputs,
543                   Value* result) {
544     base::SmallVector<TFNode*, 8> nodes(inputs.size());
545     GetNodes(nodes.begin(), inputs);
546     result->node = BUILD(SimdLaneOp, opcode, imm.lane, nodes.begin());
547   }
548 
Simd8x16ShuffleOp(FullDecoder * decoder,const Simd128Immediate<validate> & imm,const Value & input0,const Value & input1,Value * result)549   void Simd8x16ShuffleOp(FullDecoder* decoder,
550                          const Simd128Immediate<validate>& imm,
551                          const Value& input0, const Value& input1,
552                          Value* result) {
553     TFNode* input_nodes[] = {input0.node, input1.node};
554     result->node = BUILD(Simd8x16ShuffleOp, imm.value, input_nodes);
555   }
556 
Throw(FullDecoder * decoder,const ExceptionIndexImmediate<validate> & imm,const Vector<Value> & value_args)557   void Throw(FullDecoder* decoder, const ExceptionIndexImmediate<validate>& imm,
558              const Vector<Value>& value_args) {
559     int count = value_args.length();
560     ZoneVector<TFNode*> args(count, decoder->zone());
561     for (int i = 0; i < count; ++i) {
562       args[i] = value_args[i].node;
563     }
564     BUILD(Throw, imm.index, imm.exception, VectorOf(args), decoder->position());
565     builder_->TerminateThrow(effect(), control());
566   }
567 
Rethrow(FullDecoder * decoder,const Value & exception)568   void Rethrow(FullDecoder* decoder, const Value& exception) {
569     BUILD(Rethrow, exception.node);
570     builder_->TerminateThrow(effect(), control());
571   }
572 
BrOnException(FullDecoder * decoder,const Value & exception,const ExceptionIndexImmediate<validate> & imm,uint32_t depth,Vector<Value> values)573   void BrOnException(FullDecoder* decoder, const Value& exception,
574                      const ExceptionIndexImmediate<validate>& imm,
575                      uint32_t depth, Vector<Value> values) {
576     TFNode* if_match = nullptr;
577     TFNode* if_no_match = nullptr;
578 
579     // Get the exception tag and see if it matches the expected one.
580     TFNode* caught_tag =
581         BUILD(GetExceptionTag, exception.node, decoder->position());
582     TFNode* exception_tag = BUILD(LoadExceptionTagFromTable, imm.index);
583     TFNode* compare = BUILD(ExceptionTagEqual, caught_tag, exception_tag);
584     BUILD(BranchNoHint, compare, &if_match, &if_no_match);
585     SsaEnv* if_no_match_env = Split(decoder->zone(), ssa_env_);
586     SsaEnv* if_match_env = Steal(decoder->zone(), ssa_env_);
587     if_no_match_env->control = if_no_match;
588     if_match_env->control = if_match;
589 
590     // If the tags match we extract the values from the exception object and
591     // push them onto the operand stack using the passed {values} vector.
592     SetEnv(if_match_env);
593     base::SmallVector<TFNode*, 8> caught_values(values.size());
594     Vector<TFNode*> caught_vector = VectorOf(caught_values);
595     BUILD(GetExceptionValues, exception.node, imm.exception, caught_vector);
596     for (size_t i = 0, e = values.size(); i < e; ++i) {
597       values[i].node = caught_vector[i];
598     }
599     BrOrRet(decoder, depth);
600 
601     // If the tags don't match we fall-through here.
602     SetEnv(if_no_match_env);
603   }
604 
Catch(FullDecoder * decoder,Control * block,Value * exception)605   void Catch(FullDecoder* decoder, Control* block, Value* exception) {
606     DCHECK(block->is_try_catch());
607     DCHECK_EQ(decoder->control_at(0), block);
608 
609     current_catch_ = block->previous_catch;  // Pop try scope.
610 
611     // The catch block is unreachable if no possible throws in the try block
612     // exist. We only build a landing pad if some node in the try block can
613     // (possibly) throw. Otherwise the catch environments remain empty.
614     if (!block->try_info->might_throw()) {
615       decoder->SetSucceedingCodeDynamicallyUnreachable();
616       return;
617     }
618 
619     SetEnv(block->try_info->catch_env);
620     DCHECK_NOT_NULL(block->try_info->exception);
621     exception->node = block->try_info->exception;
622   }
623 
AtomicOp(FullDecoder * decoder,WasmOpcode opcode,Vector<Value> args,const MemoryAccessImmediate<validate> & imm,Value * result)624   void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
625                 const MemoryAccessImmediate<validate>& imm, Value* result) {
626     base::SmallVector<TFNode*, 8> inputs(args.size());
627     GetNodes(inputs.begin(), args);
628     TFNode* node = BUILD(AtomicOp, opcode, inputs.begin(), imm.alignment,
629                          imm.offset, decoder->position());
630     if (result) result->node = node;
631   }
632 
AtomicFence(FullDecoder * decoder)633   void AtomicFence(FullDecoder* decoder) { BUILD(AtomicFence); }
634 
MemoryInit(FullDecoder * decoder,const MemoryInitImmediate<validate> & imm,const Value & dst,const Value & src,const Value & size)635   void MemoryInit(FullDecoder* decoder,
636                   const MemoryInitImmediate<validate>& imm, const Value& dst,
637                   const Value& src, const Value& size) {
638     BUILD(MemoryInit, imm.data_segment_index, dst.node, src.node, size.node,
639           decoder->position());
640   }
641 
DataDrop(FullDecoder * decoder,const DataDropImmediate<validate> & imm)642   void DataDrop(FullDecoder* decoder, const DataDropImmediate<validate>& imm) {
643     BUILD(DataDrop, imm.index, decoder->position());
644   }
645 
MemoryCopy(FullDecoder * decoder,const MemoryCopyImmediate<validate> & imm,const Value & dst,const Value & src,const Value & size)646   void MemoryCopy(FullDecoder* decoder,
647                   const MemoryCopyImmediate<validate>& imm, const Value& dst,
648                   const Value& src, const Value& size) {
649     BUILD(MemoryCopy, dst.node, src.node, size.node, decoder->position());
650   }
651 
MemoryFill(FullDecoder * decoder,const MemoryIndexImmediate<validate> & imm,const Value & dst,const Value & value,const Value & size)652   void MemoryFill(FullDecoder* decoder,
653                   const MemoryIndexImmediate<validate>& imm, const Value& dst,
654                   const Value& value, const Value& size) {
655     BUILD(MemoryFill, dst.node, value.node, size.node, decoder->position());
656   }
657 
TableInit(FullDecoder * decoder,const TableInitImmediate<validate> & imm,Vector<Value> args)658   void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm,
659                  Vector<Value> args) {
660     BUILD(TableInit, imm.table.index, imm.elem_segment_index, args[0].node,
661           args[1].node, args[2].node, decoder->position());
662   }
663 
ElemDrop(FullDecoder * decoder,const ElemDropImmediate<validate> & imm)664   void ElemDrop(FullDecoder* decoder, const ElemDropImmediate<validate>& imm) {
665     BUILD(ElemDrop, imm.index, decoder->position());
666   }
667 
TableCopy(FullDecoder * decoder,const TableCopyImmediate<validate> & imm,Vector<Value> args)668   void TableCopy(FullDecoder* decoder, const TableCopyImmediate<validate>& imm,
669                  Vector<Value> args) {
670     BUILD(TableCopy, imm.table_dst.index, imm.table_src.index, args[0].node,
671           args[1].node, args[2].node, decoder->position());
672   }
673 
TableGrow(FullDecoder * decoder,const TableIndexImmediate<validate> & imm,const Value & value,const Value & delta,Value * result)674   void TableGrow(FullDecoder* decoder, const TableIndexImmediate<validate>& imm,
675                  const Value& value, const Value& delta, Value* result) {
676     result->node = BUILD(TableGrow, imm.index, value.node, delta.node);
677   }
678 
TableSize(FullDecoder * decoder,const TableIndexImmediate<validate> & imm,Value * result)679   void TableSize(FullDecoder* decoder, const TableIndexImmediate<validate>& imm,
680                  Value* result) {
681     result->node = BUILD(TableSize, imm.index);
682   }
683 
TableFill(FullDecoder * decoder,const TableIndexImmediate<validate> & imm,const Value & start,const Value & value,const Value & count)684   void TableFill(FullDecoder* decoder, const TableIndexImmediate<validate>& imm,
685                  const Value& start, const Value& value, const Value& count) {
686     BUILD(TableFill, imm.index, start.node, value.node, count.node);
687   }
688 
StructNewWithRtt(FullDecoder * decoder,const StructIndexImmediate<validate> & imm,const Value & rtt,const Value args[],Value * result)689   void StructNewWithRtt(FullDecoder* decoder,
690                         const StructIndexImmediate<validate>& imm,
691                         const Value& rtt, const Value args[], Value* result) {
692     uint32_t field_count = imm.struct_type->field_count();
693     base::SmallVector<TFNode*, 16> arg_nodes(field_count);
694     for (uint32_t i = 0; i < field_count; i++) {
695       arg_nodes[i] = args[i].node;
696     }
697     result->node = BUILD(StructNewWithRtt, imm.index, imm.struct_type, rtt.node,
698                          VectorOf(arg_nodes));
699   }
StructNewDefault(FullDecoder * decoder,const StructIndexImmediate<validate> & imm,const Value & rtt,Value * result)700   void StructNewDefault(FullDecoder* decoder,
701                         const StructIndexImmediate<validate>& imm,
702                         const Value& rtt, Value* result) {
703     uint32_t field_count = imm.struct_type->field_count();
704     base::SmallVector<TFNode*, 16> arg_nodes(field_count);
705     for (uint32_t i = 0; i < field_count; i++) {
706       arg_nodes[i] = DefaultValue(imm.struct_type->field(i));
707     }
708     result->node = BUILD(StructNewWithRtt, imm.index, imm.struct_type, rtt.node,
709                          VectorOf(arg_nodes));
710   }
711 
StructGet(FullDecoder * decoder,const Value & struct_object,const FieldIndexImmediate<validate> & field,bool is_signed,Value * result)712   void StructGet(FullDecoder* decoder, const Value& struct_object,
713                  const FieldIndexImmediate<validate>& field, bool is_signed,
714                  Value* result) {
715     CheckForNull null_check = struct_object.type.is_nullable()
716                                   ? CheckForNull::kWithNullCheck
717                                   : CheckForNull::kWithoutNullCheck;
718     result->node =
719         BUILD(StructGet, struct_object.node, field.struct_index.struct_type,
720               field.index, null_check, is_signed, decoder->position());
721   }
722 
StructSet(FullDecoder * decoder,const Value & struct_object,const FieldIndexImmediate<validate> & field,const Value & field_value)723   void StructSet(FullDecoder* decoder, const Value& struct_object,
724                  const FieldIndexImmediate<validate>& field,
725                  const Value& field_value) {
726     CheckForNull null_check = struct_object.type.is_nullable()
727                                   ? CheckForNull::kWithNullCheck
728                                   : CheckForNull::kWithoutNullCheck;
729     BUILD(StructSet, struct_object.node, field.struct_index.struct_type,
730           field.index, field_value.node, null_check, decoder->position());
731   }
732 
ArrayNewWithRtt(FullDecoder * decoder,const ArrayIndexImmediate<validate> & imm,const Value & length,const Value & initial_value,const Value & rtt,Value * result)733   void ArrayNewWithRtt(FullDecoder* decoder,
734                        const ArrayIndexImmediate<validate>& imm,
735                        const Value& length, const Value& initial_value,
736                        const Value& rtt, Value* result) {
737     result->node = BUILD(ArrayNewWithRtt, imm.index, imm.array_type,
738                          length.node, initial_value.node, rtt.node);
739   }
740 
ArrayNewDefault(FullDecoder * decoder,const ArrayIndexImmediate<validate> & imm,const Value & length,const Value & rtt,Value * result)741   void ArrayNewDefault(FullDecoder* decoder,
742                        const ArrayIndexImmediate<validate>& imm,
743                        const Value& length, const Value& rtt, Value* result) {
744     TFNode* initial_value = DefaultValue(imm.array_type->element_type());
745     result->node = BUILD(ArrayNewWithRtt, imm.index, imm.array_type,
746                          length.node, initial_value, rtt.node);
747   }
748 
ArrayGet(FullDecoder * decoder,const Value & array_obj,const ArrayIndexImmediate<validate> & imm,const Value & index,bool is_signed,Value * result)749   void ArrayGet(FullDecoder* decoder, const Value& array_obj,
750                 const ArrayIndexImmediate<validate>& imm, const Value& index,
751                 bool is_signed, Value* result) {
752     CheckForNull null_check = array_obj.type.is_nullable()
753                                   ? CheckForNull::kWithNullCheck
754                                   : CheckForNull::kWithoutNullCheck;
755     result->node = BUILD(ArrayGet, array_obj.node, imm.array_type, index.node,
756                          null_check, is_signed, decoder->position());
757   }
758 
ArraySet(FullDecoder * decoder,const Value & array_obj,const ArrayIndexImmediate<validate> & imm,const Value & index,const Value & value)759   void ArraySet(FullDecoder* decoder, const Value& array_obj,
760                 const ArrayIndexImmediate<validate>& imm, const Value& index,
761                 const Value& value) {
762     CheckForNull null_check = array_obj.type.is_nullable()
763                                   ? CheckForNull::kWithNullCheck
764                                   : CheckForNull::kWithoutNullCheck;
765     BUILD(ArraySet, array_obj.node, imm.array_type, index.node, value.node,
766           null_check, decoder->position());
767   }
768 
ArrayLen(FullDecoder * decoder,const Value & array_obj,Value * result)769   void ArrayLen(FullDecoder* decoder, const Value& array_obj, Value* result) {
770     result->node = BUILD(ArrayLen, array_obj.node, decoder->position());
771   }
772 
I31New(FullDecoder * decoder,const Value & input,Value * result)773   void I31New(FullDecoder* decoder, const Value& input, Value* result) {
774     result->node = BUILD(I31New, input.node);
775   }
776 
I31GetS(FullDecoder * decoder,const Value & input,Value * result)777   void I31GetS(FullDecoder* decoder, const Value& input, Value* result) {
778     result->node = BUILD(I31GetS, input.node);
779   }
780 
I31GetU(FullDecoder * decoder,const Value & input,Value * result)781   void I31GetU(FullDecoder* decoder, const Value& input, Value* result) {
782     result->node = BUILD(I31GetU, input.node);
783   }
784 
RttCanon(FullDecoder * decoder,const HeapTypeImmediate<validate> & imm,Value * result)785   void RttCanon(FullDecoder* decoder, const HeapTypeImmediate<validate>& imm,
786                 Value* result) {
787     result->node = BUILD(RttCanon, imm.type);
788   }
789 
RttSub(FullDecoder * decoder,const HeapTypeImmediate<validate> & imm,const Value & parent,Value * result)790   void RttSub(FullDecoder* decoder, const HeapTypeImmediate<validate>& imm,
791               const Value& parent, Value* result) {
792     result->node = BUILD(RttSub, imm.type, parent.node);
793   }
794 
RefTest(FullDecoder * decoder,const Value & object,const Value & rtt,Value * result)795   void RefTest(FullDecoder* decoder, const Value& object, const Value& rtt,
796                Value* result) {
797     using CheckForI31 = compiler::WasmGraphBuilder::CheckForI31;
798     using RttIsI31 = compiler::WasmGraphBuilder::RttIsI31;
799     CheckForNull null_check = object.type.is_nullable()
800                                   ? CheckForNull::kWithNullCheck
801                                   : CheckForNull::kWithoutNullCheck;
802     CheckForI31 i31_check =
803         IsSubtypeOf(kWasmI31Ref, object.type, decoder->module_)
804             ? CheckForI31::kWithI31Check
805             : CheckForI31::kNoI31Check;
806     RttIsI31 rtt_is_i31 = rtt.type.heap_representation() == HeapType::kI31
807                               ? RttIsI31::kRttIsI31
808                               : RttIsI31::kRttIsNotI31;
809     result->node = BUILD(RefTest, object.node, rtt.node, null_check, i31_check,
810                          rtt_is_i31);
811   }
812 
RefCast(FullDecoder * decoder,const Value & object,const Value & rtt,Value * result)813   void RefCast(FullDecoder* decoder, const Value& object, const Value& rtt,
814                Value* result) {
815     using CheckForI31 = compiler::WasmGraphBuilder::CheckForI31;
816     using RttIsI31 = compiler::WasmGraphBuilder::RttIsI31;
817     CheckForNull null_check = object.type.is_nullable()
818                                   ? CheckForNull::kWithNullCheck
819                                   : CheckForNull::kWithoutNullCheck;
820     CheckForI31 i31_check =
821         IsSubtypeOf(kWasmI31Ref, object.type, decoder->module_)
822             ? CheckForI31::kWithI31Check
823             : CheckForI31::kNoI31Check;
824     RttIsI31 rtt_is_i31 = rtt.type.heap_representation() == HeapType::kI31
825                               ? RttIsI31::kRttIsI31
826                               : RttIsI31::kRttIsNotI31;
827     result->node = BUILD(RefCast, object.node, rtt.node, null_check, i31_check,
828                          rtt_is_i31, decoder->position());
829   }
830 
BrOnCast(FullDecoder * decoder,const Value & object,const Value & rtt,Value * value_on_branch,uint32_t depth)831   void BrOnCast(FullDecoder* decoder, const Value& object, const Value& rtt,
832                 Value* value_on_branch, uint32_t depth) {
833     using CheckForI31 = compiler::WasmGraphBuilder::CheckForI31;
834     using RttIsI31 = compiler::WasmGraphBuilder::RttIsI31;
835     CheckForNull null_check = object.type.is_nullable()
836                                   ? CheckForNull::kWithNullCheck
837                                   : CheckForNull::kWithoutNullCheck;
838     CheckForI31 i31_check =
839         IsSubtypeOf(kWasmI31Ref, object.type, decoder->module_)
840             ? CheckForI31::kWithI31Check
841             : CheckForI31::kNoI31Check;
842     RttIsI31 rtt_is_i31 = rtt.type.heap_representation() == HeapType::kI31
843                               ? RttIsI31::kRttIsI31
844                               : RttIsI31::kRttIsNotI31;
845     SsaEnv* match_env = Split(decoder->zone(), ssa_env_);
846     SsaEnv* no_match_env = Steal(decoder->zone(), ssa_env_);
847     no_match_env->SetNotMerged();
848     BUILD(BrOnCast, object.node, rtt.node, null_check, i31_check, rtt_is_i31,
849           &match_env->control, &match_env->effect, &no_match_env->control,
850           &no_match_env->effect);
851     builder_->SetControl(no_match_env->control);
852     SetEnv(match_env);
853     value_on_branch->node = object.node;
854     BrOrRet(decoder, depth);
855     SetEnv(no_match_env);
856   }
857 
PassThrough(FullDecoder * decoder,const Value & from,Value * to)858   void PassThrough(FullDecoder* decoder, const Value& from, Value* to) {
859     to->node = from.node;
860   }
861 
862  private:
863   SsaEnv* ssa_env_ = nullptr;
864   compiler::WasmGraphBuilder* builder_;
865   uint32_t current_catch_ = kNullCatch;
866 
effect()867   TFNode* effect() { return builder_->effect(); }
868 
control()869   TFNode* control() { return builder_->control(); }
870 
current_try_info(FullDecoder * decoder)871   TryInfo* current_try_info(FullDecoder* decoder) {
872     return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
873         ->try_info;
874   }
875 
GetNodes(TFNode ** nodes,Value * values,size_t count)876   void GetNodes(TFNode** nodes, Value* values, size_t count) {
877     for (size_t i = 0; i < count; ++i) {
878       nodes[i] = values[i].node;
879     }
880   }
881 
GetNodes(TFNode ** nodes,Vector<Value> values)882   void GetNodes(TFNode** nodes, Vector<Value> values) {
883     GetNodes(nodes, values.begin(), values.size());
884   }
885 
SetEnv(SsaEnv * env)886   void SetEnv(SsaEnv* env) {
887     if (FLAG_trace_wasm_decoder) {
888       char state = 'X';
889       if (env) {
890         switch (env->state) {
891           case SsaEnv::kReached:
892             state = 'R';
893             break;
894           case SsaEnv::kUnreachable:
895             state = 'U';
896             break;
897           case SsaEnv::kMerged:
898             state = 'M';
899             break;
900           case SsaEnv::kControlEnd:
901             state = 'E';
902             break;
903         }
904       }
905       PrintF("{set_env = %p, state = %c", env, state);
906       if (env && env->control) {
907         PrintF(", control = ");
908         compiler::WasmGraphBuilder::PrintDebugName(env->control);
909       }
910       PrintF("}\n");
911     }
912     if (ssa_env_) {
913       ssa_env_->control = control();
914       ssa_env_->effect = effect();
915     }
916     ssa_env_ = env;
917     builder_->SetEffectControl(env->effect, env->control);
918     builder_->set_instance_cache(&env->instance_cache);
919   }
920 
CheckForException(FullDecoder * decoder,TFNode * node)921   TFNode* CheckForException(FullDecoder* decoder, TFNode* node) {
922     if (node == nullptr) return nullptr;
923 
924     const bool inside_try_scope = current_catch_ != kNullCatch;
925 
926     if (!inside_try_scope) return node;
927 
928     TFNode* if_success = nullptr;
929     TFNode* if_exception = nullptr;
930     if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
931       return node;
932     }
933 
934     SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
935     success_env->control = if_success;
936 
937     SsaEnv* exception_env = Split(decoder->zone(), success_env);
938     exception_env->control = if_exception;
939     exception_env->effect = if_exception;
940     SetEnv(exception_env);
941     TryInfo* try_info = current_try_info(decoder);
942     Goto(decoder, try_info->catch_env);
943     if (try_info->exception == nullptr) {
944       DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
945       try_info->exception = if_exception;
946     } else {
947       DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
948       try_info->exception = builder_->CreateOrMergeIntoPhi(
949           MachineRepresentation::kWord32, try_info->catch_env->control,
950           try_info->exception, if_exception);
951     }
952 
953     SetEnv(success_env);
954     return node;
955   }
956 
DefaultValue(ValueType type)957   TFNode* DefaultValue(ValueType type) {
958     DCHECK(type.is_defaultable());
959     switch (type.kind()) {
960       case ValueType::kI8:
961       case ValueType::kI16:
962       case ValueType::kI32:
963         return builder_->Int32Constant(0);
964       case ValueType::kI64:
965         return builder_->Int64Constant(0);
966       case ValueType::kF32:
967         return builder_->Float32Constant(0);
968       case ValueType::kF64:
969         return builder_->Float64Constant(0);
970       case ValueType::kS128:
971         return builder_->S128Zero();
972       case ValueType::kOptRef:
973         return builder_->RefNull();
974       case ValueType::kRtt:
975       case ValueType::kStmt:
976       case ValueType::kBottom:
977       case ValueType::kRef:
978         UNREACHABLE();
979     }
980   }
981 
MergeValuesInto(FullDecoder * decoder,Control * c,Merge<Value> * merge,Value * values)982   void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge,
983                        Value* values) {
984     DCHECK(merge == &c->start_merge || merge == &c->end_merge);
985 
986     SsaEnv* target = c->end_env;
987     const bool first = target->state == SsaEnv::kUnreachable;
988     Goto(decoder, target);
989 
990     if (merge->arity == 0) return;
991 
992     for (uint32_t i = 0; i < merge->arity; ++i) {
993       Value& val = values[i];
994       Value& old = (*merge)[i];
995       DCHECK_NOT_NULL(val.node);
996       DCHECK(val.type == kWasmBottom || val.type.machine_representation() ==
997                                             old.type.machine_representation());
998       old.node = first ? val.node
999                        : builder_->CreateOrMergeIntoPhi(
1000                              old.type.machine_representation(), target->control,
1001                              old.node, val.node);
1002     }
1003   }
1004 
MergeValuesInto(FullDecoder * decoder,Control * c,Merge<Value> * merge)1005   void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge) {
1006 #ifdef DEBUG
1007     uint32_t avail =
1008         decoder->stack_size() - decoder->control_at(0)->stack_depth;
1009     DCHECK_GE(avail, merge->arity);
1010 #endif
1011     Value* stack_values =
1012         merge->arity > 0 ? decoder->stack_value(merge->arity) : nullptr;
1013     MergeValuesInto(decoder, c, merge, stack_values);
1014   }
1015 
Goto(FullDecoder * decoder,SsaEnv * to)1016   void Goto(FullDecoder* decoder, SsaEnv* to) {
1017     DCHECK_NOT_NULL(to);
1018     switch (to->state) {
1019       case SsaEnv::kUnreachable: {  // Overwrite destination.
1020         to->state = SsaEnv::kReached;
1021         to->locals = ssa_env_->locals;
1022         to->control = control();
1023         to->effect = effect();
1024         to->instance_cache = ssa_env_->instance_cache;
1025         break;
1026       }
1027       case SsaEnv::kReached: {  // Create a new merge.
1028         to->state = SsaEnv::kMerged;
1029         // Merge control.
1030         TFNode* controls[] = {to->control, control()};
1031         TFNode* merge = builder_->Merge(2, controls);
1032         to->control = merge;
1033         // Merge effects.
1034         TFNode* old_effect = effect();
1035         if (old_effect != to->effect) {
1036           TFNode* inputs[] = {to->effect, old_effect, merge};
1037           to->effect = builder_->EffectPhi(2, inputs);
1038         }
1039         // Merge SSA values.
1040         for (int i = decoder->num_locals() - 1; i >= 0; i--) {
1041           TFNode* a = to->locals[i];
1042           TFNode* b = ssa_env_->locals[i];
1043           if (a != b) {
1044             TFNode* inputs[] = {a, b, merge};
1045             to->locals[i] = builder_->Phi(decoder->local_type(i), 2, inputs);
1046           }
1047         }
1048         // Start a new merge from the instance cache.
1049         builder_->NewInstanceCacheMerge(&to->instance_cache,
1050                                         &ssa_env_->instance_cache, merge);
1051         break;
1052       }
1053       case SsaEnv::kMerged: {
1054         TFNode* merge = to->control;
1055         // Extend the existing merge control node.
1056         builder_->AppendToMerge(merge, control());
1057         // Merge effects.
1058         to->effect =
1059             builder_->CreateOrMergeIntoEffectPhi(merge, to->effect, effect());
1060         // Merge locals.
1061         for (int i = decoder->num_locals() - 1; i >= 0; i--) {
1062           to->locals[i] = builder_->CreateOrMergeIntoPhi(
1063               decoder->local_type(i).machine_representation(), merge,
1064               to->locals[i], ssa_env_->locals[i]);
1065         }
1066         // Merge the instance caches.
1067         builder_->MergeInstanceCacheInto(&to->instance_cache,
1068                                          &ssa_env_->instance_cache, merge);
1069         break;
1070       }
1071       default:
1072         UNREACHABLE();
1073     }
1074     return ssa_env_->Kill();
1075   }
1076 
PrepareForLoop(FullDecoder * decoder)1077   void PrepareForLoop(FullDecoder* decoder) {
1078     ssa_env_->state = SsaEnv::kMerged;
1079 
1080     builder_->SetControl(builder_->Loop(control()));
1081     TFNode* effect_inputs[] = {effect(), control()};
1082     builder_->SetEffect(builder_->EffectPhi(1, effect_inputs));
1083     builder_->TerminateLoop(effect(), control());
1084     // The '+ 1' here is to be able to set the instance cache as assigned.
1085     BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
1086         decoder, decoder->pc(), decoder->num_locals() + 1, decoder->zone());
1087     if (decoder->failed()) return;
1088     DCHECK_NOT_NULL(assigned);
1089 
1090     // Only introduce phis for variables assigned in this loop.
1091     int instance_cache_index = decoder->num_locals();
1092     for (int i = decoder->num_locals() - 1; i >= 0; i--) {
1093       if (!assigned->Contains(i)) continue;
1094       TFNode* inputs[] = {ssa_env_->locals[i], control()};
1095       ssa_env_->locals[i] = builder_->Phi(decoder->local_type(i), 1, inputs);
1096     }
1097     // Introduce phis for instance cache pointers if necessary.
1098     if (assigned->Contains(instance_cache_index)) {
1099       builder_->PrepareInstanceCacheForLoop(&ssa_env_->instance_cache,
1100                                             control());
1101     }
1102 
1103     SetEnv(Split(decoder->zone(), ssa_env_));
1104     builder_->StackCheck(decoder->position());
1105   }
1106 
1107   // Create a complete copy of {from}.
Split(Zone * zone,SsaEnv * from)1108   SsaEnv* Split(Zone* zone, SsaEnv* from) {
1109     DCHECK_NOT_NULL(from);
1110     if (from == ssa_env_) {
1111       ssa_env_->control = control();
1112       ssa_env_->effect = effect();
1113     }
1114     SsaEnv* result = zone->New<SsaEnv>(*from);
1115     result->state = SsaEnv::kReached;
1116     return result;
1117   }
1118 
1119   // Create a copy of {from} that steals its state and leaves {from}
1120   // unreachable.
Steal(Zone * zone,SsaEnv * from)1121   SsaEnv* Steal(Zone* zone, SsaEnv* from) {
1122     DCHECK_NOT_NULL(from);
1123     if (from == ssa_env_) {
1124       ssa_env_->control = control();
1125       ssa_env_->effect = effect();
1126     }
1127     SsaEnv* result = zone->New<SsaEnv>(std::move(*from));
1128     result->state = SsaEnv::kReached;
1129     return result;
1130   }
1131 
1132   // Create an unreachable environment.
UnreachableEnv(Zone * zone)1133   SsaEnv* UnreachableEnv(Zone* zone) {
1134     return zone->New<SsaEnv>(zone, SsaEnv::kUnreachable, nullptr, nullptr, 0);
1135   }
1136 
DoCall(FullDecoder * decoder,CallMode call_mode,uint32_t table_index,CheckForNull null_check,TFNode * caller_node,const FunctionSig * sig,uint32_t sig_index,const Value args[],Value returns[])1137   void DoCall(FullDecoder* decoder, CallMode call_mode, uint32_t table_index,
1138               CheckForNull null_check, TFNode* caller_node,
1139               const FunctionSig* sig, uint32_t sig_index, const Value args[],
1140               Value returns[]) {
1141     size_t param_count = sig->parameter_count();
1142     size_t return_count = sig->return_count();
1143     base::SmallVector<TFNode*, 16> arg_nodes(param_count + 1);
1144     base::SmallVector<TFNode*, 1> return_nodes(return_count);
1145     arg_nodes[0] = caller_node;
1146     for (size_t i = 0; i < param_count; ++i) {
1147       arg_nodes[i + 1] = args[i].node;
1148     }
1149     switch (call_mode) {
1150       case kIndirect:
1151         BUILD(CallIndirect, table_index, sig_index, VectorOf(arg_nodes),
1152               VectorOf(return_nodes), decoder->position());
1153         break;
1154       case kDirect:
1155         BUILD(CallDirect, sig_index, VectorOf(arg_nodes),
1156               VectorOf(return_nodes), decoder->position());
1157         break;
1158       case kRef:
1159         BUILD(CallRef, sig_index, VectorOf(arg_nodes), VectorOf(return_nodes),
1160               null_check, decoder->position());
1161         break;
1162     }
1163     for (size_t i = 0; i < return_count; ++i) {
1164       returns[i].node = return_nodes[i];
1165     }
1166     // The invoked function could have used grow_memory, so we need to
1167     // reload mem_size and mem_start.
1168     LoadContextIntoSsa(ssa_env_);
1169   }
1170 
DoReturnCall(FullDecoder * decoder,CallMode call_mode,uint32_t table_index,CheckForNull null_check,TFNode * index_node,const FunctionSig * sig,uint32_t sig_index,const Value args[])1171   void DoReturnCall(FullDecoder* decoder, CallMode call_mode,
1172                     uint32_t table_index, CheckForNull null_check,
1173                     TFNode* index_node, const FunctionSig* sig,
1174                     uint32_t sig_index, const Value args[]) {
1175     size_t arg_count = sig->parameter_count();
1176     base::SmallVector<TFNode*, 16> arg_nodes(arg_count + 1);
1177     arg_nodes[0] = index_node;
1178     for (size_t i = 0; i < arg_count; ++i) {
1179       arg_nodes[i + 1] = args[i].node;
1180     }
1181     switch (call_mode) {
1182       case kIndirect:
1183         BUILD(ReturnCallIndirect, table_index, sig_index, VectorOf(arg_nodes),
1184               decoder->position());
1185         break;
1186       case kDirect:
1187         BUILD(ReturnCall, sig_index, VectorOf(arg_nodes), decoder->position());
1188         break;
1189       case kRef:
1190         BUILD(ReturnCallRef, sig_index, VectorOf(arg_nodes), null_check,
1191               decoder->position());
1192     }
1193   }
1194 };
1195 
1196 }  // namespace
1197 
BuildTFGraph(AccountingAllocator * allocator,const WasmFeatures & enabled,const WasmModule * module,compiler::WasmGraphBuilder * builder,WasmFeatures * detected,const FunctionBody & body,compiler::NodeOriginTable * node_origins)1198 DecodeResult BuildTFGraph(AccountingAllocator* allocator,
1199                           const WasmFeatures& enabled, const WasmModule* module,
1200                           compiler::WasmGraphBuilder* builder,
1201                           WasmFeatures* detected, const FunctionBody& body,
1202                           compiler::NodeOriginTable* node_origins) {
1203   Zone zone(allocator, ZONE_NAME);
1204   WasmFullDecoder<Decoder::kFullValidation, WasmGraphBuildingInterface> decoder(
1205       &zone, module, enabled, detected, body, builder);
1206   if (node_origins) {
1207     builder->AddBytecodePositionDecorator(node_origins, &decoder);
1208   }
1209   decoder.Decode();
1210   if (node_origins) {
1211     builder->RemoveBytecodePositionDecorator();
1212   }
1213   return decoder.toResult(nullptr);
1214 }
1215 
1216 #undef BUILD
1217 
1218 }  // namespace wasm
1219 }  // namespace internal
1220 }  // namespace v8
1221