11cb0ef41Sopenharmony_ci// Copyright 2018 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/codegen/constant-pool.h"
61cb0ef41Sopenharmony_ci#include "src/codegen/assembler-arch.h"
71cb0ef41Sopenharmony_ci#include "src/codegen/assembler-inl.h"
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cinamespace v8 {
101cb0ef41Sopenharmony_cinamespace internal {
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#if defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_PPC64)
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciConstantPoolBuilder::ConstantPoolBuilder(int ptr_reach_bits,
151cb0ef41Sopenharmony_ci                                         int double_reach_bits) {
161cb0ef41Sopenharmony_ci  info_[ConstantPoolEntry::INTPTR].entries.reserve(64);
171cb0ef41Sopenharmony_ci  info_[ConstantPoolEntry::INTPTR].regular_reach_bits = ptr_reach_bits;
181cb0ef41Sopenharmony_ci  info_[ConstantPoolEntry::DOUBLE].regular_reach_bits = double_reach_bits;
191cb0ef41Sopenharmony_ci}
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciConstantPoolEntry::Access ConstantPoolBuilder::NextAccess(
221cb0ef41Sopenharmony_ci    ConstantPoolEntry::Type type) const {
231cb0ef41Sopenharmony_ci  const PerTypeEntryInfo& info = info_[type];
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  if (info.overflow()) return ConstantPoolEntry::OVERFLOWED;
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci  int dbl_count = info_[ConstantPoolEntry::DOUBLE].regular_count;
281cb0ef41Sopenharmony_ci  int dbl_offset = dbl_count * kDoubleSize;
291cb0ef41Sopenharmony_ci  int ptr_count = info_[ConstantPoolEntry::INTPTR].regular_count;
301cb0ef41Sopenharmony_ci  int ptr_offset = ptr_count * kSystemPointerSize + dbl_offset;
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci  if (type == ConstantPoolEntry::DOUBLE) {
331cb0ef41Sopenharmony_ci    // Double overflow detection must take into account the reach for both types
341cb0ef41Sopenharmony_ci    int ptr_reach_bits = info_[ConstantPoolEntry::INTPTR].regular_reach_bits;
351cb0ef41Sopenharmony_ci    if (!is_uintn(dbl_offset, info.regular_reach_bits) ||
361cb0ef41Sopenharmony_ci        (ptr_count > 0 &&
371cb0ef41Sopenharmony_ci         !is_uintn(ptr_offset + kDoubleSize - kSystemPointerSize,
381cb0ef41Sopenharmony_ci                   ptr_reach_bits))) {
391cb0ef41Sopenharmony_ci      return ConstantPoolEntry::OVERFLOWED;
401cb0ef41Sopenharmony_ci    }
411cb0ef41Sopenharmony_ci  } else {
421cb0ef41Sopenharmony_ci    DCHECK(type == ConstantPoolEntry::INTPTR);
431cb0ef41Sopenharmony_ci    if (!is_uintn(ptr_offset, info.regular_reach_bits)) {
441cb0ef41Sopenharmony_ci      return ConstantPoolEntry::OVERFLOWED;
451cb0ef41Sopenharmony_ci    }
461cb0ef41Sopenharmony_ci  }
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  return ConstantPoolEntry::REGULAR;
491cb0ef41Sopenharmony_ci}
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ciConstantPoolEntry::Access ConstantPoolBuilder::AddEntry(
521cb0ef41Sopenharmony_ci    ConstantPoolEntry* entry, ConstantPoolEntry::Type type) {
531cb0ef41Sopenharmony_ci  DCHECK(!emitted_label_.is_bound());
541cb0ef41Sopenharmony_ci  PerTypeEntryInfo& info = info_[type];
551cb0ef41Sopenharmony_ci  const int entry_size = ConstantPoolEntry::size(type);
561cb0ef41Sopenharmony_ci  bool merged = false;
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  if (entry->sharing_ok()) {
591cb0ef41Sopenharmony_ci    // Try to merge entries
601cb0ef41Sopenharmony_ci    std::vector<ConstantPoolEntry>::iterator it = info.shared_entries.begin();
611cb0ef41Sopenharmony_ci    int end = static_cast<int>(info.shared_entries.size());
621cb0ef41Sopenharmony_ci    for (int i = 0; i < end; i++, it++) {
631cb0ef41Sopenharmony_ci      if ((entry_size == kSystemPointerSize)
641cb0ef41Sopenharmony_ci              ? entry->value() == it->value()
651cb0ef41Sopenharmony_ci              : entry->value64() == it->value64()) {
661cb0ef41Sopenharmony_ci        // Merge with found entry.
671cb0ef41Sopenharmony_ci        entry->set_merged_index(i);
681cb0ef41Sopenharmony_ci        merged = true;
691cb0ef41Sopenharmony_ci        break;
701cb0ef41Sopenharmony_ci      }
711cb0ef41Sopenharmony_ci    }
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci  // By definition, merged entries have regular access.
751cb0ef41Sopenharmony_ci  DCHECK(!merged || entry->merged_index() < info.regular_count);
761cb0ef41Sopenharmony_ci  ConstantPoolEntry::Access access =
771cb0ef41Sopenharmony_ci      (merged ? ConstantPoolEntry::REGULAR : NextAccess(type));
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ci  // Enforce an upper bound on search time by limiting the search to
801cb0ef41Sopenharmony_ci  // unique sharable entries which fit in the regular section.
811cb0ef41Sopenharmony_ci  if (entry->sharing_ok() && !merged && access == ConstantPoolEntry::REGULAR) {
821cb0ef41Sopenharmony_ci    info.shared_entries.push_back(*entry);
831cb0ef41Sopenharmony_ci  } else {
841cb0ef41Sopenharmony_ci    info.entries.push_back(*entry);
851cb0ef41Sopenharmony_ci  }
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  // We're done if we found a match or have already triggered the
881cb0ef41Sopenharmony_ci  // overflow state.
891cb0ef41Sopenharmony_ci  if (merged || info.overflow()) return access;
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  if (access == ConstantPoolEntry::REGULAR) {
921cb0ef41Sopenharmony_ci    info.regular_count++;
931cb0ef41Sopenharmony_ci  } else {
941cb0ef41Sopenharmony_ci    info.overflow_start = static_cast<int>(info.entries.size()) - 1;
951cb0ef41Sopenharmony_ci  }
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci  return access;
981cb0ef41Sopenharmony_ci}
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_civoid ConstantPoolBuilder::EmitSharedEntries(Assembler* assm,
1011cb0ef41Sopenharmony_ci                                            ConstantPoolEntry::Type type) {
1021cb0ef41Sopenharmony_ci  PerTypeEntryInfo& info = info_[type];
1031cb0ef41Sopenharmony_ci  std::vector<ConstantPoolEntry>& shared_entries = info.shared_entries;
1041cb0ef41Sopenharmony_ci  const int entry_size = ConstantPoolEntry::size(type);
1051cb0ef41Sopenharmony_ci  int base = emitted_label_.pos();
1061cb0ef41Sopenharmony_ci  DCHECK_GT(base, 0);
1071cb0ef41Sopenharmony_ci  int shared_end = static_cast<int>(shared_entries.size());
1081cb0ef41Sopenharmony_ci  std::vector<ConstantPoolEntry>::iterator shared_it = shared_entries.begin();
1091cb0ef41Sopenharmony_ci  for (int i = 0; i < shared_end; i++, shared_it++) {
1101cb0ef41Sopenharmony_ci    int offset = assm->pc_offset() - base;
1111cb0ef41Sopenharmony_ci    shared_it->set_offset(offset);  // Save offset for merged entries.
1121cb0ef41Sopenharmony_ci    if (entry_size == kSystemPointerSize) {
1131cb0ef41Sopenharmony_ci      assm->dp(shared_it->value());
1141cb0ef41Sopenharmony_ci    } else {
1151cb0ef41Sopenharmony_ci      assm->dq(shared_it->value64());
1161cb0ef41Sopenharmony_ci    }
1171cb0ef41Sopenharmony_ci    DCHECK(is_uintn(offset, info.regular_reach_bits));
1181cb0ef41Sopenharmony_ci
1191cb0ef41Sopenharmony_ci    // Patch load sequence with correct offset.
1201cb0ef41Sopenharmony_ci    assm->PatchConstantPoolAccessInstruction(shared_it->position(), offset,
1211cb0ef41Sopenharmony_ci                                             ConstantPoolEntry::REGULAR, type);
1221cb0ef41Sopenharmony_ci  }
1231cb0ef41Sopenharmony_ci}
1241cb0ef41Sopenharmony_ci
1251cb0ef41Sopenharmony_civoid ConstantPoolBuilder::EmitGroup(Assembler* assm,
1261cb0ef41Sopenharmony_ci                                    ConstantPoolEntry::Access access,
1271cb0ef41Sopenharmony_ci                                    ConstantPoolEntry::Type type) {
1281cb0ef41Sopenharmony_ci  PerTypeEntryInfo& info = info_[type];
1291cb0ef41Sopenharmony_ci  const bool overflow = info.overflow();
1301cb0ef41Sopenharmony_ci  std::vector<ConstantPoolEntry>& entries = info.entries;
1311cb0ef41Sopenharmony_ci  std::vector<ConstantPoolEntry>& shared_entries = info.shared_entries;
1321cb0ef41Sopenharmony_ci  const int entry_size = ConstantPoolEntry::size(type);
1331cb0ef41Sopenharmony_ci  int base = emitted_label_.pos();
1341cb0ef41Sopenharmony_ci  DCHECK_GT(base, 0);
1351cb0ef41Sopenharmony_ci  int begin;
1361cb0ef41Sopenharmony_ci  int end;
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  if (access == ConstantPoolEntry::REGULAR) {
1391cb0ef41Sopenharmony_ci    // Emit any shared entries first
1401cb0ef41Sopenharmony_ci    EmitSharedEntries(assm, type);
1411cb0ef41Sopenharmony_ci  }
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  if (access == ConstantPoolEntry::REGULAR) {
1441cb0ef41Sopenharmony_ci    begin = 0;
1451cb0ef41Sopenharmony_ci    end = overflow ? info.overflow_start : static_cast<int>(entries.size());
1461cb0ef41Sopenharmony_ci  } else {
1471cb0ef41Sopenharmony_ci    DCHECK(access == ConstantPoolEntry::OVERFLOWED);
1481cb0ef41Sopenharmony_ci    if (!overflow) return;
1491cb0ef41Sopenharmony_ci    begin = info.overflow_start;
1501cb0ef41Sopenharmony_ci    end = static_cast<int>(entries.size());
1511cb0ef41Sopenharmony_ci  }
1521cb0ef41Sopenharmony_ci
1531cb0ef41Sopenharmony_ci  std::vector<ConstantPoolEntry>::iterator it = entries.begin();
1541cb0ef41Sopenharmony_ci  if (begin > 0) std::advance(it, begin);
1551cb0ef41Sopenharmony_ci  for (int i = begin; i < end; i++, it++) {
1561cb0ef41Sopenharmony_ci    // Update constant pool if necessary and get the entry's offset.
1571cb0ef41Sopenharmony_ci    int offset;
1581cb0ef41Sopenharmony_ci    ConstantPoolEntry::Access entry_access;
1591cb0ef41Sopenharmony_ci    if (!it->is_merged()) {
1601cb0ef41Sopenharmony_ci      // Emit new entry
1611cb0ef41Sopenharmony_ci      offset = assm->pc_offset() - base;
1621cb0ef41Sopenharmony_ci      entry_access = access;
1631cb0ef41Sopenharmony_ci      if (entry_size == kSystemPointerSize) {
1641cb0ef41Sopenharmony_ci        assm->dp(it->value());
1651cb0ef41Sopenharmony_ci      } else {
1661cb0ef41Sopenharmony_ci        assm->dq(it->value64());
1671cb0ef41Sopenharmony_ci      }
1681cb0ef41Sopenharmony_ci    } else {
1691cb0ef41Sopenharmony_ci      // Retrieve offset from shared entry.
1701cb0ef41Sopenharmony_ci      offset = shared_entries[it->merged_index()].offset();
1711cb0ef41Sopenharmony_ci      entry_access = ConstantPoolEntry::REGULAR;
1721cb0ef41Sopenharmony_ci    }
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_ci    DCHECK(entry_access == ConstantPoolEntry::OVERFLOWED ||
1751cb0ef41Sopenharmony_ci           is_uintn(offset, info.regular_reach_bits));
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci    // Patch load sequence with correct offset.
1781cb0ef41Sopenharmony_ci    assm->PatchConstantPoolAccessInstruction(it->position(), offset,
1791cb0ef41Sopenharmony_ci                                             entry_access, type);
1801cb0ef41Sopenharmony_ci  }
1811cb0ef41Sopenharmony_ci}
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci// Emit and return size of pool.
1841cb0ef41Sopenharmony_ciint ConstantPoolBuilder::Emit(Assembler* assm) {
1851cb0ef41Sopenharmony_ci  bool emitted = emitted_label_.is_bound();
1861cb0ef41Sopenharmony_ci  bool empty = IsEmpty();
1871cb0ef41Sopenharmony_ci
1881cb0ef41Sopenharmony_ci  if (!emitted) {
1891cb0ef41Sopenharmony_ci    // Mark start of constant pool.  Align if necessary.
1901cb0ef41Sopenharmony_ci    if (!empty) assm->DataAlign(kDoubleSize);
1911cb0ef41Sopenharmony_ci    assm->bind(&emitted_label_);
1921cb0ef41Sopenharmony_ci    if (!empty) {
1931cb0ef41Sopenharmony_ci      // Emit in groups based on access and type.
1941cb0ef41Sopenharmony_ci      // Emit doubles first for alignment purposes.
1951cb0ef41Sopenharmony_ci      EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::DOUBLE);
1961cb0ef41Sopenharmony_ci      EmitGroup(assm, ConstantPoolEntry::REGULAR, ConstantPoolEntry::INTPTR);
1971cb0ef41Sopenharmony_ci      if (info_[ConstantPoolEntry::DOUBLE].overflow()) {
1981cb0ef41Sopenharmony_ci        assm->DataAlign(kDoubleSize);
1991cb0ef41Sopenharmony_ci        EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
2001cb0ef41Sopenharmony_ci                  ConstantPoolEntry::DOUBLE);
2011cb0ef41Sopenharmony_ci      }
2021cb0ef41Sopenharmony_ci      if (info_[ConstantPoolEntry::INTPTR].overflow()) {
2031cb0ef41Sopenharmony_ci        EmitGroup(assm, ConstantPoolEntry::OVERFLOWED,
2041cb0ef41Sopenharmony_ci                  ConstantPoolEntry::INTPTR);
2051cb0ef41Sopenharmony_ci      }
2061cb0ef41Sopenharmony_ci    }
2071cb0ef41Sopenharmony_ci  }
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci  return !empty ? (assm->pc_offset() - emitted_label_.pos()) : 0;
2101cb0ef41Sopenharmony_ci}
2111cb0ef41Sopenharmony_ci
2121cb0ef41Sopenharmony_ci#endif  // defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_PPC64)
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci#if defined(V8_TARGET_ARCH_ARM64)
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci// Constant Pool.
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ciConstantPool::ConstantPool(Assembler* assm) : assm_(assm) {}
2191cb0ef41Sopenharmony_ciConstantPool::~ConstantPool() { DCHECK_EQ(blocked_nesting_, 0); }
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ciRelocInfoStatus ConstantPool::RecordEntry(uint32_t data,
2221cb0ef41Sopenharmony_ci                                          RelocInfo::Mode rmode) {
2231cb0ef41Sopenharmony_ci  ConstantPoolKey key(data, rmode);
2241cb0ef41Sopenharmony_ci  CHECK(key.is_value32());
2251cb0ef41Sopenharmony_ci  return RecordKey(std::move(key), assm_->pc_offset());
2261cb0ef41Sopenharmony_ci}
2271cb0ef41Sopenharmony_ci
2281cb0ef41Sopenharmony_ciRelocInfoStatus ConstantPool::RecordEntry(uint64_t data,
2291cb0ef41Sopenharmony_ci                                          RelocInfo::Mode rmode) {
2301cb0ef41Sopenharmony_ci  ConstantPoolKey key(data, rmode);
2311cb0ef41Sopenharmony_ci  CHECK(!key.is_value32());
2321cb0ef41Sopenharmony_ci  return RecordKey(std::move(key), assm_->pc_offset());
2331cb0ef41Sopenharmony_ci}
2341cb0ef41Sopenharmony_ci
2351cb0ef41Sopenharmony_ciRelocInfoStatus ConstantPool::RecordKey(ConstantPoolKey key, int offset) {
2361cb0ef41Sopenharmony_ci  RelocInfoStatus write_reloc_info = GetRelocInfoStatusFor(key);
2371cb0ef41Sopenharmony_ci  if (write_reloc_info == RelocInfoStatus::kMustRecord) {
2381cb0ef41Sopenharmony_ci    if (key.is_value32()) {
2391cb0ef41Sopenharmony_ci      if (entry32_count_ == 0) first_use_32_ = offset;
2401cb0ef41Sopenharmony_ci      ++entry32_count_;
2411cb0ef41Sopenharmony_ci    } else {
2421cb0ef41Sopenharmony_ci      if (entry64_count_ == 0) first_use_64_ = offset;
2431cb0ef41Sopenharmony_ci      ++entry64_count_;
2441cb0ef41Sopenharmony_ci    }
2451cb0ef41Sopenharmony_ci  }
2461cb0ef41Sopenharmony_ci  entries_.insert(std::make_pair(key, offset));
2471cb0ef41Sopenharmony_ci
2481cb0ef41Sopenharmony_ci  if (Entry32Count() + Entry64Count() > ConstantPool::kApproxMaxEntryCount) {
2491cb0ef41Sopenharmony_ci    // Request constant pool emission after the next instruction.
2501cb0ef41Sopenharmony_ci    SetNextCheckIn(1);
2511cb0ef41Sopenharmony_ci  }
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci  return write_reloc_info;
2541cb0ef41Sopenharmony_ci}
2551cb0ef41Sopenharmony_ci
2561cb0ef41Sopenharmony_ciRelocInfoStatus ConstantPool::GetRelocInfoStatusFor(
2571cb0ef41Sopenharmony_ci    const ConstantPoolKey& key) {
2581cb0ef41Sopenharmony_ci  if (key.AllowsDeduplication()) {
2591cb0ef41Sopenharmony_ci    auto existing = entries_.find(key);
2601cb0ef41Sopenharmony_ci    if (existing != entries_.end()) {
2611cb0ef41Sopenharmony_ci      return RelocInfoStatus::kMustOmitForDuplicate;
2621cb0ef41Sopenharmony_ci    }
2631cb0ef41Sopenharmony_ci  }
2641cb0ef41Sopenharmony_ci  return RelocInfoStatus::kMustRecord;
2651cb0ef41Sopenharmony_ci}
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_civoid ConstantPool::EmitAndClear(Jump require_jump) {
2681cb0ef41Sopenharmony_ci  DCHECK(!IsBlocked());
2691cb0ef41Sopenharmony_ci  // Prevent recursive pool emission.
2701cb0ef41Sopenharmony_ci  Assembler::BlockPoolsScope block_pools(assm_, PoolEmissionCheck::kSkip);
2711cb0ef41Sopenharmony_ci  Alignment require_alignment =
2721cb0ef41Sopenharmony_ci      IsAlignmentRequiredIfEmittedAt(require_jump, assm_->pc_offset());
2731cb0ef41Sopenharmony_ci  int size = ComputeSize(require_jump, require_alignment);
2741cb0ef41Sopenharmony_ci  Label size_check;
2751cb0ef41Sopenharmony_ci  assm_->bind(&size_check);
2761cb0ef41Sopenharmony_ci  assm_->RecordConstPool(size);
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci  // Emit the constant pool. It is preceded by an optional branch if
2791cb0ef41Sopenharmony_ci  // {require_jump} and a header which will:
2801cb0ef41Sopenharmony_ci  //  1) Encode the size of the constant pool, for use by the disassembler.
2811cb0ef41Sopenharmony_ci  //  2) Terminate the program, to try to prevent execution from accidentally
2821cb0ef41Sopenharmony_ci  //     flowing into the constant pool.
2831cb0ef41Sopenharmony_ci  //  3) align the 64bit pool entries to 64-bit.
2841cb0ef41Sopenharmony_ci  // TODO(all): Make the alignment part less fragile. Currently code is
2851cb0ef41Sopenharmony_ci  // allocated as a byte array so there are no guarantees the alignment will
2861cb0ef41Sopenharmony_ci  // be preserved on compaction. Currently it works as allocation seems to be
2871cb0ef41Sopenharmony_ci  // 64-bit aligned.
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_ci  Label after_pool;
2901cb0ef41Sopenharmony_ci  if (require_jump == Jump::kRequired) assm_->b(&after_pool);
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci  assm_->RecordComment("[ Constant Pool");
2931cb0ef41Sopenharmony_ci  EmitPrologue(require_alignment);
2941cb0ef41Sopenharmony_ci  if (require_alignment == Alignment::kRequired) assm_->Align(kInt64Size);
2951cb0ef41Sopenharmony_ci  EmitEntries();
2961cb0ef41Sopenharmony_ci  assm_->RecordComment("]");
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci  if (after_pool.is_linked()) assm_->bind(&after_pool);
2991cb0ef41Sopenharmony_ci
3001cb0ef41Sopenharmony_ci  DCHECK_EQ(assm_->SizeOfCodeGeneratedSince(&size_check), size);
3011cb0ef41Sopenharmony_ci  Clear();
3021cb0ef41Sopenharmony_ci}
3031cb0ef41Sopenharmony_ci
3041cb0ef41Sopenharmony_civoid ConstantPool::Clear() {
3051cb0ef41Sopenharmony_ci  entries_.clear();
3061cb0ef41Sopenharmony_ci  first_use_32_ = -1;
3071cb0ef41Sopenharmony_ci  first_use_64_ = -1;
3081cb0ef41Sopenharmony_ci  entry32_count_ = 0;
3091cb0ef41Sopenharmony_ci  entry64_count_ = 0;
3101cb0ef41Sopenharmony_ci  next_check_ = 0;
3111cb0ef41Sopenharmony_ci}
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_civoid ConstantPool::StartBlock() {
3141cb0ef41Sopenharmony_ci  if (blocked_nesting_ == 0) {
3151cb0ef41Sopenharmony_ci    // Prevent constant pool checks from happening by setting the next check to
3161cb0ef41Sopenharmony_ci    // the biggest possible offset.
3171cb0ef41Sopenharmony_ci    next_check_ = kMaxInt;
3181cb0ef41Sopenharmony_ci  }
3191cb0ef41Sopenharmony_ci  ++blocked_nesting_;
3201cb0ef41Sopenharmony_ci}
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_civoid ConstantPool::EndBlock() {
3231cb0ef41Sopenharmony_ci  --blocked_nesting_;
3241cb0ef41Sopenharmony_ci  if (blocked_nesting_ == 0) {
3251cb0ef41Sopenharmony_ci    DCHECK(IsInImmRangeIfEmittedAt(assm_->pc_offset()));
3261cb0ef41Sopenharmony_ci    // Make sure a check happens quickly after getting unblocked.
3271cb0ef41Sopenharmony_ci    next_check_ = 0;
3281cb0ef41Sopenharmony_ci  }
3291cb0ef41Sopenharmony_ci}
3301cb0ef41Sopenharmony_ci
3311cb0ef41Sopenharmony_cibool ConstantPool::IsBlocked() const { return blocked_nesting_ > 0; }
3321cb0ef41Sopenharmony_ci
3331cb0ef41Sopenharmony_civoid ConstantPool::SetNextCheckIn(size_t instructions) {
3341cb0ef41Sopenharmony_ci  next_check_ =
3351cb0ef41Sopenharmony_ci      assm_->pc_offset() + static_cast<int>(instructions * kInstrSize);
3361cb0ef41Sopenharmony_ci}
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_civoid ConstantPool::EmitEntries() {
3391cb0ef41Sopenharmony_ci  for (auto iter = entries_.begin(); iter != entries_.end();) {
3401cb0ef41Sopenharmony_ci    DCHECK(iter->first.is_value32() || IsAligned(assm_->pc_offset(), 8));
3411cb0ef41Sopenharmony_ci    auto range = entries_.equal_range(iter->first);
3421cb0ef41Sopenharmony_ci    bool shared = iter->first.AllowsDeduplication();
3431cb0ef41Sopenharmony_ci    for (auto it = range.first; it != range.second; ++it) {
3441cb0ef41Sopenharmony_ci      SetLoadOffsetToConstPoolEntry(it->second, assm_->pc(), it->first);
3451cb0ef41Sopenharmony_ci      if (!shared) Emit(it->first);
3461cb0ef41Sopenharmony_ci    }
3471cb0ef41Sopenharmony_ci    if (shared) Emit(iter->first);
3481cb0ef41Sopenharmony_ci    iter = range.second;
3491cb0ef41Sopenharmony_ci  }
3501cb0ef41Sopenharmony_ci}
3511cb0ef41Sopenharmony_ci
3521cb0ef41Sopenharmony_civoid ConstantPool::Emit(const ConstantPoolKey& key) {
3531cb0ef41Sopenharmony_ci  if (key.is_value32()) {
3541cb0ef41Sopenharmony_ci    assm_->dd(key.value32());
3551cb0ef41Sopenharmony_ci  } else {
3561cb0ef41Sopenharmony_ci    assm_->dq(key.value64());
3571cb0ef41Sopenharmony_ci  }
3581cb0ef41Sopenharmony_ci}
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_cibool ConstantPool::ShouldEmitNow(Jump require_jump, size_t margin) const {
3611cb0ef41Sopenharmony_ci  if (IsEmpty()) return false;
3621cb0ef41Sopenharmony_ci  if (Entry32Count() + Entry64Count() > ConstantPool::kApproxMaxEntryCount) {
3631cb0ef41Sopenharmony_ci    return true;
3641cb0ef41Sopenharmony_ci  }
3651cb0ef41Sopenharmony_ci  // We compute {dist32/64}, i.e. the distance from the first instruction
3661cb0ef41Sopenharmony_ci  // accessing a 32bit/64bit entry in the constant pool to any of the
3671cb0ef41Sopenharmony_ci  // 32bit/64bit constant pool entries, respectively. This is required because
3681cb0ef41Sopenharmony_ci  // we do not guarantee that entries are emitted in order of reference, i.e. it
3691cb0ef41Sopenharmony_ci  // is possible that the entry with the earliest reference is emitted last.
3701cb0ef41Sopenharmony_ci  // The constant pool should be emitted if either of the following is true:
3711cb0ef41Sopenharmony_ci  // (A) {dist32/64} will be out of range at the next check in.
3721cb0ef41Sopenharmony_ci  // (B) Emission can be done behind an unconditional branch and {dist32/64}
3731cb0ef41Sopenharmony_ci  // exceeds {kOpportunityDist*}.
3741cb0ef41Sopenharmony_ci  // (C) {dist32/64} exceeds the desired approximate distance to the pool.
3751cb0ef41Sopenharmony_ci  int worst_case_size = ComputeSize(Jump::kRequired, Alignment::kRequired);
3761cb0ef41Sopenharmony_ci  size_t pool_end_32 = assm_->pc_offset() + margin + worst_case_size;
3771cb0ef41Sopenharmony_ci  size_t pool_end_64 = pool_end_32 - Entry32Count() * kInt32Size;
3781cb0ef41Sopenharmony_ci  if (Entry64Count() != 0) {
3791cb0ef41Sopenharmony_ci    // The 64-bit constants are always emitted before the 32-bit constants, so
3801cb0ef41Sopenharmony_ci    // we subtract the size of the 32-bit constants from {size}.
3811cb0ef41Sopenharmony_ci    size_t dist64 = pool_end_64 - first_use_64_;
3821cb0ef41Sopenharmony_ci    bool next_check_too_late = dist64 + 2 * kCheckInterval >= kMaxDistToPool64;
3831cb0ef41Sopenharmony_ci    bool opportune_emission_without_jump =
3841cb0ef41Sopenharmony_ci        require_jump == Jump::kOmitted && (dist64 >= kOpportunityDistToPool64);
3851cb0ef41Sopenharmony_ci    bool approximate_distance_exceeded = dist64 >= kApproxDistToPool64;
3861cb0ef41Sopenharmony_ci    if (next_check_too_late || opportune_emission_without_jump ||
3871cb0ef41Sopenharmony_ci        approximate_distance_exceeded) {
3881cb0ef41Sopenharmony_ci      return true;
3891cb0ef41Sopenharmony_ci    }
3901cb0ef41Sopenharmony_ci  }
3911cb0ef41Sopenharmony_ci  if (Entry32Count() != 0) {
3921cb0ef41Sopenharmony_ci    size_t dist32 = pool_end_32 - first_use_32_;
3931cb0ef41Sopenharmony_ci    bool next_check_too_late = dist32 + 2 * kCheckInterval >= kMaxDistToPool32;
3941cb0ef41Sopenharmony_ci    bool opportune_emission_without_jump =
3951cb0ef41Sopenharmony_ci        require_jump == Jump::kOmitted && (dist32 >= kOpportunityDistToPool32);
3961cb0ef41Sopenharmony_ci    bool approximate_distance_exceeded = dist32 >= kApproxDistToPool32;
3971cb0ef41Sopenharmony_ci    if (next_check_too_late || opportune_emission_without_jump ||
3981cb0ef41Sopenharmony_ci        approximate_distance_exceeded) {
3991cb0ef41Sopenharmony_ci      return true;
4001cb0ef41Sopenharmony_ci    }
4011cb0ef41Sopenharmony_ci  }
4021cb0ef41Sopenharmony_ci  return false;
4031cb0ef41Sopenharmony_ci}
4041cb0ef41Sopenharmony_ci
4051cb0ef41Sopenharmony_ciint ConstantPool::ComputeSize(Jump require_jump,
4061cb0ef41Sopenharmony_ci                              Alignment require_alignment) const {
4071cb0ef41Sopenharmony_ci  int size_up_to_marker = PrologueSize(require_jump);
4081cb0ef41Sopenharmony_ci  int alignment = require_alignment == Alignment::kRequired ? kInstrSize : 0;
4091cb0ef41Sopenharmony_ci  size_t size_after_marker =
4101cb0ef41Sopenharmony_ci      Entry32Count() * kInt32Size + alignment + Entry64Count() * kInt64Size;
4111cb0ef41Sopenharmony_ci  return size_up_to_marker + static_cast<int>(size_after_marker);
4121cb0ef41Sopenharmony_ci}
4131cb0ef41Sopenharmony_ci
4141cb0ef41Sopenharmony_ciAlignment ConstantPool::IsAlignmentRequiredIfEmittedAt(Jump require_jump,
4151cb0ef41Sopenharmony_ci                                                       int pc_offset) const {
4161cb0ef41Sopenharmony_ci  int size_up_to_marker = PrologueSize(require_jump);
4171cb0ef41Sopenharmony_ci  if (Entry64Count() != 0 &&
4181cb0ef41Sopenharmony_ci      !IsAligned(pc_offset + size_up_to_marker, kInt64Size)) {
4191cb0ef41Sopenharmony_ci    return Alignment::kRequired;
4201cb0ef41Sopenharmony_ci  }
4211cb0ef41Sopenharmony_ci  return Alignment::kOmitted;
4221cb0ef41Sopenharmony_ci}
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_cibool ConstantPool::IsInImmRangeIfEmittedAt(int pc_offset) {
4251cb0ef41Sopenharmony_ci  // Check that all entries are in range if the pool is emitted at {pc_offset}.
4261cb0ef41Sopenharmony_ci  // This ignores kPcLoadDelta (conservatively, since all offsets are positive),
4271cb0ef41Sopenharmony_ci  // and over-estimates the last entry's address with the pool's end.
4281cb0ef41Sopenharmony_ci  Alignment require_alignment =
4291cb0ef41Sopenharmony_ci      IsAlignmentRequiredIfEmittedAt(Jump::kRequired, pc_offset);
4301cb0ef41Sopenharmony_ci  size_t pool_end_32 =
4311cb0ef41Sopenharmony_ci      pc_offset + ComputeSize(Jump::kRequired, require_alignment);
4321cb0ef41Sopenharmony_ci  size_t pool_end_64 = pool_end_32 - Entry32Count() * kInt32Size;
4331cb0ef41Sopenharmony_ci  bool entries_in_range_32 =
4341cb0ef41Sopenharmony_ci      Entry32Count() == 0 || (pool_end_32 < first_use_32_ + kMaxDistToPool32);
4351cb0ef41Sopenharmony_ci  bool entries_in_range_64 =
4361cb0ef41Sopenharmony_ci      Entry64Count() == 0 || (pool_end_64 < first_use_64_ + kMaxDistToPool64);
4371cb0ef41Sopenharmony_ci  return entries_in_range_32 && entries_in_range_64;
4381cb0ef41Sopenharmony_ci}
4391cb0ef41Sopenharmony_ci
4401cb0ef41Sopenharmony_ciConstantPool::BlockScope::BlockScope(Assembler* assm, size_t margin)
4411cb0ef41Sopenharmony_ci    : pool_(&assm->constpool_) {
4421cb0ef41Sopenharmony_ci  pool_->assm_->EmitConstPoolWithJumpIfNeeded(margin);
4431cb0ef41Sopenharmony_ci  pool_->StartBlock();
4441cb0ef41Sopenharmony_ci}
4451cb0ef41Sopenharmony_ci
4461cb0ef41Sopenharmony_ciConstantPool::BlockScope::BlockScope(Assembler* assm, PoolEmissionCheck check)
4471cb0ef41Sopenharmony_ci    : pool_(&assm->constpool_) {
4481cb0ef41Sopenharmony_ci  DCHECK_EQ(check, PoolEmissionCheck::kSkip);
4491cb0ef41Sopenharmony_ci  pool_->StartBlock();
4501cb0ef41Sopenharmony_ci}
4511cb0ef41Sopenharmony_ci
4521cb0ef41Sopenharmony_ciConstantPool::BlockScope::~BlockScope() { pool_->EndBlock(); }
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_civoid ConstantPool::MaybeCheck() {
4551cb0ef41Sopenharmony_ci  if (assm_->pc_offset() >= next_check_) {
4561cb0ef41Sopenharmony_ci    Check(Emission::kIfNeeded, Jump::kRequired);
4571cb0ef41Sopenharmony_ci  }
4581cb0ef41Sopenharmony_ci}
4591cb0ef41Sopenharmony_ci
4601cb0ef41Sopenharmony_ci#endif  // defined(V8_TARGET_ARCH_ARM64)
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci#if defined(V8_TARGET_ARCH_RISCV64)
4631cb0ef41Sopenharmony_ci
4641cb0ef41Sopenharmony_ci// Constant Pool.
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ciConstantPool::ConstantPool(Assembler* assm) : assm_(assm) {}
4671cb0ef41Sopenharmony_ciConstantPool::~ConstantPool() { DCHECK_EQ(blocked_nesting_, 0); }
4681cb0ef41Sopenharmony_ci
4691cb0ef41Sopenharmony_ciRelocInfoStatus ConstantPool::RecordEntry(uint32_t data,
4701cb0ef41Sopenharmony_ci                                          RelocInfo::Mode rmode) {
4711cb0ef41Sopenharmony_ci  ConstantPoolKey key(data, rmode);
4721cb0ef41Sopenharmony_ci  CHECK(key.is_value32());
4731cb0ef41Sopenharmony_ci  return RecordKey(std::move(key), assm_->pc_offset());
4741cb0ef41Sopenharmony_ci}
4751cb0ef41Sopenharmony_ci
4761cb0ef41Sopenharmony_ciRelocInfoStatus ConstantPool::RecordEntry(uint64_t data,
4771cb0ef41Sopenharmony_ci                                          RelocInfo::Mode rmode) {
4781cb0ef41Sopenharmony_ci  ConstantPoolKey key(data, rmode);
4791cb0ef41Sopenharmony_ci  CHECK(!key.is_value32());
4801cb0ef41Sopenharmony_ci  return RecordKey(std::move(key), assm_->pc_offset());
4811cb0ef41Sopenharmony_ci}
4821cb0ef41Sopenharmony_ci
4831cb0ef41Sopenharmony_ciRelocInfoStatus ConstantPool::RecordKey(ConstantPoolKey key, int offset) {
4841cb0ef41Sopenharmony_ci  RelocInfoStatus write_reloc_info = GetRelocInfoStatusFor(key);
4851cb0ef41Sopenharmony_ci  if (write_reloc_info == RelocInfoStatus::kMustRecord) {
4861cb0ef41Sopenharmony_ci    if (key.is_value32()) {
4871cb0ef41Sopenharmony_ci      if (entry32_count_ == 0) first_use_32_ = offset;
4881cb0ef41Sopenharmony_ci      ++entry32_count_;
4891cb0ef41Sopenharmony_ci    } else {
4901cb0ef41Sopenharmony_ci      if (entry64_count_ == 0) first_use_64_ = offset;
4911cb0ef41Sopenharmony_ci      ++entry64_count_;
4921cb0ef41Sopenharmony_ci    }
4931cb0ef41Sopenharmony_ci  }
4941cb0ef41Sopenharmony_ci  entries_.insert(std::make_pair(key, offset));
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_ci  if (Entry32Count() + Entry64Count() > ConstantPool::kApproxMaxEntryCount) {
4971cb0ef41Sopenharmony_ci    // Request constant pool emission after the next instruction.
4981cb0ef41Sopenharmony_ci    SetNextCheckIn(1);
4991cb0ef41Sopenharmony_ci  }
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci  return write_reloc_info;
5021cb0ef41Sopenharmony_ci}
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_ciRelocInfoStatus ConstantPool::GetRelocInfoStatusFor(
5051cb0ef41Sopenharmony_ci    const ConstantPoolKey& key) {
5061cb0ef41Sopenharmony_ci  if (key.AllowsDeduplication()) {
5071cb0ef41Sopenharmony_ci    auto existing = entries_.find(key);
5081cb0ef41Sopenharmony_ci    if (existing != entries_.end()) {
5091cb0ef41Sopenharmony_ci      return RelocInfoStatus::kMustOmitForDuplicate;
5101cb0ef41Sopenharmony_ci    }
5111cb0ef41Sopenharmony_ci  }
5121cb0ef41Sopenharmony_ci  return RelocInfoStatus::kMustRecord;
5131cb0ef41Sopenharmony_ci}
5141cb0ef41Sopenharmony_ci
5151cb0ef41Sopenharmony_civoid ConstantPool::EmitAndClear(Jump require_jump) {
5161cb0ef41Sopenharmony_ci  DCHECK(!IsBlocked());
5171cb0ef41Sopenharmony_ci  // Prevent recursive pool emission.
5181cb0ef41Sopenharmony_ci  Assembler::BlockPoolsScope block_pools(assm_, PoolEmissionCheck::kSkip);
5191cb0ef41Sopenharmony_ci  Alignment require_alignment =
5201cb0ef41Sopenharmony_ci      IsAlignmentRequiredIfEmittedAt(require_jump, assm_->pc_offset());
5211cb0ef41Sopenharmony_ci  int size = ComputeSize(require_jump, require_alignment);
5221cb0ef41Sopenharmony_ci  Label size_check;
5231cb0ef41Sopenharmony_ci  assm_->bind(&size_check);
5241cb0ef41Sopenharmony_ci  assm_->RecordConstPool(size);
5251cb0ef41Sopenharmony_ci
5261cb0ef41Sopenharmony_ci  // Emit the constant pool. It is preceded by an optional branch if
5271cb0ef41Sopenharmony_ci  // {require_jump} and a header which will:
5281cb0ef41Sopenharmony_ci  //  1) Encode the size of the constant pool, for use by the disassembler.
5291cb0ef41Sopenharmony_ci  //  2) Terminate the program, to try to prevent execution from accidentally
5301cb0ef41Sopenharmony_ci  //     flowing into the constant pool.
5311cb0ef41Sopenharmony_ci  //  3) align the 64bit pool entries to 64-bit.
5321cb0ef41Sopenharmony_ci  // TODO(all): Make the alignment part less fragile. Currently code is
5331cb0ef41Sopenharmony_ci  // allocated as a byte array so there are no guarantees the alignment will
5341cb0ef41Sopenharmony_ci  // be preserved on compaction. Currently it works as allocation seems to be
5351cb0ef41Sopenharmony_ci  // 64-bit aligned.
5361cb0ef41Sopenharmony_ci  DEBUG_PRINTF("\tConstant Pool start\n")
5371cb0ef41Sopenharmony_ci  Label after_pool;
5381cb0ef41Sopenharmony_ci  if (require_jump == Jump::kRequired) assm_->b(&after_pool);
5391cb0ef41Sopenharmony_ci
5401cb0ef41Sopenharmony_ci  assm_->RecordComment("[ Constant Pool");
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci  EmitPrologue(require_alignment);
5431cb0ef41Sopenharmony_ci  if (require_alignment == Alignment::kRequired) assm_->DataAlign(kInt64Size);
5441cb0ef41Sopenharmony_ci  EmitEntries();
5451cb0ef41Sopenharmony_ci  assm_->RecordComment("]");
5461cb0ef41Sopenharmony_ci  assm_->bind(&after_pool);
5471cb0ef41Sopenharmony_ci  DEBUG_PRINTF("\tConstant Pool end\n")
5481cb0ef41Sopenharmony_ci
5491cb0ef41Sopenharmony_ci  DCHECK_LE(assm_->SizeOfCodeGeneratedSince(&size_check) - size, 3);
5501cb0ef41Sopenharmony_ci  Clear();
5511cb0ef41Sopenharmony_ci}
5521cb0ef41Sopenharmony_ci
5531cb0ef41Sopenharmony_civoid ConstantPool::Clear() {
5541cb0ef41Sopenharmony_ci  entries_.clear();
5551cb0ef41Sopenharmony_ci  first_use_32_ = -1;
5561cb0ef41Sopenharmony_ci  first_use_64_ = -1;
5571cb0ef41Sopenharmony_ci  entry32_count_ = 0;
5581cb0ef41Sopenharmony_ci  entry64_count_ = 0;
5591cb0ef41Sopenharmony_ci  next_check_ = 0;
5601cb0ef41Sopenharmony_ci}
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_civoid ConstantPool::StartBlock() {
5631cb0ef41Sopenharmony_ci  if (blocked_nesting_ == 0) {
5641cb0ef41Sopenharmony_ci    // Prevent constant pool checks from happening by setting the next check to
5651cb0ef41Sopenharmony_ci    // the biggest possible offset.
5661cb0ef41Sopenharmony_ci    next_check_ = kMaxInt;
5671cb0ef41Sopenharmony_ci  }
5681cb0ef41Sopenharmony_ci  ++blocked_nesting_;
5691cb0ef41Sopenharmony_ci}
5701cb0ef41Sopenharmony_ci
5711cb0ef41Sopenharmony_civoid ConstantPool::EndBlock() {
5721cb0ef41Sopenharmony_ci  --blocked_nesting_;
5731cb0ef41Sopenharmony_ci  if (blocked_nesting_ == 0) {
5741cb0ef41Sopenharmony_ci    DCHECK(IsInImmRangeIfEmittedAt(assm_->pc_offset()));
5751cb0ef41Sopenharmony_ci    // Make sure a check happens quickly after getting unblocked.
5761cb0ef41Sopenharmony_ci    next_check_ = 0;
5771cb0ef41Sopenharmony_ci  }
5781cb0ef41Sopenharmony_ci}
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_cibool ConstantPool::IsBlocked() const { return blocked_nesting_ > 0; }
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_civoid ConstantPool::SetNextCheckIn(size_t instructions) {
5831cb0ef41Sopenharmony_ci  next_check_ =
5841cb0ef41Sopenharmony_ci      assm_->pc_offset() + static_cast<int>(instructions * kInstrSize);
5851cb0ef41Sopenharmony_ci}
5861cb0ef41Sopenharmony_ci
5871cb0ef41Sopenharmony_civoid ConstantPool::EmitEntries() {
5881cb0ef41Sopenharmony_ci  for (auto iter = entries_.begin(); iter != entries_.end();) {
5891cb0ef41Sopenharmony_ci    DCHECK(iter->first.is_value32() || IsAligned(assm_->pc_offset(), 8));
5901cb0ef41Sopenharmony_ci    auto range = entries_.equal_range(iter->first);
5911cb0ef41Sopenharmony_ci    bool shared = iter->first.AllowsDeduplication();
5921cb0ef41Sopenharmony_ci    for (auto it = range.first; it != range.second; ++it) {
5931cb0ef41Sopenharmony_ci      SetLoadOffsetToConstPoolEntry(it->second, assm_->pc(), it->first);
5941cb0ef41Sopenharmony_ci      if (!shared) Emit(it->first);
5951cb0ef41Sopenharmony_ci    }
5961cb0ef41Sopenharmony_ci    if (shared) Emit(iter->first);
5971cb0ef41Sopenharmony_ci    iter = range.second;
5981cb0ef41Sopenharmony_ci  }
5991cb0ef41Sopenharmony_ci}
6001cb0ef41Sopenharmony_ci
6011cb0ef41Sopenharmony_civoid ConstantPool::Emit(const ConstantPoolKey& key) {
6021cb0ef41Sopenharmony_ci  if (key.is_value32()) {
6031cb0ef41Sopenharmony_ci    assm_->dd(key.value32());
6041cb0ef41Sopenharmony_ci  } else {
6051cb0ef41Sopenharmony_ci    assm_->dq(key.value64());
6061cb0ef41Sopenharmony_ci  }
6071cb0ef41Sopenharmony_ci}
6081cb0ef41Sopenharmony_ci
6091cb0ef41Sopenharmony_cibool ConstantPool::ShouldEmitNow(Jump require_jump, size_t margin) const {
6101cb0ef41Sopenharmony_ci  if (IsEmpty()) return false;
6111cb0ef41Sopenharmony_ci  if (Entry32Count() + Entry64Count() > ConstantPool::kApproxMaxEntryCount) {
6121cb0ef41Sopenharmony_ci    return true;
6131cb0ef41Sopenharmony_ci  }
6141cb0ef41Sopenharmony_ci  // We compute {dist32/64}, i.e. the distance from the first instruction
6151cb0ef41Sopenharmony_ci  // accessing a 32bit/64bit entry in the constant pool to any of the
6161cb0ef41Sopenharmony_ci  // 32bit/64bit constant pool entries, respectively. This is required because
6171cb0ef41Sopenharmony_ci  // we do not guarantee that entries are emitted in order of reference, i.e. it
6181cb0ef41Sopenharmony_ci  // is possible that the entry with the earliest reference is emitted last.
6191cb0ef41Sopenharmony_ci  // The constant pool should be emitted if either of the following is true:
6201cb0ef41Sopenharmony_ci  // (A) {dist32/64} will be out of range at the next check in.
6211cb0ef41Sopenharmony_ci  // (B) Emission can be done behind an unconditional branch and {dist32/64}
6221cb0ef41Sopenharmony_ci  // exceeds {kOpportunityDist*}.
6231cb0ef41Sopenharmony_ci  // (C) {dist32/64} exceeds the desired approximate distance to the pool.
6241cb0ef41Sopenharmony_ci  int worst_case_size = ComputeSize(Jump::kRequired, Alignment::kRequired);
6251cb0ef41Sopenharmony_ci  size_t pool_end_32 = assm_->pc_offset() + margin + worst_case_size;
6261cb0ef41Sopenharmony_ci  size_t pool_end_64 = pool_end_32 - Entry32Count() * kInt32Size;
6271cb0ef41Sopenharmony_ci  if (Entry64Count() != 0) {
6281cb0ef41Sopenharmony_ci    // The 64-bit constants are always emitted before the 32-bit constants, so
6291cb0ef41Sopenharmony_ci    // we subtract the size of the 32-bit constants from {size}.
6301cb0ef41Sopenharmony_ci    size_t dist64 = pool_end_64 - first_use_64_;
6311cb0ef41Sopenharmony_ci    bool next_check_too_late = dist64 + 2 * kCheckInterval >= kMaxDistToPool64;
6321cb0ef41Sopenharmony_ci    bool opportune_emission_without_jump =
6331cb0ef41Sopenharmony_ci        require_jump == Jump::kOmitted && (dist64 >= kOpportunityDistToPool64);
6341cb0ef41Sopenharmony_ci    bool approximate_distance_exceeded = dist64 >= kApproxDistToPool64;
6351cb0ef41Sopenharmony_ci    if (next_check_too_late || opportune_emission_without_jump ||
6361cb0ef41Sopenharmony_ci        approximate_distance_exceeded) {
6371cb0ef41Sopenharmony_ci      return true;
6381cb0ef41Sopenharmony_ci    }
6391cb0ef41Sopenharmony_ci  }
6401cb0ef41Sopenharmony_ci  if (Entry32Count() != 0) {
6411cb0ef41Sopenharmony_ci    size_t dist32 = pool_end_32 - first_use_32_;
6421cb0ef41Sopenharmony_ci    bool next_check_too_late = dist32 + 2 * kCheckInterval >= kMaxDistToPool32;
6431cb0ef41Sopenharmony_ci    bool opportune_emission_without_jump =
6441cb0ef41Sopenharmony_ci        require_jump == Jump::kOmitted && (dist32 >= kOpportunityDistToPool32);
6451cb0ef41Sopenharmony_ci    bool approximate_distance_exceeded = dist32 >= kApproxDistToPool32;
6461cb0ef41Sopenharmony_ci    if (next_check_too_late || opportune_emission_without_jump ||
6471cb0ef41Sopenharmony_ci        approximate_distance_exceeded) {
6481cb0ef41Sopenharmony_ci      return true;
6491cb0ef41Sopenharmony_ci    }
6501cb0ef41Sopenharmony_ci  }
6511cb0ef41Sopenharmony_ci  return false;
6521cb0ef41Sopenharmony_ci}
6531cb0ef41Sopenharmony_ci
6541cb0ef41Sopenharmony_ciint ConstantPool::ComputeSize(Jump require_jump,
6551cb0ef41Sopenharmony_ci                              Alignment require_alignment) const {
6561cb0ef41Sopenharmony_ci  int size_up_to_marker = PrologueSize(require_jump);
6571cb0ef41Sopenharmony_ci  int alignment = require_alignment == Alignment::kRequired ? kInstrSize : 0;
6581cb0ef41Sopenharmony_ci  size_t size_after_marker =
6591cb0ef41Sopenharmony_ci      Entry32Count() * kInt32Size + alignment + Entry64Count() * kInt64Size;
6601cb0ef41Sopenharmony_ci  return size_up_to_marker + static_cast<int>(size_after_marker);
6611cb0ef41Sopenharmony_ci}
6621cb0ef41Sopenharmony_ci
6631cb0ef41Sopenharmony_ciAlignment ConstantPool::IsAlignmentRequiredIfEmittedAt(Jump require_jump,
6641cb0ef41Sopenharmony_ci                                                       int pc_offset) const {
6651cb0ef41Sopenharmony_ci  int size_up_to_marker = PrologueSize(require_jump);
6661cb0ef41Sopenharmony_ci  if (Entry64Count() != 0 &&
6671cb0ef41Sopenharmony_ci      !IsAligned(pc_offset + size_up_to_marker, kInt64Size)) {
6681cb0ef41Sopenharmony_ci    return Alignment::kRequired;
6691cb0ef41Sopenharmony_ci  }
6701cb0ef41Sopenharmony_ci  return Alignment::kOmitted;
6711cb0ef41Sopenharmony_ci}
6721cb0ef41Sopenharmony_ci
6731cb0ef41Sopenharmony_cibool ConstantPool::IsInImmRangeIfEmittedAt(int pc_offset) {
6741cb0ef41Sopenharmony_ci  // Check that all entries are in range if the pool is emitted at {pc_offset}.
6751cb0ef41Sopenharmony_ci  // This ignores kPcLoadDelta (conservatively, since all offsets are positive),
6761cb0ef41Sopenharmony_ci  // and over-estimates the last entry's address with the pool's end.
6771cb0ef41Sopenharmony_ci  Alignment require_alignment =
6781cb0ef41Sopenharmony_ci      IsAlignmentRequiredIfEmittedAt(Jump::kRequired, pc_offset);
6791cb0ef41Sopenharmony_ci  size_t pool_end_32 =
6801cb0ef41Sopenharmony_ci      pc_offset + ComputeSize(Jump::kRequired, require_alignment);
6811cb0ef41Sopenharmony_ci  size_t pool_end_64 = pool_end_32 - Entry32Count() * kInt32Size;
6821cb0ef41Sopenharmony_ci  bool entries_in_range_32 =
6831cb0ef41Sopenharmony_ci      Entry32Count() == 0 || (pool_end_32 < first_use_32_ + kMaxDistToPool32);
6841cb0ef41Sopenharmony_ci  bool entries_in_range_64 =
6851cb0ef41Sopenharmony_ci      Entry64Count() == 0 || (pool_end_64 < first_use_64_ + kMaxDistToPool64);
6861cb0ef41Sopenharmony_ci  return entries_in_range_32 && entries_in_range_64;
6871cb0ef41Sopenharmony_ci}
6881cb0ef41Sopenharmony_ci
6891cb0ef41Sopenharmony_ciConstantPool::BlockScope::BlockScope(Assembler* assm, size_t margin)
6901cb0ef41Sopenharmony_ci    : pool_(&assm->constpool_) {
6911cb0ef41Sopenharmony_ci  pool_->assm_->EmitConstPoolWithJumpIfNeeded(margin);
6921cb0ef41Sopenharmony_ci  pool_->StartBlock();
6931cb0ef41Sopenharmony_ci}
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ciConstantPool::BlockScope::BlockScope(Assembler* assm, PoolEmissionCheck check)
6961cb0ef41Sopenharmony_ci    : pool_(&assm->constpool_) {
6971cb0ef41Sopenharmony_ci  DCHECK_EQ(check, PoolEmissionCheck::kSkip);
6981cb0ef41Sopenharmony_ci  pool_->StartBlock();
6991cb0ef41Sopenharmony_ci}
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_ciConstantPool::BlockScope::~BlockScope() { pool_->EndBlock(); }
7021cb0ef41Sopenharmony_ci
7031cb0ef41Sopenharmony_civoid ConstantPool::MaybeCheck() {
7041cb0ef41Sopenharmony_ci  if (assm_->pc_offset() >= next_check_) {
7051cb0ef41Sopenharmony_ci    Check(Emission::kIfNeeded, Jump::kRequired);
7061cb0ef41Sopenharmony_ci  }
7071cb0ef41Sopenharmony_ci}
7081cb0ef41Sopenharmony_ci
7091cb0ef41Sopenharmony_ci#endif  // defined(V8_TARGET_ARCH_RISCV64)
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_ci}  // namespace internal
7121cb0ef41Sopenharmony_ci}  // namespace v8
713