reloc-info.cc 19.3 KB
Newer Older
1 2 3 4
// 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.

5
#include "src/codegen/reloc-info.h"
6

7
#include "src/base/vlq.h"
8 9
#include "src/codegen/assembler-inl.h"
#include "src/codegen/code-reference.h"
10
#include "src/codegen/external-reference-encoder.h"
11 12
#include "src/deoptimizer/deoptimize-reason.h"
#include "src/deoptimizer/deoptimizer.h"
13 14
#include "src/heap/heap-write-barrier-inl.h"
#include "src/objects/code-inl.h"
15
#include "src/snapshot/embedded/embedded-data.h"
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

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
60
//                               1 [7 bits data]
61
//                                  ...
62 63
//                               0 [7 bits data]
//               (Bits 6..31 of pc delta, encoded with VLQ.)
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85

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;

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);
86 87 88 89 90 91
  base::VLQEncodeUnsigned(
      [this](byte byte) {
        *--pos_ = byte;
        return pos_;
      },
      pc_jump);
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
  // 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.
146
  if (rmode == RelocInfo::FULL_EMBEDDED_OBJECT) {
147 148 149 150 151 152 153 154
    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);
155
    if (RelocInfo::IsDeoptReason(rmode)) {
156 157 158 159
      DCHECK_LT(rinfo->data(), 1 << kBitsPerByte);
      WriteShortData(rinfo->data());
    } else if (RelocInfo::IsConstPool(rmode) ||
               RelocInfo::IsVeneerPool(rmode) || RelocInfo::IsDeoptId(rmode) ||
160 161
               RelocInfo::IsDeoptPosition(rmode) ||
               RelocInfo::IsDeoptNodeId(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
      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
202 203
  // pc jump as a VLQ encoded integer.
  uint32_t pc_jump = base::VLQDecodeUnsigned([this] { return *--pos_; });
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
  // 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();
225
      if (SetMode(RelocInfo::FULL_EMBEDDED_OBJECT)) return;
226 227 228 229 230 231 232 233 234 235 236 237 238
    } 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();
239
        if (RelocInfo::IsDeoptReason(rmode)) {
240 241 242 243 244 245 246 247
          Advance();
          if (SetMode(rmode)) {
            ReadShortData();
            return;
          }
        } else if (RelocInfo::IsConstPool(rmode) ||
                   RelocInfo::IsVeneerPool(rmode) ||
                   RelocInfo::IsDeoptId(rmode) ||
248 249
                   RelocInfo::IsDeoptPosition(rmode) ||
                   RelocInfo::IsDeoptNodeId(rmode)) {
250 251 252 253 254 255 256 257 258 259 260 261 262 263
          if (SetMode(rmode)) {
            AdvanceReadInt();
            return;
          }
          Advance(kIntSize);
        } else if (SetMode(static_cast<RelocInfo::Mode>(rmode))) {
          return;
        }
      }
    }
  }
  done_ = true;
}

264
RelocIterator::RelocIterator(Code code, int mode_mask)
265
    : RelocIterator(code, code.unchecked_relocation_info(), mode_mask) {}
266

267
RelocIterator::RelocIterator(Code code, ByteArray relocation_info,
268
                             int mode_mask)
269 270 271
    : RelocIterator(code, code.raw_instruction_start(), code.constant_pool(),
                    relocation_info.GetDataEndAddress(),
                    relocation_info.GetDataStartAddress(), mode_mask) {}
272 273

RelocIterator::RelocIterator(const CodeReference code_reference, int mode_mask)
274
    : RelocIterator(Code(), code_reference.instruction_start(),
275 276 277 278
                    code_reference.constant_pool(),
                    code_reference.relocation_end(),
                    code_reference.relocation_start(), mode_mask) {}

279
RelocIterator::RelocIterator(EmbeddedData* embedded_data, Code code,
280
                             int mode_mask)
281 282 283 284 285
    : RelocIterator(code,
                    embedded_data->InstructionStartOfBuiltin(code.builtin_id()),
                    code.constant_pool(),
                    code.relocation_start() + code.relocation_size(),
                    code.relocation_start(), mode_mask) {}
286 287

RelocIterator::RelocIterator(const CodeDesc& desc, int mode_mask)
288
    : RelocIterator(Code(), reinterpret_cast<Address>(desc.buffer), 0,
289 290 291 292
                    desc.buffer + desc.buffer_size,
                    desc.buffer + desc.buffer_size - desc.reloc_size,
                    mode_mask) {}

293 294 295
RelocIterator::RelocIterator(base::Vector<byte> instructions,
                             base::Vector<const byte> reloc_info,
                             Address const_pool, int mode_mask)
296 297 298
    : RelocIterator(Code(), reinterpret_cast<Address>(instructions.begin()),
                    const_pool, reloc_info.begin() + reloc_info.size(),
                    reloc_info.begin(), mode_mask) {}
299

300
RelocIterator::RelocIterator(Code host, Address pc, Address constant_pool,
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317
                             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) || \
318
    defined(V8_TARGET_ARCH_X64)
319
  return false;
320 321
#elif defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_MIPS) || \
    defined(V8_TARGET_ARCH_MIPS64) || defined(V8_TARGET_ARCH_PPC) ||  \
Brice Dobry's avatar
Brice Dobry committed
322
    defined(V8_TARGET_ARCH_PPC64) || defined(V8_TARGET_ARCH_S390) ||  \
323
    defined(V8_TARGET_ARCH_RISCV64) || defined(V8_TARGET_ARCH_LOONG64)
324 325 326 327 328 329 330 331 332 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
  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);
