reloc-info.cc 19.2 KB
Newer Older
1 2 3 4 5 6
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/reloc-info.h"

7
#include "src/assembler-inl.h"
8
#include "src/code-reference.h"
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
#include "src/deoptimize-reason.h"
#include "src/deoptimizer.h"
#include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/code-inl.h"
#include "src/snapshot/snapshot.h"

namespace v8 {
namespace internal {

const char* const RelocInfo::kFillerCommentString = "DEOPTIMIZATION PADDING";

// -----------------------------------------------------------------------------
// Implementation of RelocInfoWriter and RelocIterator
//
// Relocation information is written backwards in memory, from high addresses
// towards low addresses, byte by byte.  Therefore, in the encodings listed
// below, the first byte listed it at the highest address, and successive
// bytes in the record are at progressively lower addresses.
//
// Encoding
//
// The most common modes are given single-byte encodings.  Also, it is
// easy to identify the type of reloc info and skip unwanted modes in
// an iteration.
//
// The encoding relies on the fact that there are fewer than 14
// different relocation modes using standard non-compact encoding.
//
// The first byte of a relocation record has a tag in its low 2 bits:
// Here are the record schemes, depending on the low tag and optional higher
// tags.
//
// Low tag:
//   00: embedded_object:      [6-bit pc delta] 00
//
//   01: code_target:          [6-bit pc delta] 01
//
//   10: wasm_stub_call:       [6-bit pc delta] 10
//
//   11: long_record           [6 bit reloc mode] 11
//                             followed by pc delta
//                             followed by optional data depending on type.
//
//  If a pc delta exceeds 6 bits, it is split into a remainder that fits into
//  6 bits and a part that does not. The latter is encoded as a long record
//  with PC_JUMP as pseudo reloc info mode. The former is encoded as part of
//  the following record in the usual way. The long pc jump record has variable
//  length:
//               pc-jump:        [PC_JUMP] 11
//                               [7 bits data] 0
//                                  ...
//                               [7 bits data] 1
//               (Bits 6..31 of pc delta, with leading zeroes
//                dropped, and last non-zero chunk tagged with 1.)

const int kTagBits = 2;
const int kTagMask = (1 << kTagBits) - 1;
const int kLongTagBits = 6;

const int kEmbeddedObjectTag = 0;
const int kCodeTargetTag = 1;
const int kWasmStubCallTag = 2;
const int kDefaultTag = 3;

const int kSmallPCDeltaBits = kBitsPerByte - kTagBits;
const int kSmallPCDeltaMask = (1 << kSmallPCDeltaBits) - 1;
const int RelocInfo::kMaxSmallPCDelta = kSmallPCDeltaMask;

const int kChunkBits = 7;
const int kChunkMask = (1 << kChunkBits) - 1;
const int kLastChunkTagBits = 1;
const int kLastChunkTagMask = 1;
const int kLastChunkTag = 1;

uint32_t RelocInfoWriter::WriteLongPCJump(uint32_t pc_delta) {
  // Return if the pc_delta can fit in kSmallPCDeltaBits bits.
  // Otherwise write a variable length PC jump for the bits that do
  // not fit in the kSmallPCDeltaBits bits.
  if (is_uintn(pc_delta, kSmallPCDeltaBits)) return pc_delta;
  WriteMode(RelocInfo::PC_JUMP);
  uint32_t pc_jump = pc_delta >> kSmallPCDeltaBits;
  DCHECK_GT(pc_jump, 0);
  // Write kChunkBits size chunks of the pc_jump.
  for (; pc_jump > 0; pc_jump = pc_jump >> kChunkBits) {
    byte b = pc_jump & kChunkMask;
    *--pos_ = b << kLastChunkTagBits;
  }
  // Tag the last chunk so it can be identified.
  *pos_ = *pos_ | kLastChunkTag;
  // Return the remaining kSmallPCDeltaBits of the pc_delta.
  return pc_delta & kSmallPCDeltaMask;
}

void RelocInfoWriter::WriteShortTaggedPC(uint32_t pc_delta, int tag) {
  // Write a byte of tagged pc-delta, possibly preceded by an explicit pc-jump.
  pc_delta = WriteLongPCJump(pc_delta);
  *--pos_ = pc_delta << kTagBits | tag;
}

void RelocInfoWriter::WriteShortData(intptr_t data_delta) {
  *--pos_ = static_cast<byte>(data_delta);
}

void RelocInfoWriter::WriteMode(RelocInfo::Mode rmode) {
  STATIC_ASSERT(RelocInfo::NUMBER_OF_MODES <= (1 << kLongTagBits));
  *--pos_ = static_cast<int>((rmode << kTagBits) | kDefaultTag);
}

void RelocInfoWriter::WriteModeAndPC(uint32_t pc_delta, RelocInfo::Mode rmode) {
  // Write two-byte tagged pc-delta, possibly preceded by var. length pc-jump.
  pc_delta = WriteLongPCJump(pc_delta);
  WriteMode(rmode);
  *--pos_ = pc_delta;
}

void RelocInfoWriter::WriteIntData(int number) {
  for (int i = 0; i < kIntSize; i++) {
    *--pos_ = static_cast<byte>(number);
    // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
    number = number >> kBitsPerByte;
  }
}

void RelocInfoWriter::WriteData(intptr_t data_delta) {
  for (int i = 0; i < kIntptrSize; i++) {
    *--pos_ = static_cast<byte>(data_delta);
    // Signed right shift is arithmetic shift.  Tested in test-utils.cc.
    data_delta = data_delta >> kBitsPerByte;
  }
}

void RelocInfoWriter::Write(const RelocInfo* rinfo) {
  RelocInfo::Mode rmode = rinfo->rmode();
#ifdef DEBUG
  byte* begin_pos = pos_;
#endif
  DCHECK(rinfo->rmode() < RelocInfo::NUMBER_OF_MODES);
  DCHECK_GE(rinfo->pc() - reinterpret_cast<Address>(last_pc_), 0);
  // Use unsigned delta-encoding for pc.
  uint32_t pc_delta =
      static_cast<uint32_t>(rinfo->pc() - reinterpret_cast<Address>(last_pc_));

  // The two most common modes are given small tags, and usually fit in a byte.
152
  if (rmode == RelocInfo::FULL_EMBEDDED_OBJECT) {
153 154 155 156 157 158 159 160
    WriteShortTaggedPC(pc_delta, kEmbeddedObjectTag);
  } else if (rmode == RelocInfo::CODE_TARGET) {
    WriteShortTaggedPC(pc_delta, kCodeTargetTag);
    DCHECK_LE(begin_pos - pos_, RelocInfo::kMaxCallSize);
  } else if (rmode == RelocInfo::WASM_STUB_CALL) {
    WriteShortTaggedPC(pc_delta, kWasmStubCallTag);
  } else {
    WriteModeAndPC(pc_delta, rmode);
161
    if (RelocInfo::IsDeoptReason(rmode)) {
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
      DCHECK_LT(rinfo->data(), 1 << kBitsPerByte);
      WriteShortData(rinfo->data());
    } else if (RelocInfo::IsConstPool(rmode) ||
               RelocInfo::IsVeneerPool(rmode) || RelocInfo::IsDeoptId(rmode) ||
               RelocInfo::IsDeoptPosition(rmode)) {
      WriteIntData(static_cast<int>(rinfo->data()));
    }
  }
  last_pc_ = reinterpret_cast<byte*>(rinfo->pc());
#ifdef DEBUG
  DCHECK_LE(begin_pos - pos_, kMaxSize);
#endif
}

inline int RelocIterator::AdvanceGetTag() { return *--pos_ & kTagMask; }

inline RelocInfo::Mode RelocIterator::GetMode() {
  return static_cast<RelocInfo::Mode>((*pos_ >> kTagBits) &
                                      ((1 << kLongTagBits) - 1));
}

inline void RelocIterator::ReadShortTaggedPC() {
  rinfo_.pc_ += *pos_ >> kTagBits;
}

inline void RelocIterator::AdvanceReadPC() { rinfo_.pc_ += *--pos_; }

void RelocIterator::AdvanceReadInt() {
  int x = 0;
  for (int i = 0; i < kIntSize; i++) {
    x |= static_cast<int>(*--pos_) << i * kBitsPerByte;
  }
  rinfo_.data_ = x;
}

void RelocIterator::AdvanceReadData() {
  intptr_t x = 0;
  for (int i = 0; i < kIntptrSize; i++) {
    x |= static_cast<intptr_t>(*--pos_) << i * kBitsPerByte;
  }
  rinfo_.data_ = x;
}

void RelocIterator::AdvanceReadLongPCJump() {
  // Read the 32-kSmallPCDeltaBits most significant bits of the
  // pc jump in kChunkBits bit chunks and shift them into place.
  // Stop when the last chunk is encountered.
  uint32_t pc_jump = 0;
  for (int i = 0; i < kIntSize; i++) {
    byte pc_jump_part = *--pos_;
    pc_jump |= (pc_jump_part >> kLastChunkTagBits) << i * kChunkBits;
    if ((pc_jump_part & kLastChunkTagMask) == 1) break;
  }
  // The least significant kSmallPCDeltaBits bits will be added
  // later.
  rinfo_.pc_ += pc_jump << kSmallPCDeltaBits;
}

inline void RelocIterator::ReadShortData() {
  uint8_t unsigned_b = *pos_;
  rinfo_.data_ = unsigned_b;
}

void RelocIterator::next() {
  DCHECK(!done());
  // Basically, do the opposite of RelocInfoWriter::Write.
  // Reading of data is as far as possible avoided for unwanted modes,
  // but we must always update the pc.
  //
  // We exit this loop by returning when we find a mode we want.
  while (pos_ > end_) {
    int tag = AdvanceGetTag();
    if (tag == kEmbeddedObjectTag) {
      ReadShortTaggedPC();
236
      if (SetMode(RelocInfo::FULL_EMBEDDED_OBJECT)) return;
237 238 239 240 241 242 243 244 245 246 247 248 249
    } else if (tag == kCodeTargetTag) {
      ReadShortTaggedPC();
      if (SetMode(RelocInfo::CODE_TARGET)) return;
    } else if (tag == kWasmStubCallTag) {
      ReadShortTaggedPC();
      if (SetMode(RelocInfo::WASM_STUB_CALL)) return;
    } else {
      DCHECK_EQ(tag, kDefaultTag);
      RelocInfo::Mode rmode = GetMode();
      if (rmode == RelocInfo::PC_JUMP) {
        AdvanceReadLongPCJump();
      } else {
        AdvanceReadPC();
250
        if (RelocInfo::IsDeoptReason(rmode)) {
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
          Advance();
          if (SetMode(rmode)) {
            ReadShortData();
            return;
          }
        } else if (RelocInfo::IsConstPool(rmode) ||
                   RelocInfo::IsVeneerPool(rmode) ||
                   RelocInfo::IsDeoptId(rmode) ||
                   RelocInfo::IsDeoptPosition(rmode)) {
          if (SetMode(rmode)) {
            AdvanceReadInt();
            return;
          }
          Advance(kIntSize);
        } else if (SetMode(static_cast<RelocInfo::Mode>(rmode))) {
          return;
        }
      }
    }
  }
  done_ = true;
}

274
RelocIterator::RelocIterator(Code code, int mode_mask)
275 276
    : RelocIterator(code, code->unchecked_relocation_info(), mode_mask) {}

277
RelocIterator::RelocIterator(Code code, ByteArray relocation_info,
278
                             int mode_mask)
279
    : RelocIterator(code, code->raw_instruction_start(), code->constant_pool(),
280 281
                    relocation_info->GetDataEndAddress(),
                    relocation_info->GetDataStartAddress(), mode_mask) {}
282 283

RelocIterator::RelocIterator(const CodeReference code_reference, int mode_mask)
284
    : RelocIterator(Code(), code_reference.instruction_start(),
285 286 287 288
                    code_reference.constant_pool(),
                    code_reference.relocation_end(),
                    code_reference.relocation_start(), mode_mask) {}

289
RelocIterator::RelocIterator(EmbeddedData* embedded_data, Code code,
290 291 292 293 294 295 296 297
                             int mode_mask)
    : RelocIterator(
          code, embedded_data->InstructionStartOfBuiltin(code->builtin_index()),
          code->constant_pool(),
          code->relocation_start() + code->relocation_size(),
          code->relocation_start(), mode_mask) {}

RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask)
298
    : RelocIterator(Code(), reinterpret_cast<Address>(desc.buffer), 0,
299 300 301 302 303 304 305
                    desc.buffer + desc.buffer_size,
                    desc.buffer + desc.buffer_size - desc.reloc_size,
                    mode_mask) {}

RelocIterator::RelocIterator(Vector<byte> instructions,
                             Vector<const byte> reloc_info, Address const_pool,
                             int mode_mask)
306 307 308
    : RelocIterator(Code(), reinterpret_cast<Address>(instructions.begin()),
                    const_pool, reloc_info.begin() + reloc_info.size(),
                    reloc_info.begin(), mode_mask) {}
309

310
RelocIterator::RelocIterator(Code host, Address pc, Address constant_pool,
311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
                             const byte* pos, const byte* end, int mode_mask)
    : pos_(pos), end_(end), mode_mask_(mode_mask) {
  // Relocation info is read backwards.
  DCHECK_GE(pos_, end_);
  rinfo_.host_ = host;
  rinfo_.pc_ = pc;
  rinfo_.constant_pool_ = constant_pool;
  if (mode_mask_ == 0) pos_ = end_;
  next();
}

// -----------------------------------------------------------------------------
// Implementation of RelocInfo

// static
bool RelocInfo::OffHeapTargetIsCodedSpecially() {
#if defined(V8_TARGET_ARCH_ARM) || defined(V8_TARGET_ARCH_ARM64) || \
328
    defined(V8_TARGET_ARCH_X64)
329
  return false;
330 331 332
#elif defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_MIPS) || \
    defined(V8_TARGET_ARCH_MIPS64) || defined(V8_TARGET_ARCH_PPC) ||  \
    defined(V8_TARGET_ARCH_S390)
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
  return true;
#endif
}

Address RelocInfo::wasm_call_address() const {
  DCHECK_EQ(rmode_, WASM_CALL);
  return Assembler::target_address_at(pc_, constant_pool_);
}

void RelocInfo::set_wasm_call_address(Address address,
                                      ICacheFlushMode icache_flush_mode) {
  DCHECK_EQ(rmode_, WASM_CALL);
  Assembler::set_target_address_at(pc_, constant_pool_, address,
                                   icache_flush_mode);
}

Address RelocInfo::wasm_stub_call_address() const {
  DCHECK_EQ(rmode_, WASM_STUB_CALL);
  return Assembler::target_address_at(pc_, constant_pool_);
}

void RelocInfo::set_wasm_stub_call_address(Address address,
                                           ICacheFlushMode icache_flush_mode) {
  DCHECK_EQ(rmode_, WASM_STUB_CALL);
  Assembler::set_target_address_at(pc_, constant_pool_, address,
                                   icache_flush_mode);
}

void RelocInfo::set_target_address(Address target,
                                   WriteBarrierMode write_barrier_mode,
                                   ICacheFlushMode icache_flush_mode) {
  DCHECK(IsCodeTargetMode(rmode_) || IsRuntimeEntry(rmode_) ||
         IsWasmCall(rmode_));
  Assembler::set_target_address_at(pc_, constant_pool_, target,
                                   icache_flush_mode);
368
  if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() &&
369
      IsCodeTargetMode(rmode_)) {
370
    Code target_code = Code::GetCodeFromTargetAddress(target);
371 372 373 374
    MarkingBarrierForCode(host(), this, target_code);
  }
}

