11cb0ef41Sopenharmony_ci// Copyright 2011 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/safepoint-table.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <iomanip>
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#include "src/codegen/assembler-inl.h"
101cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h"
111cb0ef41Sopenharmony_ci#include "src/deoptimizer/deoptimizer.h"
121cb0ef41Sopenharmony_ci#include "src/diagnostics/disasm.h"
131cb0ef41Sopenharmony_ci#include "src/execution/frames-inl.h"
141cb0ef41Sopenharmony_ci#include "src/utils/ostreams.h"
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
171cb0ef41Sopenharmony_ci#include "src/wasm/wasm-code-manager.h"
181cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_cinamespace v8 {
211cb0ef41Sopenharmony_cinamespace internal {
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ciSafepointTable::SafepointTable(Isolate* isolate, Address pc, Code code)
241cb0ef41Sopenharmony_ci    : SafepointTable(code.InstructionStart(isolate, pc),
251cb0ef41Sopenharmony_ci                     code.SafepointTableAddress()) {}
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY
281cb0ef41Sopenharmony_ciSafepointTable::SafepointTable(const wasm::WasmCode* code)
291cb0ef41Sopenharmony_ci    : SafepointTable(
301cb0ef41Sopenharmony_ci          code->instruction_start(),
311cb0ef41Sopenharmony_ci          code->instruction_start() + code->safepoint_table_offset()) {}
321cb0ef41Sopenharmony_ci#endif  // V8_ENABLE_WEBASSEMBLY
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ciSafepointTable::SafepointTable(Address instruction_start,
351cb0ef41Sopenharmony_ci                               Address safepoint_table_address)
361cb0ef41Sopenharmony_ci    : instruction_start_(instruction_start),
371cb0ef41Sopenharmony_ci      safepoint_table_address_(safepoint_table_address),
381cb0ef41Sopenharmony_ci      length_(base::Memory<int>(safepoint_table_address + kLengthOffset)),
391cb0ef41Sopenharmony_ci      entry_configuration_(base::Memory<uint32_t>(safepoint_table_address +
401cb0ef41Sopenharmony_ci                                                  kEntryConfigurationOffset)) {}
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_ciint SafepointTable::find_return_pc(int pc_offset) {
431cb0ef41Sopenharmony_ci  for (int i = 0; i < length(); i++) {
441cb0ef41Sopenharmony_ci    SafepointEntry entry = GetEntry(i);
451cb0ef41Sopenharmony_ci    if (entry.trampoline_pc() == pc_offset || entry.pc() == pc_offset) {
461cb0ef41Sopenharmony_ci      return entry.pc();
471cb0ef41Sopenharmony_ci    }
481cb0ef41Sopenharmony_ci  }
491cb0ef41Sopenharmony_ci  UNREACHABLE();
501cb0ef41Sopenharmony_ci}
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ciSafepointEntry SafepointTable::FindEntry(Address pc) const {
531cb0ef41Sopenharmony_ci  int pc_offset = static_cast<int>(pc - instruction_start_);
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  // Check if the PC is pointing at a trampoline.
561cb0ef41Sopenharmony_ci  if (has_deopt_data()) {
571cb0ef41Sopenharmony_ci    int candidate = -1;
581cb0ef41Sopenharmony_ci    for (int i = 0; i < length_; ++i) {
591cb0ef41Sopenharmony_ci      int trampoline_pc = GetEntry(i).trampoline_pc();
601cb0ef41Sopenharmony_ci      if (trampoline_pc != -1 && trampoline_pc <= pc_offset) candidate = i;
611cb0ef41Sopenharmony_ci      if (trampoline_pc > pc_offset) break;
621cb0ef41Sopenharmony_ci    }
631cb0ef41Sopenharmony_ci    if (candidate != -1) return GetEntry(candidate);
641cb0ef41Sopenharmony_ci  }
651cb0ef41Sopenharmony_ci
661cb0ef41Sopenharmony_ci  for (int i = 0; i < length_; ++i) {
671cb0ef41Sopenharmony_ci    SafepointEntry entry = GetEntry(i);
681cb0ef41Sopenharmony_ci    if (i == length_ - 1 || GetEntry(i + 1).pc() > pc_offset) {
691cb0ef41Sopenharmony_ci      DCHECK_LE(entry.pc(), pc_offset);
701cb0ef41Sopenharmony_ci      return entry;
711cb0ef41Sopenharmony_ci    }
721cb0ef41Sopenharmony_ci  }
731cb0ef41Sopenharmony_ci  UNREACHABLE();
741cb0ef41Sopenharmony_ci}
751cb0ef41Sopenharmony_ci
761cb0ef41Sopenharmony_civoid SafepointTable::Print(std::ostream& os) const {
771cb0ef41Sopenharmony_ci  os << "Safepoints (entries = " << length_ << ", byte size = " << byte_size()
781cb0ef41Sopenharmony_ci     << ")\n";
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  for (int index = 0; index < length_; index++) {
811cb0ef41Sopenharmony_ci    SafepointEntry entry = GetEntry(index);
821cb0ef41Sopenharmony_ci    os << reinterpret_cast<const void*>(instruction_start_ + entry.pc()) << " "
831cb0ef41Sopenharmony_ci       << std::setw(6) << std::hex << entry.pc() << std::dec;
841cb0ef41Sopenharmony_ci
851cb0ef41Sopenharmony_ci    if (!entry.tagged_slots().empty()) {
861cb0ef41Sopenharmony_ci      os << "  slots (sp->fp): ";
871cb0ef41Sopenharmony_ci      for (uint8_t bits : entry.tagged_slots()) {
881cb0ef41Sopenharmony_ci        for (int bit = 0; bit < kBitsPerByte; ++bit) {
891cb0ef41Sopenharmony_ci          os << ((bits >> bit) & 1);
901cb0ef41Sopenharmony_ci        }
911cb0ef41Sopenharmony_ci      }
921cb0ef41Sopenharmony_ci    }
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci    if (entry.tagged_register_indexes() != 0) {
951cb0ef41Sopenharmony_ci      os << "  registers: ";
961cb0ef41Sopenharmony_ci      uint32_t register_bits = entry.tagged_register_indexes();
971cb0ef41Sopenharmony_ci      int bits = 32 - base::bits::CountLeadingZeros32(register_bits);
981cb0ef41Sopenharmony_ci      for (int j = bits - 1; j >= 0; --j) {
991cb0ef41Sopenharmony_ci        os << ((register_bits >> j) & 1);
1001cb0ef41Sopenharmony_ci      }
1011cb0ef41Sopenharmony_ci    }
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_ci    if (entry.has_deoptimization_index()) {
1041cb0ef41Sopenharmony_ci      os << "  deopt " << std::setw(6) << entry.deoptimization_index()
1051cb0ef41Sopenharmony_ci         << " trampoline: " << std::setw(6) << std::hex
1061cb0ef41Sopenharmony_ci         << entry.trampoline_pc();
1071cb0ef41Sopenharmony_ci    }
1081cb0ef41Sopenharmony_ci    os << "\n";
1091cb0ef41Sopenharmony_ci  }
1101cb0ef41Sopenharmony_ci}
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ciSafepointTableBuilder::Safepoint SafepointTableBuilder::DefineSafepoint(
1131cb0ef41Sopenharmony_ci    Assembler* assembler) {
1141cb0ef41Sopenharmony_ci  entries_.push_back(EntryBuilder(zone_, assembler->pc_offset_for_safepoint()));
1151cb0ef41Sopenharmony_ci  return SafepointTableBuilder::Safepoint(&entries_.back(), this);
1161cb0ef41Sopenharmony_ci}
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_ciint SafepointTableBuilder::UpdateDeoptimizationInfo(int pc, int trampoline,
1191cb0ef41Sopenharmony_ci                                                    int start,
1201cb0ef41Sopenharmony_ci                                                    int deopt_index) {
1211cb0ef41Sopenharmony_ci  DCHECK_NE(SafepointEntry::kNoTrampolinePC, trampoline);
1221cb0ef41Sopenharmony_ci  DCHECK_NE(SafepointEntry::kNoDeoptIndex, deopt_index);
1231cb0ef41Sopenharmony_ci  auto it = entries_.Find(start);
1241cb0ef41Sopenharmony_ci  DCHECK(std::any_of(it, entries_.end(),
1251cb0ef41Sopenharmony_ci                     [pc](auto& entry) { return entry.pc == pc; }));
1261cb0ef41Sopenharmony_ci  int index = start;
1271cb0ef41Sopenharmony_ci  while (it->pc != pc) ++it, ++index;
1281cb0ef41Sopenharmony_ci  it->trampoline = trampoline;
1291cb0ef41Sopenharmony_ci  it->deopt_index = deopt_index;
1301cb0ef41Sopenharmony_ci  return index;
1311cb0ef41Sopenharmony_ci}
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_civoid SafepointTableBuilder::Emit(Assembler* assembler, int tagged_slots_size) {
1341cb0ef41Sopenharmony_ci  DCHECK_LT(max_stack_index_, tagged_slots_size);
1351cb0ef41Sopenharmony_ci
1361cb0ef41Sopenharmony_ci#ifdef DEBUG
1371cb0ef41Sopenharmony_ci  int last_pc = -1;
1381cb0ef41Sopenharmony_ci  int last_trampoline = -1;
1391cb0ef41Sopenharmony_ci  for (const EntryBuilder& entry : entries_) {
1401cb0ef41Sopenharmony_ci    // Entries are ordered by PC.
1411cb0ef41Sopenharmony_ci    DCHECK_LT(last_pc, entry.pc);
1421cb0ef41Sopenharmony_ci    last_pc = entry.pc;
1431cb0ef41Sopenharmony_ci    // Trampoline PCs are increasing, and larger than regular PCs.
1441cb0ef41Sopenharmony_ci    if (entry.trampoline != SafepointEntry::kNoTrampolinePC) {
1451cb0ef41Sopenharmony_ci      DCHECK_LT(last_trampoline, entry.trampoline);
1461cb0ef41Sopenharmony_ci      DCHECK_LT(entries_.back().pc, entry.trampoline);
1471cb0ef41Sopenharmony_ci      last_trampoline = entry.trampoline;
1481cb0ef41Sopenharmony_ci    }
1491cb0ef41Sopenharmony_ci    // An entry either has trampoline and deopt index, or none of the two.
1501cb0ef41Sopenharmony_ci    DCHECK_EQ(entry.trampoline == SafepointEntry::kNoTrampolinePC,
1511cb0ef41Sopenharmony_ci              entry.deopt_index == SafepointEntry::kNoDeoptIndex);
1521cb0ef41Sopenharmony_ci  }
1531cb0ef41Sopenharmony_ci#endif  // DEBUG
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  RemoveDuplicates();
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci  // The encoding is compacted by translating stack slot indices s.t. they
1581cb0ef41Sopenharmony_ci  // start at 0. See also below.
1591cb0ef41Sopenharmony_ci  tagged_slots_size -= min_stack_index();
1601cb0ef41Sopenharmony_ci
1611cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64
1621cb0ef41Sopenharmony_ci  // We cannot emit a const pool within the safepoint table.
1631cb0ef41Sopenharmony_ci  Assembler::BlockConstPoolScope block_const_pool(assembler);
1641cb0ef41Sopenharmony_ci#endif
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci  // Make sure the safepoint table is properly aligned. Pad with nops.
1671cb0ef41Sopenharmony_ci  assembler->Align(Code::kMetadataAlignment);
1681cb0ef41Sopenharmony_ci  assembler->RecordComment(";;; Safepoint table.");
1691cb0ef41Sopenharmony_ci  safepoint_table_offset_ = assembler->pc_offset();
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  // Compute the required sizes of the fields.
1721cb0ef41Sopenharmony_ci  int used_register_indexes = 0;
1731cb0ef41Sopenharmony_ci  STATIC_ASSERT(SafepointEntry::kNoTrampolinePC == -1);
1741cb0ef41Sopenharmony_ci  int max_pc = SafepointEntry::kNoTrampolinePC;
1751cb0ef41Sopenharmony_ci  STATIC_ASSERT(SafepointEntry::kNoDeoptIndex == -1);
1761cb0ef41Sopenharmony_ci  int max_deopt_index = SafepointEntry::kNoDeoptIndex;
1771cb0ef41Sopenharmony_ci  for (const EntryBuilder& entry : entries_) {
1781cb0ef41Sopenharmony_ci    used_register_indexes |= entry.register_indexes;
1791cb0ef41Sopenharmony_ci    max_pc = std::max(max_pc, std::max(entry.pc, entry.trampoline));
1801cb0ef41Sopenharmony_ci    max_deopt_index = std::max(max_deopt_index, entry.deopt_index);
1811cb0ef41Sopenharmony_ci  }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  // Derive the bytes and bools for the entry configuration from the values.
1841cb0ef41Sopenharmony_ci  auto value_to_bytes = [](int value) {
1851cb0ef41Sopenharmony_ci    DCHECK_LE(0, value);
1861cb0ef41Sopenharmony_ci    if (value == 0) return 0;
1871cb0ef41Sopenharmony_ci    if (value <= 0xff) return 1;
1881cb0ef41Sopenharmony_ci    if (value <= 0xffff) return 2;
1891cb0ef41Sopenharmony_ci    if (value <= 0xffffff) return 3;
1901cb0ef41Sopenharmony_ci    return 4;
1911cb0ef41Sopenharmony_ci  };
1921cb0ef41Sopenharmony_ci  bool has_deopt_data = max_deopt_index != -1;
1931cb0ef41Sopenharmony_ci  int register_indexes_size = value_to_bytes(used_register_indexes);
1941cb0ef41Sopenharmony_ci  // Add 1 so all values (including kNoDeoptIndex and kNoTrampolinePC) are
1951cb0ef41Sopenharmony_ci  // non-negative.
1961cb0ef41Sopenharmony_ci  STATIC_ASSERT(SafepointEntry::kNoDeoptIndex == -1);
1971cb0ef41Sopenharmony_ci  STATIC_ASSERT(SafepointEntry::kNoTrampolinePC == -1);
1981cb0ef41Sopenharmony_ci  int pc_size = value_to_bytes(max_pc + 1);
1991cb0ef41Sopenharmony_ci  int deopt_index_size = value_to_bytes(max_deopt_index + 1);
2001cb0ef41Sopenharmony_ci  int tagged_slots_bytes =
2011cb0ef41Sopenharmony_ci      (tagged_slots_size + kBitsPerByte - 1) / kBitsPerByte;
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci  // Add a CHECK to ensure we never overflow the space in the bitfield, even for
2041cb0ef41Sopenharmony_ci  // huge functions which might not be covered by tests.
2051cb0ef41Sopenharmony_ci  CHECK(SafepointTable::RegisterIndexesSizeField::is_valid(
2061cb0ef41Sopenharmony_ci            register_indexes_size) &&
2071cb0ef41Sopenharmony_ci        SafepointTable::PcSizeField::is_valid(pc_size) &&
2081cb0ef41Sopenharmony_ci        SafepointTable::DeoptIndexSizeField::is_valid(deopt_index_size) &&
2091cb0ef41Sopenharmony_ci        SafepointTable::TaggedSlotsBytesField::is_valid(tagged_slots_bytes));
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci  uint32_t entry_configuration =
2121cb0ef41Sopenharmony_ci      SafepointTable::HasDeoptDataField::encode(has_deopt_data) |
2131cb0ef41Sopenharmony_ci      SafepointTable::RegisterIndexesSizeField::encode(register_indexes_size) |
2141cb0ef41Sopenharmony_ci      SafepointTable::PcSizeField::encode(pc_size) |
2151cb0ef41Sopenharmony_ci      SafepointTable::DeoptIndexSizeField::encode(deopt_index_size) |
2161cb0ef41Sopenharmony_ci      SafepointTable::TaggedSlotsBytesField::encode(tagged_slots_bytes);
2171cb0ef41Sopenharmony_ci
2181cb0ef41Sopenharmony_ci  // Emit the table header.
2191cb0ef41Sopenharmony_ci  STATIC_ASSERT(SafepointTable::kLengthOffset == 0 * kIntSize);
2201cb0ef41Sopenharmony_ci  STATIC_ASSERT(SafepointTable::kEntryConfigurationOffset == 1 * kIntSize);
2211cb0ef41Sopenharmony_ci  STATIC_ASSERT(SafepointTable::kHeaderSize == 2 * kIntSize);
2221cb0ef41Sopenharmony_ci  int length = static_cast<int>(entries_.size());
2231cb0ef41Sopenharmony_ci  assembler->dd(length);
2241cb0ef41Sopenharmony_ci  assembler->dd(entry_configuration);
2251cb0ef41Sopenharmony_ci
2261cb0ef41Sopenharmony_ci  auto emit_bytes = [assembler](int value, int bytes) {
2271cb0ef41Sopenharmony_ci    DCHECK_LE(0, value);
2281cb0ef41Sopenharmony_ci    for (; bytes > 0; --bytes, value >>= 8) assembler->db(value);
2291cb0ef41Sopenharmony_ci    DCHECK_EQ(0, value);
2301cb0ef41Sopenharmony_ci  };
2311cb0ef41Sopenharmony_ci  // Emit entries, sorted by pc offsets.
2321cb0ef41Sopenharmony_ci  for (const EntryBuilder& entry : entries_) {
2331cb0ef41Sopenharmony_ci    emit_bytes(entry.pc, pc_size);
2341cb0ef41Sopenharmony_ci    if (has_deopt_data) {
2351cb0ef41Sopenharmony_ci      // Add 1 so all values (including kNoDeoptIndex and kNoTrampolinePC) are
2361cb0ef41Sopenharmony_ci      // non-negative.
2371cb0ef41Sopenharmony_ci      STATIC_ASSERT(SafepointEntry::kNoDeoptIndex == -1);
2381cb0ef41Sopenharmony_ci      STATIC_ASSERT(SafepointEntry::kNoTrampolinePC == -1);
2391cb0ef41Sopenharmony_ci      emit_bytes(entry.deopt_index + 1, deopt_index_size);
2401cb0ef41Sopenharmony_ci      emit_bytes(entry.trampoline + 1, pc_size);
2411cb0ef41Sopenharmony_ci    }
2421cb0ef41Sopenharmony_ci    emit_bytes(entry.register_indexes, register_indexes_size);
2431cb0ef41Sopenharmony_ci  }
2441cb0ef41Sopenharmony_ci
2451cb0ef41Sopenharmony_ci  // Emit bitmaps of tagged stack slots. Note the slot list is reversed in the
2461cb0ef41Sopenharmony_ci  // encoding.
2471cb0ef41Sopenharmony_ci  // TODO(jgruber): Avoid building a reversed copy of the bit vector.
2481cb0ef41Sopenharmony_ci  ZoneVector<uint8_t> bits(tagged_slots_bytes, 0, zone_);
2491cb0ef41Sopenharmony_ci  for (const EntryBuilder& entry : entries_) {
2501cb0ef41Sopenharmony_ci    std::fill(bits.begin(), bits.end(), 0);
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci    // Run through the indexes and build a bitmap.
2531cb0ef41Sopenharmony_ci    for (int idx : *entry.stack_indexes) {
2541cb0ef41Sopenharmony_ci      // The encoding is compacted by translating stack slot indices s.t. they
2551cb0ef41Sopenharmony_ci      // start at 0. See also above.
2561cb0ef41Sopenharmony_ci      const int adjusted_idx = idx - min_stack_index();
2571cb0ef41Sopenharmony_ci      DCHECK_GT(tagged_slots_size, adjusted_idx);
2581cb0ef41Sopenharmony_ci      int index = tagged_slots_size - 1 - adjusted_idx;
2591cb0ef41Sopenharmony_ci      int byte_index = index >> kBitsPerByteLog2;
2601cb0ef41Sopenharmony_ci      int bit_index = index & (kBitsPerByte - 1);
2611cb0ef41Sopenharmony_ci      bits[byte_index] |= (1u << bit_index);
2621cb0ef41Sopenharmony_ci    }
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ci    // Emit the bitmap for the current entry.
2651cb0ef41Sopenharmony_ci    for (uint8_t byte : bits) assembler->db(byte);
2661cb0ef41Sopenharmony_ci  }
2671cb0ef41Sopenharmony_ci}
2681cb0ef41Sopenharmony_ci
2691cb0ef41Sopenharmony_civoid SafepointTableBuilder::RemoveDuplicates() {
2701cb0ef41Sopenharmony_ci  // Remove any duplicate entries, i.e. succeeding entries that are identical
2711cb0ef41Sopenharmony_ci  // except for the PC. During lookup, we will find the first entry whose PC is
2721cb0ef41Sopenharmony_ci  // not larger than the PC at hand, and find the first non-duplicate.
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci  if (entries_.size() < 2) return;
2751cb0ef41Sopenharmony_ci
2761cb0ef41Sopenharmony_ci  auto is_identical_except_for_pc = [](const EntryBuilder& entry1,
2771cb0ef41Sopenharmony_ci                                       const EntryBuilder& entry2) {
2781cb0ef41Sopenharmony_ci    if (entry1.deopt_index != entry2.deopt_index) return false;
2791cb0ef41Sopenharmony_ci    DCHECK_EQ(entry1.trampoline, entry2.trampoline);
2801cb0ef41Sopenharmony_ci    return entry1.register_indexes == entry2.register_indexes &&
2811cb0ef41Sopenharmony_ci           entry1.stack_indexes->Equals(*entry2.stack_indexes);
2821cb0ef41Sopenharmony_ci  };
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_ci  auto remaining_it = entries_.begin();
2851cb0ef41Sopenharmony_ci  size_t remaining = 0;
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci  for (auto it = entries_.begin(), end = entries_.end(); it != end;
2881cb0ef41Sopenharmony_ci       ++remaining_it, ++remaining) {
2891cb0ef41Sopenharmony_ci    if (remaining_it != it) *remaining_it = *it;
2901cb0ef41Sopenharmony_ci    // Merge identical entries.
2911cb0ef41Sopenharmony_ci    do {
2921cb0ef41Sopenharmony_ci      ++it;
2931cb0ef41Sopenharmony_ci    } while (it != end && is_identical_except_for_pc(*it, *remaining_it));
2941cb0ef41Sopenharmony_ci  }
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_ci  entries_.Rewind(remaining);
2971cb0ef41Sopenharmony_ci}
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci}  // namespace internal
3001cb0ef41Sopenharmony_ci}  // namespace v8
301