359
  if (write_barrier_mode == UPDATE_WRITE_BARRIER && !host().is_null() &&
360
      IsCodeTargetMode(rmode_) && !FLAG_disable_write_barriers) {
361
    Code target_code = Code::GetCodeFromTargetAddress(target);
362
    WriteBarrier::Marking(host(), this, target_code);
363 364 365
  }
}

366 367 368 369 370
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 =
371 372 373 374
      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);
375 376
#else
  static constexpr int kTargetAddressAddressModeMask =
377
      ModeMask(CODE_TARGET) | ModeMask(RELATIVE_CODE_TARGET) |
378
      ModeMask(FULL_EMBEDDED_OBJECT) | ModeMask(EXTERNAL_REFERENCE) |
379
      ModeMask(OFF_HEAP_TARGET) | ModeMask(RUNTIME_ENTRY) | ModeMask(WASM_CALL);
380 381 382 383
#endif
  return (ModeMask(rmode_) & kTargetAddressAddressModeMask) != 0;
}

384 385 386 387 388
bool RelocInfo::RequiresRelocationAfterCodegen(const CodeDesc& desc) {
  RelocIterator it(desc, RelocInfo::PostCodegenRelocationMask());
  return !it.done();
}

389
bool RelocInfo::RequiresRelocation(Code code) {
390
  RelocIterator it(code, RelocInfo::kApplyMask);
391 392 393 394 395 396
  return !it.done();
}

#ifdef ENABLE_DISASSEMBLER
const char* RelocInfo::RelocModeName(RelocInfo::Mode rmode) {
  switch (rmode) {
397
    case NO_INFO:
398
      return "no reloc";
399 400 401 402
    case COMPRESSED_EMBEDDED_OBJECT:
      return "compressed embedded object";
    case FULL_EMBEDDED_OBJECT:
      return "full embedded object";
403 404
    case DATA_EMBEDDED_OBJECT:
      return "data embedded object";
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
    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";
427 428
    case LITERAL_CONSTANT:
      return "literal constant";
429 430
    case DEOPT_NODE_ID:
      return "deopt node id";
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
    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";
}

446
void RelocInfo::Print(Isolate* isolate, std::ostream& os) {
447
  os << reinterpret_cast<const void*>(pc_) << "  " << RelocModeName(rmode_);
448
  if (rmode_ == DEOPT_SCRIPT_OFFSET || rmode_ == DEOPT_INLINING_ID) {
449 450 451 452
    os << "  (" << data() << ")";
  } else if (rmode_ == DEOPT_REASON) {
    os << "  ("
       << DeoptimizeReasonToString(static_cast<DeoptimizeReason>(data_)) << ")";
453
  } else if (rmode_ == FULL_EMBEDDED_OBJECT) {
454
    os << "  (" << Brief(target_object(isolate)) << ")";
455
  } else if (rmode_ == COMPRESSED_EMBEDDED_OBJECT) {
456
    os << "  (" << Brief(target_object(isolate)) << " compressed)";
457 458 459 460 461 462 463 464 465 466 467
  } 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();
468
    Code code = Code::GetCodeFromTargetAddress(code_target);
469
    DCHECK(code.IsCode());
470
    os << " (" << CodeKindToString(code.kind());
471
    if (Builtins::IsBuiltin(code)) {
472
      os << " " << Builtins::name(code.builtin_id());
473 474
    }
    os << ")  (" << reinterpret_cast<const void*>(target_address()) << ")";
475
  } else if (IsRuntimeEntry(rmode_)) {
476 477 478
    // Deoptimization bailouts are stored as runtime entries.
    DeoptimizeKind type;
    if (Deoptimizer::IsDeoptimizationEntry(isolate, target_address(), &type)) {
479
      os << "  (" << Deoptimizer::MessageFor(type)
480
         << " deoptimization bailout)";
481 482 483 484 485 486 487 488 489 490 491 492
    }
  } 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_) {
493
    case COMPRESSED_EMBEDDED_OBJECT:
494
      Object::VerifyPointer(isolate, target_object(isolate));
495
      break;
496
    case FULL_EMBEDDED_OBJECT:
497
    case DATA_EMBEDDED_OBJECT:
498
      Object::VerifyAnyTagged(isolate, target_object(isolate));
499 500 501 502 503 504 505
      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
      CHECK(found.IsCode());
      CHECK(code.address() == HeapObject::cast(found).address());
510 511 512 513 514 515
      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
      CHECK(target >= code.InstructionStart(isolate, pc));
      CHECK(target <= code.InstructionEnd(isolate, pc));
519 520 521 522 523
      break;
    }
    case OFF_HEAP_TARGET: {
      Address addr = target_off_heap_target();
      CHECK_NE(addr, kNullAddress);
524
      CHECK(Builtins::IsBuiltinId(
525
          OffHeapInstructionStream::TryLookupCode(isolate, addr)));
526 527 528 529 530 531 532 533
      break;
    }
    case RUNTIME_ENTRY:
    case EXTERNAL_REFERENCE:
    case DEOPT_SCRIPT_OFFSET:
    case DEOPT_INLINING_ID:
    case DEOPT_REASON:
    case DEOPT_ID:
534
    case LITERAL_CONSTANT:
535
    case DEOPT_NODE_ID:
536 537 538 539
    case CONST_POOL:
    case VENEER_POOL:
    case WASM_CALL:
    case WASM_STUB_CALL:
540
    case NO_INFO:
541 542 543 544 545 546 547 548 549 550
      break;
    case NUMBER_OF_MODES:
    case PC_JUMP:
      UNREACHABLE();
  }
}
#endif  // VERIFY_HEAP

}  // namespace internal
}  // namespace v8