375 376 377 378 379
bool RelocInfo::HasTargetAddressAddress() const {
  // TODO(jgruber): Investigate whether WASM_CALL is still appropriate on
  // non-intel platforms now that wasm code is no longer on the heap.
#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
  static constexpr int kTargetAddressAddressModeMask =
380 381 382 383
      ModeMask(CODE_TARGET) | ModeMask(FULL_EMBEDDED_OBJECT) |
      ModeMask(COMPRESSED_EMBEDDED_OBJECT) | ModeMask(EXTERNAL_REFERENCE) |
      ModeMask(OFF_HEAP_TARGET) | ModeMask(RUNTIME_ENTRY) |
      ModeMask(WASM_CALL) | ModeMask(WASM_STUB_CALL);
384 385
#else
  static constexpr int kTargetAddressAddressModeMask =
386
      ModeMask(CODE_TARGET) | ModeMask(RELATIVE_CODE_TARGET) |
387
      ModeMask(FULL_EMBEDDED_OBJECT) | ModeMask(EXTERNAL_REFERENCE) |
388
      ModeMask(OFF_HEAP_TARGET) | ModeMask(RUNTIME_ENTRY) | ModeMask(WASM_CALL);
389 390 391 392
#endif
  return (ModeMask(rmode_) & kTargetAddressAddressModeMask) != 0;
}

