11cb0ef41Sopenharmony_ci// Copyright 2018 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/wasm/graph-builder-interface.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/compiler/wasm-compiler.h" 81cb0ef41Sopenharmony_ci#include "src/flags/flags.h" 91cb0ef41Sopenharmony_ci#include "src/handles/handles.h" 101cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 111cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h" 121cb0ef41Sopenharmony_ci#include "src/wasm/branch-hint-map.h" 131cb0ef41Sopenharmony_ci#include "src/wasm/decoder.h" 141cb0ef41Sopenharmony_ci#include "src/wasm/function-body-decoder-impl.h" 151cb0ef41Sopenharmony_ci#include "src/wasm/function-body-decoder.h" 161cb0ef41Sopenharmony_ci#include "src/wasm/value-type.h" 171cb0ef41Sopenharmony_ci#include "src/wasm/wasm-limits.h" 181cb0ef41Sopenharmony_ci#include "src/wasm/wasm-linkage.h" 191cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h" 201cb0ef41Sopenharmony_ci#include "src/wasm/wasm-opcodes-inl.h" 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_cinamespace v8 { 231cb0ef41Sopenharmony_cinamespace internal { 241cb0ef41Sopenharmony_cinamespace wasm { 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cinamespace { 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci// An SsaEnv environment carries the current local variable renaming 291cb0ef41Sopenharmony_ci// as well as the current effect and control dependency in the TF graph. 301cb0ef41Sopenharmony_ci// It maintains a control state that tracks whether the environment 311cb0ef41Sopenharmony_ci// is reachable, has reached a control end, or has been merged. 321cb0ef41Sopenharmony_cistruct SsaEnv : public ZoneObject { 331cb0ef41Sopenharmony_ci enum State { kUnreachable, kReached, kMerged }; 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci State state; 361cb0ef41Sopenharmony_ci TFNode* control; 371cb0ef41Sopenharmony_ci TFNode* effect; 381cb0ef41Sopenharmony_ci compiler::WasmInstanceCacheNodes instance_cache; 391cb0ef41Sopenharmony_ci ZoneVector<TFNode*> locals; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ci SsaEnv(Zone* zone, State state, TFNode* control, TFNode* effect, 421cb0ef41Sopenharmony_ci uint32_t locals_size) 431cb0ef41Sopenharmony_ci : state(state), 441cb0ef41Sopenharmony_ci control(control), 451cb0ef41Sopenharmony_ci effect(effect), 461cb0ef41Sopenharmony_ci locals(locals_size, zone) {} 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci SsaEnv(const SsaEnv& other) V8_NOEXCEPT = default; 491cb0ef41Sopenharmony_ci SsaEnv(SsaEnv&& other) V8_NOEXCEPT : state(other.state), 501cb0ef41Sopenharmony_ci control(other.control), 511cb0ef41Sopenharmony_ci effect(other.effect), 521cb0ef41Sopenharmony_ci instance_cache(other.instance_cache), 531cb0ef41Sopenharmony_ci locals(std::move(other.locals)) { 541cb0ef41Sopenharmony_ci other.Kill(); 551cb0ef41Sopenharmony_ci } 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci void Kill() { 581cb0ef41Sopenharmony_ci state = kUnreachable; 591cb0ef41Sopenharmony_ci for (TFNode*& local : locals) { 601cb0ef41Sopenharmony_ci local = nullptr; 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci control = nullptr; 631cb0ef41Sopenharmony_ci effect = nullptr; 641cb0ef41Sopenharmony_ci instance_cache = {}; 651cb0ef41Sopenharmony_ci } 661cb0ef41Sopenharmony_ci void SetNotMerged() { 671cb0ef41Sopenharmony_ci if (state == kMerged) state = kReached; 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci}; 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ciclass WasmGraphBuildingInterface { 721cb0ef41Sopenharmony_ci public: 731cb0ef41Sopenharmony_ci static constexpr Decoder::ValidateFlag validate = Decoder::kFullValidation; 741cb0ef41Sopenharmony_ci using FullDecoder = WasmFullDecoder<validate, WasmGraphBuildingInterface>; 751cb0ef41Sopenharmony_ci using CheckForNull = compiler::WasmGraphBuilder::CheckForNull; 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci struct Value : public ValueBase<validate> { 781cb0ef41Sopenharmony_ci TFNode* node = nullptr; 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci template <typename... Args> 811cb0ef41Sopenharmony_ci explicit Value(Args&&... args) V8_NOEXCEPT 821cb0ef41Sopenharmony_ci : ValueBase(std::forward<Args>(args)...) {} 831cb0ef41Sopenharmony_ci }; 841cb0ef41Sopenharmony_ci using ValueVector = base::SmallVector<Value, 8>; 851cb0ef41Sopenharmony_ci using NodeVector = base::SmallVector<TFNode*, 8>; 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci struct TryInfo : public ZoneObject { 881cb0ef41Sopenharmony_ci SsaEnv* catch_env; 891cb0ef41Sopenharmony_ci TFNode* exception = nullptr; 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci bool might_throw() const { return exception != nullptr; } 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(TryInfo); 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci explicit TryInfo(SsaEnv* c) : catch_env(c) {} 961cb0ef41Sopenharmony_ci }; 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci struct Control : public ControlBase<Value, validate> { 991cb0ef41Sopenharmony_ci SsaEnv* merge_env = nullptr; // merge environment for the construct. 1001cb0ef41Sopenharmony_ci SsaEnv* false_env = nullptr; // false environment (only for if). 1011cb0ef41Sopenharmony_ci TryInfo* try_info = nullptr; // information about try statements. 1021cb0ef41Sopenharmony_ci int32_t previous_catch = -1; // previous Control with a catch. 1031cb0ef41Sopenharmony_ci BitVector* loop_assignments = nullptr; // locals assigned in this loop. 1041cb0ef41Sopenharmony_ci TFNode* loop_node = nullptr; // loop header of this loop. 1051cb0ef41Sopenharmony_ci MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(Control); 1061cb0ef41Sopenharmony_ci 1071cb0ef41Sopenharmony_ci template <typename... Args> 1081cb0ef41Sopenharmony_ci explicit Control(Args&&... args) V8_NOEXCEPT 1091cb0ef41Sopenharmony_ci : ControlBase(std::forward<Args>(args)...) {} 1101cb0ef41Sopenharmony_ci }; 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder, 1131cb0ef41Sopenharmony_ci int func_index, InlinedStatus inlined_status) 1141cb0ef41Sopenharmony_ci : builder_(builder), 1151cb0ef41Sopenharmony_ci func_index_(func_index), 1161cb0ef41Sopenharmony_ci inlined_status_(inlined_status) {} 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci void StartFunction(FullDecoder* decoder) { 1191cb0ef41Sopenharmony_ci // Get the branch hints map and type feedback for this function (if 1201cb0ef41Sopenharmony_ci // available). 1211cb0ef41Sopenharmony_ci if (decoder->module_) { 1221cb0ef41Sopenharmony_ci auto branch_hints_it = decoder->module_->branch_hints.find(func_index_); 1231cb0ef41Sopenharmony_ci if (branch_hints_it != decoder->module_->branch_hints.end()) { 1241cb0ef41Sopenharmony_ci branch_hints_ = &branch_hints_it->second; 1251cb0ef41Sopenharmony_ci } 1261cb0ef41Sopenharmony_ci TypeFeedbackStorage& feedbacks = decoder->module_->type_feedback; 1271cb0ef41Sopenharmony_ci base::MutexGuard mutex_guard(&feedbacks.mutex); 1281cb0ef41Sopenharmony_ci auto feedback = feedbacks.feedback_for_function.find(func_index_); 1291cb0ef41Sopenharmony_ci if (feedback != feedbacks.feedback_for_function.end()) { 1301cb0ef41Sopenharmony_ci type_feedback_ = feedback->second.feedback_vector; 1311cb0ef41Sopenharmony_ci // We need to keep the feedback in the module to inline later. However, 1321cb0ef41Sopenharmony_ci // this means we are stuck with it forever. 1331cb0ef41Sopenharmony_ci // TODO(jkummerow): Reconsider our options here. 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci } 1361cb0ef41Sopenharmony_ci // The first '+ 1' is needed by TF Start node, the second '+ 1' is for the 1371cb0ef41Sopenharmony_ci // instance parameter. 1381cb0ef41Sopenharmony_ci builder_->Start(static_cast<int>(decoder->sig_->parameter_count() + 1 + 1)); 1391cb0ef41Sopenharmony_ci uint32_t num_locals = decoder->num_locals(); 1401cb0ef41Sopenharmony_ci SsaEnv* ssa_env = decoder->zone()->New<SsaEnv>( 1411cb0ef41Sopenharmony_ci decoder->zone(), SsaEnv::kReached, effect(), control(), num_locals); 1421cb0ef41Sopenharmony_ci SetEnv(ssa_env); 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci // Initialize local variables. Parameters are shifted by 1 because of the 1451cb0ef41Sopenharmony_ci // the instance parameter. 1461cb0ef41Sopenharmony_ci uint32_t index = 0; 1471cb0ef41Sopenharmony_ci for (; index < decoder->sig_->parameter_count(); ++index) { 1481cb0ef41Sopenharmony_ci ssa_env->locals[index] = builder_->Param(index + 1); 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci while (index < num_locals) { 1511cb0ef41Sopenharmony_ci ValueType type = decoder->local_type(index); 1521cb0ef41Sopenharmony_ci TFNode* node; 1531cb0ef41Sopenharmony_ci if ((decoder->enabled_.has_nn_locals() || 1541cb0ef41Sopenharmony_ci decoder->enabled_.has_unsafe_nn_locals()) && 1551cb0ef41Sopenharmony_ci !type.is_defaultable()) { 1561cb0ef41Sopenharmony_ci DCHECK(type.is_reference()); 1571cb0ef41Sopenharmony_ci // TODO(jkummerow): Consider using "the hole" instead, to make any 1581cb0ef41Sopenharmony_ci // illegal uses more obvious. 1591cb0ef41Sopenharmony_ci node = builder_->RefNull(); 1601cb0ef41Sopenharmony_ci } else { 1611cb0ef41Sopenharmony_ci node = DefaultValue(type); 1621cb0ef41Sopenharmony_ci } 1631cb0ef41Sopenharmony_ci while (index < num_locals && decoder->local_type(index) == type) { 1641cb0ef41Sopenharmony_ci // Do a whole run of like-typed locals at a time. 1651cb0ef41Sopenharmony_ci ssa_env->locals[index++] = node; 1661cb0ef41Sopenharmony_ci } 1671cb0ef41Sopenharmony_ci } 1681cb0ef41Sopenharmony_ci LoadContextIntoSsa(ssa_env); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci if (FLAG_trace_wasm && inlined_status_ == kRegularFunction) { 1711cb0ef41Sopenharmony_ci builder_->TraceFunctionEntry(decoder->position()); 1721cb0ef41Sopenharmony_ci } 1731cb0ef41Sopenharmony_ci } 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci // Reload the instance cache entries into the Ssa Environment. 1761cb0ef41Sopenharmony_ci void LoadContextIntoSsa(SsaEnv* ssa_env) { 1771cb0ef41Sopenharmony_ci if (ssa_env) builder_->InitInstanceCache(&ssa_env->instance_cache); 1781cb0ef41Sopenharmony_ci } 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_ci void StartFunctionBody(FullDecoder* decoder, Control* block) {} 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci void FinishFunction(FullDecoder*) { 1831cb0ef41Sopenharmony_ci if (inlined_status_ == kRegularFunction) { 1841cb0ef41Sopenharmony_ci builder_->PatchInStackCheckIfNeeded(); 1851cb0ef41Sopenharmony_ci } 1861cb0ef41Sopenharmony_ci } 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci void OnFirstError(FullDecoder*) {} 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci void NextInstruction(FullDecoder*, WasmOpcode) {} 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci void Block(FullDecoder* decoder, Control* block) { 1931cb0ef41Sopenharmony_ci // The branch environment is the outer environment. 1941cb0ef41Sopenharmony_ci block->merge_env = ssa_env_; 1951cb0ef41Sopenharmony_ci SetEnv(Steal(decoder->zone(), ssa_env_)); 1961cb0ef41Sopenharmony_ci } 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci void Loop(FullDecoder* decoder, Control* block) { 1991cb0ef41Sopenharmony_ci // This is the merge environment at the beginning of the loop. 2001cb0ef41Sopenharmony_ci SsaEnv* merge_env = Steal(decoder->zone(), ssa_env_); 2011cb0ef41Sopenharmony_ci block->merge_env = merge_env; 2021cb0ef41Sopenharmony_ci SetEnv(merge_env); 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci ssa_env_->state = SsaEnv::kMerged; 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci TFNode* loop_node = builder_->Loop(control()); 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci if (emit_loop_exits()) { 2091cb0ef41Sopenharmony_ci uint32_t nesting_depth = 0; 2101cb0ef41Sopenharmony_ci for (uint32_t depth = 1; depth < decoder->control_depth(); depth++) { 2111cb0ef41Sopenharmony_ci if (decoder->control_at(depth)->is_loop()) { 2121cb0ef41Sopenharmony_ci nesting_depth++; 2131cb0ef41Sopenharmony_ci } 2141cb0ef41Sopenharmony_ci } 2151cb0ef41Sopenharmony_ci // If this loop is nested, the parent loop's can_be_innermost field needs 2161cb0ef41Sopenharmony_ci // to be false. If the last loop in loop_infos_ has less depth, it has to 2171cb0ef41Sopenharmony_ci // be the parent loop. If it does not, it means another loop has been 2181cb0ef41Sopenharmony_ci // found within the parent loop, and that loop will have set the parent's 2191cb0ef41Sopenharmony_ci // can_be_innermost to false, so we do not need to do anything. 2201cb0ef41Sopenharmony_ci if (nesting_depth > 0 && 2211cb0ef41Sopenharmony_ci loop_infos_.back().nesting_depth < nesting_depth) { 2221cb0ef41Sopenharmony_ci loop_infos_.back().can_be_innermost = false; 2231cb0ef41Sopenharmony_ci } 2241cb0ef41Sopenharmony_ci loop_infos_.emplace_back(loop_node, nesting_depth, true); 2251cb0ef41Sopenharmony_ci } 2261cb0ef41Sopenharmony_ci 2271cb0ef41Sopenharmony_ci builder_->SetControl(loop_node); 2281cb0ef41Sopenharmony_ci decoder->control_at(0)->loop_node = loop_node; 2291cb0ef41Sopenharmony_ci 2301cb0ef41Sopenharmony_ci TFNode* effect_inputs[] = {effect(), control()}; 2311cb0ef41Sopenharmony_ci builder_->SetEffect(builder_->EffectPhi(1, effect_inputs)); 2321cb0ef41Sopenharmony_ci builder_->TerminateLoop(effect(), control()); 2331cb0ef41Sopenharmony_ci // Doing a preprocessing pass to analyze loop assignments seems to pay off 2341cb0ef41Sopenharmony_ci // compared to reallocating Nodes when rearranging Phis in Goto. 2351cb0ef41Sopenharmony_ci BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment( 2361cb0ef41Sopenharmony_ci decoder, decoder->pc(), decoder->num_locals(), decoder->zone()); 2371cb0ef41Sopenharmony_ci if (decoder->failed()) return; 2381cb0ef41Sopenharmony_ci int instance_cache_index = decoder->num_locals(); 2391cb0ef41Sopenharmony_ci // If the module has shared memory, the stack guard might reallocate the 2401cb0ef41Sopenharmony_ci // shared memory. We have to assume the instance cache will be updated. 2411cb0ef41Sopenharmony_ci if (decoder->module_->has_shared_memory) { 2421cb0ef41Sopenharmony_ci assigned->Add(instance_cache_index); 2431cb0ef41Sopenharmony_ci } 2441cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(assigned); 2451cb0ef41Sopenharmony_ci decoder->control_at(0)->loop_assignments = assigned; 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci // Only introduce phis for variables assigned in this loop. 2481cb0ef41Sopenharmony_ci for (int i = decoder->num_locals() - 1; i >= 0; i--) { 2491cb0ef41Sopenharmony_ci if (!assigned->Contains(i)) continue; 2501cb0ef41Sopenharmony_ci TFNode* inputs[] = {ssa_env_->locals[i], control()}; 2511cb0ef41Sopenharmony_ci ssa_env_->locals[i] = builder_->Phi(decoder->local_type(i), 1, inputs); 2521cb0ef41Sopenharmony_ci } 2531cb0ef41Sopenharmony_ci // Introduce phis for instance cache pointers if necessary. 2541cb0ef41Sopenharmony_ci if (assigned->Contains(instance_cache_index)) { 2551cb0ef41Sopenharmony_ci builder_->PrepareInstanceCacheForLoop(&ssa_env_->instance_cache, 2561cb0ef41Sopenharmony_ci control()); 2571cb0ef41Sopenharmony_ci } 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci // Now we setup a new environment for the inside of the loop. 2601cb0ef41Sopenharmony_ci SetEnv(Split(decoder->zone(), ssa_env_)); 2611cb0ef41Sopenharmony_ci builder_->StackCheck(decoder->module_->has_shared_memory 2621cb0ef41Sopenharmony_ci ? &ssa_env_->instance_cache 2631cb0ef41Sopenharmony_ci : nullptr, 2641cb0ef41Sopenharmony_ci decoder->position()); 2651cb0ef41Sopenharmony_ci ssa_env_->SetNotMerged(); 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci // Wrap input merge into phis. 2681cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < block->start_merge.arity; ++i) { 2691cb0ef41Sopenharmony_ci Value& val = block->start_merge[i]; 2701cb0ef41Sopenharmony_ci TFNode* inputs[] = {val.node, block->merge_env->control}; 2711cb0ef41Sopenharmony_ci val.node = builder_->Phi(val.type, 1, inputs); 2721cb0ef41Sopenharmony_ci } 2731cb0ef41Sopenharmony_ci } 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci void Try(FullDecoder* decoder, Control* block) { 2761cb0ef41Sopenharmony_ci SsaEnv* outer_env = ssa_env_; 2771cb0ef41Sopenharmony_ci SsaEnv* catch_env = Split(decoder->zone(), outer_env); 2781cb0ef41Sopenharmony_ci // Mark catch environment as unreachable, since only accessable 2791cb0ef41Sopenharmony_ci // through catch unwinding (i.e. landing pads). 2801cb0ef41Sopenharmony_ci catch_env->state = SsaEnv::kUnreachable; 2811cb0ef41Sopenharmony_ci SsaEnv* try_env = Steal(decoder->zone(), outer_env); 2821cb0ef41Sopenharmony_ci SetEnv(try_env); 2831cb0ef41Sopenharmony_ci TryInfo* try_info = decoder->zone()->New<TryInfo>(catch_env); 2841cb0ef41Sopenharmony_ci block->merge_env = outer_env; 2851cb0ef41Sopenharmony_ci block->try_info = try_info; 2861cb0ef41Sopenharmony_ci } 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_ci void If(FullDecoder* decoder, const Value& cond, Control* if_block) { 2891cb0ef41Sopenharmony_ci TFNode* if_true = nullptr; 2901cb0ef41Sopenharmony_ci TFNode* if_false = nullptr; 2911cb0ef41Sopenharmony_ci WasmBranchHint hint = WasmBranchHint::kNoHint; 2921cb0ef41Sopenharmony_ci if (branch_hints_) { 2931cb0ef41Sopenharmony_ci hint = branch_hints_->GetHintFor(decoder->pc_relative_offset()); 2941cb0ef41Sopenharmony_ci } 2951cb0ef41Sopenharmony_ci switch (hint) { 2961cb0ef41Sopenharmony_ci case WasmBranchHint::kNoHint: 2971cb0ef41Sopenharmony_ci builder_->BranchNoHint(cond.node, &if_true, &if_false); 2981cb0ef41Sopenharmony_ci break; 2991cb0ef41Sopenharmony_ci case WasmBranchHint::kUnlikely: 3001cb0ef41Sopenharmony_ci builder_->BranchExpectFalse(cond.node, &if_true, &if_false); 3011cb0ef41Sopenharmony_ci break; 3021cb0ef41Sopenharmony_ci case WasmBranchHint::kLikely: 3031cb0ef41Sopenharmony_ci builder_->BranchExpectTrue(cond.node, &if_true, &if_false); 3041cb0ef41Sopenharmony_ci break; 3051cb0ef41Sopenharmony_ci } 3061cb0ef41Sopenharmony_ci SsaEnv* merge_env = ssa_env_; 3071cb0ef41Sopenharmony_ci SsaEnv* false_env = Split(decoder->zone(), ssa_env_); 3081cb0ef41Sopenharmony_ci false_env->control = if_false; 3091cb0ef41Sopenharmony_ci SsaEnv* true_env = Steal(decoder->zone(), ssa_env_); 3101cb0ef41Sopenharmony_ci true_env->control = if_true; 3111cb0ef41Sopenharmony_ci if_block->merge_env = merge_env; 3121cb0ef41Sopenharmony_ci if_block->false_env = false_env; 3131cb0ef41Sopenharmony_ci SetEnv(true_env); 3141cb0ef41Sopenharmony_ci } 3151cb0ef41Sopenharmony_ci 3161cb0ef41Sopenharmony_ci void FallThruTo(FullDecoder* decoder, Control* c) { 3171cb0ef41Sopenharmony_ci DCHECK(!c->is_loop()); 3181cb0ef41Sopenharmony_ci MergeValuesInto(decoder, c, &c->end_merge); 3191cb0ef41Sopenharmony_ci } 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci void PopControl(FullDecoder* decoder, Control* block) { 3221cb0ef41Sopenharmony_ci // A loop just continues with the end environment. There is no merge. 3231cb0ef41Sopenharmony_ci // However, if loop unrolling is enabled, we must create a loop exit and 3241cb0ef41Sopenharmony_ci // wrap the fallthru values on the stack. 3251cb0ef41Sopenharmony_ci if (block->is_loop()) { 3261cb0ef41Sopenharmony_ci if (emit_loop_exits() && block->reachable()) { 3271cb0ef41Sopenharmony_ci BuildLoopExits(decoder, block); 3281cb0ef41Sopenharmony_ci WrapLocalsAtLoopExit(decoder, block); 3291cb0ef41Sopenharmony_ci uint32_t arity = block->end_merge.arity; 3301cb0ef41Sopenharmony_ci if (arity > 0) { 3311cb0ef41Sopenharmony_ci Value* stack_base = decoder->stack_value(arity); 3321cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < arity; i++) { 3331cb0ef41Sopenharmony_ci Value* val = stack_base + i; 3341cb0ef41Sopenharmony_ci val->node = builder_->LoopExitValue( 3351cb0ef41Sopenharmony_ci val->node, val->type.machine_representation()); 3361cb0ef41Sopenharmony_ci } 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci } 3391cb0ef41Sopenharmony_ci return; 3401cb0ef41Sopenharmony_ci } 3411cb0ef41Sopenharmony_ci // Any other block falls through to the parent block. 3421cb0ef41Sopenharmony_ci if (block->reachable()) FallThruTo(decoder, block); 3431cb0ef41Sopenharmony_ci if (block->is_onearmed_if()) { 3441cb0ef41Sopenharmony_ci // Merge the else branch into the end merge. 3451cb0ef41Sopenharmony_ci SetEnv(block->false_env); 3461cb0ef41Sopenharmony_ci DCHECK_EQ(block->start_merge.arity, block->end_merge.arity); 3471cb0ef41Sopenharmony_ci Value* values = 3481cb0ef41Sopenharmony_ci block->start_merge.arity > 0 ? &block->start_merge[0] : nullptr; 3491cb0ef41Sopenharmony_ci MergeValuesInto(decoder, block, &block->end_merge, values); 3501cb0ef41Sopenharmony_ci } 3511cb0ef41Sopenharmony_ci // Now continue with the merged environment. 3521cb0ef41Sopenharmony_ci SetEnv(block->merge_env); 3531cb0ef41Sopenharmony_ci } 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci void UnOp(FullDecoder* decoder, WasmOpcode opcode, const Value& value, 3561cb0ef41Sopenharmony_ci Value* result) { 3571cb0ef41Sopenharmony_ci result->node = builder_->Unop(opcode, value.node, decoder->position()); 3581cb0ef41Sopenharmony_ci } 3591cb0ef41Sopenharmony_ci 3601cb0ef41Sopenharmony_ci void BinOp(FullDecoder* decoder, WasmOpcode opcode, const Value& lhs, 3611cb0ef41Sopenharmony_ci const Value& rhs, Value* result) { 3621cb0ef41Sopenharmony_ci TFNode* node = 3631cb0ef41Sopenharmony_ci builder_->Binop(opcode, lhs.node, rhs.node, decoder->position()); 3641cb0ef41Sopenharmony_ci if (result) result->node = node; 3651cb0ef41Sopenharmony_ci } 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci void I32Const(FullDecoder* decoder, Value* result, int32_t value) { 3681cb0ef41Sopenharmony_ci result->node = builder_->Int32Constant(value); 3691cb0ef41Sopenharmony_ci } 3701cb0ef41Sopenharmony_ci 3711cb0ef41Sopenharmony_ci void I64Const(FullDecoder* decoder, Value* result, int64_t value) { 3721cb0ef41Sopenharmony_ci result->node = builder_->Int64Constant(value); 3731cb0ef41Sopenharmony_ci } 3741cb0ef41Sopenharmony_ci 3751cb0ef41Sopenharmony_ci void F32Const(FullDecoder* decoder, Value* result, float value) { 3761cb0ef41Sopenharmony_ci result->node = builder_->Float32Constant(value); 3771cb0ef41Sopenharmony_ci } 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci void F64Const(FullDecoder* decoder, Value* result, double value) { 3801cb0ef41Sopenharmony_ci result->node = builder_->Float64Constant(value); 3811cb0ef41Sopenharmony_ci } 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ci void S128Const(FullDecoder* decoder, const Simd128Immediate<validate>& imm, 3841cb0ef41Sopenharmony_ci Value* result) { 3851cb0ef41Sopenharmony_ci result->node = builder_->Simd128Constant(imm.value); 3861cb0ef41Sopenharmony_ci } 3871cb0ef41Sopenharmony_ci 3881cb0ef41Sopenharmony_ci void RefNull(FullDecoder* decoder, ValueType type, Value* result) { 3891cb0ef41Sopenharmony_ci result->node = builder_->RefNull(); 3901cb0ef41Sopenharmony_ci } 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_ci void RefFunc(FullDecoder* decoder, uint32_t function_index, Value* result) { 3931cb0ef41Sopenharmony_ci result->node = builder_->RefFunc(function_index); 3941cb0ef41Sopenharmony_ci } 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci void RefAsNonNull(FullDecoder* decoder, const Value& arg, Value* result) { 3971cb0ef41Sopenharmony_ci result->node = builder_->RefAsNonNull(arg.node, decoder->position()); 3981cb0ef41Sopenharmony_ci } 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci void Drop(FullDecoder* decoder) {} 4011cb0ef41Sopenharmony_ci 4021cb0ef41Sopenharmony_ci void LocalGet(FullDecoder* decoder, Value* result, 4031cb0ef41Sopenharmony_ci const IndexImmediate<validate>& imm) { 4041cb0ef41Sopenharmony_ci result->node = ssa_env_->locals[imm.index]; 4051cb0ef41Sopenharmony_ci } 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci void LocalSet(FullDecoder* decoder, const Value& value, 4081cb0ef41Sopenharmony_ci const IndexImmediate<validate>& imm) { 4091cb0ef41Sopenharmony_ci ssa_env_->locals[imm.index] = value.node; 4101cb0ef41Sopenharmony_ci } 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci void LocalTee(FullDecoder* decoder, const Value& value, Value* result, 4131cb0ef41Sopenharmony_ci const IndexImmediate<validate>& imm) { 4141cb0ef41Sopenharmony_ci result->node = value.node; 4151cb0ef41Sopenharmony_ci ssa_env_->locals[imm.index] = value.node; 4161cb0ef41Sopenharmony_ci } 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci void AllocateLocals(FullDecoder* decoder, base::Vector<Value> local_values) { 4191cb0ef41Sopenharmony_ci ZoneVector<TFNode*>* locals = &ssa_env_->locals; 4201cb0ef41Sopenharmony_ci locals->insert(locals->begin(), local_values.size(), nullptr); 4211cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < local_values.size(); i++) { 4221cb0ef41Sopenharmony_ci (*locals)[i] = local_values[i].node; 4231cb0ef41Sopenharmony_ci } 4241cb0ef41Sopenharmony_ci } 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci void DeallocateLocals(FullDecoder* decoder, uint32_t count) { 4271cb0ef41Sopenharmony_ci ZoneVector<TFNode*>* locals = &ssa_env_->locals; 4281cb0ef41Sopenharmony_ci locals->erase(locals->begin(), locals->begin() + count); 4291cb0ef41Sopenharmony_ci } 4301cb0ef41Sopenharmony_ci 4311cb0ef41Sopenharmony_ci void GlobalGet(FullDecoder* decoder, Value* result, 4321cb0ef41Sopenharmony_ci const GlobalIndexImmediate<validate>& imm) { 4331cb0ef41Sopenharmony_ci result->node = builder_->GlobalGet(imm.index); 4341cb0ef41Sopenharmony_ci } 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_ci void GlobalSet(FullDecoder* decoder, const Value& value, 4371cb0ef41Sopenharmony_ci const GlobalIndexImmediate<validate>& imm) { 4381cb0ef41Sopenharmony_ci builder_->GlobalSet(imm.index, value.node); 4391cb0ef41Sopenharmony_ci } 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci void TableGet(FullDecoder* decoder, const Value& index, Value* result, 4421cb0ef41Sopenharmony_ci const IndexImmediate<validate>& imm) { 4431cb0ef41Sopenharmony_ci result->node = 4441cb0ef41Sopenharmony_ci builder_->TableGet(imm.index, index.node, decoder->position()); 4451cb0ef41Sopenharmony_ci } 4461cb0ef41Sopenharmony_ci 4471cb0ef41Sopenharmony_ci void TableSet(FullDecoder* decoder, const Value& index, const Value& value, 4481cb0ef41Sopenharmony_ci const IndexImmediate<validate>& imm) { 4491cb0ef41Sopenharmony_ci builder_->TableSet(imm.index, index.node, value.node, decoder->position()); 4501cb0ef41Sopenharmony_ci } 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ci void Trap(FullDecoder* decoder, TrapReason reason) { 4531cb0ef41Sopenharmony_ci builder_->Trap(reason, decoder->position()); 4541cb0ef41Sopenharmony_ci } 4551cb0ef41Sopenharmony_ci 4561cb0ef41Sopenharmony_ci void AssertNull(FullDecoder* decoder, const Value& obj, Value* result) { 4571cb0ef41Sopenharmony_ci builder_->TrapIfFalse( 4581cb0ef41Sopenharmony_ci wasm::TrapReason::kTrapIllegalCast, 4591cb0ef41Sopenharmony_ci builder_->Binop(kExprRefEq, obj.node, builder_->RefNull(), 4601cb0ef41Sopenharmony_ci decoder->position()), 4611cb0ef41Sopenharmony_ci decoder->position()); 4621cb0ef41Sopenharmony_ci result->node = obj.node; 4631cb0ef41Sopenharmony_ci } 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci void NopForTestingUnsupportedInLiftoff(FullDecoder* decoder) {} 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci void Select(FullDecoder* decoder, const Value& cond, const Value& fval, 4681cb0ef41Sopenharmony_ci const Value& tval, Value* result) { 4691cb0ef41Sopenharmony_ci result->node = 4701cb0ef41Sopenharmony_ci builder_->Select(cond.node, tval.node, fval.node, result->type); 4711cb0ef41Sopenharmony_ci } 4721cb0ef41Sopenharmony_ci 4731cb0ef41Sopenharmony_ci ValueVector CopyStackValues(FullDecoder* decoder, uint32_t count, 4741cb0ef41Sopenharmony_ci uint32_t drop_values) { 4751cb0ef41Sopenharmony_ci Value* stack_base = 4761cb0ef41Sopenharmony_ci count > 0 ? decoder->stack_value(count + drop_values) : nullptr; 4771cb0ef41Sopenharmony_ci ValueVector stack_values(count); 4781cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < count; i++) { 4791cb0ef41Sopenharmony_ci stack_values[i] = stack_base[i]; 4801cb0ef41Sopenharmony_ci } 4811cb0ef41Sopenharmony_ci return stack_values; 4821cb0ef41Sopenharmony_ci } 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_ci void DoReturn(FullDecoder* decoder, uint32_t drop_values) { 4851cb0ef41Sopenharmony_ci uint32_t ret_count = static_cast<uint32_t>(decoder->sig_->return_count()); 4861cb0ef41Sopenharmony_ci NodeVector values(ret_count); 4871cb0ef41Sopenharmony_ci SsaEnv* internal_env = ssa_env_; 4881cb0ef41Sopenharmony_ci if (emit_loop_exits()) { 4891cb0ef41Sopenharmony_ci SsaEnv* exit_env = Split(decoder->zone(), ssa_env_); 4901cb0ef41Sopenharmony_ci SetEnv(exit_env); 4911cb0ef41Sopenharmony_ci auto stack_values = CopyStackValues(decoder, ret_count, drop_values); 4921cb0ef41Sopenharmony_ci BuildNestedLoopExits(decoder, decoder->control_depth() - 1, false, 4931cb0ef41Sopenharmony_ci stack_values); 4941cb0ef41Sopenharmony_ci GetNodes(values.begin(), base::VectorOf(stack_values)); 4951cb0ef41Sopenharmony_ci } else { 4961cb0ef41Sopenharmony_ci Value* stack_base = ret_count == 0 4971cb0ef41Sopenharmony_ci ? nullptr 4981cb0ef41Sopenharmony_ci : decoder->stack_value(ret_count + drop_values); 4991cb0ef41Sopenharmony_ci GetNodes(values.begin(), stack_base, ret_count); 5001cb0ef41Sopenharmony_ci } 5011cb0ef41Sopenharmony_ci if (FLAG_trace_wasm && inlined_status_ == kRegularFunction) { 5021cb0ef41Sopenharmony_ci builder_->TraceFunctionExit(base::VectorOf(values), decoder->position()); 5031cb0ef41Sopenharmony_ci } 5041cb0ef41Sopenharmony_ci builder_->Return(base::VectorOf(values)); 5051cb0ef41Sopenharmony_ci SetEnv(internal_env); 5061cb0ef41Sopenharmony_ci } 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ci void BrOrRet(FullDecoder* decoder, uint32_t depth, uint32_t drop_values) { 5091cb0ef41Sopenharmony_ci if (depth == decoder->control_depth() - 1) { 5101cb0ef41Sopenharmony_ci DoReturn(decoder, drop_values); 5111cb0ef41Sopenharmony_ci } else { 5121cb0ef41Sopenharmony_ci Control* target = decoder->control_at(depth); 5131cb0ef41Sopenharmony_ci if (emit_loop_exits()) { 5141cb0ef41Sopenharmony_ci SsaEnv* internal_env = ssa_env_; 5151cb0ef41Sopenharmony_ci SsaEnv* exit_env = Split(decoder->zone(), ssa_env_); 5161cb0ef41Sopenharmony_ci SetEnv(exit_env); 5171cb0ef41Sopenharmony_ci uint32_t value_count = target->br_merge()->arity; 5181cb0ef41Sopenharmony_ci auto stack_values = CopyStackValues(decoder, value_count, drop_values); 5191cb0ef41Sopenharmony_ci BuildNestedLoopExits(decoder, depth, true, stack_values); 5201cb0ef41Sopenharmony_ci MergeValuesInto(decoder, target, target->br_merge(), 5211cb0ef41Sopenharmony_ci stack_values.data()); 5221cb0ef41Sopenharmony_ci SetEnv(internal_env); 5231cb0ef41Sopenharmony_ci } else { 5241cb0ef41Sopenharmony_ci MergeValuesInto(decoder, target, target->br_merge(), drop_values); 5251cb0ef41Sopenharmony_ci } 5261cb0ef41Sopenharmony_ci } 5271cb0ef41Sopenharmony_ci } 5281cb0ef41Sopenharmony_ci 5291cb0ef41Sopenharmony_ci void BrIf(FullDecoder* decoder, const Value& cond, uint32_t depth) { 5301cb0ef41Sopenharmony_ci SsaEnv* fenv = ssa_env_; 5311cb0ef41Sopenharmony_ci SsaEnv* tenv = Split(decoder->zone(), fenv); 5321cb0ef41Sopenharmony_ci fenv->SetNotMerged(); 5331cb0ef41Sopenharmony_ci WasmBranchHint hint = WasmBranchHint::kNoHint; 5341cb0ef41Sopenharmony_ci if (branch_hints_) { 5351cb0ef41Sopenharmony_ci hint = branch_hints_->GetHintFor(decoder->pc_relative_offset()); 5361cb0ef41Sopenharmony_ci } 5371cb0ef41Sopenharmony_ci switch (hint) { 5381cb0ef41Sopenharmony_ci case WasmBranchHint::kNoHint: 5391cb0ef41Sopenharmony_ci builder_->BranchNoHint(cond.node, &tenv->control, &fenv->control); 5401cb0ef41Sopenharmony_ci break; 5411cb0ef41Sopenharmony_ci case WasmBranchHint::kUnlikely: 5421cb0ef41Sopenharmony_ci builder_->BranchExpectFalse(cond.node, &tenv->control, &fenv->control); 5431cb0ef41Sopenharmony_ci break; 5441cb0ef41Sopenharmony_ci case WasmBranchHint::kLikely: 5451cb0ef41Sopenharmony_ci builder_->BranchExpectTrue(cond.node, &tenv->control, &fenv->control); 5461cb0ef41Sopenharmony_ci break; 5471cb0ef41Sopenharmony_ci } 5481cb0ef41Sopenharmony_ci builder_->SetControl(fenv->control); 5491cb0ef41Sopenharmony_ci SetEnv(tenv); 5501cb0ef41Sopenharmony_ci BrOrRet(decoder, depth, 1); 5511cb0ef41Sopenharmony_ci SetEnv(fenv); 5521cb0ef41Sopenharmony_ci } 5531cb0ef41Sopenharmony_ci 5541cb0ef41Sopenharmony_ci void BrTable(FullDecoder* decoder, const BranchTableImmediate<validate>& imm, 5551cb0ef41Sopenharmony_ci const Value& key) { 5561cb0ef41Sopenharmony_ci if (imm.table_count == 0) { 5571cb0ef41Sopenharmony_ci // Only a default target. Do the equivalent of br. 5581cb0ef41Sopenharmony_ci uint32_t target = BranchTableIterator<validate>(decoder, imm).next(); 5591cb0ef41Sopenharmony_ci BrOrRet(decoder, target, 1); 5601cb0ef41Sopenharmony_ci return; 5611cb0ef41Sopenharmony_ci } 5621cb0ef41Sopenharmony_ci 5631cb0ef41Sopenharmony_ci SsaEnv* branch_env = ssa_env_; 5641cb0ef41Sopenharmony_ci // Build branches to the various blocks based on the table. 5651cb0ef41Sopenharmony_ci TFNode* sw = builder_->Switch(imm.table_count + 1, key.node); 5661cb0ef41Sopenharmony_ci 5671cb0ef41Sopenharmony_ci SsaEnv* copy = Steal(decoder->zone(), branch_env); 5681cb0ef41Sopenharmony_ci SetEnv(copy); 5691cb0ef41Sopenharmony_ci BranchTableIterator<validate> iterator(decoder, imm); 5701cb0ef41Sopenharmony_ci while (iterator.has_next()) { 5711cb0ef41Sopenharmony_ci uint32_t i = iterator.cur_index(); 5721cb0ef41Sopenharmony_ci uint32_t target = iterator.next(); 5731cb0ef41Sopenharmony_ci SetEnv(Split(decoder->zone(), copy)); 5741cb0ef41Sopenharmony_ci builder_->SetControl(i == imm.table_count ? builder_->IfDefault(sw) 5751cb0ef41Sopenharmony_ci : builder_->IfValue(i, sw)); 5761cb0ef41Sopenharmony_ci BrOrRet(decoder, target, 1); 5771cb0ef41Sopenharmony_ci } 5781cb0ef41Sopenharmony_ci DCHECK(decoder->ok()); 5791cb0ef41Sopenharmony_ci SetEnv(branch_env); 5801cb0ef41Sopenharmony_ci } 5811cb0ef41Sopenharmony_ci 5821cb0ef41Sopenharmony_ci void Else(FullDecoder* decoder, Control* if_block) { 5831cb0ef41Sopenharmony_ci if (if_block->reachable()) { 5841cb0ef41Sopenharmony_ci // Merge the if branch into the end merge. 5851cb0ef41Sopenharmony_ci MergeValuesInto(decoder, if_block, &if_block->end_merge); 5861cb0ef41Sopenharmony_ci } 5871cb0ef41Sopenharmony_ci SetEnv(if_block->false_env); 5881cb0ef41Sopenharmony_ci } 5891cb0ef41Sopenharmony_ci 5901cb0ef41Sopenharmony_ci void LoadMem(FullDecoder* decoder, LoadType type, 5911cb0ef41Sopenharmony_ci const MemoryAccessImmediate<validate>& imm, const Value& index, 5921cb0ef41Sopenharmony_ci Value* result) { 5931cb0ef41Sopenharmony_ci result->node = 5941cb0ef41Sopenharmony_ci builder_->LoadMem(type.value_type(), type.mem_type(), index.node, 5951cb0ef41Sopenharmony_ci imm.offset, imm.alignment, decoder->position()); 5961cb0ef41Sopenharmony_ci } 5971cb0ef41Sopenharmony_ci 5981cb0ef41Sopenharmony_ci void LoadTransform(FullDecoder* decoder, LoadType type, 5991cb0ef41Sopenharmony_ci LoadTransformationKind transform, 6001cb0ef41Sopenharmony_ci const MemoryAccessImmediate<validate>& imm, 6011cb0ef41Sopenharmony_ci const Value& index, Value* result) { 6021cb0ef41Sopenharmony_ci result->node = builder_->LoadTransform(type.value_type(), type.mem_type(), 6031cb0ef41Sopenharmony_ci transform, index.node, imm.offset, 6041cb0ef41Sopenharmony_ci imm.alignment, decoder->position()); 6051cb0ef41Sopenharmony_ci } 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_ci void LoadLane(FullDecoder* decoder, LoadType type, const Value& value, 6081cb0ef41Sopenharmony_ci const Value& index, const MemoryAccessImmediate<validate>& imm, 6091cb0ef41Sopenharmony_ci const uint8_t laneidx, Value* result) { 6101cb0ef41Sopenharmony_ci result->node = builder_->LoadLane( 6111cb0ef41Sopenharmony_ci type.value_type(), type.mem_type(), value.node, index.node, imm.offset, 6121cb0ef41Sopenharmony_ci imm.alignment, laneidx, decoder->position()); 6131cb0ef41Sopenharmony_ci } 6141cb0ef41Sopenharmony_ci 6151cb0ef41Sopenharmony_ci void StoreMem(FullDecoder* decoder, StoreType type, 6161cb0ef41Sopenharmony_ci const MemoryAccessImmediate<validate>& imm, const Value& index, 6171cb0ef41Sopenharmony_ci const Value& value) { 6181cb0ef41Sopenharmony_ci builder_->StoreMem(type.mem_rep(), index.node, imm.offset, imm.alignment, 6191cb0ef41Sopenharmony_ci value.node, decoder->position(), type.value_type()); 6201cb0ef41Sopenharmony_ci } 6211cb0ef41Sopenharmony_ci 6221cb0ef41Sopenharmony_ci void StoreLane(FullDecoder* decoder, StoreType type, 6231cb0ef41Sopenharmony_ci const MemoryAccessImmediate<validate>& imm, const Value& index, 6241cb0ef41Sopenharmony_ci const Value& value, const uint8_t laneidx) { 6251cb0ef41Sopenharmony_ci builder_->StoreLane(type.mem_rep(), index.node, imm.offset, imm.alignment, 6261cb0ef41Sopenharmony_ci value.node, laneidx, decoder->position(), 6271cb0ef41Sopenharmony_ci type.value_type()); 6281cb0ef41Sopenharmony_ci } 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_ci void CurrentMemoryPages(FullDecoder* decoder, Value* result) { 6311cb0ef41Sopenharmony_ci result->node = builder_->CurrentMemoryPages(); 6321cb0ef41Sopenharmony_ci } 6331cb0ef41Sopenharmony_ci 6341cb0ef41Sopenharmony_ci void MemoryGrow(FullDecoder* decoder, const Value& value, Value* result) { 6351cb0ef41Sopenharmony_ci result->node = builder_->MemoryGrow(value.node); 6361cb0ef41Sopenharmony_ci // Always reload the instance cache after growing memory. 6371cb0ef41Sopenharmony_ci LoadContextIntoSsa(ssa_env_); 6381cb0ef41Sopenharmony_ci } 6391cb0ef41Sopenharmony_ci 6401cb0ef41Sopenharmony_ci void CallDirect(FullDecoder* decoder, 6411cb0ef41Sopenharmony_ci const CallFunctionImmediate<validate>& imm, 6421cb0ef41Sopenharmony_ci const Value args[], Value returns[]) { 6431cb0ef41Sopenharmony_ci if (FLAG_wasm_speculative_inlining && type_feedback_.size() > 0) { 6441cb0ef41Sopenharmony_ci DCHECK_LT(feedback_instruction_index_, type_feedback_.size()); 6451cb0ef41Sopenharmony_ci feedback_instruction_index_++; 6461cb0ef41Sopenharmony_ci } 6471cb0ef41Sopenharmony_ci DoCall(decoder, CallInfo::CallDirect(imm.index), imm.sig, args, returns); 6481cb0ef41Sopenharmony_ci } 6491cb0ef41Sopenharmony_ci 6501cb0ef41Sopenharmony_ci void ReturnCall(FullDecoder* decoder, 6511cb0ef41Sopenharmony_ci const CallFunctionImmediate<validate>& imm, 6521cb0ef41Sopenharmony_ci const Value args[]) { 6531cb0ef41Sopenharmony_ci if (FLAG_wasm_speculative_inlining && type_feedback_.size() > 0) { 6541cb0ef41Sopenharmony_ci DCHECK_LT(feedback_instruction_index_, type_feedback_.size()); 6551cb0ef41Sopenharmony_ci feedback_instruction_index_++; 6561cb0ef41Sopenharmony_ci } 6571cb0ef41Sopenharmony_ci DoReturnCall(decoder, CallInfo::CallDirect(imm.index), imm.sig, args); 6581cb0ef41Sopenharmony_ci } 6591cb0ef41Sopenharmony_ci 6601cb0ef41Sopenharmony_ci void CallIndirect(FullDecoder* decoder, const Value& index, 6611cb0ef41Sopenharmony_ci const CallIndirectImmediate<validate>& imm, 6621cb0ef41Sopenharmony_ci const Value args[], Value returns[]) { 6631cb0ef41Sopenharmony_ci DoCall( 6641cb0ef41Sopenharmony_ci decoder, 6651cb0ef41Sopenharmony_ci CallInfo::CallIndirect(index, imm.table_imm.index, imm.sig_imm.index), 6661cb0ef41Sopenharmony_ci imm.sig, args, returns); 6671cb0ef41Sopenharmony_ci } 6681cb0ef41Sopenharmony_ci 6691cb0ef41Sopenharmony_ci void ReturnCallIndirect(FullDecoder* decoder, const Value& index, 6701cb0ef41Sopenharmony_ci const CallIndirectImmediate<validate>& imm, 6711cb0ef41Sopenharmony_ci const Value args[]) { 6721cb0ef41Sopenharmony_ci DoReturnCall( 6731cb0ef41Sopenharmony_ci decoder, 6741cb0ef41Sopenharmony_ci CallInfo::CallIndirect(index, imm.table_imm.index, imm.sig_imm.index), 6751cb0ef41Sopenharmony_ci imm.sig, args); 6761cb0ef41Sopenharmony_ci } 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_ci void CallRef(FullDecoder* decoder, const Value& func_ref, 6791cb0ef41Sopenharmony_ci const FunctionSig* sig, uint32_t sig_index, const Value args[], 6801cb0ef41Sopenharmony_ci Value returns[]) { 6811cb0ef41Sopenharmony_ci int maybe_feedback = -1; 6821cb0ef41Sopenharmony_ci if (FLAG_wasm_speculative_inlining && type_feedback_.size() > 0) { 6831cb0ef41Sopenharmony_ci DCHECK_LT(feedback_instruction_index_, type_feedback_.size()); 6841cb0ef41Sopenharmony_ci maybe_feedback = 6851cb0ef41Sopenharmony_ci type_feedback_[feedback_instruction_index_].function_index; 6861cb0ef41Sopenharmony_ci feedback_instruction_index_++; 6871cb0ef41Sopenharmony_ci } 6881cb0ef41Sopenharmony_ci if (maybe_feedback == -1) { 6891cb0ef41Sopenharmony_ci DoCall(decoder, CallInfo::CallRef(func_ref, NullCheckFor(func_ref.type)), 6901cb0ef41Sopenharmony_ci sig, args, returns); 6911cb0ef41Sopenharmony_ci return; 6921cb0ef41Sopenharmony_ci } 6931cb0ef41Sopenharmony_ci 6941cb0ef41Sopenharmony_ci // Check for equality against a function at a specific index, and if 6951cb0ef41Sopenharmony_ci // successful, just emit a direct call. 6961cb0ef41Sopenharmony_ci DCHECK_GE(maybe_feedback, 0); 6971cb0ef41Sopenharmony_ci const uint32_t expected_function_index = maybe_feedback; 6981cb0ef41Sopenharmony_ci 6991cb0ef41Sopenharmony_ci if (FLAG_trace_wasm_speculative_inlining) { 7001cb0ef41Sopenharmony_ci PrintF("[Function #%d call #%d: graph support for inlining target #%d]\n", 7011cb0ef41Sopenharmony_ci func_index_, feedback_instruction_index_ - 1, 7021cb0ef41Sopenharmony_ci expected_function_index); 7031cb0ef41Sopenharmony_ci } 7041cb0ef41Sopenharmony_ci 7051cb0ef41Sopenharmony_ci TFNode* success_control; 7061cb0ef41Sopenharmony_ci TFNode* failure_control; 7071cb0ef41Sopenharmony_ci builder_->CompareToInternalFunctionAtIndex( 7081cb0ef41Sopenharmony_ci func_ref.node, expected_function_index, &success_control, 7091cb0ef41Sopenharmony_ci &failure_control); 7101cb0ef41Sopenharmony_ci TFNode* initial_effect = effect(); 7111cb0ef41Sopenharmony_ci 7121cb0ef41Sopenharmony_ci builder_->SetControl(success_control); 7131cb0ef41Sopenharmony_ci ssa_env_->control = success_control; 7141cb0ef41Sopenharmony_ci Value* returns_direct = 7151cb0ef41Sopenharmony_ci decoder->zone()->NewArray<Value>(sig->return_count()); 7161cb0ef41Sopenharmony_ci DoCall(decoder, CallInfo::CallDirect(expected_function_index), 7171cb0ef41Sopenharmony_ci decoder->module_->signature(sig_index), args, returns_direct); 7181cb0ef41Sopenharmony_ci TFNode* control_direct = control(); 7191cb0ef41Sopenharmony_ci TFNode* effect_direct = effect(); 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci builder_->SetEffectControl(initial_effect, failure_control); 7221cb0ef41Sopenharmony_ci ssa_env_->effect = initial_effect; 7231cb0ef41Sopenharmony_ci ssa_env_->control = failure_control; 7241cb0ef41Sopenharmony_ci Value* returns_ref = decoder->zone()->NewArray<Value>(sig->return_count()); 7251cb0ef41Sopenharmony_ci DoCall(decoder, CallInfo::CallRef(func_ref, NullCheckFor(func_ref.type)), 7261cb0ef41Sopenharmony_ci sig, args, returns_ref); 7271cb0ef41Sopenharmony_ci 7281cb0ef41Sopenharmony_ci TFNode* control_ref = control(); 7291cb0ef41Sopenharmony_ci TFNode* effect_ref = effect(); 7301cb0ef41Sopenharmony_ci 7311cb0ef41Sopenharmony_ci TFNode* control_args[] = {control_direct, control_ref}; 7321cb0ef41Sopenharmony_ci TFNode* control = builder_->Merge(2, control_args); 7331cb0ef41Sopenharmony_ci 7341cb0ef41Sopenharmony_ci TFNode* effect_args[] = {effect_direct, effect_ref, control}; 7351cb0ef41Sopenharmony_ci TFNode* effect = builder_->EffectPhi(2, effect_args); 7361cb0ef41Sopenharmony_ci 7371cb0ef41Sopenharmony_ci ssa_env_->control = control; 7381cb0ef41Sopenharmony_ci ssa_env_->effect = effect; 7391cb0ef41Sopenharmony_ci builder_->SetEffectControl(effect, control); 7401cb0ef41Sopenharmony_ci 7411cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < sig->return_count(); i++) { 7421cb0ef41Sopenharmony_ci TFNode* phi_args[] = {returns_direct[i].node, returns_ref[i].node, 7431cb0ef41Sopenharmony_ci control}; 7441cb0ef41Sopenharmony_ci returns[i].node = builder_->Phi(sig->GetReturn(i), 2, phi_args); 7451cb0ef41Sopenharmony_ci } 7461cb0ef41Sopenharmony_ci } 7471cb0ef41Sopenharmony_ci 7481cb0ef41Sopenharmony_ci void ReturnCallRef(FullDecoder* decoder, const Value& func_ref, 7491cb0ef41Sopenharmony_ci const FunctionSig* sig, uint32_t sig_index, 7501cb0ef41Sopenharmony_ci const Value args[]) { 7511cb0ef41Sopenharmony_ci int maybe_feedback = -1; 7521cb0ef41Sopenharmony_ci if (FLAG_wasm_speculative_inlining && type_feedback_.size() > 0) { 7531cb0ef41Sopenharmony_ci DCHECK_LT(feedback_instruction_index_, type_feedback_.size()); 7541cb0ef41Sopenharmony_ci maybe_feedback = 7551cb0ef41Sopenharmony_ci type_feedback_[feedback_instruction_index_].function_index; 7561cb0ef41Sopenharmony_ci feedback_instruction_index_++; 7571cb0ef41Sopenharmony_ci } 7581cb0ef41Sopenharmony_ci if (maybe_feedback == -1) { 7591cb0ef41Sopenharmony_ci DoReturnCall(decoder, 7601cb0ef41Sopenharmony_ci CallInfo::CallRef(func_ref, NullCheckFor(func_ref.type)), 7611cb0ef41Sopenharmony_ci sig, args); 7621cb0ef41Sopenharmony_ci return; 7631cb0ef41Sopenharmony_ci } 7641cb0ef41Sopenharmony_ci 7651cb0ef41Sopenharmony_ci // Check for equality against a function at a specific index, and if 7661cb0ef41Sopenharmony_ci // successful, just emit a direct call. 7671cb0ef41Sopenharmony_ci DCHECK_GE(maybe_feedback, 0); 7681cb0ef41Sopenharmony_ci const uint32_t expected_function_index = maybe_feedback; 7691cb0ef41Sopenharmony_ci 7701cb0ef41Sopenharmony_ci if (FLAG_trace_wasm_speculative_inlining) { 7711cb0ef41Sopenharmony_ci PrintF("[Function #%d call #%d: graph support for inlining target #%d]\n", 7721cb0ef41Sopenharmony_ci func_index_, feedback_instruction_index_ - 1, 7731cb0ef41Sopenharmony_ci expected_function_index); 7741cb0ef41Sopenharmony_ci } 7751cb0ef41Sopenharmony_ci 7761cb0ef41Sopenharmony_ci TFNode* success_control; 7771cb0ef41Sopenharmony_ci TFNode* failure_control; 7781cb0ef41Sopenharmony_ci builder_->CompareToInternalFunctionAtIndex( 7791cb0ef41Sopenharmony_ci func_ref.node, expected_function_index, &success_control, 7801cb0ef41Sopenharmony_ci &failure_control); 7811cb0ef41Sopenharmony_ci TFNode* initial_effect = effect(); 7821cb0ef41Sopenharmony_ci 7831cb0ef41Sopenharmony_ci builder_->SetControl(success_control); 7841cb0ef41Sopenharmony_ci ssa_env_->control = success_control; 7851cb0ef41Sopenharmony_ci DoReturnCall(decoder, CallInfo::CallDirect(expected_function_index), sig, 7861cb0ef41Sopenharmony_ci args); 7871cb0ef41Sopenharmony_ci 7881cb0ef41Sopenharmony_ci builder_->SetEffectControl(initial_effect, failure_control); 7891cb0ef41Sopenharmony_ci ssa_env_->effect = initial_effect; 7901cb0ef41Sopenharmony_ci ssa_env_->control = failure_control; 7911cb0ef41Sopenharmony_ci DoReturnCall(decoder, 7921cb0ef41Sopenharmony_ci CallInfo::CallRef(func_ref, NullCheckFor(func_ref.type)), sig, 7931cb0ef41Sopenharmony_ci args); 7941cb0ef41Sopenharmony_ci } 7951cb0ef41Sopenharmony_ci 7961cb0ef41Sopenharmony_ci void BrOnNull(FullDecoder* decoder, const Value& ref_object, uint32_t depth, 7971cb0ef41Sopenharmony_ci bool pass_null_along_branch, Value* result_on_fallthrough) { 7981cb0ef41Sopenharmony_ci SsaEnv* false_env = ssa_env_; 7991cb0ef41Sopenharmony_ci SsaEnv* true_env = Split(decoder->zone(), false_env); 8001cb0ef41Sopenharmony_ci false_env->SetNotMerged(); 8011cb0ef41Sopenharmony_ci builder_->BrOnNull(ref_object.node, &true_env->control, 8021cb0ef41Sopenharmony_ci &false_env->control); 8031cb0ef41Sopenharmony_ci builder_->SetControl(false_env->control); 8041cb0ef41Sopenharmony_ci SetEnv(true_env); 8051cb0ef41Sopenharmony_ci BrOrRet(decoder, depth, pass_null_along_branch ? 0 : 1); 8061cb0ef41Sopenharmony_ci SetEnv(false_env); 8071cb0ef41Sopenharmony_ci result_on_fallthrough->node = ref_object.node; 8081cb0ef41Sopenharmony_ci } 8091cb0ef41Sopenharmony_ci 8101cb0ef41Sopenharmony_ci void BrOnNonNull(FullDecoder* decoder, const Value& ref_object, 8111cb0ef41Sopenharmony_ci uint32_t depth) { 8121cb0ef41Sopenharmony_ci SsaEnv* false_env = ssa_env_; 8131cb0ef41Sopenharmony_ci SsaEnv* true_env = Split(decoder->zone(), false_env); 8141cb0ef41Sopenharmony_ci false_env->SetNotMerged(); 8151cb0ef41Sopenharmony_ci builder_->BrOnNull(ref_object.node, &false_env->control, 8161cb0ef41Sopenharmony_ci &true_env->control); 8171cb0ef41Sopenharmony_ci builder_->SetControl(false_env->control); 8181cb0ef41Sopenharmony_ci SetEnv(true_env); 8191cb0ef41Sopenharmony_ci BrOrRet(decoder, depth, 0); 8201cb0ef41Sopenharmony_ci SetEnv(false_env); 8211cb0ef41Sopenharmony_ci } 8221cb0ef41Sopenharmony_ci 8231cb0ef41Sopenharmony_ci void SimdOp(FullDecoder* decoder, WasmOpcode opcode, base::Vector<Value> args, 8241cb0ef41Sopenharmony_ci Value* result) { 8251cb0ef41Sopenharmony_ci NodeVector inputs(args.size()); 8261cb0ef41Sopenharmony_ci GetNodes(inputs.begin(), args); 8271cb0ef41Sopenharmony_ci TFNode* node = builder_->SimdOp(opcode, inputs.begin()); 8281cb0ef41Sopenharmony_ci if (result) result->node = node; 8291cb0ef41Sopenharmony_ci } 8301cb0ef41Sopenharmony_ci 8311cb0ef41Sopenharmony_ci void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode, 8321cb0ef41Sopenharmony_ci const SimdLaneImmediate<validate>& imm, 8331cb0ef41Sopenharmony_ci base::Vector<Value> inputs, Value* result) { 8341cb0ef41Sopenharmony_ci NodeVector nodes(inputs.size()); 8351cb0ef41Sopenharmony_ci GetNodes(nodes.begin(), inputs); 8361cb0ef41Sopenharmony_ci result->node = builder_->SimdLaneOp(opcode, imm.lane, nodes.begin()); 8371cb0ef41Sopenharmony_ci } 8381cb0ef41Sopenharmony_ci 8391cb0ef41Sopenharmony_ci void Simd8x16ShuffleOp(FullDecoder* decoder, 8401cb0ef41Sopenharmony_ci const Simd128Immediate<validate>& imm, 8411cb0ef41Sopenharmony_ci const Value& input0, const Value& input1, 8421cb0ef41Sopenharmony_ci Value* result) { 8431cb0ef41Sopenharmony_ci TFNode* input_nodes[] = {input0.node, input1.node}; 8441cb0ef41Sopenharmony_ci result->node = builder_->Simd8x16ShuffleOp(imm.value, input_nodes); 8451cb0ef41Sopenharmony_ci } 8461cb0ef41Sopenharmony_ci 8471cb0ef41Sopenharmony_ci void Throw(FullDecoder* decoder, const TagIndexImmediate<validate>& imm, 8481cb0ef41Sopenharmony_ci const base::Vector<Value>& value_args) { 8491cb0ef41Sopenharmony_ci int count = value_args.length(); 8501cb0ef41Sopenharmony_ci ZoneVector<TFNode*> args(count, decoder->zone()); 8511cb0ef41Sopenharmony_ci for (int i = 0; i < count; ++i) { 8521cb0ef41Sopenharmony_ci args[i] = value_args[i].node; 8531cb0ef41Sopenharmony_ci } 8541cb0ef41Sopenharmony_ci CheckForException(decoder, 8551cb0ef41Sopenharmony_ci builder_->Throw(imm.index, imm.tag, base::VectorOf(args), 8561cb0ef41Sopenharmony_ci decoder->position())); 8571cb0ef41Sopenharmony_ci builder_->TerminateThrow(effect(), control()); 8581cb0ef41Sopenharmony_ci } 8591cb0ef41Sopenharmony_ci 8601cb0ef41Sopenharmony_ci void Rethrow(FullDecoder* decoder, Control* block) { 8611cb0ef41Sopenharmony_ci DCHECK(block->is_try_catchall() || block->is_try_catch()); 8621cb0ef41Sopenharmony_ci TFNode* exception = block->try_info->exception; 8631cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(exception); 8641cb0ef41Sopenharmony_ci CheckForException(decoder, builder_->Rethrow(exception)); 8651cb0ef41Sopenharmony_ci builder_->TerminateThrow(effect(), control()); 8661cb0ef41Sopenharmony_ci } 8671cb0ef41Sopenharmony_ci 8681cb0ef41Sopenharmony_ci void CatchException(FullDecoder* decoder, 8691cb0ef41Sopenharmony_ci const TagIndexImmediate<validate>& imm, Control* block, 8701cb0ef41Sopenharmony_ci base::Vector<Value> values) { 8711cb0ef41Sopenharmony_ci DCHECK(block->is_try_catch()); 8721cb0ef41Sopenharmony_ci // The catch block is unreachable if no possible throws in the try block 8731cb0ef41Sopenharmony_ci // exist. We only build a landing pad if some node in the try block can 8741cb0ef41Sopenharmony_ci // (possibly) throw. Otherwise the catch environments remain empty. 8751cb0ef41Sopenharmony_ci if (!block->try_info->might_throw()) { 8761cb0ef41Sopenharmony_ci block->reachability = kSpecOnlyReachable; 8771cb0ef41Sopenharmony_ci return; 8781cb0ef41Sopenharmony_ci } 8791cb0ef41Sopenharmony_ci 8801cb0ef41Sopenharmony_ci TFNode* exception = block->try_info->exception; 8811cb0ef41Sopenharmony_ci SetEnv(block->try_info->catch_env); 8821cb0ef41Sopenharmony_ci 8831cb0ef41Sopenharmony_ci TFNode* if_catch = nullptr; 8841cb0ef41Sopenharmony_ci TFNode* if_no_catch = nullptr; 8851cb0ef41Sopenharmony_ci 8861cb0ef41Sopenharmony_ci // Get the exception tag and see if it matches the expected one. 8871cb0ef41Sopenharmony_ci TFNode* caught_tag = builder_->GetExceptionTag(exception); 8881cb0ef41Sopenharmony_ci TFNode* exception_tag = builder_->LoadTagFromTable(imm.index); 8891cb0ef41Sopenharmony_ci TFNode* compare = builder_->ExceptionTagEqual(caught_tag, exception_tag); 8901cb0ef41Sopenharmony_ci builder_->BranchNoHint(compare, &if_catch, &if_no_catch); 8911cb0ef41Sopenharmony_ci 8921cb0ef41Sopenharmony_ci // If the tags don't match we continue with the next tag by setting the 8931cb0ef41Sopenharmony_ci // false environment as the new {TryInfo::catch_env} here. 8941cb0ef41Sopenharmony_ci SsaEnv* if_no_catch_env = Split(decoder->zone(), ssa_env_); 8951cb0ef41Sopenharmony_ci if_no_catch_env->control = if_no_catch; 8961cb0ef41Sopenharmony_ci SsaEnv* if_catch_env = Steal(decoder->zone(), ssa_env_); 8971cb0ef41Sopenharmony_ci if_catch_env->control = if_catch; 8981cb0ef41Sopenharmony_ci block->try_info->catch_env = if_no_catch_env; 8991cb0ef41Sopenharmony_ci 9001cb0ef41Sopenharmony_ci // If the tags match we extract the values from the exception object and 9011cb0ef41Sopenharmony_ci // push them onto the operand stack using the passed {values} vector. 9021cb0ef41Sopenharmony_ci SetEnv(if_catch_env); 9031cb0ef41Sopenharmony_ci NodeVector caught_values(values.size()); 9041cb0ef41Sopenharmony_ci base::Vector<TFNode*> caught_vector = base::VectorOf(caught_values); 9051cb0ef41Sopenharmony_ci builder_->GetExceptionValues(exception, imm.tag, caught_vector); 9061cb0ef41Sopenharmony_ci for (size_t i = 0, e = values.size(); i < e; ++i) { 9071cb0ef41Sopenharmony_ci values[i].node = caught_values[i]; 9081cb0ef41Sopenharmony_ci } 9091cb0ef41Sopenharmony_ci } 9101cb0ef41Sopenharmony_ci 9111cb0ef41Sopenharmony_ci void Delegate(FullDecoder* decoder, uint32_t depth, Control* block) { 9121cb0ef41Sopenharmony_ci DCHECK_EQ(decoder->control_at(0), block); 9131cb0ef41Sopenharmony_ci DCHECK(block->is_incomplete_try()); 9141cb0ef41Sopenharmony_ci 9151cb0ef41Sopenharmony_ci if (block->try_info->might_throw()) { 9161cb0ef41Sopenharmony_ci // Merge the current env into the target handler's env. 9171cb0ef41Sopenharmony_ci SetEnv(block->try_info->catch_env); 9181cb0ef41Sopenharmony_ci if (depth == decoder->control_depth() - 1) { 9191cb0ef41Sopenharmony_ci // We just throw to the caller here, so no need to generate IfSuccess 9201cb0ef41Sopenharmony_ci // and IfFailure nodes. 9211cb0ef41Sopenharmony_ci builder_->Rethrow(block->try_info->exception); 9221cb0ef41Sopenharmony_ci builder_->TerminateThrow(effect(), control()); 9231cb0ef41Sopenharmony_ci return; 9241cb0ef41Sopenharmony_ci } 9251cb0ef41Sopenharmony_ci DCHECK(decoder->control_at(depth)->is_try()); 9261cb0ef41Sopenharmony_ci TryInfo* target_try = decoder->control_at(depth)->try_info; 9271cb0ef41Sopenharmony_ci if (emit_loop_exits()) { 9281cb0ef41Sopenharmony_ci ValueVector stack_values; 9291cb0ef41Sopenharmony_ci BuildNestedLoopExits(decoder, depth, true, stack_values, 9301cb0ef41Sopenharmony_ci &block->try_info->exception); 9311cb0ef41Sopenharmony_ci } 9321cb0ef41Sopenharmony_ci Goto(decoder, target_try->catch_env); 9331cb0ef41Sopenharmony_ci 9341cb0ef41Sopenharmony_ci // Create or merge the exception. 9351cb0ef41Sopenharmony_ci if (target_try->catch_env->state == SsaEnv::kReached) { 9361cb0ef41Sopenharmony_ci target_try->exception = block->try_info->exception; 9371cb0ef41Sopenharmony_ci } else { 9381cb0ef41Sopenharmony_ci DCHECK_EQ(target_try->catch_env->state, SsaEnv::kMerged); 9391cb0ef41Sopenharmony_ci target_try->exception = builder_->CreateOrMergeIntoPhi( 9401cb0ef41Sopenharmony_ci MachineRepresentation::kTagged, target_try->catch_env->control, 9411cb0ef41Sopenharmony_ci target_try->exception, block->try_info->exception); 9421cb0ef41Sopenharmony_ci } 9431cb0ef41Sopenharmony_ci } 9441cb0ef41Sopenharmony_ci } 9451cb0ef41Sopenharmony_ci 9461cb0ef41Sopenharmony_ci void CatchAll(FullDecoder* decoder, Control* block) { 9471cb0ef41Sopenharmony_ci DCHECK(block->is_try_catchall() || block->is_try_catch()); 9481cb0ef41Sopenharmony_ci DCHECK_EQ(decoder->control_at(0), block); 9491cb0ef41Sopenharmony_ci 9501cb0ef41Sopenharmony_ci // The catch block is unreachable if no possible throws in the try block 9511cb0ef41Sopenharmony_ci // exist. We only build a landing pad if some node in the try block can 9521cb0ef41Sopenharmony_ci // (possibly) throw. Otherwise the catch environments remain empty. 9531cb0ef41Sopenharmony_ci if (!block->try_info->might_throw()) { 9541cb0ef41Sopenharmony_ci decoder->SetSucceedingCodeDynamicallyUnreachable(); 9551cb0ef41Sopenharmony_ci return; 9561cb0ef41Sopenharmony_ci } 9571cb0ef41Sopenharmony_ci 9581cb0ef41Sopenharmony_ci SetEnv(block->try_info->catch_env); 9591cb0ef41Sopenharmony_ci } 9601cb0ef41Sopenharmony_ci 9611cb0ef41Sopenharmony_ci void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, 9621cb0ef41Sopenharmony_ci base::Vector<Value> args, 9631cb0ef41Sopenharmony_ci const MemoryAccessImmediate<validate>& imm, Value* result) { 9641cb0ef41Sopenharmony_ci NodeVector inputs(args.size()); 9651cb0ef41Sopenharmony_ci GetNodes(inputs.begin(), args); 9661cb0ef41Sopenharmony_ci TFNode* node = builder_->AtomicOp(opcode, inputs.begin(), imm.alignment, 9671cb0ef41Sopenharmony_ci imm.offset, decoder->position()); 9681cb0ef41Sopenharmony_ci if (result) result->node = node; 9691cb0ef41Sopenharmony_ci } 9701cb0ef41Sopenharmony_ci 9711cb0ef41Sopenharmony_ci void AtomicFence(FullDecoder* decoder) { builder_->AtomicFence(); } 9721cb0ef41Sopenharmony_ci 9731cb0ef41Sopenharmony_ci void MemoryInit(FullDecoder* decoder, 9741cb0ef41Sopenharmony_ci const MemoryInitImmediate<validate>& imm, const Value& dst, 9751cb0ef41Sopenharmony_ci const Value& src, const Value& size) { 9761cb0ef41Sopenharmony_ci builder_->MemoryInit(imm.data_segment.index, dst.node, src.node, size.node, 9771cb0ef41Sopenharmony_ci decoder->position()); 9781cb0ef41Sopenharmony_ci } 9791cb0ef41Sopenharmony_ci 9801cb0ef41Sopenharmony_ci void DataDrop(FullDecoder* decoder, const IndexImmediate<validate>& imm) { 9811cb0ef41Sopenharmony_ci builder_->DataDrop(imm.index, decoder->position()); 9821cb0ef41Sopenharmony_ci } 9831cb0ef41Sopenharmony_ci 9841cb0ef41Sopenharmony_ci void MemoryCopy(FullDecoder* decoder, 9851cb0ef41Sopenharmony_ci const MemoryCopyImmediate<validate>& imm, const Value& dst, 9861cb0ef41Sopenharmony_ci const Value& src, const Value& size) { 9871cb0ef41Sopenharmony_ci builder_->MemoryCopy(dst.node, src.node, size.node, decoder->position()); 9881cb0ef41Sopenharmony_ci } 9891cb0ef41Sopenharmony_ci 9901cb0ef41Sopenharmony_ci void MemoryFill(FullDecoder* decoder, 9911cb0ef41Sopenharmony_ci const MemoryIndexImmediate<validate>& imm, const Value& dst, 9921cb0ef41Sopenharmony_ci const Value& value, const Value& size) { 9931cb0ef41Sopenharmony_ci builder_->MemoryFill(dst.node, value.node, size.node, decoder->position()); 9941cb0ef41Sopenharmony_ci } 9951cb0ef41Sopenharmony_ci 9961cb0ef41Sopenharmony_ci void TableInit(FullDecoder* decoder, const TableInitImmediate<validate>& imm, 9971cb0ef41Sopenharmony_ci base::Vector<Value> args) { 9981cb0ef41Sopenharmony_ci builder_->TableInit(imm.table.index, imm.element_segment.index, 9991cb0ef41Sopenharmony_ci args[0].node, args[1].node, args[2].node, 10001cb0ef41Sopenharmony_ci decoder->position()); 10011cb0ef41Sopenharmony_ci } 10021cb0ef41Sopenharmony_ci 10031cb0ef41Sopenharmony_ci void ElemDrop(FullDecoder* decoder, const IndexImmediate<validate>& imm) { 10041cb0ef41Sopenharmony_ci builder_->ElemDrop(imm.index, decoder->position()); 10051cb0ef41Sopenharmony_ci } 10061cb0ef41Sopenharmony_ci 10071cb0ef41Sopenharmony_ci void TableCopy(FullDecoder* decoder, const TableCopyImmediate<validate>& imm, 10081cb0ef41Sopenharmony_ci base::Vector<Value> args) { 10091cb0ef41Sopenharmony_ci builder_->TableCopy(imm.table_dst.index, imm.table_src.index, args[0].node, 10101cb0ef41Sopenharmony_ci args[1].node, args[2].node, decoder->position()); 10111cb0ef41Sopenharmony_ci } 10121cb0ef41Sopenharmony_ci 10131cb0ef41Sopenharmony_ci void TableGrow(FullDecoder* decoder, const IndexImmediate<validate>& imm, 10141cb0ef41Sopenharmony_ci const Value& value, const Value& delta, Value* result) { 10151cb0ef41Sopenharmony_ci result->node = builder_->TableGrow(imm.index, value.node, delta.node); 10161cb0ef41Sopenharmony_ci } 10171cb0ef41Sopenharmony_ci 10181cb0ef41Sopenharmony_ci void TableSize(FullDecoder* decoder, const IndexImmediate<validate>& imm, 10191cb0ef41Sopenharmony_ci Value* result) { 10201cb0ef41Sopenharmony_ci result->node = builder_->TableSize(imm.index); 10211cb0ef41Sopenharmony_ci } 10221cb0ef41Sopenharmony_ci 10231cb0ef41Sopenharmony_ci void TableFill(FullDecoder* decoder, const IndexImmediate<validate>& imm, 10241cb0ef41Sopenharmony_ci const Value& start, const Value& value, const Value& count) { 10251cb0ef41Sopenharmony_ci builder_->TableFill(imm.index, start.node, value.node, count.node); 10261cb0ef41Sopenharmony_ci } 10271cb0ef41Sopenharmony_ci 10281cb0ef41Sopenharmony_ci void StructNewWithRtt(FullDecoder* decoder, 10291cb0ef41Sopenharmony_ci const StructIndexImmediate<validate>& imm, 10301cb0ef41Sopenharmony_ci const Value& rtt, const Value args[], Value* result) { 10311cb0ef41Sopenharmony_ci uint32_t field_count = imm.struct_type->field_count(); 10321cb0ef41Sopenharmony_ci NodeVector arg_nodes(field_count); 10331cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < field_count; i++) { 10341cb0ef41Sopenharmony_ci arg_nodes[i] = args[i].node; 10351cb0ef41Sopenharmony_ci } 10361cb0ef41Sopenharmony_ci result->node = builder_->StructNewWithRtt( 10371cb0ef41Sopenharmony_ci imm.index, imm.struct_type, rtt.node, base::VectorOf(arg_nodes)); 10381cb0ef41Sopenharmony_ci } 10391cb0ef41Sopenharmony_ci void StructNewDefault(FullDecoder* decoder, 10401cb0ef41Sopenharmony_ci const StructIndexImmediate<validate>& imm, 10411cb0ef41Sopenharmony_ci const Value& rtt, Value* result) { 10421cb0ef41Sopenharmony_ci uint32_t field_count = imm.struct_type->field_count(); 10431cb0ef41Sopenharmony_ci NodeVector arg_nodes(field_count); 10441cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < field_count; i++) { 10451cb0ef41Sopenharmony_ci arg_nodes[i] = DefaultValue(imm.struct_type->field(i)); 10461cb0ef41Sopenharmony_ci } 10471cb0ef41Sopenharmony_ci result->node = builder_->StructNewWithRtt( 10481cb0ef41Sopenharmony_ci imm.index, imm.struct_type, rtt.node, base::VectorOf(arg_nodes)); 10491cb0ef41Sopenharmony_ci } 10501cb0ef41Sopenharmony_ci 10511cb0ef41Sopenharmony_ci void StructGet(FullDecoder* decoder, const Value& struct_object, 10521cb0ef41Sopenharmony_ci const FieldImmediate<validate>& field, bool is_signed, 10531cb0ef41Sopenharmony_ci Value* result) { 10541cb0ef41Sopenharmony_ci result->node = builder_->StructGet( 10551cb0ef41Sopenharmony_ci struct_object.node, field.struct_imm.struct_type, field.field_imm.index, 10561cb0ef41Sopenharmony_ci NullCheckFor(struct_object.type), is_signed, decoder->position()); 10571cb0ef41Sopenharmony_ci } 10581cb0ef41Sopenharmony_ci 10591cb0ef41Sopenharmony_ci void StructSet(FullDecoder* decoder, const Value& struct_object, 10601cb0ef41Sopenharmony_ci const FieldImmediate<validate>& field, 10611cb0ef41Sopenharmony_ci const Value& field_value) { 10621cb0ef41Sopenharmony_ci builder_->StructSet(struct_object.node, field.struct_imm.struct_type, 10631cb0ef41Sopenharmony_ci field.field_imm.index, field_value.node, 10641cb0ef41Sopenharmony_ci NullCheckFor(struct_object.type), decoder->position()); 10651cb0ef41Sopenharmony_ci } 10661cb0ef41Sopenharmony_ci 10671cb0ef41Sopenharmony_ci void ArrayNewWithRtt(FullDecoder* decoder, 10681cb0ef41Sopenharmony_ci const ArrayIndexImmediate<validate>& imm, 10691cb0ef41Sopenharmony_ci const Value& length, const Value& initial_value, 10701cb0ef41Sopenharmony_ci const Value& rtt, Value* result) { 10711cb0ef41Sopenharmony_ci result->node = builder_->ArrayNewWithRtt(imm.index, imm.array_type, 10721cb0ef41Sopenharmony_ci length.node, initial_value.node, 10731cb0ef41Sopenharmony_ci rtt.node, decoder->position()); 10741cb0ef41Sopenharmony_ci // array.new_with_rtt introduces a loop. Therefore, we have to mark the 10751cb0ef41Sopenharmony_ci // immediately nesting loop (if any) as non-innermost. 10761cb0ef41Sopenharmony_ci if (!loop_infos_.empty()) loop_infos_.back().can_be_innermost = false; 10771cb0ef41Sopenharmony_ci } 10781cb0ef41Sopenharmony_ci 10791cb0ef41Sopenharmony_ci void ArrayNewDefault(FullDecoder* decoder, 10801cb0ef41Sopenharmony_ci const ArrayIndexImmediate<validate>& imm, 10811cb0ef41Sopenharmony_ci const Value& length, const Value& rtt, Value* result) { 10821cb0ef41Sopenharmony_ci // This will cause the default value to be chosen automatically based 10831cb0ef41Sopenharmony_ci // on the element type. 10841cb0ef41Sopenharmony_ci TFNode* initial_value = nullptr; 10851cb0ef41Sopenharmony_ci result->node = 10861cb0ef41Sopenharmony_ci builder_->ArrayNewWithRtt(imm.index, imm.array_type, length.node, 10871cb0ef41Sopenharmony_ci initial_value, rtt.node, decoder->position()); 10881cb0ef41Sopenharmony_ci } 10891cb0ef41Sopenharmony_ci 10901cb0ef41Sopenharmony_ci void ArrayGet(FullDecoder* decoder, const Value& array_obj, 10911cb0ef41Sopenharmony_ci const ArrayIndexImmediate<validate>& imm, const Value& index, 10921cb0ef41Sopenharmony_ci bool is_signed, Value* result) { 10931cb0ef41Sopenharmony_ci result->node = builder_->ArrayGet(array_obj.node, imm.array_type, 10941cb0ef41Sopenharmony_ci index.node, NullCheckFor(array_obj.type), 10951cb0ef41Sopenharmony_ci is_signed, decoder->position()); 10961cb0ef41Sopenharmony_ci } 10971cb0ef41Sopenharmony_ci 10981cb0ef41Sopenharmony_ci void ArraySet(FullDecoder* decoder, const Value& array_obj, 10991cb0ef41Sopenharmony_ci const ArrayIndexImmediate<validate>& imm, const Value& index, 11001cb0ef41Sopenharmony_ci const Value& value) { 11011cb0ef41Sopenharmony_ci builder_->ArraySet(array_obj.node, imm.array_type, index.node, value.node, 11021cb0ef41Sopenharmony_ci NullCheckFor(array_obj.type), decoder->position()); 11031cb0ef41Sopenharmony_ci } 11041cb0ef41Sopenharmony_ci 11051cb0ef41Sopenharmony_ci void ArrayLen(FullDecoder* decoder, const Value& array_obj, Value* result) { 11061cb0ef41Sopenharmony_ci result->node = builder_->ArrayLen( 11071cb0ef41Sopenharmony_ci array_obj.node, NullCheckFor(array_obj.type), decoder->position()); 11081cb0ef41Sopenharmony_ci } 11091cb0ef41Sopenharmony_ci 11101cb0ef41Sopenharmony_ci void ArrayCopy(FullDecoder* decoder, const Value& dst, const Value& dst_index, 11111cb0ef41Sopenharmony_ci const Value& src, const Value& src_index, 11121cb0ef41Sopenharmony_ci const Value& length) { 11131cb0ef41Sopenharmony_ci builder_->ArrayCopy(dst.node, dst_index.node, NullCheckFor(dst.type), 11141cb0ef41Sopenharmony_ci src.node, src_index.node, NullCheckFor(src.type), 11151cb0ef41Sopenharmony_ci length.node, decoder->position()); 11161cb0ef41Sopenharmony_ci } 11171cb0ef41Sopenharmony_ci 11181cb0ef41Sopenharmony_ci void ArrayInit(FullDecoder* decoder, const ArrayIndexImmediate<validate>& imm, 11191cb0ef41Sopenharmony_ci const base::Vector<Value>& elements, const Value& rtt, 11201cb0ef41Sopenharmony_ci Value* result) { 11211cb0ef41Sopenharmony_ci NodeVector element_nodes(elements.size()); 11221cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < elements.size(); i++) { 11231cb0ef41Sopenharmony_ci element_nodes[i] = elements[i].node; 11241cb0ef41Sopenharmony_ci } 11251cb0ef41Sopenharmony_ci result->node = 11261cb0ef41Sopenharmony_ci builder_->ArrayInit(imm.array_type, rtt.node, VectorOf(element_nodes)); 11271cb0ef41Sopenharmony_ci } 11281cb0ef41Sopenharmony_ci 11291cb0ef41Sopenharmony_ci void ArrayInitFromData(FullDecoder* decoder, 11301cb0ef41Sopenharmony_ci const ArrayIndexImmediate<validate>& array_imm, 11311cb0ef41Sopenharmony_ci const IndexImmediate<validate>& data_segment, 11321cb0ef41Sopenharmony_ci const Value& offset, const Value& length, 11331cb0ef41Sopenharmony_ci const Value& rtt, Value* result) { 11341cb0ef41Sopenharmony_ci result->node = builder_->ArrayInitFromData( 11351cb0ef41Sopenharmony_ci array_imm.array_type, data_segment.index, offset.node, length.node, 11361cb0ef41Sopenharmony_ci rtt.node, decoder->position()); 11371cb0ef41Sopenharmony_ci } 11381cb0ef41Sopenharmony_ci 11391cb0ef41Sopenharmony_ci void I31New(FullDecoder* decoder, const Value& input, Value* result) { 11401cb0ef41Sopenharmony_ci result->node = builder_->I31New(input.node); 11411cb0ef41Sopenharmony_ci } 11421cb0ef41Sopenharmony_ci 11431cb0ef41Sopenharmony_ci void I31GetS(FullDecoder* decoder, const Value& input, Value* result) { 11441cb0ef41Sopenharmony_ci result->node = builder_->I31GetS(input.node); 11451cb0ef41Sopenharmony_ci } 11461cb0ef41Sopenharmony_ci 11471cb0ef41Sopenharmony_ci void I31GetU(FullDecoder* decoder, const Value& input, Value* result) { 11481cb0ef41Sopenharmony_ci result->node = builder_->I31GetU(input.node); 11491cb0ef41Sopenharmony_ci } 11501cb0ef41Sopenharmony_ci 11511cb0ef41Sopenharmony_ci void RttCanon(FullDecoder* decoder, uint32_t type_index, Value* result) { 11521cb0ef41Sopenharmony_ci result->node = builder_->RttCanon(type_index); 11531cb0ef41Sopenharmony_ci } 11541cb0ef41Sopenharmony_ci 11551cb0ef41Sopenharmony_ci using StaticKnowledge = compiler::WasmGraphBuilder::ObjectReferenceKnowledge; 11561cb0ef41Sopenharmony_ci 11571cb0ef41Sopenharmony_ci StaticKnowledge ComputeStaticKnowledge(ValueType object_type, 11581cb0ef41Sopenharmony_ci ValueType rtt_type, 11591cb0ef41Sopenharmony_ci const WasmModule* module) { 11601cb0ef41Sopenharmony_ci StaticKnowledge result; 11611cb0ef41Sopenharmony_ci result.object_can_be_null = object_type.is_nullable(); 11621cb0ef41Sopenharmony_ci DCHECK(object_type.is_object_reference()); // Checked by validation. 11631cb0ef41Sopenharmony_ci // In the bottom case, the result is irrelevant. 11641cb0ef41Sopenharmony_ci result.rtt_depth = rtt_type.is_bottom() 11651cb0ef41Sopenharmony_ci ? 0 /* unused */ 11661cb0ef41Sopenharmony_ci : static_cast<uint8_t>(GetSubtypingDepth( 11671cb0ef41Sopenharmony_ci module, rtt_type.ref_index())); 11681cb0ef41Sopenharmony_ci return result; 11691cb0ef41Sopenharmony_ci } 11701cb0ef41Sopenharmony_ci 11711cb0ef41Sopenharmony_ci void RefTest(FullDecoder* decoder, const Value& object, const Value& rtt, 11721cb0ef41Sopenharmony_ci Value* result) { 11731cb0ef41Sopenharmony_ci StaticKnowledge config = 11741cb0ef41Sopenharmony_ci ComputeStaticKnowledge(object.type, rtt.type, decoder->module_); 11751cb0ef41Sopenharmony_ci result->node = builder_->RefTest(object.node, rtt.node, config); 11761cb0ef41Sopenharmony_ci } 11771cb0ef41Sopenharmony_ci 11781cb0ef41Sopenharmony_ci void RefCast(FullDecoder* decoder, const Value& object, const Value& rtt, 11791cb0ef41Sopenharmony_ci Value* result) { 11801cb0ef41Sopenharmony_ci StaticKnowledge config = 11811cb0ef41Sopenharmony_ci ComputeStaticKnowledge(object.type, rtt.type, decoder->module_); 11821cb0ef41Sopenharmony_ci result->node = 11831cb0ef41Sopenharmony_ci builder_->RefCast(object.node, rtt.node, config, decoder->position()); 11841cb0ef41Sopenharmony_ci } 11851cb0ef41Sopenharmony_ci 11861cb0ef41Sopenharmony_ci template <void (compiler::WasmGraphBuilder::*branch_function)( 11871cb0ef41Sopenharmony_ci TFNode*, TFNode*, StaticKnowledge, TFNode**, TFNode**, TFNode**, 11881cb0ef41Sopenharmony_ci TFNode**)> 11891cb0ef41Sopenharmony_ci void BrOnCastAbs(FullDecoder* decoder, const Value& object, const Value& rtt, 11901cb0ef41Sopenharmony_ci Value* forwarding_value, uint32_t br_depth, 11911cb0ef41Sopenharmony_ci bool branch_on_match) { 11921cb0ef41Sopenharmony_ci StaticKnowledge config = 11931cb0ef41Sopenharmony_ci ComputeStaticKnowledge(object.type, rtt.type, decoder->module_); 11941cb0ef41Sopenharmony_ci SsaEnv* branch_env = Split(decoder->zone(), ssa_env_); 11951cb0ef41Sopenharmony_ci SsaEnv* no_branch_env = Steal(decoder->zone(), ssa_env_); 11961cb0ef41Sopenharmony_ci no_branch_env->SetNotMerged(); 11971cb0ef41Sopenharmony_ci SsaEnv* match_env = branch_on_match ? branch_env : no_branch_env; 11981cb0ef41Sopenharmony_ci SsaEnv* no_match_env = branch_on_match ? no_branch_env : branch_env; 11991cb0ef41Sopenharmony_ci (builder_->*branch_function)(object.node, rtt.node, config, 12001cb0ef41Sopenharmony_ci &match_env->control, &match_env->effect, 12011cb0ef41Sopenharmony_ci &no_match_env->control, &no_match_env->effect); 12021cb0ef41Sopenharmony_ci builder_->SetControl(no_branch_env->control); 12031cb0ef41Sopenharmony_ci SetEnv(branch_env); 12041cb0ef41Sopenharmony_ci forwarding_value->node = object.node; 12051cb0ef41Sopenharmony_ci // Currently, br_on_* instructions modify the value stack before calling 12061cb0ef41Sopenharmony_ci // the interface function, so we don't need to drop any values here. 12071cb0ef41Sopenharmony_ci BrOrRet(decoder, br_depth, 0); 12081cb0ef41Sopenharmony_ci SetEnv(no_branch_env); 12091cb0ef41Sopenharmony_ci } 12101cb0ef41Sopenharmony_ci 12111cb0ef41Sopenharmony_ci void BrOnCast(FullDecoder* decoder, const Value& object, const Value& rtt, 12121cb0ef41Sopenharmony_ci Value* value_on_branch, uint32_t br_depth) { 12131cb0ef41Sopenharmony_ci BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnCast>( 12141cb0ef41Sopenharmony_ci decoder, object, rtt, value_on_branch, br_depth, true); 12151cb0ef41Sopenharmony_ci } 12161cb0ef41Sopenharmony_ci 12171cb0ef41Sopenharmony_ci void BrOnCastFail(FullDecoder* decoder, const Value& object, const Value& rtt, 12181cb0ef41Sopenharmony_ci Value* value_on_fallthrough, uint32_t br_depth) { 12191cb0ef41Sopenharmony_ci BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnCast>( 12201cb0ef41Sopenharmony_ci decoder, object, rtt, value_on_fallthrough, br_depth, false); 12211cb0ef41Sopenharmony_ci } 12221cb0ef41Sopenharmony_ci 12231cb0ef41Sopenharmony_ci void RefIsData(FullDecoder* decoder, const Value& object, Value* result) { 12241cb0ef41Sopenharmony_ci result->node = builder_->RefIsData(object.node, object.type.is_nullable()); 12251cb0ef41Sopenharmony_ci } 12261cb0ef41Sopenharmony_ci 12271cb0ef41Sopenharmony_ci void RefAsData(FullDecoder* decoder, const Value& object, Value* result) { 12281cb0ef41Sopenharmony_ci result->node = builder_->RefAsData(object.node, object.type.is_nullable(), 12291cb0ef41Sopenharmony_ci decoder->position()); 12301cb0ef41Sopenharmony_ci } 12311cb0ef41Sopenharmony_ci 12321cb0ef41Sopenharmony_ci void BrOnData(FullDecoder* decoder, const Value& object, 12331cb0ef41Sopenharmony_ci Value* value_on_branch, uint32_t br_depth) { 12341cb0ef41Sopenharmony_ci BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnData>( 12351cb0ef41Sopenharmony_ci decoder, object, Value{nullptr, kWasmBottom}, value_on_branch, br_depth, 12361cb0ef41Sopenharmony_ci true); 12371cb0ef41Sopenharmony_ci } 12381cb0ef41Sopenharmony_ci 12391cb0ef41Sopenharmony_ci void BrOnNonData(FullDecoder* decoder, const Value& object, 12401cb0ef41Sopenharmony_ci Value* value_on_fallthrough, uint32_t br_depth) { 12411cb0ef41Sopenharmony_ci BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnData>( 12421cb0ef41Sopenharmony_ci decoder, object, Value{nullptr, kWasmBottom}, value_on_fallthrough, 12431cb0ef41Sopenharmony_ci br_depth, false); 12441cb0ef41Sopenharmony_ci } 12451cb0ef41Sopenharmony_ci 12461cb0ef41Sopenharmony_ci void RefIsFunc(FullDecoder* decoder, const Value& object, Value* result) { 12471cb0ef41Sopenharmony_ci result->node = builder_->RefIsFunc(object.node, object.type.is_nullable()); 12481cb0ef41Sopenharmony_ci } 12491cb0ef41Sopenharmony_ci 12501cb0ef41Sopenharmony_ci void RefAsFunc(FullDecoder* decoder, const Value& object, Value* result) { 12511cb0ef41Sopenharmony_ci result->node = builder_->RefAsFunc(object.node, object.type.is_nullable(), 12521cb0ef41Sopenharmony_ci decoder->position()); 12531cb0ef41Sopenharmony_ci } 12541cb0ef41Sopenharmony_ci 12551cb0ef41Sopenharmony_ci void BrOnFunc(FullDecoder* decoder, const Value& object, 12561cb0ef41Sopenharmony_ci Value* value_on_branch, uint32_t br_depth) { 12571cb0ef41Sopenharmony_ci BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnFunc>( 12581cb0ef41Sopenharmony_ci decoder, object, Value{nullptr, kWasmBottom}, value_on_branch, br_depth, 12591cb0ef41Sopenharmony_ci true); 12601cb0ef41Sopenharmony_ci } 12611cb0ef41Sopenharmony_ci 12621cb0ef41Sopenharmony_ci void BrOnNonFunc(FullDecoder* decoder, const Value& object, 12631cb0ef41Sopenharmony_ci Value* value_on_fallthrough, uint32_t br_depth) { 12641cb0ef41Sopenharmony_ci BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnFunc>( 12651cb0ef41Sopenharmony_ci decoder, object, Value{nullptr, kWasmBottom}, value_on_fallthrough, 12661cb0ef41Sopenharmony_ci br_depth, false); 12671cb0ef41Sopenharmony_ci } 12681cb0ef41Sopenharmony_ci 12691cb0ef41Sopenharmony_ci void RefIsArray(FullDecoder* decoder, const Value& object, Value* result) { 12701cb0ef41Sopenharmony_ci result->node = builder_->RefIsArray(object.node, object.type.is_nullable()); 12711cb0ef41Sopenharmony_ci } 12721cb0ef41Sopenharmony_ci 12731cb0ef41Sopenharmony_ci void RefAsArray(FullDecoder* decoder, const Value& object, Value* result) { 12741cb0ef41Sopenharmony_ci result->node = builder_->RefAsArray(object.node, object.type.is_nullable(), 12751cb0ef41Sopenharmony_ci decoder->position()); 12761cb0ef41Sopenharmony_ci } 12771cb0ef41Sopenharmony_ci 12781cb0ef41Sopenharmony_ci void BrOnArray(FullDecoder* decoder, const Value& object, 12791cb0ef41Sopenharmony_ci Value* value_on_branch, uint32_t br_depth) { 12801cb0ef41Sopenharmony_ci BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnArray>( 12811cb0ef41Sopenharmony_ci decoder, object, Value{nullptr, kWasmBottom}, value_on_branch, br_depth, 12821cb0ef41Sopenharmony_ci true); 12831cb0ef41Sopenharmony_ci } 12841cb0ef41Sopenharmony_ci 12851cb0ef41Sopenharmony_ci void BrOnNonArray(FullDecoder* decoder, const Value& object, 12861cb0ef41Sopenharmony_ci Value* value_on_fallthrough, uint32_t br_depth) { 12871cb0ef41Sopenharmony_ci BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnArray>( 12881cb0ef41Sopenharmony_ci decoder, object, Value{nullptr, kWasmBottom}, value_on_fallthrough, 12891cb0ef41Sopenharmony_ci br_depth, false); 12901cb0ef41Sopenharmony_ci } 12911cb0ef41Sopenharmony_ci 12921cb0ef41Sopenharmony_ci void RefIsI31(FullDecoder* decoder, const Value& object, Value* result) { 12931cb0ef41Sopenharmony_ci result->node = builder_->RefIsI31(object.node); 12941cb0ef41Sopenharmony_ci } 12951cb0ef41Sopenharmony_ci 12961cb0ef41Sopenharmony_ci void RefAsI31(FullDecoder* decoder, const Value& object, Value* result) { 12971cb0ef41Sopenharmony_ci result->node = builder_->RefAsI31(object.node, decoder->position()); 12981cb0ef41Sopenharmony_ci } 12991cb0ef41Sopenharmony_ci 13001cb0ef41Sopenharmony_ci void BrOnI31(FullDecoder* decoder, const Value& object, 13011cb0ef41Sopenharmony_ci Value* value_on_branch, uint32_t br_depth) { 13021cb0ef41Sopenharmony_ci BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnI31>( 13031cb0ef41Sopenharmony_ci decoder, object, Value{nullptr, kWasmBottom}, value_on_branch, br_depth, 13041cb0ef41Sopenharmony_ci true); 13051cb0ef41Sopenharmony_ci } 13061cb0ef41Sopenharmony_ci 13071cb0ef41Sopenharmony_ci void BrOnNonI31(FullDecoder* decoder, const Value& object, 13081cb0ef41Sopenharmony_ci Value* value_on_fallthrough, uint32_t br_depth) { 13091cb0ef41Sopenharmony_ci BrOnCastAbs<&compiler::WasmGraphBuilder::BrOnI31>( 13101cb0ef41Sopenharmony_ci decoder, object, Value{nullptr, kWasmBottom}, value_on_fallthrough, 13111cb0ef41Sopenharmony_ci br_depth, false); 13121cb0ef41Sopenharmony_ci } 13131cb0ef41Sopenharmony_ci 13141cb0ef41Sopenharmony_ci void Forward(FullDecoder* decoder, const Value& from, Value* to) { 13151cb0ef41Sopenharmony_ci to->node = from.node; 13161cb0ef41Sopenharmony_ci } 13171cb0ef41Sopenharmony_ci 13181cb0ef41Sopenharmony_ci std::vector<compiler::WasmLoopInfo> loop_infos() { return loop_infos_; } 13191cb0ef41Sopenharmony_ci 13201cb0ef41Sopenharmony_ci private: 13211cb0ef41Sopenharmony_ci SsaEnv* ssa_env_ = nullptr; 13221cb0ef41Sopenharmony_ci compiler::WasmGraphBuilder* builder_; 13231cb0ef41Sopenharmony_ci int func_index_; 13241cb0ef41Sopenharmony_ci const BranchHintMap* branch_hints_ = nullptr; 13251cb0ef41Sopenharmony_ci // Tracks loop data for loop unrolling. 13261cb0ef41Sopenharmony_ci std::vector<compiler::WasmLoopInfo> loop_infos_; 13271cb0ef41Sopenharmony_ci InlinedStatus inlined_status_; 13281cb0ef41Sopenharmony_ci // The entries in {type_feedback_} are indexed by the position of feedback- 13291cb0ef41Sopenharmony_ci // consuming instructions (currently only call_ref). 13301cb0ef41Sopenharmony_ci int feedback_instruction_index_ = 0; 13311cb0ef41Sopenharmony_ci std::vector<CallSiteFeedback> type_feedback_; 13321cb0ef41Sopenharmony_ci 13331cb0ef41Sopenharmony_ci TFNode* effect() { return builder_->effect(); } 13341cb0ef41Sopenharmony_ci 13351cb0ef41Sopenharmony_ci TFNode* control() { return builder_->control(); } 13361cb0ef41Sopenharmony_ci 13371cb0ef41Sopenharmony_ci TryInfo* current_try_info(FullDecoder* decoder) { 13381cb0ef41Sopenharmony_ci DCHECK_LT(decoder->current_catch(), decoder->control_depth()); 13391cb0ef41Sopenharmony_ci return decoder->control_at(decoder->control_depth_of_current_catch()) 13401cb0ef41Sopenharmony_ci ->try_info; 13411cb0ef41Sopenharmony_ci } 13421cb0ef41Sopenharmony_ci 13431cb0ef41Sopenharmony_ci // If {emit_loop_exits()} returns true, we need to emit LoopExit, 13441cb0ef41Sopenharmony_ci // LoopExitEffect, and LoopExit nodes whenever a control resp. effect resp. 13451cb0ef41Sopenharmony_ci // value escapes a loop. We emit loop exits in the following cases: 13461cb0ef41Sopenharmony_ci // - When popping the control of a loop. 13471cb0ef41Sopenharmony_ci // - At some nodes which connect to the graph's end. We do not always need to 13481cb0ef41Sopenharmony_ci // emit loop exits for such nodes, since the wasm loop analysis algorithm 13491cb0ef41Sopenharmony_ci // can handle a loop body which connects directly to the graph's end. 13501cb0ef41Sopenharmony_ci // However, we need to emit them anyway for nodes that may be rewired to 13511cb0ef41Sopenharmony_ci // different nodes during inlining. These are Return and TailCall nodes. 13521cb0ef41Sopenharmony_ci // - After IfFailure nodes. 13531cb0ef41Sopenharmony_ci // - When exiting a loop through Delegate. 13541cb0ef41Sopenharmony_ci bool emit_loop_exits() { 13551cb0ef41Sopenharmony_ci return FLAG_wasm_loop_unrolling || FLAG_wasm_loop_peeling; 13561cb0ef41Sopenharmony_ci } 13571cb0ef41Sopenharmony_ci 13581cb0ef41Sopenharmony_ci void GetNodes(TFNode** nodes, Value* values, size_t count) { 13591cb0ef41Sopenharmony_ci for (size_t i = 0; i < count; ++i) { 13601cb0ef41Sopenharmony_ci nodes[i] = values[i].node; 13611cb0ef41Sopenharmony_ci } 13621cb0ef41Sopenharmony_ci } 13631cb0ef41Sopenharmony_ci 13641cb0ef41Sopenharmony_ci void GetNodes(TFNode** nodes, base::Vector<Value> values) { 13651cb0ef41Sopenharmony_ci GetNodes(nodes, values.begin(), values.size()); 13661cb0ef41Sopenharmony_ci } 13671cb0ef41Sopenharmony_ci 13681cb0ef41Sopenharmony_ci void SetEnv(SsaEnv* env) { 13691cb0ef41Sopenharmony_ci if (FLAG_trace_wasm_decoder) { 13701cb0ef41Sopenharmony_ci char state = 'X'; 13711cb0ef41Sopenharmony_ci if (env) { 13721cb0ef41Sopenharmony_ci switch (env->state) { 13731cb0ef41Sopenharmony_ci case SsaEnv::kReached: 13741cb0ef41Sopenharmony_ci state = 'R'; 13751cb0ef41Sopenharmony_ci break; 13761cb0ef41Sopenharmony_ci case SsaEnv::kUnreachable: 13771cb0ef41Sopenharmony_ci state = 'U'; 13781cb0ef41Sopenharmony_ci break; 13791cb0ef41Sopenharmony_ci case SsaEnv::kMerged: 13801cb0ef41Sopenharmony_ci state = 'M'; 13811cb0ef41Sopenharmony_ci break; 13821cb0ef41Sopenharmony_ci } 13831cb0ef41Sopenharmony_ci } 13841cb0ef41Sopenharmony_ci PrintF("{set_env = %p, state = %c", env, state); 13851cb0ef41Sopenharmony_ci if (env && env->control) { 13861cb0ef41Sopenharmony_ci PrintF(", control = "); 13871cb0ef41Sopenharmony_ci compiler::WasmGraphBuilder::PrintDebugName(env->control); 13881cb0ef41Sopenharmony_ci } 13891cb0ef41Sopenharmony_ci PrintF("}\n"); 13901cb0ef41Sopenharmony_ci } 13911cb0ef41Sopenharmony_ci if (ssa_env_) { 13921cb0ef41Sopenharmony_ci ssa_env_->control = control(); 13931cb0ef41Sopenharmony_ci ssa_env_->effect = effect(); 13941cb0ef41Sopenharmony_ci } 13951cb0ef41Sopenharmony_ci ssa_env_ = env; 13961cb0ef41Sopenharmony_ci builder_->SetEffectControl(env->effect, env->control); 13971cb0ef41Sopenharmony_ci builder_->set_instance_cache(&env->instance_cache); 13981cb0ef41Sopenharmony_ci } 13991cb0ef41Sopenharmony_ci 14001cb0ef41Sopenharmony_ci TFNode* CheckForException(FullDecoder* decoder, TFNode* node) { 14011cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(node); 14021cb0ef41Sopenharmony_ci 14031cb0ef41Sopenharmony_ci // We need to emit IfSuccess/IfException nodes if this node throws and has 14041cb0ef41Sopenharmony_ci // an exception handler. An exception handler can either be a try-scope 14051cb0ef41Sopenharmony_ci // around this node, or if this function is being inlined, the IfException 14061cb0ef41Sopenharmony_ci // output of the inlined Call node. 14071cb0ef41Sopenharmony_ci const bool inside_try_scope = decoder->current_catch() != -1; 14081cb0ef41Sopenharmony_ci if (inlined_status_ != kInlinedHandledCall && !inside_try_scope) { 14091cb0ef41Sopenharmony_ci return node; 14101cb0ef41Sopenharmony_ci } 14111cb0ef41Sopenharmony_ci 14121cb0ef41Sopenharmony_ci TFNode* if_success = nullptr; 14131cb0ef41Sopenharmony_ci TFNode* if_exception = nullptr; 14141cb0ef41Sopenharmony_ci if (!builder_->ThrowsException(node, &if_success, &if_exception)) { 14151cb0ef41Sopenharmony_ci return node; 14161cb0ef41Sopenharmony_ci } 14171cb0ef41Sopenharmony_ci 14181cb0ef41Sopenharmony_ci SsaEnv* success_env = Steal(decoder->zone(), ssa_env_); 14191cb0ef41Sopenharmony_ci success_env->control = if_success; 14201cb0ef41Sopenharmony_ci 14211cb0ef41Sopenharmony_ci SsaEnv* exception_env = Split(decoder->zone(), success_env); 14221cb0ef41Sopenharmony_ci exception_env->control = if_exception; 14231cb0ef41Sopenharmony_ci exception_env->effect = if_exception; 14241cb0ef41Sopenharmony_ci SetEnv(exception_env); 14251cb0ef41Sopenharmony_ci 14261cb0ef41Sopenharmony_ci if (emit_loop_exits()) { 14271cb0ef41Sopenharmony_ci ValueVector values; 14281cb0ef41Sopenharmony_ci BuildNestedLoopExits(decoder, 14291cb0ef41Sopenharmony_ci inside_try_scope 14301cb0ef41Sopenharmony_ci ? decoder->control_depth_of_current_catch() 14311cb0ef41Sopenharmony_ci : decoder->control_depth() - 1, 14321cb0ef41Sopenharmony_ci true, values, &if_exception); 14331cb0ef41Sopenharmony_ci } 14341cb0ef41Sopenharmony_ci if (inside_try_scope) { 14351cb0ef41Sopenharmony_ci TryInfo* try_info = current_try_info(decoder); 14361cb0ef41Sopenharmony_ci Goto(decoder, try_info->catch_env); 14371cb0ef41Sopenharmony_ci if (try_info->exception == nullptr) { 14381cb0ef41Sopenharmony_ci DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state); 14391cb0ef41Sopenharmony_ci try_info->exception = if_exception; 14401cb0ef41Sopenharmony_ci } else { 14411cb0ef41Sopenharmony_ci DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state); 14421cb0ef41Sopenharmony_ci try_info->exception = builder_->CreateOrMergeIntoPhi( 14431cb0ef41Sopenharmony_ci MachineRepresentation::kTaggedPointer, try_info->catch_env->control, 14441cb0ef41Sopenharmony_ci try_info->exception, if_exception); 14451cb0ef41Sopenharmony_ci } 14461cb0ef41Sopenharmony_ci } else { 14471cb0ef41Sopenharmony_ci DCHECK_EQ(inlined_status_, kInlinedHandledCall); 14481cb0ef41Sopenharmony_ci // Leave the IfException/LoopExit node dangling. We will connect it during 14491cb0ef41Sopenharmony_ci // inlining to the handler of the inlined call. 14501cb0ef41Sopenharmony_ci // Note: We have to generate the handler now since we have no way of 14511cb0ef41Sopenharmony_ci // generating a LoopExit if needed in the inlining code. 14521cb0ef41Sopenharmony_ci } 14531cb0ef41Sopenharmony_ci 14541cb0ef41Sopenharmony_ci SetEnv(success_env); 14551cb0ef41Sopenharmony_ci return node; 14561cb0ef41Sopenharmony_ci } 14571cb0ef41Sopenharmony_ci 14581cb0ef41Sopenharmony_ci TFNode* DefaultValue(ValueType type) { 14591cb0ef41Sopenharmony_ci DCHECK(type.is_defaultable()); 14601cb0ef41Sopenharmony_ci switch (type.kind()) { 14611cb0ef41Sopenharmony_ci case kI8: 14621cb0ef41Sopenharmony_ci case kI16: 14631cb0ef41Sopenharmony_ci case kI32: 14641cb0ef41Sopenharmony_ci return builder_->Int32Constant(0); 14651cb0ef41Sopenharmony_ci case kI64: 14661cb0ef41Sopenharmony_ci return builder_->Int64Constant(0); 14671cb0ef41Sopenharmony_ci case kF32: 14681cb0ef41Sopenharmony_ci return builder_->Float32Constant(0); 14691cb0ef41Sopenharmony_ci case kF64: 14701cb0ef41Sopenharmony_ci return builder_->Float64Constant(0); 14711cb0ef41Sopenharmony_ci case kS128: 14721cb0ef41Sopenharmony_ci return builder_->S128Zero(); 14731cb0ef41Sopenharmony_ci case kOptRef: 14741cb0ef41Sopenharmony_ci return builder_->RefNull(); 14751cb0ef41Sopenharmony_ci case kRtt: 14761cb0ef41Sopenharmony_ci case kVoid: 14771cb0ef41Sopenharmony_ci case kBottom: 14781cb0ef41Sopenharmony_ci case kRef: 14791cb0ef41Sopenharmony_ci UNREACHABLE(); 14801cb0ef41Sopenharmony_ci } 14811cb0ef41Sopenharmony_ci } 14821cb0ef41Sopenharmony_ci 14831cb0ef41Sopenharmony_ci void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge, 14841cb0ef41Sopenharmony_ci Value* values) { 14851cb0ef41Sopenharmony_ci DCHECK(merge == &c->start_merge || merge == &c->end_merge); 14861cb0ef41Sopenharmony_ci 14871cb0ef41Sopenharmony_ci SsaEnv* target = c->merge_env; 14881cb0ef41Sopenharmony_ci // This has to be computed before calling Goto(). 14891cb0ef41Sopenharmony_ci const bool first = target->state == SsaEnv::kUnreachable; 14901cb0ef41Sopenharmony_ci 14911cb0ef41Sopenharmony_ci Goto(decoder, target); 14921cb0ef41Sopenharmony_ci 14931cb0ef41Sopenharmony_ci if (merge->arity == 0) return; 14941cb0ef41Sopenharmony_ci 14951cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < merge->arity; ++i) { 14961cb0ef41Sopenharmony_ci Value& val = values[i]; 14971cb0ef41Sopenharmony_ci Value& old = (*merge)[i]; 14981cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(val.node); 14991cb0ef41Sopenharmony_ci DCHECK(val.type == kWasmBottom || val.type.machine_representation() == 15001cb0ef41Sopenharmony_ci old.type.machine_representation()); 15011cb0ef41Sopenharmony_ci old.node = first ? val.node 15021cb0ef41Sopenharmony_ci : builder_->CreateOrMergeIntoPhi( 15031cb0ef41Sopenharmony_ci old.type.machine_representation(), target->control, 15041cb0ef41Sopenharmony_ci old.node, val.node); 15051cb0ef41Sopenharmony_ci } 15061cb0ef41Sopenharmony_ci } 15071cb0ef41Sopenharmony_ci 15081cb0ef41Sopenharmony_ci void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge, 15091cb0ef41Sopenharmony_ci uint32_t drop_values = 0) { 15101cb0ef41Sopenharmony_ci#ifdef DEBUG 15111cb0ef41Sopenharmony_ci uint32_t avail = decoder->stack_size() - 15121cb0ef41Sopenharmony_ci decoder->control_at(0)->stack_depth - drop_values; 15131cb0ef41Sopenharmony_ci DCHECK_GE(avail, merge->arity); 15141cb0ef41Sopenharmony_ci#endif 15151cb0ef41Sopenharmony_ci Value* stack_values = merge->arity > 0 15161cb0ef41Sopenharmony_ci ? decoder->stack_value(merge->arity + drop_values) 15171cb0ef41Sopenharmony_ci : nullptr; 15181cb0ef41Sopenharmony_ci MergeValuesInto(decoder, c, merge, stack_values); 15191cb0ef41Sopenharmony_ci } 15201cb0ef41Sopenharmony_ci 15211cb0ef41Sopenharmony_ci void Goto(FullDecoder* decoder, SsaEnv* to) { 15221cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(to); 15231cb0ef41Sopenharmony_ci switch (to->state) { 15241cb0ef41Sopenharmony_ci case SsaEnv::kUnreachable: { // Overwrite destination. 15251cb0ef41Sopenharmony_ci to->state = SsaEnv::kReached; 15261cb0ef41Sopenharmony_ci // There might be an offset in the locals due to a 'let'. 15271cb0ef41Sopenharmony_ci DCHECK_EQ(ssa_env_->locals.size(), decoder->num_locals()); 15281cb0ef41Sopenharmony_ci DCHECK_GE(ssa_env_->locals.size(), to->locals.size()); 15291cb0ef41Sopenharmony_ci uint32_t local_count_diff = 15301cb0ef41Sopenharmony_ci static_cast<uint32_t>(ssa_env_->locals.size() - to->locals.size()); 15311cb0ef41Sopenharmony_ci to->locals = ssa_env_->locals; 15321cb0ef41Sopenharmony_ci to->locals.erase(to->locals.begin(), 15331cb0ef41Sopenharmony_ci to->locals.begin() + local_count_diff); 15341cb0ef41Sopenharmony_ci to->control = control(); 15351cb0ef41Sopenharmony_ci to->effect = effect(); 15361cb0ef41Sopenharmony_ci to->instance_cache = ssa_env_->instance_cache; 15371cb0ef41Sopenharmony_ci break; 15381cb0ef41Sopenharmony_ci } 15391cb0ef41Sopenharmony_ci case SsaEnv::kReached: { // Create a new merge. 15401cb0ef41Sopenharmony_ci to->state = SsaEnv::kMerged; 15411cb0ef41Sopenharmony_ci // Merge control. 15421cb0ef41Sopenharmony_ci TFNode* controls[] = {to->control, control()}; 15431cb0ef41Sopenharmony_ci TFNode* merge = builder_->Merge(2, controls); 15441cb0ef41Sopenharmony_ci to->control = merge; 15451cb0ef41Sopenharmony_ci // Merge effects. 15461cb0ef41Sopenharmony_ci TFNode* old_effect = effect(); 15471cb0ef41Sopenharmony_ci if (old_effect != to->effect) { 15481cb0ef41Sopenharmony_ci TFNode* inputs[] = {to->effect, old_effect, merge}; 15491cb0ef41Sopenharmony_ci to->effect = builder_->EffectPhi(2, inputs); 15501cb0ef41Sopenharmony_ci } 15511cb0ef41Sopenharmony_ci // Merge locals. 15521cb0ef41Sopenharmony_ci // There might be an offset in the locals due to a 'let'. 15531cb0ef41Sopenharmony_ci DCHECK_EQ(ssa_env_->locals.size(), decoder->num_locals()); 15541cb0ef41Sopenharmony_ci DCHECK_GE(ssa_env_->locals.size(), to->locals.size()); 15551cb0ef41Sopenharmony_ci uint32_t local_count_diff = 15561cb0ef41Sopenharmony_ci static_cast<uint32_t>(ssa_env_->locals.size() - to->locals.size()); 15571cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < to->locals.size(); i++) { 15581cb0ef41Sopenharmony_ci TFNode* a = to->locals[i]; 15591cb0ef41Sopenharmony_ci TFNode* b = ssa_env_->locals[i + local_count_diff]; 15601cb0ef41Sopenharmony_ci if (a != b) { 15611cb0ef41Sopenharmony_ci TFNode* inputs[] = {a, b, merge}; 15621cb0ef41Sopenharmony_ci to->locals[i] = builder_->Phi( 15631cb0ef41Sopenharmony_ci decoder->local_type(i + local_count_diff), 2, inputs); 15641cb0ef41Sopenharmony_ci } 15651cb0ef41Sopenharmony_ci } 15661cb0ef41Sopenharmony_ci // Start a new merge from the instance cache. 15671cb0ef41Sopenharmony_ci builder_->NewInstanceCacheMerge(&to->instance_cache, 15681cb0ef41Sopenharmony_ci &ssa_env_->instance_cache, merge); 15691cb0ef41Sopenharmony_ci break; 15701cb0ef41Sopenharmony_ci } 15711cb0ef41Sopenharmony_ci case SsaEnv::kMerged: { 15721cb0ef41Sopenharmony_ci TFNode* merge = to->control; 15731cb0ef41Sopenharmony_ci // Extend the existing merge control node. 15741cb0ef41Sopenharmony_ci builder_->AppendToMerge(merge, control()); 15751cb0ef41Sopenharmony_ci // Merge effects. 15761cb0ef41Sopenharmony_ci to->effect = 15771cb0ef41Sopenharmony_ci builder_->CreateOrMergeIntoEffectPhi(merge, to->effect, effect()); 15781cb0ef41Sopenharmony_ci // Merge locals. 15791cb0ef41Sopenharmony_ci // There might be an offset in the locals due to a 'let'. 15801cb0ef41Sopenharmony_ci DCHECK_EQ(ssa_env_->locals.size(), decoder->num_locals()); 15811cb0ef41Sopenharmony_ci DCHECK_GE(ssa_env_->locals.size(), to->locals.size()); 15821cb0ef41Sopenharmony_ci uint32_t local_count_diff = 15831cb0ef41Sopenharmony_ci static_cast<uint32_t>(ssa_env_->locals.size() - to->locals.size()); 15841cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < to->locals.size(); i++) { 15851cb0ef41Sopenharmony_ci to->locals[i] = builder_->CreateOrMergeIntoPhi( 15861cb0ef41Sopenharmony_ci decoder->local_type(i + local_count_diff) 15871cb0ef41Sopenharmony_ci .machine_representation(), 15881cb0ef41Sopenharmony_ci merge, to->locals[i], ssa_env_->locals[i + local_count_diff]); 15891cb0ef41Sopenharmony_ci } 15901cb0ef41Sopenharmony_ci // Merge the instance caches. 15911cb0ef41Sopenharmony_ci builder_->MergeInstanceCacheInto(&to->instance_cache, 15921cb0ef41Sopenharmony_ci &ssa_env_->instance_cache, merge); 15931cb0ef41Sopenharmony_ci break; 15941cb0ef41Sopenharmony_ci } 15951cb0ef41Sopenharmony_ci default: 15961cb0ef41Sopenharmony_ci UNREACHABLE(); 15971cb0ef41Sopenharmony_ci } 15981cb0ef41Sopenharmony_ci } 15991cb0ef41Sopenharmony_ci 16001cb0ef41Sopenharmony_ci // Create a complete copy of {from}. 16011cb0ef41Sopenharmony_ci SsaEnv* Split(Zone* zone, SsaEnv* from) { 16021cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(from); 16031cb0ef41Sopenharmony_ci if (from == ssa_env_) { 16041cb0ef41Sopenharmony_ci ssa_env_->control = control(); 16051cb0ef41Sopenharmony_ci ssa_env_->effect = effect(); 16061cb0ef41Sopenharmony_ci } 16071cb0ef41Sopenharmony_ci SsaEnv* result = zone->New<SsaEnv>(*from); 16081cb0ef41Sopenharmony_ci result->state = SsaEnv::kReached; 16091cb0ef41Sopenharmony_ci return result; 16101cb0ef41Sopenharmony_ci } 16111cb0ef41Sopenharmony_ci 16121cb0ef41Sopenharmony_ci // Create a copy of {from} that steals its state and leaves {from} 16131cb0ef41Sopenharmony_ci // unreachable. 16141cb0ef41Sopenharmony_ci SsaEnv* Steal(Zone* zone, SsaEnv* from) { 16151cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(from); 16161cb0ef41Sopenharmony_ci if (from == ssa_env_) { 16171cb0ef41Sopenharmony_ci ssa_env_->control = control(); 16181cb0ef41Sopenharmony_ci ssa_env_->effect = effect(); 16191cb0ef41Sopenharmony_ci } 16201cb0ef41Sopenharmony_ci SsaEnv* result = zone->New<SsaEnv>(std::move(*from)); 16211cb0ef41Sopenharmony_ci // Restore the length of {from->locals} after applying move-constructor. 16221cb0ef41Sopenharmony_ci from->locals.resize(result->locals.size()); 16231cb0ef41Sopenharmony_ci result->state = SsaEnv::kReached; 16241cb0ef41Sopenharmony_ci return result; 16251cb0ef41Sopenharmony_ci } 16261cb0ef41Sopenharmony_ci 16271cb0ef41Sopenharmony_ci class CallInfo { 16281cb0ef41Sopenharmony_ci public: 16291cb0ef41Sopenharmony_ci enum CallMode { kCallDirect, kCallIndirect, kCallRef }; 16301cb0ef41Sopenharmony_ci 16311cb0ef41Sopenharmony_ci static CallInfo CallDirect(uint32_t callee_index) { 16321cb0ef41Sopenharmony_ci return {kCallDirect, callee_index, nullptr, 0, 16331cb0ef41Sopenharmony_ci CheckForNull::kWithoutNullCheck}; 16341cb0ef41Sopenharmony_ci } 16351cb0ef41Sopenharmony_ci 16361cb0ef41Sopenharmony_ci static CallInfo CallIndirect(const Value& index_value, uint32_t table_index, 16371cb0ef41Sopenharmony_ci uint32_t sig_index) { 16381cb0ef41Sopenharmony_ci return {kCallIndirect, sig_index, &index_value, table_index, 16391cb0ef41Sopenharmony_ci CheckForNull::kWithoutNullCheck}; 16401cb0ef41Sopenharmony_ci } 16411cb0ef41Sopenharmony_ci 16421cb0ef41Sopenharmony_ci static CallInfo CallRef(const Value& funcref_value, 16431cb0ef41Sopenharmony_ci CheckForNull null_check) { 16441cb0ef41Sopenharmony_ci return {kCallRef, 0, &funcref_value, 0, null_check}; 16451cb0ef41Sopenharmony_ci } 16461cb0ef41Sopenharmony_ci 16471cb0ef41Sopenharmony_ci CallMode call_mode() { return call_mode_; } 16481cb0ef41Sopenharmony_ci 16491cb0ef41Sopenharmony_ci uint32_t sig_index() { 16501cb0ef41Sopenharmony_ci DCHECK_EQ(call_mode_, kCallIndirect); 16511cb0ef41Sopenharmony_ci return callee_or_sig_index_; 16521cb0ef41Sopenharmony_ci } 16531cb0ef41Sopenharmony_ci 16541cb0ef41Sopenharmony_ci uint32_t callee_index() { 16551cb0ef41Sopenharmony_ci DCHECK_EQ(call_mode_, kCallDirect); 16561cb0ef41Sopenharmony_ci return callee_or_sig_index_; 16571cb0ef41Sopenharmony_ci } 16581cb0ef41Sopenharmony_ci 16591cb0ef41Sopenharmony_ci CheckForNull null_check() { 16601cb0ef41Sopenharmony_ci DCHECK_EQ(call_mode_, kCallRef); 16611cb0ef41Sopenharmony_ci return null_check_; 16621cb0ef41Sopenharmony_ci } 16631cb0ef41Sopenharmony_ci 16641cb0ef41Sopenharmony_ci const Value* index_or_callee_value() { 16651cb0ef41Sopenharmony_ci DCHECK_NE(call_mode_, kCallDirect); 16661cb0ef41Sopenharmony_ci return index_or_callee_value_; 16671cb0ef41Sopenharmony_ci } 16681cb0ef41Sopenharmony_ci 16691cb0ef41Sopenharmony_ci uint32_t table_index() { 16701cb0ef41Sopenharmony_ci DCHECK_EQ(call_mode_, kCallIndirect); 16711cb0ef41Sopenharmony_ci return table_index_; 16721cb0ef41Sopenharmony_ci } 16731cb0ef41Sopenharmony_ci 16741cb0ef41Sopenharmony_ci private: 16751cb0ef41Sopenharmony_ci CallInfo(CallMode call_mode, uint32_t callee_or_sig_index, 16761cb0ef41Sopenharmony_ci const Value* index_or_callee_value, uint32_t table_index, 16771cb0ef41Sopenharmony_ci CheckForNull null_check) 16781cb0ef41Sopenharmony_ci : call_mode_(call_mode), 16791cb0ef41Sopenharmony_ci callee_or_sig_index_(callee_or_sig_index), 16801cb0ef41Sopenharmony_ci index_or_callee_value_(index_or_callee_value), 16811cb0ef41Sopenharmony_ci table_index_(table_index), 16821cb0ef41Sopenharmony_ci null_check_(null_check) {} 16831cb0ef41Sopenharmony_ci CallMode call_mode_; 16841cb0ef41Sopenharmony_ci uint32_t callee_or_sig_index_; 16851cb0ef41Sopenharmony_ci const Value* index_or_callee_value_; 16861cb0ef41Sopenharmony_ci uint32_t table_index_; 16871cb0ef41Sopenharmony_ci CheckForNull null_check_; 16881cb0ef41Sopenharmony_ci }; 16891cb0ef41Sopenharmony_ci 16901cb0ef41Sopenharmony_ci void DoCall(FullDecoder* decoder, CallInfo call_info, const FunctionSig* sig, 16911cb0ef41Sopenharmony_ci const Value args[], Value returns[]) { 16921cb0ef41Sopenharmony_ci size_t param_count = sig->parameter_count(); 16931cb0ef41Sopenharmony_ci size_t return_count = sig->return_count(); 16941cb0ef41Sopenharmony_ci 16951cb0ef41Sopenharmony_ci // Construct a function signature based on the real function parameters. 16961cb0ef41Sopenharmony_ci FunctionSig::Builder real_sig_builder(builder_->graph_zone(), return_count, 16971cb0ef41Sopenharmony_ci param_count); 16981cb0ef41Sopenharmony_ci for (size_t i = 0; i < param_count; i++) { 16991cb0ef41Sopenharmony_ci real_sig_builder.AddParam(args[i].type); 17001cb0ef41Sopenharmony_ci } 17011cb0ef41Sopenharmony_ci for (size_t i = 0; i < return_count; i++) { 17021cb0ef41Sopenharmony_ci real_sig_builder.AddReturn(sig->GetReturn(i)); 17031cb0ef41Sopenharmony_ci } 17041cb0ef41Sopenharmony_ci FunctionSig* real_sig = real_sig_builder.Build(); 17051cb0ef41Sopenharmony_ci 17061cb0ef41Sopenharmony_ci NodeVector arg_nodes(param_count + 1); 17071cb0ef41Sopenharmony_ci base::SmallVector<TFNode*, 1> return_nodes(return_count); 17081cb0ef41Sopenharmony_ci arg_nodes[0] = (call_info.call_mode() == CallInfo::kCallDirect) 17091cb0ef41Sopenharmony_ci ? nullptr 17101cb0ef41Sopenharmony_ci : call_info.index_or_callee_value()->node; 17111cb0ef41Sopenharmony_ci 17121cb0ef41Sopenharmony_ci for (size_t i = 0; i < param_count; ++i) { 17131cb0ef41Sopenharmony_ci arg_nodes[i + 1] = args[i].node; 17141cb0ef41Sopenharmony_ci } 17151cb0ef41Sopenharmony_ci switch (call_info.call_mode()) { 17161cb0ef41Sopenharmony_ci case CallInfo::kCallIndirect: 17171cb0ef41Sopenharmony_ci CheckForException( 17181cb0ef41Sopenharmony_ci decoder, builder_->CallIndirect( 17191cb0ef41Sopenharmony_ci call_info.table_index(), call_info.sig_index(), 17201cb0ef41Sopenharmony_ci real_sig, base::VectorOf(arg_nodes), 17211cb0ef41Sopenharmony_ci base::VectorOf(return_nodes), decoder->position())); 17221cb0ef41Sopenharmony_ci break; 17231cb0ef41Sopenharmony_ci case CallInfo::kCallDirect: 17241cb0ef41Sopenharmony_ci CheckForException( 17251cb0ef41Sopenharmony_ci decoder, builder_->CallDirect(call_info.callee_index(), real_sig, 17261cb0ef41Sopenharmony_ci base::VectorOf(arg_nodes), 17271cb0ef41Sopenharmony_ci base::VectorOf(return_nodes), 17281cb0ef41Sopenharmony_ci decoder->position())); 17291cb0ef41Sopenharmony_ci break; 17301cb0ef41Sopenharmony_ci case CallInfo::kCallRef: 17311cb0ef41Sopenharmony_ci CheckForException( 17321cb0ef41Sopenharmony_ci decoder, 17331cb0ef41Sopenharmony_ci builder_->CallRef(real_sig, base::VectorOf(arg_nodes), 17341cb0ef41Sopenharmony_ci base::VectorOf(return_nodes), 17351cb0ef41Sopenharmony_ci call_info.null_check(), decoder->position())); 17361cb0ef41Sopenharmony_ci break; 17371cb0ef41Sopenharmony_ci } 17381cb0ef41Sopenharmony_ci for (size_t i = 0; i < return_count; ++i) { 17391cb0ef41Sopenharmony_ci returns[i].node = return_nodes[i]; 17401cb0ef41Sopenharmony_ci } 17411cb0ef41Sopenharmony_ci if (decoder->module_->initial_pages != decoder->module_->maximum_pages) { 17421cb0ef41Sopenharmony_ci // The invoked function could have used grow_memory, so we need to 17431cb0ef41Sopenharmony_ci // reload mem_size and mem_start. 17441cb0ef41Sopenharmony_ci LoadContextIntoSsa(ssa_env_); 17451cb0ef41Sopenharmony_ci } 17461cb0ef41Sopenharmony_ci } 17471cb0ef41Sopenharmony_ci 17481cb0ef41Sopenharmony_ci void DoReturnCall(FullDecoder* decoder, CallInfo call_info, 17491cb0ef41Sopenharmony_ci const FunctionSig* sig, const Value args[]) { 17501cb0ef41Sopenharmony_ci size_t arg_count = sig->parameter_count(); 17511cb0ef41Sopenharmony_ci 17521cb0ef41Sopenharmony_ci // Construct a function signature based on the real function parameters. 17531cb0ef41Sopenharmony_ci FunctionSig::Builder real_sig_builder(builder_->graph_zone(), 17541cb0ef41Sopenharmony_ci sig->return_count(), arg_count); 17551cb0ef41Sopenharmony_ci for (size_t i = 0; i < arg_count; i++) { 17561cb0ef41Sopenharmony_ci real_sig_builder.AddParam(args[i].type); 17571cb0ef41Sopenharmony_ci } 17581cb0ef41Sopenharmony_ci for (size_t i = 0; i < sig->return_count(); i++) { 17591cb0ef41Sopenharmony_ci real_sig_builder.AddReturn(sig->GetReturn(i)); 17601cb0ef41Sopenharmony_ci } 17611cb0ef41Sopenharmony_ci FunctionSig* real_sig = real_sig_builder.Build(); 17621cb0ef41Sopenharmony_ci 17631cb0ef41Sopenharmony_ci ValueVector arg_values(arg_count + 1); 17641cb0ef41Sopenharmony_ci if (call_info.call_mode() == CallInfo::kCallDirect) { 17651cb0ef41Sopenharmony_ci arg_values[0].node = nullptr; 17661cb0ef41Sopenharmony_ci } else { 17671cb0ef41Sopenharmony_ci arg_values[0] = *call_info.index_or_callee_value(); 17681cb0ef41Sopenharmony_ci // This is not done by copy assignment. 17691cb0ef41Sopenharmony_ci arg_values[0].node = call_info.index_or_callee_value()->node; 17701cb0ef41Sopenharmony_ci } 17711cb0ef41Sopenharmony_ci if (arg_count > 0) { 17721cb0ef41Sopenharmony_ci std::memcpy(arg_values.data() + 1, args, arg_count * sizeof(Value)); 17731cb0ef41Sopenharmony_ci } 17741cb0ef41Sopenharmony_ci 17751cb0ef41Sopenharmony_ci if (emit_loop_exits()) { 17761cb0ef41Sopenharmony_ci BuildNestedLoopExits(decoder, decoder->control_depth(), false, 17771cb0ef41Sopenharmony_ci arg_values); 17781cb0ef41Sopenharmony_ci } 17791cb0ef41Sopenharmony_ci 17801cb0ef41Sopenharmony_ci NodeVector arg_nodes(arg_count + 1); 17811cb0ef41Sopenharmony_ci GetNodes(arg_nodes.data(), base::VectorOf(arg_values)); 17821cb0ef41Sopenharmony_ci 17831cb0ef41Sopenharmony_ci switch (call_info.call_mode()) { 17841cb0ef41Sopenharmony_ci case CallInfo::kCallIndirect: 17851cb0ef41Sopenharmony_ci builder_->ReturnCallIndirect( 17861cb0ef41Sopenharmony_ci call_info.table_index(), call_info.sig_index(), real_sig, 17871cb0ef41Sopenharmony_ci base::VectorOf(arg_nodes), decoder->position()); 17881cb0ef41Sopenharmony_ci break; 17891cb0ef41Sopenharmony_ci case CallInfo::kCallDirect: 17901cb0ef41Sopenharmony_ci builder_->ReturnCall(call_info.callee_index(), real_sig, 17911cb0ef41Sopenharmony_ci base::VectorOf(arg_nodes), decoder->position()); 17921cb0ef41Sopenharmony_ci break; 17931cb0ef41Sopenharmony_ci case CallInfo::kCallRef: 17941cb0ef41Sopenharmony_ci builder_->ReturnCallRef(real_sig, base::VectorOf(arg_nodes), 17951cb0ef41Sopenharmony_ci call_info.null_check(), decoder->position()); 17961cb0ef41Sopenharmony_ci break; 17971cb0ef41Sopenharmony_ci } 17981cb0ef41Sopenharmony_ci } 17991cb0ef41Sopenharmony_ci 18001cb0ef41Sopenharmony_ci void BuildLoopExits(FullDecoder* decoder, Control* loop) { 18011cb0ef41Sopenharmony_ci builder_->LoopExit(loop->loop_node); 18021cb0ef41Sopenharmony_ci ssa_env_->control = control(); 18031cb0ef41Sopenharmony_ci ssa_env_->effect = effect(); 18041cb0ef41Sopenharmony_ci } 18051cb0ef41Sopenharmony_ci 18061cb0ef41Sopenharmony_ci void WrapLocalsAtLoopExit(FullDecoder* decoder, Control* loop) { 18071cb0ef41Sopenharmony_ci for (uint32_t index = 0; index < decoder->num_locals(); index++) { 18081cb0ef41Sopenharmony_ci if (loop->loop_assignments->Contains(static_cast<int>(index))) { 18091cb0ef41Sopenharmony_ci ssa_env_->locals[index] = builder_->LoopExitValue( 18101cb0ef41Sopenharmony_ci ssa_env_->locals[index], 18111cb0ef41Sopenharmony_ci decoder->local_type(index).machine_representation()); 18121cb0ef41Sopenharmony_ci } 18131cb0ef41Sopenharmony_ci } 18141cb0ef41Sopenharmony_ci if (loop->loop_assignments->Contains(decoder->num_locals())) { 18151cb0ef41Sopenharmony_ci#define WRAP_CACHE_FIELD(field) \ 18161cb0ef41Sopenharmony_ci if (ssa_env_->instance_cache.field != nullptr) { \ 18171cb0ef41Sopenharmony_ci ssa_env_->instance_cache.field = builder_->LoopExitValue( \ 18181cb0ef41Sopenharmony_ci ssa_env_->instance_cache.field, MachineType::PointerRepresentation()); \ 18191cb0ef41Sopenharmony_ci } 18201cb0ef41Sopenharmony_ci 18211cb0ef41Sopenharmony_ci WRAP_CACHE_FIELD(mem_start); 18221cb0ef41Sopenharmony_ci WRAP_CACHE_FIELD(mem_size); 18231cb0ef41Sopenharmony_ci#undef WRAP_CACHE_FIELD 18241cb0ef41Sopenharmony_ci } 18251cb0ef41Sopenharmony_ci } 18261cb0ef41Sopenharmony_ci 18271cb0ef41Sopenharmony_ci void BuildNestedLoopExits(FullDecoder* decoder, uint32_t depth_limit, 18281cb0ef41Sopenharmony_ci bool wrap_exit_values, ValueVector& stack_values, 18291cb0ef41Sopenharmony_ci TFNode** exception_value = nullptr) { 18301cb0ef41Sopenharmony_ci DCHECK(emit_loop_exits()); 18311cb0ef41Sopenharmony_ci Control* control = nullptr; 18321cb0ef41Sopenharmony_ci // We are only interested in exits from the innermost loop. 18331cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < depth_limit; i++) { 18341cb0ef41Sopenharmony_ci Control* c = decoder->control_at(i); 18351cb0ef41Sopenharmony_ci if (c->is_loop()) { 18361cb0ef41Sopenharmony_ci control = c; 18371cb0ef41Sopenharmony_ci break; 18381cb0ef41Sopenharmony_ci } 18391cb0ef41Sopenharmony_ci } 18401cb0ef41Sopenharmony_ci if (control != nullptr) { 18411cb0ef41Sopenharmony_ci BuildLoopExits(decoder, control); 18421cb0ef41Sopenharmony_ci for (Value& value : stack_values) { 18431cb0ef41Sopenharmony_ci if (value.node != nullptr) { 18441cb0ef41Sopenharmony_ci value.node = builder_->LoopExitValue( 18451cb0ef41Sopenharmony_ci value.node, value.type.machine_representation()); 18461cb0ef41Sopenharmony_ci } 18471cb0ef41Sopenharmony_ci } 18481cb0ef41Sopenharmony_ci if (exception_value != nullptr) { 18491cb0ef41Sopenharmony_ci *exception_value = builder_->LoopExitValue( 18501cb0ef41Sopenharmony_ci *exception_value, MachineRepresentation::kWord32); 18511cb0ef41Sopenharmony_ci } 18521cb0ef41Sopenharmony_ci if (wrap_exit_values) { 18531cb0ef41Sopenharmony_ci WrapLocalsAtLoopExit(decoder, control); 18541cb0ef41Sopenharmony_ci } 18551cb0ef41Sopenharmony_ci } 18561cb0ef41Sopenharmony_ci } 18571cb0ef41Sopenharmony_ci 18581cb0ef41Sopenharmony_ci CheckForNull NullCheckFor(ValueType type) { 18591cb0ef41Sopenharmony_ci DCHECK(type.is_object_reference()); 18601cb0ef41Sopenharmony_ci return (!FLAG_experimental_wasm_skip_null_checks && type.is_nullable()) 18611cb0ef41Sopenharmony_ci ? CheckForNull::kWithNullCheck 18621cb0ef41Sopenharmony_ci : CheckForNull::kWithoutNullCheck; 18631cb0ef41Sopenharmony_ci } 18641cb0ef41Sopenharmony_ci}; 18651cb0ef41Sopenharmony_ci 18661cb0ef41Sopenharmony_ci} // namespace 18671cb0ef41Sopenharmony_ci 18681cb0ef41Sopenharmony_ciDecodeResult BuildTFGraph(AccountingAllocator* allocator, 18691cb0ef41Sopenharmony_ci const WasmFeatures& enabled, const WasmModule* module, 18701cb0ef41Sopenharmony_ci compiler::WasmGraphBuilder* builder, 18711cb0ef41Sopenharmony_ci WasmFeatures* detected, const FunctionBody& body, 18721cb0ef41Sopenharmony_ci std::vector<compiler::WasmLoopInfo>* loop_infos, 18731cb0ef41Sopenharmony_ci compiler::NodeOriginTable* node_origins, 18741cb0ef41Sopenharmony_ci int func_index, InlinedStatus inlined_status) { 18751cb0ef41Sopenharmony_ci Zone zone(allocator, ZONE_NAME); 18761cb0ef41Sopenharmony_ci WasmFullDecoder<Decoder::kFullValidation, WasmGraphBuildingInterface> decoder( 18771cb0ef41Sopenharmony_ci &zone, module, enabled, detected, body, builder, func_index, 18781cb0ef41Sopenharmony_ci inlined_status); 18791cb0ef41Sopenharmony_ci if (node_origins) { 18801cb0ef41Sopenharmony_ci builder->AddBytecodePositionDecorator(node_origins, &decoder); 18811cb0ef41Sopenharmony_ci } 18821cb0ef41Sopenharmony_ci decoder.Decode(); 18831cb0ef41Sopenharmony_ci if (node_origins) { 18841cb0ef41Sopenharmony_ci builder->RemoveBytecodePositionDecorator(); 18851cb0ef41Sopenharmony_ci } 18861cb0ef41Sopenharmony_ci *loop_infos = decoder.interface().loop_infos(); 18871cb0ef41Sopenharmony_ci 18881cb0ef41Sopenharmony_ci return decoder.toResult(nullptr); 18891cb0ef41Sopenharmony_ci} 18901cb0ef41Sopenharmony_ci 18911cb0ef41Sopenharmony_ci} // namespace wasm 18921cb0ef41Sopenharmony_ci} // namespace internal 18931cb0ef41Sopenharmony_ci} // namespace v8 1894