11cb0ef41Sopenharmony_ci// Copyright 2013 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/backend/code-generator.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include "src/base/iterator.h" 81cb0ef41Sopenharmony_ci#include "src/codegen/assembler-inl.h" 91cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler-inl.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/optimized-compilation-info.h" 111cb0ef41Sopenharmony_ci#include "src/codegen/string-constants.h" 121cb0ef41Sopenharmony_ci#include "src/compiler/backend/code-generator-impl.h" 131cb0ef41Sopenharmony_ci#include "src/compiler/globals.h" 141cb0ef41Sopenharmony_ci#include "src/compiler/linkage.h" 151cb0ef41Sopenharmony_ci#include "src/compiler/pipeline.h" 161cb0ef41Sopenharmony_ci#include "src/diagnostics/eh-frame.h" 171cb0ef41Sopenharmony_ci#include "src/execution/frames.h" 181cb0ef41Sopenharmony_ci#include "src/logging/counters.h" 191cb0ef41Sopenharmony_ci#include "src/logging/log.h" 201cb0ef41Sopenharmony_ci#include "src/objects/smi.h" 211cb0ef41Sopenharmony_ci#include "src/utils/address-map.h" 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_cinamespace v8 { 241cb0ef41Sopenharmony_cinamespace internal { 251cb0ef41Sopenharmony_cinamespace compiler { 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciclass CodeGenerator::JumpTable final : public ZoneObject { 281cb0ef41Sopenharmony_ci public: 291cb0ef41Sopenharmony_ci JumpTable(JumpTable* next, Label** targets, size_t target_count) 301cb0ef41Sopenharmony_ci : next_(next), targets_(targets), target_count_(target_count) {} 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci Label* label() { return &label_; } 331cb0ef41Sopenharmony_ci JumpTable* next() const { return next_; } 341cb0ef41Sopenharmony_ci Label** targets() const { return targets_; } 351cb0ef41Sopenharmony_ci size_t target_count() const { return target_count_; } 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_ci private: 381cb0ef41Sopenharmony_ci Label label_; 391cb0ef41Sopenharmony_ci JumpTable* const next_; 401cb0ef41Sopenharmony_ci Label** const targets_; 411cb0ef41Sopenharmony_ci size_t const target_count_; 421cb0ef41Sopenharmony_ci}; 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ciCodeGenerator::CodeGenerator(Zone* codegen_zone, Frame* frame, Linkage* linkage, 451cb0ef41Sopenharmony_ci InstructionSequence* instructions, 461cb0ef41Sopenharmony_ci OptimizedCompilationInfo* info, Isolate* isolate, 471cb0ef41Sopenharmony_ci base::Optional<OsrHelper> osr_helper, 481cb0ef41Sopenharmony_ci int start_source_position, 491cb0ef41Sopenharmony_ci JumpOptimizationInfo* jump_opt, 501cb0ef41Sopenharmony_ci const AssemblerOptions& options, Builtin builtin, 511cb0ef41Sopenharmony_ci size_t max_unoptimized_frame_height, 521cb0ef41Sopenharmony_ci size_t max_pushed_argument_count, 531cb0ef41Sopenharmony_ci const char* debug_name) 541cb0ef41Sopenharmony_ci : zone_(codegen_zone), 551cb0ef41Sopenharmony_ci isolate_(isolate), 561cb0ef41Sopenharmony_ci frame_access_state_(nullptr), 571cb0ef41Sopenharmony_ci linkage_(linkage), 581cb0ef41Sopenharmony_ci instructions_(instructions), 591cb0ef41Sopenharmony_ci unwinding_info_writer_(codegen_zone), 601cb0ef41Sopenharmony_ci info_(info), 611cb0ef41Sopenharmony_ci labels_( 621cb0ef41Sopenharmony_ci codegen_zone->NewArray<Label>(instructions->InstructionBlockCount())), 631cb0ef41Sopenharmony_ci current_block_(RpoNumber::Invalid()), 641cb0ef41Sopenharmony_ci start_source_position_(start_source_position), 651cb0ef41Sopenharmony_ci current_source_position_(SourcePosition::Unknown()), 661cb0ef41Sopenharmony_ci tasm_(isolate, options, CodeObjectRequired::kNo), 671cb0ef41Sopenharmony_ci resolver_(this), 681cb0ef41Sopenharmony_ci safepoints_(codegen_zone), 691cb0ef41Sopenharmony_ci handlers_(codegen_zone), 701cb0ef41Sopenharmony_ci deoptimization_exits_(codegen_zone), 711cb0ef41Sopenharmony_ci deoptimization_literals_(codegen_zone), 721cb0ef41Sopenharmony_ci translations_(codegen_zone), 731cb0ef41Sopenharmony_ci max_unoptimized_frame_height_(max_unoptimized_frame_height), 741cb0ef41Sopenharmony_ci max_pushed_argument_count_(max_pushed_argument_count), 751cb0ef41Sopenharmony_ci caller_registers_saved_(false), 761cb0ef41Sopenharmony_ci jump_tables_(nullptr), 771cb0ef41Sopenharmony_ci ools_(nullptr), 781cb0ef41Sopenharmony_ci osr_helper_(std::move(osr_helper)), 791cb0ef41Sopenharmony_ci osr_pc_offset_(-1), 801cb0ef41Sopenharmony_ci optimized_out_literal_id_(-1), 811cb0ef41Sopenharmony_ci source_position_table_builder_( 821cb0ef41Sopenharmony_ci codegen_zone, SourcePositionTableBuilder::RECORD_SOURCE_POSITIONS), 831cb0ef41Sopenharmony_ci protected_instructions_(codegen_zone), 841cb0ef41Sopenharmony_ci result_(kSuccess), 851cb0ef41Sopenharmony_ci block_starts_(codegen_zone), 861cb0ef41Sopenharmony_ci instr_starts_(codegen_zone), 871cb0ef41Sopenharmony_ci debug_name_(debug_name) { 881cb0ef41Sopenharmony_ci for (int i = 0; i < instructions->InstructionBlockCount(); ++i) { 891cb0ef41Sopenharmony_ci new (&labels_[i]) Label; 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci CreateFrameAccessState(frame); 921cb0ef41Sopenharmony_ci CHECK_EQ(info->is_osr(), osr_helper_.has_value()); 931cb0ef41Sopenharmony_ci tasm_.set_jump_optimization_info(jump_opt); 941cb0ef41Sopenharmony_ci CodeKind code_kind = info->code_kind(); 951cb0ef41Sopenharmony_ci if (code_kind == CodeKind::WASM_FUNCTION || 961cb0ef41Sopenharmony_ci code_kind == CodeKind::WASM_TO_CAPI_FUNCTION || 971cb0ef41Sopenharmony_ci code_kind == CodeKind::WASM_TO_JS_FUNCTION || 981cb0ef41Sopenharmony_ci code_kind == CodeKind::JS_TO_WASM_FUNCTION) { 991cb0ef41Sopenharmony_ci tasm_.set_abort_hard(true); 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci tasm_.set_builtin(builtin); 1021cb0ef41Sopenharmony_ci} 1031cb0ef41Sopenharmony_ci 1041cb0ef41Sopenharmony_cibool CodeGenerator::wasm_runtime_exception_support() const { 1051cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(info_); 1061cb0ef41Sopenharmony_ci return info_->wasm_runtime_exception_support(); 1071cb0ef41Sopenharmony_ci} 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_civoid CodeGenerator::AddProtectedInstructionLanding(uint32_t instr_offset, 1101cb0ef41Sopenharmony_ci uint32_t landing_offset) { 1111cb0ef41Sopenharmony_ci protected_instructions_.push_back({instr_offset, landing_offset}); 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_civoid CodeGenerator::CreateFrameAccessState(Frame* frame) { 1151cb0ef41Sopenharmony_ci FinishFrame(frame); 1161cb0ef41Sopenharmony_ci frame_access_state_ = zone()->New<FrameAccessState>(frame); 1171cb0ef41Sopenharmony_ci} 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_cibool CodeGenerator::ShouldApplyOffsetToStackCheck(Instruction* instr, 1201cb0ef41Sopenharmony_ci uint32_t* offset) { 1211cb0ef41Sopenharmony_ci DCHECK_EQ(instr->arch_opcode(), kArchStackPointerGreaterThan); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci StackCheckKind kind = 1241cb0ef41Sopenharmony_ci static_cast<StackCheckKind>(MiscField::decode(instr->opcode())); 1251cb0ef41Sopenharmony_ci if (kind != StackCheckKind::kJSFunctionEntry) return false; 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci uint32_t stack_check_offset = *offset = GetStackCheckOffset(); 1281cb0ef41Sopenharmony_ci return stack_check_offset > kStackLimitSlackForDeoptimizationInBytes; 1291cb0ef41Sopenharmony_ci} 1301cb0ef41Sopenharmony_ci 1311cb0ef41Sopenharmony_ciuint32_t CodeGenerator::GetStackCheckOffset() { 1321cb0ef41Sopenharmony_ci if (!frame_access_state()->has_frame()) { 1331cb0ef41Sopenharmony_ci DCHECK_EQ(max_unoptimized_frame_height_, 0); 1341cb0ef41Sopenharmony_ci DCHECK_EQ(max_pushed_argument_count_, 0); 1351cb0ef41Sopenharmony_ci return 0; 1361cb0ef41Sopenharmony_ci } 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci int32_t optimized_frame_height = 1391cb0ef41Sopenharmony_ci frame()->GetTotalFrameSlotCount() * kSystemPointerSize; 1401cb0ef41Sopenharmony_ci DCHECK(is_int32(max_unoptimized_frame_height_)); 1411cb0ef41Sopenharmony_ci int32_t signed_max_unoptimized_frame_height = 1421cb0ef41Sopenharmony_ci static_cast<int32_t>(max_unoptimized_frame_height_); 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ci // The offset is either the delta between the optimized frames and the 1451cb0ef41Sopenharmony_ci // interpreted frame, or the maximal number of bytes pushed to the stack 1461cb0ef41Sopenharmony_ci // while preparing for function calls, whichever is bigger. 1471cb0ef41Sopenharmony_ci uint32_t frame_height_delta = static_cast<uint32_t>(std::max( 1481cb0ef41Sopenharmony_ci signed_max_unoptimized_frame_height - optimized_frame_height, 0)); 1491cb0ef41Sopenharmony_ci uint32_t max_pushed_argument_bytes = 1501cb0ef41Sopenharmony_ci static_cast<uint32_t>(max_pushed_argument_count_ * kSystemPointerSize); 1511cb0ef41Sopenharmony_ci return std::max(frame_height_delta, max_pushed_argument_bytes); 1521cb0ef41Sopenharmony_ci} 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ciCodeGenerator::CodeGenResult CodeGenerator::AssembleDeoptimizerCall( 1551cb0ef41Sopenharmony_ci DeoptimizationExit* exit) { 1561cb0ef41Sopenharmony_ci int deoptimization_id = exit->deoptimization_id(); 1571cb0ef41Sopenharmony_ci if (deoptimization_id > Deoptimizer::kMaxNumberOfEntries) { 1581cb0ef41Sopenharmony_ci return kTooManyDeoptimizationBailouts; 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci 1611cb0ef41Sopenharmony_ci DeoptimizeKind deopt_kind = exit->kind(); 1621cb0ef41Sopenharmony_ci DeoptimizeReason deoptimization_reason = exit->reason(); 1631cb0ef41Sopenharmony_ci Label* jump_deoptimization_entry_label = 1641cb0ef41Sopenharmony_ci &jump_deoptimization_entry_labels_[static_cast<int>(deopt_kind)]; 1651cb0ef41Sopenharmony_ci if (info()->source_positions()) { 1661cb0ef41Sopenharmony_ci tasm()->RecordDeoptReason(deoptimization_reason, exit->node_id(), 1671cb0ef41Sopenharmony_ci exit->pos(), deoptimization_id); 1681cb0ef41Sopenharmony_ci } 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci if (deopt_kind == DeoptimizeKind::kLazy) { 1711cb0ef41Sopenharmony_ci ++lazy_deopt_count_; 1721cb0ef41Sopenharmony_ci tasm()->BindExceptionHandler(exit->label()); 1731cb0ef41Sopenharmony_ci } else { 1741cb0ef41Sopenharmony_ci ++eager_deopt_count_; 1751cb0ef41Sopenharmony_ci tasm()->bind(exit->label()); 1761cb0ef41Sopenharmony_ci } 1771cb0ef41Sopenharmony_ci Builtin target = Deoptimizer::GetDeoptimizationEntry(deopt_kind); 1781cb0ef41Sopenharmony_ci tasm()->CallForDeoptimization(target, deoptimization_id, exit->label(), 1791cb0ef41Sopenharmony_ci deopt_kind, exit->continue_label(), 1801cb0ef41Sopenharmony_ci jump_deoptimization_entry_label); 1811cb0ef41Sopenharmony_ci 1821cb0ef41Sopenharmony_ci exit->set_emitted(); 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci return kSuccess; 1851cb0ef41Sopenharmony_ci} 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_civoid CodeGenerator::MaybeEmitOutOfLineConstantPool() { 1881cb0ef41Sopenharmony_ci tasm()->MaybeEmitOutOfLineConstantPool(); 1891cb0ef41Sopenharmony_ci} 1901cb0ef41Sopenharmony_ci 1911cb0ef41Sopenharmony_civoid CodeGenerator::AssembleCode() { 1921cb0ef41Sopenharmony_ci OptimizedCompilationInfo* info = this->info(); 1931cb0ef41Sopenharmony_ci 1941cb0ef41Sopenharmony_ci // Open a frame scope to indicate that there is a frame on the stack. The 1951cb0ef41Sopenharmony_ci // MANUAL indicates that the scope shouldn't actually generate code to set up 1961cb0ef41Sopenharmony_ci // the frame (that is done in AssemblePrologue). 1971cb0ef41Sopenharmony_ci FrameScope frame_scope(tasm(), StackFrame::MANUAL); 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci if (info->source_positions()) { 2001cb0ef41Sopenharmony_ci AssembleSourcePosition(start_source_position()); 2011cb0ef41Sopenharmony_ci } 2021cb0ef41Sopenharmony_ci offsets_info_.code_start_register_check = tasm()->pc_offset(); 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci tasm()->CodeEntry(); 2051cb0ef41Sopenharmony_ci 2061cb0ef41Sopenharmony_ci // Check that {kJavaScriptCallCodeStartRegister} has been set correctly. 2071cb0ef41Sopenharmony_ci if (FLAG_debug_code && info->called_with_code_start_register()) { 2081cb0ef41Sopenharmony_ci tasm()->RecordComment("-- Prologue: check code start register --"); 2091cb0ef41Sopenharmony_ci AssembleCodeStartRegisterCheck(); 2101cb0ef41Sopenharmony_ci } 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci offsets_info_.deopt_check = tasm()->pc_offset(); 2131cb0ef41Sopenharmony_ci // We want to bailout only from JS functions, which are the only ones 2141cb0ef41Sopenharmony_ci // that are optimized. 2151cb0ef41Sopenharmony_ci if (info->IsOptimizing()) { 2161cb0ef41Sopenharmony_ci DCHECK(linkage()->GetIncomingDescriptor()->IsJSFunctionCall()); 2171cb0ef41Sopenharmony_ci tasm()->RecordComment("-- Prologue: check for deoptimization --"); 2181cb0ef41Sopenharmony_ci BailoutIfDeoptimized(); 2191cb0ef41Sopenharmony_ci } 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci // Define deoptimization literals for all inlined functions. 2221cb0ef41Sopenharmony_ci DCHECK_EQ(0u, deoptimization_literals_.size()); 2231cb0ef41Sopenharmony_ci for (OptimizedCompilationInfo::InlinedFunctionHolder& inlined : 2241cb0ef41Sopenharmony_ci info->inlined_functions()) { 2251cb0ef41Sopenharmony_ci if (!inlined.shared_info.equals(info->shared_info())) { 2261cb0ef41Sopenharmony_ci int index = DefineDeoptimizationLiteral( 2271cb0ef41Sopenharmony_ci DeoptimizationLiteral(inlined.shared_info)); 2281cb0ef41Sopenharmony_ci inlined.RegisterInlinedFunctionId(index); 2291cb0ef41Sopenharmony_ci } 2301cb0ef41Sopenharmony_ci } 2311cb0ef41Sopenharmony_ci inlined_function_count_ = deoptimization_literals_.size(); 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci // Define deoptimization literals for all BytecodeArrays to which we might 2341cb0ef41Sopenharmony_ci // deopt to ensure they are strongly held by the optimized code. 2351cb0ef41Sopenharmony_ci if (info->has_bytecode_array()) { 2361cb0ef41Sopenharmony_ci DefineDeoptimizationLiteral(DeoptimizationLiteral(info->bytecode_array())); 2371cb0ef41Sopenharmony_ci } 2381cb0ef41Sopenharmony_ci for (OptimizedCompilationInfo::InlinedFunctionHolder& inlined : 2391cb0ef41Sopenharmony_ci info->inlined_functions()) { 2401cb0ef41Sopenharmony_ci DefineDeoptimizationLiteral(DeoptimizationLiteral(inlined.bytecode_array)); 2411cb0ef41Sopenharmony_ci } 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci unwinding_info_writer_.SetNumberOfInstructionBlocks( 2441cb0ef41Sopenharmony_ci instructions()->InstructionBlockCount()); 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci if (info->trace_turbo_json()) { 2471cb0ef41Sopenharmony_ci block_starts_.assign(instructions()->instruction_blocks().size(), -1); 2481cb0ef41Sopenharmony_ci instr_starts_.assign(instructions()->instructions().size(), {}); 2491cb0ef41Sopenharmony_ci } 2501cb0ef41Sopenharmony_ci // Assemble instructions in assembly order. 2511cb0ef41Sopenharmony_ci offsets_info_.blocks_start = tasm()->pc_offset(); 2521cb0ef41Sopenharmony_ci for (const InstructionBlock* block : instructions()->ao_blocks()) { 2531cb0ef41Sopenharmony_ci // Align loop headers on vendor recommended boundaries. 2541cb0ef41Sopenharmony_ci if (!tasm()->jump_optimization_info()) { 2551cb0ef41Sopenharmony_ci if (block->ShouldAlignLoopHeader()) { 2561cb0ef41Sopenharmony_ci tasm()->LoopHeaderAlign(); 2571cb0ef41Sopenharmony_ci } else if (block->ShouldAlignCodeTarget()) { 2581cb0ef41Sopenharmony_ci tasm()->CodeTargetAlign(); 2591cb0ef41Sopenharmony_ci } 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci if (info->trace_turbo_json()) { 2621cb0ef41Sopenharmony_ci block_starts_[block->rpo_number().ToInt()] = tasm()->pc_offset(); 2631cb0ef41Sopenharmony_ci } 2641cb0ef41Sopenharmony_ci // Bind a label for a block. 2651cb0ef41Sopenharmony_ci current_block_ = block->rpo_number(); 2661cb0ef41Sopenharmony_ci unwinding_info_writer_.BeginInstructionBlock(tasm()->pc_offset(), block); 2671cb0ef41Sopenharmony_ci if (FLAG_code_comments) { 2681cb0ef41Sopenharmony_ci std::ostringstream buffer; 2691cb0ef41Sopenharmony_ci buffer << "-- B" << block->rpo_number().ToInt() << " start"; 2701cb0ef41Sopenharmony_ci if (block->IsDeferred()) buffer << " (deferred)"; 2711cb0ef41Sopenharmony_ci if (!block->needs_frame()) buffer << " (no frame)"; 2721cb0ef41Sopenharmony_ci if (block->must_construct_frame()) buffer << " (construct frame)"; 2731cb0ef41Sopenharmony_ci if (block->must_deconstruct_frame()) buffer << " (deconstruct frame)"; 2741cb0ef41Sopenharmony_ci 2751cb0ef41Sopenharmony_ci if (block->IsLoopHeader()) { 2761cb0ef41Sopenharmony_ci buffer << " (loop up to " << block->loop_end().ToInt() << ")"; 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci if (block->loop_header().IsValid()) { 2791cb0ef41Sopenharmony_ci buffer << " (in loop " << block->loop_header().ToInt() << ")"; 2801cb0ef41Sopenharmony_ci } 2811cb0ef41Sopenharmony_ci buffer << " --"; 2821cb0ef41Sopenharmony_ci tasm()->RecordComment(buffer.str().c_str()); 2831cb0ef41Sopenharmony_ci } 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci frame_access_state()->MarkHasFrame(block->needs_frame()); 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci tasm()->bind(GetLabel(current_block_)); 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci if (block->must_construct_frame()) { 2901cb0ef41Sopenharmony_ci AssembleConstructFrame(); 2911cb0ef41Sopenharmony_ci // We need to setup the root register after we assemble the prologue, to 2921cb0ef41Sopenharmony_ci // avoid clobbering callee saved registers in case of C linkage and 2931cb0ef41Sopenharmony_ci // using the roots. 2941cb0ef41Sopenharmony_ci // TODO(mtrofin): investigate how we can avoid doing this repeatedly. 2951cb0ef41Sopenharmony_ci if (linkage()->GetIncomingDescriptor()->InitializeRootRegister()) { 2961cb0ef41Sopenharmony_ci tasm()->InitializeRootRegister(); 2971cb0ef41Sopenharmony_ci } 2981cb0ef41Sopenharmony_ci } 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci if (FLAG_enable_embedded_constant_pool && !block->needs_frame()) { 3011cb0ef41Sopenharmony_ci ConstantPoolUnavailableScope constant_pool_unavailable(tasm()); 3021cb0ef41Sopenharmony_ci result_ = AssembleBlock(block); 3031cb0ef41Sopenharmony_ci } else { 3041cb0ef41Sopenharmony_ci result_ = AssembleBlock(block); 3051cb0ef41Sopenharmony_ci } 3061cb0ef41Sopenharmony_ci if (result_ != kSuccess) return; 3071cb0ef41Sopenharmony_ci unwinding_info_writer_.EndInstructionBlock(block); 3081cb0ef41Sopenharmony_ci } 3091cb0ef41Sopenharmony_ci 3101cb0ef41Sopenharmony_ci // Assemble all out-of-line code. 3111cb0ef41Sopenharmony_ci offsets_info_.out_of_line_code = tasm()->pc_offset(); 3121cb0ef41Sopenharmony_ci if (ools_) { 3131cb0ef41Sopenharmony_ci tasm()->RecordComment("-- Out of line code --"); 3141cb0ef41Sopenharmony_ci for (OutOfLineCode* ool = ools_; ool; ool = ool->next()) { 3151cb0ef41Sopenharmony_ci tasm()->bind(ool->entry()); 3161cb0ef41Sopenharmony_ci ool->Generate(); 3171cb0ef41Sopenharmony_ci if (ool->exit()->is_bound()) tasm()->jmp(ool->exit()); 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci } 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci // This nop operation is needed to ensure that the trampoline is not 3221cb0ef41Sopenharmony_ci // confused with the pc of the call before deoptimization. 3231cb0ef41Sopenharmony_ci // The test regress/regress-259 is an example of where we need it. 3241cb0ef41Sopenharmony_ci tasm()->nop(); 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci // For some targets, we must make sure that constant and veneer pools are 3271cb0ef41Sopenharmony_ci // emitted before emitting the deoptimization exits. 3281cb0ef41Sopenharmony_ci PrepareForDeoptimizationExits(&deoptimization_exits_); 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_ci deopt_exit_start_offset_ = tasm()->pc_offset(); 3311cb0ef41Sopenharmony_ci 3321cb0ef41Sopenharmony_ci // Assemble deoptimization exits. 3331cb0ef41Sopenharmony_ci offsets_info_.deoptimization_exits = tasm()->pc_offset(); 3341cb0ef41Sopenharmony_ci int last_updated = 0; 3351cb0ef41Sopenharmony_ci // We sort the deoptimization exits here so that the lazy ones will be visited 3361cb0ef41Sopenharmony_ci // last. We need this as lazy deopts might need additional instructions. 3371cb0ef41Sopenharmony_ci auto cmp = [](const DeoptimizationExit* a, const DeoptimizationExit* b) { 3381cb0ef41Sopenharmony_ci // The deoptimization exits are sorted so that lazy deopt exits appear after 3391cb0ef41Sopenharmony_ci // eager deopts. 3401cb0ef41Sopenharmony_ci static_assert(static_cast<int>(DeoptimizeKind::kLazy) == 3411cb0ef41Sopenharmony_ci static_cast<int>(kLastDeoptimizeKind), 3421cb0ef41Sopenharmony_ci "lazy deopts are expected to be emitted last"); 3431cb0ef41Sopenharmony_ci if (a->kind() != b->kind()) { 3441cb0ef41Sopenharmony_ci return a->kind() < b->kind(); 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci return a->pc_offset() < b->pc_offset(); 3471cb0ef41Sopenharmony_ci }; 3481cb0ef41Sopenharmony_ci std::sort(deoptimization_exits_.begin(), deoptimization_exits_.end(), cmp); 3491cb0ef41Sopenharmony_ci 3501cb0ef41Sopenharmony_ci { 3511cb0ef41Sopenharmony_ci#ifdef V8_TARGET_ARCH_PPC64 3521cb0ef41Sopenharmony_ci v8::internal::Assembler::BlockTrampolinePoolScope block_trampoline_pool( 3531cb0ef41Sopenharmony_ci tasm()); 3541cb0ef41Sopenharmony_ci#endif 3551cb0ef41Sopenharmony_ci for (DeoptimizationExit* exit : deoptimization_exits_) { 3561cb0ef41Sopenharmony_ci if (exit->emitted()) continue; 3571cb0ef41Sopenharmony_ci exit->set_deoptimization_id(next_deoptimization_id_++); 3581cb0ef41Sopenharmony_ci result_ = AssembleDeoptimizerCall(exit); 3591cb0ef41Sopenharmony_ci if (result_ != kSuccess) return; 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci // UpdateDeoptimizationInfo expects lazy deopts to be visited in pc_offset 3621cb0ef41Sopenharmony_ci // order, which is always the case since they are added to 3631cb0ef41Sopenharmony_ci // deoptimization_exits_ in that order, and the optional sort operation 3641cb0ef41Sopenharmony_ci // above preserves that order. 3651cb0ef41Sopenharmony_ci if (exit->kind() == DeoptimizeKind::kLazy) { 3661cb0ef41Sopenharmony_ci int trampoline_pc = exit->label()->pos(); 3671cb0ef41Sopenharmony_ci last_updated = safepoints()->UpdateDeoptimizationInfo( 3681cb0ef41Sopenharmony_ci exit->pc_offset(), trampoline_pc, last_updated, 3691cb0ef41Sopenharmony_ci exit->deoptimization_id()); 3701cb0ef41Sopenharmony_ci } 3711cb0ef41Sopenharmony_ci } 3721cb0ef41Sopenharmony_ci } 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci offsets_info_.pools = tasm()->pc_offset(); 3751cb0ef41Sopenharmony_ci // TODO(jgruber): Move all inlined metadata generation into a new, 3761cb0ef41Sopenharmony_ci // architecture-independent version of FinishCode. Currently, this includes 3771cb0ef41Sopenharmony_ci // the safepoint table, handler table, constant pool, and code comments, in 3781cb0ef41Sopenharmony_ci // that order. 3791cb0ef41Sopenharmony_ci FinishCode(); 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci offsets_info_.jump_tables = tasm()->pc_offset(); 3821cb0ef41Sopenharmony_ci // Emit the jump tables. 3831cb0ef41Sopenharmony_ci if (jump_tables_) { 3841cb0ef41Sopenharmony_ci tasm()->Align(kSystemPointerSize); 3851cb0ef41Sopenharmony_ci for (JumpTable* table = jump_tables_; table; table = table->next()) { 3861cb0ef41Sopenharmony_ci tasm()->bind(table->label()); 3871cb0ef41Sopenharmony_ci AssembleJumpTable(table->targets(), table->target_count()); 3881cb0ef41Sopenharmony_ci } 3891cb0ef41Sopenharmony_ci } 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci // The PerfJitLogger logs code up until here, excluding the safepoint 3921cb0ef41Sopenharmony_ci // table. Resolve the unwinding info now so it is aware of the same code 3931cb0ef41Sopenharmony_ci // size as reported by perf. 3941cb0ef41Sopenharmony_ci unwinding_info_writer_.Finish(tasm()->pc_offset()); 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci // Final alignment before starting on the metadata section. 3971cb0ef41Sopenharmony_ci tasm()->Align(Code::kMetadataAlignment); 3981cb0ef41Sopenharmony_ci 3991cb0ef41Sopenharmony_ci safepoints()->Emit(tasm(), frame()->GetTotalFrameSlotCount()); 4001cb0ef41Sopenharmony_ci 4011cb0ef41Sopenharmony_ci // Emit the exception handler table. 4021cb0ef41Sopenharmony_ci if (!handlers_.empty()) { 4031cb0ef41Sopenharmony_ci handler_table_offset_ = HandlerTable::EmitReturnTableStart(tasm()); 4041cb0ef41Sopenharmony_ci for (size_t i = 0; i < handlers_.size(); ++i) { 4051cb0ef41Sopenharmony_ci HandlerTable::EmitReturnEntry(tasm(), handlers_[i].pc_offset, 4061cb0ef41Sopenharmony_ci handlers_[i].handler->pos()); 4071cb0ef41Sopenharmony_ci } 4081cb0ef41Sopenharmony_ci } 4091cb0ef41Sopenharmony_ci 4101cb0ef41Sopenharmony_ci tasm()->MaybeEmitOutOfLineConstantPool(); 4111cb0ef41Sopenharmony_ci tasm()->FinalizeJumpOptimizationInfo(); 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci result_ = kSuccess; 4141cb0ef41Sopenharmony_ci} 4151cb0ef41Sopenharmony_ci 4161cb0ef41Sopenharmony_civoid CodeGenerator::AssembleArchBinarySearchSwitchRange( 4171cb0ef41Sopenharmony_ci Register input, RpoNumber def_block, std::pair<int32_t, Label*>* begin, 4181cb0ef41Sopenharmony_ci std::pair<int32_t, Label*>* end) { 4191cb0ef41Sopenharmony_ci if (end - begin < kBinarySearchSwitchMinimalCases) { 4201cb0ef41Sopenharmony_ci while (begin != end) { 4211cb0ef41Sopenharmony_ci tasm()->JumpIfEqual(input, begin->first, begin->second); 4221cb0ef41Sopenharmony_ci ++begin; 4231cb0ef41Sopenharmony_ci } 4241cb0ef41Sopenharmony_ci AssembleArchJumpRegardlessOfAssemblyOrder(def_block); 4251cb0ef41Sopenharmony_ci return; 4261cb0ef41Sopenharmony_ci } 4271cb0ef41Sopenharmony_ci auto middle = begin + (end - begin) / 2; 4281cb0ef41Sopenharmony_ci Label less_label; 4291cb0ef41Sopenharmony_ci tasm()->JumpIfLessThan(input, middle->first, &less_label); 4301cb0ef41Sopenharmony_ci AssembleArchBinarySearchSwitchRange(input, def_block, middle, end); 4311cb0ef41Sopenharmony_ci tasm()->bind(&less_label); 4321cb0ef41Sopenharmony_ci AssembleArchBinarySearchSwitchRange(input, def_block, begin, middle); 4331cb0ef41Sopenharmony_ci} 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_civoid CodeGenerator::AssembleArchJump(RpoNumber target) { 4361cb0ef41Sopenharmony_ci if (!IsNextInAssemblyOrder(target)) 4371cb0ef41Sopenharmony_ci AssembleArchJumpRegardlessOfAssemblyOrder(target); 4381cb0ef41Sopenharmony_ci} 4391cb0ef41Sopenharmony_ci 4401cb0ef41Sopenharmony_cibase::OwnedVector<byte> CodeGenerator::GetSourcePositionTable() { 4411cb0ef41Sopenharmony_ci return source_position_table_builder_.ToSourcePositionTableVector(); 4421cb0ef41Sopenharmony_ci} 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_cibase::OwnedVector<byte> CodeGenerator::GetProtectedInstructionsData() { 4451cb0ef41Sopenharmony_ci return base::OwnedVector<byte>::Of( 4461cb0ef41Sopenharmony_ci base::Vector<byte>::cast(base::VectorOf(protected_instructions_))); 4471cb0ef41Sopenharmony_ci} 4481cb0ef41Sopenharmony_ci 4491cb0ef41Sopenharmony_ciMaybeHandle<Code> CodeGenerator::FinalizeCode() { 4501cb0ef41Sopenharmony_ci if (result_ != kSuccess) { 4511cb0ef41Sopenharmony_ci tasm()->AbortedCodeGeneration(); 4521cb0ef41Sopenharmony_ci return MaybeHandle<Code>(); 4531cb0ef41Sopenharmony_ci } 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ci // Allocate the source position table. 4561cb0ef41Sopenharmony_ci Handle<ByteArray> source_positions = 4571cb0ef41Sopenharmony_ci source_position_table_builder_.ToSourcePositionTable(isolate()); 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci // Allocate deoptimization data. 4601cb0ef41Sopenharmony_ci Handle<DeoptimizationData> deopt_data = GenerateDeoptimizationData(); 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci // Allocate and install the code. 4631cb0ef41Sopenharmony_ci CodeDesc desc; 4641cb0ef41Sopenharmony_ci tasm()->GetCode(isolate(), &desc, safepoints(), handler_table_offset_); 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci#if defined(V8_OS_WIN64) 4671cb0ef41Sopenharmony_ci if (Builtins::IsBuiltinId(info_->builtin())) { 4681cb0ef41Sopenharmony_ci isolate_->SetBuiltinUnwindData(info_->builtin(), tasm()->GetUnwindInfo()); 4691cb0ef41Sopenharmony_ci } 4701cb0ef41Sopenharmony_ci#endif // V8_OS_WIN64 4711cb0ef41Sopenharmony_ci 4721cb0ef41Sopenharmony_ci if (unwinding_info_writer_.eh_frame_writer()) { 4731cb0ef41Sopenharmony_ci unwinding_info_writer_.eh_frame_writer()->GetEhFrame(&desc); 4741cb0ef41Sopenharmony_ci } 4751cb0ef41Sopenharmony_ci 4761cb0ef41Sopenharmony_ci MaybeHandle<Code> maybe_code = 4771cb0ef41Sopenharmony_ci Factory::CodeBuilder(isolate(), desc, info()->code_kind()) 4781cb0ef41Sopenharmony_ci .set_builtin(info()->builtin()) 4791cb0ef41Sopenharmony_ci .set_inlined_bytecode_size(info()->inlined_bytecode_size()) 4801cb0ef41Sopenharmony_ci .set_source_position_table(source_positions) 4811cb0ef41Sopenharmony_ci .set_deoptimization_data(deopt_data) 4821cb0ef41Sopenharmony_ci .set_is_turbofanned() 4831cb0ef41Sopenharmony_ci .set_stack_slots(frame()->GetTotalFrameSlotCount()) 4841cb0ef41Sopenharmony_ci .set_profiler_data(info()->profiler_data()) 4851cb0ef41Sopenharmony_ci .TryBuild(); 4861cb0ef41Sopenharmony_ci 4871cb0ef41Sopenharmony_ci Handle<Code> code; 4881cb0ef41Sopenharmony_ci if (!maybe_code.ToHandle(&code)) { 4891cb0ef41Sopenharmony_ci tasm()->AbortedCodeGeneration(); 4901cb0ef41Sopenharmony_ci return MaybeHandle<Code>(); 4911cb0ef41Sopenharmony_ci } 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci // Counts both compiled code and metadata. 4941cb0ef41Sopenharmony_ci isolate()->counters()->total_compiled_code_size()->Increment( 4951cb0ef41Sopenharmony_ci code->raw_body_size()); 4961cb0ef41Sopenharmony_ci 4971cb0ef41Sopenharmony_ci LOG_CODE_EVENT(isolate(), CodeLinePosInfoRecordEvent( 4981cb0ef41Sopenharmony_ci code->raw_instruction_start(), 4991cb0ef41Sopenharmony_ci *source_positions, JitCodeEvent::JIT_CODE)); 5001cb0ef41Sopenharmony_ci 5011cb0ef41Sopenharmony_ci return code; 5021cb0ef41Sopenharmony_ci} 5031cb0ef41Sopenharmony_ci 5041cb0ef41Sopenharmony_cibool CodeGenerator::IsNextInAssemblyOrder(RpoNumber block) const { 5051cb0ef41Sopenharmony_ci return instructions() 5061cb0ef41Sopenharmony_ci ->InstructionBlockAt(current_block_) 5071cb0ef41Sopenharmony_ci ->ao_number() 5081cb0ef41Sopenharmony_ci .IsNext(instructions()->InstructionBlockAt(block)->ao_number()); 5091cb0ef41Sopenharmony_ci} 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_civoid CodeGenerator::RecordSafepoint(ReferenceMap* references) { 5121cb0ef41Sopenharmony_ci auto safepoint = safepoints()->DefineSafepoint(tasm()); 5131cb0ef41Sopenharmony_ci int frame_header_offset = frame()->GetFixedSlotCount(); 5141cb0ef41Sopenharmony_ci for (const InstructionOperand& operand : references->reference_operands()) { 5151cb0ef41Sopenharmony_ci if (operand.IsStackSlot()) { 5161cb0ef41Sopenharmony_ci int index = LocationOperand::cast(operand).index(); 5171cb0ef41Sopenharmony_ci DCHECK_LE(0, index); 5181cb0ef41Sopenharmony_ci // We might index values in the fixed part of the frame (i.e. the 5191cb0ef41Sopenharmony_ci // closure pointer or the context pointer); these are not spill slots 5201cb0ef41Sopenharmony_ci // and therefore don't work with the SafepointTable currently, but 5211cb0ef41Sopenharmony_ci // we also don't need to worry about them, since the GC has special 5221cb0ef41Sopenharmony_ci // knowledge about those fields anyway. 5231cb0ef41Sopenharmony_ci if (index < frame_header_offset) continue; 5241cb0ef41Sopenharmony_ci safepoint.DefineTaggedStackSlot(index); 5251cb0ef41Sopenharmony_ci } 5261cb0ef41Sopenharmony_ci } 5271cb0ef41Sopenharmony_ci} 5281cb0ef41Sopenharmony_ci 5291cb0ef41Sopenharmony_cibool CodeGenerator::IsMaterializableFromRoot(Handle<HeapObject> object, 5301cb0ef41Sopenharmony_ci RootIndex* index_return) { 5311cb0ef41Sopenharmony_ci const CallDescriptor* incoming_descriptor = 5321cb0ef41Sopenharmony_ci linkage()->GetIncomingDescriptor(); 5331cb0ef41Sopenharmony_ci if (incoming_descriptor->flags() & CallDescriptor::kCanUseRoots) { 5341cb0ef41Sopenharmony_ci return isolate()->roots_table().IsRootHandle(object, index_return) && 5351cb0ef41Sopenharmony_ci RootsTable::IsImmortalImmovable(*index_return); 5361cb0ef41Sopenharmony_ci } 5371cb0ef41Sopenharmony_ci return false; 5381cb0ef41Sopenharmony_ci} 5391cb0ef41Sopenharmony_ci 5401cb0ef41Sopenharmony_ciCodeGenerator::CodeGenResult CodeGenerator::AssembleBlock( 5411cb0ef41Sopenharmony_ci const InstructionBlock* block) { 5421cb0ef41Sopenharmony_ci if (block->IsHandler()) { 5431cb0ef41Sopenharmony_ci tasm()->ExceptionHandler(); 5441cb0ef41Sopenharmony_ci } 5451cb0ef41Sopenharmony_ci for (int i = block->code_start(); i < block->code_end(); ++i) { 5461cb0ef41Sopenharmony_ci CodeGenResult result = AssembleInstruction(i, block); 5471cb0ef41Sopenharmony_ci if (result != kSuccess) return result; 5481cb0ef41Sopenharmony_ci } 5491cb0ef41Sopenharmony_ci return kSuccess; 5501cb0ef41Sopenharmony_ci} 5511cb0ef41Sopenharmony_ci 5521cb0ef41Sopenharmony_cibool CodeGenerator::IsValidPush(InstructionOperand source, 5531cb0ef41Sopenharmony_ci CodeGenerator::PushTypeFlags push_type) { 5541cb0ef41Sopenharmony_ci if (source.IsImmediate() && 5551cb0ef41Sopenharmony_ci ((push_type & CodeGenerator::kImmediatePush) != 0)) { 5561cb0ef41Sopenharmony_ci return true; 5571cb0ef41Sopenharmony_ci } 5581cb0ef41Sopenharmony_ci if (source.IsRegister() && 5591cb0ef41Sopenharmony_ci ((push_type & CodeGenerator::kRegisterPush) != 0)) { 5601cb0ef41Sopenharmony_ci return true; 5611cb0ef41Sopenharmony_ci } 5621cb0ef41Sopenharmony_ci if (source.IsStackSlot() && 5631cb0ef41Sopenharmony_ci ((push_type & CodeGenerator::kStackSlotPush) != 0)) { 5641cb0ef41Sopenharmony_ci return true; 5651cb0ef41Sopenharmony_ci } 5661cb0ef41Sopenharmony_ci return false; 5671cb0ef41Sopenharmony_ci} 5681cb0ef41Sopenharmony_ci 5691cb0ef41Sopenharmony_civoid CodeGenerator::GetPushCompatibleMoves(Instruction* instr, 5701cb0ef41Sopenharmony_ci PushTypeFlags push_type, 5711cb0ef41Sopenharmony_ci ZoneVector<MoveOperands*>* pushes) { 5721cb0ef41Sopenharmony_ci static constexpr int first_push_compatible_index = 5731cb0ef41Sopenharmony_ci kReturnAddressStackSlotCount; 5741cb0ef41Sopenharmony_ci pushes->clear(); 5751cb0ef41Sopenharmony_ci for (int i = Instruction::FIRST_GAP_POSITION; 5761cb0ef41Sopenharmony_ci i <= Instruction::LAST_GAP_POSITION; ++i) { 5771cb0ef41Sopenharmony_ci Instruction::GapPosition inner_pos = 5781cb0ef41Sopenharmony_ci static_cast<Instruction::GapPosition>(i); 5791cb0ef41Sopenharmony_ci ParallelMove* parallel_move = instr->GetParallelMove(inner_pos); 5801cb0ef41Sopenharmony_ci if (parallel_move != nullptr) { 5811cb0ef41Sopenharmony_ci for (auto move : *parallel_move) { 5821cb0ef41Sopenharmony_ci InstructionOperand source = move->source(); 5831cb0ef41Sopenharmony_ci InstructionOperand destination = move->destination(); 5841cb0ef41Sopenharmony_ci // If there are any moves from slots that will be overridden by pushes, 5851cb0ef41Sopenharmony_ci // then the full gap resolver must be used since optimization with 5861cb0ef41Sopenharmony_ci // pushes don't participate in the parallel move and might clobber 5871cb0ef41Sopenharmony_ci // values needed for the gap resolve. 5881cb0ef41Sopenharmony_ci if (source.IsAnyStackSlot() && LocationOperand::cast(source).index() >= 5891cb0ef41Sopenharmony_ci first_push_compatible_index) { 5901cb0ef41Sopenharmony_ci pushes->clear(); 5911cb0ef41Sopenharmony_ci return; 5921cb0ef41Sopenharmony_ci } 5931cb0ef41Sopenharmony_ci // TODO(danno): Right now, only consider moves from the FIRST gap for 5941cb0ef41Sopenharmony_ci // pushes. Theoretically, we could extract pushes for both gaps (there 5951cb0ef41Sopenharmony_ci // are cases where this happens), but the logic for that would also have 5961cb0ef41Sopenharmony_ci // to check to make sure that non-memory inputs to the pushes from the 5971cb0ef41Sopenharmony_ci // LAST gap don't get clobbered in the FIRST gap. 5981cb0ef41Sopenharmony_ci if (i == Instruction::FIRST_GAP_POSITION) { 5991cb0ef41Sopenharmony_ci if (destination.IsStackSlot() && 6001cb0ef41Sopenharmony_ci LocationOperand::cast(destination).index() >= 6011cb0ef41Sopenharmony_ci first_push_compatible_index) { 6021cb0ef41Sopenharmony_ci int index = LocationOperand::cast(destination).index(); 6031cb0ef41Sopenharmony_ci if (IsValidPush(source, push_type)) { 6041cb0ef41Sopenharmony_ci if (index >= static_cast<int>(pushes->size())) { 6051cb0ef41Sopenharmony_ci pushes->resize(index + 1); 6061cb0ef41Sopenharmony_ci } 6071cb0ef41Sopenharmony_ci (*pushes)[index] = move; 6081cb0ef41Sopenharmony_ci } 6091cb0ef41Sopenharmony_ci } 6101cb0ef41Sopenharmony_ci } 6111cb0ef41Sopenharmony_ci } 6121cb0ef41Sopenharmony_ci } 6131cb0ef41Sopenharmony_ci } 6141cb0ef41Sopenharmony_ci 6151cb0ef41Sopenharmony_ci // For now, only support a set of continuous pushes at the end of the list. 6161cb0ef41Sopenharmony_ci size_t push_count_upper_bound = pushes->size(); 6171cb0ef41Sopenharmony_ci size_t push_begin = push_count_upper_bound; 6181cb0ef41Sopenharmony_ci for (auto move : base::Reversed(*pushes)) { 6191cb0ef41Sopenharmony_ci if (move == nullptr) break; 6201cb0ef41Sopenharmony_ci push_begin--; 6211cb0ef41Sopenharmony_ci } 6221cb0ef41Sopenharmony_ci size_t push_count = pushes->size() - push_begin; 6231cb0ef41Sopenharmony_ci std::copy(pushes->begin() + push_begin, 6241cb0ef41Sopenharmony_ci pushes->begin() + push_begin + push_count, pushes->begin()); 6251cb0ef41Sopenharmony_ci pushes->resize(push_count); 6261cb0ef41Sopenharmony_ci} 6271cb0ef41Sopenharmony_ci 6281cb0ef41Sopenharmony_ciCodeGenerator::MoveType::Type CodeGenerator::MoveType::InferMove( 6291cb0ef41Sopenharmony_ci InstructionOperand* source, InstructionOperand* destination) { 6301cb0ef41Sopenharmony_ci if (source->IsConstant()) { 6311cb0ef41Sopenharmony_ci if (destination->IsAnyRegister()) { 6321cb0ef41Sopenharmony_ci return MoveType::kConstantToRegister; 6331cb0ef41Sopenharmony_ci } else { 6341cb0ef41Sopenharmony_ci DCHECK(destination->IsAnyStackSlot()); 6351cb0ef41Sopenharmony_ci return MoveType::kConstantToStack; 6361cb0ef41Sopenharmony_ci } 6371cb0ef41Sopenharmony_ci } 6381cb0ef41Sopenharmony_ci DCHECK(LocationOperand::cast(source)->IsCompatible( 6391cb0ef41Sopenharmony_ci LocationOperand::cast(destination))); 6401cb0ef41Sopenharmony_ci if (source->IsAnyRegister()) { 6411cb0ef41Sopenharmony_ci if (destination->IsAnyRegister()) { 6421cb0ef41Sopenharmony_ci return MoveType::kRegisterToRegister; 6431cb0ef41Sopenharmony_ci } else { 6441cb0ef41Sopenharmony_ci DCHECK(destination->IsAnyStackSlot()); 6451cb0ef41Sopenharmony_ci return MoveType::kRegisterToStack; 6461cb0ef41Sopenharmony_ci } 6471cb0ef41Sopenharmony_ci } else { 6481cb0ef41Sopenharmony_ci DCHECK(source->IsAnyStackSlot()); 6491cb0ef41Sopenharmony_ci if (destination->IsAnyRegister()) { 6501cb0ef41Sopenharmony_ci return MoveType::kStackToRegister; 6511cb0ef41Sopenharmony_ci } else { 6521cb0ef41Sopenharmony_ci DCHECK(destination->IsAnyStackSlot()); 6531cb0ef41Sopenharmony_ci return MoveType::kStackToStack; 6541cb0ef41Sopenharmony_ci } 6551cb0ef41Sopenharmony_ci } 6561cb0ef41Sopenharmony_ci} 6571cb0ef41Sopenharmony_ci 6581cb0ef41Sopenharmony_ciCodeGenerator::MoveType::Type CodeGenerator::MoveType::InferSwap( 6591cb0ef41Sopenharmony_ci InstructionOperand* source, InstructionOperand* destination) { 6601cb0ef41Sopenharmony_ci DCHECK(LocationOperand::cast(source)->IsCompatible( 6611cb0ef41Sopenharmony_ci LocationOperand::cast(destination))); 6621cb0ef41Sopenharmony_ci if (source->IsAnyRegister()) { 6631cb0ef41Sopenharmony_ci if (destination->IsAnyRegister()) { 6641cb0ef41Sopenharmony_ci return MoveType::kRegisterToRegister; 6651cb0ef41Sopenharmony_ci } else { 6661cb0ef41Sopenharmony_ci DCHECK(destination->IsAnyStackSlot()); 6671cb0ef41Sopenharmony_ci return MoveType::kRegisterToStack; 6681cb0ef41Sopenharmony_ci } 6691cb0ef41Sopenharmony_ci } else { 6701cb0ef41Sopenharmony_ci DCHECK(source->IsAnyStackSlot()); 6711cb0ef41Sopenharmony_ci DCHECK(destination->IsAnyStackSlot()); 6721cb0ef41Sopenharmony_ci return MoveType::kStackToStack; 6731cb0ef41Sopenharmony_ci } 6741cb0ef41Sopenharmony_ci} 6751cb0ef41Sopenharmony_ci 6761cb0ef41Sopenharmony_ciRpoNumber CodeGenerator::ComputeBranchInfo(BranchInfo* branch, 6771cb0ef41Sopenharmony_ci Instruction* instr) { 6781cb0ef41Sopenharmony_ci // Assemble a branch after this instruction. 6791cb0ef41Sopenharmony_ci InstructionOperandConverter i(this, instr); 6801cb0ef41Sopenharmony_ci RpoNumber true_rpo = i.InputRpo(instr->InputCount() - 2); 6811cb0ef41Sopenharmony_ci RpoNumber false_rpo = i.InputRpo(instr->InputCount() - 1); 6821cb0ef41Sopenharmony_ci 6831cb0ef41Sopenharmony_ci if (true_rpo == false_rpo) { 6841cb0ef41Sopenharmony_ci return true_rpo; 6851cb0ef41Sopenharmony_ci } 6861cb0ef41Sopenharmony_ci FlagsCondition condition = FlagsConditionField::decode(instr->opcode()); 6871cb0ef41Sopenharmony_ci if (IsNextInAssemblyOrder(true_rpo)) { 6881cb0ef41Sopenharmony_ci // true block is next, can fall through if condition negated. 6891cb0ef41Sopenharmony_ci std::swap(true_rpo, false_rpo); 6901cb0ef41Sopenharmony_ci condition = NegateFlagsCondition(condition); 6911cb0ef41Sopenharmony_ci } 6921cb0ef41Sopenharmony_ci branch->condition = condition; 6931cb0ef41Sopenharmony_ci branch->true_label = GetLabel(true_rpo); 6941cb0ef41Sopenharmony_ci branch->false_label = GetLabel(false_rpo); 6951cb0ef41Sopenharmony_ci branch->fallthru = IsNextInAssemblyOrder(false_rpo); 6961cb0ef41Sopenharmony_ci return RpoNumber::Invalid(); 6971cb0ef41Sopenharmony_ci} 6981cb0ef41Sopenharmony_ci 6991cb0ef41Sopenharmony_ciCodeGenerator::CodeGenResult CodeGenerator::AssembleInstruction( 7001cb0ef41Sopenharmony_ci int instruction_index, const InstructionBlock* block) { 7011cb0ef41Sopenharmony_ci Instruction* instr = instructions()->InstructionAt(instruction_index); 7021cb0ef41Sopenharmony_ci if (info()->trace_turbo_json()) { 7031cb0ef41Sopenharmony_ci instr_starts_[instruction_index].gap_pc_offset = tasm()->pc_offset(); 7041cb0ef41Sopenharmony_ci } 7051cb0ef41Sopenharmony_ci int first_unused_stack_slot; 7061cb0ef41Sopenharmony_ci FlagsMode mode = FlagsModeField::decode(instr->opcode()); 7071cb0ef41Sopenharmony_ci if (mode != kFlags_trap) { 7081cb0ef41Sopenharmony_ci AssembleSourcePosition(instr); 7091cb0ef41Sopenharmony_ci } 7101cb0ef41Sopenharmony_ci bool adjust_stack = 7111cb0ef41Sopenharmony_ci GetSlotAboveSPBeforeTailCall(instr, &first_unused_stack_slot); 7121cb0ef41Sopenharmony_ci if (adjust_stack) AssembleTailCallBeforeGap(instr, first_unused_stack_slot); 7131cb0ef41Sopenharmony_ci AssembleGaps(instr); 7141cb0ef41Sopenharmony_ci if (adjust_stack) AssembleTailCallAfterGap(instr, first_unused_stack_slot); 7151cb0ef41Sopenharmony_ci DCHECK_IMPLIES( 7161cb0ef41Sopenharmony_ci block->must_deconstruct_frame(), 7171cb0ef41Sopenharmony_ci instr != instructions()->InstructionAt(block->last_instruction_index()) || 7181cb0ef41Sopenharmony_ci instr->IsRet() || instr->IsJump()); 7191cb0ef41Sopenharmony_ci if (instr->IsJump() && block->must_deconstruct_frame()) { 7201cb0ef41Sopenharmony_ci AssembleDeconstructFrame(); 7211cb0ef41Sopenharmony_ci } 7221cb0ef41Sopenharmony_ci if (info()->trace_turbo_json()) { 7231cb0ef41Sopenharmony_ci instr_starts_[instruction_index].arch_instr_pc_offset = tasm()->pc_offset(); 7241cb0ef41Sopenharmony_ci } 7251cb0ef41Sopenharmony_ci // Assemble architecture-specific code for the instruction. 7261cb0ef41Sopenharmony_ci CodeGenResult result = AssembleArchInstruction(instr); 7271cb0ef41Sopenharmony_ci if (result != kSuccess) return result; 7281cb0ef41Sopenharmony_ci 7291cb0ef41Sopenharmony_ci if (info()->trace_turbo_json()) { 7301cb0ef41Sopenharmony_ci instr_starts_[instruction_index].condition_pc_offset = tasm()->pc_offset(); 7311cb0ef41Sopenharmony_ci } 7321cb0ef41Sopenharmony_ci 7331cb0ef41Sopenharmony_ci FlagsCondition condition = FlagsConditionField::decode(instr->opcode()); 7341cb0ef41Sopenharmony_ci switch (mode) { 7351cb0ef41Sopenharmony_ci case kFlags_branch: { 7361cb0ef41Sopenharmony_ci BranchInfo branch; 7371cb0ef41Sopenharmony_ci RpoNumber target = ComputeBranchInfo(&branch, instr); 7381cb0ef41Sopenharmony_ci if (target.IsValid()) { 7391cb0ef41Sopenharmony_ci // redundant branch. 7401cb0ef41Sopenharmony_ci if (!IsNextInAssemblyOrder(target)) { 7411cb0ef41Sopenharmony_ci AssembleArchJump(target); 7421cb0ef41Sopenharmony_ci } 7431cb0ef41Sopenharmony_ci return kSuccess; 7441cb0ef41Sopenharmony_ci } 7451cb0ef41Sopenharmony_ci // Assemble architecture-specific branch. 7461cb0ef41Sopenharmony_ci AssembleArchBranch(instr, &branch); 7471cb0ef41Sopenharmony_ci break; 7481cb0ef41Sopenharmony_ci } 7491cb0ef41Sopenharmony_ci case kFlags_deoptimize: { 7501cb0ef41Sopenharmony_ci // Assemble a conditional eager deoptimization after this instruction. 7511cb0ef41Sopenharmony_ci InstructionOperandConverter i(this, instr); 7521cb0ef41Sopenharmony_ci size_t frame_state_offset = 7531cb0ef41Sopenharmony_ci DeoptFrameStateOffsetField::decode(instr->opcode()); 7541cb0ef41Sopenharmony_ci size_t immediate_args_count = 7551cb0ef41Sopenharmony_ci DeoptImmedArgsCountField::decode(instr->opcode()); 7561cb0ef41Sopenharmony_ci DeoptimizationExit* const exit = AddDeoptimizationExit( 7571cb0ef41Sopenharmony_ci instr, frame_state_offset, immediate_args_count); 7581cb0ef41Sopenharmony_ci BranchInfo branch; 7591cb0ef41Sopenharmony_ci branch.condition = condition; 7601cb0ef41Sopenharmony_ci branch.true_label = exit->label(); 7611cb0ef41Sopenharmony_ci branch.false_label = exit->continue_label(); 7621cb0ef41Sopenharmony_ci branch.fallthru = true; 7631cb0ef41Sopenharmony_ci AssembleArchDeoptBranch(instr, &branch); 7641cb0ef41Sopenharmony_ci tasm()->bind(exit->continue_label()); 7651cb0ef41Sopenharmony_ci break; 7661cb0ef41Sopenharmony_ci } 7671cb0ef41Sopenharmony_ci case kFlags_set: { 7681cb0ef41Sopenharmony_ci // Assemble a boolean materialization after this instruction. 7691cb0ef41Sopenharmony_ci AssembleArchBoolean(instr, condition); 7701cb0ef41Sopenharmony_ci break; 7711cb0ef41Sopenharmony_ci } 7721cb0ef41Sopenharmony_ci case kFlags_select: { 7731cb0ef41Sopenharmony_ci AssembleArchSelect(instr, condition); 7741cb0ef41Sopenharmony_ci break; 7751cb0ef41Sopenharmony_ci } 7761cb0ef41Sopenharmony_ci case kFlags_trap: { 7771cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 7781cb0ef41Sopenharmony_ci AssembleArchTrap(instr, condition); 7791cb0ef41Sopenharmony_ci break; 7801cb0ef41Sopenharmony_ci#else 7811cb0ef41Sopenharmony_ci UNREACHABLE(); 7821cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 7831cb0ef41Sopenharmony_ci } 7841cb0ef41Sopenharmony_ci case kFlags_none: { 7851cb0ef41Sopenharmony_ci break; 7861cb0ef41Sopenharmony_ci } 7871cb0ef41Sopenharmony_ci } 7881cb0ef41Sopenharmony_ci 7891cb0ef41Sopenharmony_ci return kSuccess; 7901cb0ef41Sopenharmony_ci} 7911cb0ef41Sopenharmony_ci 7921cb0ef41Sopenharmony_civoid CodeGenerator::AssembleSourcePosition(Instruction* instr) { 7931cb0ef41Sopenharmony_ci SourcePosition source_position = SourcePosition::Unknown(); 7941cb0ef41Sopenharmony_ci if (instr->IsNop() && instr->AreMovesRedundant()) return; 7951cb0ef41Sopenharmony_ci if (!instructions()->GetSourcePosition(instr, &source_position)) return; 7961cb0ef41Sopenharmony_ci AssembleSourcePosition(source_position); 7971cb0ef41Sopenharmony_ci} 7981cb0ef41Sopenharmony_ci 7991cb0ef41Sopenharmony_civoid CodeGenerator::AssembleSourcePosition(SourcePosition source_position) { 8001cb0ef41Sopenharmony_ci if (source_position == current_source_position_) return; 8011cb0ef41Sopenharmony_ci current_source_position_ = source_position; 8021cb0ef41Sopenharmony_ci if (!source_position.IsKnown()) return; 8031cb0ef41Sopenharmony_ci source_position_table_builder_.AddPosition(tasm()->pc_offset(), 8041cb0ef41Sopenharmony_ci source_position, false); 8051cb0ef41Sopenharmony_ci if (FLAG_code_comments) { 8061cb0ef41Sopenharmony_ci OptimizedCompilationInfo* info = this->info(); 8071cb0ef41Sopenharmony_ci if (!info->IsOptimizing()) { 8081cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 8091cb0ef41Sopenharmony_ci if (!info->IsWasm()) return; 8101cb0ef41Sopenharmony_ci#else 8111cb0ef41Sopenharmony_ci return; 8121cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 8131cb0ef41Sopenharmony_ci } 8141cb0ef41Sopenharmony_ci std::ostringstream buffer; 8151cb0ef41Sopenharmony_ci buffer << "-- "; 8161cb0ef41Sopenharmony_ci // Turbolizer only needs the source position, as it can reconstruct 8171cb0ef41Sopenharmony_ci // the inlining stack from other information. 8181cb0ef41Sopenharmony_ci if (info->trace_turbo_json() || !tasm()->isolate() || 8191cb0ef41Sopenharmony_ci tasm()->isolate()->concurrent_recompilation_enabled()) { 8201cb0ef41Sopenharmony_ci buffer << source_position; 8211cb0ef41Sopenharmony_ci } else { 8221cb0ef41Sopenharmony_ci AllowGarbageCollection allocation; 8231cb0ef41Sopenharmony_ci AllowHandleAllocation handles; 8241cb0ef41Sopenharmony_ci AllowHandleDereference deref; 8251cb0ef41Sopenharmony_ci buffer << source_position.InliningStack(info); 8261cb0ef41Sopenharmony_ci } 8271cb0ef41Sopenharmony_ci buffer << " --"; 8281cb0ef41Sopenharmony_ci tasm()->RecordComment(buffer.str().c_str()); 8291cb0ef41Sopenharmony_ci } 8301cb0ef41Sopenharmony_ci} 8311cb0ef41Sopenharmony_ci 8321cb0ef41Sopenharmony_cibool CodeGenerator::GetSlotAboveSPBeforeTailCall(Instruction* instr, 8331cb0ef41Sopenharmony_ci int* slot) { 8341cb0ef41Sopenharmony_ci if (instr->IsTailCall()) { 8351cb0ef41Sopenharmony_ci InstructionOperandConverter g(this, instr); 8361cb0ef41Sopenharmony_ci *slot = g.InputInt32(instr->InputCount() - 1); 8371cb0ef41Sopenharmony_ci return true; 8381cb0ef41Sopenharmony_ci } else { 8391cb0ef41Sopenharmony_ci return false; 8401cb0ef41Sopenharmony_ci } 8411cb0ef41Sopenharmony_ci} 8421cb0ef41Sopenharmony_ci 8431cb0ef41Sopenharmony_ciStubCallMode CodeGenerator::DetermineStubCallMode() const { 8441cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 8451cb0ef41Sopenharmony_ci CodeKind code_kind = info()->code_kind(); 8461cb0ef41Sopenharmony_ci if (code_kind == CodeKind::WASM_FUNCTION || 8471cb0ef41Sopenharmony_ci code_kind == CodeKind::WASM_TO_CAPI_FUNCTION || 8481cb0ef41Sopenharmony_ci code_kind == CodeKind::WASM_TO_JS_FUNCTION) { 8491cb0ef41Sopenharmony_ci return StubCallMode::kCallWasmRuntimeStub; 8501cb0ef41Sopenharmony_ci } 8511cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 8521cb0ef41Sopenharmony_ci return StubCallMode::kCallCodeObject; 8531cb0ef41Sopenharmony_ci} 8541cb0ef41Sopenharmony_ci 8551cb0ef41Sopenharmony_civoid CodeGenerator::AssembleGaps(Instruction* instr) { 8561cb0ef41Sopenharmony_ci for (int i = Instruction::FIRST_GAP_POSITION; 8571cb0ef41Sopenharmony_ci i <= Instruction::LAST_GAP_POSITION; i++) { 8581cb0ef41Sopenharmony_ci Instruction::GapPosition inner_pos = 8591cb0ef41Sopenharmony_ci static_cast<Instruction::GapPosition>(i); 8601cb0ef41Sopenharmony_ci ParallelMove* move = instr->GetParallelMove(inner_pos); 8611cb0ef41Sopenharmony_ci if (move != nullptr) resolver()->Resolve(move); 8621cb0ef41Sopenharmony_ci } 8631cb0ef41Sopenharmony_ci} 8641cb0ef41Sopenharmony_ci 8651cb0ef41Sopenharmony_cinamespace { 8661cb0ef41Sopenharmony_ci 8671cb0ef41Sopenharmony_ciHandle<PodArray<InliningPosition>> CreateInliningPositions( 8681cb0ef41Sopenharmony_ci OptimizedCompilationInfo* info, Isolate* isolate) { 8691cb0ef41Sopenharmony_ci const OptimizedCompilationInfo::InlinedFunctionList& inlined_functions = 8701cb0ef41Sopenharmony_ci info->inlined_functions(); 8711cb0ef41Sopenharmony_ci Handle<PodArray<InliningPosition>> inl_positions = 8721cb0ef41Sopenharmony_ci PodArray<InliningPosition>::New( 8731cb0ef41Sopenharmony_ci isolate, static_cast<int>(inlined_functions.size()), 8741cb0ef41Sopenharmony_ci AllocationType::kOld); 8751cb0ef41Sopenharmony_ci for (size_t i = 0; i < inlined_functions.size(); ++i) { 8761cb0ef41Sopenharmony_ci inl_positions->set(static_cast<int>(i), inlined_functions[i].position); 8771cb0ef41Sopenharmony_ci } 8781cb0ef41Sopenharmony_ci return inl_positions; 8791cb0ef41Sopenharmony_ci} 8801cb0ef41Sopenharmony_ci 8811cb0ef41Sopenharmony_ci} // namespace 8821cb0ef41Sopenharmony_ci 8831cb0ef41Sopenharmony_ciHandle<DeoptimizationData> CodeGenerator::GenerateDeoptimizationData() { 8841cb0ef41Sopenharmony_ci OptimizedCompilationInfo* info = this->info(); 8851cb0ef41Sopenharmony_ci int deopt_count = static_cast<int>(deoptimization_exits_.size()); 8861cb0ef41Sopenharmony_ci if (deopt_count == 0 && !info->is_osr()) { 8871cb0ef41Sopenharmony_ci return DeoptimizationData::Empty(isolate()); 8881cb0ef41Sopenharmony_ci } 8891cb0ef41Sopenharmony_ci Handle<DeoptimizationData> data = 8901cb0ef41Sopenharmony_ci DeoptimizationData::New(isolate(), deopt_count, AllocationType::kOld); 8911cb0ef41Sopenharmony_ci 8921cb0ef41Sopenharmony_ci Handle<TranslationArray> translation_array = 8931cb0ef41Sopenharmony_ci translations_.ToTranslationArray(isolate()->factory()); 8941cb0ef41Sopenharmony_ci 8951cb0ef41Sopenharmony_ci data->SetTranslationByteArray(*translation_array); 8961cb0ef41Sopenharmony_ci data->SetInlinedFunctionCount( 8971cb0ef41Sopenharmony_ci Smi::FromInt(static_cast<int>(inlined_function_count_))); 8981cb0ef41Sopenharmony_ci data->SetOptimizationId(Smi::FromInt(info->optimization_id())); 8991cb0ef41Sopenharmony_ci 9001cb0ef41Sopenharmony_ci data->SetDeoptExitStart(Smi::FromInt(deopt_exit_start_offset_)); 9011cb0ef41Sopenharmony_ci data->SetEagerDeoptCount(Smi::FromInt(eager_deopt_count_)); 9021cb0ef41Sopenharmony_ci data->SetLazyDeoptCount(Smi::FromInt(lazy_deopt_count_)); 9031cb0ef41Sopenharmony_ci 9041cb0ef41Sopenharmony_ci if (info->has_shared_info()) { 9051cb0ef41Sopenharmony_ci data->SetSharedFunctionInfo(*info->shared_info()); 9061cb0ef41Sopenharmony_ci } else { 9071cb0ef41Sopenharmony_ci data->SetSharedFunctionInfo(Smi::zero()); 9081cb0ef41Sopenharmony_ci } 9091cb0ef41Sopenharmony_ci 9101cb0ef41Sopenharmony_ci Handle<DeoptimizationLiteralArray> literals = 9111cb0ef41Sopenharmony_ci isolate()->factory()->NewDeoptimizationLiteralArray( 9121cb0ef41Sopenharmony_ci static_cast<int>(deoptimization_literals_.size())); 9131cb0ef41Sopenharmony_ci for (unsigned i = 0; i < deoptimization_literals_.size(); i++) { 9141cb0ef41Sopenharmony_ci Handle<Object> object = deoptimization_literals_[i].Reify(isolate()); 9151cb0ef41Sopenharmony_ci CHECK(!object.is_null()); 9161cb0ef41Sopenharmony_ci literals->set(i, *object); 9171cb0ef41Sopenharmony_ci } 9181cb0ef41Sopenharmony_ci data->SetLiteralArray(*literals); 9191cb0ef41Sopenharmony_ci 9201cb0ef41Sopenharmony_ci Handle<PodArray<InliningPosition>> inl_pos = 9211cb0ef41Sopenharmony_ci CreateInliningPositions(info, isolate()); 9221cb0ef41Sopenharmony_ci data->SetInliningPositions(*inl_pos); 9231cb0ef41Sopenharmony_ci 9241cb0ef41Sopenharmony_ci if (info->is_osr()) { 9251cb0ef41Sopenharmony_ci DCHECK_LE(0, osr_pc_offset_); 9261cb0ef41Sopenharmony_ci data->SetOsrBytecodeOffset(Smi::FromInt(info_->osr_offset().ToInt())); 9271cb0ef41Sopenharmony_ci data->SetOsrPcOffset(Smi::FromInt(osr_pc_offset_)); 9281cb0ef41Sopenharmony_ci } else { 9291cb0ef41Sopenharmony_ci BytecodeOffset osr_offset = BytecodeOffset::None(); 9301cb0ef41Sopenharmony_ci data->SetOsrBytecodeOffset(Smi::FromInt(osr_offset.ToInt())); 9311cb0ef41Sopenharmony_ci data->SetOsrPcOffset(Smi::FromInt(-1)); 9321cb0ef41Sopenharmony_ci } 9331cb0ef41Sopenharmony_ci 9341cb0ef41Sopenharmony_ci // Populate deoptimization entries. 9351cb0ef41Sopenharmony_ci for (int i = 0; i < deopt_count; i++) { 9361cb0ef41Sopenharmony_ci DeoptimizationExit* deoptimization_exit = deoptimization_exits_[i]; 9371cb0ef41Sopenharmony_ci CHECK_NOT_NULL(deoptimization_exit); 9381cb0ef41Sopenharmony_ci DCHECK_EQ(i, deoptimization_exit->deoptimization_id()); 9391cb0ef41Sopenharmony_ci data->SetBytecodeOffset(i, deoptimization_exit->bailout_id()); 9401cb0ef41Sopenharmony_ci data->SetTranslationIndex( 9411cb0ef41Sopenharmony_ci i, Smi::FromInt(deoptimization_exit->translation_id())); 9421cb0ef41Sopenharmony_ci data->SetPc(i, Smi::FromInt(deoptimization_exit->pc_offset())); 9431cb0ef41Sopenharmony_ci#ifdef DEBUG 9441cb0ef41Sopenharmony_ci data->SetNodeId(i, Smi::FromInt(deoptimization_exit->node_id())); 9451cb0ef41Sopenharmony_ci#endif // DEBUG 9461cb0ef41Sopenharmony_ci } 9471cb0ef41Sopenharmony_ci 9481cb0ef41Sopenharmony_ci return data; 9491cb0ef41Sopenharmony_ci} 9501cb0ef41Sopenharmony_ci 9511cb0ef41Sopenharmony_ciLabel* CodeGenerator::AddJumpTable(Label** targets, size_t target_count) { 9521cb0ef41Sopenharmony_ci jump_tables_ = zone()->New<JumpTable>(jump_tables_, targets, target_count); 9531cb0ef41Sopenharmony_ci return jump_tables_->label(); 9541cb0ef41Sopenharmony_ci} 9551cb0ef41Sopenharmony_ci 9561cb0ef41Sopenharmony_civoid CodeGenerator::RecordCallPosition(Instruction* instr) { 9571cb0ef41Sopenharmony_ci const bool needs_frame_state = 9581cb0ef41Sopenharmony_ci instr->HasCallDescriptorFlag(CallDescriptor::kNeedsFrameState); 9591cb0ef41Sopenharmony_ci RecordSafepoint(instr->reference_map()); 9601cb0ef41Sopenharmony_ci 9611cb0ef41Sopenharmony_ci if (instr->HasCallDescriptorFlag(CallDescriptor::kHasExceptionHandler)) { 9621cb0ef41Sopenharmony_ci InstructionOperandConverter i(this, instr); 9631cb0ef41Sopenharmony_ci RpoNumber handler_rpo = i.InputRpo(instr->InputCount() - 1); 9641cb0ef41Sopenharmony_ci DCHECK(instructions()->InstructionBlockAt(handler_rpo)->IsHandler()); 9651cb0ef41Sopenharmony_ci handlers_.push_back( 9661cb0ef41Sopenharmony_ci {GetLabel(handler_rpo), tasm()->pc_offset_for_safepoint()}); 9671cb0ef41Sopenharmony_ci } 9681cb0ef41Sopenharmony_ci 9691cb0ef41Sopenharmony_ci if (needs_frame_state) { 9701cb0ef41Sopenharmony_ci MarkLazyDeoptSite(); 9711cb0ef41Sopenharmony_ci // If the frame state is present, it starts at argument 1 - after 9721cb0ef41Sopenharmony_ci // the code address. 9731cb0ef41Sopenharmony_ci size_t frame_state_offset = 1; 9741cb0ef41Sopenharmony_ci FrameStateDescriptor* descriptor = 9751cb0ef41Sopenharmony_ci GetDeoptimizationEntry(instr, frame_state_offset).descriptor(); 9761cb0ef41Sopenharmony_ci int pc_offset = tasm()->pc_offset_for_safepoint(); 9771cb0ef41Sopenharmony_ci BuildTranslation(instr, pc_offset, frame_state_offset, 0, 9781cb0ef41Sopenharmony_ci descriptor->state_combine()); 9791cb0ef41Sopenharmony_ci } 9801cb0ef41Sopenharmony_ci} 9811cb0ef41Sopenharmony_ci 9821cb0ef41Sopenharmony_ciint CodeGenerator::DefineDeoptimizationLiteral(DeoptimizationLiteral literal) { 9831cb0ef41Sopenharmony_ci literal.Validate(); 9841cb0ef41Sopenharmony_ci int result = static_cast<int>(deoptimization_literals_.size()); 9851cb0ef41Sopenharmony_ci for (unsigned i = 0; i < deoptimization_literals_.size(); ++i) { 9861cb0ef41Sopenharmony_ci deoptimization_literals_[i].Validate(); 9871cb0ef41Sopenharmony_ci if (deoptimization_literals_[i] == literal) return i; 9881cb0ef41Sopenharmony_ci } 9891cb0ef41Sopenharmony_ci deoptimization_literals_.push_back(literal); 9901cb0ef41Sopenharmony_ci return result; 9911cb0ef41Sopenharmony_ci} 9921cb0ef41Sopenharmony_ci 9931cb0ef41Sopenharmony_ciDeoptimizationEntry const& CodeGenerator::GetDeoptimizationEntry( 9941cb0ef41Sopenharmony_ci Instruction* instr, size_t frame_state_offset) { 9951cb0ef41Sopenharmony_ci InstructionOperandConverter i(this, instr); 9961cb0ef41Sopenharmony_ci int const state_id = i.InputInt32(frame_state_offset); 9971cb0ef41Sopenharmony_ci return instructions()->GetDeoptimizationEntry(state_id); 9981cb0ef41Sopenharmony_ci} 9991cb0ef41Sopenharmony_ci 10001cb0ef41Sopenharmony_civoid CodeGenerator::TranslateStateValueDescriptor( 10011cb0ef41Sopenharmony_ci StateValueDescriptor* desc, StateValueList* nested, 10021cb0ef41Sopenharmony_ci InstructionOperandIterator* iter) { 10031cb0ef41Sopenharmony_ci if (desc->IsNested()) { 10041cb0ef41Sopenharmony_ci translations_.BeginCapturedObject(static_cast<int>(nested->size())); 10051cb0ef41Sopenharmony_ci for (auto field : *nested) { 10061cb0ef41Sopenharmony_ci TranslateStateValueDescriptor(field.desc, field.nested, iter); 10071cb0ef41Sopenharmony_ci } 10081cb0ef41Sopenharmony_ci } else if (desc->IsArgumentsElements()) { 10091cb0ef41Sopenharmony_ci translations_.ArgumentsElements(desc->arguments_type()); 10101cb0ef41Sopenharmony_ci } else if (desc->IsArgumentsLength()) { 10111cb0ef41Sopenharmony_ci translations_.ArgumentsLength(); 10121cb0ef41Sopenharmony_ci } else if (desc->IsDuplicate()) { 10131cb0ef41Sopenharmony_ci translations_.DuplicateObject(static_cast<int>(desc->id())); 10141cb0ef41Sopenharmony_ci } else if (desc->IsPlain()) { 10151cb0ef41Sopenharmony_ci InstructionOperand* op = iter->Advance(); 10161cb0ef41Sopenharmony_ci AddTranslationForOperand(iter->instruction(), op, desc->type()); 10171cb0ef41Sopenharmony_ci } else { 10181cb0ef41Sopenharmony_ci DCHECK(desc->IsOptimizedOut()); 10191cb0ef41Sopenharmony_ci if (optimized_out_literal_id_ == -1) { 10201cb0ef41Sopenharmony_ci optimized_out_literal_id_ = DefineDeoptimizationLiteral( 10211cb0ef41Sopenharmony_ci DeoptimizationLiteral(isolate()->factory()->optimized_out())); 10221cb0ef41Sopenharmony_ci } 10231cb0ef41Sopenharmony_ci translations_.StoreLiteral(optimized_out_literal_id_); 10241cb0ef41Sopenharmony_ci } 10251cb0ef41Sopenharmony_ci} 10261cb0ef41Sopenharmony_ci 10271cb0ef41Sopenharmony_civoid CodeGenerator::TranslateFrameStateDescriptorOperands( 10281cb0ef41Sopenharmony_ci FrameStateDescriptor* desc, InstructionOperandIterator* iter) { 10291cb0ef41Sopenharmony_ci size_t index = 0; 10301cb0ef41Sopenharmony_ci StateValueList* values = desc->GetStateValueDescriptors(); 10311cb0ef41Sopenharmony_ci for (StateValueList::iterator it = values->begin(); it != values->end(); 10321cb0ef41Sopenharmony_ci ++it, ++index) { 10331cb0ef41Sopenharmony_ci TranslateStateValueDescriptor((*it).desc, (*it).nested, iter); 10341cb0ef41Sopenharmony_ci } 10351cb0ef41Sopenharmony_ci DCHECK_EQ(desc->GetSize(), index); 10361cb0ef41Sopenharmony_ci} 10371cb0ef41Sopenharmony_ci 10381cb0ef41Sopenharmony_civoid CodeGenerator::BuildTranslationForFrameStateDescriptor( 10391cb0ef41Sopenharmony_ci FrameStateDescriptor* descriptor, InstructionOperandIterator* iter, 10401cb0ef41Sopenharmony_ci OutputFrameStateCombine state_combine) { 10411cb0ef41Sopenharmony_ci // Outer-most state must be added to translation first. 10421cb0ef41Sopenharmony_ci if (descriptor->outer_state() != nullptr) { 10431cb0ef41Sopenharmony_ci BuildTranslationForFrameStateDescriptor(descriptor->outer_state(), iter, 10441cb0ef41Sopenharmony_ci state_combine); 10451cb0ef41Sopenharmony_ci } 10461cb0ef41Sopenharmony_ci 10471cb0ef41Sopenharmony_ci Handle<SharedFunctionInfo> shared_info; 10481cb0ef41Sopenharmony_ci if (!descriptor->shared_info().ToHandle(&shared_info)) { 10491cb0ef41Sopenharmony_ci if (!info()->has_shared_info()) { 10501cb0ef41Sopenharmony_ci return; // Stub with no SharedFunctionInfo. 10511cb0ef41Sopenharmony_ci } 10521cb0ef41Sopenharmony_ci shared_info = info()->shared_info(); 10531cb0ef41Sopenharmony_ci } 10541cb0ef41Sopenharmony_ci 10551cb0ef41Sopenharmony_ci const BytecodeOffset bailout_id = descriptor->bailout_id(); 10561cb0ef41Sopenharmony_ci const int shared_info_id = 10571cb0ef41Sopenharmony_ci DefineDeoptimizationLiteral(DeoptimizationLiteral(shared_info)); 10581cb0ef41Sopenharmony_ci const unsigned int height = 10591cb0ef41Sopenharmony_ci static_cast<unsigned int>(descriptor->GetHeight()); 10601cb0ef41Sopenharmony_ci 10611cb0ef41Sopenharmony_ci switch (descriptor->type()) { 10621cb0ef41Sopenharmony_ci case FrameStateType::kUnoptimizedFunction: { 10631cb0ef41Sopenharmony_ci int return_offset = 0; 10641cb0ef41Sopenharmony_ci int return_count = 0; 10651cb0ef41Sopenharmony_ci if (!state_combine.IsOutputIgnored()) { 10661cb0ef41Sopenharmony_ci return_offset = static_cast<int>(state_combine.GetOffsetToPokeAt()); 10671cb0ef41Sopenharmony_ci return_count = static_cast<int>(iter->instruction()->OutputCount()); 10681cb0ef41Sopenharmony_ci } 10691cb0ef41Sopenharmony_ci translations_.BeginInterpretedFrame(bailout_id, shared_info_id, height, 10701cb0ef41Sopenharmony_ci return_offset, return_count); 10711cb0ef41Sopenharmony_ci break; 10721cb0ef41Sopenharmony_ci } 10731cb0ef41Sopenharmony_ci case FrameStateType::kArgumentsAdaptor: 10741cb0ef41Sopenharmony_ci translations_.BeginArgumentsAdaptorFrame(shared_info_id, height); 10751cb0ef41Sopenharmony_ci break; 10761cb0ef41Sopenharmony_ci case FrameStateType::kConstructStub: 10771cb0ef41Sopenharmony_ci DCHECK(bailout_id.IsValidForConstructStub()); 10781cb0ef41Sopenharmony_ci translations_.BeginConstructStubFrame(bailout_id, shared_info_id, height); 10791cb0ef41Sopenharmony_ci break; 10801cb0ef41Sopenharmony_ci case FrameStateType::kBuiltinContinuation: { 10811cb0ef41Sopenharmony_ci translations_.BeginBuiltinContinuationFrame(bailout_id, shared_info_id, 10821cb0ef41Sopenharmony_ci height); 10831cb0ef41Sopenharmony_ci break; 10841cb0ef41Sopenharmony_ci } 10851cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 10861cb0ef41Sopenharmony_ci case FrameStateType::kJSToWasmBuiltinContinuation: { 10871cb0ef41Sopenharmony_ci const JSToWasmFrameStateDescriptor* js_to_wasm_descriptor = 10881cb0ef41Sopenharmony_ci static_cast<const JSToWasmFrameStateDescriptor*>(descriptor); 10891cb0ef41Sopenharmony_ci translations_.BeginJSToWasmBuiltinContinuationFrame( 10901cb0ef41Sopenharmony_ci bailout_id, shared_info_id, height, 10911cb0ef41Sopenharmony_ci js_to_wasm_descriptor->return_kind()); 10921cb0ef41Sopenharmony_ci break; 10931cb0ef41Sopenharmony_ci } 10941cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 10951cb0ef41Sopenharmony_ci case FrameStateType::kJavaScriptBuiltinContinuation: { 10961cb0ef41Sopenharmony_ci translations_.BeginJavaScriptBuiltinContinuationFrame( 10971cb0ef41Sopenharmony_ci bailout_id, shared_info_id, height); 10981cb0ef41Sopenharmony_ci break; 10991cb0ef41Sopenharmony_ci } 11001cb0ef41Sopenharmony_ci case FrameStateType::kJavaScriptBuiltinContinuationWithCatch: { 11011cb0ef41Sopenharmony_ci translations_.BeginJavaScriptBuiltinContinuationWithCatchFrame( 11021cb0ef41Sopenharmony_ci bailout_id, shared_info_id, height); 11031cb0ef41Sopenharmony_ci break; 11041cb0ef41Sopenharmony_ci } 11051cb0ef41Sopenharmony_ci } 11061cb0ef41Sopenharmony_ci 11071cb0ef41Sopenharmony_ci TranslateFrameStateDescriptorOperands(descriptor, iter); 11081cb0ef41Sopenharmony_ci} 11091cb0ef41Sopenharmony_ci 11101cb0ef41Sopenharmony_ciDeoptimizationExit* CodeGenerator::BuildTranslation( 11111cb0ef41Sopenharmony_ci Instruction* instr, int pc_offset, size_t frame_state_offset, 11121cb0ef41Sopenharmony_ci size_t immediate_args_count, OutputFrameStateCombine state_combine) { 11131cb0ef41Sopenharmony_ci DeoptimizationEntry const& entry = 11141cb0ef41Sopenharmony_ci GetDeoptimizationEntry(instr, frame_state_offset); 11151cb0ef41Sopenharmony_ci FrameStateDescriptor* const descriptor = entry.descriptor(); 11161cb0ef41Sopenharmony_ci frame_state_offset++; 11171cb0ef41Sopenharmony_ci 11181cb0ef41Sopenharmony_ci const int update_feedback_count = entry.feedback().IsValid() ? 1 : 0; 11191cb0ef41Sopenharmony_ci const int translation_index = translations_.BeginTranslation( 11201cb0ef41Sopenharmony_ci static_cast<int>(descriptor->GetFrameCount()), 11211cb0ef41Sopenharmony_ci static_cast<int>(descriptor->GetJSFrameCount()), update_feedback_count); 11221cb0ef41Sopenharmony_ci if (entry.feedback().IsValid()) { 11231cb0ef41Sopenharmony_ci DeoptimizationLiteral literal = 11241cb0ef41Sopenharmony_ci DeoptimizationLiteral(entry.feedback().vector); 11251cb0ef41Sopenharmony_ci int literal_id = DefineDeoptimizationLiteral(literal); 11261cb0ef41Sopenharmony_ci translations_.AddUpdateFeedback(literal_id, entry.feedback().slot.ToInt()); 11271cb0ef41Sopenharmony_ci } 11281cb0ef41Sopenharmony_ci InstructionOperandIterator iter(instr, frame_state_offset); 11291cb0ef41Sopenharmony_ci BuildTranslationForFrameStateDescriptor(descriptor, &iter, state_combine); 11301cb0ef41Sopenharmony_ci 11311cb0ef41Sopenharmony_ci DeoptimizationExit* const exit = zone()->New<DeoptimizationExit>( 11321cb0ef41Sopenharmony_ci current_source_position_, descriptor->bailout_id(), translation_index, 11331cb0ef41Sopenharmony_ci pc_offset, entry.kind(), entry.reason(), 11341cb0ef41Sopenharmony_ci#ifdef DEBUG 11351cb0ef41Sopenharmony_ci entry.node_id()); 11361cb0ef41Sopenharmony_ci#else // DEBUG 11371cb0ef41Sopenharmony_ci 0); 11381cb0ef41Sopenharmony_ci#endif // DEBUG 11391cb0ef41Sopenharmony_ci if (immediate_args_count != 0) { 11401cb0ef41Sopenharmony_ci auto immediate_args = zone()->New<ZoneVector<ImmediateOperand*>>(zone()); 11411cb0ef41Sopenharmony_ci InstructionOperandIterator imm_iter( 11421cb0ef41Sopenharmony_ci instr, frame_state_offset - immediate_args_count - 1); 11431cb0ef41Sopenharmony_ci for (size_t i = 0; i < immediate_args_count; i++) { 11441cb0ef41Sopenharmony_ci immediate_args->emplace_back(ImmediateOperand::cast(imm_iter.Advance())); 11451cb0ef41Sopenharmony_ci } 11461cb0ef41Sopenharmony_ci exit->set_immediate_args(immediate_args); 11471cb0ef41Sopenharmony_ci } 11481cb0ef41Sopenharmony_ci 11491cb0ef41Sopenharmony_ci deoptimization_exits_.push_back(exit); 11501cb0ef41Sopenharmony_ci return exit; 11511cb0ef41Sopenharmony_ci} 11521cb0ef41Sopenharmony_ci 11531cb0ef41Sopenharmony_civoid CodeGenerator::AddTranslationForOperand(Instruction* instr, 11541cb0ef41Sopenharmony_ci InstructionOperand* op, 11551cb0ef41Sopenharmony_ci MachineType type) { 11561cb0ef41Sopenharmony_ci if (op->IsStackSlot()) { 11571cb0ef41Sopenharmony_ci if (type.representation() == MachineRepresentation::kBit) { 11581cb0ef41Sopenharmony_ci translations_.StoreBoolStackSlot(LocationOperand::cast(op)->index()); 11591cb0ef41Sopenharmony_ci } else if (type == MachineType::Int8() || type == MachineType::Int16() || 11601cb0ef41Sopenharmony_ci type == MachineType::Int32()) { 11611cb0ef41Sopenharmony_ci translations_.StoreInt32StackSlot(LocationOperand::cast(op)->index()); 11621cb0ef41Sopenharmony_ci } else if (type == MachineType::Uint8() || type == MachineType::Uint16() || 11631cb0ef41Sopenharmony_ci type == MachineType::Uint32()) { 11641cb0ef41Sopenharmony_ci translations_.StoreUint32StackSlot(LocationOperand::cast(op)->index()); 11651cb0ef41Sopenharmony_ci } else if (type == MachineType::Int64()) { 11661cb0ef41Sopenharmony_ci translations_.StoreInt64StackSlot(LocationOperand::cast(op)->index()); 11671cb0ef41Sopenharmony_ci } else { 11681cb0ef41Sopenharmony_ci#if defined(V8_COMPRESS_POINTERS) 11691cb0ef41Sopenharmony_ci CHECK(MachineRepresentation::kTagged == type.representation() || 11701cb0ef41Sopenharmony_ci MachineRepresentation::kCompressed == type.representation()); 11711cb0ef41Sopenharmony_ci#else 11721cb0ef41Sopenharmony_ci CHECK(MachineRepresentation::kTagged == type.representation()); 11731cb0ef41Sopenharmony_ci#endif 11741cb0ef41Sopenharmony_ci translations_.StoreStackSlot(LocationOperand::cast(op)->index()); 11751cb0ef41Sopenharmony_ci } 11761cb0ef41Sopenharmony_ci } else if (op->IsFPStackSlot()) { 11771cb0ef41Sopenharmony_ci if (type.representation() == MachineRepresentation::kFloat64) { 11781cb0ef41Sopenharmony_ci translations_.StoreDoubleStackSlot(LocationOperand::cast(op)->index()); 11791cb0ef41Sopenharmony_ci } else { 11801cb0ef41Sopenharmony_ci CHECK_EQ(MachineRepresentation::kFloat32, type.representation()); 11811cb0ef41Sopenharmony_ci translations_.StoreFloatStackSlot(LocationOperand::cast(op)->index()); 11821cb0ef41Sopenharmony_ci } 11831cb0ef41Sopenharmony_ci } else if (op->IsRegister()) { 11841cb0ef41Sopenharmony_ci InstructionOperandConverter converter(this, instr); 11851cb0ef41Sopenharmony_ci if (type.representation() == MachineRepresentation::kBit) { 11861cb0ef41Sopenharmony_ci translations_.StoreBoolRegister(converter.ToRegister(op)); 11871cb0ef41Sopenharmony_ci } else if (type == MachineType::Int8() || type == MachineType::Int16() || 11881cb0ef41Sopenharmony_ci type == MachineType::Int32()) { 11891cb0ef41Sopenharmony_ci translations_.StoreInt32Register(converter.ToRegister(op)); 11901cb0ef41Sopenharmony_ci } else if (type == MachineType::Uint8() || type == MachineType::Uint16() || 11911cb0ef41Sopenharmony_ci type == MachineType::Uint32()) { 11921cb0ef41Sopenharmony_ci translations_.StoreUint32Register(converter.ToRegister(op)); 11931cb0ef41Sopenharmony_ci } else if (type == MachineType::Int64()) { 11941cb0ef41Sopenharmony_ci translations_.StoreInt64Register(converter.ToRegister(op)); 11951cb0ef41Sopenharmony_ci } else { 11961cb0ef41Sopenharmony_ci#if defined(V8_COMPRESS_POINTERS) 11971cb0ef41Sopenharmony_ci CHECK(MachineRepresentation::kTagged == type.representation() || 11981cb0ef41Sopenharmony_ci MachineRepresentation::kCompressed == type.representation()); 11991cb0ef41Sopenharmony_ci#else 12001cb0ef41Sopenharmony_ci CHECK(MachineRepresentation::kTagged == type.representation()); 12011cb0ef41Sopenharmony_ci#endif 12021cb0ef41Sopenharmony_ci translations_.StoreRegister(converter.ToRegister(op)); 12031cb0ef41Sopenharmony_ci } 12041cb0ef41Sopenharmony_ci } else if (op->IsFPRegister()) { 12051cb0ef41Sopenharmony_ci InstructionOperandConverter converter(this, instr); 12061cb0ef41Sopenharmony_ci if (type.representation() == MachineRepresentation::kFloat64) { 12071cb0ef41Sopenharmony_ci translations_.StoreDoubleRegister(converter.ToDoubleRegister(op)); 12081cb0ef41Sopenharmony_ci } else { 12091cb0ef41Sopenharmony_ci CHECK_EQ(MachineRepresentation::kFloat32, type.representation()); 12101cb0ef41Sopenharmony_ci translations_.StoreFloatRegister(converter.ToFloatRegister(op)); 12111cb0ef41Sopenharmony_ci } 12121cb0ef41Sopenharmony_ci } else { 12131cb0ef41Sopenharmony_ci CHECK(op->IsImmediate()); 12141cb0ef41Sopenharmony_ci InstructionOperandConverter converter(this, instr); 12151cb0ef41Sopenharmony_ci Constant constant = converter.ToConstant(op); 12161cb0ef41Sopenharmony_ci DeoptimizationLiteral literal; 12171cb0ef41Sopenharmony_ci switch (constant.type()) { 12181cb0ef41Sopenharmony_ci case Constant::kInt32: 12191cb0ef41Sopenharmony_ci if (type.representation() == MachineRepresentation::kTagged) { 12201cb0ef41Sopenharmony_ci // When pointers are 4 bytes, we can use int32 constants to represent 12211cb0ef41Sopenharmony_ci // Smis. 12221cb0ef41Sopenharmony_ci DCHECK_EQ(4, kSystemPointerSize); 12231cb0ef41Sopenharmony_ci Smi smi(static_cast<Address>(constant.ToInt32())); 12241cb0ef41Sopenharmony_ci DCHECK(smi.IsSmi()); 12251cb0ef41Sopenharmony_ci literal = DeoptimizationLiteral(smi.value()); 12261cb0ef41Sopenharmony_ci } else if (type.representation() == MachineRepresentation::kBit) { 12271cb0ef41Sopenharmony_ci if (constant.ToInt32() == 0) { 12281cb0ef41Sopenharmony_ci literal = 12291cb0ef41Sopenharmony_ci DeoptimizationLiteral(isolate()->factory()->false_value()); 12301cb0ef41Sopenharmony_ci } else { 12311cb0ef41Sopenharmony_ci DCHECK_EQ(1, constant.ToInt32()); 12321cb0ef41Sopenharmony_ci literal = DeoptimizationLiteral(isolate()->factory()->true_value()); 12331cb0ef41Sopenharmony_ci } 12341cb0ef41Sopenharmony_ci } else { 12351cb0ef41Sopenharmony_ci DCHECK(type == MachineType::Int32() || 12361cb0ef41Sopenharmony_ci type == MachineType::Uint32() || 12371cb0ef41Sopenharmony_ci type.representation() == MachineRepresentation::kWord32 || 12381cb0ef41Sopenharmony_ci type.representation() == MachineRepresentation::kNone); 12391cb0ef41Sopenharmony_ci DCHECK(type.representation() != MachineRepresentation::kNone || 12401cb0ef41Sopenharmony_ci constant.ToInt32() == FrameStateDescriptor::kImpossibleValue); 12411cb0ef41Sopenharmony_ci if (type == MachineType::Uint32()) { 12421cb0ef41Sopenharmony_ci literal = DeoptimizationLiteral( 12431cb0ef41Sopenharmony_ci static_cast<uint32_t>(constant.ToInt32())); 12441cb0ef41Sopenharmony_ci } else { 12451cb0ef41Sopenharmony_ci literal = DeoptimizationLiteral(constant.ToInt32()); 12461cb0ef41Sopenharmony_ci } 12471cb0ef41Sopenharmony_ci } 12481cb0ef41Sopenharmony_ci break; 12491cb0ef41Sopenharmony_ci case Constant::kInt64: 12501cb0ef41Sopenharmony_ci DCHECK_EQ(8, kSystemPointerSize); 12511cb0ef41Sopenharmony_ci if (type.representation() == MachineRepresentation::kWord64) { 12521cb0ef41Sopenharmony_ci literal = 12531cb0ef41Sopenharmony_ci DeoptimizationLiteral(static_cast<double>(constant.ToInt64())); 12541cb0ef41Sopenharmony_ci } else { 12551cb0ef41Sopenharmony_ci // When pointers are 8 bytes, we can use int64 constants to represent 12561cb0ef41Sopenharmony_ci // Smis. 12571cb0ef41Sopenharmony_ci DCHECK_EQ(MachineRepresentation::kTagged, type.representation()); 12581cb0ef41Sopenharmony_ci Smi smi(static_cast<Address>(constant.ToInt64())); 12591cb0ef41Sopenharmony_ci DCHECK(smi.IsSmi()); 12601cb0ef41Sopenharmony_ci literal = DeoptimizationLiteral(smi.value()); 12611cb0ef41Sopenharmony_ci } 12621cb0ef41Sopenharmony_ci break; 12631cb0ef41Sopenharmony_ci case Constant::kFloat32: 12641cb0ef41Sopenharmony_ci DCHECK(type.representation() == MachineRepresentation::kFloat32 || 12651cb0ef41Sopenharmony_ci type.representation() == MachineRepresentation::kTagged); 12661cb0ef41Sopenharmony_ci literal = DeoptimizationLiteral(constant.ToFloat32()); 12671cb0ef41Sopenharmony_ci break; 12681cb0ef41Sopenharmony_ci case Constant::kFloat64: 12691cb0ef41Sopenharmony_ci DCHECK(type.representation() == MachineRepresentation::kFloat64 || 12701cb0ef41Sopenharmony_ci type.representation() == MachineRepresentation::kTagged); 12711cb0ef41Sopenharmony_ci literal = DeoptimizationLiteral(constant.ToFloat64().value()); 12721cb0ef41Sopenharmony_ci break; 12731cb0ef41Sopenharmony_ci case Constant::kHeapObject: 12741cb0ef41Sopenharmony_ci DCHECK_EQ(MachineRepresentation::kTagged, type.representation()); 12751cb0ef41Sopenharmony_ci literal = DeoptimizationLiteral(constant.ToHeapObject()); 12761cb0ef41Sopenharmony_ci break; 12771cb0ef41Sopenharmony_ci case Constant::kCompressedHeapObject: 12781cb0ef41Sopenharmony_ci DCHECK_EQ(MachineType::AnyTagged(), type); 12791cb0ef41Sopenharmony_ci literal = DeoptimizationLiteral(constant.ToHeapObject()); 12801cb0ef41Sopenharmony_ci break; 12811cb0ef41Sopenharmony_ci case Constant::kDelayedStringConstant: 12821cb0ef41Sopenharmony_ci DCHECK_EQ(MachineRepresentation::kTagged, type.representation()); 12831cb0ef41Sopenharmony_ci literal = DeoptimizationLiteral(constant.ToDelayedStringConstant()); 12841cb0ef41Sopenharmony_ci break; 12851cb0ef41Sopenharmony_ci default: 12861cb0ef41Sopenharmony_ci UNREACHABLE(); 12871cb0ef41Sopenharmony_ci } 12881cb0ef41Sopenharmony_ci if (literal.object().equals(info()->closure()) && 12891cb0ef41Sopenharmony_ci info()->function_context_specializing()) { 12901cb0ef41Sopenharmony_ci translations_.StoreJSFrameFunction(); 12911cb0ef41Sopenharmony_ci } else { 12921cb0ef41Sopenharmony_ci int literal_id = DefineDeoptimizationLiteral(literal); 12931cb0ef41Sopenharmony_ci translations_.StoreLiteral(literal_id); 12941cb0ef41Sopenharmony_ci } 12951cb0ef41Sopenharmony_ci } 12961cb0ef41Sopenharmony_ci} 12971cb0ef41Sopenharmony_ci 12981cb0ef41Sopenharmony_civoid CodeGenerator::MarkLazyDeoptSite() { 12991cb0ef41Sopenharmony_ci last_lazy_deopt_pc_ = tasm()->pc_offset(); 13001cb0ef41Sopenharmony_ci} 13011cb0ef41Sopenharmony_ci 13021cb0ef41Sopenharmony_ciDeoptimizationExit* CodeGenerator::AddDeoptimizationExit( 13031cb0ef41Sopenharmony_ci Instruction* instr, size_t frame_state_offset, 13041cb0ef41Sopenharmony_ci size_t immediate_args_count) { 13051cb0ef41Sopenharmony_ci return BuildTranslation(instr, -1, frame_state_offset, immediate_args_count, 13061cb0ef41Sopenharmony_ci OutputFrameStateCombine::Ignore()); 13071cb0ef41Sopenharmony_ci} 13081cb0ef41Sopenharmony_ci 13091cb0ef41Sopenharmony_ciOutOfLineCode::OutOfLineCode(CodeGenerator* gen) 13101cb0ef41Sopenharmony_ci : frame_(gen->frame()), tasm_(gen->tasm()), next_(gen->ools_) { 13111cb0ef41Sopenharmony_ci gen->ools_ = this; 13121cb0ef41Sopenharmony_ci} 13131cb0ef41Sopenharmony_ci 13141cb0ef41Sopenharmony_ciOutOfLineCode::~OutOfLineCode() = default; 13151cb0ef41Sopenharmony_ci 13161cb0ef41Sopenharmony_ciHandle<Object> DeoptimizationLiteral::Reify(Isolate* isolate) const { 13171cb0ef41Sopenharmony_ci Validate(); 13181cb0ef41Sopenharmony_ci switch (kind_) { 13191cb0ef41Sopenharmony_ci case DeoptimizationLiteralKind::kObject: { 13201cb0ef41Sopenharmony_ci return object_; 13211cb0ef41Sopenharmony_ci } 13221cb0ef41Sopenharmony_ci case DeoptimizationLiteralKind::kNumber: { 13231cb0ef41Sopenharmony_ci return isolate->factory()->NewNumber(number_); 13241cb0ef41Sopenharmony_ci } 13251cb0ef41Sopenharmony_ci case DeoptimizationLiteralKind::kString: { 13261cb0ef41Sopenharmony_ci return string_->AllocateStringConstant(isolate); 13271cb0ef41Sopenharmony_ci } 13281cb0ef41Sopenharmony_ci case DeoptimizationLiteralKind::kInvalid: { 13291cb0ef41Sopenharmony_ci UNREACHABLE(); 13301cb0ef41Sopenharmony_ci } 13311cb0ef41Sopenharmony_ci } 13321cb0ef41Sopenharmony_ci UNREACHABLE(); 13331cb0ef41Sopenharmony_ci} 13341cb0ef41Sopenharmony_ci 13351cb0ef41Sopenharmony_ci} // namespace compiler 13361cb0ef41Sopenharmony_ci} // namespace internal 13371cb0ef41Sopenharmony_ci} // namespace v8 1338