393 394 395 396 397
bool RelocInfo::RequiresRelocationAfterCodegen(const CodeDesc& desc) {
  RelocIterator it(desc, RelocInfo::PostCodegenRelocationMask());
  return !it.done();
}

398
bool RelocInfo::RequiresRelocation(Code code) {
399
  RelocIterator it(code, RelocInfo::kApplyMask);
400 401 402 403 404 405 406 407
  return !it.done();
}

#ifdef ENABLE_DISASSEMBLER
const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
  switch (rmode) {
    case NONE:
      return "no reloc";
408 409 410 411
    case COMPRESSED_EMBEDDED_OBJECT:
      return "compressed embedded object";
    case FULL_EMBEDDED_OBJECT:
      return "full embedded object";
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
    case CODE_TARGET:
      return "code target";
    case RELATIVE_CODE_TARGET:
      return "relative code target";
    case RUNTIME_ENTRY:
      return "runtime entry";
    case EXTERNAL_REFERENCE:
      return "external reference";
    case INTERNAL_REFERENCE:
      return "internal reference";
    case INTERNAL_REFERENCE_ENCODED:
      return "encoded internal reference";
    case OFF_HEAP_TARGET:
      return "off heap target";
    case DEOPT_SCRIPT_OFFSET:
      return "deopt script offset";
    case DEOPT_INLINING_ID:
      return "deopt inlining id";
    case DEOPT_REASON:
      return "deopt reason";
    case DEOPT_ID:
      return "deopt index";
    case CONST_POOL:
      return "constant pool";
    case VENEER_POOL:
      return "veneer pool";
    case WASM_CALL:
      return "internal wasm call";
    case WASM_STUB_CALL:
      return "wasm stub call";
    case NUMBER_OF_MODES:
    case PC_JUMP:
      UNREACHABLE();
  }
  return "unknown relocation type";
}

