11cb0ef41Sopenharmony_ci// Copyright (c) 1994-2006 Sun Microsystems Inc. 21cb0ef41Sopenharmony_ci// All Rights Reserved. 31cb0ef41Sopenharmony_ci// 41cb0ef41Sopenharmony_ci// Redistribution and use in source and binary forms, with or without 51cb0ef41Sopenharmony_ci// modification, are permitted provided that the following conditions are 61cb0ef41Sopenharmony_ci// met: 71cb0ef41Sopenharmony_ci// 81cb0ef41Sopenharmony_ci// - Redistributions of source code must retain the above copyright notice, 91cb0ef41Sopenharmony_ci// this list of conditions and the following disclaimer. 101cb0ef41Sopenharmony_ci// 111cb0ef41Sopenharmony_ci// - Redistribution in binary form must reproduce the above copyright 121cb0ef41Sopenharmony_ci// notice, this list of conditions and the following disclaimer in the 131cb0ef41Sopenharmony_ci// documentation and/or other materials provided with the distribution. 141cb0ef41Sopenharmony_ci// 151cb0ef41Sopenharmony_ci// - Neither the name of Sun Microsystems or the names of contributors may 161cb0ef41Sopenharmony_ci// be used to endorse or promote products derived from this software without 171cb0ef41Sopenharmony_ci// specific prior written permission. 181cb0ef41Sopenharmony_ci// 191cb0ef41Sopenharmony_ci// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 201cb0ef41Sopenharmony_ci// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 211cb0ef41Sopenharmony_ci// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 221cb0ef41Sopenharmony_ci// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 231cb0ef41Sopenharmony_ci// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 241cb0ef41Sopenharmony_ci// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 251cb0ef41Sopenharmony_ci// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 261cb0ef41Sopenharmony_ci// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 271cb0ef41Sopenharmony_ci// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 281cb0ef41Sopenharmony_ci// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 291cb0ef41Sopenharmony_ci// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ci// The original source code covered by the above license above has been 321cb0ef41Sopenharmony_ci// modified significantly by Google Inc. 331cb0ef41Sopenharmony_ci// Copyright 2012 the V8 project authors. All rights reserved. 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci#ifndef V8_CODEGEN_ASSEMBLER_H_ 361cb0ef41Sopenharmony_ci#define V8_CODEGEN_ASSEMBLER_H_ 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_ci#include <forward_list> 391cb0ef41Sopenharmony_ci#include <memory> 401cb0ef41Sopenharmony_ci#include <unordered_map> 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ci#include "src/base/macros.h" 431cb0ef41Sopenharmony_ci#include "src/base/memory.h" 441cb0ef41Sopenharmony_ci#include "src/codegen/code-comments.h" 451cb0ef41Sopenharmony_ci#include "src/codegen/cpu-features.h" 461cb0ef41Sopenharmony_ci#include "src/codegen/external-reference.h" 471cb0ef41Sopenharmony_ci#include "src/codegen/reglist.h" 481cb0ef41Sopenharmony_ci#include "src/codegen/reloc-info.h" 491cb0ef41Sopenharmony_ci#include "src/common/globals.h" 501cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimize-reason.h" 511cb0ef41Sopenharmony_ci#include "src/flags/flags.h" 521cb0ef41Sopenharmony_ci#include "src/handles/handles.h" 531cb0ef41Sopenharmony_ci#include "src/objects/objects.h" 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_cinamespace v8 { 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci// Forward declarations. 581cb0ef41Sopenharmony_ciclass ApiFunction; 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_cinamespace internal { 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ciusing base::Memory; 631cb0ef41Sopenharmony_ciusing base::ReadUnalignedValue; 641cb0ef41Sopenharmony_ciusing base::WriteUnalignedValue; 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci// Forward declarations. 671cb0ef41Sopenharmony_ciclass EmbeddedData; 681cb0ef41Sopenharmony_ciclass OffHeapInstructionStream; 691cb0ef41Sopenharmony_ciclass Isolate; 701cb0ef41Sopenharmony_ciclass SCTableReference; 711cb0ef41Sopenharmony_ciclass SourcePosition; 721cb0ef41Sopenharmony_ciclass StatsCounter; 731cb0ef41Sopenharmony_ciclass StringConstantBase; 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 761cb0ef41Sopenharmony_ci// Optimization for far-jmp like instructions that can be replaced by shorter. 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ciclass JumpOptimizationInfo { 791cb0ef41Sopenharmony_ci public: 801cb0ef41Sopenharmony_ci bool is_collecting() const { return stage_ == kCollection; } 811cb0ef41Sopenharmony_ci bool is_optimizing() const { return stage_ == kOptimization; } 821cb0ef41Sopenharmony_ci void set_optimizing() { 831cb0ef41Sopenharmony_ci DCHECK(is_optimizable()); 841cb0ef41Sopenharmony_ci stage_ = kOptimization; 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci bool is_optimizable() const { return optimizable_; } 881cb0ef41Sopenharmony_ci void set_optimizable() { 891cb0ef41Sopenharmony_ci DCHECK(is_collecting()); 901cb0ef41Sopenharmony_ci optimizable_ = true; 911cb0ef41Sopenharmony_ci } 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci // Used to verify the instruction sequence is always the same in two stages. 941cb0ef41Sopenharmony_ci size_t hash_code() const { return hash_code_; } 951cb0ef41Sopenharmony_ci void set_hash_code(size_t hash_code) { hash_code_ = hash_code; } 961cb0ef41Sopenharmony_ci 971cb0ef41Sopenharmony_ci std::vector<uint32_t>& farjmp_bitmap() { return farjmp_bitmap_; } 981cb0ef41Sopenharmony_ci 991cb0ef41Sopenharmony_ci private: 1001cb0ef41Sopenharmony_ci enum { kCollection, kOptimization } stage_ = kCollection; 1011cb0ef41Sopenharmony_ci bool optimizable_ = false; 1021cb0ef41Sopenharmony_ci std::vector<uint32_t> farjmp_bitmap_; 1031cb0ef41Sopenharmony_ci size_t hash_code_ = 0u; 1041cb0ef41Sopenharmony_ci}; 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ciclass HeapObjectRequest { 1071cb0ef41Sopenharmony_ci public: 1081cb0ef41Sopenharmony_ci explicit HeapObjectRequest(double heap_number, int offset = -1); 1091cb0ef41Sopenharmony_ci explicit HeapObjectRequest(const StringConstantBase* string, int offset = -1); 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci enum Kind { kHeapNumber, kStringConstant }; 1121cb0ef41Sopenharmony_ci Kind kind() const { return kind_; } 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci double heap_number() const { 1151cb0ef41Sopenharmony_ci DCHECK_EQ(kind(), kHeapNumber); 1161cb0ef41Sopenharmony_ci return value_.heap_number; 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci const StringConstantBase* string() const { 1201cb0ef41Sopenharmony_ci DCHECK_EQ(kind(), kStringConstant); 1211cb0ef41Sopenharmony_ci return value_.string; 1221cb0ef41Sopenharmony_ci } 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci // The code buffer offset at the time of the request. 1251cb0ef41Sopenharmony_ci int offset() const { 1261cb0ef41Sopenharmony_ci DCHECK_GE(offset_, 0); 1271cb0ef41Sopenharmony_ci return offset_; 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci void set_offset(int offset) { 1301cb0ef41Sopenharmony_ci DCHECK_LT(offset_, 0); 1311cb0ef41Sopenharmony_ci offset_ = offset; 1321cb0ef41Sopenharmony_ci DCHECK_GE(offset_, 0); 1331cb0ef41Sopenharmony_ci } 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci private: 1361cb0ef41Sopenharmony_ci Kind kind_; 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci union { 1391cb0ef41Sopenharmony_ci double heap_number; 1401cb0ef41Sopenharmony_ci const StringConstantBase* string; 1411cb0ef41Sopenharmony_ci } value_; 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci int offset_; 1441cb0ef41Sopenharmony_ci}; 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 1471cb0ef41Sopenharmony_ci// Platform independent assembler base class. 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_cienum class CodeObjectRequired { kNo, kYes }; 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_cistruct V8_EXPORT_PRIVATE AssemblerOptions { 1521cb0ef41Sopenharmony_ci // Recording reloc info for external references and off-heap targets is 1531cb0ef41Sopenharmony_ci // needed whenever code is serialized, e.g. into the snapshot or as a Wasm 1541cb0ef41Sopenharmony_ci // module. This flag allows this reloc info to be disabled for code that 1551cb0ef41Sopenharmony_ci // will not survive process destruction. 1561cb0ef41Sopenharmony_ci bool record_reloc_info_for_serialization = true; 1571cb0ef41Sopenharmony_ci // Recording reloc info can be disabled wholesale. This is needed when the 1581cb0ef41Sopenharmony_ci // assembler is used on existing code directly (e.g. JumpTableAssembler) 1591cb0ef41Sopenharmony_ci // without any buffer to hold reloc information. 1601cb0ef41Sopenharmony_ci bool disable_reloc_info_for_patching = false; 1611cb0ef41Sopenharmony_ci // Enables root-relative access to arbitrary untagged addresses (usually 1621cb0ef41Sopenharmony_ci // external references). Only valid if code will not survive the process. 1631cb0ef41Sopenharmony_ci bool enable_root_relative_access = false; 1641cb0ef41Sopenharmony_ci // Enables specific assembler sequences only used for the simulator. 1651cb0ef41Sopenharmony_ci bool enable_simulator_code = false; 1661cb0ef41Sopenharmony_ci // Enables use of isolate-independent constants, indirected through the 1671cb0ef41Sopenharmony_ci // root array. 1681cb0ef41Sopenharmony_ci // (macro assembler feature). 1691cb0ef41Sopenharmony_ci bool isolate_independent_code = false; 1701cb0ef41Sopenharmony_ci // Enables the use of isolate-independent builtins through an off-heap 1711cb0ef41Sopenharmony_ci // trampoline. (macro assembler feature). 1721cb0ef41Sopenharmony_ci bool inline_offheap_trampolines = true; 1731cb0ef41Sopenharmony_ci // Enables generation of pc-relative calls to builtins if the off-heap 1741cb0ef41Sopenharmony_ci // builtins are guaranteed to be within the reach of pc-relative call or jump 1751cb0ef41Sopenharmony_ci // instructions. For example, when the bultins code is re-embedded into the 1761cb0ef41Sopenharmony_ci // code range. 1771cb0ef41Sopenharmony_ci bool short_builtin_calls = false; 1781cb0ef41Sopenharmony_ci // On some platforms, all code is created within a certain address range in 1791cb0ef41Sopenharmony_ci // the process, and the base of this code range is configured here. 1801cb0ef41Sopenharmony_ci Address code_range_base = 0; 1811cb0ef41Sopenharmony_ci // Enable pc-relative calls/jumps on platforms that support it. When setting 1821cb0ef41Sopenharmony_ci // this flag, the code range must be small enough to fit all offsets into 1831cb0ef41Sopenharmony_ci // the instruction immediates. 1841cb0ef41Sopenharmony_ci bool use_pc_relative_calls_and_jumps = false; 1851cb0ef41Sopenharmony_ci // Enables the collection of information useful for the generation of unwind 1861cb0ef41Sopenharmony_ci // info. This is useful in some platform (Win64) where the unwind info depends 1871cb0ef41Sopenharmony_ci // on a function prologue/epilogue. 1881cb0ef41Sopenharmony_ci bool collect_win64_unwind_info = false; 1891cb0ef41Sopenharmony_ci // Whether to emit code comments. 1901cb0ef41Sopenharmony_ci bool emit_code_comments = FLAG_code_comments; 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci static AssemblerOptions Default(Isolate* isolate); 1931cb0ef41Sopenharmony_ci static AssemblerOptions DefaultForOffHeapTrampoline(Isolate* isolate); 1941cb0ef41Sopenharmony_ci}; 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ciclass AssemblerBuffer { 1971cb0ef41Sopenharmony_ci public: 1981cb0ef41Sopenharmony_ci virtual ~AssemblerBuffer() = default; 1991cb0ef41Sopenharmony_ci virtual byte* start() const = 0; 2001cb0ef41Sopenharmony_ci virtual int size() const = 0; 2011cb0ef41Sopenharmony_ci // Return a grown copy of this buffer. The contained data is uninitialized. 2021cb0ef41Sopenharmony_ci // The data in {this} will still be read afterwards (until {this} is 2031cb0ef41Sopenharmony_ci // destructed), but not written. 2041cb0ef41Sopenharmony_ci virtual std::unique_ptr<AssemblerBuffer> Grow(int new_size) 2051cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT = 0; 2061cb0ef41Sopenharmony_ci}; 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci// Allocate an AssemblerBuffer which uses an existing buffer. This buffer cannot 2091cb0ef41Sopenharmony_ci// grow, so it must be large enough for all code emitted by the Assembler. 2101cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE 2111cb0ef41Sopenharmony_cistd::unique_ptr<AssemblerBuffer> ExternalAssemblerBuffer(void* buffer, 2121cb0ef41Sopenharmony_ci int size); 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ci// Allocate a new growable AssemblerBuffer with a given initial size. 2151cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE 2161cb0ef41Sopenharmony_cistd::unique_ptr<AssemblerBuffer> NewAssemblerBuffer(int size); 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE AssemblerBase : public Malloced { 2191cb0ef41Sopenharmony_ci public: 2201cb0ef41Sopenharmony_ci AssemblerBase(const AssemblerOptions& options, 2211cb0ef41Sopenharmony_ci std::unique_ptr<AssemblerBuffer>); 2221cb0ef41Sopenharmony_ci virtual ~AssemblerBase(); 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci const AssemblerOptions& options() const { return options_; } 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci bool predictable_code_size() const { return predictable_code_size_; } 2271cb0ef41Sopenharmony_ci void set_predictable_code_size(bool value) { predictable_code_size_ = value; } 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci uint64_t enabled_cpu_features() const { return enabled_cpu_features_; } 2301cb0ef41Sopenharmony_ci void set_enabled_cpu_features(uint64_t features) { 2311cb0ef41Sopenharmony_ci enabled_cpu_features_ = features; 2321cb0ef41Sopenharmony_ci } 2331cb0ef41Sopenharmony_ci // Features are usually enabled by CpuFeatureScope, which also asserts that 2341cb0ef41Sopenharmony_ci // the features are supported before they are enabled. 2351cb0ef41Sopenharmony_ci // IMPORTANT: IsEnabled() should only be used by DCHECKs. For real feature 2361cb0ef41Sopenharmony_ci // detection, use IsSupported(). 2371cb0ef41Sopenharmony_ci bool IsEnabled(CpuFeature f) { 2381cb0ef41Sopenharmony_ci return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0; 2391cb0ef41Sopenharmony_ci } 2401cb0ef41Sopenharmony_ci void EnableCpuFeature(CpuFeature f) { 2411cb0ef41Sopenharmony_ci enabled_cpu_features_ |= (static_cast<uint64_t>(1) << f); 2421cb0ef41Sopenharmony_ci } 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci bool is_constant_pool_available() const { 2451cb0ef41Sopenharmony_ci if (FLAG_enable_embedded_constant_pool) { 2461cb0ef41Sopenharmony_ci // We need to disable constant pool here for embeded builtins 2471cb0ef41Sopenharmony_ci // because the metadata section is not adjacent to instructions 2481cb0ef41Sopenharmony_ci return constant_pool_available_ && !options().isolate_independent_code; 2491cb0ef41Sopenharmony_ci } else { 2501cb0ef41Sopenharmony_ci // Embedded constant pool not supported on this architecture. 2511cb0ef41Sopenharmony_ci UNREACHABLE(); 2521cb0ef41Sopenharmony_ci } 2531cb0ef41Sopenharmony_ci } 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci JumpOptimizationInfo* jump_optimization_info() { 2561cb0ef41Sopenharmony_ci return jump_optimization_info_; 2571cb0ef41Sopenharmony_ci } 2581cb0ef41Sopenharmony_ci void set_jump_optimization_info(JumpOptimizationInfo* jump_opt) { 2591cb0ef41Sopenharmony_ci jump_optimization_info_ = jump_opt; 2601cb0ef41Sopenharmony_ci } 2611cb0ef41Sopenharmony_ci 2621cb0ef41Sopenharmony_ci void FinalizeJumpOptimizationInfo() {} 2631cb0ef41Sopenharmony_ci 2641cb0ef41Sopenharmony_ci // Overwrite a host NaN with a quiet target NaN. Used by mksnapshot for 2651cb0ef41Sopenharmony_ci // cross-snapshotting. 2661cb0ef41Sopenharmony_ci static void QuietNaN(HeapObject nan) {} 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci int pc_offset() const { return static_cast<int>(pc_ - buffer_start_); } 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_ci int pc_offset_for_safepoint() { 2711cb0ef41Sopenharmony_ci#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) || \ 2721cb0ef41Sopenharmony_ci defined(V8_TARGET_ARCH_LOONG64) 2731cb0ef41Sopenharmony_ci // MIPS and LOONG need to use their own implementation to avoid trampoline's 2741cb0ef41Sopenharmony_ci // influence. 2751cb0ef41Sopenharmony_ci UNREACHABLE(); 2761cb0ef41Sopenharmony_ci#else 2771cb0ef41Sopenharmony_ci return pc_offset(); 2781cb0ef41Sopenharmony_ci#endif 2791cb0ef41Sopenharmony_ci } 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci byte* buffer_start() const { return buffer_->start(); } 2821cb0ef41Sopenharmony_ci int buffer_size() const { return buffer_->size(); } 2831cb0ef41Sopenharmony_ci int instruction_size() const { return pc_offset(); } 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci std::unique_ptr<AssemblerBuffer> ReleaseBuffer() { 2861cb0ef41Sopenharmony_ci std::unique_ptr<AssemblerBuffer> buffer = std::move(buffer_); 2871cb0ef41Sopenharmony_ci DCHECK_NULL(buffer_); 2881cb0ef41Sopenharmony_ci // Reset fields to prevent accidental further modifications of the buffer. 2891cb0ef41Sopenharmony_ci buffer_start_ = nullptr; 2901cb0ef41Sopenharmony_ci pc_ = nullptr; 2911cb0ef41Sopenharmony_ci return buffer; 2921cb0ef41Sopenharmony_ci } 2931cb0ef41Sopenharmony_ci 2941cb0ef41Sopenharmony_ci // This function is called when code generation is aborted, so that 2951cb0ef41Sopenharmony_ci // the assembler could clean up internal data structures. 2961cb0ef41Sopenharmony_ci virtual void AbortedCodeGeneration() {} 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci // Debugging 2991cb0ef41Sopenharmony_ci void Print(Isolate* isolate); 3001cb0ef41Sopenharmony_ci 3011cb0ef41Sopenharmony_ci // Record an inline code comment that can be used by a disassembler. 3021cb0ef41Sopenharmony_ci // Use --code-comments to enable. 3031cb0ef41Sopenharmony_ci V8_INLINE void RecordComment(const char* comment) { 3041cb0ef41Sopenharmony_ci // Set explicit dependency on --code-comments for dead-code elimination in 3051cb0ef41Sopenharmony_ci // release builds. 3061cb0ef41Sopenharmony_ci if (!FLAG_code_comments) return; 3071cb0ef41Sopenharmony_ci if (options().emit_code_comments) { 3081cb0ef41Sopenharmony_ci code_comments_writer_.Add(pc_offset(), std::string(comment)); 3091cb0ef41Sopenharmony_ci } 3101cb0ef41Sopenharmony_ci } 3111cb0ef41Sopenharmony_ci 3121cb0ef41Sopenharmony_ci V8_INLINE void RecordComment(std::string comment) { 3131cb0ef41Sopenharmony_ci // Set explicit dependency on --code-comments for dead-code elimination in 3141cb0ef41Sopenharmony_ci // release builds. 3151cb0ef41Sopenharmony_ci if (!FLAG_code_comments) return; 3161cb0ef41Sopenharmony_ci if (options().emit_code_comments) { 3171cb0ef41Sopenharmony_ci code_comments_writer_.Add(pc_offset(), std::move(comment)); 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci } 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci#ifdef V8_CODE_COMMENTS 3221cb0ef41Sopenharmony_ci class CodeComment { 3231cb0ef41Sopenharmony_ci public: 3241cb0ef41Sopenharmony_ci explicit CodeComment(Assembler* assembler, const std::string& comment) 3251cb0ef41Sopenharmony_ci : assembler_(assembler) { 3261cb0ef41Sopenharmony_ci if (FLAG_code_comments) Open(comment); 3271cb0ef41Sopenharmony_ci } 3281cb0ef41Sopenharmony_ci ~CodeComment() { 3291cb0ef41Sopenharmony_ci if (FLAG_code_comments) Close(); 3301cb0ef41Sopenharmony_ci } 3311cb0ef41Sopenharmony_ci static const int kIndentWidth = 2; 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci private: 3341cb0ef41Sopenharmony_ci int depth() const; 3351cb0ef41Sopenharmony_ci void Open(const std::string& comment); 3361cb0ef41Sopenharmony_ci void Close(); 3371cb0ef41Sopenharmony_ci Assembler* assembler_; 3381cb0ef41Sopenharmony_ci }; 3391cb0ef41Sopenharmony_ci#else // V8_CODE_COMMENTS 3401cb0ef41Sopenharmony_ci class CodeComment { 3411cb0ef41Sopenharmony_ci explicit CodeComment(Assembler* assembler, std::string comment) {} 3421cb0ef41Sopenharmony_ci }; 3431cb0ef41Sopenharmony_ci#endif 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_ci // The minimum buffer size. Should be at least two times the platform-specific 3461cb0ef41Sopenharmony_ci // {Assembler::kGap}. 3471cb0ef41Sopenharmony_ci static constexpr int kMinimalBufferSize = 128; 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci // The default buffer size used if we do not know the final size of the 3501cb0ef41Sopenharmony_ci // generated code. 3511cb0ef41Sopenharmony_ci static constexpr int kDefaultBufferSize = 4 * KB; 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci protected: 3541cb0ef41Sopenharmony_ci // Add 'target' to the {code_targets_} vector, if necessary, and return the 3551cb0ef41Sopenharmony_ci // offset at which it is stored. 3561cb0ef41Sopenharmony_ci int AddCodeTarget(Handle<CodeT> target); 3571cb0ef41Sopenharmony_ci Handle<CodeT> GetCodeTarget(intptr_t code_target_index) const; 3581cb0ef41Sopenharmony_ci 3591cb0ef41Sopenharmony_ci // Add 'object' to the {embedded_objects_} vector and return the index at 3601cb0ef41Sopenharmony_ci // which it is stored. 3611cb0ef41Sopenharmony_ci using EmbeddedObjectIndex = size_t; 3621cb0ef41Sopenharmony_ci EmbeddedObjectIndex AddEmbeddedObject(Handle<HeapObject> object); 3631cb0ef41Sopenharmony_ci Handle<HeapObject> GetEmbeddedObject(EmbeddedObjectIndex index) const; 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci // The buffer into which code and relocation info are generated. 3661cb0ef41Sopenharmony_ci std::unique_ptr<AssemblerBuffer> buffer_; 3671cb0ef41Sopenharmony_ci // Cached from {buffer_->start()}, for faster access. 3681cb0ef41Sopenharmony_ci byte* buffer_start_; 3691cb0ef41Sopenharmony_ci std::forward_list<HeapObjectRequest> heap_object_requests_; 3701cb0ef41Sopenharmony_ci // The program counter, which points into the buffer above and moves forward. 3711cb0ef41Sopenharmony_ci // TODO(jkummerow): This should probably have type {Address}. 3721cb0ef41Sopenharmony_ci byte* pc_; 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci void set_constant_pool_available(bool available) { 3751cb0ef41Sopenharmony_ci if (FLAG_enable_embedded_constant_pool) { 3761cb0ef41Sopenharmony_ci constant_pool_available_ = available; 3771cb0ef41Sopenharmony_ci } else { 3781cb0ef41Sopenharmony_ci // Embedded constant pool not supported on this architecture. 3791cb0ef41Sopenharmony_ci UNREACHABLE(); 3801cb0ef41Sopenharmony_ci } 3811cb0ef41Sopenharmony_ci } 3821cb0ef41Sopenharmony_ci 3831cb0ef41Sopenharmony_ci // {RequestHeapObject} records the need for a future heap number allocation, 3841cb0ef41Sopenharmony_ci // code stub generation or string allocation. After code assembly, each 3851cb0ef41Sopenharmony_ci // platform's {Assembler::AllocateAndInstallRequestedHeapObjects} will 3861cb0ef41Sopenharmony_ci // allocate these objects and place them where they are expected (determined 3871cb0ef41Sopenharmony_ci // by the pc offset associated with each request). 3881cb0ef41Sopenharmony_ci void RequestHeapObject(HeapObjectRequest request); 3891cb0ef41Sopenharmony_ci 3901cb0ef41Sopenharmony_ci bool ShouldRecordRelocInfo(RelocInfo::Mode rmode) const { 3911cb0ef41Sopenharmony_ci DCHECK(!RelocInfo::IsNoInfo(rmode)); 3921cb0ef41Sopenharmony_ci if (options().disable_reloc_info_for_patching) return false; 3931cb0ef41Sopenharmony_ci if (RelocInfo::IsOnlyForSerializer(rmode) && 3941cb0ef41Sopenharmony_ci !options().record_reloc_info_for_serialization && !FLAG_debug_code) { 3951cb0ef41Sopenharmony_ci return false; 3961cb0ef41Sopenharmony_ci } 3971cb0ef41Sopenharmony_ci#ifndef ENABLE_DISASSEMBLER 3981cb0ef41Sopenharmony_ci if (RelocInfo::IsLiteralConstant(rmode)) return false; 3991cb0ef41Sopenharmony_ci#endif 4001cb0ef41Sopenharmony_ci return true; 4011cb0ef41Sopenharmony_ci } 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci CodeCommentsWriter code_comments_writer_; 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci private: 4061cb0ef41Sopenharmony_ci // Before we copy code into the code space, we sometimes cannot encode 4071cb0ef41Sopenharmony_ci // call/jump code targets as we normally would, as the difference between the 4081cb0ef41Sopenharmony_ci // instruction's location in the temporary buffer and the call target is not 4091cb0ef41Sopenharmony_ci // guaranteed to fit in the instruction's offset field. We keep track of the 4101cb0ef41Sopenharmony_ci // code handles we encounter in calls in this vector, and encode the index of 4111cb0ef41Sopenharmony_ci // the code handle in the vector instead. 4121cb0ef41Sopenharmony_ci std::vector<Handle<CodeT>> code_targets_; 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ci // If an assembler needs a small number to refer to a heap object handle 4151cb0ef41Sopenharmony_ci // (for example, because there are only 32bit available on a 64bit arch), the 4161cb0ef41Sopenharmony_ci // assembler adds the object into this vector using AddEmbeddedObject, and 4171cb0ef41Sopenharmony_ci // may then refer to the heap object using the handle's index in this vector. 4181cb0ef41Sopenharmony_ci std::vector<Handle<HeapObject>> embedded_objects_; 4191cb0ef41Sopenharmony_ci 4201cb0ef41Sopenharmony_ci // Embedded objects are deduplicated based on handle location. This is a 4211cb0ef41Sopenharmony_ci // compromise that is almost as effective as deduplication based on actual 4221cb0ef41Sopenharmony_ci // heap object addresses maintains GC safety. 4231cb0ef41Sopenharmony_ci std::unordered_map<Handle<HeapObject>, EmbeddedObjectIndex, 4241cb0ef41Sopenharmony_ci Handle<HeapObject>::hash, Handle<HeapObject>::equal_to> 4251cb0ef41Sopenharmony_ci embedded_objects_map_; 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_ci const AssemblerOptions options_; 4281cb0ef41Sopenharmony_ci uint64_t enabled_cpu_features_; 4291cb0ef41Sopenharmony_ci bool predictable_code_size_; 4301cb0ef41Sopenharmony_ci 4311cb0ef41Sopenharmony_ci // Indicates whether the constant pool can be accessed, which is only possible 4321cb0ef41Sopenharmony_ci // if the pp register points to the current code object's constant pool. 4331cb0ef41Sopenharmony_ci bool constant_pool_available_; 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci JumpOptimizationInfo* jump_optimization_info_; 4361cb0ef41Sopenharmony_ci 4371cb0ef41Sopenharmony_ci#ifdef V8_CODE_COMMENTS 4381cb0ef41Sopenharmony_ci int comment_depth_ = 0; 4391cb0ef41Sopenharmony_ci#endif 4401cb0ef41Sopenharmony_ci 4411cb0ef41Sopenharmony_ci // Constant pool. 4421cb0ef41Sopenharmony_ci friend class FrameAndConstantPoolScope; 4431cb0ef41Sopenharmony_ci friend class ConstantPoolUnavailableScope; 4441cb0ef41Sopenharmony_ci}; 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci// Enable a specified feature within a scope. 4471cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE V8_NODISCARD CpuFeatureScope { 4481cb0ef41Sopenharmony_ci public: 4491cb0ef41Sopenharmony_ci enum CheckPolicy { 4501cb0ef41Sopenharmony_ci kCheckSupported, 4511cb0ef41Sopenharmony_ci kDontCheckSupported, 4521cb0ef41Sopenharmony_ci }; 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci#ifdef DEBUG 4551cb0ef41Sopenharmony_ci CpuFeatureScope(AssemblerBase* assembler, CpuFeature f, 4561cb0ef41Sopenharmony_ci CheckPolicy check = kCheckSupported); 4571cb0ef41Sopenharmony_ci ~CpuFeatureScope(); 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci private: 4601cb0ef41Sopenharmony_ci AssemblerBase* assembler_; 4611cb0ef41Sopenharmony_ci uint64_t old_enabled_; 4621cb0ef41Sopenharmony_ci#else 4631cb0ef41Sopenharmony_ci CpuFeatureScope(AssemblerBase* assembler, CpuFeature f, 4641cb0ef41Sopenharmony_ci CheckPolicy check = kCheckSupported) {} 4651cb0ef41Sopenharmony_ci ~CpuFeatureScope() { 4661cb0ef41Sopenharmony_ci // Define a destructor to avoid unused variable warnings. 4671cb0ef41Sopenharmony_ci } 4681cb0ef41Sopenharmony_ci#endif 4691cb0ef41Sopenharmony_ci}; 4701cb0ef41Sopenharmony_ci 4711cb0ef41Sopenharmony_ci#ifdef V8_CODE_COMMENTS 4721cb0ef41Sopenharmony_ci#define ASM_CODE_COMMENT(asm) ASM_CODE_COMMENT_STRING(asm, __func__) 4731cb0ef41Sopenharmony_ci#define ASM_CODE_COMMENT_STRING(asm, comment) \ 4741cb0ef41Sopenharmony_ci AssemblerBase::CodeComment UNIQUE_IDENTIFIER(asm_code_comment)(asm, comment) 4751cb0ef41Sopenharmony_ci#else 4761cb0ef41Sopenharmony_ci#define ASM_CODE_COMMENT(asm) 4771cb0ef41Sopenharmony_ci#define ASM_CODE_COMMENT_STRING(asm, ...) 4781cb0ef41Sopenharmony_ci#endif 4791cb0ef41Sopenharmony_ci 4801cb0ef41Sopenharmony_ci} // namespace internal 4811cb0ef41Sopenharmony_ci} // namespace v8 4821cb0ef41Sopenharmony_ci#endif // V8_CODEGEN_ASSEMBLER_H_ 483