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