void RelocInfo::Print(Isolate* isolate, std::ostream& os) {  // NOLINT
  os << reinterpret_cast<const void*>(pc_) << "  " << RelocModeName(rmode_);
451
  if (rmode_ == DEOPT_SCRIPT_OFFSET || rmode_ == DEOPT_INLINING_ID) {
452 453 454 455
    os << "  (" << data() << ")";
  } else if (rmode_ == DEOPT_REASON) {
    os << "  ("
       << DeoptimizeReasonToString(static_cast<DeoptimizeReason>(data_)) << ")";
456
  } else if (rmode_ == FULL_EMBEDDED_OBJECT) {
457
    os << "  (" << Brief(target_object()) << ")";
458 459
  } else if (rmode_ == COMPRESSED_EMBEDDED_OBJECT) {
    os << "  (" << Brief(target_object()) << " compressed)";
460 461 462 463 464 465 466 467 468 469 470
  } else if (rmode_ == EXTERNAL_REFERENCE) {
    if (isolate) {
      ExternalReferenceEncoder ref_encoder(isolate);
      os << " ("
         << ref_encoder.NameOfAddress(isolate, target_external_reference())
         << ") ";
    }
    os << " (" << reinterpret_cast<const void*>(target_external_reference())
       << ")";
  } else if (IsCodeTargetMode(rmode_)) {
    const Address code_target = target_address();
471
    Code code = Code::GetCodeFromTargetAddress(code_target);
472 473 474 475 476 477 478 479 480 481
    DCHECK(code->IsCode());
    os << " (" << Code::Kind2String(code->kind());
    if (Builtins::IsBuiltin(code)) {
      os << " " << Builtins::name(code->builtin_index());
    }
    os << ")  (" << reinterpret_cast<const void*>(target_address()) << ")";
  } else if (IsRuntimeEntry(rmode_) && isolate->deoptimizer_data() != nullptr) {
    // Deoptimization bailouts are stored as runtime entries.
    DeoptimizeKind type;
    if (Deoptimizer::IsDeoptimizationEntry(isolate, target_address(), &type)) {
482 483
      os << "  (" << Deoptimizer::MessageFor(type)
         << " deoptimization bailout)";
484 485 486 487 488 489 490 491 492 493 494 495
    }
  } else if (IsConstPool(rmode_)) {
    os << " (size " << static_cast<int>(data_) << ")";
  }

  os << "\n";
}
#endif  // ENABLE_DISASSEMBLER

