11cb0ef41Sopenharmony_ci// Copyright 2014 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#ifndef V8_COMPILER_BACKEND_CODE_GENERATOR_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_BACKEND_CODE_GENERATOR_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <memory> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include "src/base/optional.h" 111cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/optimized-compilation-info.h" 131cb0ef41Sopenharmony_ci#include "src/codegen/safepoint-table.h" 141cb0ef41Sopenharmony_ci#include "src/codegen/source-position-table.h" 151cb0ef41Sopenharmony_ci#include "src/compiler/backend/gap-resolver.h" 161cb0ef41Sopenharmony_ci#include "src/compiler/backend/instruction.h" 171cb0ef41Sopenharmony_ci#include "src/compiler/backend/unwinding-info-writer.h" 181cb0ef41Sopenharmony_ci#include "src/compiler/osr.h" 191cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimizer.h" 201cb0ef41Sopenharmony_ci#include "src/objects/code-kind.h" 211cb0ef41Sopenharmony_ci#include "src/trap-handler/trap-handler.h" 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cinamespace v8 { 241cb0ef41Sopenharmony_cinamespace internal { 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cinamespace compiler { 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci// Forward declarations. 291cb0ef41Sopenharmony_ciclass DeoptimizationExit; 301cb0ef41Sopenharmony_ciclass FrameAccessState; 311cb0ef41Sopenharmony_ciclass Linkage; 321cb0ef41Sopenharmony_ciclass OutOfLineCode; 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_cistruct BranchInfo { 351cb0ef41Sopenharmony_ci FlagsCondition condition; 361cb0ef41Sopenharmony_ci Label* true_label; 371cb0ef41Sopenharmony_ci Label* false_label; 381cb0ef41Sopenharmony_ci bool fallthru; 391cb0ef41Sopenharmony_ci}; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ciclass InstructionOperandIterator { 421cb0ef41Sopenharmony_ci public: 431cb0ef41Sopenharmony_ci InstructionOperandIterator(Instruction* instr, size_t pos) 441cb0ef41Sopenharmony_ci : instr_(instr), pos_(pos) {} 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci Instruction* instruction() const { return instr_; } 471cb0ef41Sopenharmony_ci InstructionOperand* Advance() { return instr_->InputAt(pos_++); } 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci private: 501cb0ef41Sopenharmony_ci Instruction* instr_; 511cb0ef41Sopenharmony_ci size_t pos_; 521cb0ef41Sopenharmony_ci}; 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_cienum class DeoptimizationLiteralKind { kObject, kNumber, kString, kInvalid }; 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci// Either a non-null Handle<Object>, a double or a StringConstantBase. 571cb0ef41Sopenharmony_ciclass DeoptimizationLiteral { 581cb0ef41Sopenharmony_ci public: 591cb0ef41Sopenharmony_ci DeoptimizationLiteral() 601cb0ef41Sopenharmony_ci : kind_(DeoptimizationLiteralKind::kInvalid), 611cb0ef41Sopenharmony_ci object_(), 621cb0ef41Sopenharmony_ci number_(0), 631cb0ef41Sopenharmony_ci string_(nullptr) {} 641cb0ef41Sopenharmony_ci explicit DeoptimizationLiteral(Handle<Object> object) 651cb0ef41Sopenharmony_ci : kind_(DeoptimizationLiteralKind::kObject), object_(object) { 661cb0ef41Sopenharmony_ci CHECK(!object_.is_null()); 671cb0ef41Sopenharmony_ci } 681cb0ef41Sopenharmony_ci explicit DeoptimizationLiteral(double number) 691cb0ef41Sopenharmony_ci : kind_(DeoptimizationLiteralKind::kNumber), number_(number) {} 701cb0ef41Sopenharmony_ci explicit DeoptimizationLiteral(const StringConstantBase* string) 711cb0ef41Sopenharmony_ci : kind_(DeoptimizationLiteralKind::kString), string_(string) {} 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci Handle<Object> object() const { return object_; } 741cb0ef41Sopenharmony_ci const StringConstantBase* string() const { return string_; } 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci bool operator==(const DeoptimizationLiteral& other) const { 771cb0ef41Sopenharmony_ci return kind_ == other.kind_ && object_.equals(other.object_) && 781cb0ef41Sopenharmony_ci bit_cast<uint64_t>(number_) == bit_cast<uint64_t>(other.number_) && 791cb0ef41Sopenharmony_ci bit_cast<intptr_t>(string_) == bit_cast<intptr_t>(other.string_); 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci Handle<Object> Reify(Isolate* isolate) const; 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_ci void Validate() const { 851cb0ef41Sopenharmony_ci CHECK_NE(kind_, DeoptimizationLiteralKind::kInvalid); 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci DeoptimizationLiteralKind kind() const { 891cb0ef41Sopenharmony_ci Validate(); 901cb0ef41Sopenharmony_ci return kind_; 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci private: 941cb0ef41Sopenharmony_ci DeoptimizationLiteralKind kind_; 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci Handle<Object> object_; 971cb0ef41Sopenharmony_ci double number_ = 0; 981cb0ef41Sopenharmony_ci const StringConstantBase* string_ = nullptr; 991cb0ef41Sopenharmony_ci}; 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci// These structs hold pc offsets for generated instructions and is only used 1021cb0ef41Sopenharmony_ci// when tracing for turbolizer is enabled. 1031cb0ef41Sopenharmony_cistruct TurbolizerCodeOffsetsInfo { 1041cb0ef41Sopenharmony_ci int code_start_register_check = -1; 1051cb0ef41Sopenharmony_ci int deopt_check = -1; 1061cb0ef41Sopenharmony_ci int blocks_start = -1; 1071cb0ef41Sopenharmony_ci int out_of_line_code = -1; 1081cb0ef41Sopenharmony_ci int deoptimization_exits = -1; 1091cb0ef41Sopenharmony_ci int pools = -1; 1101cb0ef41Sopenharmony_ci int jump_tables = -1; 1111cb0ef41Sopenharmony_ci}; 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_cistruct TurbolizerInstructionStartInfo { 1141cb0ef41Sopenharmony_ci int gap_pc_offset = -1; 1151cb0ef41Sopenharmony_ci int arch_instr_pc_offset = -1; 1161cb0ef41Sopenharmony_ci int condition_pc_offset = -1; 1171cb0ef41Sopenharmony_ci}; 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci// Generates native code for a sequence of instructions. 1201cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE CodeGenerator final : public GapResolver::Assembler { 1211cb0ef41Sopenharmony_ci public: 1221cb0ef41Sopenharmony_ci explicit CodeGenerator(Zone* codegen_zone, Frame* frame, Linkage* linkage, 1231cb0ef41Sopenharmony_ci InstructionSequence* instructions, 1241cb0ef41Sopenharmony_ci OptimizedCompilationInfo* info, Isolate* isolate, 1251cb0ef41Sopenharmony_ci base::Optional<OsrHelper> osr_helper, 1261cb0ef41Sopenharmony_ci int start_source_position, 1271cb0ef41Sopenharmony_ci JumpOptimizationInfo* jump_opt, 1281cb0ef41Sopenharmony_ci const AssemblerOptions& options, Builtin builtin, 1291cb0ef41Sopenharmony_ci size_t max_unoptimized_frame_height, 1301cb0ef41Sopenharmony_ci size_t max_pushed_argument_count, 1311cb0ef41Sopenharmony_ci const char* debug_name = nullptr); 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci // Generate native code. After calling AssembleCode, call FinalizeCode to 1341cb0ef41Sopenharmony_ci // produce the actual code object. If an error occurs during either phase, 1351cb0ef41Sopenharmony_ci // FinalizeCode returns an empty MaybeHandle. 1361cb0ef41Sopenharmony_ci void AssembleCode(); // Does not need to run on main thread. 1371cb0ef41Sopenharmony_ci MaybeHandle<Code> FinalizeCode(); 1381cb0ef41Sopenharmony_ci 1391cb0ef41Sopenharmony_ci base::OwnedVector<byte> GetSourcePositionTable(); 1401cb0ef41Sopenharmony_ci base::OwnedVector<byte> GetProtectedInstructionsData(); 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci InstructionSequence* instructions() const { return instructions_; } 1431cb0ef41Sopenharmony_ci FrameAccessState* frame_access_state() const { return frame_access_state_; } 1441cb0ef41Sopenharmony_ci const Frame* frame() const { return frame_access_state_->frame(); } 1451cb0ef41Sopenharmony_ci Isolate* isolate() const { return isolate_; } 1461cb0ef41Sopenharmony_ci Linkage* linkage() const { return linkage_; } 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci Label* GetLabel(RpoNumber rpo) { return &labels_[rpo.ToSize()]; } 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci void AddProtectedInstructionLanding(uint32_t instr_offset, 1511cb0ef41Sopenharmony_ci uint32_t landing_offset); 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci bool wasm_runtime_exception_support() const; 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci SourcePosition start_source_position() const { 1561cb0ef41Sopenharmony_ci return start_source_position_; 1571cb0ef41Sopenharmony_ci } 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci void AssembleSourcePosition(Instruction* instr); 1601cb0ef41Sopenharmony_ci void AssembleSourcePosition(SourcePosition source_position); 1611cb0ef41Sopenharmony_ci 1621cb0ef41Sopenharmony_ci // Record a safepoint with the given pointer map. 1631cb0ef41Sopenharmony_ci void RecordSafepoint(ReferenceMap* references); 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci Zone* zone() const { return zone_; } 1661cb0ef41Sopenharmony_ci TurboAssembler* tasm() { return &tasm_; } 1671cb0ef41Sopenharmony_ci SafepointTableBuilder* safepoint_table_builder() { return &safepoints_; } 1681cb0ef41Sopenharmony_ci size_t handler_table_offset() const { return handler_table_offset_; } 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci const ZoneVector<int>& block_starts() const { return block_starts_; } 1711cb0ef41Sopenharmony_ci const ZoneVector<TurbolizerInstructionStartInfo>& instr_starts() const { 1721cb0ef41Sopenharmony_ci return instr_starts_; 1731cb0ef41Sopenharmony_ci } 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci const TurbolizerCodeOffsetsInfo& offsets_info() const { 1761cb0ef41Sopenharmony_ci return offsets_info_; 1771cb0ef41Sopenharmony_ci } 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci static constexpr int kBinarySearchSwitchMinimalCases = 4; 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci // Returns true if an offset should be applied to the given stack check. There 1821cb0ef41Sopenharmony_ci // are two reasons that this could happen: 1831cb0ef41Sopenharmony_ci // 1. The optimized frame is smaller than the corresponding deoptimized frames 1841cb0ef41Sopenharmony_ci // and an offset must be applied in order to be able to deopt safely. 1851cb0ef41Sopenharmony_ci // 2. The current function pushes a large number of arguments to the stack. 1861cb0ef41Sopenharmony_ci // These are not accounted for by the initial frame setup. 1871cb0ef41Sopenharmony_ci bool ShouldApplyOffsetToStackCheck(Instruction* instr, uint32_t* offset); 1881cb0ef41Sopenharmony_ci uint32_t GetStackCheckOffset(); 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci CodeKind code_kind() const { return info_->code_kind(); } 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci private: 1931cb0ef41Sopenharmony_ci GapResolver* resolver() { return &resolver_; } 1941cb0ef41Sopenharmony_ci SafepointTableBuilder* safepoints() { return &safepoints_; } 1951cb0ef41Sopenharmony_ci OptimizedCompilationInfo* info() const { return info_; } 1961cb0ef41Sopenharmony_ci OsrHelper* osr_helper() { return &(*osr_helper_); } 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci // Create the FrameAccessState object. The Frame is immutable from here on. 1991cb0ef41Sopenharmony_ci void CreateFrameAccessState(Frame* frame); 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci // Architecture - specific frame finalization. 2021cb0ef41Sopenharmony_ci void FinishFrame(Frame* frame); 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci // Checks if {block} will appear directly after {current_block_} when 2051cb0ef41Sopenharmony_ci // assembling code, in which case, a fall-through can be used. 2061cb0ef41Sopenharmony_ci bool IsNextInAssemblyOrder(RpoNumber block) const; 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci // Check if a heap object can be materialized by loading from a heap root, 2091cb0ef41Sopenharmony_ci // which is cheaper on some platforms than materializing the actual heap 2101cb0ef41Sopenharmony_ci // object constant. 2111cb0ef41Sopenharmony_ci bool IsMaterializableFromRoot(Handle<HeapObject> object, 2121cb0ef41Sopenharmony_ci RootIndex* index_return); 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci enum CodeGenResult { kSuccess, kTooManyDeoptimizationBailouts }; 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ci // Assemble instructions for the specified block. 2171cb0ef41Sopenharmony_ci CodeGenResult AssembleBlock(const InstructionBlock* block); 2181cb0ef41Sopenharmony_ci 2191cb0ef41Sopenharmony_ci // Assemble code for the specified instruction. 2201cb0ef41Sopenharmony_ci CodeGenResult AssembleInstruction(int instruction_index, 2211cb0ef41Sopenharmony_ci const InstructionBlock* block); 2221cb0ef41Sopenharmony_ci void AssembleGaps(Instruction* instr); 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci // Compute branch info from given instruction. Returns a valid rpo number 2251cb0ef41Sopenharmony_ci // if the branch is redundant, the returned rpo number point to the target 2261cb0ef41Sopenharmony_ci // basic block. 2271cb0ef41Sopenharmony_ci RpoNumber ComputeBranchInfo(BranchInfo* branch, Instruction* instr); 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci // Returns true if a instruction is a tail call that needs to adjust the stack 2301cb0ef41Sopenharmony_ci // pointer before execution. The stack slot index to the empty slot above the 2311cb0ef41Sopenharmony_ci // adjusted stack pointer is returned in |slot|. 2321cb0ef41Sopenharmony_ci bool GetSlotAboveSPBeforeTailCall(Instruction* instr, int* slot); 2331cb0ef41Sopenharmony_ci 2341cb0ef41Sopenharmony_ci // Determines how to call helper stubs depending on the code kind. 2351cb0ef41Sopenharmony_ci StubCallMode DetermineStubCallMode() const; 2361cb0ef41Sopenharmony_ci 2371cb0ef41Sopenharmony_ci CodeGenResult AssembleDeoptimizerCall(DeoptimizationExit* exit); 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci // =========================================================================== 2401cb0ef41Sopenharmony_ci // ============= Architecture-specific code generation methods. ============== 2411cb0ef41Sopenharmony_ci // =========================================================================== 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci CodeGenResult AssembleArchInstruction(Instruction* instr); 2441cb0ef41Sopenharmony_ci void AssembleArchJump(RpoNumber target); 2451cb0ef41Sopenharmony_ci void AssembleArchJumpRegardlessOfAssemblyOrder(RpoNumber target); 2461cb0ef41Sopenharmony_ci void AssembleArchBranch(Instruction* instr, BranchInfo* branch); 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci // Generates special branch for deoptimization condition. 2491cb0ef41Sopenharmony_ci void AssembleArchDeoptBranch(Instruction* instr, BranchInfo* branch); 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci void AssembleArchBoolean(Instruction* instr, FlagsCondition condition); 2521cb0ef41Sopenharmony_ci void AssembleArchSelect(Instruction* instr, FlagsCondition condition); 2531cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 2541cb0ef41Sopenharmony_ci void AssembleArchTrap(Instruction* instr, FlagsCondition condition); 2551cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 2561cb0ef41Sopenharmony_ci void AssembleArchBinarySearchSwitchRange(Register input, RpoNumber def_block, 2571cb0ef41Sopenharmony_ci std::pair<int32_t, Label*>* begin, 2581cb0ef41Sopenharmony_ci std::pair<int32_t, Label*>* end); 2591cb0ef41Sopenharmony_ci void AssembleArchBinarySearchSwitch(Instruction* instr); 2601cb0ef41Sopenharmony_ci void AssembleArchTableSwitch(Instruction* instr); 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci // Generates code that checks whether the {kJavaScriptCallCodeStartRegister} 2631cb0ef41Sopenharmony_ci // contains the expected pointer to the start of the instruction stream. 2641cb0ef41Sopenharmony_ci void AssembleCodeStartRegisterCheck(); 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci // When entering a code that is marked for deoptimization, rather continuing 2671cb0ef41Sopenharmony_ci // with its execution, we jump to a lazy compiled code. We need to do this 2681cb0ef41Sopenharmony_ci // because this code has already been deoptimized and needs to be unlinked 2691cb0ef41Sopenharmony_ci // from the JS functions referring it. 2701cb0ef41Sopenharmony_ci void BailoutIfDeoptimized(); 2711cb0ef41Sopenharmony_ci 2721cb0ef41Sopenharmony_ci // Generates an architecture-specific, descriptor-specific prologue 2731cb0ef41Sopenharmony_ci // to set up a stack frame. 2741cb0ef41Sopenharmony_ci void AssembleConstructFrame(); 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci // Generates an architecture-specific, descriptor-specific return sequence 2771cb0ef41Sopenharmony_ci // to tear down a stack frame. 2781cb0ef41Sopenharmony_ci void AssembleReturn(InstructionOperand* pop); 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci void AssembleDeconstructFrame(); 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci // Generates code to manipulate the stack in preparation for a tail call. 2831cb0ef41Sopenharmony_ci void AssemblePrepareTailCall(); 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci enum PushTypeFlag { 2861cb0ef41Sopenharmony_ci kImmediatePush = 0x1, 2871cb0ef41Sopenharmony_ci kRegisterPush = 0x2, 2881cb0ef41Sopenharmony_ci kStackSlotPush = 0x4, 2891cb0ef41Sopenharmony_ci kScalarPush = kRegisterPush | kStackSlotPush 2901cb0ef41Sopenharmony_ci }; 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci using PushTypeFlags = base::Flags<PushTypeFlag>; 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci static bool IsValidPush(InstructionOperand source, PushTypeFlags push_type); 2951cb0ef41Sopenharmony_ci 2961cb0ef41Sopenharmony_ci // Generate a list of moves from an instruction that are candidates to be 2971cb0ef41Sopenharmony_ci // turned into push instructions on platforms that support them. In general, 2981cb0ef41Sopenharmony_ci // the list of push candidates are moves to a set of contiguous destination 2991cb0ef41Sopenharmony_ci // InstructionOperand locations on the stack that don't clobber values that 3001cb0ef41Sopenharmony_ci // are needed to resolve the gap or use values generated by the gap, 3011cb0ef41Sopenharmony_ci // i.e. moves that can be hoisted together before the actual gap and assembled 3021cb0ef41Sopenharmony_ci // together. 3031cb0ef41Sopenharmony_ci static void GetPushCompatibleMoves(Instruction* instr, 3041cb0ef41Sopenharmony_ci PushTypeFlags push_type, 3051cb0ef41Sopenharmony_ci ZoneVector<MoveOperands*>* pushes); 3061cb0ef41Sopenharmony_ci 3071cb0ef41Sopenharmony_ci class MoveType { 3081cb0ef41Sopenharmony_ci public: 3091cb0ef41Sopenharmony_ci enum Type { 3101cb0ef41Sopenharmony_ci kRegisterToRegister, 3111cb0ef41Sopenharmony_ci kRegisterToStack, 3121cb0ef41Sopenharmony_ci kStackToRegister, 3131cb0ef41Sopenharmony_ci kStackToStack, 3141cb0ef41Sopenharmony_ci kConstantToRegister, 3151cb0ef41Sopenharmony_ci kConstantToStack 3161cb0ef41Sopenharmony_ci }; 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci // Detect what type of move or swap needs to be performed. Note that these 3191cb0ef41Sopenharmony_ci // functions do not take into account the representation (Tagged, FP, 3201cb0ef41Sopenharmony_ci // ...etc). 3211cb0ef41Sopenharmony_ci 3221cb0ef41Sopenharmony_ci static Type InferMove(InstructionOperand* source, 3231cb0ef41Sopenharmony_ci InstructionOperand* destination); 3241cb0ef41Sopenharmony_ci static Type InferSwap(InstructionOperand* source, 3251cb0ef41Sopenharmony_ci InstructionOperand* destination); 3261cb0ef41Sopenharmony_ci }; 3271cb0ef41Sopenharmony_ci // Called before a tail call |instr|'s gap moves are assembled and allows 3281cb0ef41Sopenharmony_ci // gap-specific pre-processing, e.g. adjustment of the sp for tail calls that 3291cb0ef41Sopenharmony_ci // need it before gap moves or conversion of certain gap moves into pushes. 3301cb0ef41Sopenharmony_ci void AssembleTailCallBeforeGap(Instruction* instr, 3311cb0ef41Sopenharmony_ci int first_unused_stack_slot); 3321cb0ef41Sopenharmony_ci // Called after a tail call |instr|'s gap moves are assembled and allows 3331cb0ef41Sopenharmony_ci // gap-specific post-processing, e.g. adjustment of the sp for tail calls that 3341cb0ef41Sopenharmony_ci // need it after gap moves. 3351cb0ef41Sopenharmony_ci void AssembleTailCallAfterGap(Instruction* instr, 3361cb0ef41Sopenharmony_ci int first_unused_stack_slot); 3371cb0ef41Sopenharmony_ci 3381cb0ef41Sopenharmony_ci void FinishCode(); 3391cb0ef41Sopenharmony_ci void MaybeEmitOutOfLineConstantPool(); 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci void IncrementStackAccessCounter(InstructionOperand* source, 3421cb0ef41Sopenharmony_ci InstructionOperand* destination); 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci // =========================================================================== 3451cb0ef41Sopenharmony_ci // ============== Architecture-specific gap resolver methods. ================ 3461cb0ef41Sopenharmony_ci // =========================================================================== 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci // Interface used by the gap resolver to emit moves and swaps. 3491cb0ef41Sopenharmony_ci void AssembleMove(InstructionOperand* source, 3501cb0ef41Sopenharmony_ci InstructionOperand* destination) final; 3511cb0ef41Sopenharmony_ci void AssembleSwap(InstructionOperand* source, 3521cb0ef41Sopenharmony_ci InstructionOperand* destination) final; 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci // =========================================================================== 3551cb0ef41Sopenharmony_ci // =================== Jump table construction methods. ====================== 3561cb0ef41Sopenharmony_ci // =========================================================================== 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ci class JumpTable; 3591cb0ef41Sopenharmony_ci // Adds a jump table that is emitted after the actual code. Returns label 3601cb0ef41Sopenharmony_ci // pointing to the beginning of the table. {targets} is assumed to be static 3611cb0ef41Sopenharmony_ci // or zone allocated. 3621cb0ef41Sopenharmony_ci Label* AddJumpTable(Label** targets, size_t target_count); 3631cb0ef41Sopenharmony_ci // Emits a jump table. 3641cb0ef41Sopenharmony_ci void AssembleJumpTable(Label** targets, size_t target_count); 3651cb0ef41Sopenharmony_ci 3661cb0ef41Sopenharmony_ci // =========================================================================== 3671cb0ef41Sopenharmony_ci // ================== Deoptimization table construction. ===================== 3681cb0ef41Sopenharmony_ci // =========================================================================== 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_ci void RecordCallPosition(Instruction* instr); 3711cb0ef41Sopenharmony_ci Handle<DeoptimizationData> GenerateDeoptimizationData(); 3721cb0ef41Sopenharmony_ci int DefineDeoptimizationLiteral(DeoptimizationLiteral literal); 3731cb0ef41Sopenharmony_ci DeoptimizationEntry const& GetDeoptimizationEntry(Instruction* instr, 3741cb0ef41Sopenharmony_ci size_t frame_state_offset); 3751cb0ef41Sopenharmony_ci DeoptimizationExit* BuildTranslation(Instruction* instr, int pc_offset, 3761cb0ef41Sopenharmony_ci size_t frame_state_offset, 3771cb0ef41Sopenharmony_ci size_t immediate_args_count, 3781cb0ef41Sopenharmony_ci OutputFrameStateCombine state_combine); 3791cb0ef41Sopenharmony_ci void BuildTranslationForFrameStateDescriptor( 3801cb0ef41Sopenharmony_ci FrameStateDescriptor* descriptor, InstructionOperandIterator* iter, 3811cb0ef41Sopenharmony_ci OutputFrameStateCombine state_combine); 3821cb0ef41Sopenharmony_ci void TranslateStateValueDescriptor(StateValueDescriptor* desc, 3831cb0ef41Sopenharmony_ci StateValueList* nested, 3841cb0ef41Sopenharmony_ci InstructionOperandIterator* iter); 3851cb0ef41Sopenharmony_ci void TranslateFrameStateDescriptorOperands(FrameStateDescriptor* desc, 3861cb0ef41Sopenharmony_ci InstructionOperandIterator* iter); 3871cb0ef41Sopenharmony_ci void AddTranslationForOperand(Instruction* instr, InstructionOperand* op, 3881cb0ef41Sopenharmony_ci MachineType type); 3891cb0ef41Sopenharmony_ci void MarkLazyDeoptSite(); 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci void PrepareForDeoptimizationExits(ZoneDeque<DeoptimizationExit*>* exits); 3921cb0ef41Sopenharmony_ci DeoptimizationExit* AddDeoptimizationExit(Instruction* instr, 3931cb0ef41Sopenharmony_ci size_t frame_state_offset, 3941cb0ef41Sopenharmony_ci size_t immediate_args_count); 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci // =========================================================================== 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci struct HandlerInfo { 3991cb0ef41Sopenharmony_ci Label* handler; 4001cb0ef41Sopenharmony_ci int pc_offset; 4011cb0ef41Sopenharmony_ci }; 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci friend class OutOfLineCode; 4041cb0ef41Sopenharmony_ci friend class CodeGeneratorTester; 4051cb0ef41Sopenharmony_ci 4061cb0ef41Sopenharmony_ci Zone* zone_; 4071cb0ef41Sopenharmony_ci Isolate* isolate_; 4081cb0ef41Sopenharmony_ci FrameAccessState* frame_access_state_; 4091cb0ef41Sopenharmony_ci Linkage* const linkage_; 4101cb0ef41Sopenharmony_ci InstructionSequence* const instructions_; 4111cb0ef41Sopenharmony_ci UnwindingInfoWriter unwinding_info_writer_; 4121cb0ef41Sopenharmony_ci OptimizedCompilationInfo* const info_; 4131cb0ef41Sopenharmony_ci Label* const labels_; 4141cb0ef41Sopenharmony_ci Label return_label_; 4151cb0ef41Sopenharmony_ci RpoNumber current_block_; 4161cb0ef41Sopenharmony_ci SourcePosition start_source_position_; 4171cb0ef41Sopenharmony_ci SourcePosition current_source_position_; 4181cb0ef41Sopenharmony_ci TurboAssembler tasm_; 4191cb0ef41Sopenharmony_ci GapResolver resolver_; 4201cb0ef41Sopenharmony_ci SafepointTableBuilder safepoints_; 4211cb0ef41Sopenharmony_ci ZoneVector<HandlerInfo> handlers_; 4221cb0ef41Sopenharmony_ci int next_deoptimization_id_ = 0; 4231cb0ef41Sopenharmony_ci int deopt_exit_start_offset_ = 0; 4241cb0ef41Sopenharmony_ci int eager_deopt_count_ = 0; 4251cb0ef41Sopenharmony_ci int lazy_deopt_count_ = 0; 4261cb0ef41Sopenharmony_ci ZoneDeque<DeoptimizationExit*> deoptimization_exits_; 4271cb0ef41Sopenharmony_ci ZoneDeque<DeoptimizationLiteral> deoptimization_literals_; 4281cb0ef41Sopenharmony_ci size_t inlined_function_count_ = 0; 4291cb0ef41Sopenharmony_ci TranslationArrayBuilder translations_; 4301cb0ef41Sopenharmony_ci int handler_table_offset_ = 0; 4311cb0ef41Sopenharmony_ci int last_lazy_deopt_pc_ = 0; 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci // Deoptimization exits must be as small as possible, since their count grows 4341cb0ef41Sopenharmony_ci // with function size. {jump_deoptimization_entry_labels_} is an optimization 4351cb0ef41Sopenharmony_ci // to that effect, which extracts the (potentially large) instruction 4361cb0ef41Sopenharmony_ci // sequence for the final jump to the deoptimization entry into a single spot 4371cb0ef41Sopenharmony_ci // per Code object. All deopt exits can then near-call to this label. Note: 4381cb0ef41Sopenharmony_ci // not used on all architectures. 4391cb0ef41Sopenharmony_ci Label jump_deoptimization_entry_labels_[kDeoptimizeKindCount]; 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci // The maximal combined height of all frames produced upon deoptimization, and 4421cb0ef41Sopenharmony_ci // the maximal number of pushed arguments for function calls. Applied as an 4431cb0ef41Sopenharmony_ci // offset to the first stack check of an optimized function. 4441cb0ef41Sopenharmony_ci const size_t max_unoptimized_frame_height_; 4451cb0ef41Sopenharmony_ci const size_t max_pushed_argument_count_; 4461cb0ef41Sopenharmony_ci 4471cb0ef41Sopenharmony_ci // kArchCallCFunction could be reached either: 4481cb0ef41Sopenharmony_ci // kArchCallCFunction; 4491cb0ef41Sopenharmony_ci // or: 4501cb0ef41Sopenharmony_ci // kArchSaveCallerRegisters; 4511cb0ef41Sopenharmony_ci // kArchCallCFunction; 4521cb0ef41Sopenharmony_ci // kArchRestoreCallerRegisters; 4531cb0ef41Sopenharmony_ci // The boolean is used to distinguish the two cases. In the latter case, we 4541cb0ef41Sopenharmony_ci // also need to decide if FP registers need to be saved, which is controlled 4551cb0ef41Sopenharmony_ci // by fp_mode_. 4561cb0ef41Sopenharmony_ci bool caller_registers_saved_; 4571cb0ef41Sopenharmony_ci SaveFPRegsMode fp_mode_; 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci JumpTable* jump_tables_; 4601cb0ef41Sopenharmony_ci OutOfLineCode* ools_; 4611cb0ef41Sopenharmony_ci base::Optional<OsrHelper> osr_helper_; 4621cb0ef41Sopenharmony_ci int osr_pc_offset_; 4631cb0ef41Sopenharmony_ci int optimized_out_literal_id_; 4641cb0ef41Sopenharmony_ci SourcePositionTableBuilder source_position_table_builder_; 4651cb0ef41Sopenharmony_ci ZoneVector<trap_handler::ProtectedInstructionData> protected_instructions_; 4661cb0ef41Sopenharmony_ci CodeGenResult result_; 4671cb0ef41Sopenharmony_ci ZoneVector<int> block_starts_; 4681cb0ef41Sopenharmony_ci TurbolizerCodeOffsetsInfo offsets_info_; 4691cb0ef41Sopenharmony_ci ZoneVector<TurbolizerInstructionStartInfo> instr_starts_; 4701cb0ef41Sopenharmony_ci 4711cb0ef41Sopenharmony_ci const char* debug_name_ = nullptr; 4721cb0ef41Sopenharmony_ci}; 4731cb0ef41Sopenharmony_ci 4741cb0ef41Sopenharmony_ci} // namespace compiler 4751cb0ef41Sopenharmony_ci} // namespace internal 4761cb0ef41Sopenharmony_ci} // namespace v8 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_ci#endif // V8_COMPILER_BACKEND_CODE_GENERATOR_H_ 479