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