#ifdef VERIFY_HEAP
void RelocInfo::Verify(Isolate* isolate) {
  switch (rmode_) {
496 497
    case COMPRESSED_EMBEDDED_OBJECT:
    case FULL_EMBEDDED_OBJECT:
498 499 500 501 502 503 504 505
      Object::VerifyPointer(isolate, target_object());
      break;
    case CODE_TARGET:
    case RELATIVE_CODE_TARGET: {
      // convert inline target address to code object
      Address addr = target_address();
      CHECK_NE(addr, kNullAddress);
      // Check that we can find the right code object.
506
      Code code = Code::GetCodeFromTargetAddress(addr);
507
      Object found = isolate->FindCodeObject(addr);
508 509 510 511 512 513 514 515
      CHECK(found->IsCode());
      CHECK(code->address() == HeapObject::cast(found)->address());
      break;
    }
    case INTERNAL_REFERENCE:
    case INTERNAL_REFERENCE_ENCODED: {
      Address target = target_internal_reference();
      Address pc = target_internal_reference_address();
516
      Code code = Code::cast(isolate->FindCodeObject(pc));
517 518 519 520 521 522 523
      CHECK(target >= code->InstructionStart());
      CHECK(target <= code->InstructionEnd());
      break;
    }
    case OFF_HEAP_TARGET: {
      Address addr = target_off_heap_target();
      CHECK_NE(addr, kNullAddress);
524
      CHECK(!InstructionStream::TryLookupCode(isolate, addr).is_null());
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547
      break;
    }
    case RUNTIME_ENTRY:
    case EXTERNAL_REFERENCE:
    case DEOPT_SCRIPT_OFFSET:
    case DEOPT_INLINING_ID:
    case DEOPT_REASON:
    case DEOPT_ID:
    case CONST_POOL:
    case VENEER_POOL:
    case WASM_CALL:
    case WASM_STUB_CALL:
    case NONE:
      break;
    case NUMBER_OF_MODES:
    case PC_JUMP:
      UNREACHABLE();
  }
}
#endif  // VERIFY_HEAP

}  // namespace internal
}  // namespace v8