11cb0ef41Sopenharmony_ci// Copyright 2015 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/compiler/bytecode-graph-builder.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/ast/ast.h" 81cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h" 91cb0ef41Sopenharmony_ci#include "src/codegen/source-position-table.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/tick-counter.h" 111cb0ef41Sopenharmony_ci#include "src/common/assert-scope.h" 121cb0ef41Sopenharmony_ci#include "src/compiler/access-builder.h" 131cb0ef41Sopenharmony_ci#include "src/compiler/bytecode-analysis.h" 141cb0ef41Sopenharmony_ci#include "src/compiler/common-operator.h" 151cb0ef41Sopenharmony_ci#include "src/compiler/compiler-source-position-table.h" 161cb0ef41Sopenharmony_ci#include "src/compiler/js-heap-broker.h" 171cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h" 181cb0ef41Sopenharmony_ci#include "src/compiler/node-matchers.h" 191cb0ef41Sopenharmony_ci#include "src/compiler/node-observer.h" 201cb0ef41Sopenharmony_ci#include "src/compiler/operator-properties.h" 211cb0ef41Sopenharmony_ci#include "src/compiler/simplified-operator.h" 221cb0ef41Sopenharmony_ci#include "src/compiler/state-values-utils.h" 231cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-array-iterator.h" 241cb0ef41Sopenharmony_ci#include "src/interpreter/bytecode-flags.h" 251cb0ef41Sopenharmony_ci#include "src/interpreter/bytecodes.h" 261cb0ef41Sopenharmony_ci#include "src/objects/js-array-inl.h" 271cb0ef41Sopenharmony_ci#include "src/objects/js-generator.h" 281cb0ef41Sopenharmony_ci#include "src/objects/literal-objects-inl.h" 291cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h" 301cb0ef41Sopenharmony_ci#include "src/objects/smi.h" 311cb0ef41Sopenharmony_ci#include "src/objects/template-objects-inl.h" 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_cinamespace v8 { 341cb0ef41Sopenharmony_cinamespace internal { 351cb0ef41Sopenharmony_cinamespace compiler { 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ciclass BytecodeGraphBuilder { 381cb0ef41Sopenharmony_ci public: 391cb0ef41Sopenharmony_ci BytecodeGraphBuilder(JSHeapBroker* broker, Zone* local_zone, 401cb0ef41Sopenharmony_ci NativeContextRef const& native_context, 411cb0ef41Sopenharmony_ci SharedFunctionInfoRef const& shared_info, 421cb0ef41Sopenharmony_ci FeedbackCellRef const& feedback_cell, 431cb0ef41Sopenharmony_ci BytecodeOffset osr_offset, JSGraph* jsgraph, 441cb0ef41Sopenharmony_ci CallFrequency const& invocation_frequency, 451cb0ef41Sopenharmony_ci SourcePositionTable* source_positions, int inlining_id, 461cb0ef41Sopenharmony_ci CodeKind code_kind, BytecodeGraphBuilderFlags flags, 471cb0ef41Sopenharmony_ci TickCounter* tick_counter, 481cb0ef41Sopenharmony_ci ObserveNodeInfo const& observe_node_info); 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ci BytecodeGraphBuilder(const BytecodeGraphBuilder&) = delete; 511cb0ef41Sopenharmony_ci BytecodeGraphBuilder& operator=(const BytecodeGraphBuilder&) = delete; 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci // Creates a graph by visiting bytecodes. 541cb0ef41Sopenharmony_ci void CreateGraph(); 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci private: 571cb0ef41Sopenharmony_ci class Environment; 581cb0ef41Sopenharmony_ci class OsrIteratorState; 591cb0ef41Sopenharmony_ci struct SubEnvironment; 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci void RemoveMergeEnvironmentsBeforeOffset(int limit_offset); 621cb0ef41Sopenharmony_ci void AdvanceToOsrEntryAndPeelLoops(); 631cb0ef41Sopenharmony_ci 641cb0ef41Sopenharmony_ci // Advance {bytecode_iterator} to the given offset. If possible, also advance 651cb0ef41Sopenharmony_ci // {source_position_iterator} while updating the source position table. 661cb0ef41Sopenharmony_ci void AdvanceIteratorsTo(int bytecode_offset); 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci void VisitSingleBytecode(); 691cb0ef41Sopenharmony_ci void VisitBytecodes(); 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ci // Get or create the node that represents the outer function closure. 721cb0ef41Sopenharmony_ci Node* GetFunctionClosure(); 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci // Get or create the node for this parameter index. If such a node is 751cb0ef41Sopenharmony_ci // already cached, it is returned directly and the {debug_name_hint} is 761cb0ef41Sopenharmony_ci // ignored. 771cb0ef41Sopenharmony_ci Node* GetParameter(int index, const char* debug_name_hint = nullptr); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci CodeKind code_kind() const { return code_kind_; } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci // The node representing the current feedback vector is generated once prior 821cb0ef41Sopenharmony_ci // to visiting bytecodes, and is later passed as input to other nodes that 831cb0ef41Sopenharmony_ci // may need it. 841cb0ef41Sopenharmony_ci // TODO(jgruber): Remove feedback_vector() and rename feedback_vector_node() 851cb0ef41Sopenharmony_ci // to feedback_vector() once all uses of the direct heap object reference 861cb0ef41Sopenharmony_ci // have been replaced with a Node* reference. 871cb0ef41Sopenharmony_ci void CreateFeedbackVectorNode(); 881cb0ef41Sopenharmony_ci Node* feedback_vector_node() const { 891cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(feedback_vector_node_); 901cb0ef41Sopenharmony_ci return feedback_vector_node_; 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci // Same as above for the feedback vector node. 941cb0ef41Sopenharmony_ci void CreateNativeContextNode(); 951cb0ef41Sopenharmony_ci Node* native_context_node() const { 961cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(native_context_node_); 971cb0ef41Sopenharmony_ci return native_context_node_; 981cb0ef41Sopenharmony_ci } 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci Node* BuildLoadFeedbackCell(int index); 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci // Builder for loading a native context field. 1031cb0ef41Sopenharmony_ci Node* BuildLoadNativeContextField(int index); 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci // Helper function for creating a feedback source containing type feedback 1061cb0ef41Sopenharmony_ci // vector and a feedback slot. 1071cb0ef41Sopenharmony_ci FeedbackSource CreateFeedbackSource(int slot_id); 1081cb0ef41Sopenharmony_ci FeedbackSource CreateFeedbackSource(FeedbackSlot slot); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci void set_environment(Environment* env) { environment_ = env; } 1111cb0ef41Sopenharmony_ci const Environment* environment() const { return environment_; } 1121cb0ef41Sopenharmony_ci Environment* environment() { return environment_; } 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci // Node creation helpers 1151cb0ef41Sopenharmony_ci Node* NewNode(const Operator* op, bool incomplete = false) { 1161cb0ef41Sopenharmony_ci return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete); 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci template <class... Args> 1201cb0ef41Sopenharmony_ci Node* NewNode(const Operator* op, Node* n0, Args... nodes) { 1211cb0ef41Sopenharmony_ci Node* buffer[] = {n0, nodes...}; 1221cb0ef41Sopenharmony_ci return MakeNode(op, arraysize(buffer), buffer); 1231cb0ef41Sopenharmony_ci } 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci // Helpers to create new control nodes. 1261cb0ef41Sopenharmony_ci Node* NewIfTrue() { return NewNode(common()->IfTrue()); } 1271cb0ef41Sopenharmony_ci Node* NewIfFalse() { return NewNode(common()->IfFalse()); } 1281cb0ef41Sopenharmony_ci Node* NewIfValue(int32_t value) { return NewNode(common()->IfValue(value)); } 1291cb0ef41Sopenharmony_ci Node* NewIfDefault() { return NewNode(common()->IfDefault()); } 1301cb0ef41Sopenharmony_ci Node* NewMerge() { return NewNode(common()->Merge(1), true); } 1311cb0ef41Sopenharmony_ci Node* NewLoop() { return NewNode(common()->Loop(1), true); } 1321cb0ef41Sopenharmony_ci Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) { 1331cb0ef41Sopenharmony_ci return NewNode(common()->Branch(hint), condition); 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci Node* NewSwitch(Node* condition, int control_output_count) { 1361cb0ef41Sopenharmony_ci return NewNode(common()->Switch(control_output_count), condition); 1371cb0ef41Sopenharmony_ci } 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci // Creates a new Phi node having {count} input values. 1401cb0ef41Sopenharmony_ci Node* NewPhi(int count, Node* input, Node* control); 1411cb0ef41Sopenharmony_ci Node* NewEffectPhi(int count, Node* input, Node* control); 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci // Helpers for merging control, effect or value dependencies. 1441cb0ef41Sopenharmony_ci Node* MergeControl(Node* control, Node* other); 1451cb0ef41Sopenharmony_ci Node* MergeEffect(Node* effect, Node* other_effect, Node* control); 1461cb0ef41Sopenharmony_ci Node* MergeValue(Node* value, Node* other_value, Node* control); 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci // The main node creation chokepoint. Adds context, frame state, effect, 1491cb0ef41Sopenharmony_ci // and control dependencies depending on the operator. 1501cb0ef41Sopenharmony_ci Node* MakeNode(const Operator* op, int value_input_count, 1511cb0ef41Sopenharmony_ci Node* const* value_inputs, bool incomplete = false); 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci Node** EnsureInputBufferSize(int size); 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci Node* const* GetCallArgumentsFromRegisters(Node* callee, Node* receiver, 1561cb0ef41Sopenharmony_ci interpreter::Register first_arg, 1571cb0ef41Sopenharmony_ci int arg_count); 1581cb0ef41Sopenharmony_ci Node* const* ProcessCallVarArgs(ConvertReceiverMode receiver_mode, 1591cb0ef41Sopenharmony_ci Node* callee, interpreter::Register first_reg, 1601cb0ef41Sopenharmony_ci int arg_count); 1611cb0ef41Sopenharmony_ci Node* const* GetConstructArgumentsFromRegister( 1621cb0ef41Sopenharmony_ci Node* target, Node* new_target, interpreter::Register first_arg, 1631cb0ef41Sopenharmony_ci int arg_count); 1641cb0ef41Sopenharmony_ci Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op, 1651cb0ef41Sopenharmony_ci interpreter::Register receiver, 1661cb0ef41Sopenharmony_ci size_t reg_count); 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci // Prepare information for eager deoptimization. This information is carried 1691cb0ef41Sopenharmony_ci // by dedicated {Checkpoint} nodes that are wired into the effect chain. 1701cb0ef41Sopenharmony_ci // Conceptually this frame state is "before" a given operation. 1711cb0ef41Sopenharmony_ci void PrepareEagerCheckpoint(); 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci // Prepare information for lazy deoptimization. This information is attached 1741cb0ef41Sopenharmony_ci // to the given node and the output value produced by the node is combined. 1751cb0ef41Sopenharmony_ci // 1761cb0ef41Sopenharmony_ci // The low-level chokepoint - use the variants below instead. 1771cb0ef41Sopenharmony_ci void PrepareFrameState(Node* node, OutputFrameStateCombine combine, 1781cb0ef41Sopenharmony_ci BytecodeOffset bailout_id, 1791cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness); 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci // In the common case, frame states are conceptually "after" a given 1821cb0ef41Sopenharmony_ci // operation and at the current bytecode offset. 1831cb0ef41Sopenharmony_ci void PrepareFrameState(Node* node, OutputFrameStateCombine combine) { 1841cb0ef41Sopenharmony_ci if (!OperatorProperties::HasFrameStateInput(node->op())) return; 1851cb0ef41Sopenharmony_ci const int offset = bytecode_iterator().current_offset(); 1861cb0ef41Sopenharmony_ci return PrepareFrameState(node, combine, BytecodeOffset(offset), 1871cb0ef41Sopenharmony_ci bytecode_analysis().GetOutLivenessFor(offset)); 1881cb0ef41Sopenharmony_ci } 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci // For function-entry stack checks, they're conceptually "before" the first 1911cb0ef41Sopenharmony_ci // bytecode and at a special marker bytecode offset. 1921cb0ef41Sopenharmony_ci // In the case of FE stack checks, the current bytecode is also the first 1931cb0ef41Sopenharmony_ci // bytecode, so we use a special marker bytecode offset to signify a virtual 1941cb0ef41Sopenharmony_ci // bytecode before the first physical bytecode. 1951cb0ef41Sopenharmony_ci void PrepareFrameStateForFunctionEntryStackCheck(Node* node) { 1961cb0ef41Sopenharmony_ci DCHECK_EQ(bytecode_iterator().current_offset(), 0); 1971cb0ef41Sopenharmony_ci DCHECK(OperatorProperties::HasFrameStateInput(node->op())); 1981cb0ef41Sopenharmony_ci DCHECK(node->opcode() == IrOpcode::kJSStackCheck); 1991cb0ef41Sopenharmony_ci return PrepareFrameState(node, OutputFrameStateCombine::Ignore(), 2001cb0ef41Sopenharmony_ci BytecodeOffset(kFunctionEntryBytecodeOffset), 2011cb0ef41Sopenharmony_ci bytecode_analysis().GetInLivenessFor(0)); 2021cb0ef41Sopenharmony_ci } 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci // For OSR-entry stack checks, they're conceptually "before" the first 2051cb0ef41Sopenharmony_ci // bytecode of the current loop. We implement this in a similar manner to 2061cb0ef41Sopenharmony_ci // function-entry (FE) stack checks above, i.e. we deopt at the predecessor 2071cb0ef41Sopenharmony_ci // of the current bytecode. 2081cb0ef41Sopenharmony_ci // In the case of OSR-entry stack checks, a physical predecessor bytecode 2091cb0ef41Sopenharmony_ci // exists: the JumpLoop bytecode. We attach to JumpLoop by using 2101cb0ef41Sopenharmony_ci // `bytecode_analysis().osr_bailout_id()` instead of current_offset (the 2111cb0ef41Sopenharmony_ci // former points at JumpLoop, the latter at the loop header, i.e. the target 2121cb0ef41Sopenharmony_ci // of JumpLoop). 2131cb0ef41Sopenharmony_ci void PrepareFrameStateForOSREntryStackCheck(Node* node) { 2141cb0ef41Sopenharmony_ci DCHECK(OperatorProperties::HasFrameStateInput(node->op())); 2151cb0ef41Sopenharmony_ci DCHECK(node->opcode() == IrOpcode::kJSStackCheck); 2161cb0ef41Sopenharmony_ci const int offset = bytecode_analysis().osr_bailout_id().ToInt(); 2171cb0ef41Sopenharmony_ci return PrepareFrameState(node, OutputFrameStateCombine::Ignore(), 2181cb0ef41Sopenharmony_ci BytecodeOffset(offset), 2191cb0ef41Sopenharmony_ci bytecode_analysis().GetOutLivenessFor(offset)); 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci void BuildCreateArguments(CreateArgumentsType type); 2231cb0ef41Sopenharmony_ci Node* BuildLoadGlobal(NameRef name, uint32_t feedback_slot_index, 2241cb0ef41Sopenharmony_ci TypeofMode typeof_mode); 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci enum class NamedStoreMode { 2271cb0ef41Sopenharmony_ci // Check the prototype chain before storing. 2281cb0ef41Sopenharmony_ci kSet, 2291cb0ef41Sopenharmony_ci // Define value to the receiver without checking the prototype chain. 2301cb0ef41Sopenharmony_ci kDefineOwn, 2311cb0ef41Sopenharmony_ci }; 2321cb0ef41Sopenharmony_ci void BuildNamedStore(NamedStoreMode store_mode); 2331cb0ef41Sopenharmony_ci void BuildLdaLookupSlot(TypeofMode typeof_mode); 2341cb0ef41Sopenharmony_ci void BuildLdaLookupContextSlot(TypeofMode typeof_mode); 2351cb0ef41Sopenharmony_ci void BuildLdaLookupGlobalSlot(TypeofMode typeof_mode); 2361cb0ef41Sopenharmony_ci void BuildCallVarArgs(ConvertReceiverMode receiver_mode); 2371cb0ef41Sopenharmony_ci void BuildCall(ConvertReceiverMode receiver_mode, Node* const* args, 2381cb0ef41Sopenharmony_ci size_t arg_count, int slot_id); 2391cb0ef41Sopenharmony_ci void BuildCall(ConvertReceiverMode receiver_mode, 2401cb0ef41Sopenharmony_ci std::initializer_list<Node*> args, int slot_id) { 2411cb0ef41Sopenharmony_ci BuildCall(receiver_mode, args.begin(), args.size(), slot_id); 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci void BuildUnaryOp(const Operator* op); 2441cb0ef41Sopenharmony_ci void BuildBinaryOp(const Operator* op); 2451cb0ef41Sopenharmony_ci void BuildBinaryOpWithImmediate(const Operator* op); 2461cb0ef41Sopenharmony_ci void BuildCompareOp(const Operator* op); 2471cb0ef41Sopenharmony_ci void BuildDelete(LanguageMode language_mode); 2481cb0ef41Sopenharmony_ci void BuildCastOperator(const Operator* op); 2491cb0ef41Sopenharmony_ci void BuildHoleCheckAndThrow(Node* condition, Runtime::FunctionId runtime_id, 2501cb0ef41Sopenharmony_ci Node* name = nullptr); 2511cb0ef41Sopenharmony_ci 2521cb0ef41Sopenharmony_ci // Optional early lowering to the simplified operator level. Note that 2531cb0ef41Sopenharmony_ci // the result has already been wired into the environment just like 2541cb0ef41Sopenharmony_ci // any other invocation of {NewNode} would do. 2551cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedUnaryOp( 2561cb0ef41Sopenharmony_ci const Operator* op, Node* operand, FeedbackSlot slot); 2571cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedBinaryOp( 2581cb0ef41Sopenharmony_ci const Operator* op, Node* left, Node* right, FeedbackSlot slot); 2591cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedForInNext( 2601cb0ef41Sopenharmony_ci Node* receiver, Node* cache_array, Node* cache_type, Node* index, 2611cb0ef41Sopenharmony_ci FeedbackSlot slot); 2621cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedForInPrepare( 2631cb0ef41Sopenharmony_ci Node* receiver, FeedbackSlot slot); 2641cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedToNumber( 2651cb0ef41Sopenharmony_ci Node* input, FeedbackSlot slot); 2661cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedCall(const Operator* op, 2671cb0ef41Sopenharmony_ci Node* const* args, 2681cb0ef41Sopenharmony_ci int arg_count, 2691cb0ef41Sopenharmony_ci FeedbackSlot slot); 2701cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedConstruct( 2711cb0ef41Sopenharmony_ci const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot); 2721cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedGetIterator( 2731cb0ef41Sopenharmony_ci const Operator* op, Node* receiver, FeedbackSlot load_slot, 2741cb0ef41Sopenharmony_ci FeedbackSlot call_slot); 2751cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedLoadNamed( 2761cb0ef41Sopenharmony_ci const Operator* op, FeedbackSlot slot); 2771cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedLoadKeyed( 2781cb0ef41Sopenharmony_ci const Operator* op, Node* receiver, Node* key, FeedbackSlot slot); 2791cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedStoreNamed( 2801cb0ef41Sopenharmony_ci const Operator* op, Node* receiver, Node* value, FeedbackSlot slot); 2811cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult TryBuildSimplifiedStoreKeyed( 2821cb0ef41Sopenharmony_ci const Operator* op, Node* receiver, Node* key, Node* value, 2831cb0ef41Sopenharmony_ci FeedbackSlot slot); 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci // Applies the given early reduction onto the current environment. 2861cb0ef41Sopenharmony_ci void ApplyEarlyReduction(JSTypeHintLowering::LoweringResult reduction); 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_ci // Check the context chain for extensions, for lookup fast paths. 2891cb0ef41Sopenharmony_ci Environment* CheckContextExtensions(uint32_t depth); 2901cb0ef41Sopenharmony_ci // Slow path taken when we cannot figure out the current scope info. 2911cb0ef41Sopenharmony_ci Environment* CheckContextExtensionsSlowPath(uint32_t depth); 2921cb0ef41Sopenharmony_ci // Helper function that tries to get the current scope info. 2931cb0ef41Sopenharmony_ci base::Optional<ScopeInfoRef> TryGetScopeInfo(); 2941cb0ef41Sopenharmony_ci // Helper function to create a context extension check. 2951cb0ef41Sopenharmony_ci Environment* CheckContextExtensionAtDepth(Environment* slow_environment, 2961cb0ef41Sopenharmony_ci uint32_t depth); 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci // Helper function to create for-in mode from the recorded type feedback. 2991cb0ef41Sopenharmony_ci ForInMode GetForInMode(FeedbackSlot slot); 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci // Helper function to compute call frequency from the recorded type 3021cb0ef41Sopenharmony_ci // feedback. Returns unknown if invocation count is unknown. Returns 0 if 3031cb0ef41Sopenharmony_ci // feedback is insufficient. 3041cb0ef41Sopenharmony_ci CallFrequency ComputeCallFrequency(int slot_id) const; 3051cb0ef41Sopenharmony_ci 3061cb0ef41Sopenharmony_ci // Helper function to extract the speculation mode from the recorded type 3071cb0ef41Sopenharmony_ci // feedback. Returns kDisallowSpeculation if feedback is insufficient. 3081cb0ef41Sopenharmony_ci SpeculationMode GetSpeculationMode(int slot_id) const; 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci // Helper function to determine the call feedback relation from the recorded 3111cb0ef41Sopenharmony_ci // type feedback. Returns kUnrelated if feedback is insufficient. 3121cb0ef41Sopenharmony_ci CallFeedbackRelation ComputeCallFeedbackRelation(int slot_id) const; 3131cb0ef41Sopenharmony_ci 3141cb0ef41Sopenharmony_ci // Helpers for building the implicit FunctionEntry and IterationBody 3151cb0ef41Sopenharmony_ci // StackChecks. 3161cb0ef41Sopenharmony_ci void BuildFunctionEntryStackCheck(); 3171cb0ef41Sopenharmony_ci void BuildIterationBodyStackCheck(); 3181cb0ef41Sopenharmony_ci void BuildOSREntryStackCheck(); 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci // Control flow plumbing. 3211cb0ef41Sopenharmony_ci void BuildJump(); 3221cb0ef41Sopenharmony_ci void BuildJumpIf(Node* condition); 3231cb0ef41Sopenharmony_ci void BuildJumpIfNot(Node* condition); 3241cb0ef41Sopenharmony_ci void BuildJumpIfEqual(Node* comperand); 3251cb0ef41Sopenharmony_ci void BuildJumpIfNotEqual(Node* comperand); 3261cb0ef41Sopenharmony_ci void BuildJumpIfTrue(); 3271cb0ef41Sopenharmony_ci void BuildJumpIfFalse(); 3281cb0ef41Sopenharmony_ci void BuildJumpIfToBooleanTrue(); 3291cb0ef41Sopenharmony_ci void BuildJumpIfToBooleanFalse(); 3301cb0ef41Sopenharmony_ci void BuildJumpIfNotHole(); 3311cb0ef41Sopenharmony_ci void BuildJumpIfJSReceiver(); 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci void BuildSwitchOnSmi(Node* condition); 3341cb0ef41Sopenharmony_ci void BuildSwitchOnGeneratorState( 3351cb0ef41Sopenharmony_ci const ZoneVector<ResumeJumpTarget>& resume_jump_targets, 3361cb0ef41Sopenharmony_ci bool allow_fallthrough_on_executing); 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ci // Simulates control flow by forward-propagating environments. 3391cb0ef41Sopenharmony_ci void MergeIntoSuccessorEnvironment(int target_offset); 3401cb0ef41Sopenharmony_ci void BuildLoopHeaderEnvironment(int current_offset); 3411cb0ef41Sopenharmony_ci void SwitchToMergeEnvironment(int current_offset); 3421cb0ef41Sopenharmony_ci 3431cb0ef41Sopenharmony_ci // Simulates control flow that exits the function body. 3441cb0ef41Sopenharmony_ci void MergeControlToLeaveFunction(Node* exit); 3451cb0ef41Sopenharmony_ci 3461cb0ef41Sopenharmony_ci // Builds loop exit nodes for every exited loop between the current bytecode 3471cb0ef41Sopenharmony_ci // offset and {target_offset}. 3481cb0ef41Sopenharmony_ci void BuildLoopExitsForBranch(int target_offset); 3491cb0ef41Sopenharmony_ci void BuildLoopExitsForFunctionExit(const BytecodeLivenessState* liveness); 3501cb0ef41Sopenharmony_ci void BuildLoopExitsUntilLoop(int loop_offset, 3511cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness); 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci // Helper for building a return (from an actual return or a suspend). 3541cb0ef41Sopenharmony_ci void BuildReturn(const BytecodeLivenessState* liveness); 3551cb0ef41Sopenharmony_ci 3561cb0ef41Sopenharmony_ci // Simulates entry and exit of exception handlers. 3571cb0ef41Sopenharmony_ci void ExitThenEnterExceptionHandlers(int current_offset); 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci // Update the current position of the {SourcePositionTable} to that of the 3601cb0ef41Sopenharmony_ci // bytecode at {offset}, if any. 3611cb0ef41Sopenharmony_ci void UpdateSourcePosition(int offset); 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_ci // Growth increment for the temporary buffer used to construct input lists to 3641cb0ef41Sopenharmony_ci // new nodes. 3651cb0ef41Sopenharmony_ci static const int kInputBufferSizeIncrement = 64; 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci // An abstract representation for an exception handler that is being 3681cb0ef41Sopenharmony_ci // entered and exited while the graph builder is iterating over the 3691cb0ef41Sopenharmony_ci // underlying bytecode. The exception handlers within the bytecode are 3701cb0ef41Sopenharmony_ci // well scoped, hence will form a stack during iteration. 3711cb0ef41Sopenharmony_ci struct ExceptionHandler { 3721cb0ef41Sopenharmony_ci int start_offset_; // Start offset of the handled area in the bytecode. 3731cb0ef41Sopenharmony_ci int end_offset_; // End offset of the handled area in the bytecode. 3741cb0ef41Sopenharmony_ci int handler_offset_; // Handler entry offset within the bytecode. 3751cb0ef41Sopenharmony_ci int context_register_; // Index of register holding handler context. 3761cb0ef41Sopenharmony_ci }; 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci template <class T = Object> 3791cb0ef41Sopenharmony_ci typename ref_traits<T>::ref_type MakeRefForConstantForIndexOperand( 3801cb0ef41Sopenharmony_ci int operand_index) { 3811cb0ef41Sopenharmony_ci // The BytecodeArray itself was fetched by using a barrier so all reads 3821cb0ef41Sopenharmony_ci // from the constant pool are safe. 3831cb0ef41Sopenharmony_ci return MakeRefAssumeMemoryFence( 3841cb0ef41Sopenharmony_ci broker(), broker()->CanonicalPersistentHandle(Handle<T>::cast( 3851cb0ef41Sopenharmony_ci bytecode_iterator().GetConstantForIndexOperand( 3861cb0ef41Sopenharmony_ci operand_index, local_isolate_)))); 3871cb0ef41Sopenharmony_ci } 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ci Graph* graph() const { return jsgraph_->graph(); } 3901cb0ef41Sopenharmony_ci CommonOperatorBuilder* common() const { return jsgraph_->common(); } 3911cb0ef41Sopenharmony_ci Zone* graph_zone() const { return graph()->zone(); } 3921cb0ef41Sopenharmony_ci JSGraph* jsgraph() const { return jsgraph_; } 3931cb0ef41Sopenharmony_ci Isolate* isolate() const { return jsgraph_->isolate(); } 3941cb0ef41Sopenharmony_ci JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); } 3951cb0ef41Sopenharmony_ci SimplifiedOperatorBuilder* simplified() const { 3961cb0ef41Sopenharmony_ci return jsgraph_->simplified(); 3971cb0ef41Sopenharmony_ci } 3981cb0ef41Sopenharmony_ci Zone* local_zone() const { return local_zone_; } 3991cb0ef41Sopenharmony_ci BytecodeArrayRef bytecode_array() const { return bytecode_array_; } 4001cb0ef41Sopenharmony_ci FeedbackVectorRef const& feedback_vector() const { return feedback_vector_; } 4011cb0ef41Sopenharmony_ci const JSTypeHintLowering& type_hint_lowering() const { 4021cb0ef41Sopenharmony_ci return type_hint_lowering_; 4031cb0ef41Sopenharmony_ci } 4041cb0ef41Sopenharmony_ci const FrameStateFunctionInfo* frame_state_function_info() const { 4051cb0ef41Sopenharmony_ci return frame_state_function_info_; 4061cb0ef41Sopenharmony_ci } 4071cb0ef41Sopenharmony_ci SourcePositionTableIterator& source_position_iterator() { 4081cb0ef41Sopenharmony_ci return *source_position_iterator_.get(); 4091cb0ef41Sopenharmony_ci } 4101cb0ef41Sopenharmony_ci interpreter::BytecodeArrayIterator const& bytecode_iterator() const { 4111cb0ef41Sopenharmony_ci return bytecode_iterator_; 4121cb0ef41Sopenharmony_ci } 4131cb0ef41Sopenharmony_ci interpreter::BytecodeArrayIterator& bytecode_iterator() { 4141cb0ef41Sopenharmony_ci return bytecode_iterator_; 4151cb0ef41Sopenharmony_ci } 4161cb0ef41Sopenharmony_ci BytecodeAnalysis const& bytecode_analysis() const { 4171cb0ef41Sopenharmony_ci return bytecode_analysis_; 4181cb0ef41Sopenharmony_ci } 4191cb0ef41Sopenharmony_ci int currently_peeled_loop_offset() const { 4201cb0ef41Sopenharmony_ci return currently_peeled_loop_offset_; 4211cb0ef41Sopenharmony_ci } 4221cb0ef41Sopenharmony_ci void set_currently_peeled_loop_offset(int offset) { 4231cb0ef41Sopenharmony_ci currently_peeled_loop_offset_ = offset; 4241cb0ef41Sopenharmony_ci } 4251cb0ef41Sopenharmony_ci bool skip_first_stack_check() const { 4261cb0ef41Sopenharmony_ci return skip_first_stack_and_tierup_check_; 4271cb0ef41Sopenharmony_ci } 4281cb0ef41Sopenharmony_ci bool skip_tierup_check() const { 4291cb0ef41Sopenharmony_ci return skip_first_stack_and_tierup_check_ || osr_; 4301cb0ef41Sopenharmony_ci } 4311cb0ef41Sopenharmony_ci int current_exception_handler() const { return current_exception_handler_; } 4321cb0ef41Sopenharmony_ci void set_current_exception_handler(int index) { 4331cb0ef41Sopenharmony_ci current_exception_handler_ = index; 4341cb0ef41Sopenharmony_ci } 4351cb0ef41Sopenharmony_ci bool needs_eager_checkpoint() const { return needs_eager_checkpoint_; } 4361cb0ef41Sopenharmony_ci void mark_as_needing_eager_checkpoint(bool value) { 4371cb0ef41Sopenharmony_ci needs_eager_checkpoint_ = value; 4381cb0ef41Sopenharmony_ci } 4391cb0ef41Sopenharmony_ci JSHeapBroker* broker() const { return broker_; } 4401cb0ef41Sopenharmony_ci NativeContextRef native_context() const { return native_context_; } 4411cb0ef41Sopenharmony_ci SharedFunctionInfoRef shared_info() const { return shared_info_; } 4421cb0ef41Sopenharmony_ci 4431cb0ef41Sopenharmony_ci#define DECLARE_VISIT_BYTECODE(name, ...) void Visit##name(); 4441cb0ef41Sopenharmony_ci BYTECODE_LIST(DECLARE_VISIT_BYTECODE) 4451cb0ef41Sopenharmony_ci#undef DECLARE_VISIT_BYTECODE 4461cb0ef41Sopenharmony_ci 4471cb0ef41Sopenharmony_ci JSHeapBroker* const broker_; 4481cb0ef41Sopenharmony_ci LocalIsolate* const local_isolate_; 4491cb0ef41Sopenharmony_ci Zone* const local_zone_; 4501cb0ef41Sopenharmony_ci JSGraph* const jsgraph_; 4511cb0ef41Sopenharmony_ci // The native context for which we optimize. 4521cb0ef41Sopenharmony_ci NativeContextRef const native_context_; 4531cb0ef41Sopenharmony_ci SharedFunctionInfoRef const shared_info_; 4541cb0ef41Sopenharmony_ci BytecodeArrayRef const bytecode_array_; 4551cb0ef41Sopenharmony_ci FeedbackCellRef const feedback_cell_; 4561cb0ef41Sopenharmony_ci FeedbackVectorRef const feedback_vector_; 4571cb0ef41Sopenharmony_ci CallFrequency const invocation_frequency_; 4581cb0ef41Sopenharmony_ci JSTypeHintLowering const type_hint_lowering_; 4591cb0ef41Sopenharmony_ci const FrameStateFunctionInfo* const frame_state_function_info_; 4601cb0ef41Sopenharmony_ci std::unique_ptr<SourcePositionTableIterator> source_position_iterator_; 4611cb0ef41Sopenharmony_ci interpreter::BytecodeArrayIterator bytecode_iterator_; 4621cb0ef41Sopenharmony_ci BytecodeAnalysis const bytecode_analysis_; 4631cb0ef41Sopenharmony_ci Environment* environment_; 4641cb0ef41Sopenharmony_ci bool const osr_; 4651cb0ef41Sopenharmony_ci int currently_peeled_loop_offset_; 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_ci const bool skip_first_stack_and_tierup_check_; 4681cb0ef41Sopenharmony_ci 4691cb0ef41Sopenharmony_ci // Merge environments are snapshots of the environment at points where the 4701cb0ef41Sopenharmony_ci // control flow merges. This models a forward data flow propagation of all 4711cb0ef41Sopenharmony_ci // values from all predecessors of the merge in question. They are indexed by 4721cb0ef41Sopenharmony_ci // the bytecode offset 4731cb0ef41Sopenharmony_ci ZoneMap<int, Environment*> merge_environments_; 4741cb0ef41Sopenharmony_ci 4751cb0ef41Sopenharmony_ci // Generator merge environments are snapshots of the current resume 4761cb0ef41Sopenharmony_ci // environment, tracing back through loop headers to the resume switch of a 4771cb0ef41Sopenharmony_ci // generator. They allow us to model a single resume jump as several switch 4781cb0ef41Sopenharmony_ci // statements across loop headers, keeping those loop headers reducible, 4791cb0ef41Sopenharmony_ci // without having to merge the "executing" environments of the generator into 4801cb0ef41Sopenharmony_ci // the "resuming" ones. They are indexed by the suspend id of the resume. 4811cb0ef41Sopenharmony_ci ZoneMap<int, Environment*> generator_merge_environments_; 4821cb0ef41Sopenharmony_ci 4831cb0ef41Sopenharmony_ci ZoneVector<Node*> cached_parameters_; 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_ci // Exception handlers currently entered by the iteration. 4861cb0ef41Sopenharmony_ci ZoneStack<ExceptionHandler> exception_handlers_; 4871cb0ef41Sopenharmony_ci int current_exception_handler_; 4881cb0ef41Sopenharmony_ci 4891cb0ef41Sopenharmony_ci // Temporary storage for building node input lists. 4901cb0ef41Sopenharmony_ci int input_buffer_size_; 4911cb0ef41Sopenharmony_ci Node** input_buffer_; 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci const CodeKind code_kind_; 4941cb0ef41Sopenharmony_ci Node* feedback_vector_node_; 4951cb0ef41Sopenharmony_ci Node* native_context_node_; 4961cb0ef41Sopenharmony_ci 4971cb0ef41Sopenharmony_ci // Optimization to only create checkpoints when the current position in the 4981cb0ef41Sopenharmony_ci // control-flow is not effect-dominated by another checkpoint already. All 4991cb0ef41Sopenharmony_ci // operations that do not have observable side-effects can be re-evaluated. 5001cb0ef41Sopenharmony_ci bool needs_eager_checkpoint_; 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_ci // Nodes representing values in the activation record. 5031cb0ef41Sopenharmony_ci SetOncePointer<Node> function_closure_; 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_ci // Control nodes that exit the function body. 5061cb0ef41Sopenharmony_ci ZoneVector<Node*> exit_controls_; 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ci StateValuesCache state_values_cache_; 5091cb0ef41Sopenharmony_ci 5101cb0ef41Sopenharmony_ci // The source position table, to be populated. 5111cb0ef41Sopenharmony_ci SourcePositionTable* const source_positions_; 5121cb0ef41Sopenharmony_ci 5131cb0ef41Sopenharmony_ci SourcePosition const start_position_; 5141cb0ef41Sopenharmony_ci 5151cb0ef41Sopenharmony_ci TickCounter* const tick_counter_; 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci ObserveNodeInfo const observe_node_info_; 5181cb0ef41Sopenharmony_ci 5191cb0ef41Sopenharmony_ci static constexpr int kBinaryOperationHintIndex = 1; 5201cb0ef41Sopenharmony_ci static constexpr int kBinaryOperationSmiHintIndex = 1; 5211cb0ef41Sopenharmony_ci static constexpr int kCompareOperationHintIndex = 1; 5221cb0ef41Sopenharmony_ci static constexpr int kCountOperationHintIndex = 0; 5231cb0ef41Sopenharmony_ci static constexpr int kUnaryOperationHintIndex = 0; 5241cb0ef41Sopenharmony_ci}; 5251cb0ef41Sopenharmony_ci 5261cb0ef41Sopenharmony_ci// The abstract execution environment simulates the content of the interpreter 5271cb0ef41Sopenharmony_ci// register file. The environment performs SSA-renaming of all tracked nodes at 5281cb0ef41Sopenharmony_ci// split and merge points in the control flow. 5291cb0ef41Sopenharmony_ciclass BytecodeGraphBuilder::Environment : public ZoneObject { 5301cb0ef41Sopenharmony_ci public: 5311cb0ef41Sopenharmony_ci Environment(BytecodeGraphBuilder* builder, int register_count, 5321cb0ef41Sopenharmony_ci int parameter_count, 5331cb0ef41Sopenharmony_ci interpreter::Register incoming_new_target_or_generator, 5341cb0ef41Sopenharmony_ci Node* control_dependency); 5351cb0ef41Sopenharmony_ci 5361cb0ef41Sopenharmony_ci // Specifies whether environment binding methods should attach frame state 5371cb0ef41Sopenharmony_ci // inputs to nodes representing the value being bound. This is done because 5381cb0ef41Sopenharmony_ci // the {OutputFrameStateCombine} is closely related to the binding method. 5391cb0ef41Sopenharmony_ci enum FrameStateAttachmentMode { kAttachFrameState, kDontAttachFrameState }; 5401cb0ef41Sopenharmony_ci 5411cb0ef41Sopenharmony_ci int parameter_count() const { return parameter_count_; } 5421cb0ef41Sopenharmony_ci int register_count() const { return register_count_; } 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_ci Node* LookupAccumulator() const; 5451cb0ef41Sopenharmony_ci Node* LookupRegister(interpreter::Register the_register) const; 5461cb0ef41Sopenharmony_ci Node* LookupGeneratorState() const; 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_ci void BindAccumulator(Node* node, 5491cb0ef41Sopenharmony_ci FrameStateAttachmentMode mode = kDontAttachFrameState); 5501cb0ef41Sopenharmony_ci void BindRegister(interpreter::Register the_register, Node* node, 5511cb0ef41Sopenharmony_ci FrameStateAttachmentMode mode = kDontAttachFrameState); 5521cb0ef41Sopenharmony_ci void BindRegistersToProjections( 5531cb0ef41Sopenharmony_ci interpreter::Register first_reg, Node* node, 5541cb0ef41Sopenharmony_ci FrameStateAttachmentMode mode = kDontAttachFrameState); 5551cb0ef41Sopenharmony_ci void BindGeneratorState(Node* node); 5561cb0ef41Sopenharmony_ci void RecordAfterState(Node* node, 5571cb0ef41Sopenharmony_ci FrameStateAttachmentMode mode = kDontAttachFrameState); 5581cb0ef41Sopenharmony_ci 5591cb0ef41Sopenharmony_ci // Effect dependency tracked by this environment. 5601cb0ef41Sopenharmony_ci Node* GetEffectDependency() { return effect_dependency_; } 5611cb0ef41Sopenharmony_ci void UpdateEffectDependency(Node* dependency) { 5621cb0ef41Sopenharmony_ci effect_dependency_ = dependency; 5631cb0ef41Sopenharmony_ci } 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci // Preserve a checkpoint of the environment for the IR graph. Any 5661cb0ef41Sopenharmony_ci // further mutation of the environment will not affect checkpoints. 5671cb0ef41Sopenharmony_ci Node* Checkpoint(BytecodeOffset bytecode_offset, 5681cb0ef41Sopenharmony_ci OutputFrameStateCombine combine, 5691cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness); 5701cb0ef41Sopenharmony_ci 5711cb0ef41Sopenharmony_ci // Control dependency tracked by this environment. 5721cb0ef41Sopenharmony_ci Node* GetControlDependency() const { return control_dependency_; } 5731cb0ef41Sopenharmony_ci void UpdateControlDependency(Node* dependency) { 5741cb0ef41Sopenharmony_ci control_dependency_ = dependency; 5751cb0ef41Sopenharmony_ci } 5761cb0ef41Sopenharmony_ci 5771cb0ef41Sopenharmony_ci Node* Context() const { return context_; } 5781cb0ef41Sopenharmony_ci void SetContext(Node* new_context) { context_ = new_context; } 5791cb0ef41Sopenharmony_ci 5801cb0ef41Sopenharmony_ci Environment* Copy(); 5811cb0ef41Sopenharmony_ci void Merge(Environment* other, const BytecodeLivenessState* liveness); 5821cb0ef41Sopenharmony_ci 5831cb0ef41Sopenharmony_ci void FillWithOsrValues(); 5841cb0ef41Sopenharmony_ci void PrepareForLoop(const BytecodeLoopAssignments& assignments, 5851cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness); 5861cb0ef41Sopenharmony_ci void PrepareForLoopExit(Node* loop, 5871cb0ef41Sopenharmony_ci const BytecodeLoopAssignments& assignments, 5881cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness); 5891cb0ef41Sopenharmony_ci 5901cb0ef41Sopenharmony_ci private: 5911cb0ef41Sopenharmony_ci friend Zone; 5921cb0ef41Sopenharmony_ci 5931cb0ef41Sopenharmony_ci explicit Environment(const Environment* copy); 5941cb0ef41Sopenharmony_ci 5951cb0ef41Sopenharmony_ci bool StateValuesRequireUpdate(Node** state_values, Node** values, int count); 5961cb0ef41Sopenharmony_ci void UpdateStateValues(Node** state_values, Node** values, int count); 5971cb0ef41Sopenharmony_ci Node* GetStateValuesFromCache(Node** values, int count, 5981cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness); 5991cb0ef41Sopenharmony_ci 6001cb0ef41Sopenharmony_ci int RegisterToValuesIndex(interpreter::Register the_register) const; 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ci Zone* zone() const { return builder_->local_zone(); } 6031cb0ef41Sopenharmony_ci Graph* graph() const { return builder_->graph(); } 6041cb0ef41Sopenharmony_ci CommonOperatorBuilder* common() const { return builder_->common(); } 6051cb0ef41Sopenharmony_ci BytecodeGraphBuilder* builder() const { return builder_; } 6061cb0ef41Sopenharmony_ci const NodeVector* values() const { return &values_; } 6071cb0ef41Sopenharmony_ci NodeVector* values() { return &values_; } 6081cb0ef41Sopenharmony_ci int register_base() const { return register_base_; } 6091cb0ef41Sopenharmony_ci int accumulator_base() const { return accumulator_base_; } 6101cb0ef41Sopenharmony_ci 6111cb0ef41Sopenharmony_ci BytecodeGraphBuilder* builder_; 6121cb0ef41Sopenharmony_ci int register_count_; 6131cb0ef41Sopenharmony_ci int parameter_count_; 6141cb0ef41Sopenharmony_ci Node* context_; 6151cb0ef41Sopenharmony_ci Node* control_dependency_; 6161cb0ef41Sopenharmony_ci Node* effect_dependency_; 6171cb0ef41Sopenharmony_ci NodeVector values_; 6181cb0ef41Sopenharmony_ci Node* parameters_state_values_; 6191cb0ef41Sopenharmony_ci Node* generator_state_; 6201cb0ef41Sopenharmony_ci int register_base_; 6211cb0ef41Sopenharmony_ci int accumulator_base_; 6221cb0ef41Sopenharmony_ci}; 6231cb0ef41Sopenharmony_ci 6241cb0ef41Sopenharmony_ci// A helper for creating a temporary sub-environment for simple branches. 6251cb0ef41Sopenharmony_cistruct BytecodeGraphBuilder::SubEnvironment final { 6261cb0ef41Sopenharmony_ci public: 6271cb0ef41Sopenharmony_ci explicit SubEnvironment(BytecodeGraphBuilder* builder) 6281cb0ef41Sopenharmony_ci : builder_(builder), parent_(builder->environment()->Copy()) {} 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_ci ~SubEnvironment() { builder_->set_environment(parent_); } 6311cb0ef41Sopenharmony_ci 6321cb0ef41Sopenharmony_ci private: 6331cb0ef41Sopenharmony_ci BytecodeGraphBuilder* builder_; 6341cb0ef41Sopenharmony_ci BytecodeGraphBuilder::Environment* parent_; 6351cb0ef41Sopenharmony_ci}; 6361cb0ef41Sopenharmony_ci 6371cb0ef41Sopenharmony_ci// Issues: 6381cb0ef41Sopenharmony_ci// - Scopes - intimately tied to AST. Need to eval what is needed. 6391cb0ef41Sopenharmony_ci// - Need to resolve closure parameter treatment. 6401cb0ef41Sopenharmony_ciBytecodeGraphBuilder::Environment::Environment( 6411cb0ef41Sopenharmony_ci BytecodeGraphBuilder* builder, int register_count, int parameter_count, 6421cb0ef41Sopenharmony_ci interpreter::Register incoming_new_target_or_generator, 6431cb0ef41Sopenharmony_ci Node* control_dependency) 6441cb0ef41Sopenharmony_ci : builder_(builder), 6451cb0ef41Sopenharmony_ci register_count_(register_count), 6461cb0ef41Sopenharmony_ci parameter_count_(parameter_count), 6471cb0ef41Sopenharmony_ci control_dependency_(control_dependency), 6481cb0ef41Sopenharmony_ci effect_dependency_(control_dependency), 6491cb0ef41Sopenharmony_ci values_(builder->local_zone()), 6501cb0ef41Sopenharmony_ci parameters_state_values_(nullptr), 6511cb0ef41Sopenharmony_ci generator_state_(nullptr) { 6521cb0ef41Sopenharmony_ci // The layout of values_ is: 6531cb0ef41Sopenharmony_ci // 6541cb0ef41Sopenharmony_ci // [receiver] [parameters] [registers] [accumulator] 6551cb0ef41Sopenharmony_ci // 6561cb0ef41Sopenharmony_ci // parameter[0] is the receiver (this), parameters 1..N are the 6571cb0ef41Sopenharmony_ci // parameters supplied to the method (arg0..argN-1). The accumulator 6581cb0ef41Sopenharmony_ci // is stored separately. 6591cb0ef41Sopenharmony_ci 6601cb0ef41Sopenharmony_ci // Parameters including the receiver 6611cb0ef41Sopenharmony_ci for (int i = 0; i < parameter_count; i++) { 6621cb0ef41Sopenharmony_ci const char* debug_name = (i == 0) ? "%this" : nullptr; 6631cb0ef41Sopenharmony_ci Node* parameter = builder->GetParameter(i, debug_name); 6641cb0ef41Sopenharmony_ci values()->push_back(parameter); 6651cb0ef41Sopenharmony_ci } 6661cb0ef41Sopenharmony_ci 6671cb0ef41Sopenharmony_ci // Registers 6681cb0ef41Sopenharmony_ci register_base_ = static_cast<int>(values()->size()); 6691cb0ef41Sopenharmony_ci Node* undefined_constant = builder->jsgraph()->UndefinedConstant(); 6701cb0ef41Sopenharmony_ci values()->insert(values()->end(), register_count, undefined_constant); 6711cb0ef41Sopenharmony_ci 6721cb0ef41Sopenharmony_ci // Accumulator 6731cb0ef41Sopenharmony_ci accumulator_base_ = static_cast<int>(values()->size()); 6741cb0ef41Sopenharmony_ci values()->push_back(undefined_constant); 6751cb0ef41Sopenharmony_ci 6761cb0ef41Sopenharmony_ci // Context 6771cb0ef41Sopenharmony_ci int context_index = Linkage::GetJSCallContextParamIndex(parameter_count); 6781cb0ef41Sopenharmony_ci context_ = builder->GetParameter(context_index, "%context"); 6791cb0ef41Sopenharmony_ci 6801cb0ef41Sopenharmony_ci // Incoming new.target or generator register 6811cb0ef41Sopenharmony_ci if (incoming_new_target_or_generator.is_valid()) { 6821cb0ef41Sopenharmony_ci int new_target_index = 6831cb0ef41Sopenharmony_ci Linkage::GetJSCallNewTargetParamIndex(parameter_count); 6841cb0ef41Sopenharmony_ci Node* new_target_node = 6851cb0ef41Sopenharmony_ci builder->GetParameter(new_target_index, "%new.target"); 6861cb0ef41Sopenharmony_ci 6871cb0ef41Sopenharmony_ci int values_index = RegisterToValuesIndex(incoming_new_target_or_generator); 6881cb0ef41Sopenharmony_ci values()->at(values_index) = new_target_node; 6891cb0ef41Sopenharmony_ci } 6901cb0ef41Sopenharmony_ci} 6911cb0ef41Sopenharmony_ci 6921cb0ef41Sopenharmony_ciBytecodeGraphBuilder::Environment::Environment( 6931cb0ef41Sopenharmony_ci const BytecodeGraphBuilder::Environment* other) 6941cb0ef41Sopenharmony_ci : builder_(other->builder_), 6951cb0ef41Sopenharmony_ci register_count_(other->register_count_), 6961cb0ef41Sopenharmony_ci parameter_count_(other->parameter_count_), 6971cb0ef41Sopenharmony_ci context_(other->context_), 6981cb0ef41Sopenharmony_ci control_dependency_(other->control_dependency_), 6991cb0ef41Sopenharmony_ci effect_dependency_(other->effect_dependency_), 7001cb0ef41Sopenharmony_ci values_(other->zone()), 7011cb0ef41Sopenharmony_ci parameters_state_values_(other->parameters_state_values_), 7021cb0ef41Sopenharmony_ci generator_state_(other->generator_state_), 7031cb0ef41Sopenharmony_ci register_base_(other->register_base_), 7041cb0ef41Sopenharmony_ci accumulator_base_(other->accumulator_base_) { 7051cb0ef41Sopenharmony_ci values_ = other->values_; 7061cb0ef41Sopenharmony_ci} 7071cb0ef41Sopenharmony_ci 7081cb0ef41Sopenharmony_ci 7091cb0ef41Sopenharmony_ciint BytecodeGraphBuilder::Environment::RegisterToValuesIndex( 7101cb0ef41Sopenharmony_ci interpreter::Register the_register) const { 7111cb0ef41Sopenharmony_ci if (the_register.is_parameter()) { 7121cb0ef41Sopenharmony_ci return the_register.ToParameterIndex(); 7131cb0ef41Sopenharmony_ci } else { 7141cb0ef41Sopenharmony_ci return the_register.index() + register_base(); 7151cb0ef41Sopenharmony_ci } 7161cb0ef41Sopenharmony_ci} 7171cb0ef41Sopenharmony_ci 7181cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::Environment::LookupAccumulator() const { 7191cb0ef41Sopenharmony_ci return values()->at(accumulator_base_); 7201cb0ef41Sopenharmony_ci} 7211cb0ef41Sopenharmony_ci 7221cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::Environment::LookupGeneratorState() const { 7231cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(generator_state_); 7241cb0ef41Sopenharmony_ci return generator_state_; 7251cb0ef41Sopenharmony_ci} 7261cb0ef41Sopenharmony_ci 7271cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::Environment::LookupRegister( 7281cb0ef41Sopenharmony_ci interpreter::Register the_register) const { 7291cb0ef41Sopenharmony_ci if (the_register.is_current_context()) { 7301cb0ef41Sopenharmony_ci return Context(); 7311cb0ef41Sopenharmony_ci } else if (the_register.is_function_closure()) { 7321cb0ef41Sopenharmony_ci return builder()->GetFunctionClosure(); 7331cb0ef41Sopenharmony_ci } else { 7341cb0ef41Sopenharmony_ci int values_index = RegisterToValuesIndex(the_register); 7351cb0ef41Sopenharmony_ci return values()->at(values_index); 7361cb0ef41Sopenharmony_ci } 7371cb0ef41Sopenharmony_ci} 7381cb0ef41Sopenharmony_ci 7391cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::Environment::BindAccumulator( 7401cb0ef41Sopenharmony_ci Node* node, FrameStateAttachmentMode mode) { 7411cb0ef41Sopenharmony_ci if (mode == FrameStateAttachmentMode::kAttachFrameState) { 7421cb0ef41Sopenharmony_ci builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt(0)); 7431cb0ef41Sopenharmony_ci } 7441cb0ef41Sopenharmony_ci values()->at(accumulator_base_) = node; 7451cb0ef41Sopenharmony_ci} 7461cb0ef41Sopenharmony_ci 7471cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::Environment::BindGeneratorState(Node* node) { 7481cb0ef41Sopenharmony_ci generator_state_ = node; 7491cb0ef41Sopenharmony_ci} 7501cb0ef41Sopenharmony_ci 7511cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::Environment::BindRegister( 7521cb0ef41Sopenharmony_ci interpreter::Register the_register, Node* node, 7531cb0ef41Sopenharmony_ci FrameStateAttachmentMode mode) { 7541cb0ef41Sopenharmony_ci int values_index = RegisterToValuesIndex(the_register); 7551cb0ef41Sopenharmony_ci if (mode == FrameStateAttachmentMode::kAttachFrameState) { 7561cb0ef41Sopenharmony_ci builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( 7571cb0ef41Sopenharmony_ci accumulator_base_ - values_index)); 7581cb0ef41Sopenharmony_ci } 7591cb0ef41Sopenharmony_ci values()->at(values_index) = node; 7601cb0ef41Sopenharmony_ci} 7611cb0ef41Sopenharmony_ci 7621cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::Environment::BindRegistersToProjections( 7631cb0ef41Sopenharmony_ci interpreter::Register first_reg, Node* node, 7641cb0ef41Sopenharmony_ci FrameStateAttachmentMode mode) { 7651cb0ef41Sopenharmony_ci int values_index = RegisterToValuesIndex(first_reg); 7661cb0ef41Sopenharmony_ci if (mode == FrameStateAttachmentMode::kAttachFrameState) { 7671cb0ef41Sopenharmony_ci builder()->PrepareFrameState(node, OutputFrameStateCombine::PokeAt( 7681cb0ef41Sopenharmony_ci accumulator_base_ - values_index)); 7691cb0ef41Sopenharmony_ci } 7701cb0ef41Sopenharmony_ci for (int i = 0; i < node->op()->ValueOutputCount(); i++) { 7711cb0ef41Sopenharmony_ci values()->at(values_index + i) = 7721cb0ef41Sopenharmony_ci builder()->NewNode(common()->Projection(i), node); 7731cb0ef41Sopenharmony_ci } 7741cb0ef41Sopenharmony_ci} 7751cb0ef41Sopenharmony_ci 7761cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::Environment::RecordAfterState( 7771cb0ef41Sopenharmony_ci Node* node, FrameStateAttachmentMode mode) { 7781cb0ef41Sopenharmony_ci if (mode == FrameStateAttachmentMode::kAttachFrameState) { 7791cb0ef41Sopenharmony_ci builder()->PrepareFrameState(node, OutputFrameStateCombine::Ignore()); 7801cb0ef41Sopenharmony_ci } 7811cb0ef41Sopenharmony_ci} 7821cb0ef41Sopenharmony_ci 7831cb0ef41Sopenharmony_ciBytecodeGraphBuilder::Environment* BytecodeGraphBuilder::Environment::Copy() { 7841cb0ef41Sopenharmony_ci return zone()->New<Environment>(this); 7851cb0ef41Sopenharmony_ci} 7861cb0ef41Sopenharmony_ci 7871cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::Environment::Merge( 7881cb0ef41Sopenharmony_ci BytecodeGraphBuilder::Environment* other, 7891cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness) { 7901cb0ef41Sopenharmony_ci // Create a merge of the control dependencies of both environments and update 7911cb0ef41Sopenharmony_ci // the current environment's control dependency accordingly. 7921cb0ef41Sopenharmony_ci Node* control = builder()->MergeControl(GetControlDependency(), 7931cb0ef41Sopenharmony_ci other->GetControlDependency()); 7941cb0ef41Sopenharmony_ci UpdateControlDependency(control); 7951cb0ef41Sopenharmony_ci 7961cb0ef41Sopenharmony_ci // Create a merge of the effect dependencies of both environments and update 7971cb0ef41Sopenharmony_ci // the current environment's effect dependency accordingly. 7981cb0ef41Sopenharmony_ci Node* effect = builder()->MergeEffect(GetEffectDependency(), 7991cb0ef41Sopenharmony_ci other->GetEffectDependency(), control); 8001cb0ef41Sopenharmony_ci UpdateEffectDependency(effect); 8011cb0ef41Sopenharmony_ci 8021cb0ef41Sopenharmony_ci // Introduce Phi nodes for values that are live and have differing inputs at 8031cb0ef41Sopenharmony_ci // the merge point, potentially extending an existing Phi node if possible. 8041cb0ef41Sopenharmony_ci context_ = builder()->MergeValue(context_, other->context_, control); 8051cb0ef41Sopenharmony_ci for (int i = 0; i < parameter_count(); i++) { 8061cb0ef41Sopenharmony_ci values_[i] = builder()->MergeValue(values_[i], other->values_[i], control); 8071cb0ef41Sopenharmony_ci } 8081cb0ef41Sopenharmony_ci for (int i = 0; i < register_count(); i++) { 8091cb0ef41Sopenharmony_ci int index = register_base() + i; 8101cb0ef41Sopenharmony_ci if (liveness == nullptr || liveness->RegisterIsLive(i)) { 8111cb0ef41Sopenharmony_ci#if DEBUG 8121cb0ef41Sopenharmony_ci // We only do these DCHECKs when we are not in the resume path of a 8131cb0ef41Sopenharmony_ci // generator -- this is, when either there is no generator state at all, 8141cb0ef41Sopenharmony_ci // or the generator state is not the constant "executing" value. 8151cb0ef41Sopenharmony_ci if (generator_state_ == nullptr || 8161cb0ef41Sopenharmony_ci NumberMatcher(generator_state_) 8171cb0ef41Sopenharmony_ci .Is(JSGeneratorObject::kGeneratorExecuting)) { 8181cb0ef41Sopenharmony_ci DCHECK_NE(values_[index], builder()->jsgraph()->OptimizedOutConstant()); 8191cb0ef41Sopenharmony_ci DCHECK_NE(other->values_[index], 8201cb0ef41Sopenharmony_ci builder()->jsgraph()->OptimizedOutConstant()); 8211cb0ef41Sopenharmony_ci } 8221cb0ef41Sopenharmony_ci#endif 8231cb0ef41Sopenharmony_ci 8241cb0ef41Sopenharmony_ci values_[index] = 8251cb0ef41Sopenharmony_ci builder()->MergeValue(values_[index], other->values_[index], control); 8261cb0ef41Sopenharmony_ci 8271cb0ef41Sopenharmony_ci } else { 8281cb0ef41Sopenharmony_ci values_[index] = builder()->jsgraph()->OptimizedOutConstant(); 8291cb0ef41Sopenharmony_ci } 8301cb0ef41Sopenharmony_ci } 8311cb0ef41Sopenharmony_ci 8321cb0ef41Sopenharmony_ci if (liveness == nullptr || liveness->AccumulatorIsLive()) { 8331cb0ef41Sopenharmony_ci DCHECK_NE(values_[accumulator_base()], 8341cb0ef41Sopenharmony_ci builder()->jsgraph()->OptimizedOutConstant()); 8351cb0ef41Sopenharmony_ci DCHECK_NE(other->values_[accumulator_base()], 8361cb0ef41Sopenharmony_ci builder()->jsgraph()->OptimizedOutConstant()); 8371cb0ef41Sopenharmony_ci 8381cb0ef41Sopenharmony_ci values_[accumulator_base()] = 8391cb0ef41Sopenharmony_ci builder()->MergeValue(values_[accumulator_base()], 8401cb0ef41Sopenharmony_ci other->values_[accumulator_base()], control); 8411cb0ef41Sopenharmony_ci } else { 8421cb0ef41Sopenharmony_ci values_[accumulator_base()] = builder()->jsgraph()->OptimizedOutConstant(); 8431cb0ef41Sopenharmony_ci } 8441cb0ef41Sopenharmony_ci 8451cb0ef41Sopenharmony_ci if (generator_state_ != nullptr) { 8461cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(other->generator_state_); 8471cb0ef41Sopenharmony_ci generator_state_ = builder()->MergeValue(generator_state_, 8481cb0ef41Sopenharmony_ci other->generator_state_, control); 8491cb0ef41Sopenharmony_ci } 8501cb0ef41Sopenharmony_ci} 8511cb0ef41Sopenharmony_ci 8521cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::Environment::PrepareForLoop( 8531cb0ef41Sopenharmony_ci const BytecodeLoopAssignments& assignments, 8541cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness) { 8551cb0ef41Sopenharmony_ci // Create a control node for the loop header. 8561cb0ef41Sopenharmony_ci Node* control = builder()->NewLoop(); 8571cb0ef41Sopenharmony_ci 8581cb0ef41Sopenharmony_ci // Create a Phi for external effects. 8591cb0ef41Sopenharmony_ci Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control); 8601cb0ef41Sopenharmony_ci UpdateEffectDependency(effect); 8611cb0ef41Sopenharmony_ci 8621cb0ef41Sopenharmony_ci // Create Phis for any values that are live on entry to the loop and may be 8631cb0ef41Sopenharmony_ci // updated by the end of the loop. 8641cb0ef41Sopenharmony_ci context_ = builder()->NewPhi(1, context_, control); 8651cb0ef41Sopenharmony_ci for (int i = 0; i < parameter_count(); i++) { 8661cb0ef41Sopenharmony_ci if (assignments.ContainsParameter(i)) { 8671cb0ef41Sopenharmony_ci values_[i] = builder()->NewPhi(1, values_[i], control); 8681cb0ef41Sopenharmony_ci } 8691cb0ef41Sopenharmony_ci } 8701cb0ef41Sopenharmony_ci for (int i = 0; i < register_count(); i++) { 8711cb0ef41Sopenharmony_ci if (assignments.ContainsLocal(i) && 8721cb0ef41Sopenharmony_ci (liveness == nullptr || liveness->RegisterIsLive(i))) { 8731cb0ef41Sopenharmony_ci int index = register_base() + i; 8741cb0ef41Sopenharmony_ci values_[index] = builder()->NewPhi(1, values_[index], control); 8751cb0ef41Sopenharmony_ci } 8761cb0ef41Sopenharmony_ci } 8771cb0ef41Sopenharmony_ci // The accumulator should not be live on entry. 8781cb0ef41Sopenharmony_ci DCHECK_IMPLIES(liveness != nullptr, !liveness->AccumulatorIsLive()); 8791cb0ef41Sopenharmony_ci 8801cb0ef41Sopenharmony_ci if (generator_state_ != nullptr) { 8811cb0ef41Sopenharmony_ci generator_state_ = builder()->NewPhi(1, generator_state_, control); 8821cb0ef41Sopenharmony_ci } 8831cb0ef41Sopenharmony_ci 8841cb0ef41Sopenharmony_ci // Connect to the loop end. 8851cb0ef41Sopenharmony_ci Node* terminate = builder()->graph()->NewNode( 8861cb0ef41Sopenharmony_ci builder()->common()->Terminate(), effect, control); 8871cb0ef41Sopenharmony_ci builder()->exit_controls_.push_back(terminate); 8881cb0ef41Sopenharmony_ci} 8891cb0ef41Sopenharmony_ci 8901cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::Environment::FillWithOsrValues() { 8911cb0ef41Sopenharmony_ci Node* start = graph()->start(); 8921cb0ef41Sopenharmony_ci 8931cb0ef41Sopenharmony_ci // Create OSR values for each environment value. 8941cb0ef41Sopenharmony_ci SetContext(graph()->NewNode( 8951cb0ef41Sopenharmony_ci common()->OsrValue(Linkage::kOsrContextSpillSlotIndex), start)); 8961cb0ef41Sopenharmony_ci int size = static_cast<int>(values()->size()); 8971cb0ef41Sopenharmony_ci for (int i = 0; i < size; i++) { 8981cb0ef41Sopenharmony_ci int idx = i; // Indexing scheme follows {StandardFrame}, adapt accordingly. 8991cb0ef41Sopenharmony_ci if (i >= register_base()) idx += InterpreterFrameConstants::kExtraSlotCount; 9001cb0ef41Sopenharmony_ci if (i >= accumulator_base()) idx = Linkage::kOsrAccumulatorRegisterIndex; 9011cb0ef41Sopenharmony_ci values()->at(i) = graph()->NewNode(common()->OsrValue(idx), start); 9021cb0ef41Sopenharmony_ci } 9031cb0ef41Sopenharmony_ci} 9041cb0ef41Sopenharmony_ci 9051cb0ef41Sopenharmony_cibool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( 9061cb0ef41Sopenharmony_ci Node** state_values, Node** values, int count) { 9071cb0ef41Sopenharmony_ci if (*state_values == nullptr) { 9081cb0ef41Sopenharmony_ci return true; 9091cb0ef41Sopenharmony_ci } 9101cb0ef41Sopenharmony_ci Node::Inputs inputs = (*state_values)->inputs(); 9111cb0ef41Sopenharmony_ci if (inputs.count() != count) return true; 9121cb0ef41Sopenharmony_ci for (int i = 0; i < count; i++) { 9131cb0ef41Sopenharmony_ci if (inputs[i] != values[i]) { 9141cb0ef41Sopenharmony_ci return true; 9151cb0ef41Sopenharmony_ci } 9161cb0ef41Sopenharmony_ci } 9171cb0ef41Sopenharmony_ci return false; 9181cb0ef41Sopenharmony_ci} 9191cb0ef41Sopenharmony_ci 9201cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::Environment::PrepareForLoopExit( 9211cb0ef41Sopenharmony_ci Node* loop, const BytecodeLoopAssignments& assignments, 9221cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness) { 9231cb0ef41Sopenharmony_ci DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); 9241cb0ef41Sopenharmony_ci 9251cb0ef41Sopenharmony_ci Node* control = GetControlDependency(); 9261cb0ef41Sopenharmony_ci 9271cb0ef41Sopenharmony_ci // Create the loop exit node. 9281cb0ef41Sopenharmony_ci Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop); 9291cb0ef41Sopenharmony_ci UpdateControlDependency(loop_exit); 9301cb0ef41Sopenharmony_ci 9311cb0ef41Sopenharmony_ci // Rename the effect. 9321cb0ef41Sopenharmony_ci Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(), 9331cb0ef41Sopenharmony_ci GetEffectDependency(), loop_exit); 9341cb0ef41Sopenharmony_ci UpdateEffectDependency(effect_rename); 9351cb0ef41Sopenharmony_ci 9361cb0ef41Sopenharmony_ci // TODO(jarin) We should also rename context here. However, unconditional 9371cb0ef41Sopenharmony_ci // renaming confuses global object and native context specialization. 9381cb0ef41Sopenharmony_ci // We should only rename if the context is assigned in the loop. 9391cb0ef41Sopenharmony_ci 9401cb0ef41Sopenharmony_ci // Rename the environment values if they were assigned in the loop and are 9411cb0ef41Sopenharmony_ci // live after exiting the loop. 9421cb0ef41Sopenharmony_ci for (int i = 0; i < parameter_count(); i++) { 9431cb0ef41Sopenharmony_ci if (assignments.ContainsParameter(i)) { 9441cb0ef41Sopenharmony_ci Node* rename = graph()->NewNode( 9451cb0ef41Sopenharmony_ci common()->LoopExitValue(MachineRepresentation::kTagged), values_[i], 9461cb0ef41Sopenharmony_ci loop_exit); 9471cb0ef41Sopenharmony_ci values_[i] = rename; 9481cb0ef41Sopenharmony_ci } 9491cb0ef41Sopenharmony_ci } 9501cb0ef41Sopenharmony_ci for (int i = 0; i < register_count(); i++) { 9511cb0ef41Sopenharmony_ci if (assignments.ContainsLocal(i) && 9521cb0ef41Sopenharmony_ci (liveness == nullptr || liveness->RegisterIsLive(i))) { 9531cb0ef41Sopenharmony_ci Node* rename = graph()->NewNode( 9541cb0ef41Sopenharmony_ci common()->LoopExitValue(MachineRepresentation::kTagged), 9551cb0ef41Sopenharmony_ci values_[register_base() + i], loop_exit); 9561cb0ef41Sopenharmony_ci values_[register_base() + i] = rename; 9571cb0ef41Sopenharmony_ci } 9581cb0ef41Sopenharmony_ci } 9591cb0ef41Sopenharmony_ci if (liveness == nullptr || liveness->AccumulatorIsLive()) { 9601cb0ef41Sopenharmony_ci Node* rename = graph()->NewNode( 9611cb0ef41Sopenharmony_ci common()->LoopExitValue(MachineRepresentation::kTagged), 9621cb0ef41Sopenharmony_ci values_[accumulator_base()], loop_exit); 9631cb0ef41Sopenharmony_ci values_[accumulator_base()] = rename; 9641cb0ef41Sopenharmony_ci } 9651cb0ef41Sopenharmony_ci 9661cb0ef41Sopenharmony_ci if (generator_state_ != nullptr) { 9671cb0ef41Sopenharmony_ci generator_state_ = graph()->NewNode( 9681cb0ef41Sopenharmony_ci common()->LoopExitValue(MachineRepresentation::kTagged), 9691cb0ef41Sopenharmony_ci generator_state_, loop_exit); 9701cb0ef41Sopenharmony_ci } 9711cb0ef41Sopenharmony_ci} 9721cb0ef41Sopenharmony_ci 9731cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, 9741cb0ef41Sopenharmony_ci Node** values, 9751cb0ef41Sopenharmony_ci int count) { 9761cb0ef41Sopenharmony_ci if (StateValuesRequireUpdate(state_values, values, count)) { 9771cb0ef41Sopenharmony_ci const Operator* op = common()->StateValues(count, SparseInputMask::Dense()); 9781cb0ef41Sopenharmony_ci (*state_values) = graph()->NewNode(op, count, values); 9791cb0ef41Sopenharmony_ci } 9801cb0ef41Sopenharmony_ci} 9811cb0ef41Sopenharmony_ci 9821cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::Environment::GetStateValuesFromCache( 9831cb0ef41Sopenharmony_ci Node** values, int count, const BytecodeLivenessState* liveness) { 9841cb0ef41Sopenharmony_ci return builder_->state_values_cache_.GetNodeForValues( 9851cb0ef41Sopenharmony_ci values, static_cast<size_t>(count), liveness); 9861cb0ef41Sopenharmony_ci} 9871cb0ef41Sopenharmony_ci 9881cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::Environment::Checkpoint( 9891cb0ef41Sopenharmony_ci BytecodeOffset bailout_id, OutputFrameStateCombine combine, 9901cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness) { 9911cb0ef41Sopenharmony_ci if (parameter_count() == register_count()) { 9921cb0ef41Sopenharmony_ci // Re-use the state-value cache if the number of local registers happens 9931cb0ef41Sopenharmony_ci // to match the parameter count. 9941cb0ef41Sopenharmony_ci parameters_state_values_ = 9951cb0ef41Sopenharmony_ci GetStateValuesFromCache(&values()->at(0), parameter_count(), nullptr); 9961cb0ef41Sopenharmony_ci } else { 9971cb0ef41Sopenharmony_ci UpdateStateValues(¶meters_state_values_, &values()->at(0), 9981cb0ef41Sopenharmony_ci parameter_count()); 9991cb0ef41Sopenharmony_ci } 10001cb0ef41Sopenharmony_ci 10011cb0ef41Sopenharmony_ci Node* registers_state_values = GetStateValuesFromCache( 10021cb0ef41Sopenharmony_ci &values()->at(register_base()), register_count(), liveness); 10031cb0ef41Sopenharmony_ci 10041cb0ef41Sopenharmony_ci bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive(); 10051cb0ef41Sopenharmony_ci Node* accumulator_state_value = 10061cb0ef41Sopenharmony_ci accumulator_is_live && combine != OutputFrameStateCombine::PokeAt(0) 10071cb0ef41Sopenharmony_ci ? values()->at(accumulator_base()) 10081cb0ef41Sopenharmony_ci : builder()->jsgraph()->OptimizedOutConstant(); 10091cb0ef41Sopenharmony_ci 10101cb0ef41Sopenharmony_ci const Operator* op = common()->FrameState( 10111cb0ef41Sopenharmony_ci bailout_id, combine, builder()->frame_state_function_info()); 10121cb0ef41Sopenharmony_ci Node* result = graph()->NewNode( 10131cb0ef41Sopenharmony_ci op, parameters_state_values_, registers_state_values, 10141cb0ef41Sopenharmony_ci accumulator_state_value, Context(), builder()->GetFunctionClosure(), 10151cb0ef41Sopenharmony_ci builder()->graph()->start()); 10161cb0ef41Sopenharmony_ci 10171cb0ef41Sopenharmony_ci return result; 10181cb0ef41Sopenharmony_ci} 10191cb0ef41Sopenharmony_ci 10201cb0ef41Sopenharmony_ciBytecodeGraphBuilder::BytecodeGraphBuilder( 10211cb0ef41Sopenharmony_ci JSHeapBroker* broker, Zone* local_zone, 10221cb0ef41Sopenharmony_ci NativeContextRef const& native_context, 10231cb0ef41Sopenharmony_ci SharedFunctionInfoRef const& shared_info, 10241cb0ef41Sopenharmony_ci FeedbackCellRef const& feedback_cell, BytecodeOffset osr_offset, 10251cb0ef41Sopenharmony_ci JSGraph* jsgraph, CallFrequency const& invocation_frequency, 10261cb0ef41Sopenharmony_ci SourcePositionTable* source_positions, int inlining_id, CodeKind code_kind, 10271cb0ef41Sopenharmony_ci BytecodeGraphBuilderFlags flags, TickCounter* tick_counter, 10281cb0ef41Sopenharmony_ci ObserveNodeInfo const& observe_node_info) 10291cb0ef41Sopenharmony_ci : broker_(broker), 10301cb0ef41Sopenharmony_ci local_isolate_(broker_->local_isolate() 10311cb0ef41Sopenharmony_ci ? broker_->local_isolate() 10321cb0ef41Sopenharmony_ci : broker_->isolate()->AsLocalIsolate()), 10331cb0ef41Sopenharmony_ci local_zone_(local_zone), 10341cb0ef41Sopenharmony_ci jsgraph_(jsgraph), 10351cb0ef41Sopenharmony_ci native_context_(native_context), 10361cb0ef41Sopenharmony_ci shared_info_(shared_info), 10371cb0ef41Sopenharmony_ci bytecode_array_(shared_info.GetBytecodeArray()), 10381cb0ef41Sopenharmony_ci feedback_cell_(feedback_cell), 10391cb0ef41Sopenharmony_ci feedback_vector_(feedback_cell.feedback_vector().value()), 10401cb0ef41Sopenharmony_ci invocation_frequency_(invocation_frequency), 10411cb0ef41Sopenharmony_ci type_hint_lowering_( 10421cb0ef41Sopenharmony_ci broker, jsgraph, feedback_vector_, 10431cb0ef41Sopenharmony_ci (flags & BytecodeGraphBuilderFlag::kBailoutOnUninitialized) 10441cb0ef41Sopenharmony_ci ? JSTypeHintLowering::kBailoutOnUninitialized 10451cb0ef41Sopenharmony_ci : JSTypeHintLowering::kNoFlags), 10461cb0ef41Sopenharmony_ci frame_state_function_info_(common()->CreateFrameStateFunctionInfo( 10471cb0ef41Sopenharmony_ci FrameStateType::kUnoptimizedFunction, 10481cb0ef41Sopenharmony_ci bytecode_array().parameter_count(), bytecode_array().register_count(), 10491cb0ef41Sopenharmony_ci shared_info.object())), 10501cb0ef41Sopenharmony_ci source_position_iterator_(std::make_unique<SourcePositionTableIterator>( 10511cb0ef41Sopenharmony_ci bytecode_array().SourcePositionTable())), 10521cb0ef41Sopenharmony_ci bytecode_iterator_(bytecode_array().object()), 10531cb0ef41Sopenharmony_ci bytecode_analysis_( 10541cb0ef41Sopenharmony_ci bytecode_array().object(), local_zone, osr_offset, 10551cb0ef41Sopenharmony_ci flags & BytecodeGraphBuilderFlag::kAnalyzeEnvironmentLiveness), 10561cb0ef41Sopenharmony_ci environment_(nullptr), 10571cb0ef41Sopenharmony_ci osr_(!osr_offset.IsNone()), 10581cb0ef41Sopenharmony_ci currently_peeled_loop_offset_(-1), 10591cb0ef41Sopenharmony_ci skip_first_stack_and_tierup_check_( 10601cb0ef41Sopenharmony_ci flags & BytecodeGraphBuilderFlag::kSkipFirstStackAndTierupCheck), 10611cb0ef41Sopenharmony_ci merge_environments_(local_zone), 10621cb0ef41Sopenharmony_ci generator_merge_environments_(local_zone), 10631cb0ef41Sopenharmony_ci cached_parameters_(local_zone), 10641cb0ef41Sopenharmony_ci exception_handlers_(local_zone), 10651cb0ef41Sopenharmony_ci current_exception_handler_(0), 10661cb0ef41Sopenharmony_ci input_buffer_size_(0), 10671cb0ef41Sopenharmony_ci input_buffer_(nullptr), 10681cb0ef41Sopenharmony_ci code_kind_(code_kind), 10691cb0ef41Sopenharmony_ci feedback_vector_node_(nullptr), 10701cb0ef41Sopenharmony_ci native_context_node_(nullptr), 10711cb0ef41Sopenharmony_ci needs_eager_checkpoint_(true), 10721cb0ef41Sopenharmony_ci exit_controls_(local_zone), 10731cb0ef41Sopenharmony_ci state_values_cache_(jsgraph), 10741cb0ef41Sopenharmony_ci source_positions_(source_positions), 10751cb0ef41Sopenharmony_ci start_position_(shared_info.StartPosition(), inlining_id), 10761cb0ef41Sopenharmony_ci tick_counter_(tick_counter), 10771cb0ef41Sopenharmony_ci observe_node_info_(observe_node_info) {} 10781cb0ef41Sopenharmony_ci 10791cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::GetFunctionClosure() { 10801cb0ef41Sopenharmony_ci if (!function_closure_.is_set()) { 10811cb0ef41Sopenharmony_ci int index = Linkage::kJSCallClosureParamIndex; 10821cb0ef41Sopenharmony_ci Node* node = GetParameter(index, "%closure"); 10831cb0ef41Sopenharmony_ci function_closure_.set(node); 10841cb0ef41Sopenharmony_ci } 10851cb0ef41Sopenharmony_ci return function_closure_.get(); 10861cb0ef41Sopenharmony_ci} 10871cb0ef41Sopenharmony_ci 10881cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::GetParameter(int parameter_index, 10891cb0ef41Sopenharmony_ci const char* debug_name_hint) { 10901cb0ef41Sopenharmony_ci // We use negative indices for some parameters. 10911cb0ef41Sopenharmony_ci DCHECK_LE(ParameterInfo::kMinIndex, parameter_index); 10921cb0ef41Sopenharmony_ci const size_t index = 10931cb0ef41Sopenharmony_ci static_cast<size_t>(parameter_index - ParameterInfo::kMinIndex); 10941cb0ef41Sopenharmony_ci 10951cb0ef41Sopenharmony_ci if (cached_parameters_.size() <= index) { 10961cb0ef41Sopenharmony_ci cached_parameters_.resize(index + 1, nullptr); 10971cb0ef41Sopenharmony_ci } 10981cb0ef41Sopenharmony_ci 10991cb0ef41Sopenharmony_ci if (cached_parameters_[index] == nullptr) { 11001cb0ef41Sopenharmony_ci cached_parameters_[index] = 11011cb0ef41Sopenharmony_ci NewNode(common()->Parameter(parameter_index, debug_name_hint), 11021cb0ef41Sopenharmony_ci graph()->start()); 11031cb0ef41Sopenharmony_ci } 11041cb0ef41Sopenharmony_ci 11051cb0ef41Sopenharmony_ci return cached_parameters_[index]; 11061cb0ef41Sopenharmony_ci} 11071cb0ef41Sopenharmony_ci 11081cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::CreateFeedbackVectorNode() { 11091cb0ef41Sopenharmony_ci DCHECK_NULL(feedback_vector_node_); 11101cb0ef41Sopenharmony_ci feedback_vector_node_ = jsgraph()->Constant(feedback_vector()); 11111cb0ef41Sopenharmony_ci} 11121cb0ef41Sopenharmony_ci 11131cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::BuildLoadFeedbackCell(int index) { 11141cb0ef41Sopenharmony_ci return jsgraph()->Constant(feedback_vector().GetClosureFeedbackCell(index)); 11151cb0ef41Sopenharmony_ci} 11161cb0ef41Sopenharmony_ci 11171cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::CreateNativeContextNode() { 11181cb0ef41Sopenharmony_ci DCHECK_NULL(native_context_node_); 11191cb0ef41Sopenharmony_ci native_context_node_ = jsgraph()->Constant(native_context()); 11201cb0ef41Sopenharmony_ci} 11211cb0ef41Sopenharmony_ci 11221cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) { 11231cb0ef41Sopenharmony_ci Node* result = NewNode(javascript()->LoadContext(0, index, true)); 11241cb0ef41Sopenharmony_ci NodeProperties::ReplaceContextInput(result, native_context_node()); 11251cb0ef41Sopenharmony_ci return result; 11261cb0ef41Sopenharmony_ci} 11271cb0ef41Sopenharmony_ci 11281cb0ef41Sopenharmony_ciFeedbackSource BytecodeGraphBuilder::CreateFeedbackSource(int slot_id) { 11291cb0ef41Sopenharmony_ci return CreateFeedbackSource(FeedbackVector::ToSlot(slot_id)); 11301cb0ef41Sopenharmony_ci} 11311cb0ef41Sopenharmony_ci 11321cb0ef41Sopenharmony_ciFeedbackSource BytecodeGraphBuilder::CreateFeedbackSource(FeedbackSlot slot) { 11331cb0ef41Sopenharmony_ci return FeedbackSource(feedback_vector(), slot); 11341cb0ef41Sopenharmony_ci} 11351cb0ef41Sopenharmony_ci 11361cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::CreateGraph() { 11371cb0ef41Sopenharmony_ci SourcePositionTable::Scope pos_scope(source_positions_, start_position_); 11381cb0ef41Sopenharmony_ci 11391cb0ef41Sopenharmony_ci // Set up the basic structure of the graph. Outputs for {Start} are the formal 11401cb0ef41Sopenharmony_ci // parameters (including the receiver) plus new target, number of arguments, 11411cb0ef41Sopenharmony_ci // context and closure. 11421cb0ef41Sopenharmony_ci int start_output_arity = StartNode::OutputArityForFormalParameterCount( 11431cb0ef41Sopenharmony_ci bytecode_array().parameter_count()); 11441cb0ef41Sopenharmony_ci graph()->SetStart(graph()->NewNode(common()->Start(start_output_arity))); 11451cb0ef41Sopenharmony_ci 11461cb0ef41Sopenharmony_ci Environment env(this, bytecode_array().register_count(), 11471cb0ef41Sopenharmony_ci bytecode_array().parameter_count(), 11481cb0ef41Sopenharmony_ci bytecode_array().incoming_new_target_or_generator_register(), 11491cb0ef41Sopenharmony_ci graph()->start()); 11501cb0ef41Sopenharmony_ci set_environment(&env); 11511cb0ef41Sopenharmony_ci 11521cb0ef41Sopenharmony_ci CreateFeedbackVectorNode(); 11531cb0ef41Sopenharmony_ci CreateNativeContextNode(); 11541cb0ef41Sopenharmony_ci 11551cb0ef41Sopenharmony_ci VisitBytecodes(); 11561cb0ef41Sopenharmony_ci 11571cb0ef41Sopenharmony_ci // Finish the basic structure of the graph. 11581cb0ef41Sopenharmony_ci DCHECK_NE(0u, exit_controls_.size()); 11591cb0ef41Sopenharmony_ci int const input_count = static_cast<int>(exit_controls_.size()); 11601cb0ef41Sopenharmony_ci Node** const inputs = &exit_controls_.front(); 11611cb0ef41Sopenharmony_ci Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); 11621cb0ef41Sopenharmony_ci graph()->SetEnd(end); 11631cb0ef41Sopenharmony_ci} 11641cb0ef41Sopenharmony_ci 11651cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::PrepareEagerCheckpoint() { 11661cb0ef41Sopenharmony_ci if (needs_eager_checkpoint()) { 11671cb0ef41Sopenharmony_ci // Create an explicit checkpoint node for before the operation. This only 11681cb0ef41Sopenharmony_ci // needs to happen if we aren't effect-dominated by a {Checkpoint} already. 11691cb0ef41Sopenharmony_ci mark_as_needing_eager_checkpoint(false); 11701cb0ef41Sopenharmony_ci Node* node = NewNode(common()->Checkpoint()); 11711cb0ef41Sopenharmony_ci DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 11721cb0ef41Sopenharmony_ci DCHECK_EQ(IrOpcode::kDead, 11731cb0ef41Sopenharmony_ci NodeProperties::GetFrameStateInput(node)->opcode()); 11741cb0ef41Sopenharmony_ci BytecodeOffset bailout_id(bytecode_iterator().current_offset()); 11751cb0ef41Sopenharmony_ci 11761cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness_before = 11771cb0ef41Sopenharmony_ci bytecode_analysis().GetInLivenessFor( 11781cb0ef41Sopenharmony_ci bytecode_iterator().current_offset()); 11791cb0ef41Sopenharmony_ci 11801cb0ef41Sopenharmony_ci Node* frame_state_before = environment()->Checkpoint( 11811cb0ef41Sopenharmony_ci bailout_id, OutputFrameStateCombine::Ignore(), liveness_before); 11821cb0ef41Sopenharmony_ci NodeProperties::ReplaceFrameStateInput(node, frame_state_before); 11831cb0ef41Sopenharmony_ci#ifdef DEBUG 11841cb0ef41Sopenharmony_ci } else { 11851cb0ef41Sopenharmony_ci // In case we skipped checkpoint creation above, we must be able to find an 11861cb0ef41Sopenharmony_ci // existing checkpoint that effect-dominates the nodes about to be created. 11871cb0ef41Sopenharmony_ci // Starting a search from the current effect-dependency has to succeed. 11881cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 11891cb0ef41Sopenharmony_ci while (effect->opcode() != IrOpcode::kCheckpoint) { 11901cb0ef41Sopenharmony_ci DCHECK(effect->op()->HasProperty(Operator::kNoWrite)); 11911cb0ef41Sopenharmony_ci DCHECK_EQ(1, effect->op()->EffectInputCount()); 11921cb0ef41Sopenharmony_ci effect = NodeProperties::GetEffectInput(effect); 11931cb0ef41Sopenharmony_ci } 11941cb0ef41Sopenharmony_ci } 11951cb0ef41Sopenharmony_ci#else 11961cb0ef41Sopenharmony_ci } 11971cb0ef41Sopenharmony_ci#endif // DEBUG 11981cb0ef41Sopenharmony_ci} 11991cb0ef41Sopenharmony_ci 12001cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::PrepareFrameState( 12011cb0ef41Sopenharmony_ci Node* node, OutputFrameStateCombine combine, BytecodeOffset bailout_id, 12021cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness) { 12031cb0ef41Sopenharmony_ci if (OperatorProperties::HasFrameStateInput(node->op())) { 12041cb0ef41Sopenharmony_ci // Add the frame state for after the operation. The node in question has 12051cb0ef41Sopenharmony_ci // already been created and had a {Dead} frame state input up until now. 12061cb0ef41Sopenharmony_ci DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op())); 12071cb0ef41Sopenharmony_ci DCHECK_EQ(IrOpcode::kDead, 12081cb0ef41Sopenharmony_ci NodeProperties::GetFrameStateInput(node)->opcode()); 12091cb0ef41Sopenharmony_ci 12101cb0ef41Sopenharmony_ci Node* frame_state_after = 12111cb0ef41Sopenharmony_ci environment()->Checkpoint(bailout_id, combine, liveness); 12121cb0ef41Sopenharmony_ci NodeProperties::ReplaceFrameStateInput(node, frame_state_after); 12131cb0ef41Sopenharmony_ci } 12141cb0ef41Sopenharmony_ci} 12151cb0ef41Sopenharmony_ci 12161cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::AdvanceIteratorsTo(int bytecode_offset) { 12171cb0ef41Sopenharmony_ci for (; bytecode_iterator().current_offset() != bytecode_offset; 12181cb0ef41Sopenharmony_ci bytecode_iterator().Advance()) { 12191cb0ef41Sopenharmony_ci UpdateSourcePosition(bytecode_iterator().current_offset()); 12201cb0ef41Sopenharmony_ci } 12211cb0ef41Sopenharmony_ci} 12221cb0ef41Sopenharmony_ci 12231cb0ef41Sopenharmony_ci// Stores the state of the SourcePosition iterator, and the index to the 12241cb0ef41Sopenharmony_ci// current exception handlers stack. We need, during the OSR graph generation, 12251cb0ef41Sopenharmony_ci// to backup the states of these iterators at the LoopHeader offset of each 12261cb0ef41Sopenharmony_ci// outer loop which contains the OSR loop. The iterators are then restored when 12271cb0ef41Sopenharmony_ci// peeling the loops, so that both exception handling and synchronisation with 12281cb0ef41Sopenharmony_ci// the source position can be achieved. 12291cb0ef41Sopenharmony_ciclass BytecodeGraphBuilder::OsrIteratorState { 12301cb0ef41Sopenharmony_ci public: 12311cb0ef41Sopenharmony_ci explicit OsrIteratorState(BytecodeGraphBuilder* graph_builder) 12321cb0ef41Sopenharmony_ci : graph_builder_(graph_builder), 12331cb0ef41Sopenharmony_ci saved_states_(graph_builder->local_zone()) {} 12341cb0ef41Sopenharmony_ci 12351cb0ef41Sopenharmony_ci void ProcessOsrPrelude() { 12361cb0ef41Sopenharmony_ci ZoneVector<int> outer_loop_offsets(graph_builder_->local_zone()); 12371cb0ef41Sopenharmony_ci int osr_entry = graph_builder_->bytecode_analysis().osr_entry_point(); 12381cb0ef41Sopenharmony_ci 12391cb0ef41Sopenharmony_ci // We find here the outermost loop which contains the OSR loop. 12401cb0ef41Sopenharmony_ci int outermost_loop_offset = osr_entry; 12411cb0ef41Sopenharmony_ci while ((outermost_loop_offset = graph_builder_->bytecode_analysis() 12421cb0ef41Sopenharmony_ci .GetLoopInfoFor(outermost_loop_offset) 12431cb0ef41Sopenharmony_ci .parent_offset()) != -1) { 12441cb0ef41Sopenharmony_ci outer_loop_offsets.push_back(outermost_loop_offset); 12451cb0ef41Sopenharmony_ci } 12461cb0ef41Sopenharmony_ci outermost_loop_offset = 12471cb0ef41Sopenharmony_ci outer_loop_offsets.empty() ? osr_entry : outer_loop_offsets.back(); 12481cb0ef41Sopenharmony_ci graph_builder_->AdvanceIteratorsTo(outermost_loop_offset); 12491cb0ef41Sopenharmony_ci 12501cb0ef41Sopenharmony_ci // We save some iterators states at the offsets of the loop headers of the 12511cb0ef41Sopenharmony_ci // outer loops (the ones containing the OSR loop). They will be used for 12521cb0ef41Sopenharmony_ci // jumping back in the bytecode. 12531cb0ef41Sopenharmony_ci for (ZoneVector<int>::const_reverse_iterator it = 12541cb0ef41Sopenharmony_ci outer_loop_offsets.crbegin(); 12551cb0ef41Sopenharmony_ci it != outer_loop_offsets.crend(); ++it) { 12561cb0ef41Sopenharmony_ci graph_builder_->AdvanceIteratorsTo(*it); 12571cb0ef41Sopenharmony_ci graph_builder_->ExitThenEnterExceptionHandlers( 12581cb0ef41Sopenharmony_ci graph_builder_->bytecode_iterator().current_offset()); 12591cb0ef41Sopenharmony_ci saved_states_.push(IteratorsStates( 12601cb0ef41Sopenharmony_ci graph_builder_->current_exception_handler(), 12611cb0ef41Sopenharmony_ci graph_builder_->source_position_iterator().GetState())); 12621cb0ef41Sopenharmony_ci } 12631cb0ef41Sopenharmony_ci 12641cb0ef41Sopenharmony_ci // Finishing by advancing to the OSR entry 12651cb0ef41Sopenharmony_ci graph_builder_->AdvanceIteratorsTo(osr_entry); 12661cb0ef41Sopenharmony_ci 12671cb0ef41Sopenharmony_ci // Enters all remaining exception handler which end before the OSR loop 12681cb0ef41Sopenharmony_ci // so that on next call of VisitSingleBytecode they will get popped from 12691cb0ef41Sopenharmony_ci // the exception handlers stack. 12701cb0ef41Sopenharmony_ci graph_builder_->ExitThenEnterExceptionHandlers(osr_entry); 12711cb0ef41Sopenharmony_ci graph_builder_->set_currently_peeled_loop_offset( 12721cb0ef41Sopenharmony_ci graph_builder_->bytecode_analysis() 12731cb0ef41Sopenharmony_ci .GetLoopInfoFor(osr_entry) 12741cb0ef41Sopenharmony_ci .parent_offset()); 12751cb0ef41Sopenharmony_ci } 12761cb0ef41Sopenharmony_ci 12771cb0ef41Sopenharmony_ci void RestoreState(int target_offset, int new_parent_offset) { 12781cb0ef41Sopenharmony_ci graph_builder_->bytecode_iterator().SetOffset(target_offset); 12791cb0ef41Sopenharmony_ci // In case of a return, we must not build loop exits for 12801cb0ef41Sopenharmony_ci // not-yet-built outer loops. 12811cb0ef41Sopenharmony_ci graph_builder_->set_currently_peeled_loop_offset(new_parent_offset); 12821cb0ef41Sopenharmony_ci IteratorsStates saved_state = saved_states_.top(); 12831cb0ef41Sopenharmony_ci graph_builder_->source_position_iterator().RestoreState( 12841cb0ef41Sopenharmony_ci saved_state.source_iterator_state_); 12851cb0ef41Sopenharmony_ci graph_builder_->set_current_exception_handler( 12861cb0ef41Sopenharmony_ci saved_state.exception_handler_index_); 12871cb0ef41Sopenharmony_ci saved_states_.pop(); 12881cb0ef41Sopenharmony_ci } 12891cb0ef41Sopenharmony_ci 12901cb0ef41Sopenharmony_ci private: 12911cb0ef41Sopenharmony_ci struct IteratorsStates { 12921cb0ef41Sopenharmony_ci int exception_handler_index_; 12931cb0ef41Sopenharmony_ci SourcePositionTableIterator::IndexAndPositionState source_iterator_state_; 12941cb0ef41Sopenharmony_ci 12951cb0ef41Sopenharmony_ci IteratorsStates(int exception_handler_index, 12961cb0ef41Sopenharmony_ci SourcePositionTableIterator::IndexAndPositionState 12971cb0ef41Sopenharmony_ci source_iterator_state) 12981cb0ef41Sopenharmony_ci : exception_handler_index_(exception_handler_index), 12991cb0ef41Sopenharmony_ci source_iterator_state_(source_iterator_state) {} 13001cb0ef41Sopenharmony_ci }; 13011cb0ef41Sopenharmony_ci 13021cb0ef41Sopenharmony_ci BytecodeGraphBuilder* graph_builder_; 13031cb0ef41Sopenharmony_ci ZoneStack<IteratorsStates> saved_states_; 13041cb0ef41Sopenharmony_ci}; 13051cb0ef41Sopenharmony_ci 13061cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::RemoveMergeEnvironmentsBeforeOffset( 13071cb0ef41Sopenharmony_ci int limit_offset) { 13081cb0ef41Sopenharmony_ci if (!merge_environments_.empty()) { 13091cb0ef41Sopenharmony_ci ZoneMap<int, Environment*>::iterator it = merge_environments_.begin(); 13101cb0ef41Sopenharmony_ci ZoneMap<int, Environment*>::iterator stop_it = merge_environments_.end(); 13111cb0ef41Sopenharmony_ci while (it != stop_it && it->first <= limit_offset) { 13121cb0ef41Sopenharmony_ci it = merge_environments_.erase(it); 13131cb0ef41Sopenharmony_ci } 13141cb0ef41Sopenharmony_ci } 13151cb0ef41Sopenharmony_ci} 13161cb0ef41Sopenharmony_ci 13171cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildFunctionEntryStackCheck() { 13181cb0ef41Sopenharmony_ci if (!skip_first_stack_check()) { 13191cb0ef41Sopenharmony_ci DCHECK(exception_handlers_.empty()); 13201cb0ef41Sopenharmony_ci Node* node = 13211cb0ef41Sopenharmony_ci NewNode(javascript()->StackCheck(StackCheckKind::kJSFunctionEntry)); 13221cb0ef41Sopenharmony_ci PrepareFrameStateForFunctionEntryStackCheck(node); 13231cb0ef41Sopenharmony_ci } 13241cb0ef41Sopenharmony_ci} 13251cb0ef41Sopenharmony_ci 13261cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildIterationBodyStackCheck() { 13271cb0ef41Sopenharmony_ci Node* node = 13281cb0ef41Sopenharmony_ci NewNode(javascript()->StackCheck(StackCheckKind::kJSIterationBody)); 13291cb0ef41Sopenharmony_ci environment()->RecordAfterState(node, Environment::kAttachFrameState); 13301cb0ef41Sopenharmony_ci} 13311cb0ef41Sopenharmony_ci 13321cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildOSREntryStackCheck() { 13331cb0ef41Sopenharmony_ci DCHECK(exception_handlers_.empty()); 13341cb0ef41Sopenharmony_ci Node* node = 13351cb0ef41Sopenharmony_ci NewNode(javascript()->StackCheck(StackCheckKind::kJSFunctionEntry)); 13361cb0ef41Sopenharmony_ci PrepareFrameStateForOSREntryStackCheck(node); 13371cb0ef41Sopenharmony_ci} 13381cb0ef41Sopenharmony_ci 13391cb0ef41Sopenharmony_ci// We will iterate through the OSR loop, then its parent, and so on 13401cb0ef41Sopenharmony_ci// until we have reached the outmost loop containing the OSR loop. We do 13411cb0ef41Sopenharmony_ci// not generate nodes for anything before the outermost loop. 13421cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::AdvanceToOsrEntryAndPeelLoops() { 13431cb0ef41Sopenharmony_ci environment()->FillWithOsrValues(); 13441cb0ef41Sopenharmony_ci 13451cb0ef41Sopenharmony_ci // The entry stack check has to happen *before* initialising the OSR prelude; 13461cb0ef41Sopenharmony_ci // it has to happen before setting up exception handlers, so that the 13471cb0ef41Sopenharmony_ci // optimized code can't accidentally catch a failingstack with a OSR-ed loop 13481cb0ef41Sopenharmony_ci // inside a try-catch, e.g. 13491cb0ef41Sopenharmony_ci // 13501cb0ef41Sopenharmony_ci // try { 13511cb0ef41Sopenharmony_ci // loop { OSR(); } 13521cb0ef41Sopenharmony_ci // } catch { 13531cb0ef41Sopenharmony_ci // // Ignore failed stack check. 13541cb0ef41Sopenharmony_ci // } 13551cb0ef41Sopenharmony_ci BuildOSREntryStackCheck(); 13561cb0ef41Sopenharmony_ci 13571cb0ef41Sopenharmony_ci OsrIteratorState iterator_states(this); 13581cb0ef41Sopenharmony_ci iterator_states.ProcessOsrPrelude(); 13591cb0ef41Sopenharmony_ci int osr_entry = bytecode_analysis().osr_entry_point(); 13601cb0ef41Sopenharmony_ci DCHECK_EQ(bytecode_iterator().current_offset(), osr_entry); 13611cb0ef41Sopenharmony_ci 13621cb0ef41Sopenharmony_ci // Suppose we have n nested loops, loop_0 being the outermost one, and 13631cb0ef41Sopenharmony_ci // loop_n being the OSR loop. We start iterating the bytecode at the header 13641cb0ef41Sopenharmony_ci // of loop_n (the OSR loop), and then we peel the part of the the body of 13651cb0ef41Sopenharmony_ci // loop_{n-1} following the end of loop_n. We then rewind the iterator to 13661cb0ef41Sopenharmony_ci // the header of loop_{n-1}, and so on until we have partly peeled loop 0. 13671cb0ef41Sopenharmony_ci // The full loop_0 body will be generating with the rest of the function, 13681cb0ef41Sopenharmony_ci // outside the OSR generation. 13691cb0ef41Sopenharmony_ci 13701cb0ef41Sopenharmony_ci // To do so, if we are visiting a loop, we continue to visit what's left 13711cb0ef41Sopenharmony_ci // of its parent, and then when reaching the parent's JumpLoop, we do not 13721cb0ef41Sopenharmony_ci // create any jump for that but rewind the bytecode iterator to visit the 13731cb0ef41Sopenharmony_ci // parent loop entirely, and so on. 13741cb0ef41Sopenharmony_ci 13751cb0ef41Sopenharmony_ci int current_parent_offset = 13761cb0ef41Sopenharmony_ci bytecode_analysis().GetLoopInfoFor(osr_entry).parent_offset(); 13771cb0ef41Sopenharmony_ci while (current_parent_offset != -1) { 13781cb0ef41Sopenharmony_ci const LoopInfo& current_parent_loop = 13791cb0ef41Sopenharmony_ci bytecode_analysis().GetLoopInfoFor(current_parent_offset); 13801cb0ef41Sopenharmony_ci // We iterate until the back edge of the parent loop, which we detect by 13811cb0ef41Sopenharmony_ci // the offset that the JumpLoop targets. 13821cb0ef41Sopenharmony_ci for (; !bytecode_iterator().done(); bytecode_iterator().Advance()) { 13831cb0ef41Sopenharmony_ci if (bytecode_iterator().current_bytecode() == 13841cb0ef41Sopenharmony_ci interpreter::Bytecode::kJumpLoop && 13851cb0ef41Sopenharmony_ci bytecode_iterator().GetJumpTargetOffset() == current_parent_offset) { 13861cb0ef41Sopenharmony_ci // Reached the end of the current parent loop. 13871cb0ef41Sopenharmony_ci break; 13881cb0ef41Sopenharmony_ci } 13891cb0ef41Sopenharmony_ci VisitSingleBytecode(); 13901cb0ef41Sopenharmony_ci } 13911cb0ef41Sopenharmony_ci DCHECK(!bytecode_iterator() 13921cb0ef41Sopenharmony_ci .done()); // Should have found the loop's jump target. 13931cb0ef41Sopenharmony_ci 13941cb0ef41Sopenharmony_ci // We also need to take care of the merge environments and exceptions 13951cb0ef41Sopenharmony_ci // handlers here because the omitted JumpLoop bytecode can still be the 13961cb0ef41Sopenharmony_ci // target of jumps or the first bytecode after a try block. 13971cb0ef41Sopenharmony_ci ExitThenEnterExceptionHandlers(bytecode_iterator().current_offset()); 13981cb0ef41Sopenharmony_ci SwitchToMergeEnvironment(bytecode_iterator().current_offset()); 13991cb0ef41Sopenharmony_ci 14001cb0ef41Sopenharmony_ci // This jump is the jump of our parent loop, which is not yet created. 14011cb0ef41Sopenharmony_ci // So we do not build the jump nodes, but restore the bytecode and the 14021cb0ef41Sopenharmony_ci // SourcePosition iterators to the values they had when we were visiting 14031cb0ef41Sopenharmony_ci // the offset pointed at by the JumpLoop we've just reached. 14041cb0ef41Sopenharmony_ci // We have already built nodes for inner loops, but now we will 14051cb0ef41Sopenharmony_ci // iterate again over them and build new nodes corresponding to the same 14061cb0ef41Sopenharmony_ci // bytecode offsets. Any jump or reference to this inner loops must now 14071cb0ef41Sopenharmony_ci // point to the new nodes we will build, hence we clear the relevant part 14081cb0ef41Sopenharmony_ci // of the environment. 14091cb0ef41Sopenharmony_ci // Completely clearing the environment is not possible because merge 14101cb0ef41Sopenharmony_ci // environments for forward jumps out of the loop need to be preserved 14111cb0ef41Sopenharmony_ci // (e.g. a return or a labeled break in the middle of a loop). 14121cb0ef41Sopenharmony_ci RemoveMergeEnvironmentsBeforeOffset(bytecode_iterator().current_offset()); 14131cb0ef41Sopenharmony_ci iterator_states.RestoreState(current_parent_offset, 14141cb0ef41Sopenharmony_ci current_parent_loop.parent_offset()); 14151cb0ef41Sopenharmony_ci current_parent_offset = current_parent_loop.parent_offset(); 14161cb0ef41Sopenharmony_ci } 14171cb0ef41Sopenharmony_ci} 14181cb0ef41Sopenharmony_ci 14191cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitSingleBytecode() { 14201cb0ef41Sopenharmony_ci tick_counter_->TickAndMaybeEnterSafepoint(); 14211cb0ef41Sopenharmony_ci int current_offset = bytecode_iterator().current_offset(); 14221cb0ef41Sopenharmony_ci UpdateSourcePosition(current_offset); 14231cb0ef41Sopenharmony_ci ExitThenEnterExceptionHandlers(current_offset); 14241cb0ef41Sopenharmony_ci DCHECK_GE(exception_handlers_.empty() ? current_offset 14251cb0ef41Sopenharmony_ci : exception_handlers_.top().end_offset_, 14261cb0ef41Sopenharmony_ci current_offset); 14271cb0ef41Sopenharmony_ci SwitchToMergeEnvironment(current_offset); 14281cb0ef41Sopenharmony_ci 14291cb0ef41Sopenharmony_ci if (environment() != nullptr) { 14301cb0ef41Sopenharmony_ci BuildLoopHeaderEnvironment(current_offset); 14311cb0ef41Sopenharmony_ci 14321cb0ef41Sopenharmony_ci switch (bytecode_iterator().current_bytecode()) { 14331cb0ef41Sopenharmony_ci#define BYTECODE_CASE(name, ...) \ 14341cb0ef41Sopenharmony_ci case interpreter::Bytecode::k##name: \ 14351cb0ef41Sopenharmony_ci Visit##name(); \ 14361cb0ef41Sopenharmony_ci break; 14371cb0ef41Sopenharmony_ci BYTECODE_LIST(BYTECODE_CASE) 14381cb0ef41Sopenharmony_ci#undef BYTECODE_CASE 14391cb0ef41Sopenharmony_ci } 14401cb0ef41Sopenharmony_ci } 14411cb0ef41Sopenharmony_ci} 14421cb0ef41Sopenharmony_ci 14431cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitBytecodes() { 14441cb0ef41Sopenharmony_ci if (!bytecode_analysis().resume_jump_targets().empty()) { 14451cb0ef41Sopenharmony_ci environment()->BindGeneratorState( 14461cb0ef41Sopenharmony_ci jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting)); 14471cb0ef41Sopenharmony_ci } 14481cb0ef41Sopenharmony_ci 14491cb0ef41Sopenharmony_ci if (osr_) { 14501cb0ef41Sopenharmony_ci // We peel the OSR loop and any outer loop containing it except that we 14511cb0ef41Sopenharmony_ci // leave the nodes corresponding to the whole outermost loop (including 14521cb0ef41Sopenharmony_ci // the last copies of the loops it contains) to be generated by the normal 14531cb0ef41Sopenharmony_ci // bytecode iteration below. 14541cb0ef41Sopenharmony_ci AdvanceToOsrEntryAndPeelLoops(); 14551cb0ef41Sopenharmony_ci } else { 14561cb0ef41Sopenharmony_ci BuildFunctionEntryStackCheck(); 14571cb0ef41Sopenharmony_ci } 14581cb0ef41Sopenharmony_ci 14591cb0ef41Sopenharmony_ci for (; !bytecode_iterator().done(); bytecode_iterator().Advance()) { 14601cb0ef41Sopenharmony_ci VisitSingleBytecode(); 14611cb0ef41Sopenharmony_ci } 14621cb0ef41Sopenharmony_ci 14631cb0ef41Sopenharmony_ci DCHECK(exception_handlers_.empty()); 14641cb0ef41Sopenharmony_ci} 14651cb0ef41Sopenharmony_ci 14661cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaZero() { 14671cb0ef41Sopenharmony_ci Node* node = jsgraph()->ZeroConstant(); 14681cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 14691cb0ef41Sopenharmony_ci} 14701cb0ef41Sopenharmony_ci 14711cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaSmi() { 14721cb0ef41Sopenharmony_ci Node* node = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); 14731cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 14741cb0ef41Sopenharmony_ci} 14751cb0ef41Sopenharmony_ci 14761cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaConstant() { 14771cb0ef41Sopenharmony_ci ObjectRef object = MakeRefForConstantForIndexOperand(0); 14781cb0ef41Sopenharmony_ci Node* node = jsgraph()->Constant(object); 14791cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 14801cb0ef41Sopenharmony_ci} 14811cb0ef41Sopenharmony_ci 14821cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaUndefined() { 14831cb0ef41Sopenharmony_ci Node* node = jsgraph()->UndefinedConstant(); 14841cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 14851cb0ef41Sopenharmony_ci} 14861cb0ef41Sopenharmony_ci 14871cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaNull() { 14881cb0ef41Sopenharmony_ci Node* node = jsgraph()->NullConstant(); 14891cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 14901cb0ef41Sopenharmony_ci} 14911cb0ef41Sopenharmony_ci 14921cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaTheHole() { 14931cb0ef41Sopenharmony_ci Node* node = jsgraph()->TheHoleConstant(); 14941cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 14951cb0ef41Sopenharmony_ci} 14961cb0ef41Sopenharmony_ci 14971cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaTrue() { 14981cb0ef41Sopenharmony_ci Node* node = jsgraph()->TrueConstant(); 14991cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 15001cb0ef41Sopenharmony_ci} 15011cb0ef41Sopenharmony_ci 15021cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaFalse() { 15031cb0ef41Sopenharmony_ci Node* node = jsgraph()->FalseConstant(); 15041cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 15051cb0ef41Sopenharmony_ci} 15061cb0ef41Sopenharmony_ci 15071cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdar() { 15081cb0ef41Sopenharmony_ci Node* value = 15091cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 15101cb0ef41Sopenharmony_ci environment()->BindAccumulator(value); 15111cb0ef41Sopenharmony_ci} 15121cb0ef41Sopenharmony_ci 15131cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitStar() { 15141cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 15151cb0ef41Sopenharmony_ci environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value); 15161cb0ef41Sopenharmony_ci} 15171cb0ef41Sopenharmony_ci 15181cb0ef41Sopenharmony_ci#define SHORT_STAR_VISITOR(Name, ...) \ 15191cb0ef41Sopenharmony_ci void BytecodeGraphBuilder::Visit##Name() { \ 15201cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); \ 15211cb0ef41Sopenharmony_ci environment()->BindRegister( \ 15221cb0ef41Sopenharmony_ci interpreter::Register::FromShortStar(interpreter::Bytecode::k##Name), \ 15231cb0ef41Sopenharmony_ci value); \ 15241cb0ef41Sopenharmony_ci } 15251cb0ef41Sopenharmony_ciSHORT_STAR_BYTECODE_LIST(SHORT_STAR_VISITOR) 15261cb0ef41Sopenharmony_ci#undef SHORT_STAR_VISITOR 15271cb0ef41Sopenharmony_ci 15281cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitMov() { 15291cb0ef41Sopenharmony_ci Node* value = 15301cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 15311cb0ef41Sopenharmony_ci environment()->BindRegister(bytecode_iterator().GetRegisterOperand(1), value); 15321cb0ef41Sopenharmony_ci} 15331cb0ef41Sopenharmony_ci 15341cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::BuildLoadGlobal(NameRef name, 15351cb0ef41Sopenharmony_ci uint32_t feedback_slot_index, 15361cb0ef41Sopenharmony_ci TypeofMode typeof_mode) { 15371cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource(feedback_slot_index); 15381cb0ef41Sopenharmony_ci DCHECK(IsLoadGlobalICKind(broker()->GetFeedbackSlotKind(feedback))); 15391cb0ef41Sopenharmony_ci const Operator* op = javascript()->LoadGlobal(name, feedback, typeof_mode); 15401cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 15411cb0ef41Sopenharmony_ci return NewNode(op, feedback_vector_node()); 15421cb0ef41Sopenharmony_ci} 15431cb0ef41Sopenharmony_ci 15441cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaGlobal() { 15451cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 15461cb0ef41Sopenharmony_ci NameRef name = MakeRefForConstantForIndexOperand<Name>(0); 15471cb0ef41Sopenharmony_ci uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1); 15481cb0ef41Sopenharmony_ci Node* node = 15491cb0ef41Sopenharmony_ci BuildLoadGlobal(name, feedback_slot_index, TypeofMode::kNotInside); 15501cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 15511cb0ef41Sopenharmony_ci} 15521cb0ef41Sopenharmony_ci 15531cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaGlobalInsideTypeof() { 15541cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 15551cb0ef41Sopenharmony_ci NameRef name = MakeRefForConstantForIndexOperand<Name>(0); 15561cb0ef41Sopenharmony_ci uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1); 15571cb0ef41Sopenharmony_ci Node* node = BuildLoadGlobal(name, feedback_slot_index, TypeofMode::kInside); 15581cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 15591cb0ef41Sopenharmony_ci} 15601cb0ef41Sopenharmony_ci 15611cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitStaGlobal() { 15621cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 15631cb0ef41Sopenharmony_ci NameRef name = MakeRefForConstantForIndexOperand<Name>(0); 15641cb0ef41Sopenharmony_ci FeedbackSource feedback = 15651cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1)); 15661cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 15671cb0ef41Sopenharmony_ci 15681cb0ef41Sopenharmony_ci LanguageMode language_mode = 15691cb0ef41Sopenharmony_ci GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(feedback)); 15701cb0ef41Sopenharmony_ci const Operator* op = javascript()->StoreGlobal(language_mode, name, feedback); 15711cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 15721cb0ef41Sopenharmony_ci Node* node = NewNode(op, value, feedback_vector_node()); 15731cb0ef41Sopenharmony_ci environment()->RecordAfterState(node, Environment::kAttachFrameState); 15741cb0ef41Sopenharmony_ci} 15751cb0ef41Sopenharmony_ci 15761cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitStaInArrayLiteral() { 15771cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 15781cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 15791cb0ef41Sopenharmony_ci Node* array = 15801cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 15811cb0ef41Sopenharmony_ci Node* index = 15821cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 15831cb0ef41Sopenharmony_ci FeedbackSource feedback = 15841cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 15851cb0ef41Sopenharmony_ci const Operator* op = javascript()->StoreInArrayLiteral(feedback); 15861cb0ef41Sopenharmony_ci 15871cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 15881cb0ef41Sopenharmony_ci TryBuildSimplifiedStoreKeyed(op, array, index, value, feedback.slot); 15891cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 15901cb0ef41Sopenharmony_ci 15911cb0ef41Sopenharmony_ci Node* node = nullptr; 15921cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 15931cb0ef41Sopenharmony_ci node = lowering.value(); 15941cb0ef41Sopenharmony_ci } else { 15951cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 15961cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 15971cb0ef41Sopenharmony_ci node = NewNode(op, array, index, value, feedback_vector_node()); 15981cb0ef41Sopenharmony_ci } 15991cb0ef41Sopenharmony_ci 16001cb0ef41Sopenharmony_ci environment()->RecordAfterState(node, Environment::kAttachFrameState); 16011cb0ef41Sopenharmony_ci} 16021cb0ef41Sopenharmony_ci 16031cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitDefineKeyedOwnPropertyInLiteral() { 16041cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 16051cb0ef41Sopenharmony_ci 16061cb0ef41Sopenharmony_ci Node* object = 16071cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 16081cb0ef41Sopenharmony_ci Node* name = 16091cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 16101cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 16111cb0ef41Sopenharmony_ci int flags = bytecode_iterator().GetFlagOperand(2); 16121cb0ef41Sopenharmony_ci FeedbackSource feedback = 16131cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(3)); 16141cb0ef41Sopenharmony_ci const Operator* op = javascript()->DefineKeyedOwnPropertyInLiteral(feedback); 16151cb0ef41Sopenharmony_ci 16161cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 16171cb0ef41Sopenharmony_ci TryBuildSimplifiedStoreKeyed(op, object, name, value, feedback.slot); 16181cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 16191cb0ef41Sopenharmony_ci 16201cb0ef41Sopenharmony_ci Node* node = nullptr; 16211cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 16221cb0ef41Sopenharmony_ci node = lowering.value(); 16231cb0ef41Sopenharmony_ci } else { 16241cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 16251cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 16261cb0ef41Sopenharmony_ci node = NewNode(op, object, name, value, jsgraph()->Constant(flags), 16271cb0ef41Sopenharmony_ci feedback_vector_node()); 16281cb0ef41Sopenharmony_ci } 16291cb0ef41Sopenharmony_ci 16301cb0ef41Sopenharmony_ci environment()->RecordAfterState(node, Environment::kAttachFrameState); 16311cb0ef41Sopenharmony_ci} 16321cb0ef41Sopenharmony_ci 16331cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCollectTypeProfile() { 16341cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 16351cb0ef41Sopenharmony_ci 16361cb0ef41Sopenharmony_ci Node* position = 16371cb0ef41Sopenharmony_ci jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); 16381cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 16391cb0ef41Sopenharmony_ci Node* vector = jsgraph()->Constant(feedback_vector()); 16401cb0ef41Sopenharmony_ci 16411cb0ef41Sopenharmony_ci const Operator* op = javascript()->CallRuntime(Runtime::kCollectTypeProfile); 16421cb0ef41Sopenharmony_ci 16431cb0ef41Sopenharmony_ci Node* node = NewNode(op, position, value, vector); 16441cb0ef41Sopenharmony_ci environment()->RecordAfterState(node, Environment::kAttachFrameState); 16451cb0ef41Sopenharmony_ci} 16461cb0ef41Sopenharmony_ci 16471cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaContextSlot() { 16481cb0ef41Sopenharmony_ci const Operator* op = javascript()->LoadContext( 16491cb0ef41Sopenharmony_ci bytecode_iterator().GetUnsignedImmediateOperand(2), 16501cb0ef41Sopenharmony_ci bytecode_iterator().GetIndexOperand(1), false); 16511cb0ef41Sopenharmony_ci Node* node = NewNode(op); 16521cb0ef41Sopenharmony_ci Node* context = 16531cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 16541cb0ef41Sopenharmony_ci NodeProperties::ReplaceContextInput(node, context); 16551cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 16561cb0ef41Sopenharmony_ci} 16571cb0ef41Sopenharmony_ci 16581cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaImmutableContextSlot() { 16591cb0ef41Sopenharmony_ci const Operator* op = javascript()->LoadContext( 16601cb0ef41Sopenharmony_ci bytecode_iterator().GetUnsignedImmediateOperand(2), 16611cb0ef41Sopenharmony_ci bytecode_iterator().GetIndexOperand(1), true); 16621cb0ef41Sopenharmony_ci Node* node = NewNode(op); 16631cb0ef41Sopenharmony_ci Node* context = 16641cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 16651cb0ef41Sopenharmony_ci NodeProperties::ReplaceContextInput(node, context); 16661cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 16671cb0ef41Sopenharmony_ci} 16681cb0ef41Sopenharmony_ci 16691cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaCurrentContextSlot() { 16701cb0ef41Sopenharmony_ci const Operator* op = javascript()->LoadContext( 16711cb0ef41Sopenharmony_ci 0, bytecode_iterator().GetIndexOperand(0), false); 16721cb0ef41Sopenharmony_ci Node* node = NewNode(op); 16731cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 16741cb0ef41Sopenharmony_ci} 16751cb0ef41Sopenharmony_ci 16761cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaImmutableCurrentContextSlot() { 16771cb0ef41Sopenharmony_ci const Operator* op = javascript()->LoadContext( 16781cb0ef41Sopenharmony_ci 0, bytecode_iterator().GetIndexOperand(0), true); 16791cb0ef41Sopenharmony_ci Node* node = NewNode(op); 16801cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 16811cb0ef41Sopenharmony_ci} 16821cb0ef41Sopenharmony_ci 16831cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitStaContextSlot() { 16841cb0ef41Sopenharmony_ci const Operator* op = javascript()->StoreContext( 16851cb0ef41Sopenharmony_ci bytecode_iterator().GetUnsignedImmediateOperand(2), 16861cb0ef41Sopenharmony_ci bytecode_iterator().GetIndexOperand(1)); 16871cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 16881cb0ef41Sopenharmony_ci Node* node = NewNode(op, value); 16891cb0ef41Sopenharmony_ci Node* context = 16901cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 16911cb0ef41Sopenharmony_ci NodeProperties::ReplaceContextInput(node, context); 16921cb0ef41Sopenharmony_ci} 16931cb0ef41Sopenharmony_ci 16941cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitStaCurrentContextSlot() { 16951cb0ef41Sopenharmony_ci const Operator* op = 16961cb0ef41Sopenharmony_ci javascript()->StoreContext(0, bytecode_iterator().GetIndexOperand(0)); 16971cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 16981cb0ef41Sopenharmony_ci NewNode(op, value); 16991cb0ef41Sopenharmony_ci} 17001cb0ef41Sopenharmony_ci 17011cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildLdaLookupSlot(TypeofMode typeof_mode) { 17021cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 17031cb0ef41Sopenharmony_ci Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0)); 17041cb0ef41Sopenharmony_ci const Operator* op = 17051cb0ef41Sopenharmony_ci javascript()->CallRuntime(typeof_mode == TypeofMode::kNotInside 17061cb0ef41Sopenharmony_ci ? Runtime::kLoadLookupSlot 17071cb0ef41Sopenharmony_ci : Runtime::kLoadLookupSlotInsideTypeof); 17081cb0ef41Sopenharmony_ci Node* value = NewNode(op, name); 17091cb0ef41Sopenharmony_ci environment()->BindAccumulator(value, Environment::kAttachFrameState); 17101cb0ef41Sopenharmony_ci} 17111cb0ef41Sopenharmony_ci 17121cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaLookupSlot() { 17131cb0ef41Sopenharmony_ci BuildLdaLookupSlot(TypeofMode::kNotInside); 17141cb0ef41Sopenharmony_ci} 17151cb0ef41Sopenharmony_ci 17161cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaLookupSlotInsideTypeof() { 17171cb0ef41Sopenharmony_ci BuildLdaLookupSlot(TypeofMode::kInside); 17181cb0ef41Sopenharmony_ci} 17191cb0ef41Sopenharmony_ci 17201cb0ef41Sopenharmony_ciBytecodeGraphBuilder::Environment* 17211cb0ef41Sopenharmony_ciBytecodeGraphBuilder::CheckContextExtensionAtDepth( 17221cb0ef41Sopenharmony_ci Environment* slow_environment, uint32_t depth) { 17231cb0ef41Sopenharmony_ci Node* extension_slot = NewNode( 17241cb0ef41Sopenharmony_ci javascript()->LoadContext(depth, Context::EXTENSION_INDEX, false)); 17251cb0ef41Sopenharmony_ci Node* check_no_extension = 17261cb0ef41Sopenharmony_ci NewNode(simplified()->ReferenceEqual(), extension_slot, 17271cb0ef41Sopenharmony_ci jsgraph()->UndefinedConstant()); 17281cb0ef41Sopenharmony_ci NewBranch(check_no_extension); 17291cb0ef41Sopenharmony_ci { 17301cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 17311cb0ef41Sopenharmony_ci NewIfFalse(); 17321cb0ef41Sopenharmony_ci // If there is an extension, merge into the slow path. 17331cb0ef41Sopenharmony_ci if (slow_environment == nullptr) { 17341cb0ef41Sopenharmony_ci slow_environment = environment(); 17351cb0ef41Sopenharmony_ci NewMerge(); 17361cb0ef41Sopenharmony_ci } else { 17371cb0ef41Sopenharmony_ci slow_environment->Merge(environment(), 17381cb0ef41Sopenharmony_ci bytecode_analysis().GetInLivenessFor( 17391cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 17401cb0ef41Sopenharmony_ci } 17411cb0ef41Sopenharmony_ci } 17421cb0ef41Sopenharmony_ci NewIfTrue(); 17431cb0ef41Sopenharmony_ci // Do nothing on if there is no extension, eventually falling through to 17441cb0ef41Sopenharmony_ci // the fast path. 17451cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(slow_environment); 17461cb0ef41Sopenharmony_ci return slow_environment; 17471cb0ef41Sopenharmony_ci} 17481cb0ef41Sopenharmony_ci 17491cb0ef41Sopenharmony_cibase::Optional<ScopeInfoRef> BytecodeGraphBuilder::TryGetScopeInfo() { 17501cb0ef41Sopenharmony_ci Node* context = environment()->Context(); 17511cb0ef41Sopenharmony_ci switch (context->opcode()) { 17521cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateFunctionContext: 17531cb0ef41Sopenharmony_ci return CreateFunctionContextParametersOf(context->op()) 17541cb0ef41Sopenharmony_ci .scope_info(broker()); 17551cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateBlockContext: 17561cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateCatchContext: 17571cb0ef41Sopenharmony_ci case IrOpcode::kJSCreateWithContext: 17581cb0ef41Sopenharmony_ci return ScopeInfoOf(broker(), context->op()); 17591cb0ef41Sopenharmony_ci case IrOpcode::kParameter: { 17601cb0ef41Sopenharmony_ci ScopeInfoRef scope_info = shared_info_.scope_info(); 17611cb0ef41Sopenharmony_ci if (scope_info.HasOuterScopeInfo()) { 17621cb0ef41Sopenharmony_ci scope_info = scope_info.OuterScopeInfo(); 17631cb0ef41Sopenharmony_ci } 17641cb0ef41Sopenharmony_ci return scope_info; 17651cb0ef41Sopenharmony_ci } 17661cb0ef41Sopenharmony_ci default: 17671cb0ef41Sopenharmony_ci return base::nullopt; 17681cb0ef41Sopenharmony_ci } 17691cb0ef41Sopenharmony_ci} 17701cb0ef41Sopenharmony_ci 17711cb0ef41Sopenharmony_ciBytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions( 17721cb0ef41Sopenharmony_ci uint32_t depth) { 17731cb0ef41Sopenharmony_ci base::Optional<ScopeInfoRef> maybe_scope_info = TryGetScopeInfo(); 17741cb0ef41Sopenharmony_ci if (!maybe_scope_info.has_value()) { 17751cb0ef41Sopenharmony_ci return CheckContextExtensionsSlowPath(depth); 17761cb0ef41Sopenharmony_ci } 17771cb0ef41Sopenharmony_ci 17781cb0ef41Sopenharmony_ci ScopeInfoRef scope_info = maybe_scope_info.value(); 17791cb0ef41Sopenharmony_ci // We only need to check up to the last-but-one depth, because an eval 17801cb0ef41Sopenharmony_ci // in the same scope as the variable itself has no way of shadowing it. 17811cb0ef41Sopenharmony_ci Environment* slow_environment = nullptr; 17821cb0ef41Sopenharmony_ci for (uint32_t d = 0; d < depth; d++) { 17831cb0ef41Sopenharmony_ci if (scope_info.HasContextExtensionSlot()) { 17841cb0ef41Sopenharmony_ci slow_environment = CheckContextExtensionAtDepth(slow_environment, d); 17851cb0ef41Sopenharmony_ci } 17861cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!scope_info.HasOuterScopeInfo(), d + 1 == depth); 17871cb0ef41Sopenharmony_ci if (scope_info.HasOuterScopeInfo()) { 17881cb0ef41Sopenharmony_ci scope_info = scope_info.OuterScopeInfo(); 17891cb0ef41Sopenharmony_ci } 17901cb0ef41Sopenharmony_ci } 17911cb0ef41Sopenharmony_ci 17921cb0ef41Sopenharmony_ci // The depth can be zero, in which case no slow-path checks are built, and 17931cb0ef41Sopenharmony_ci // the slow path environment can be null. 17941cb0ef41Sopenharmony_ci DCHECK_IMPLIES(slow_environment == nullptr, depth == 0); 17951cb0ef41Sopenharmony_ci return slow_environment; 17961cb0ef41Sopenharmony_ci} 17971cb0ef41Sopenharmony_ci 17981cb0ef41Sopenharmony_ciBytecodeGraphBuilder::Environment* 17991cb0ef41Sopenharmony_ciBytecodeGraphBuilder::CheckContextExtensionsSlowPath(uint32_t depth) { 18001cb0ef41Sopenharmony_ci // Output environment where the context has an extension 18011cb0ef41Sopenharmony_ci Environment* slow_environment = nullptr; 18021cb0ef41Sopenharmony_ci 18031cb0ef41Sopenharmony_ci // We only need to check up to the last-but-one depth, because an eval 18041cb0ef41Sopenharmony_ci // in the same scope as the variable itself has no way of shadowing it. 18051cb0ef41Sopenharmony_ci for (uint32_t d = 0; d < depth; d++) { 18061cb0ef41Sopenharmony_ci Node* has_extension = NewNode(javascript()->HasContextExtension(d)); 18071cb0ef41Sopenharmony_ci 18081cb0ef41Sopenharmony_ci Environment* undefined_extension_env; 18091cb0ef41Sopenharmony_ci NewBranch(has_extension); 18101cb0ef41Sopenharmony_ci { 18111cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 18121cb0ef41Sopenharmony_ci NewIfTrue(); 18131cb0ef41Sopenharmony_ci slow_environment = CheckContextExtensionAtDepth(slow_environment, d); 18141cb0ef41Sopenharmony_ci undefined_extension_env = environment(); 18151cb0ef41Sopenharmony_ci } 18161cb0ef41Sopenharmony_ci NewIfFalse(); 18171cb0ef41Sopenharmony_ci environment()->Merge(undefined_extension_env, 18181cb0ef41Sopenharmony_ci bytecode_analysis().GetInLivenessFor( 18191cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 18201cb0ef41Sopenharmony_ci mark_as_needing_eager_checkpoint(true); 18211cb0ef41Sopenharmony_ci // Do nothing on if there is no extension, eventually falling through to 18221cb0ef41Sopenharmony_ci // the fast path. 18231cb0ef41Sopenharmony_ci } 18241cb0ef41Sopenharmony_ci 18251cb0ef41Sopenharmony_ci // The depth can be zero, in which case no slow-path checks are built, and 18261cb0ef41Sopenharmony_ci // the slow path environment can be null. 18271cb0ef41Sopenharmony_ci DCHECK_IMPLIES(slow_environment == nullptr, depth == 0); 18281cb0ef41Sopenharmony_ci return slow_environment; 18291cb0ef41Sopenharmony_ci} 18301cb0ef41Sopenharmony_ci 18311cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildLdaLookupContextSlot(TypeofMode typeof_mode) { 18321cb0ef41Sopenharmony_ci uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2); 18331cb0ef41Sopenharmony_ci 18341cb0ef41Sopenharmony_ci // Check if any context in the depth has an extension. 18351cb0ef41Sopenharmony_ci Environment* slow_environment = CheckContextExtensions(depth); 18361cb0ef41Sopenharmony_ci 18371cb0ef41Sopenharmony_ci // Fast path, do a context load. 18381cb0ef41Sopenharmony_ci { 18391cb0ef41Sopenharmony_ci uint32_t slot_index = bytecode_iterator().GetIndexOperand(1); 18401cb0ef41Sopenharmony_ci 18411cb0ef41Sopenharmony_ci const Operator* op = javascript()->LoadContext(depth, slot_index, false); 18421cb0ef41Sopenharmony_ci environment()->BindAccumulator(NewNode(op)); 18431cb0ef41Sopenharmony_ci } 18441cb0ef41Sopenharmony_ci 18451cb0ef41Sopenharmony_ci // Only build the slow path if there were any slow-path checks. 18461cb0ef41Sopenharmony_ci if (slow_environment != nullptr) { 18471cb0ef41Sopenharmony_ci // Add a merge to the fast environment. 18481cb0ef41Sopenharmony_ci NewMerge(); 18491cb0ef41Sopenharmony_ci Environment* fast_environment = environment(); 18501cb0ef41Sopenharmony_ci 18511cb0ef41Sopenharmony_ci // Slow path, do a runtime load lookup. 18521cb0ef41Sopenharmony_ci set_environment(slow_environment); 18531cb0ef41Sopenharmony_ci { 18541cb0ef41Sopenharmony_ci Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0)); 18551cb0ef41Sopenharmony_ci 18561cb0ef41Sopenharmony_ci const Operator* op = 18571cb0ef41Sopenharmony_ci javascript()->CallRuntime(typeof_mode == TypeofMode::kNotInside 18581cb0ef41Sopenharmony_ci ? Runtime::kLoadLookupSlot 18591cb0ef41Sopenharmony_ci : Runtime::kLoadLookupSlotInsideTypeof); 18601cb0ef41Sopenharmony_ci Node* value = NewNode(op, name); 18611cb0ef41Sopenharmony_ci environment()->BindAccumulator(value, Environment::kAttachFrameState); 18621cb0ef41Sopenharmony_ci } 18631cb0ef41Sopenharmony_ci 18641cb0ef41Sopenharmony_ci fast_environment->Merge(environment(), 18651cb0ef41Sopenharmony_ci bytecode_analysis().GetOutLivenessFor( 18661cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 18671cb0ef41Sopenharmony_ci set_environment(fast_environment); 18681cb0ef41Sopenharmony_ci mark_as_needing_eager_checkpoint(true); 18691cb0ef41Sopenharmony_ci } 18701cb0ef41Sopenharmony_ci} 18711cb0ef41Sopenharmony_ci 18721cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaLookupContextSlot() { 18731cb0ef41Sopenharmony_ci BuildLdaLookupContextSlot(TypeofMode::kNotInside); 18741cb0ef41Sopenharmony_ci} 18751cb0ef41Sopenharmony_ci 18761cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaLookupContextSlotInsideTypeof() { 18771cb0ef41Sopenharmony_ci BuildLdaLookupContextSlot(TypeofMode::kInside); 18781cb0ef41Sopenharmony_ci} 18791cb0ef41Sopenharmony_ci 18801cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildLdaLookupGlobalSlot(TypeofMode typeof_mode) { 18811cb0ef41Sopenharmony_ci uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(2); 18821cb0ef41Sopenharmony_ci 18831cb0ef41Sopenharmony_ci // Check if any context in the depth has an extension. 18841cb0ef41Sopenharmony_ci Environment* slow_environment = CheckContextExtensions(depth); 18851cb0ef41Sopenharmony_ci 18861cb0ef41Sopenharmony_ci // Fast path, do a global load. 18871cb0ef41Sopenharmony_ci { 18881cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 18891cb0ef41Sopenharmony_ci NameRef name = MakeRefForConstantForIndexOperand<Name>(0); 18901cb0ef41Sopenharmony_ci uint32_t feedback_slot_index = bytecode_iterator().GetIndexOperand(1); 18911cb0ef41Sopenharmony_ci Node* node = BuildLoadGlobal(name, feedback_slot_index, typeof_mode); 18921cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 18931cb0ef41Sopenharmony_ci } 18941cb0ef41Sopenharmony_ci 18951cb0ef41Sopenharmony_ci // Only build the slow path if there were any slow-path checks. 18961cb0ef41Sopenharmony_ci if (slow_environment != nullptr) { 18971cb0ef41Sopenharmony_ci // Add a merge to the fast environment. 18981cb0ef41Sopenharmony_ci NewMerge(); 18991cb0ef41Sopenharmony_ci Environment* fast_environment = environment(); 19001cb0ef41Sopenharmony_ci 19011cb0ef41Sopenharmony_ci // Slow path, do a runtime load lookup. 19021cb0ef41Sopenharmony_ci set_environment(slow_environment); 19031cb0ef41Sopenharmony_ci { 19041cb0ef41Sopenharmony_ci Node* name = 19051cb0ef41Sopenharmony_ci jsgraph()->Constant(MakeRefForConstantForIndexOperand<Name>(0)); 19061cb0ef41Sopenharmony_ci 19071cb0ef41Sopenharmony_ci const Operator* op = 19081cb0ef41Sopenharmony_ci javascript()->CallRuntime(typeof_mode == TypeofMode::kNotInside 19091cb0ef41Sopenharmony_ci ? Runtime::kLoadLookupSlot 19101cb0ef41Sopenharmony_ci : Runtime::kLoadLookupSlotInsideTypeof); 19111cb0ef41Sopenharmony_ci Node* value = NewNode(op, name); 19121cb0ef41Sopenharmony_ci environment()->BindAccumulator(value, Environment::kAttachFrameState); 19131cb0ef41Sopenharmony_ci } 19141cb0ef41Sopenharmony_ci 19151cb0ef41Sopenharmony_ci fast_environment->Merge(environment(), 19161cb0ef41Sopenharmony_ci bytecode_analysis().GetOutLivenessFor( 19171cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 19181cb0ef41Sopenharmony_ci set_environment(fast_environment); 19191cb0ef41Sopenharmony_ci mark_as_needing_eager_checkpoint(true); 19201cb0ef41Sopenharmony_ci } 19211cb0ef41Sopenharmony_ci} 19221cb0ef41Sopenharmony_ci 19231cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaLookupGlobalSlot() { 19241cb0ef41Sopenharmony_ci BuildLdaLookupGlobalSlot(TypeofMode::kNotInside); 19251cb0ef41Sopenharmony_ci} 19261cb0ef41Sopenharmony_ci 19271cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaLookupGlobalSlotInsideTypeof() { 19281cb0ef41Sopenharmony_ci BuildLdaLookupGlobalSlot(TypeofMode::kInside); 19291cb0ef41Sopenharmony_ci} 19301cb0ef41Sopenharmony_ci 19311cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitStaLookupSlot() { 19321cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 19331cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 19341cb0ef41Sopenharmony_ci Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0)); 19351cb0ef41Sopenharmony_ci int bytecode_flags = bytecode_iterator().GetFlagOperand(1); 19361cb0ef41Sopenharmony_ci LanguageMode language_mode = static_cast<LanguageMode>( 19371cb0ef41Sopenharmony_ci interpreter::StoreLookupSlotFlags::LanguageModeBit::decode( 19381cb0ef41Sopenharmony_ci bytecode_flags)); 19391cb0ef41Sopenharmony_ci LookupHoistingMode lookup_hoisting_mode = static_cast<LookupHoistingMode>( 19401cb0ef41Sopenharmony_ci interpreter::StoreLookupSlotFlags::LookupHoistingModeBit::decode( 19411cb0ef41Sopenharmony_ci bytecode_flags)); 19421cb0ef41Sopenharmony_ci DCHECK_IMPLIES(lookup_hoisting_mode == LookupHoistingMode::kLegacySloppy, 19431cb0ef41Sopenharmony_ci is_sloppy(language_mode)); 19441cb0ef41Sopenharmony_ci const Operator* op = javascript()->CallRuntime( 19451cb0ef41Sopenharmony_ci is_strict(language_mode) 19461cb0ef41Sopenharmony_ci ? Runtime::kStoreLookupSlot_Strict 19471cb0ef41Sopenharmony_ci : lookup_hoisting_mode == LookupHoistingMode::kLegacySloppy 19481cb0ef41Sopenharmony_ci ? Runtime::kStoreLookupSlot_SloppyHoisting 19491cb0ef41Sopenharmony_ci : Runtime::kStoreLookupSlot_Sloppy); 19501cb0ef41Sopenharmony_ci Node* store = NewNode(op, name, value); 19511cb0ef41Sopenharmony_ci environment()->BindAccumulator(store, Environment::kAttachFrameState); 19521cb0ef41Sopenharmony_ci} 19531cb0ef41Sopenharmony_ci 19541cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitGetNamedProperty() { 19551cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 19561cb0ef41Sopenharmony_ci Node* object = 19571cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 19581cb0ef41Sopenharmony_ci NameRef name = MakeRefForConstantForIndexOperand<Name>(1); 19591cb0ef41Sopenharmony_ci FeedbackSource feedback = 19601cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 19611cb0ef41Sopenharmony_ci const Operator* op = javascript()->LoadNamed(name, feedback); 19621cb0ef41Sopenharmony_ci 19631cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 19641cb0ef41Sopenharmony_ci TryBuildSimplifiedLoadNamed(op, feedback.slot); 19651cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 19661cb0ef41Sopenharmony_ci 19671cb0ef41Sopenharmony_ci Node* node = nullptr; 19681cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 19691cb0ef41Sopenharmony_ci node = lowering.value(); 19701cb0ef41Sopenharmony_ci } else { 19711cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 19721cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 19731cb0ef41Sopenharmony_ci node = NewNode(op, object, feedback_vector_node()); 19741cb0ef41Sopenharmony_ci } 19751cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 19761cb0ef41Sopenharmony_ci} 19771cb0ef41Sopenharmony_ci 19781cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitGetNamedPropertyFromSuper() { 19791cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 19801cb0ef41Sopenharmony_ci Node* receiver = 19811cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 19821cb0ef41Sopenharmony_ci Node* home_object = environment()->LookupAccumulator(); 19831cb0ef41Sopenharmony_ci NameRef name = MakeRefForConstantForIndexOperand<Name>(1); 19841cb0ef41Sopenharmony_ci 19851cb0ef41Sopenharmony_ci FeedbackSource feedback = 19861cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 19871cb0ef41Sopenharmony_ci const Operator* op = javascript()->LoadNamedFromSuper(name, feedback); 19881cb0ef41Sopenharmony_ci 19891cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 19901cb0ef41Sopenharmony_ci TryBuildSimplifiedLoadNamed(op, feedback.slot); 19911cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 19921cb0ef41Sopenharmony_ci 19931cb0ef41Sopenharmony_ci Node* node = nullptr; 19941cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 19951cb0ef41Sopenharmony_ci node = lowering.value(); 19961cb0ef41Sopenharmony_ci } else { 19971cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 19981cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 19991cb0ef41Sopenharmony_ci node = NewNode(op, receiver, home_object, feedback_vector_node()); 20001cb0ef41Sopenharmony_ci } 20011cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 20021cb0ef41Sopenharmony_ci} 20031cb0ef41Sopenharmony_ci 20041cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitGetKeyedProperty() { 20051cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 20061cb0ef41Sopenharmony_ci Node* key = environment()->LookupAccumulator(); 20071cb0ef41Sopenharmony_ci Node* object = 20081cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 20091cb0ef41Sopenharmony_ci FeedbackSource feedback = 20101cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1)); 20111cb0ef41Sopenharmony_ci const Operator* op = javascript()->LoadProperty(feedback); 20121cb0ef41Sopenharmony_ci 20131cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 20141cb0ef41Sopenharmony_ci TryBuildSimplifiedLoadKeyed(op, object, key, feedback.slot); 20151cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 20161cb0ef41Sopenharmony_ci 20171cb0ef41Sopenharmony_ci Node* node = nullptr; 20181cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 20191cb0ef41Sopenharmony_ci node = lowering.value(); 20201cb0ef41Sopenharmony_ci } else { 20211cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 20221cb0ef41Sopenharmony_ci STATIC_ASSERT(JSLoadPropertyNode::ObjectIndex() == 0); 20231cb0ef41Sopenharmony_ci STATIC_ASSERT(JSLoadPropertyNode::KeyIndex() == 1); 20241cb0ef41Sopenharmony_ci STATIC_ASSERT(JSLoadPropertyNode::FeedbackVectorIndex() == 2); 20251cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 20261cb0ef41Sopenharmony_ci node = NewNode(op, object, key, feedback_vector_node()); 20271cb0ef41Sopenharmony_ci } 20281cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 20291cb0ef41Sopenharmony_ci} 20301cb0ef41Sopenharmony_ci 20311cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildNamedStore(NamedStoreMode store_mode) { 20321cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 20331cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 20341cb0ef41Sopenharmony_ci Node* object = 20351cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 20361cb0ef41Sopenharmony_ci NameRef name = MakeRefForConstantForIndexOperand<Name>(1); 20371cb0ef41Sopenharmony_ci FeedbackSource feedback = 20381cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 20391cb0ef41Sopenharmony_ci 20401cb0ef41Sopenharmony_ci const Operator* op; 20411cb0ef41Sopenharmony_ci if (store_mode == NamedStoreMode::kDefineOwn) { 20421cb0ef41Sopenharmony_ci DCHECK_EQ(FeedbackSlotKind::kDefineNamedOwn, 20431cb0ef41Sopenharmony_ci broker()->GetFeedbackSlotKind(feedback)); 20441cb0ef41Sopenharmony_ci 20451cb0ef41Sopenharmony_ci op = javascript()->DefineNamedOwnProperty(name, feedback); 20461cb0ef41Sopenharmony_ci } else { 20471cb0ef41Sopenharmony_ci DCHECK_EQ(NamedStoreMode::kSet, store_mode); 20481cb0ef41Sopenharmony_ci LanguageMode language_mode = 20491cb0ef41Sopenharmony_ci GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(feedback)); 20501cb0ef41Sopenharmony_ci op = javascript()->SetNamedProperty(language_mode, name, feedback); 20511cb0ef41Sopenharmony_ci } 20521cb0ef41Sopenharmony_ci 20531cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 20541cb0ef41Sopenharmony_ci TryBuildSimplifiedStoreNamed(op, object, value, feedback.slot); 20551cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 20561cb0ef41Sopenharmony_ci 20571cb0ef41Sopenharmony_ci Node* node = nullptr; 20581cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 20591cb0ef41Sopenharmony_ci node = lowering.value(); 20601cb0ef41Sopenharmony_ci } else { 20611cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 20621cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 20631cb0ef41Sopenharmony_ci node = NewNode(op, object, value, feedback_vector_node()); 20641cb0ef41Sopenharmony_ci } 20651cb0ef41Sopenharmony_ci environment()->RecordAfterState(node, Environment::kAttachFrameState); 20661cb0ef41Sopenharmony_ci} 20671cb0ef41Sopenharmony_ci 20681cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitSetNamedProperty() { 20691cb0ef41Sopenharmony_ci BuildNamedStore(NamedStoreMode::kSet); 20701cb0ef41Sopenharmony_ci} 20711cb0ef41Sopenharmony_ci 20721cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitDefineNamedOwnProperty() { 20731cb0ef41Sopenharmony_ci BuildNamedStore(NamedStoreMode::kDefineOwn); 20741cb0ef41Sopenharmony_ci} 20751cb0ef41Sopenharmony_ci 20761cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitSetKeyedProperty() { 20771cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 20781cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 20791cb0ef41Sopenharmony_ci Node* object = 20801cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 20811cb0ef41Sopenharmony_ci Node* key = 20821cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 20831cb0ef41Sopenharmony_ci FeedbackSource source = 20841cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 20851cb0ef41Sopenharmony_ci LanguageMode language_mode = 20861cb0ef41Sopenharmony_ci GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(source)); 20871cb0ef41Sopenharmony_ci const Operator* op = javascript()->SetKeyedProperty(language_mode, source); 20881cb0ef41Sopenharmony_ci 20891cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 20901cb0ef41Sopenharmony_ci TryBuildSimplifiedStoreKeyed(op, object, key, value, source.slot); 20911cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 20921cb0ef41Sopenharmony_ci 20931cb0ef41Sopenharmony_ci Node* node = nullptr; 20941cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 20951cb0ef41Sopenharmony_ci node = lowering.value(); 20961cb0ef41Sopenharmony_ci } else { 20971cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 20981cb0ef41Sopenharmony_ci STATIC_ASSERT(JSSetKeyedPropertyNode::ObjectIndex() == 0); 20991cb0ef41Sopenharmony_ci STATIC_ASSERT(JSSetKeyedPropertyNode::KeyIndex() == 1); 21001cb0ef41Sopenharmony_ci STATIC_ASSERT(JSSetKeyedPropertyNode::ValueIndex() == 2); 21011cb0ef41Sopenharmony_ci STATIC_ASSERT(JSSetKeyedPropertyNode::FeedbackVectorIndex() == 3); 21021cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 21031cb0ef41Sopenharmony_ci node = NewNode(op, object, key, value, feedback_vector_node()); 21041cb0ef41Sopenharmony_ci } 21051cb0ef41Sopenharmony_ci 21061cb0ef41Sopenharmony_ci environment()->RecordAfterState(node, Environment::kAttachFrameState); 21071cb0ef41Sopenharmony_ci} 21081cb0ef41Sopenharmony_ci 21091cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitDefineKeyedOwnProperty() { 21101cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 21111cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 21121cb0ef41Sopenharmony_ci Node* object = 21131cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 21141cb0ef41Sopenharmony_ci Node* key = 21151cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 21161cb0ef41Sopenharmony_ci FeedbackSource source = 21171cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 21181cb0ef41Sopenharmony_ci LanguageMode language_mode = 21191cb0ef41Sopenharmony_ci GetLanguageModeFromSlotKind(broker()->GetFeedbackSlotKind(source)); 21201cb0ef41Sopenharmony_ci 21211cb0ef41Sopenharmony_ci const Operator* op = 21221cb0ef41Sopenharmony_ci javascript()->DefineKeyedOwnProperty(language_mode, source); 21231cb0ef41Sopenharmony_ci 21241cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 21251cb0ef41Sopenharmony_ci TryBuildSimplifiedStoreKeyed(op, object, key, value, source.slot); 21261cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 21271cb0ef41Sopenharmony_ci 21281cb0ef41Sopenharmony_ci Node* node = nullptr; 21291cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 21301cb0ef41Sopenharmony_ci node = lowering.value(); 21311cb0ef41Sopenharmony_ci } else { 21321cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 21331cb0ef41Sopenharmony_ci STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::ObjectIndex() == 0); 21341cb0ef41Sopenharmony_ci STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::KeyIndex() == 1); 21351cb0ef41Sopenharmony_ci STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::ValueIndex() == 2); 21361cb0ef41Sopenharmony_ci STATIC_ASSERT(JSDefineKeyedOwnPropertyNode::FeedbackVectorIndex() == 3); 21371cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 21381cb0ef41Sopenharmony_ci node = NewNode(op, object, key, value, feedback_vector_node()); 21391cb0ef41Sopenharmony_ci } 21401cb0ef41Sopenharmony_ci 21411cb0ef41Sopenharmony_ci environment()->RecordAfterState(node, Environment::kAttachFrameState); 21421cb0ef41Sopenharmony_ci} 21431cb0ef41Sopenharmony_ci 21441cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLdaModuleVariable() { 21451cb0ef41Sopenharmony_ci int32_t cell_index = bytecode_iterator().GetImmediateOperand(0); 21461cb0ef41Sopenharmony_ci uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1); 21471cb0ef41Sopenharmony_ci Node* module = 21481cb0ef41Sopenharmony_ci NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true)); 21491cb0ef41Sopenharmony_ci Node* value = NewNode(javascript()->LoadModule(cell_index), module); 21501cb0ef41Sopenharmony_ci environment()->BindAccumulator(value); 21511cb0ef41Sopenharmony_ci} 21521cb0ef41Sopenharmony_ci 21531cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitStaModuleVariable() { 21541cb0ef41Sopenharmony_ci int32_t cell_index = bytecode_iterator().GetImmediateOperand(0); 21551cb0ef41Sopenharmony_ci uint32_t depth = bytecode_iterator().GetUnsignedImmediateOperand(1); 21561cb0ef41Sopenharmony_ci Node* module = 21571cb0ef41Sopenharmony_ci NewNode(javascript()->LoadContext(depth, Context::EXTENSION_INDEX, true)); 21581cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 21591cb0ef41Sopenharmony_ci NewNode(javascript()->StoreModule(cell_index), module, value); 21601cb0ef41Sopenharmony_ci} 21611cb0ef41Sopenharmony_ci 21621cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitPushContext() { 21631cb0ef41Sopenharmony_ci Node* new_context = environment()->LookupAccumulator(); 21641cb0ef41Sopenharmony_ci environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), 21651cb0ef41Sopenharmony_ci environment()->Context()); 21661cb0ef41Sopenharmony_ci environment()->SetContext(new_context); 21671cb0ef41Sopenharmony_ci} 21681cb0ef41Sopenharmony_ci 21691cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitPopContext() { 21701cb0ef41Sopenharmony_ci Node* context = 21711cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 21721cb0ef41Sopenharmony_ci environment()->SetContext(context); 21731cb0ef41Sopenharmony_ci} 21741cb0ef41Sopenharmony_ci 21751cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateClosure() { 21761cb0ef41Sopenharmony_ci SharedFunctionInfoRef shared_info = 21771cb0ef41Sopenharmony_ci MakeRefForConstantForIndexOperand<SharedFunctionInfo>(0); 21781cb0ef41Sopenharmony_ci AllocationType allocation = 21791cb0ef41Sopenharmony_ci interpreter::CreateClosureFlags::PretenuredBit::decode( 21801cb0ef41Sopenharmony_ci bytecode_iterator().GetFlagOperand(2)) 21811cb0ef41Sopenharmony_ci ? AllocationType::kOld 21821cb0ef41Sopenharmony_ci : AllocationType::kYoung; 21831cb0ef41Sopenharmony_ci CodeTRef compile_lazy = 21841cb0ef41Sopenharmony_ci MakeRef(broker(), *BUILTIN_CODE(jsgraph()->isolate(), CompileLazy)); 21851cb0ef41Sopenharmony_ci const Operator* op = 21861cb0ef41Sopenharmony_ci javascript()->CreateClosure(shared_info, compile_lazy, allocation); 21871cb0ef41Sopenharmony_ci Node* closure = NewNode( 21881cb0ef41Sopenharmony_ci op, BuildLoadFeedbackCell(bytecode_iterator().GetIndexOperand(1))); 21891cb0ef41Sopenharmony_ci environment()->BindAccumulator(closure); 21901cb0ef41Sopenharmony_ci} 21911cb0ef41Sopenharmony_ci 21921cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateBlockContext() { 21931cb0ef41Sopenharmony_ci ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(0); 21941cb0ef41Sopenharmony_ci const Operator* op = javascript()->CreateBlockContext(scope_info); 21951cb0ef41Sopenharmony_ci Node* context = NewNode(op); 21961cb0ef41Sopenharmony_ci environment()->BindAccumulator(context); 21971cb0ef41Sopenharmony_ci} 21981cb0ef41Sopenharmony_ci 21991cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateFunctionContext() { 22001cb0ef41Sopenharmony_ci ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(0); 22011cb0ef41Sopenharmony_ci uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(1); 22021cb0ef41Sopenharmony_ci const Operator* op = 22031cb0ef41Sopenharmony_ci javascript()->CreateFunctionContext(scope_info, slots, FUNCTION_SCOPE); 22041cb0ef41Sopenharmony_ci Node* context = NewNode(op); 22051cb0ef41Sopenharmony_ci environment()->BindAccumulator(context); 22061cb0ef41Sopenharmony_ci} 22071cb0ef41Sopenharmony_ci 22081cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateEvalContext() { 22091cb0ef41Sopenharmony_ci ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(0); 22101cb0ef41Sopenharmony_ci uint32_t slots = bytecode_iterator().GetUnsignedImmediateOperand(1); 22111cb0ef41Sopenharmony_ci const Operator* op = 22121cb0ef41Sopenharmony_ci javascript()->CreateFunctionContext(scope_info, slots, EVAL_SCOPE); 22131cb0ef41Sopenharmony_ci Node* context = NewNode(op); 22141cb0ef41Sopenharmony_ci environment()->BindAccumulator(context); 22151cb0ef41Sopenharmony_ci} 22161cb0ef41Sopenharmony_ci 22171cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateCatchContext() { 22181cb0ef41Sopenharmony_ci interpreter::Register reg = bytecode_iterator().GetRegisterOperand(0); 22191cb0ef41Sopenharmony_ci Node* exception = environment()->LookupRegister(reg); 22201cb0ef41Sopenharmony_ci ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(1); 22211cb0ef41Sopenharmony_ci 22221cb0ef41Sopenharmony_ci const Operator* op = javascript()->CreateCatchContext(scope_info); 22231cb0ef41Sopenharmony_ci Node* context = NewNode(op, exception); 22241cb0ef41Sopenharmony_ci environment()->BindAccumulator(context); 22251cb0ef41Sopenharmony_ci} 22261cb0ef41Sopenharmony_ci 22271cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateWithContext() { 22281cb0ef41Sopenharmony_ci Node* object = 22291cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 22301cb0ef41Sopenharmony_ci ScopeInfoRef scope_info = MakeRefForConstantForIndexOperand<ScopeInfo>(1); 22311cb0ef41Sopenharmony_ci 22321cb0ef41Sopenharmony_ci const Operator* op = javascript()->CreateWithContext(scope_info); 22331cb0ef41Sopenharmony_ci Node* context = NewNode(op, object); 22341cb0ef41Sopenharmony_ci environment()->BindAccumulator(context); 22351cb0ef41Sopenharmony_ci} 22361cb0ef41Sopenharmony_ci 22371cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildCreateArguments(CreateArgumentsType type) { 22381cb0ef41Sopenharmony_ci const Operator* op = javascript()->CreateArguments(type); 22391cb0ef41Sopenharmony_ci Node* object = NewNode(op, GetFunctionClosure()); 22401cb0ef41Sopenharmony_ci environment()->BindAccumulator(object, Environment::kAttachFrameState); 22411cb0ef41Sopenharmony_ci} 22421cb0ef41Sopenharmony_ci 22431cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateMappedArguments() { 22441cb0ef41Sopenharmony_ci BuildCreateArguments(CreateArgumentsType::kMappedArguments); 22451cb0ef41Sopenharmony_ci} 22461cb0ef41Sopenharmony_ci 22471cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateUnmappedArguments() { 22481cb0ef41Sopenharmony_ci BuildCreateArguments(CreateArgumentsType::kUnmappedArguments); 22491cb0ef41Sopenharmony_ci} 22501cb0ef41Sopenharmony_ci 22511cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateRestParameter() { 22521cb0ef41Sopenharmony_ci BuildCreateArguments(CreateArgumentsType::kRestParameter); 22531cb0ef41Sopenharmony_ci} 22541cb0ef41Sopenharmony_ci 22551cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateRegExpLiteral() { 22561cb0ef41Sopenharmony_ci StringRef constant_pattern = MakeRefForConstantForIndexOperand<String>(0); 22571cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(1); 22581cb0ef41Sopenharmony_ci FeedbackSource pair = CreateFeedbackSource(slot_id); 22591cb0ef41Sopenharmony_ci int literal_flags = bytecode_iterator().GetFlagOperand(2); 22601cb0ef41Sopenharmony_ci STATIC_ASSERT(JSCreateLiteralRegExpNode::FeedbackVectorIndex() == 0); 22611cb0ef41Sopenharmony_ci const Operator* op = 22621cb0ef41Sopenharmony_ci javascript()->CreateLiteralRegExp(constant_pattern, pair, literal_flags); 22631cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 22641cb0ef41Sopenharmony_ci Node* literal = NewNode(op, feedback_vector_node()); 22651cb0ef41Sopenharmony_ci environment()->BindAccumulator(literal, Environment::kAttachFrameState); 22661cb0ef41Sopenharmony_ci} 22671cb0ef41Sopenharmony_ci 22681cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateArrayLiteral() { 22691cb0ef41Sopenharmony_ci ArrayBoilerplateDescriptionRef array_boilerplate_description = 22701cb0ef41Sopenharmony_ci MakeRefForConstantForIndexOperand<ArrayBoilerplateDescription>(0); 22711cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(1); 22721cb0ef41Sopenharmony_ci FeedbackSource pair = CreateFeedbackSource(slot_id); 22731cb0ef41Sopenharmony_ci int bytecode_flags = bytecode_iterator().GetFlagOperand(2); 22741cb0ef41Sopenharmony_ci int literal_flags = 22751cb0ef41Sopenharmony_ci interpreter::CreateArrayLiteralFlags::FlagsBits::decode(bytecode_flags); 22761cb0ef41Sopenharmony_ci // Disable allocation site mementos. Only unoptimized code will collect 22771cb0ef41Sopenharmony_ci // feedback about allocation site. Once the code is optimized we expect the 22781cb0ef41Sopenharmony_ci // data to converge. So, we disable allocation site mementos in optimized 22791cb0ef41Sopenharmony_ci // code. We can revisit this when we have data to the contrary. 22801cb0ef41Sopenharmony_ci literal_flags |= ArrayLiteral::kDisableMementos; 22811cb0ef41Sopenharmony_ci int number_of_elements = 22821cb0ef41Sopenharmony_ci array_boilerplate_description.constants_elements_length(); 22831cb0ef41Sopenharmony_ci STATIC_ASSERT(JSCreateLiteralArrayNode::FeedbackVectorIndex() == 0); 22841cb0ef41Sopenharmony_ci const Operator* op = javascript()->CreateLiteralArray( 22851cb0ef41Sopenharmony_ci array_boilerplate_description, pair, literal_flags, number_of_elements); 22861cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 22871cb0ef41Sopenharmony_ci Node* literal = NewNode(op, feedback_vector_node()); 22881cb0ef41Sopenharmony_ci environment()->BindAccumulator(literal, Environment::kAttachFrameState); 22891cb0ef41Sopenharmony_ci} 22901cb0ef41Sopenharmony_ci 22911cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateEmptyArrayLiteral() { 22921cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(0); 22931cb0ef41Sopenharmony_ci FeedbackSource pair = CreateFeedbackSource(slot_id); 22941cb0ef41Sopenharmony_ci const Operator* op = javascript()->CreateEmptyLiteralArray(pair); 22951cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 22961cb0ef41Sopenharmony_ci Node* literal = NewNode(op, feedback_vector_node()); 22971cb0ef41Sopenharmony_ci environment()->BindAccumulator(literal); 22981cb0ef41Sopenharmony_ci} 22991cb0ef41Sopenharmony_ci 23001cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateArrayFromIterable() { 23011cb0ef41Sopenharmony_ci Node* iterable = NewNode(javascript()->CreateArrayFromIterable(), 23021cb0ef41Sopenharmony_ci environment()->LookupAccumulator()); 23031cb0ef41Sopenharmony_ci environment()->BindAccumulator(iterable, Environment::kAttachFrameState); 23041cb0ef41Sopenharmony_ci} 23051cb0ef41Sopenharmony_ci 23061cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateObjectLiteral() { 23071cb0ef41Sopenharmony_ci ObjectBoilerplateDescriptionRef constant_properties = 23081cb0ef41Sopenharmony_ci MakeRefForConstantForIndexOperand<ObjectBoilerplateDescription>(0); 23091cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(1); 23101cb0ef41Sopenharmony_ci FeedbackSource pair = CreateFeedbackSource(slot_id); 23111cb0ef41Sopenharmony_ci int bytecode_flags = bytecode_iterator().GetFlagOperand(2); 23121cb0ef41Sopenharmony_ci int literal_flags = 23131cb0ef41Sopenharmony_ci interpreter::CreateObjectLiteralFlags::FlagsBits::decode(bytecode_flags); 23141cb0ef41Sopenharmony_ci int number_of_properties = constant_properties.size(); 23151cb0ef41Sopenharmony_ci STATIC_ASSERT(JSCreateLiteralObjectNode::FeedbackVectorIndex() == 0); 23161cb0ef41Sopenharmony_ci const Operator* op = javascript()->CreateLiteralObject( 23171cb0ef41Sopenharmony_ci constant_properties, pair, literal_flags, number_of_properties); 23181cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 23191cb0ef41Sopenharmony_ci Node* literal = NewNode(op, feedback_vector_node()); 23201cb0ef41Sopenharmony_ci environment()->BindAccumulator(literal, Environment::kAttachFrameState); 23211cb0ef41Sopenharmony_ci} 23221cb0ef41Sopenharmony_ci 23231cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCreateEmptyObjectLiteral() { 23241cb0ef41Sopenharmony_ci Node* literal = NewNode(javascript()->CreateEmptyLiteralObject()); 23251cb0ef41Sopenharmony_ci environment()->BindAccumulator(literal); 23261cb0ef41Sopenharmony_ci} 23271cb0ef41Sopenharmony_ci 23281cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCloneObject() { 23291cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 23301cb0ef41Sopenharmony_ci Node* source = 23311cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 23321cb0ef41Sopenharmony_ci int flags = bytecode_iterator().GetFlagOperand(1); 23331cb0ef41Sopenharmony_ci int slot = bytecode_iterator().GetIndexOperand(2); 23341cb0ef41Sopenharmony_ci const Operator* op = 23351cb0ef41Sopenharmony_ci javascript()->CloneObject(CreateFeedbackSource(slot), flags); 23361cb0ef41Sopenharmony_ci STATIC_ASSERT(JSCloneObjectNode::SourceIndex() == 0); 23371cb0ef41Sopenharmony_ci STATIC_ASSERT(JSCloneObjectNode::FeedbackVectorIndex() == 1); 23381cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 23391cb0ef41Sopenharmony_ci Node* value = NewNode(op, source, feedback_vector_node()); 23401cb0ef41Sopenharmony_ci environment()->BindAccumulator(value, Environment::kAttachFrameState); 23411cb0ef41Sopenharmony_ci} 23421cb0ef41Sopenharmony_ci 23431cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitGetTemplateObject() { 23441cb0ef41Sopenharmony_ci FeedbackSource source = 23451cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1)); 23461cb0ef41Sopenharmony_ci TemplateObjectDescriptionRef description = 23471cb0ef41Sopenharmony_ci MakeRefForConstantForIndexOperand<TemplateObjectDescription>(0); 23481cb0ef41Sopenharmony_ci STATIC_ASSERT(JSGetTemplateObjectNode::FeedbackVectorIndex() == 0); 23491cb0ef41Sopenharmony_ci const Operator* op = 23501cb0ef41Sopenharmony_ci javascript()->GetTemplateObject(description, shared_info(), source); 23511cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 23521cb0ef41Sopenharmony_ci Node* template_object = NewNode(op, feedback_vector_node()); 23531cb0ef41Sopenharmony_ci environment()->BindAccumulator(template_object); 23541cb0ef41Sopenharmony_ci} 23551cb0ef41Sopenharmony_ci 23561cb0ef41Sopenharmony_ciNode* const* BytecodeGraphBuilder::GetCallArgumentsFromRegisters( 23571cb0ef41Sopenharmony_ci Node* callee, Node* receiver, interpreter::Register first_arg, 23581cb0ef41Sopenharmony_ci int arg_count) { 23591cb0ef41Sopenharmony_ci const int arity = JSCallNode::ArityForArgc(arg_count); 23601cb0ef41Sopenharmony_ci Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity)); 23611cb0ef41Sopenharmony_ci int cursor = 0; 23621cb0ef41Sopenharmony_ci 23631cb0ef41Sopenharmony_ci STATIC_ASSERT(JSCallNode::TargetIndex() == 0); 23641cb0ef41Sopenharmony_ci STATIC_ASSERT(JSCallNode::ReceiverIndex() == 1); 23651cb0ef41Sopenharmony_ci STATIC_ASSERT(JSCallNode::FirstArgumentIndex() == 2); 23661cb0ef41Sopenharmony_ci STATIC_ASSERT(JSCallNode::kFeedbackVectorIsLastInput); 23671cb0ef41Sopenharmony_ci 23681cb0ef41Sopenharmony_ci all[cursor++] = callee; 23691cb0ef41Sopenharmony_ci all[cursor++] = receiver; 23701cb0ef41Sopenharmony_ci 23711cb0ef41Sopenharmony_ci // The function arguments are in consecutive registers. 23721cb0ef41Sopenharmony_ci const int arg_base = first_arg.index(); 23731cb0ef41Sopenharmony_ci for (int i = 0; i < arg_count; ++i) { 23741cb0ef41Sopenharmony_ci all[cursor++] = 23751cb0ef41Sopenharmony_ci environment()->LookupRegister(interpreter::Register(arg_base + i)); 23761cb0ef41Sopenharmony_ci } 23771cb0ef41Sopenharmony_ci 23781cb0ef41Sopenharmony_ci all[cursor++] = feedback_vector_node(); 23791cb0ef41Sopenharmony_ci 23801cb0ef41Sopenharmony_ci DCHECK_EQ(cursor, arity); 23811cb0ef41Sopenharmony_ci return all; 23821cb0ef41Sopenharmony_ci} 23831cb0ef41Sopenharmony_ci 23841cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildCall(ConvertReceiverMode receiver_mode, 23851cb0ef41Sopenharmony_ci Node* const* args, size_t arg_count, 23861cb0ef41Sopenharmony_ci int slot_id) { 23871cb0ef41Sopenharmony_ci DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode( 23881cb0ef41Sopenharmony_ci bytecode_iterator().current_bytecode()), 23891cb0ef41Sopenharmony_ci receiver_mode); 23901cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 23911cb0ef41Sopenharmony_ci 23921cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource(slot_id); 23931cb0ef41Sopenharmony_ci CallFrequency frequency = ComputeCallFrequency(slot_id); 23941cb0ef41Sopenharmony_ci SpeculationMode speculation_mode = GetSpeculationMode(slot_id); 23951cb0ef41Sopenharmony_ci CallFeedbackRelation call_feedback_relation = 23961cb0ef41Sopenharmony_ci ComputeCallFeedbackRelation(slot_id); 23971cb0ef41Sopenharmony_ci const Operator* op = 23981cb0ef41Sopenharmony_ci javascript()->Call(arg_count, frequency, feedback, receiver_mode, 23991cb0ef41Sopenharmony_ci speculation_mode, call_feedback_relation); 24001cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 24011cb0ef41Sopenharmony_ci 24021cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall( 24031cb0ef41Sopenharmony_ci op, args, static_cast<int>(arg_count), feedback.slot); 24041cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 24051cb0ef41Sopenharmony_ci 24061cb0ef41Sopenharmony_ci Node* node = nullptr; 24071cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 24081cb0ef41Sopenharmony_ci node = lowering.value(); 24091cb0ef41Sopenharmony_ci } else { 24101cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 24111cb0ef41Sopenharmony_ci node = MakeNode(op, static_cast<int>(arg_count), args); 24121cb0ef41Sopenharmony_ci } 24131cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 24141cb0ef41Sopenharmony_ci} 24151cb0ef41Sopenharmony_ci 24161cb0ef41Sopenharmony_ciNode* const* BytecodeGraphBuilder::ProcessCallVarArgs( 24171cb0ef41Sopenharmony_ci ConvertReceiverMode receiver_mode, Node* callee, 24181cb0ef41Sopenharmony_ci interpreter::Register first_reg, int arg_count) { 24191cb0ef41Sopenharmony_ci DCHECK_GE(arg_count, 0); 24201cb0ef41Sopenharmony_ci Node* receiver_node; 24211cb0ef41Sopenharmony_ci interpreter::Register first_arg; 24221cb0ef41Sopenharmony_ci 24231cb0ef41Sopenharmony_ci if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { 24241cb0ef41Sopenharmony_ci // The receiver is implicit (and undefined), the arguments are in 24251cb0ef41Sopenharmony_ci // consecutive registers. 24261cb0ef41Sopenharmony_ci receiver_node = jsgraph()->UndefinedConstant(); 24271cb0ef41Sopenharmony_ci first_arg = first_reg; 24281cb0ef41Sopenharmony_ci } else { 24291cb0ef41Sopenharmony_ci // The receiver is the first register, followed by the arguments in the 24301cb0ef41Sopenharmony_ci // consecutive registers. 24311cb0ef41Sopenharmony_ci receiver_node = environment()->LookupRegister(first_reg); 24321cb0ef41Sopenharmony_ci first_arg = interpreter::Register(first_reg.index() + 1); 24331cb0ef41Sopenharmony_ci } 24341cb0ef41Sopenharmony_ci 24351cb0ef41Sopenharmony_ci Node* const* call_args = GetCallArgumentsFromRegisters(callee, receiver_node, 24361cb0ef41Sopenharmony_ci first_arg, arg_count); 24371cb0ef41Sopenharmony_ci return call_args; 24381cb0ef41Sopenharmony_ci} 24391cb0ef41Sopenharmony_ci 24401cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildCallVarArgs(ConvertReceiverMode receiver_mode) { 24411cb0ef41Sopenharmony_ci DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode( 24421cb0ef41Sopenharmony_ci bytecode_iterator().current_bytecode()), 24431cb0ef41Sopenharmony_ci receiver_mode); 24441cb0ef41Sopenharmony_ci Node* callee = 24451cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 24461cb0ef41Sopenharmony_ci interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 24471cb0ef41Sopenharmony_ci size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 24481cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(3); 24491cb0ef41Sopenharmony_ci 24501cb0ef41Sopenharmony_ci int arg_count = receiver_mode == ConvertReceiverMode::kNullOrUndefined 24511cb0ef41Sopenharmony_ci ? static_cast<int>(reg_count) 24521cb0ef41Sopenharmony_ci : static_cast<int>(reg_count) - 1; 24531cb0ef41Sopenharmony_ci Node* const* call_args = 24541cb0ef41Sopenharmony_ci ProcessCallVarArgs(receiver_mode, callee, first_reg, arg_count); 24551cb0ef41Sopenharmony_ci BuildCall(receiver_mode, call_args, JSCallNode::ArityForArgc(arg_count), 24561cb0ef41Sopenharmony_ci slot_id); 24571cb0ef41Sopenharmony_ci} 24581cb0ef41Sopenharmony_ci 24591cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallAnyReceiver() { 24601cb0ef41Sopenharmony_ci BuildCallVarArgs(ConvertReceiverMode::kAny); 24611cb0ef41Sopenharmony_ci} 24621cb0ef41Sopenharmony_ci 24631cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallProperty() { 24641cb0ef41Sopenharmony_ci BuildCallVarArgs(ConvertReceiverMode::kNotNullOrUndefined); 24651cb0ef41Sopenharmony_ci} 24661cb0ef41Sopenharmony_ci 24671cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallProperty0() { 24681cb0ef41Sopenharmony_ci Node* callee = 24691cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 24701cb0ef41Sopenharmony_ci Node* receiver = 24711cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 24721cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(2); 24731cb0ef41Sopenharmony_ci BuildCall(ConvertReceiverMode::kNotNullOrUndefined, 24741cb0ef41Sopenharmony_ci {callee, receiver, feedback_vector_node()}, slot_id); 24751cb0ef41Sopenharmony_ci} 24761cb0ef41Sopenharmony_ci 24771cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallProperty1() { 24781cb0ef41Sopenharmony_ci Node* callee = 24791cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 24801cb0ef41Sopenharmony_ci Node* receiver = 24811cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 24821cb0ef41Sopenharmony_ci Node* arg0 = 24831cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); 24841cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(3); 24851cb0ef41Sopenharmony_ci BuildCall(ConvertReceiverMode::kNotNullOrUndefined, 24861cb0ef41Sopenharmony_ci {callee, receiver, arg0, feedback_vector_node()}, slot_id); 24871cb0ef41Sopenharmony_ci} 24881cb0ef41Sopenharmony_ci 24891cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallProperty2() { 24901cb0ef41Sopenharmony_ci Node* callee = 24911cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 24921cb0ef41Sopenharmony_ci Node* receiver = 24931cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 24941cb0ef41Sopenharmony_ci Node* arg0 = 24951cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); 24961cb0ef41Sopenharmony_ci Node* arg1 = 24971cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(3)); 24981cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(4); 24991cb0ef41Sopenharmony_ci BuildCall(ConvertReceiverMode::kNotNullOrUndefined, 25001cb0ef41Sopenharmony_ci {callee, receiver, arg0, arg1, feedback_vector_node()}, slot_id); 25011cb0ef41Sopenharmony_ci} 25021cb0ef41Sopenharmony_ci 25031cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallUndefinedReceiver() { 25041cb0ef41Sopenharmony_ci BuildCallVarArgs(ConvertReceiverMode::kNullOrUndefined); 25051cb0ef41Sopenharmony_ci} 25061cb0ef41Sopenharmony_ci 25071cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallUndefinedReceiver0() { 25081cb0ef41Sopenharmony_ci Node* callee = 25091cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 25101cb0ef41Sopenharmony_ci Node* receiver = jsgraph()->UndefinedConstant(); 25111cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(1); 25121cb0ef41Sopenharmony_ci BuildCall(ConvertReceiverMode::kNullOrUndefined, 25131cb0ef41Sopenharmony_ci {callee, receiver, feedback_vector_node()}, slot_id); 25141cb0ef41Sopenharmony_ci} 25151cb0ef41Sopenharmony_ci 25161cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallUndefinedReceiver1() { 25171cb0ef41Sopenharmony_ci Node* callee = 25181cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 25191cb0ef41Sopenharmony_ci Node* receiver = jsgraph()->UndefinedConstant(); 25201cb0ef41Sopenharmony_ci Node* arg0 = 25211cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 25221cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(2); 25231cb0ef41Sopenharmony_ci BuildCall(ConvertReceiverMode::kNullOrUndefined, 25241cb0ef41Sopenharmony_ci {callee, receiver, arg0, feedback_vector_node()}, slot_id); 25251cb0ef41Sopenharmony_ci} 25261cb0ef41Sopenharmony_ci 25271cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallUndefinedReceiver2() { 25281cb0ef41Sopenharmony_ci Node* callee = 25291cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 25301cb0ef41Sopenharmony_ci Node* receiver = jsgraph()->UndefinedConstant(); 25311cb0ef41Sopenharmony_ci Node* arg0 = 25321cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 25331cb0ef41Sopenharmony_ci Node* arg1 = 25341cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); 25351cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(3); 25361cb0ef41Sopenharmony_ci BuildCall(ConvertReceiverMode::kNullOrUndefined, 25371cb0ef41Sopenharmony_ci {callee, receiver, arg0, arg1, feedback_vector_node()}, slot_id); 25381cb0ef41Sopenharmony_ci} 25391cb0ef41Sopenharmony_ci 25401cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallWithSpread() { 25411cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 25421cb0ef41Sopenharmony_ci Node* callee = 25431cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 25441cb0ef41Sopenharmony_ci interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 25451cb0ef41Sopenharmony_ci Node* receiver_node = environment()->LookupRegister(receiver); 25461cb0ef41Sopenharmony_ci size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 25471cb0ef41Sopenharmony_ci interpreter::Register first_arg = interpreter::Register(receiver.index() + 1); 25481cb0ef41Sopenharmony_ci int arg_count = static_cast<int>(reg_count) - 1; 25491cb0ef41Sopenharmony_ci Node* const* args = GetCallArgumentsFromRegisters(callee, receiver_node, 25501cb0ef41Sopenharmony_ci first_arg, arg_count); 25511cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(3); 25521cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource(slot_id); 25531cb0ef41Sopenharmony_ci CallFrequency frequency = ComputeCallFrequency(slot_id); 25541cb0ef41Sopenharmony_ci SpeculationMode speculation_mode = GetSpeculationMode(slot_id); 25551cb0ef41Sopenharmony_ci const Operator* op = javascript()->CallWithSpread( 25561cb0ef41Sopenharmony_ci JSCallWithSpreadNode::ArityForArgc(arg_count), frequency, feedback, 25571cb0ef41Sopenharmony_ci speculation_mode); 25581cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 25591cb0ef41Sopenharmony_ci 25601cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedCall( 25611cb0ef41Sopenharmony_ci op, args, static_cast<int>(arg_count), feedback.slot); 25621cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 25631cb0ef41Sopenharmony_ci 25641cb0ef41Sopenharmony_ci Node* node = nullptr; 25651cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 25661cb0ef41Sopenharmony_ci node = lowering.value(); 25671cb0ef41Sopenharmony_ci } else { 25681cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 25691cb0ef41Sopenharmony_ci node = MakeNode(op, JSCallWithSpreadNode::ArityForArgc(arg_count), args); 25701cb0ef41Sopenharmony_ci } 25711cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 25721cb0ef41Sopenharmony_ci} 25731cb0ef41Sopenharmony_ci 25741cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallJSRuntime() { 25751cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 25761cb0ef41Sopenharmony_ci Node* callee = BuildLoadNativeContextField( 25771cb0ef41Sopenharmony_ci bytecode_iterator().GetNativeContextIndexOperand(0)); 25781cb0ef41Sopenharmony_ci interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 25791cb0ef41Sopenharmony_ci size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 25801cb0ef41Sopenharmony_ci int arg_count = static_cast<int>(reg_count); 25811cb0ef41Sopenharmony_ci int arity = JSCallNode::ArityForArgc(arg_count); 25821cb0ef41Sopenharmony_ci 25831cb0ef41Sopenharmony_ci const Operator* call = javascript()->Call(arity); 25841cb0ef41Sopenharmony_ci Node* const* call_args = ProcessCallVarArgs( 25851cb0ef41Sopenharmony_ci ConvertReceiverMode::kNullOrUndefined, callee, first_reg, arg_count); 25861cb0ef41Sopenharmony_ci Node* value = MakeNode(call, arity, call_args); 25871cb0ef41Sopenharmony_ci environment()->BindAccumulator(value, Environment::kAttachFrameState); 25881cb0ef41Sopenharmony_ci} 25891cb0ef41Sopenharmony_ci 25901cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::ProcessCallRuntimeArguments( 25911cb0ef41Sopenharmony_ci const Operator* call_runtime_op, interpreter::Register receiver, 25921cb0ef41Sopenharmony_ci size_t reg_count) { 25931cb0ef41Sopenharmony_ci int arg_count = static_cast<int>(reg_count); 25941cb0ef41Sopenharmony_ci // arity is args. 25951cb0ef41Sopenharmony_ci int arity = arg_count; 25961cb0ef41Sopenharmony_ci Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity)); 25971cb0ef41Sopenharmony_ci int first_arg_index = receiver.index(); 25981cb0ef41Sopenharmony_ci for (int i = 0; i < static_cast<int>(reg_count); ++i) { 25991cb0ef41Sopenharmony_ci all[i] = environment()->LookupRegister( 26001cb0ef41Sopenharmony_ci interpreter::Register(first_arg_index + i)); 26011cb0ef41Sopenharmony_ci } 26021cb0ef41Sopenharmony_ci Node* value = MakeNode(call_runtime_op, arity, all); 26031cb0ef41Sopenharmony_ci return value; 26041cb0ef41Sopenharmony_ci} 26051cb0ef41Sopenharmony_ci 26061cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallRuntime() { 26071cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 26081cb0ef41Sopenharmony_ci Runtime::FunctionId function_id = bytecode_iterator().GetRuntimeIdOperand(0); 26091cb0ef41Sopenharmony_ci interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 26101cb0ef41Sopenharmony_ci size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 26111cb0ef41Sopenharmony_ci 26121cb0ef41Sopenharmony_ci // Handle %ObserveNode here (rather than in JSIntrinsicLowering) to observe 26131cb0ef41Sopenharmony_ci // the node as early as possible. 26141cb0ef41Sopenharmony_ci if (function_id == Runtime::FunctionId::kObserveNode) { 26151cb0ef41Sopenharmony_ci DCHECK_EQ(1, reg_count); 26161cb0ef41Sopenharmony_ci Node* value = environment()->LookupRegister(receiver); 26171cb0ef41Sopenharmony_ci observe_node_info_.StartObserving(value); 26181cb0ef41Sopenharmony_ci environment()->BindAccumulator(value); 26191cb0ef41Sopenharmony_ci } else { 26201cb0ef41Sopenharmony_ci // Create node to perform the runtime call. 26211cb0ef41Sopenharmony_ci const Operator* call = javascript()->CallRuntime(function_id, reg_count); 26221cb0ef41Sopenharmony_ci Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); 26231cb0ef41Sopenharmony_ci environment()->BindAccumulator(value, Environment::kAttachFrameState); 26241cb0ef41Sopenharmony_ci 26251cb0ef41Sopenharmony_ci // Connect to the end if {function_id} is non-returning. 26261cb0ef41Sopenharmony_ci if (Runtime::IsNonReturning(function_id)) { 26271cb0ef41Sopenharmony_ci // TODO(7099): Investigate if we need LoopExit node here. 26281cb0ef41Sopenharmony_ci Node* control = NewNode(common()->Throw()); 26291cb0ef41Sopenharmony_ci MergeControlToLeaveFunction(control); 26301cb0ef41Sopenharmony_ci } 26311cb0ef41Sopenharmony_ci } 26321cb0ef41Sopenharmony_ci} 26331cb0ef41Sopenharmony_ci 26341cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitCallRuntimeForPair() { 26351cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 26361cb0ef41Sopenharmony_ci Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); 26371cb0ef41Sopenharmony_ci interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 26381cb0ef41Sopenharmony_ci size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 26391cb0ef41Sopenharmony_ci interpreter::Register first_return = 26401cb0ef41Sopenharmony_ci bytecode_iterator().GetRegisterOperand(3); 26411cb0ef41Sopenharmony_ci 26421cb0ef41Sopenharmony_ci // Create node to perform the runtime call. 26431cb0ef41Sopenharmony_ci const Operator* call = javascript()->CallRuntime(functionId, reg_count); 26441cb0ef41Sopenharmony_ci Node* return_pair = ProcessCallRuntimeArguments(call, receiver, reg_count); 26451cb0ef41Sopenharmony_ci environment()->BindRegistersToProjections(first_return, return_pair, 26461cb0ef41Sopenharmony_ci Environment::kAttachFrameState); 26471cb0ef41Sopenharmony_ci} 26481cb0ef41Sopenharmony_ci 26491cb0ef41Sopenharmony_ciNode* const* BytecodeGraphBuilder::GetConstructArgumentsFromRegister( 26501cb0ef41Sopenharmony_ci Node* target, Node* new_target, interpreter::Register first_arg, 26511cb0ef41Sopenharmony_ci int arg_count) { 26521cb0ef41Sopenharmony_ci const int arity = JSConstructNode::ArityForArgc(arg_count); 26531cb0ef41Sopenharmony_ci Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity)); 26541cb0ef41Sopenharmony_ci int cursor = 0; 26551cb0ef41Sopenharmony_ci 26561cb0ef41Sopenharmony_ci STATIC_ASSERT(JSConstructNode::TargetIndex() == 0); 26571cb0ef41Sopenharmony_ci STATIC_ASSERT(JSConstructNode::NewTargetIndex() == 1); 26581cb0ef41Sopenharmony_ci STATIC_ASSERT(JSConstructNode::FirstArgumentIndex() == 2); 26591cb0ef41Sopenharmony_ci STATIC_ASSERT(JSConstructNode::kFeedbackVectorIsLastInput); 26601cb0ef41Sopenharmony_ci 26611cb0ef41Sopenharmony_ci all[cursor++] = target; 26621cb0ef41Sopenharmony_ci all[cursor++] = new_target; 26631cb0ef41Sopenharmony_ci 26641cb0ef41Sopenharmony_ci // The function arguments are in consecutive registers. 26651cb0ef41Sopenharmony_ci int arg_base = first_arg.index(); 26661cb0ef41Sopenharmony_ci for (int i = 0; i < arg_count; ++i) { 26671cb0ef41Sopenharmony_ci all[cursor++] = 26681cb0ef41Sopenharmony_ci environment()->LookupRegister(interpreter::Register(arg_base + i)); 26691cb0ef41Sopenharmony_ci } 26701cb0ef41Sopenharmony_ci 26711cb0ef41Sopenharmony_ci all[cursor++] = feedback_vector_node(); 26721cb0ef41Sopenharmony_ci 26731cb0ef41Sopenharmony_ci DCHECK_EQ(cursor, arity); 26741cb0ef41Sopenharmony_ci return all; 26751cb0ef41Sopenharmony_ci} 26761cb0ef41Sopenharmony_ci 26771cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitConstruct() { 26781cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 26791cb0ef41Sopenharmony_ci interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); 26801cb0ef41Sopenharmony_ci interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 26811cb0ef41Sopenharmony_ci size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 26821cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(3); 26831cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource(slot_id); 26841cb0ef41Sopenharmony_ci 26851cb0ef41Sopenharmony_ci Node* new_target = environment()->LookupAccumulator(); 26861cb0ef41Sopenharmony_ci Node* callee = environment()->LookupRegister(callee_reg); 26871cb0ef41Sopenharmony_ci 26881cb0ef41Sopenharmony_ci CallFrequency frequency = ComputeCallFrequency(slot_id); 26891cb0ef41Sopenharmony_ci const uint32_t arg_count = static_cast<uint32_t>(reg_count); 26901cb0ef41Sopenharmony_ci const uint32_t arity = JSConstructNode::ArityForArgc(arg_count); 26911cb0ef41Sopenharmony_ci const Operator* op = javascript()->Construct(arity, frequency, feedback); 26921cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 26931cb0ef41Sopenharmony_ci Node* const* args = GetConstructArgumentsFromRegister(callee, new_target, 26941cb0ef41Sopenharmony_ci first_reg, arg_count); 26951cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedConstruct( 26961cb0ef41Sopenharmony_ci op, args, static_cast<int>(arg_count), feedback.slot); 26971cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 26981cb0ef41Sopenharmony_ci 26991cb0ef41Sopenharmony_ci Node* node = nullptr; 27001cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 27011cb0ef41Sopenharmony_ci node = lowering.value(); 27021cb0ef41Sopenharmony_ci } else { 27031cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 27041cb0ef41Sopenharmony_ci node = MakeNode(op, arity, args); 27051cb0ef41Sopenharmony_ci } 27061cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 27071cb0ef41Sopenharmony_ci} 27081cb0ef41Sopenharmony_ci 27091cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitConstructWithSpread() { 27101cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 27111cb0ef41Sopenharmony_ci interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); 27121cb0ef41Sopenharmony_ci interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 27131cb0ef41Sopenharmony_ci size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 27141cb0ef41Sopenharmony_ci int const slot_id = bytecode_iterator().GetIndexOperand(3); 27151cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource(slot_id); 27161cb0ef41Sopenharmony_ci 27171cb0ef41Sopenharmony_ci Node* new_target = environment()->LookupAccumulator(); 27181cb0ef41Sopenharmony_ci Node* callee = environment()->LookupRegister(callee_reg); 27191cb0ef41Sopenharmony_ci 27201cb0ef41Sopenharmony_ci CallFrequency frequency = ComputeCallFrequency(slot_id); 27211cb0ef41Sopenharmony_ci const uint32_t arg_count = static_cast<uint32_t>(reg_count); 27221cb0ef41Sopenharmony_ci const uint32_t arity = JSConstructNode::ArityForArgc(arg_count); 27231cb0ef41Sopenharmony_ci const Operator* op = 27241cb0ef41Sopenharmony_ci javascript()->ConstructWithSpread(arity, frequency, feedback); 27251cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 27261cb0ef41Sopenharmony_ci Node* const* args = GetConstructArgumentsFromRegister(callee, new_target, 27271cb0ef41Sopenharmony_ci first_reg, arg_count); 27281cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedConstruct( 27291cb0ef41Sopenharmony_ci op, args, static_cast<int>(arg_count), feedback.slot); 27301cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 27311cb0ef41Sopenharmony_ci 27321cb0ef41Sopenharmony_ci Node* node = nullptr; 27331cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 27341cb0ef41Sopenharmony_ci node = lowering.value(); 27351cb0ef41Sopenharmony_ci } else { 27361cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 27371cb0ef41Sopenharmony_ci node = MakeNode(op, arity, args); 27381cb0ef41Sopenharmony_ci } 27391cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 27401cb0ef41Sopenharmony_ci} 27411cb0ef41Sopenharmony_ci 27421cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitInvokeIntrinsic() { 27431cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 27441cb0ef41Sopenharmony_ci Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0); 27451cb0ef41Sopenharmony_ci interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); 27461cb0ef41Sopenharmony_ci size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); 27471cb0ef41Sopenharmony_ci 27481cb0ef41Sopenharmony_ci // Create node to perform the runtime call. Turbofan will take care of the 27491cb0ef41Sopenharmony_ci // lowering. 27501cb0ef41Sopenharmony_ci const Operator* call = javascript()->CallRuntime(functionId, reg_count); 27511cb0ef41Sopenharmony_ci Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); 27521cb0ef41Sopenharmony_ci environment()->BindAccumulator(value, Environment::kAttachFrameState); 27531cb0ef41Sopenharmony_ci} 27541cb0ef41Sopenharmony_ci 27551cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitThrow() { 27561cb0ef41Sopenharmony_ci BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor( 27571cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 27581cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 27591cb0ef41Sopenharmony_ci Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); 27601cb0ef41Sopenharmony_ci environment()->BindAccumulator(call, Environment::kAttachFrameState); 27611cb0ef41Sopenharmony_ci Node* control = NewNode(common()->Throw()); 27621cb0ef41Sopenharmony_ci MergeControlToLeaveFunction(control); 27631cb0ef41Sopenharmony_ci} 27641cb0ef41Sopenharmony_ci 27651cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitAbort() { 27661cb0ef41Sopenharmony_ci BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor( 27671cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 27681cb0ef41Sopenharmony_ci AbortReason reason = 27691cb0ef41Sopenharmony_ci static_cast<AbortReason>(bytecode_iterator().GetIndexOperand(0)); 27701cb0ef41Sopenharmony_ci NewNode(simplified()->RuntimeAbort(reason)); 27711cb0ef41Sopenharmony_ci Node* control = NewNode(common()->Throw()); 27721cb0ef41Sopenharmony_ci MergeControlToLeaveFunction(control); 27731cb0ef41Sopenharmony_ci} 27741cb0ef41Sopenharmony_ci 27751cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitReThrow() { 27761cb0ef41Sopenharmony_ci BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor( 27771cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 27781cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 27791cb0ef41Sopenharmony_ci NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); 27801cb0ef41Sopenharmony_ci Node* control = NewNode(common()->Throw()); 27811cb0ef41Sopenharmony_ci MergeControlToLeaveFunction(control); 27821cb0ef41Sopenharmony_ci} 27831cb0ef41Sopenharmony_ci 27841cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildHoleCheckAndThrow( 27851cb0ef41Sopenharmony_ci Node* condition, Runtime::FunctionId runtime_id, Node* name) { 27861cb0ef41Sopenharmony_ci Node* accumulator = environment()->LookupAccumulator(); 27871cb0ef41Sopenharmony_ci NewBranch(condition, BranchHint::kFalse); 27881cb0ef41Sopenharmony_ci { 27891cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 27901cb0ef41Sopenharmony_ci 27911cb0ef41Sopenharmony_ci NewIfTrue(); 27921cb0ef41Sopenharmony_ci BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor( 27931cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 27941cb0ef41Sopenharmony_ci Node* node; 27951cb0ef41Sopenharmony_ci const Operator* op = javascript()->CallRuntime(runtime_id); 27961cb0ef41Sopenharmony_ci if (runtime_id == Runtime::kThrowAccessedUninitializedVariable) { 27971cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(name); 27981cb0ef41Sopenharmony_ci node = NewNode(op, name); 27991cb0ef41Sopenharmony_ci } else { 28001cb0ef41Sopenharmony_ci DCHECK(runtime_id == Runtime::kThrowSuperAlreadyCalledError || 28011cb0ef41Sopenharmony_ci runtime_id == Runtime::kThrowSuperNotCalled); 28021cb0ef41Sopenharmony_ci node = NewNode(op); 28031cb0ef41Sopenharmony_ci } 28041cb0ef41Sopenharmony_ci environment()->RecordAfterState(node, Environment::kAttachFrameState); 28051cb0ef41Sopenharmony_ci Node* control = NewNode(common()->Throw()); 28061cb0ef41Sopenharmony_ci MergeControlToLeaveFunction(control); 28071cb0ef41Sopenharmony_ci } 28081cb0ef41Sopenharmony_ci NewIfFalse(); 28091cb0ef41Sopenharmony_ci environment()->BindAccumulator(accumulator); 28101cb0ef41Sopenharmony_ci} 28111cb0ef41Sopenharmony_ci 28121cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitThrowReferenceErrorIfHole() { 28131cb0ef41Sopenharmony_ci Node* accumulator = environment()->LookupAccumulator(); 28141cb0ef41Sopenharmony_ci Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator, 28151cb0ef41Sopenharmony_ci jsgraph()->TheHoleConstant()); 28161cb0ef41Sopenharmony_ci Node* name = jsgraph()->Constant(MakeRefForConstantForIndexOperand(0)); 28171cb0ef41Sopenharmony_ci BuildHoleCheckAndThrow(check_for_hole, 28181cb0ef41Sopenharmony_ci Runtime::kThrowAccessedUninitializedVariable, name); 28191cb0ef41Sopenharmony_ci} 28201cb0ef41Sopenharmony_ci 28211cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitThrowSuperNotCalledIfHole() { 28221cb0ef41Sopenharmony_ci Node* accumulator = environment()->LookupAccumulator(); 28231cb0ef41Sopenharmony_ci Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator, 28241cb0ef41Sopenharmony_ci jsgraph()->TheHoleConstant()); 28251cb0ef41Sopenharmony_ci BuildHoleCheckAndThrow(check_for_hole, Runtime::kThrowSuperNotCalled); 28261cb0ef41Sopenharmony_ci} 28271cb0ef41Sopenharmony_ci 28281cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitThrowSuperAlreadyCalledIfNotHole() { 28291cb0ef41Sopenharmony_ci Node* accumulator = environment()->LookupAccumulator(); 28301cb0ef41Sopenharmony_ci Node* check_for_hole = NewNode(simplified()->ReferenceEqual(), accumulator, 28311cb0ef41Sopenharmony_ci jsgraph()->TheHoleConstant()); 28321cb0ef41Sopenharmony_ci Node* check_for_not_hole = 28331cb0ef41Sopenharmony_ci NewNode(simplified()->BooleanNot(), check_for_hole); 28341cb0ef41Sopenharmony_ci BuildHoleCheckAndThrow(check_for_not_hole, 28351cb0ef41Sopenharmony_ci Runtime::kThrowSuperAlreadyCalledError); 28361cb0ef41Sopenharmony_ci} 28371cb0ef41Sopenharmony_ci 28381cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitThrowIfNotSuperConstructor() { 28391cb0ef41Sopenharmony_ci Node* constructor = 28401cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 28411cb0ef41Sopenharmony_ci Node* check_is_constructor = 28421cb0ef41Sopenharmony_ci NewNode(simplified()->ObjectIsConstructor(), constructor); 28431cb0ef41Sopenharmony_ci NewBranch(check_is_constructor, BranchHint::kTrue); 28441cb0ef41Sopenharmony_ci { 28451cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 28461cb0ef41Sopenharmony_ci NewIfFalse(); 28471cb0ef41Sopenharmony_ci BuildLoopExitsForFunctionExit(bytecode_analysis().GetInLivenessFor( 28481cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 28491cb0ef41Sopenharmony_ci Node* node = 28501cb0ef41Sopenharmony_ci NewNode(javascript()->CallRuntime(Runtime::kThrowNotSuperConstructor), 28511cb0ef41Sopenharmony_ci constructor, GetFunctionClosure()); 28521cb0ef41Sopenharmony_ci environment()->RecordAfterState(node, Environment::kAttachFrameState); 28531cb0ef41Sopenharmony_ci Node* control = NewNode(common()->Throw()); 28541cb0ef41Sopenharmony_ci MergeControlToLeaveFunction(control); 28551cb0ef41Sopenharmony_ci } 28561cb0ef41Sopenharmony_ci NewIfTrue(); 28571cb0ef41Sopenharmony_ci 28581cb0ef41Sopenharmony_ci constructor = NewNode(common()->TypeGuard(Type::Callable()), constructor); 28591cb0ef41Sopenharmony_ci environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), 28601cb0ef41Sopenharmony_ci constructor); 28611cb0ef41Sopenharmony_ci} 28621cb0ef41Sopenharmony_ci 28631cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildUnaryOp(const Operator* op) { 28641cb0ef41Sopenharmony_ci DCHECK(JSOperator::IsUnaryWithFeedback(op->opcode())); 28651cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 28661cb0ef41Sopenharmony_ci Node* operand = environment()->LookupAccumulator(); 28671cb0ef41Sopenharmony_ci 28681cb0ef41Sopenharmony_ci FeedbackSlot slot = 28691cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex); 28701cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 28711cb0ef41Sopenharmony_ci TryBuildSimplifiedUnaryOp(op, operand, slot); 28721cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 28731cb0ef41Sopenharmony_ci 28741cb0ef41Sopenharmony_ci Node* node = nullptr; 28751cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 28761cb0ef41Sopenharmony_ci node = lowering.value(); 28771cb0ef41Sopenharmony_ci } else { 28781cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 28791cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 28801cb0ef41Sopenharmony_ci node = NewNode(op, operand, feedback_vector_node()); 28811cb0ef41Sopenharmony_ci } 28821cb0ef41Sopenharmony_ci 28831cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 28841cb0ef41Sopenharmony_ci} 28851cb0ef41Sopenharmony_ci 28861cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildBinaryOp(const Operator* op) { 28871cb0ef41Sopenharmony_ci DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode())); 28881cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 28891cb0ef41Sopenharmony_ci Node* left = 28901cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 28911cb0ef41Sopenharmony_ci Node* right = environment()->LookupAccumulator(); 28921cb0ef41Sopenharmony_ci 28931cb0ef41Sopenharmony_ci FeedbackSlot slot = 28941cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex); 28951cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 28961cb0ef41Sopenharmony_ci TryBuildSimplifiedBinaryOp(op, left, right, slot); 28971cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 28981cb0ef41Sopenharmony_ci 28991cb0ef41Sopenharmony_ci Node* node = nullptr; 29001cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 29011cb0ef41Sopenharmony_ci node = lowering.value(); 29021cb0ef41Sopenharmony_ci } else { 29031cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 29041cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 29051cb0ef41Sopenharmony_ci node = NewNode(op, left, right, feedback_vector_node()); 29061cb0ef41Sopenharmony_ci } 29071cb0ef41Sopenharmony_ci 29081cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 29091cb0ef41Sopenharmony_ci} 29101cb0ef41Sopenharmony_ci 29111cb0ef41Sopenharmony_ci// Helper function to create for-in mode from the recorded type feedback. 29121cb0ef41Sopenharmony_ciForInMode BytecodeGraphBuilder::GetForInMode(FeedbackSlot slot) { 29131cb0ef41Sopenharmony_ci FeedbackSource source(feedback_vector(), slot); 29141cb0ef41Sopenharmony_ci switch (broker()->GetFeedbackForForIn(source)) { 29151cb0ef41Sopenharmony_ci case ForInHint::kNone: 29161cb0ef41Sopenharmony_ci case ForInHint::kEnumCacheKeysAndIndices: 29171cb0ef41Sopenharmony_ci return ForInMode::kUseEnumCacheKeysAndIndices; 29181cb0ef41Sopenharmony_ci case ForInHint::kEnumCacheKeys: 29191cb0ef41Sopenharmony_ci return ForInMode::kUseEnumCacheKeys; 29201cb0ef41Sopenharmony_ci case ForInHint::kAny: 29211cb0ef41Sopenharmony_ci return ForInMode::kGeneric; 29221cb0ef41Sopenharmony_ci } 29231cb0ef41Sopenharmony_ci UNREACHABLE(); 29241cb0ef41Sopenharmony_ci} 29251cb0ef41Sopenharmony_ci 29261cb0ef41Sopenharmony_ciCallFrequency BytecodeGraphBuilder::ComputeCallFrequency(int slot_id) const { 29271cb0ef41Sopenharmony_ci if (invocation_frequency_.IsUnknown()) return CallFrequency(); 29281cb0ef41Sopenharmony_ci FeedbackSlot slot = FeedbackVector::ToSlot(slot_id); 29291cb0ef41Sopenharmony_ci FeedbackSource source(feedback_vector(), slot); 29301cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = broker()->GetFeedbackForCall(source); 29311cb0ef41Sopenharmony_ci float feedback_frequency = 29321cb0ef41Sopenharmony_ci feedback.IsInsufficient() ? 0.0f : feedback.AsCall().frequency(); 29331cb0ef41Sopenharmony_ci if (feedback_frequency == 0.0f) { // Prevent multiplying zero and infinity. 29341cb0ef41Sopenharmony_ci return CallFrequency(0.0f); 29351cb0ef41Sopenharmony_ci } else { 29361cb0ef41Sopenharmony_ci return CallFrequency(feedback_frequency * invocation_frequency_.value()); 29371cb0ef41Sopenharmony_ci } 29381cb0ef41Sopenharmony_ci} 29391cb0ef41Sopenharmony_ci 29401cb0ef41Sopenharmony_ciSpeculationMode BytecodeGraphBuilder::GetSpeculationMode(int slot_id) const { 29411cb0ef41Sopenharmony_ci FeedbackSlot slot = FeedbackVector::ToSlot(slot_id); 29421cb0ef41Sopenharmony_ci FeedbackSource source(feedback_vector(), slot); 29431cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = broker()->GetFeedbackForCall(source); 29441cb0ef41Sopenharmony_ci return feedback.IsInsufficient() ? SpeculationMode::kDisallowSpeculation 29451cb0ef41Sopenharmony_ci : feedback.AsCall().speculation_mode(); 29461cb0ef41Sopenharmony_ci} 29471cb0ef41Sopenharmony_ci 29481cb0ef41Sopenharmony_ciCallFeedbackRelation BytecodeGraphBuilder::ComputeCallFeedbackRelation( 29491cb0ef41Sopenharmony_ci int slot_id) const { 29501cb0ef41Sopenharmony_ci FeedbackSlot slot = FeedbackVector::ToSlot(slot_id); 29511cb0ef41Sopenharmony_ci FeedbackSource source(feedback_vector(), slot); 29521cb0ef41Sopenharmony_ci ProcessedFeedback const& feedback = broker()->GetFeedbackForCall(source); 29531cb0ef41Sopenharmony_ci if (feedback.IsInsufficient()) return CallFeedbackRelation::kUnrelated; 29541cb0ef41Sopenharmony_ci CallFeedbackContent call_feedback_content = 29551cb0ef41Sopenharmony_ci feedback.AsCall().call_feedback_content(); 29561cb0ef41Sopenharmony_ci return call_feedback_content == CallFeedbackContent::kTarget 29571cb0ef41Sopenharmony_ci ? CallFeedbackRelation::kTarget 29581cb0ef41Sopenharmony_ci : CallFeedbackRelation::kReceiver; 29591cb0ef41Sopenharmony_ci} 29601cb0ef41Sopenharmony_ci 29611cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitBitwiseNot() { 29621cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 29631cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex)); 29641cb0ef41Sopenharmony_ci BuildUnaryOp(javascript()->BitwiseNot(feedback)); 29651cb0ef41Sopenharmony_ci} 29661cb0ef41Sopenharmony_ci 29671cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitDec() { 29681cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 29691cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex)); 29701cb0ef41Sopenharmony_ci BuildUnaryOp(javascript()->Decrement(feedback)); 29711cb0ef41Sopenharmony_ci} 29721cb0ef41Sopenharmony_ci 29731cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitInc() { 29741cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 29751cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex)); 29761cb0ef41Sopenharmony_ci BuildUnaryOp(javascript()->Increment(feedback)); 29771cb0ef41Sopenharmony_ci} 29781cb0ef41Sopenharmony_ci 29791cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitNegate() { 29801cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 29811cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kUnaryOperationHintIndex)); 29821cb0ef41Sopenharmony_ci BuildUnaryOp(javascript()->Negate(feedback)); 29831cb0ef41Sopenharmony_ci} 29841cb0ef41Sopenharmony_ci 29851cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitAdd() { 29861cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 29871cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 29881cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->Add(feedback)); 29891cb0ef41Sopenharmony_ci} 29901cb0ef41Sopenharmony_ci 29911cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitSub() { 29921cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 29931cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 29941cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->Subtract(feedback)); 29951cb0ef41Sopenharmony_ci} 29961cb0ef41Sopenharmony_ci 29971cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitMul() { 29981cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 29991cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 30001cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->Multiply(feedback)); 30011cb0ef41Sopenharmony_ci} 30021cb0ef41Sopenharmony_ci 30031cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitDiv() { 30041cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30051cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 30061cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->Divide(feedback)); 30071cb0ef41Sopenharmony_ci} 30081cb0ef41Sopenharmony_ci 30091cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitMod() { 30101cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30111cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 30121cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->Modulus(feedback)); 30131cb0ef41Sopenharmony_ci} 30141cb0ef41Sopenharmony_ci 30151cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitExp() { 30161cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30171cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 30181cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->Exponentiate(feedback)); 30191cb0ef41Sopenharmony_ci} 30201cb0ef41Sopenharmony_ci 30211cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitBitwiseOr() { 30221cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30231cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 30241cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->BitwiseOr(feedback)); 30251cb0ef41Sopenharmony_ci} 30261cb0ef41Sopenharmony_ci 30271cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitBitwiseXor() { 30281cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30291cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 30301cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->BitwiseXor(feedback)); 30311cb0ef41Sopenharmony_ci} 30321cb0ef41Sopenharmony_ci 30331cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitBitwiseAnd() { 30341cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30351cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 30361cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->BitwiseAnd(feedback)); 30371cb0ef41Sopenharmony_ci} 30381cb0ef41Sopenharmony_ci 30391cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitShiftLeft() { 30401cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30411cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 30421cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->ShiftLeft(feedback)); 30431cb0ef41Sopenharmony_ci} 30441cb0ef41Sopenharmony_ci 30451cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitShiftRight() { 30461cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30471cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 30481cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->ShiftRight(feedback)); 30491cb0ef41Sopenharmony_ci} 30501cb0ef41Sopenharmony_ci 30511cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitShiftRightLogical() { 30521cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30531cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationHintIndex)); 30541cb0ef41Sopenharmony_ci BuildBinaryOp(javascript()->ShiftRightLogical(feedback)); 30551cb0ef41Sopenharmony_ci} 30561cb0ef41Sopenharmony_ci 30571cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildBinaryOpWithImmediate(const Operator* op) { 30581cb0ef41Sopenharmony_ci DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode())); 30591cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 30601cb0ef41Sopenharmony_ci Node* left = environment()->LookupAccumulator(); 30611cb0ef41Sopenharmony_ci Node* right = jsgraph()->Constant(bytecode_iterator().GetImmediateOperand(0)); 30621cb0ef41Sopenharmony_ci 30631cb0ef41Sopenharmony_ci FeedbackSlot slot = 30641cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex); 30651cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 30661cb0ef41Sopenharmony_ci TryBuildSimplifiedBinaryOp(op, left, right, slot); 30671cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 30681cb0ef41Sopenharmony_ci 30691cb0ef41Sopenharmony_ci Node* node = nullptr; 30701cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 30711cb0ef41Sopenharmony_ci node = lowering.value(); 30721cb0ef41Sopenharmony_ci } else { 30731cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 30741cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 30751cb0ef41Sopenharmony_ci node = NewNode(op, left, right, feedback_vector_node()); 30761cb0ef41Sopenharmony_ci } 30771cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 30781cb0ef41Sopenharmony_ci} 30791cb0ef41Sopenharmony_ci 30801cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitAddSmi() { 30811cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30821cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 30831cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->Add(feedback)); 30841cb0ef41Sopenharmony_ci} 30851cb0ef41Sopenharmony_ci 30861cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitSubSmi() { 30871cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30881cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 30891cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->Subtract(feedback)); 30901cb0ef41Sopenharmony_ci} 30911cb0ef41Sopenharmony_ci 30921cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitMulSmi() { 30931cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 30941cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 30951cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->Multiply(feedback)); 30961cb0ef41Sopenharmony_ci} 30971cb0ef41Sopenharmony_ci 30981cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitDivSmi() { 30991cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 31001cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 31011cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->Divide(feedback)); 31021cb0ef41Sopenharmony_ci} 31031cb0ef41Sopenharmony_ci 31041cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitModSmi() { 31051cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 31061cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 31071cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->Modulus(feedback)); 31081cb0ef41Sopenharmony_ci} 31091cb0ef41Sopenharmony_ci 31101cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitExpSmi() { 31111cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 31121cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 31131cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->Exponentiate(feedback)); 31141cb0ef41Sopenharmony_ci} 31151cb0ef41Sopenharmony_ci 31161cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitBitwiseOrSmi() { 31171cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 31181cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 31191cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->BitwiseOr(feedback)); 31201cb0ef41Sopenharmony_ci} 31211cb0ef41Sopenharmony_ci 31221cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitBitwiseXorSmi() { 31231cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 31241cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 31251cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->BitwiseXor(feedback)); 31261cb0ef41Sopenharmony_ci} 31271cb0ef41Sopenharmony_ci 31281cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitBitwiseAndSmi() { 31291cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 31301cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 31311cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->BitwiseAnd(feedback)); 31321cb0ef41Sopenharmony_ci} 31331cb0ef41Sopenharmony_ci 31341cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitShiftLeftSmi() { 31351cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 31361cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 31371cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->ShiftLeft(feedback)); 31381cb0ef41Sopenharmony_ci} 31391cb0ef41Sopenharmony_ci 31401cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitShiftRightSmi() { 31411cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 31421cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 31431cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->ShiftRight(feedback)); 31441cb0ef41Sopenharmony_ci} 31451cb0ef41Sopenharmony_ci 31461cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitShiftRightLogicalSmi() { 31471cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 31481cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kBinaryOperationSmiHintIndex)); 31491cb0ef41Sopenharmony_ci BuildBinaryOpWithImmediate(javascript()->ShiftRightLogical(feedback)); 31501cb0ef41Sopenharmony_ci} 31511cb0ef41Sopenharmony_ci 31521cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitLogicalNot() { 31531cb0ef41Sopenharmony_ci Node* value = environment()->LookupAccumulator(); 31541cb0ef41Sopenharmony_ci Node* node = NewNode(simplified()->BooleanNot(), value); 31551cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 31561cb0ef41Sopenharmony_ci} 31571cb0ef41Sopenharmony_ci 31581cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitToBooleanLogicalNot() { 31591cb0ef41Sopenharmony_ci Node* value = 31601cb0ef41Sopenharmony_ci NewNode(simplified()->ToBoolean(), environment()->LookupAccumulator()); 31611cb0ef41Sopenharmony_ci Node* node = NewNode(simplified()->BooleanNot(), value); 31621cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 31631cb0ef41Sopenharmony_ci} 31641cb0ef41Sopenharmony_ci 31651cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTypeOf() { 31661cb0ef41Sopenharmony_ci Node* node = 31671cb0ef41Sopenharmony_ci NewNode(simplified()->TypeOf(), environment()->LookupAccumulator()); 31681cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 31691cb0ef41Sopenharmony_ci} 31701cb0ef41Sopenharmony_ci 31711cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildDelete(LanguageMode language_mode) { 31721cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 31731cb0ef41Sopenharmony_ci Node* key = environment()->LookupAccumulator(); 31741cb0ef41Sopenharmony_ci Node* object = 31751cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 31761cb0ef41Sopenharmony_ci Node* mode = jsgraph()->Constant(static_cast<int32_t>(language_mode)); 31771cb0ef41Sopenharmony_ci Node* node = NewNode(javascript()->DeleteProperty(), object, key, mode); 31781cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 31791cb0ef41Sopenharmony_ci} 31801cb0ef41Sopenharmony_ci 31811cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitDeletePropertyStrict() { 31821cb0ef41Sopenharmony_ci BuildDelete(LanguageMode::kStrict); 31831cb0ef41Sopenharmony_ci} 31841cb0ef41Sopenharmony_ci 31851cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitDeletePropertySloppy() { 31861cb0ef41Sopenharmony_ci BuildDelete(LanguageMode::kSloppy); 31871cb0ef41Sopenharmony_ci} 31881cb0ef41Sopenharmony_ci 31891cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitGetSuperConstructor() { 31901cb0ef41Sopenharmony_ci Node* node = NewNode(javascript()->GetSuperConstructor(), 31911cb0ef41Sopenharmony_ci environment()->LookupAccumulator()); 31921cb0ef41Sopenharmony_ci environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), node, 31931cb0ef41Sopenharmony_ci Environment::kAttachFrameState); 31941cb0ef41Sopenharmony_ci} 31951cb0ef41Sopenharmony_ci 31961cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildCompareOp(const Operator* op) { 31971cb0ef41Sopenharmony_ci DCHECK(JSOperator::IsBinaryWithFeedback(op->opcode())); 31981cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 31991cb0ef41Sopenharmony_ci Node* left = 32001cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 32011cb0ef41Sopenharmony_ci Node* right = environment()->LookupAccumulator(); 32021cb0ef41Sopenharmony_ci 32031cb0ef41Sopenharmony_ci FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1); 32041cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 32051cb0ef41Sopenharmony_ci TryBuildSimplifiedBinaryOp(op, left, right, slot); 32061cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 32071cb0ef41Sopenharmony_ci 32081cb0ef41Sopenharmony_ci Node* node = nullptr; 32091cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 32101cb0ef41Sopenharmony_ci node = lowering.value(); 32111cb0ef41Sopenharmony_ci } else { 32121cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 32131cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 32141cb0ef41Sopenharmony_ci node = NewNode(op, left, right, feedback_vector_node()); 32151cb0ef41Sopenharmony_ci } 32161cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 32171cb0ef41Sopenharmony_ci} 32181cb0ef41Sopenharmony_ci 32191cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestEqual() { 32201cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 32211cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 32221cb0ef41Sopenharmony_ci BuildCompareOp(javascript()->Equal(feedback)); 32231cb0ef41Sopenharmony_ci} 32241cb0ef41Sopenharmony_ci 32251cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestEqualStrict() { 32261cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 32271cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 32281cb0ef41Sopenharmony_ci BuildCompareOp(javascript()->StrictEqual(feedback)); 32291cb0ef41Sopenharmony_ci} 32301cb0ef41Sopenharmony_ci 32311cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestLessThan() { 32321cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 32331cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 32341cb0ef41Sopenharmony_ci BuildCompareOp(javascript()->LessThan(feedback)); 32351cb0ef41Sopenharmony_ci} 32361cb0ef41Sopenharmony_ci 32371cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestGreaterThan() { 32381cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 32391cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 32401cb0ef41Sopenharmony_ci BuildCompareOp(javascript()->GreaterThan(feedback)); 32411cb0ef41Sopenharmony_ci} 32421cb0ef41Sopenharmony_ci 32431cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestLessThanOrEqual() { 32441cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 32451cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 32461cb0ef41Sopenharmony_ci BuildCompareOp(javascript()->LessThanOrEqual(feedback)); 32471cb0ef41Sopenharmony_ci} 32481cb0ef41Sopenharmony_ci 32491cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestGreaterThanOrEqual() { 32501cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 32511cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 32521cb0ef41Sopenharmony_ci BuildCompareOp(javascript()->GreaterThanOrEqual(feedback)); 32531cb0ef41Sopenharmony_ci} 32541cb0ef41Sopenharmony_ci 32551cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestReferenceEqual() { 32561cb0ef41Sopenharmony_ci Node* left = 32571cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 32581cb0ef41Sopenharmony_ci Node* right = environment()->LookupAccumulator(); 32591cb0ef41Sopenharmony_ci Node* result = NewNode(simplified()->ReferenceEqual(), left, right); 32601cb0ef41Sopenharmony_ci environment()->BindAccumulator(result); 32611cb0ef41Sopenharmony_ci} 32621cb0ef41Sopenharmony_ci 32631cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestIn() { 32641cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 32651cb0ef41Sopenharmony_ci Node* object = environment()->LookupAccumulator(); 32661cb0ef41Sopenharmony_ci Node* key = 32671cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 32681cb0ef41Sopenharmony_ci FeedbackSource feedback = 32691cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1)); 32701cb0ef41Sopenharmony_ci STATIC_ASSERT(JSHasPropertyNode::ObjectIndex() == 0); 32711cb0ef41Sopenharmony_ci STATIC_ASSERT(JSHasPropertyNode::KeyIndex() == 1); 32721cb0ef41Sopenharmony_ci STATIC_ASSERT(JSHasPropertyNode::FeedbackVectorIndex() == 2); 32731cb0ef41Sopenharmony_ci const Operator* op = javascript()->HasProperty(feedback); 32741cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 32751cb0ef41Sopenharmony_ci Node* node = NewNode(op, object, key, feedback_vector_node()); 32761cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 32771cb0ef41Sopenharmony_ci} 32781cb0ef41Sopenharmony_ci 32791cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestInstanceOf() { 32801cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource( 32811cb0ef41Sopenharmony_ci bytecode_iterator().GetSlotOperand(kCompareOperationHintIndex)); 32821cb0ef41Sopenharmony_ci BuildCompareOp(javascript()->InstanceOf(feedback)); 32831cb0ef41Sopenharmony_ci} 32841cb0ef41Sopenharmony_ci 32851cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestUndetectable() { 32861cb0ef41Sopenharmony_ci Node* object = environment()->LookupAccumulator(); 32871cb0ef41Sopenharmony_ci Node* node = NewNode(jsgraph()->simplified()->ObjectIsUndetectable(), object); 32881cb0ef41Sopenharmony_ci environment()->BindAccumulator(node); 32891cb0ef41Sopenharmony_ci} 32901cb0ef41Sopenharmony_ci 32911cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestNull() { 32921cb0ef41Sopenharmony_ci Node* object = environment()->LookupAccumulator(); 32931cb0ef41Sopenharmony_ci Node* result = NewNode(simplified()->ReferenceEqual(), object, 32941cb0ef41Sopenharmony_ci jsgraph()->NullConstant()); 32951cb0ef41Sopenharmony_ci environment()->BindAccumulator(result); 32961cb0ef41Sopenharmony_ci} 32971cb0ef41Sopenharmony_ci 32981cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestUndefined() { 32991cb0ef41Sopenharmony_ci Node* object = environment()->LookupAccumulator(); 33001cb0ef41Sopenharmony_ci Node* result = NewNode(simplified()->ReferenceEqual(), object, 33011cb0ef41Sopenharmony_ci jsgraph()->UndefinedConstant()); 33021cb0ef41Sopenharmony_ci environment()->BindAccumulator(result); 33031cb0ef41Sopenharmony_ci} 33041cb0ef41Sopenharmony_ci 33051cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitTestTypeOf() { 33061cb0ef41Sopenharmony_ci Node* object = environment()->LookupAccumulator(); 33071cb0ef41Sopenharmony_ci auto literal_flag = interpreter::TestTypeOfFlags::Decode( 33081cb0ef41Sopenharmony_ci bytecode_iterator().GetFlagOperand(0)); 33091cb0ef41Sopenharmony_ci Node* result; 33101cb0ef41Sopenharmony_ci switch (literal_flag) { 33111cb0ef41Sopenharmony_ci case interpreter::TestTypeOfFlags::LiteralFlag::kNumber: 33121cb0ef41Sopenharmony_ci result = NewNode(simplified()->ObjectIsNumber(), object); 33131cb0ef41Sopenharmony_ci break; 33141cb0ef41Sopenharmony_ci case interpreter::TestTypeOfFlags::LiteralFlag::kString: 33151cb0ef41Sopenharmony_ci result = NewNode(simplified()->ObjectIsString(), object); 33161cb0ef41Sopenharmony_ci break; 33171cb0ef41Sopenharmony_ci case interpreter::TestTypeOfFlags::LiteralFlag::kSymbol: 33181cb0ef41Sopenharmony_ci result = NewNode(simplified()->ObjectIsSymbol(), object); 33191cb0ef41Sopenharmony_ci break; 33201cb0ef41Sopenharmony_ci case interpreter::TestTypeOfFlags::LiteralFlag::kBigInt: 33211cb0ef41Sopenharmony_ci result = NewNode(simplified()->ObjectIsBigInt(), object); 33221cb0ef41Sopenharmony_ci break; 33231cb0ef41Sopenharmony_ci case interpreter::TestTypeOfFlags::LiteralFlag::kBoolean: 33241cb0ef41Sopenharmony_ci result = NewNode(common()->Select(MachineRepresentation::kTagged), 33251cb0ef41Sopenharmony_ci NewNode(simplified()->ReferenceEqual(), object, 33261cb0ef41Sopenharmony_ci jsgraph()->TrueConstant()), 33271cb0ef41Sopenharmony_ci jsgraph()->TrueConstant(), 33281cb0ef41Sopenharmony_ci NewNode(simplified()->ReferenceEqual(), object, 33291cb0ef41Sopenharmony_ci jsgraph()->FalseConstant())); 33301cb0ef41Sopenharmony_ci break; 33311cb0ef41Sopenharmony_ci case interpreter::TestTypeOfFlags::LiteralFlag::kUndefined: 33321cb0ef41Sopenharmony_ci result = graph()->NewNode( 33331cb0ef41Sopenharmony_ci common()->Select(MachineRepresentation::kTagged), 33341cb0ef41Sopenharmony_ci graph()->NewNode(simplified()->ReferenceEqual(), object, 33351cb0ef41Sopenharmony_ci jsgraph()->NullConstant()), 33361cb0ef41Sopenharmony_ci jsgraph()->FalseConstant(), 33371cb0ef41Sopenharmony_ci graph()->NewNode(simplified()->ObjectIsUndetectable(), object)); 33381cb0ef41Sopenharmony_ci break; 33391cb0ef41Sopenharmony_ci case interpreter::TestTypeOfFlags::LiteralFlag::kFunction: 33401cb0ef41Sopenharmony_ci result = 33411cb0ef41Sopenharmony_ci graph()->NewNode(simplified()->ObjectIsDetectableCallable(), object); 33421cb0ef41Sopenharmony_ci break; 33431cb0ef41Sopenharmony_ci case interpreter::TestTypeOfFlags::LiteralFlag::kObject: 33441cb0ef41Sopenharmony_ci result = graph()->NewNode( 33451cb0ef41Sopenharmony_ci common()->Select(MachineRepresentation::kTagged), 33461cb0ef41Sopenharmony_ci graph()->NewNode(simplified()->ObjectIsNonCallable(), object), 33471cb0ef41Sopenharmony_ci jsgraph()->TrueConstant(), 33481cb0ef41Sopenharmony_ci graph()->NewNode(simplified()->ReferenceEqual(), object, 33491cb0ef41Sopenharmony_ci jsgraph()->NullConstant())); 33501cb0ef41Sopenharmony_ci break; 33511cb0ef41Sopenharmony_ci case interpreter::TestTypeOfFlags::LiteralFlag::kOther: 33521cb0ef41Sopenharmony_ci UNREACHABLE(); // Should never be emitted. 33531cb0ef41Sopenharmony_ci } 33541cb0ef41Sopenharmony_ci environment()->BindAccumulator(result); 33551cb0ef41Sopenharmony_ci} 33561cb0ef41Sopenharmony_ci 33571cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildCastOperator(const Operator* js_op) { 33581cb0ef41Sopenharmony_ci Node* value = NewNode(js_op, environment()->LookupAccumulator()); 33591cb0ef41Sopenharmony_ci environment()->BindRegister(bytecode_iterator().GetRegisterOperand(0), value, 33601cb0ef41Sopenharmony_ci Environment::kAttachFrameState); 33611cb0ef41Sopenharmony_ci} 33621cb0ef41Sopenharmony_ci 33631cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitToName() { 33641cb0ef41Sopenharmony_ci BuildCastOperator(javascript()->ToName()); 33651cb0ef41Sopenharmony_ci} 33661cb0ef41Sopenharmony_ci 33671cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitToObject() { 33681cb0ef41Sopenharmony_ci BuildCastOperator(javascript()->ToObject()); 33691cb0ef41Sopenharmony_ci} 33701cb0ef41Sopenharmony_ci 33711cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitToString() { 33721cb0ef41Sopenharmony_ci Node* value = 33731cb0ef41Sopenharmony_ci NewNode(javascript()->ToString(), environment()->LookupAccumulator()); 33741cb0ef41Sopenharmony_ci environment()->BindAccumulator(value, Environment::kAttachFrameState); 33751cb0ef41Sopenharmony_ci} 33761cb0ef41Sopenharmony_ci 33771cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitToNumber() { 33781cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 33791cb0ef41Sopenharmony_ci Node* object = environment()->LookupAccumulator(); 33801cb0ef41Sopenharmony_ci 33811cb0ef41Sopenharmony_ci FeedbackSlot slot = bytecode_iterator().GetSlotOperand(0); 33821cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 33831cb0ef41Sopenharmony_ci TryBuildSimplifiedToNumber(object, slot); 33841cb0ef41Sopenharmony_ci 33851cb0ef41Sopenharmony_ci Node* node = nullptr; 33861cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 33871cb0ef41Sopenharmony_ci node = lowering.value(); 33881cb0ef41Sopenharmony_ci } else { 33891cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 33901cb0ef41Sopenharmony_ci node = NewNode(javascript()->ToNumber(), object); 33911cb0ef41Sopenharmony_ci } 33921cb0ef41Sopenharmony_ci 33931cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 33941cb0ef41Sopenharmony_ci} 33951cb0ef41Sopenharmony_ci 33961cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitToNumeric() { 33971cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 33981cb0ef41Sopenharmony_ci Node* object = environment()->LookupAccumulator(); 33991cb0ef41Sopenharmony_ci 34001cb0ef41Sopenharmony_ci // If we have some kind of Number feedback, we do the same lowering as for 34011cb0ef41Sopenharmony_ci // ToNumber. 34021cb0ef41Sopenharmony_ci FeedbackSlot slot = bytecode_iterator().GetSlotOperand(0); 34031cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 34041cb0ef41Sopenharmony_ci TryBuildSimplifiedToNumber(object, slot); 34051cb0ef41Sopenharmony_ci 34061cb0ef41Sopenharmony_ci Node* node = nullptr; 34071cb0ef41Sopenharmony_ci if (lowering.IsSideEffectFree()) { 34081cb0ef41Sopenharmony_ci node = lowering.value(); 34091cb0ef41Sopenharmony_ci } else { 34101cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 34111cb0ef41Sopenharmony_ci node = NewNode(javascript()->ToNumeric(), object); 34121cb0ef41Sopenharmony_ci } 34131cb0ef41Sopenharmony_ci 34141cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 34151cb0ef41Sopenharmony_ci} 34161cb0ef41Sopenharmony_ci 34171cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJump() { BuildJump(); } 34181cb0ef41Sopenharmony_ci 34191cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpConstant() { BuildJump(); } 34201cb0ef41Sopenharmony_ci 34211cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfTrue() { BuildJumpIfTrue(); } 34221cb0ef41Sopenharmony_ci 34231cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfTrueConstant() { BuildJumpIfTrue(); } 34241cb0ef41Sopenharmony_ci 34251cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfFalse() { BuildJumpIfFalse(); } 34261cb0ef41Sopenharmony_ci 34271cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfFalseConstant() { BuildJumpIfFalse(); } 34281cb0ef41Sopenharmony_ci 34291cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfToBooleanTrue() { 34301cb0ef41Sopenharmony_ci BuildJumpIfToBooleanTrue(); 34311cb0ef41Sopenharmony_ci} 34321cb0ef41Sopenharmony_ci 34331cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfToBooleanTrueConstant() { 34341cb0ef41Sopenharmony_ci BuildJumpIfToBooleanTrue(); 34351cb0ef41Sopenharmony_ci} 34361cb0ef41Sopenharmony_ci 34371cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfToBooleanFalse() { 34381cb0ef41Sopenharmony_ci BuildJumpIfToBooleanFalse(); 34391cb0ef41Sopenharmony_ci} 34401cb0ef41Sopenharmony_ci 34411cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfToBooleanFalseConstant() { 34421cb0ef41Sopenharmony_ci BuildJumpIfToBooleanFalse(); 34431cb0ef41Sopenharmony_ci} 34441cb0ef41Sopenharmony_ci 34451cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfJSReceiver() { BuildJumpIfJSReceiver(); } 34461cb0ef41Sopenharmony_ci 34471cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfJSReceiverConstant() { 34481cb0ef41Sopenharmony_ci BuildJumpIfJSReceiver(); 34491cb0ef41Sopenharmony_ci} 34501cb0ef41Sopenharmony_ci 34511cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfNull() { 34521cb0ef41Sopenharmony_ci BuildJumpIfEqual(jsgraph()->NullConstant()); 34531cb0ef41Sopenharmony_ci} 34541cb0ef41Sopenharmony_ci 34551cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfNullConstant() { 34561cb0ef41Sopenharmony_ci BuildJumpIfEqual(jsgraph()->NullConstant()); 34571cb0ef41Sopenharmony_ci} 34581cb0ef41Sopenharmony_ci 34591cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfNotNull() { 34601cb0ef41Sopenharmony_ci BuildJumpIfNotEqual(jsgraph()->NullConstant()); 34611cb0ef41Sopenharmony_ci} 34621cb0ef41Sopenharmony_ci 34631cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfNotNullConstant() { 34641cb0ef41Sopenharmony_ci BuildJumpIfNotEqual(jsgraph()->NullConstant()); 34651cb0ef41Sopenharmony_ci} 34661cb0ef41Sopenharmony_ci 34671cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfUndefined() { 34681cb0ef41Sopenharmony_ci BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 34691cb0ef41Sopenharmony_ci} 34701cb0ef41Sopenharmony_ci 34711cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfUndefinedConstant() { 34721cb0ef41Sopenharmony_ci BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 34731cb0ef41Sopenharmony_ci} 34741cb0ef41Sopenharmony_ci 34751cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfNotUndefined() { 34761cb0ef41Sopenharmony_ci BuildJumpIfNotEqual(jsgraph()->UndefinedConstant()); 34771cb0ef41Sopenharmony_ci} 34781cb0ef41Sopenharmony_ci 34791cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfNotUndefinedConstant() { 34801cb0ef41Sopenharmony_ci BuildJumpIfNotEqual(jsgraph()->UndefinedConstant()); 34811cb0ef41Sopenharmony_ci} 34821cb0ef41Sopenharmony_ci 34831cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfUndefinedOrNull() { 34841cb0ef41Sopenharmony_ci BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 34851cb0ef41Sopenharmony_ci BuildJumpIfEqual(jsgraph()->NullConstant()); 34861cb0ef41Sopenharmony_ci} 34871cb0ef41Sopenharmony_ci 34881cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpIfUndefinedOrNullConstant() { 34891cb0ef41Sopenharmony_ci BuildJumpIfEqual(jsgraph()->UndefinedConstant()); 34901cb0ef41Sopenharmony_ci BuildJumpIfEqual(jsgraph()->NullConstant()); 34911cb0ef41Sopenharmony_ci} 34921cb0ef41Sopenharmony_ci 34931cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitJumpLoop() { 34941cb0ef41Sopenharmony_ci BuildIterationBodyStackCheck(); 34951cb0ef41Sopenharmony_ci BuildJump(); 34961cb0ef41Sopenharmony_ci} 34971cb0ef41Sopenharmony_ci 34981cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildSwitchOnSmi(Node* condition) { 34991cb0ef41Sopenharmony_ci interpreter::JumpTableTargetOffsets offsets = 35001cb0ef41Sopenharmony_ci bytecode_iterator().GetJumpTableTargetOffsets(); 35011cb0ef41Sopenharmony_ci 35021cb0ef41Sopenharmony_ci NewSwitch(condition, offsets.size() + 1); 35031cb0ef41Sopenharmony_ci for (interpreter::JumpTableTargetOffset entry : offsets) { 35041cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 35051cb0ef41Sopenharmony_ci NewIfValue(entry.case_value); 35061cb0ef41Sopenharmony_ci MergeIntoSuccessorEnvironment(entry.target_offset); 35071cb0ef41Sopenharmony_ci } 35081cb0ef41Sopenharmony_ci NewIfDefault(); 35091cb0ef41Sopenharmony_ci} 35101cb0ef41Sopenharmony_ci 35111cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitSwitchOnSmiNoFeedback() { 35121cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 35131cb0ef41Sopenharmony_ci 35141cb0ef41Sopenharmony_ci Node* acc = environment()->LookupAccumulator(); 35151cb0ef41Sopenharmony_ci Node* acc_smi = NewNode(simplified()->CheckSmi(FeedbackSource()), acc); 35161cb0ef41Sopenharmony_ci BuildSwitchOnSmi(acc_smi); 35171cb0ef41Sopenharmony_ci} 35181cb0ef41Sopenharmony_ci 35191cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitSetPendingMessage() { 35201cb0ef41Sopenharmony_ci Node* previous_message = NewNode(javascript()->LoadMessage()); 35211cb0ef41Sopenharmony_ci NewNode(javascript()->StoreMessage(), environment()->LookupAccumulator()); 35221cb0ef41Sopenharmony_ci environment()->BindAccumulator(previous_message); 35231cb0ef41Sopenharmony_ci} 35241cb0ef41Sopenharmony_ci 35251cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildReturn(const BytecodeLivenessState* liveness) { 35261cb0ef41Sopenharmony_ci BuildLoopExitsForFunctionExit(liveness); 35271cb0ef41Sopenharmony_ci Node* pop_node = jsgraph()->ZeroConstant(); 35281cb0ef41Sopenharmony_ci Node* control = 35291cb0ef41Sopenharmony_ci NewNode(common()->Return(), pop_node, environment()->LookupAccumulator()); 35301cb0ef41Sopenharmony_ci MergeControlToLeaveFunction(control); 35311cb0ef41Sopenharmony_ci} 35321cb0ef41Sopenharmony_ci 35331cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitReturn() { 35341cb0ef41Sopenharmony_ci BuildReturn(bytecode_analysis().GetInLivenessFor( 35351cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 35361cb0ef41Sopenharmony_ci} 35371cb0ef41Sopenharmony_ci 35381cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitDebugger() { 35391cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 35401cb0ef41Sopenharmony_ci Node* call = NewNode(javascript()->Debugger()); 35411cb0ef41Sopenharmony_ci environment()->RecordAfterState(call, Environment::kAttachFrameState); 35421cb0ef41Sopenharmony_ci} 35431cb0ef41Sopenharmony_ci 35441cb0ef41Sopenharmony_ci// We cannot create a graph from the debugger copy of the bytecode array. 35451cb0ef41Sopenharmony_ci#define DEBUG_BREAK(Name, ...) \ 35461cb0ef41Sopenharmony_ci void BytecodeGraphBuilder::Visit##Name() { UNREACHABLE(); } 35471cb0ef41Sopenharmony_ciDEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK) 35481cb0ef41Sopenharmony_ci#undef DEBUG_BREAK 35491cb0ef41Sopenharmony_ci 35501cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitIncBlockCounter() { 35511cb0ef41Sopenharmony_ci Node* closure = GetFunctionClosure(); 35521cb0ef41Sopenharmony_ci Node* coverage_array_slot = 35531cb0ef41Sopenharmony_ci jsgraph()->Constant(bytecode_iterator().GetIndexOperand(0)); 35541cb0ef41Sopenharmony_ci 35551cb0ef41Sopenharmony_ci // Lowered by js-intrinsic-lowering to call Builtin::kIncBlockCounter. 35561cb0ef41Sopenharmony_ci const Operator* op = 35571cb0ef41Sopenharmony_ci javascript()->CallRuntime(Runtime::kInlineIncBlockCounter); 35581cb0ef41Sopenharmony_ci 35591cb0ef41Sopenharmony_ci NewNode(op, closure, coverage_array_slot); 35601cb0ef41Sopenharmony_ci} 35611cb0ef41Sopenharmony_ci 35621cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitForInEnumerate() { 35631cb0ef41Sopenharmony_ci Node* receiver = 35641cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 35651cb0ef41Sopenharmony_ci Node* enumerator = NewNode(javascript()->ForInEnumerate(), receiver); 35661cb0ef41Sopenharmony_ci environment()->BindAccumulator(enumerator, Environment::kAttachFrameState); 35671cb0ef41Sopenharmony_ci} 35681cb0ef41Sopenharmony_ci 35691cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitForInPrepare() { 35701cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 35711cb0ef41Sopenharmony_ci Node* enumerator = environment()->LookupAccumulator(); 35721cb0ef41Sopenharmony_ci 35731cb0ef41Sopenharmony_ci FeedbackSlot slot = bytecode_iterator().GetSlotOperand(1); 35741cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = 35751cb0ef41Sopenharmony_ci TryBuildSimplifiedForInPrepare(enumerator, slot); 35761cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 35771cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 35781cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource(slot); 35791cb0ef41Sopenharmony_ci Node* node = NewNode(javascript()->ForInPrepare(GetForInMode(slot), feedback), 35801cb0ef41Sopenharmony_ci enumerator, feedback_vector_node()); 35811cb0ef41Sopenharmony_ci environment()->BindRegistersToProjections( 35821cb0ef41Sopenharmony_ci bytecode_iterator().GetRegisterOperand(0), node); 35831cb0ef41Sopenharmony_ci} 35841cb0ef41Sopenharmony_ci 35851cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitForInContinue() { 35861cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 35871cb0ef41Sopenharmony_ci Node* index = 35881cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 35891cb0ef41Sopenharmony_ci Node* cache_length = 35901cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 35911cb0ef41Sopenharmony_ci Node* exit_cond = NewNode(simplified()->SpeculativeNumberLessThan( 35921cb0ef41Sopenharmony_ci NumberOperationHint::kSignedSmall), 35931cb0ef41Sopenharmony_ci index, cache_length); 35941cb0ef41Sopenharmony_ci environment()->BindAccumulator(exit_cond); 35951cb0ef41Sopenharmony_ci} 35961cb0ef41Sopenharmony_ci 35971cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitForInNext() { 35981cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 35991cb0ef41Sopenharmony_ci Node* receiver = 36001cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 36011cb0ef41Sopenharmony_ci Node* index = 36021cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); 36031cb0ef41Sopenharmony_ci int catch_reg_pair_index = bytecode_iterator().GetRegisterOperand(2).index(); 36041cb0ef41Sopenharmony_ci Node* cache_type = environment()->LookupRegister( 36051cb0ef41Sopenharmony_ci interpreter::Register(catch_reg_pair_index)); 36061cb0ef41Sopenharmony_ci Node* cache_array = environment()->LookupRegister( 36071cb0ef41Sopenharmony_ci interpreter::Register(catch_reg_pair_index + 1)); 36081cb0ef41Sopenharmony_ci 36091cb0ef41Sopenharmony_ci // We need to rename the {index} here, as in case of OSR we lose the 36101cb0ef41Sopenharmony_ci // information that the {index} is always a valid unsigned Smi value. 36111cb0ef41Sopenharmony_ci index = NewNode(common()->TypeGuard(Type::UnsignedSmall()), index); 36121cb0ef41Sopenharmony_ci 36131cb0ef41Sopenharmony_ci FeedbackSlot slot = bytecode_iterator().GetSlotOperand(3); 36141cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedForInNext( 36151cb0ef41Sopenharmony_ci receiver, cache_array, cache_type, index, slot); 36161cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 36171cb0ef41Sopenharmony_ci 36181cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 36191cb0ef41Sopenharmony_ci FeedbackSource feedback = CreateFeedbackSource(slot); 36201cb0ef41Sopenharmony_ci Node* node = 36211cb0ef41Sopenharmony_ci NewNode(javascript()->ForInNext(GetForInMode(slot), feedback), receiver, 36221cb0ef41Sopenharmony_ci cache_array, cache_type, index, feedback_vector_node()); 36231cb0ef41Sopenharmony_ci environment()->BindAccumulator(node, Environment::kAttachFrameState); 36241cb0ef41Sopenharmony_ci} 36251cb0ef41Sopenharmony_ci 36261cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitForInStep() { 36271cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 36281cb0ef41Sopenharmony_ci Node* index = 36291cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 36301cb0ef41Sopenharmony_ci index = NewNode(simplified()->SpeculativeSafeIntegerAdd( 36311cb0ef41Sopenharmony_ci NumberOperationHint::kSignedSmall), 36321cb0ef41Sopenharmony_ci index, jsgraph()->OneConstant()); 36331cb0ef41Sopenharmony_ci environment()->BindAccumulator(index, Environment::kAttachFrameState); 36341cb0ef41Sopenharmony_ci} 36351cb0ef41Sopenharmony_ci 36361cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitGetIterator() { 36371cb0ef41Sopenharmony_ci PrepareEagerCheckpoint(); 36381cb0ef41Sopenharmony_ci Node* receiver = 36391cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 36401cb0ef41Sopenharmony_ci FeedbackSource load_feedback = 36411cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(1)); 36421cb0ef41Sopenharmony_ci FeedbackSource call_feedback = 36431cb0ef41Sopenharmony_ci CreateFeedbackSource(bytecode_iterator().GetIndexOperand(2)); 36441cb0ef41Sopenharmony_ci const Operator* op = javascript()->GetIterator(load_feedback, call_feedback); 36451cb0ef41Sopenharmony_ci 36461cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult lowering = TryBuildSimplifiedGetIterator( 36471cb0ef41Sopenharmony_ci op, receiver, load_feedback.slot, call_feedback.slot); 36481cb0ef41Sopenharmony_ci if (lowering.IsExit()) return; 36491cb0ef41Sopenharmony_ci 36501cb0ef41Sopenharmony_ci DCHECK(!lowering.Changed()); 36511cb0ef41Sopenharmony_ci STATIC_ASSERT(JSGetIteratorNode::ReceiverIndex() == 0); 36521cb0ef41Sopenharmony_ci STATIC_ASSERT(JSGetIteratorNode::FeedbackVectorIndex() == 1); 36531cb0ef41Sopenharmony_ci DCHECK(IrOpcode::IsFeedbackCollectingOpcode(op->opcode())); 36541cb0ef41Sopenharmony_ci Node* iterator = NewNode(op, receiver, feedback_vector_node()); 36551cb0ef41Sopenharmony_ci environment()->BindAccumulator(iterator, Environment::kAttachFrameState); 36561cb0ef41Sopenharmony_ci} 36571cb0ef41Sopenharmony_ci 36581cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitSuspendGenerator() { 36591cb0ef41Sopenharmony_ci Node* generator = environment()->LookupRegister( 36601cb0ef41Sopenharmony_ci bytecode_iterator().GetRegisterOperand(0)); 36611cb0ef41Sopenharmony_ci interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 36621cb0ef41Sopenharmony_ci // We assume we are storing a range starting from index 0. 36631cb0ef41Sopenharmony_ci CHECK_EQ(0, first_reg.index()); 36641cb0ef41Sopenharmony_ci int register_count = 36651cb0ef41Sopenharmony_ci static_cast<int>(bytecode_iterator().GetRegisterCountOperand(2)); 36661cb0ef41Sopenharmony_ci int parameter_count_without_receiver = bytecode_array().parameter_count() - 1; 36671cb0ef41Sopenharmony_ci 36681cb0ef41Sopenharmony_ci Node* suspend_id = jsgraph()->SmiConstant( 36691cb0ef41Sopenharmony_ci bytecode_iterator().GetUnsignedImmediateOperand(3)); 36701cb0ef41Sopenharmony_ci 36711cb0ef41Sopenharmony_ci // The offsets used by the bytecode iterator are relative to a different base 36721cb0ef41Sopenharmony_ci // than what is used in the interpreter, hence the addition. 36731cb0ef41Sopenharmony_ci Node* offset = 36741cb0ef41Sopenharmony_ci jsgraph()->Constant(bytecode_iterator().current_offset() + 36751cb0ef41Sopenharmony_ci (BytecodeArray::kHeaderSize - kHeapObjectTag)); 36761cb0ef41Sopenharmony_ci 36771cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness = bytecode_analysis().GetInLivenessFor( 36781cb0ef41Sopenharmony_ci bytecode_iterator().current_offset()); 36791cb0ef41Sopenharmony_ci 36801cb0ef41Sopenharmony_ci // Maybe overallocate the value list since we don't know how many registers 36811cb0ef41Sopenharmony_ci // are live. 36821cb0ef41Sopenharmony_ci // TODO(leszeks): We could get this count from liveness rather than the 36831cb0ef41Sopenharmony_ci // register list. 36841cb0ef41Sopenharmony_ci int value_input_count = 3 + parameter_count_without_receiver + register_count; 36851cb0ef41Sopenharmony_ci 36861cb0ef41Sopenharmony_ci Node** value_inputs = local_zone()->NewArray<Node*>(value_input_count); 36871cb0ef41Sopenharmony_ci value_inputs[0] = generator; 36881cb0ef41Sopenharmony_ci value_inputs[1] = suspend_id; 36891cb0ef41Sopenharmony_ci value_inputs[2] = offset; 36901cb0ef41Sopenharmony_ci 36911cb0ef41Sopenharmony_ci int count_written = 0; 36921cb0ef41Sopenharmony_ci // Store the parameters. 36931cb0ef41Sopenharmony_ci for (int i = 0; i < parameter_count_without_receiver; i++) { 36941cb0ef41Sopenharmony_ci value_inputs[3 + count_written++] = 36951cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetParameter(i)); 36961cb0ef41Sopenharmony_ci } 36971cb0ef41Sopenharmony_ci 36981cb0ef41Sopenharmony_ci // Store the registers. 36991cb0ef41Sopenharmony_ci for (int i = 0; i < register_count; ++i) { 37001cb0ef41Sopenharmony_ci if (liveness == nullptr || liveness->RegisterIsLive(i)) { 37011cb0ef41Sopenharmony_ci int index_in_parameters_and_registers = 37021cb0ef41Sopenharmony_ci parameter_count_without_receiver + i; 37031cb0ef41Sopenharmony_ci while (count_written < index_in_parameters_and_registers) { 37041cb0ef41Sopenharmony_ci value_inputs[3 + count_written++] = jsgraph()->OptimizedOutConstant(); 37051cb0ef41Sopenharmony_ci } 37061cb0ef41Sopenharmony_ci value_inputs[3 + count_written++] = 37071cb0ef41Sopenharmony_ci environment()->LookupRegister(interpreter::Register(i)); 37081cb0ef41Sopenharmony_ci DCHECK_EQ(count_written, index_in_parameters_and_registers + 1); 37091cb0ef41Sopenharmony_ci } 37101cb0ef41Sopenharmony_ci } 37111cb0ef41Sopenharmony_ci 37121cb0ef41Sopenharmony_ci // Use the actual written count rather than the register count to create the 37131cb0ef41Sopenharmony_ci // node. 37141cb0ef41Sopenharmony_ci MakeNode(javascript()->GeneratorStore(count_written), 3 + count_written, 37151cb0ef41Sopenharmony_ci value_inputs, false); 37161cb0ef41Sopenharmony_ci 37171cb0ef41Sopenharmony_ci // TODO(leszeks): This over-approximates the liveness at exit, only the 37181cb0ef41Sopenharmony_ci // accumulator should be live by this point. 37191cb0ef41Sopenharmony_ci BuildReturn(bytecode_analysis().GetInLivenessFor( 37201cb0ef41Sopenharmony_ci bytecode_iterator().current_offset())); 37211cb0ef41Sopenharmony_ci} 37221cb0ef41Sopenharmony_ci 37231cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildSwitchOnGeneratorState( 37241cb0ef41Sopenharmony_ci const ZoneVector<ResumeJumpTarget>& resume_jump_targets, 37251cb0ef41Sopenharmony_ci bool allow_fallthrough_on_executing) { 37261cb0ef41Sopenharmony_ci Node* generator_state = environment()->LookupGeneratorState(); 37271cb0ef41Sopenharmony_ci 37281cb0ef41Sopenharmony_ci int extra_cases = allow_fallthrough_on_executing ? 2 : 1; 37291cb0ef41Sopenharmony_ci NewSwitch(generator_state, 37301cb0ef41Sopenharmony_ci static_cast<int>(resume_jump_targets.size() + extra_cases)); 37311cb0ef41Sopenharmony_ci for (const ResumeJumpTarget& target : resume_jump_targets) { 37321cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 37331cb0ef41Sopenharmony_ci NewIfValue(target.suspend_id()); 37341cb0ef41Sopenharmony_ci if (target.is_leaf()) { 37351cb0ef41Sopenharmony_ci // Mark that we are resuming executing. 37361cb0ef41Sopenharmony_ci environment()->BindGeneratorState( 37371cb0ef41Sopenharmony_ci jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting)); 37381cb0ef41Sopenharmony_ci } 37391cb0ef41Sopenharmony_ci // Jump to the target offset, whether it's a loop header or the resume. 37401cb0ef41Sopenharmony_ci MergeIntoSuccessorEnvironment(target.target_offset()); 37411cb0ef41Sopenharmony_ci } 37421cb0ef41Sopenharmony_ci 37431cb0ef41Sopenharmony_ci { 37441cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 37451cb0ef41Sopenharmony_ci // We should never hit the default case (assuming generator state cannot be 37461cb0ef41Sopenharmony_ci // corrupted), so abort if we do. 37471cb0ef41Sopenharmony_ci // TODO(leszeks): Maybe only check this in debug mode, and otherwise use 37481cb0ef41Sopenharmony_ci // the default to represent one of the cases above/fallthrough below? 37491cb0ef41Sopenharmony_ci NewIfDefault(); 37501cb0ef41Sopenharmony_ci NewNode(simplified()->RuntimeAbort(AbortReason::kInvalidJumpTableIndex)); 37511cb0ef41Sopenharmony_ci // TODO(7099): Investigate if we need LoopExit here. 37521cb0ef41Sopenharmony_ci Node* control = NewNode(common()->Throw()); 37531cb0ef41Sopenharmony_ci MergeControlToLeaveFunction(control); 37541cb0ef41Sopenharmony_ci } 37551cb0ef41Sopenharmony_ci 37561cb0ef41Sopenharmony_ci if (allow_fallthrough_on_executing) { 37571cb0ef41Sopenharmony_ci // If we are executing (rather than resuming), and we allow it, just fall 37581cb0ef41Sopenharmony_ci // through to the actual loop body. 37591cb0ef41Sopenharmony_ci NewIfValue(JSGeneratorObject::kGeneratorExecuting); 37601cb0ef41Sopenharmony_ci } else { 37611cb0ef41Sopenharmony_ci // Otherwise, this environment is dead. 37621cb0ef41Sopenharmony_ci set_environment(nullptr); 37631cb0ef41Sopenharmony_ci } 37641cb0ef41Sopenharmony_ci} 37651cb0ef41Sopenharmony_ci 37661cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitSwitchOnGeneratorState() { 37671cb0ef41Sopenharmony_ci Node* generator = 37681cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 37691cb0ef41Sopenharmony_ci 37701cb0ef41Sopenharmony_ci Node* generator_is_undefined = 37711cb0ef41Sopenharmony_ci NewNode(simplified()->ReferenceEqual(), generator, 37721cb0ef41Sopenharmony_ci jsgraph()->UndefinedConstant()); 37731cb0ef41Sopenharmony_ci 37741cb0ef41Sopenharmony_ci NewBranch(generator_is_undefined); 37751cb0ef41Sopenharmony_ci { 37761cb0ef41Sopenharmony_ci SubEnvironment resume_env(this); 37771cb0ef41Sopenharmony_ci NewIfFalse(); 37781cb0ef41Sopenharmony_ci 37791cb0ef41Sopenharmony_ci Node* generator_state = 37801cb0ef41Sopenharmony_ci NewNode(javascript()->GeneratorRestoreContinuation(), generator); 37811cb0ef41Sopenharmony_ci environment()->BindGeneratorState(generator_state); 37821cb0ef41Sopenharmony_ci 37831cb0ef41Sopenharmony_ci Node* generator_context = 37841cb0ef41Sopenharmony_ci NewNode(javascript()->GeneratorRestoreContext(), generator); 37851cb0ef41Sopenharmony_ci environment()->SetContext(generator_context); 37861cb0ef41Sopenharmony_ci 37871cb0ef41Sopenharmony_ci BuildSwitchOnGeneratorState(bytecode_analysis().resume_jump_targets(), 37881cb0ef41Sopenharmony_ci false); 37891cb0ef41Sopenharmony_ci } 37901cb0ef41Sopenharmony_ci 37911cb0ef41Sopenharmony_ci // Fallthrough for the first-call case. 37921cb0ef41Sopenharmony_ci NewIfTrue(); 37931cb0ef41Sopenharmony_ci} 37941cb0ef41Sopenharmony_ci 37951cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitResumeGenerator() { 37961cb0ef41Sopenharmony_ci Node* generator = 37971cb0ef41Sopenharmony_ci environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 37981cb0ef41Sopenharmony_ci interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); 37991cb0ef41Sopenharmony_ci // We assume we are restoring registers starting fromm index 0. 38001cb0ef41Sopenharmony_ci CHECK_EQ(0, first_reg.index()); 38011cb0ef41Sopenharmony_ci 38021cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness = bytecode_analysis().GetOutLivenessFor( 38031cb0ef41Sopenharmony_ci bytecode_iterator().current_offset()); 38041cb0ef41Sopenharmony_ci 38051cb0ef41Sopenharmony_ci int parameter_count_without_receiver = bytecode_array().parameter_count() - 1; 38061cb0ef41Sopenharmony_ci 38071cb0ef41Sopenharmony_ci // Mapping between registers and array indices must match that used in 38081cb0ef41Sopenharmony_ci // InterpreterAssembler::ExportParametersAndRegisterFile. 38091cb0ef41Sopenharmony_ci for (int i = 0; i < environment()->register_count(); ++i) { 38101cb0ef41Sopenharmony_ci if (liveness == nullptr || liveness->RegisterIsLive(i)) { 38111cb0ef41Sopenharmony_ci Node* value = NewNode(javascript()->GeneratorRestoreRegister( 38121cb0ef41Sopenharmony_ci parameter_count_without_receiver + i), 38131cb0ef41Sopenharmony_ci generator); 38141cb0ef41Sopenharmony_ci environment()->BindRegister(interpreter::Register(i), value); 38151cb0ef41Sopenharmony_ci } 38161cb0ef41Sopenharmony_ci } 38171cb0ef41Sopenharmony_ci 38181cb0ef41Sopenharmony_ci // Update the accumulator with the generator's input_or_debug_pos. 38191cb0ef41Sopenharmony_ci Node* input_or_debug_pos = 38201cb0ef41Sopenharmony_ci NewNode(javascript()->GeneratorRestoreInputOrDebugPos(), generator); 38211cb0ef41Sopenharmony_ci environment()->BindAccumulator(input_or_debug_pos); 38221cb0ef41Sopenharmony_ci} 38231cb0ef41Sopenharmony_ci 38241cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitWide() { 38251cb0ef41Sopenharmony_ci // Consumed by the BytecodeArrayIterator. 38261cb0ef41Sopenharmony_ci UNREACHABLE(); 38271cb0ef41Sopenharmony_ci} 38281cb0ef41Sopenharmony_ci 38291cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitExtraWide() { 38301cb0ef41Sopenharmony_ci // Consumed by the BytecodeArrayIterator. 38311cb0ef41Sopenharmony_ci UNREACHABLE(); 38321cb0ef41Sopenharmony_ci} 38331cb0ef41Sopenharmony_ci 38341cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::VisitIllegal() { 38351cb0ef41Sopenharmony_ci // Not emitted in valid bytecode. 38361cb0ef41Sopenharmony_ci UNREACHABLE(); 38371cb0ef41Sopenharmony_ci} 38381cb0ef41Sopenharmony_ci 38391cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) { 38401cb0ef41Sopenharmony_ci auto it = merge_environments_.find(current_offset); 38411cb0ef41Sopenharmony_ci if (it != merge_environments_.end()) { 38421cb0ef41Sopenharmony_ci mark_as_needing_eager_checkpoint(true); 38431cb0ef41Sopenharmony_ci if (environment() != nullptr) { 38441cb0ef41Sopenharmony_ci it->second->Merge(environment(), 38451cb0ef41Sopenharmony_ci bytecode_analysis().GetInLivenessFor(current_offset)); 38461cb0ef41Sopenharmony_ci } 38471cb0ef41Sopenharmony_ci set_environment(it->second); 38481cb0ef41Sopenharmony_ci } 38491cb0ef41Sopenharmony_ci} 38501cb0ef41Sopenharmony_ci 38511cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { 38521cb0ef41Sopenharmony_ci if (bytecode_analysis().IsLoopHeader(current_offset)) { 38531cb0ef41Sopenharmony_ci mark_as_needing_eager_checkpoint(true); 38541cb0ef41Sopenharmony_ci const LoopInfo& loop_info = 38551cb0ef41Sopenharmony_ci bytecode_analysis().GetLoopInfoFor(current_offset); 38561cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness = 38571cb0ef41Sopenharmony_ci bytecode_analysis().GetInLivenessFor(current_offset); 38581cb0ef41Sopenharmony_ci 38591cb0ef41Sopenharmony_ci const auto& resume_jump_targets = loop_info.resume_jump_targets(); 38601cb0ef41Sopenharmony_ci bool generate_suspend_switch = !resume_jump_targets.empty(); 38611cb0ef41Sopenharmony_ci 38621cb0ef41Sopenharmony_ci // Add loop header. 38631cb0ef41Sopenharmony_ci environment()->PrepareForLoop(loop_info.assignments(), liveness); 38641cb0ef41Sopenharmony_ci 38651cb0ef41Sopenharmony_ci // Store a copy of the environment so we can connect merged back edge inputs 38661cb0ef41Sopenharmony_ci // to the loop header. 38671cb0ef41Sopenharmony_ci merge_environments_[current_offset] = environment()->Copy(); 38681cb0ef41Sopenharmony_ci 38691cb0ef41Sopenharmony_ci // If this loop contains resumes, create a new switch just after the loop 38701cb0ef41Sopenharmony_ci // for those resumes. 38711cb0ef41Sopenharmony_ci if (generate_suspend_switch) { 38721cb0ef41Sopenharmony_ci BuildSwitchOnGeneratorState(loop_info.resume_jump_targets(), true); 38731cb0ef41Sopenharmony_ci 38741cb0ef41Sopenharmony_ci // TODO(leszeks): At this point we know we are executing rather than 38751cb0ef41Sopenharmony_ci // resuming, so we should be able to prune off the phis in the environment 38761cb0ef41Sopenharmony_ci // related to the resume path. 38771cb0ef41Sopenharmony_ci 38781cb0ef41Sopenharmony_ci // Set the generator state to a known constant. 38791cb0ef41Sopenharmony_ci environment()->BindGeneratorState( 38801cb0ef41Sopenharmony_ci jsgraph()->SmiConstant(JSGeneratorObject::kGeneratorExecuting)); 38811cb0ef41Sopenharmony_ci } 38821cb0ef41Sopenharmony_ci } 38831cb0ef41Sopenharmony_ci} 38841cb0ef41Sopenharmony_ci 38851cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { 38861cb0ef41Sopenharmony_ci BuildLoopExitsForBranch(target_offset); 38871cb0ef41Sopenharmony_ci Environment*& merge_environment = merge_environments_[target_offset]; 38881cb0ef41Sopenharmony_ci 38891cb0ef41Sopenharmony_ci if (merge_environment == nullptr) { 38901cb0ef41Sopenharmony_ci // Append merge nodes to the environment. We may merge here with another 38911cb0ef41Sopenharmony_ci // environment. So add a place holder for merge nodes. We may add redundant 38921cb0ef41Sopenharmony_ci // but will be eliminated in a later pass. 38931cb0ef41Sopenharmony_ci NewMerge(); 38941cb0ef41Sopenharmony_ci merge_environment = environment(); 38951cb0ef41Sopenharmony_ci } else { 38961cb0ef41Sopenharmony_ci // Merge any values which are live coming into the successor. 38971cb0ef41Sopenharmony_ci merge_environment->Merge( 38981cb0ef41Sopenharmony_ci environment(), bytecode_analysis().GetInLivenessFor(target_offset)); 38991cb0ef41Sopenharmony_ci } 39001cb0ef41Sopenharmony_ci set_environment(nullptr); 39011cb0ef41Sopenharmony_ci} 39021cb0ef41Sopenharmony_ci 39031cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { 39041cb0ef41Sopenharmony_ci exit_controls_.push_back(exit); 39051cb0ef41Sopenharmony_ci set_environment(nullptr); 39061cb0ef41Sopenharmony_ci} 39071cb0ef41Sopenharmony_ci 39081cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { 39091cb0ef41Sopenharmony_ci int origin_offset = bytecode_iterator().current_offset(); 39101cb0ef41Sopenharmony_ci // Only build loop exits for forward edges. 39111cb0ef41Sopenharmony_ci if (target_offset > origin_offset) { 39121cb0ef41Sopenharmony_ci BuildLoopExitsUntilLoop( 39131cb0ef41Sopenharmony_ci bytecode_analysis().GetLoopOffsetFor(target_offset), 39141cb0ef41Sopenharmony_ci bytecode_analysis().GetInLivenessFor(target_offset)); 39151cb0ef41Sopenharmony_ci } 39161cb0ef41Sopenharmony_ci} 39171cb0ef41Sopenharmony_ci 39181cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildLoopExitsUntilLoop( 39191cb0ef41Sopenharmony_ci int loop_offset, const BytecodeLivenessState* liveness) { 39201cb0ef41Sopenharmony_ci int origin_offset = bytecode_iterator().current_offset(); 39211cb0ef41Sopenharmony_ci int current_loop = bytecode_analysis().GetLoopOffsetFor(origin_offset); 39221cb0ef41Sopenharmony_ci // The limit_offset is the stop offset for building loop exists, used for OSR. 39231cb0ef41Sopenharmony_ci // It prevents the creations of loopexits for loops which do not exist. 39241cb0ef41Sopenharmony_ci loop_offset = std::max(loop_offset, currently_peeled_loop_offset_); 39251cb0ef41Sopenharmony_ci 39261cb0ef41Sopenharmony_ci while (loop_offset < current_loop) { 39271cb0ef41Sopenharmony_ci Node* loop_node = merge_environments_[current_loop]->GetControlDependency(); 39281cb0ef41Sopenharmony_ci const LoopInfo& loop_info = 39291cb0ef41Sopenharmony_ci bytecode_analysis().GetLoopInfoFor(current_loop); 39301cb0ef41Sopenharmony_ci environment()->PrepareForLoopExit(loop_node, loop_info.assignments(), 39311cb0ef41Sopenharmony_ci liveness); 39321cb0ef41Sopenharmony_ci current_loop = loop_info.parent_offset(); 39331cb0ef41Sopenharmony_ci } 39341cb0ef41Sopenharmony_ci} 39351cb0ef41Sopenharmony_ci 39361cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildLoopExitsForFunctionExit( 39371cb0ef41Sopenharmony_ci const BytecodeLivenessState* liveness) { 39381cb0ef41Sopenharmony_ci BuildLoopExitsUntilLoop(-1, liveness); 39391cb0ef41Sopenharmony_ci} 39401cb0ef41Sopenharmony_ci 39411cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJump() { 39421cb0ef41Sopenharmony_ci MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 39431cb0ef41Sopenharmony_ci} 39441cb0ef41Sopenharmony_ci 39451cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJumpIf(Node* condition) { 39461cb0ef41Sopenharmony_ci NewBranch(condition, BranchHint::kNone); 39471cb0ef41Sopenharmony_ci { 39481cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 39491cb0ef41Sopenharmony_ci NewIfTrue(); 39501cb0ef41Sopenharmony_ci MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 39511cb0ef41Sopenharmony_ci } 39521cb0ef41Sopenharmony_ci NewIfFalse(); 39531cb0ef41Sopenharmony_ci} 39541cb0ef41Sopenharmony_ci 39551cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) { 39561cb0ef41Sopenharmony_ci NewBranch(condition, BranchHint::kNone); 39571cb0ef41Sopenharmony_ci { 39581cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 39591cb0ef41Sopenharmony_ci NewIfFalse(); 39601cb0ef41Sopenharmony_ci MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 39611cb0ef41Sopenharmony_ci } 39621cb0ef41Sopenharmony_ci NewIfTrue(); 39631cb0ef41Sopenharmony_ci} 39641cb0ef41Sopenharmony_ci 39651cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJumpIfEqual(Node* comperand) { 39661cb0ef41Sopenharmony_ci Node* accumulator = environment()->LookupAccumulator(); 39671cb0ef41Sopenharmony_ci Node* condition = 39681cb0ef41Sopenharmony_ci NewNode(simplified()->ReferenceEqual(), accumulator, comperand); 39691cb0ef41Sopenharmony_ci BuildJumpIf(condition); 39701cb0ef41Sopenharmony_ci} 39711cb0ef41Sopenharmony_ci 39721cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJumpIfNotEqual(Node* comperand) { 39731cb0ef41Sopenharmony_ci Node* accumulator = environment()->LookupAccumulator(); 39741cb0ef41Sopenharmony_ci Node* condition = 39751cb0ef41Sopenharmony_ci NewNode(simplified()->ReferenceEqual(), accumulator, comperand); 39761cb0ef41Sopenharmony_ci BuildJumpIfNot(condition); 39771cb0ef41Sopenharmony_ci} 39781cb0ef41Sopenharmony_ci 39791cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJumpIfFalse() { 39801cb0ef41Sopenharmony_ci NewBranch(environment()->LookupAccumulator(), BranchHint::kNone); 39811cb0ef41Sopenharmony_ci { 39821cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 39831cb0ef41Sopenharmony_ci NewIfFalse(); 39841cb0ef41Sopenharmony_ci environment()->BindAccumulator(jsgraph()->FalseConstant()); 39851cb0ef41Sopenharmony_ci MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 39861cb0ef41Sopenharmony_ci } 39871cb0ef41Sopenharmony_ci NewIfTrue(); 39881cb0ef41Sopenharmony_ci environment()->BindAccumulator(jsgraph()->TrueConstant()); 39891cb0ef41Sopenharmony_ci} 39901cb0ef41Sopenharmony_ci 39911cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJumpIfTrue() { 39921cb0ef41Sopenharmony_ci NewBranch(environment()->LookupAccumulator(), BranchHint::kNone); 39931cb0ef41Sopenharmony_ci { 39941cb0ef41Sopenharmony_ci SubEnvironment sub_environment(this); 39951cb0ef41Sopenharmony_ci NewIfTrue(); 39961cb0ef41Sopenharmony_ci environment()->BindAccumulator(jsgraph()->TrueConstant()); 39971cb0ef41Sopenharmony_ci MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 39981cb0ef41Sopenharmony_ci } 39991cb0ef41Sopenharmony_ci NewIfFalse(); 40001cb0ef41Sopenharmony_ci environment()->BindAccumulator(jsgraph()->FalseConstant()); 40011cb0ef41Sopenharmony_ci} 40021cb0ef41Sopenharmony_ci 40031cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJumpIfToBooleanTrue() { 40041cb0ef41Sopenharmony_ci Node* accumulator = environment()->LookupAccumulator(); 40051cb0ef41Sopenharmony_ci Node* condition = NewNode(simplified()->ToBoolean(), accumulator); 40061cb0ef41Sopenharmony_ci BuildJumpIf(condition); 40071cb0ef41Sopenharmony_ci} 40081cb0ef41Sopenharmony_ci 40091cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJumpIfToBooleanFalse() { 40101cb0ef41Sopenharmony_ci Node* accumulator = environment()->LookupAccumulator(); 40111cb0ef41Sopenharmony_ci Node* condition = NewNode(simplified()->ToBoolean(), accumulator); 40121cb0ef41Sopenharmony_ci BuildJumpIfNot(condition); 40131cb0ef41Sopenharmony_ci} 40141cb0ef41Sopenharmony_ci 40151cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJumpIfNotHole() { 40161cb0ef41Sopenharmony_ci Node* accumulator = environment()->LookupAccumulator(); 40171cb0ef41Sopenharmony_ci Node* condition = NewNode(simplified()->ReferenceEqual(), accumulator, 40181cb0ef41Sopenharmony_ci jsgraph()->TheHoleConstant()); 40191cb0ef41Sopenharmony_ci BuildJumpIfNot(condition); 40201cb0ef41Sopenharmony_ci} 40211cb0ef41Sopenharmony_ci 40221cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::BuildJumpIfJSReceiver() { 40231cb0ef41Sopenharmony_ci Node* accumulator = environment()->LookupAccumulator(); 40241cb0ef41Sopenharmony_ci Node* condition = NewNode(simplified()->ObjectIsReceiver(), accumulator); 40251cb0ef41Sopenharmony_ci BuildJumpIf(condition); 40261cb0ef41Sopenharmony_ci} 40271cb0ef41Sopenharmony_ci 40281cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 40291cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedUnaryOp(const Operator* op, 40301cb0ef41Sopenharmony_ci Node* operand, 40311cb0ef41Sopenharmony_ci FeedbackSlot slot) { 40321cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 40331cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 40341cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult result = 40351cb0ef41Sopenharmony_ci type_hint_lowering().ReduceUnaryOperation(op, operand, effect, control, 40361cb0ef41Sopenharmony_ci slot); 40371cb0ef41Sopenharmony_ci ApplyEarlyReduction(result); 40381cb0ef41Sopenharmony_ci return result; 40391cb0ef41Sopenharmony_ci} 40401cb0ef41Sopenharmony_ci 40411cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 40421cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedBinaryOp(const Operator* op, Node* left, 40431cb0ef41Sopenharmony_ci Node* right, 40441cb0ef41Sopenharmony_ci FeedbackSlot slot) { 40451cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 40461cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 40471cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult result = 40481cb0ef41Sopenharmony_ci type_hint_lowering().ReduceBinaryOperation(op, left, right, effect, 40491cb0ef41Sopenharmony_ci control, slot); 40501cb0ef41Sopenharmony_ci ApplyEarlyReduction(result); 40511cb0ef41Sopenharmony_ci return result; 40521cb0ef41Sopenharmony_ci} 40531cb0ef41Sopenharmony_ci 40541cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 40551cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedForInNext(Node* receiver, 40561cb0ef41Sopenharmony_ci Node* cache_array, 40571cb0ef41Sopenharmony_ci Node* cache_type, Node* index, 40581cb0ef41Sopenharmony_ci FeedbackSlot slot) { 40591cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 40601cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 40611cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult result = 40621cb0ef41Sopenharmony_ci type_hint_lowering().ReduceForInNextOperation( 40631cb0ef41Sopenharmony_ci receiver, cache_array, cache_type, index, effect, control, slot); 40641cb0ef41Sopenharmony_ci ApplyEarlyReduction(result); 40651cb0ef41Sopenharmony_ci return result; 40661cb0ef41Sopenharmony_ci} 40671cb0ef41Sopenharmony_ci 40681cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 40691cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedForInPrepare(Node* enumerator, 40701cb0ef41Sopenharmony_ci FeedbackSlot slot) { 40711cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 40721cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 40731cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult result = 40741cb0ef41Sopenharmony_ci type_hint_lowering().ReduceForInPrepareOperation(enumerator, effect, 40751cb0ef41Sopenharmony_ci control, slot); 40761cb0ef41Sopenharmony_ci ApplyEarlyReduction(result); 40771cb0ef41Sopenharmony_ci return result; 40781cb0ef41Sopenharmony_ci} 40791cb0ef41Sopenharmony_ci 40801cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 40811cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedToNumber(Node* value, 40821cb0ef41Sopenharmony_ci FeedbackSlot slot) { 40831cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 40841cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 40851cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult result = 40861cb0ef41Sopenharmony_ci type_hint_lowering().ReduceToNumberOperation(value, effect, control, 40871cb0ef41Sopenharmony_ci slot); 40881cb0ef41Sopenharmony_ci ApplyEarlyReduction(result); 40891cb0ef41Sopenharmony_ci return result; 40901cb0ef41Sopenharmony_ci} 40911cb0ef41Sopenharmony_ci 40921cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult BytecodeGraphBuilder::TryBuildSimplifiedCall( 40931cb0ef41Sopenharmony_ci const Operator* op, Node* const* args, int arg_count, FeedbackSlot slot) { 40941cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 40951cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 40961cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult result = 40971cb0ef41Sopenharmony_ci type_hint_lowering().ReduceCallOperation(op, args, arg_count, effect, 40981cb0ef41Sopenharmony_ci control, slot); 40991cb0ef41Sopenharmony_ci ApplyEarlyReduction(result); 41001cb0ef41Sopenharmony_ci return result; 41011cb0ef41Sopenharmony_ci} 41021cb0ef41Sopenharmony_ci 41031cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 41041cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op, 41051cb0ef41Sopenharmony_ci Node* const* args, 41061cb0ef41Sopenharmony_ci int arg_count, 41071cb0ef41Sopenharmony_ci FeedbackSlot slot) { 41081cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 41091cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 41101cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult result = 41111cb0ef41Sopenharmony_ci type_hint_lowering().ReduceConstructOperation(op, args, arg_count, effect, 41121cb0ef41Sopenharmony_ci control, slot); 41131cb0ef41Sopenharmony_ci ApplyEarlyReduction(result); 41141cb0ef41Sopenharmony_ci return result; 41151cb0ef41Sopenharmony_ci} 41161cb0ef41Sopenharmony_ci 41171cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 41181cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedGetIterator(const Operator* op, 41191cb0ef41Sopenharmony_ci Node* receiver, 41201cb0ef41Sopenharmony_ci FeedbackSlot load_slot, 41211cb0ef41Sopenharmony_ci FeedbackSlot call_slot) { 41221cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 41231cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 41241cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult early_reduction = 41251cb0ef41Sopenharmony_ci type_hint_lowering().ReduceGetIteratorOperation( 41261cb0ef41Sopenharmony_ci op, receiver, effect, control, load_slot, call_slot); 41271cb0ef41Sopenharmony_ci ApplyEarlyReduction(early_reduction); 41281cb0ef41Sopenharmony_ci return early_reduction; 41291cb0ef41Sopenharmony_ci} 41301cb0ef41Sopenharmony_ci 41311cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 41321cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op, 41331cb0ef41Sopenharmony_ci FeedbackSlot slot) { 41341cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 41351cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 41361cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult early_reduction = 41371cb0ef41Sopenharmony_ci type_hint_lowering().ReduceLoadNamedOperation(op, effect, control, slot); 41381cb0ef41Sopenharmony_ci ApplyEarlyReduction(early_reduction); 41391cb0ef41Sopenharmony_ci return early_reduction; 41401cb0ef41Sopenharmony_ci} 41411cb0ef41Sopenharmony_ci 41421cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 41431cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedLoadKeyed(const Operator* op, 41441cb0ef41Sopenharmony_ci Node* receiver, Node* key, 41451cb0ef41Sopenharmony_ci FeedbackSlot slot) { 41461cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 41471cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 41481cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult result = 41491cb0ef41Sopenharmony_ci type_hint_lowering().ReduceLoadKeyedOperation(op, receiver, key, effect, 41501cb0ef41Sopenharmony_ci control, slot); 41511cb0ef41Sopenharmony_ci ApplyEarlyReduction(result); 41521cb0ef41Sopenharmony_ci return result; 41531cb0ef41Sopenharmony_ci} 41541cb0ef41Sopenharmony_ci 41551cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 41561cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedStoreNamed(const Operator* op, 41571cb0ef41Sopenharmony_ci Node* receiver, Node* value, 41581cb0ef41Sopenharmony_ci FeedbackSlot slot) { 41591cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 41601cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 41611cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult result = 41621cb0ef41Sopenharmony_ci type_hint_lowering().ReduceStoreNamedOperation(op, receiver, value, 41631cb0ef41Sopenharmony_ci effect, control, slot); 41641cb0ef41Sopenharmony_ci ApplyEarlyReduction(result); 41651cb0ef41Sopenharmony_ci return result; 41661cb0ef41Sopenharmony_ci} 41671cb0ef41Sopenharmony_ci 41681cb0ef41Sopenharmony_ciJSTypeHintLowering::LoweringResult 41691cb0ef41Sopenharmony_ciBytecodeGraphBuilder::TryBuildSimplifiedStoreKeyed(const Operator* op, 41701cb0ef41Sopenharmony_ci Node* receiver, Node* key, 41711cb0ef41Sopenharmony_ci Node* value, 41721cb0ef41Sopenharmony_ci FeedbackSlot slot) { 41731cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 41741cb0ef41Sopenharmony_ci Node* control = environment()->GetControlDependency(); 41751cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult result = 41761cb0ef41Sopenharmony_ci type_hint_lowering().ReduceStoreKeyedOperation(op, receiver, key, value, 41771cb0ef41Sopenharmony_ci effect, control, slot); 41781cb0ef41Sopenharmony_ci ApplyEarlyReduction(result); 41791cb0ef41Sopenharmony_ci return result; 41801cb0ef41Sopenharmony_ci} 41811cb0ef41Sopenharmony_ci 41821cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::ApplyEarlyReduction( 41831cb0ef41Sopenharmony_ci JSTypeHintLowering::LoweringResult reduction) { 41841cb0ef41Sopenharmony_ci if (reduction.IsExit()) { 41851cb0ef41Sopenharmony_ci MergeControlToLeaveFunction(reduction.control()); 41861cb0ef41Sopenharmony_ci } else if (reduction.IsSideEffectFree()) { 41871cb0ef41Sopenharmony_ci environment()->UpdateEffectDependency(reduction.effect()); 41881cb0ef41Sopenharmony_ci environment()->UpdateControlDependency(reduction.control()); 41891cb0ef41Sopenharmony_ci } else { 41901cb0ef41Sopenharmony_ci DCHECK(!reduction.Changed()); 41911cb0ef41Sopenharmony_ci // At the moment, we assume side-effect free reduction. To support 41921cb0ef41Sopenharmony_ci // side-effects, we would have to invalidate the eager checkpoint, 41931cb0ef41Sopenharmony_ci // so that deoptimization does not repeat the side effect. 41941cb0ef41Sopenharmony_ci } 41951cb0ef41Sopenharmony_ci} 41961cb0ef41Sopenharmony_ci 41971cb0ef41Sopenharmony_ciNode** BytecodeGraphBuilder::EnsureInputBufferSize(int size) { 41981cb0ef41Sopenharmony_ci if (size > input_buffer_size_) { 41991cb0ef41Sopenharmony_ci size = size + kInputBufferSizeIncrement + input_buffer_size_; 42001cb0ef41Sopenharmony_ci input_buffer_ = local_zone()->NewArray<Node*>(size); 42011cb0ef41Sopenharmony_ci input_buffer_size_ = size; 42021cb0ef41Sopenharmony_ci } 42031cb0ef41Sopenharmony_ci return input_buffer_; 42041cb0ef41Sopenharmony_ci} 42051cb0ef41Sopenharmony_ci 42061cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::ExitThenEnterExceptionHandlers(int current_offset) { 42071cb0ef41Sopenharmony_ci DisallowGarbageCollection no_gc; 42081cb0ef41Sopenharmony_ci HandlerTable table(bytecode_array().handler_table_address(), 42091cb0ef41Sopenharmony_ci bytecode_array().handler_table_size(), 42101cb0ef41Sopenharmony_ci HandlerTable::kRangeBasedEncoding); 42111cb0ef41Sopenharmony_ci 42121cb0ef41Sopenharmony_ci // Potentially exit exception handlers. 42131cb0ef41Sopenharmony_ci while (!exception_handlers_.empty()) { 42141cb0ef41Sopenharmony_ci int current_end = exception_handlers_.top().end_offset_; 42151cb0ef41Sopenharmony_ci if (current_offset < current_end) break; // Still covered by range. 42161cb0ef41Sopenharmony_ci exception_handlers_.pop(); 42171cb0ef41Sopenharmony_ci } 42181cb0ef41Sopenharmony_ci 42191cb0ef41Sopenharmony_ci // Potentially enter exception handlers. 42201cb0ef41Sopenharmony_ci int num_entries = table.NumberOfRangeEntries(); 42211cb0ef41Sopenharmony_ci while (current_exception_handler_ < num_entries) { 42221cb0ef41Sopenharmony_ci int next_start = table.GetRangeStart(current_exception_handler_); 42231cb0ef41Sopenharmony_ci if (current_offset < next_start) break; // Not yet covered by range. 42241cb0ef41Sopenharmony_ci int next_end = table.GetRangeEnd(current_exception_handler_); 42251cb0ef41Sopenharmony_ci int next_handler = table.GetRangeHandler(current_exception_handler_); 42261cb0ef41Sopenharmony_ci int context_register = table.GetRangeData(current_exception_handler_); 42271cb0ef41Sopenharmony_ci exception_handlers_.push( 42281cb0ef41Sopenharmony_ci {next_start, next_end, next_handler, context_register}); 42291cb0ef41Sopenharmony_ci current_exception_handler_++; 42301cb0ef41Sopenharmony_ci } 42311cb0ef41Sopenharmony_ci} 42321cb0ef41Sopenharmony_ci 42331cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, 42341cb0ef41Sopenharmony_ci Node* const* value_inputs, 42351cb0ef41Sopenharmony_ci bool incomplete) { 42361cb0ef41Sopenharmony_ci DCHECK_EQ(op->ValueInputCount(), value_input_count); 42371cb0ef41Sopenharmony_ci // Parameter nodes must be created through GetParameter. 42381cb0ef41Sopenharmony_ci DCHECK_IMPLIES( 42391cb0ef41Sopenharmony_ci op->opcode() == IrOpcode::kParameter, 42401cb0ef41Sopenharmony_ci (nullptr == cached_parameters_[static_cast<std::size_t>( 42411cb0ef41Sopenharmony_ci ParameterIndexOf(op) - ParameterInfo::kMinIndex)])); 42421cb0ef41Sopenharmony_ci 42431cb0ef41Sopenharmony_ci bool has_context = OperatorProperties::HasContextInput(op); 42441cb0ef41Sopenharmony_ci bool has_frame_state = OperatorProperties::HasFrameStateInput(op); 42451cb0ef41Sopenharmony_ci bool has_control = op->ControlInputCount() == 1; 42461cb0ef41Sopenharmony_ci bool has_effect = op->EffectInputCount() == 1; 42471cb0ef41Sopenharmony_ci 42481cb0ef41Sopenharmony_ci DCHECK_LT(op->ControlInputCount(), 2); 42491cb0ef41Sopenharmony_ci DCHECK_LT(op->EffectInputCount(), 2); 42501cb0ef41Sopenharmony_ci 42511cb0ef41Sopenharmony_ci Node* result = nullptr; 42521cb0ef41Sopenharmony_ci if (!has_context && !has_frame_state && !has_control && !has_effect) { 42531cb0ef41Sopenharmony_ci result = graph()->NewNode(op, value_input_count, value_inputs, incomplete); 42541cb0ef41Sopenharmony_ci } else { 42551cb0ef41Sopenharmony_ci bool inside_handler = !exception_handlers_.empty(); 42561cb0ef41Sopenharmony_ci int input_count_with_deps = value_input_count; 42571cb0ef41Sopenharmony_ci if (has_context) ++input_count_with_deps; 42581cb0ef41Sopenharmony_ci if (has_frame_state) ++input_count_with_deps; 42591cb0ef41Sopenharmony_ci if (has_control) ++input_count_with_deps; 42601cb0ef41Sopenharmony_ci if (has_effect) ++input_count_with_deps; 42611cb0ef41Sopenharmony_ci Node** buffer = EnsureInputBufferSize(input_count_with_deps); 42621cb0ef41Sopenharmony_ci if (value_input_count > 0) { 42631cb0ef41Sopenharmony_ci memcpy(buffer, value_inputs, kSystemPointerSize * value_input_count); 42641cb0ef41Sopenharmony_ci } 42651cb0ef41Sopenharmony_ci Node** current_input = buffer + value_input_count; 42661cb0ef41Sopenharmony_ci if (has_context) { 42671cb0ef41Sopenharmony_ci *current_input++ = OperatorProperties::NeedsExactContext(op) 42681cb0ef41Sopenharmony_ci ? environment()->Context() 42691cb0ef41Sopenharmony_ci : native_context_node(); 42701cb0ef41Sopenharmony_ci } 42711cb0ef41Sopenharmony_ci if (has_frame_state) { 42721cb0ef41Sopenharmony_ci // The frame state will be inserted later. Here we misuse the {Dead} node 42731cb0ef41Sopenharmony_ci // as a sentinel to be later overwritten with the real frame state by the 42741cb0ef41Sopenharmony_ci // calls to {PrepareFrameState} within individual visitor methods. 42751cb0ef41Sopenharmony_ci *current_input++ = jsgraph()->Dead(); 42761cb0ef41Sopenharmony_ci } 42771cb0ef41Sopenharmony_ci if (has_effect) { 42781cb0ef41Sopenharmony_ci *current_input++ = environment()->GetEffectDependency(); 42791cb0ef41Sopenharmony_ci } 42801cb0ef41Sopenharmony_ci if (has_control) { 42811cb0ef41Sopenharmony_ci *current_input++ = environment()->GetControlDependency(); 42821cb0ef41Sopenharmony_ci } 42831cb0ef41Sopenharmony_ci result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); 42841cb0ef41Sopenharmony_ci // Update the current control dependency for control-producing nodes. 42851cb0ef41Sopenharmony_ci if (result->op()->ControlOutputCount() > 0) { 42861cb0ef41Sopenharmony_ci environment()->UpdateControlDependency(result); 42871cb0ef41Sopenharmony_ci } 42881cb0ef41Sopenharmony_ci // Update the current effect dependency for effect-producing nodes. 42891cb0ef41Sopenharmony_ci if (result->op()->EffectOutputCount() > 0) { 42901cb0ef41Sopenharmony_ci environment()->UpdateEffectDependency(result); 42911cb0ef41Sopenharmony_ci } 42921cb0ef41Sopenharmony_ci // Add implicit exception continuation for throwing nodes. 42931cb0ef41Sopenharmony_ci if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { 42941cb0ef41Sopenharmony_ci int handler_offset = exception_handlers_.top().handler_offset_; 42951cb0ef41Sopenharmony_ci int context_index = exception_handlers_.top().context_register_; 42961cb0ef41Sopenharmony_ci interpreter::Register context_register(context_index); 42971cb0ef41Sopenharmony_ci Environment* success_env = environment()->Copy(); 42981cb0ef41Sopenharmony_ci const Operator* if_exception = common()->IfException(); 42991cb0ef41Sopenharmony_ci Node* effect = environment()->GetEffectDependency(); 43001cb0ef41Sopenharmony_ci Node* on_exception = graph()->NewNode(if_exception, effect, result); 43011cb0ef41Sopenharmony_ci Node* context = environment()->LookupRegister(context_register); 43021cb0ef41Sopenharmony_ci environment()->UpdateControlDependency(on_exception); 43031cb0ef41Sopenharmony_ci environment()->UpdateEffectDependency(on_exception); 43041cb0ef41Sopenharmony_ci environment()->BindAccumulator(on_exception); 43051cb0ef41Sopenharmony_ci environment()->SetContext(context); 43061cb0ef41Sopenharmony_ci MergeIntoSuccessorEnvironment(handler_offset); 43071cb0ef41Sopenharmony_ci set_environment(success_env); 43081cb0ef41Sopenharmony_ci } 43091cb0ef41Sopenharmony_ci // Add implicit success continuation for throwing nodes. 43101cb0ef41Sopenharmony_ci if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { 43111cb0ef41Sopenharmony_ci const Operator* if_success = common()->IfSuccess(); 43121cb0ef41Sopenharmony_ci Node* on_success = graph()->NewNode(if_success, result); 43131cb0ef41Sopenharmony_ci environment()->UpdateControlDependency(on_success); 43141cb0ef41Sopenharmony_ci } 43151cb0ef41Sopenharmony_ci // Ensure checkpoints are created after operations with side-effects. 43161cb0ef41Sopenharmony_ci if (has_effect && !result->op()->HasProperty(Operator::kNoWrite)) { 43171cb0ef41Sopenharmony_ci mark_as_needing_eager_checkpoint(true); 43181cb0ef41Sopenharmony_ci } 43191cb0ef41Sopenharmony_ci } 43201cb0ef41Sopenharmony_ci 43211cb0ef41Sopenharmony_ci return result; 43221cb0ef41Sopenharmony_ci} 43231cb0ef41Sopenharmony_ci 43241cb0ef41Sopenharmony_ci 43251cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { 43261cb0ef41Sopenharmony_ci const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); 43271cb0ef41Sopenharmony_ci Node** buffer = EnsureInputBufferSize(count + 1); 43281cb0ef41Sopenharmony_ci MemsetPointer(buffer, input, count); 43291cb0ef41Sopenharmony_ci buffer[count] = control; 43301cb0ef41Sopenharmony_ci return graph()->NewNode(phi_op, count + 1, buffer, true); 43311cb0ef41Sopenharmony_ci} 43321cb0ef41Sopenharmony_ci 43331cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::NewEffectPhi(int count, Node* input, 43341cb0ef41Sopenharmony_ci Node* control) { 43351cb0ef41Sopenharmony_ci const Operator* phi_op = common()->EffectPhi(count); 43361cb0ef41Sopenharmony_ci Node** buffer = EnsureInputBufferSize(count + 1); 43371cb0ef41Sopenharmony_ci MemsetPointer(buffer, input, count); 43381cb0ef41Sopenharmony_ci buffer[count] = control; 43391cb0ef41Sopenharmony_ci return graph()->NewNode(phi_op, count + 1, buffer, true); 43401cb0ef41Sopenharmony_ci} 43411cb0ef41Sopenharmony_ci 43421cb0ef41Sopenharmony_ci 43431cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::MergeControl(Node* control, Node* other) { 43441cb0ef41Sopenharmony_ci int inputs = control->op()->ControlInputCount() + 1; 43451cb0ef41Sopenharmony_ci if (control->opcode() == IrOpcode::kLoop) { 43461cb0ef41Sopenharmony_ci // Control node for loop exists, add input. 43471cb0ef41Sopenharmony_ci const Operator* op = common()->Loop(inputs); 43481cb0ef41Sopenharmony_ci control->AppendInput(graph_zone(), other); 43491cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(control, op); 43501cb0ef41Sopenharmony_ci } else if (control->opcode() == IrOpcode::kMerge) { 43511cb0ef41Sopenharmony_ci // Control node for merge exists, add input. 43521cb0ef41Sopenharmony_ci const Operator* op = common()->Merge(inputs); 43531cb0ef41Sopenharmony_ci control->AppendInput(graph_zone(), other); 43541cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(control, op); 43551cb0ef41Sopenharmony_ci } else { 43561cb0ef41Sopenharmony_ci // Control node is a singleton, introduce a merge. 43571cb0ef41Sopenharmony_ci const Operator* op = common()->Merge(inputs); 43581cb0ef41Sopenharmony_ci Node* merge_inputs[] = {control, other}; 43591cb0ef41Sopenharmony_ci control = graph()->NewNode(op, arraysize(merge_inputs), merge_inputs, true); 43601cb0ef41Sopenharmony_ci } 43611cb0ef41Sopenharmony_ci return control; 43621cb0ef41Sopenharmony_ci} 43631cb0ef41Sopenharmony_ci 43641cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::MergeEffect(Node* value, Node* other, 43651cb0ef41Sopenharmony_ci Node* control) { 43661cb0ef41Sopenharmony_ci int inputs = control->op()->ControlInputCount(); 43671cb0ef41Sopenharmony_ci if (value->opcode() == IrOpcode::kEffectPhi && 43681cb0ef41Sopenharmony_ci NodeProperties::GetControlInput(value) == control) { 43691cb0ef41Sopenharmony_ci // Phi already exists, add input. 43701cb0ef41Sopenharmony_ci value->InsertInput(graph_zone(), inputs - 1, other); 43711cb0ef41Sopenharmony_ci NodeProperties::ChangeOp(value, common()->EffectPhi(inputs)); 43721cb0ef41Sopenharmony_ci } else if (value != other) { 43731cb0ef41Sopenharmony_ci // Phi does not exist yet, introduce one. 43741cb0ef41Sopenharmony_ci value = NewEffectPhi(inputs, value, control); 43751cb0ef41Sopenharmony_ci value->ReplaceInput(inputs - 1, other); 43761cb0ef41Sopenharmony_ci } 43771cb0ef41Sopenharmony_ci return value; 43781cb0ef41Sopenharmony_ci} 43791cb0ef41Sopenharmony_ci 43801cb0ef41Sopenharmony_ciNode* BytecodeGraphBuilder::MergeValue(Node* value, Node* other, 43811cb0ef41Sopenharmony_ci Node* control) { 43821cb0ef41Sopenharmony_ci int inputs = control->op()->ControlInputCount(); 43831cb0ef41Sopenharmony_ci if (value->opcode() == IrOpcode::kPhi && 43841cb0ef41Sopenharmony_ci NodeProperties::GetControlInput(value) == control) { 43851cb0ef41Sopenharmony_ci // Phi already exists, add input. 43861cb0ef41Sopenharmony_ci value->InsertInput(graph_zone(), inputs - 1, other); 43871cb0ef41Sopenharmony_ci NodeProperties::ChangeOp( 43881cb0ef41Sopenharmony_ci value, common()->Phi(MachineRepresentation::kTagged, inputs)); 43891cb0ef41Sopenharmony_ci } else if (value != other) { 43901cb0ef41Sopenharmony_ci // Phi does not exist yet, introduce one. 43911cb0ef41Sopenharmony_ci value = NewPhi(inputs, value, control); 43921cb0ef41Sopenharmony_ci value->ReplaceInput(inputs - 1, other); 43931cb0ef41Sopenharmony_ci } 43941cb0ef41Sopenharmony_ci return value; 43951cb0ef41Sopenharmony_ci} 43961cb0ef41Sopenharmony_ci 43971cb0ef41Sopenharmony_civoid BytecodeGraphBuilder::UpdateSourcePosition(int offset) { 43981cb0ef41Sopenharmony_ci if (source_position_iterator().done()) return; 43991cb0ef41Sopenharmony_ci if (source_position_iterator().code_offset() == offset) { 44001cb0ef41Sopenharmony_ci source_positions_->SetCurrentPosition(SourcePosition( 44011cb0ef41Sopenharmony_ci source_position_iterator().source_position().ScriptOffset(), 44021cb0ef41Sopenharmony_ci start_position_.InliningId())); 44031cb0ef41Sopenharmony_ci source_position_iterator().Advance(); 44041cb0ef41Sopenharmony_ci } else { 44051cb0ef41Sopenharmony_ci DCHECK_GT(source_position_iterator().code_offset(), offset); 44061cb0ef41Sopenharmony_ci } 44071cb0ef41Sopenharmony_ci} 44081cb0ef41Sopenharmony_ci 44091cb0ef41Sopenharmony_civoid BuildGraphFromBytecode(JSHeapBroker* broker, Zone* local_zone, 44101cb0ef41Sopenharmony_ci SharedFunctionInfoRef const& shared_info, 44111cb0ef41Sopenharmony_ci FeedbackCellRef const& feedback_cell, 44121cb0ef41Sopenharmony_ci BytecodeOffset osr_offset, JSGraph* jsgraph, 44131cb0ef41Sopenharmony_ci CallFrequency const& invocation_frequency, 44141cb0ef41Sopenharmony_ci SourcePositionTable* source_positions, 44151cb0ef41Sopenharmony_ci int inlining_id, CodeKind code_kind, 44161cb0ef41Sopenharmony_ci BytecodeGraphBuilderFlags flags, 44171cb0ef41Sopenharmony_ci TickCounter* tick_counter, 44181cb0ef41Sopenharmony_ci ObserveNodeInfo const& observe_node_info) { 44191cb0ef41Sopenharmony_ci BytecodeGraphBuilder builder( 44201cb0ef41Sopenharmony_ci broker, local_zone, broker->target_native_context(), shared_info, 44211cb0ef41Sopenharmony_ci feedback_cell, osr_offset, jsgraph, invocation_frequency, 44221cb0ef41Sopenharmony_ci source_positions, inlining_id, code_kind, flags, tick_counter, 44231cb0ef41Sopenharmony_ci observe_node_info); 44241cb0ef41Sopenharmony_ci builder.CreateGraph(); 44251cb0ef41Sopenharmony_ci} 44261cb0ef41Sopenharmony_ci 44271cb0ef41Sopenharmony_ci} // namespace compiler 44281cb0ef41Sopenharmony_ci} // namespace internal 44291cb0ef41Sopenharmony_ci} // namespace v8 4430