objects-printer.cc 96.2 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5
#include <iomanip>
6 7
#include <memory>

8
#include "src/common/globals.h"
9 10
#include "src/diagnostics/disasm.h"
#include "src/diagnostics/disassembler.h"
11
#include "src/execution/isolate-utils-inl.h"
12 13
#include "src/heap/heap-inl.h"                // For InOldSpace.
#include "src/heap/heap-write-barrier-inl.h"  // For GetIsolateFromWritableObj.
14
#include "src/ic/handler-configuration-inl.h"
15
#include "src/init/bootstrapper.h"
16
#include "src/interpreter/bytecodes.h"
17
#include "src/objects/all-objects-inl.h"
18
#include "src/objects/code-kind.h"
19
#include "src/regexp/regexp.h"
20
#include "src/snapshot/embedded/embedded-data.h"
21
#include "src/utils/ostreams.h"
22 23 24

#if V8_ENABLE_WEBASSEMBLY
#include "src/debug/debug-wasm-objects-inl.h"
25 26 27
#include "src/wasm/wasm-code-manager.h"
#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-objects-inl.h"
28 29
#endif  // V8_ENABLE_WEBASSEMBLY

30 31 32 33 34
namespace v8 {
namespace internal {

#ifdef OBJECT_PRINT

35
void Object::Print() const {
36 37 38 39 40
  // Output into debugger's command window if a debugger is attached.
  DbgStdoutStream dbg_os;
  this->Print(dbg_os);
  dbg_os << std::flush;

41
  StdoutStream os;
42
  this->Print(os);
43
  os << std::flush;
44 45
}

46
void Object::Print(std::ostream& os) const {
47
  if (IsSmi()) {
48 49
    os << "Smi: " << std::hex << "0x" << Smi::ToInt(*this);
    os << std::dec << " (" << Smi::ToInt(*this) << ")\n";
50
  } else {
51
    HeapObject::cast(*this).HeapObjectPrint(os);
52 53 54
  }
}

55 56 57
namespace {

void PrintHeapObjectHeaderWithoutMap(HeapObject object, std::ostream& os,
58
                                     const char* id) {
59
  os << reinterpret_cast<void*>(object.ptr()) << ": [";
60 61 62
  if (id != nullptr) {
    os << id;
  } else {
63
    os << object.map().instance_type();
64 65
  }
  os << "]";
66
  if (ReadOnlyHeap::Contains(object)) {
67
    os << " in ReadOnlySpace";
68
  } else if (GetHeapFromWritableObject(object)->InOldSpace(object)) {
69 70
    os << " in OldSpace";
  }
71 72
}

73 74
template <typename T>
void PrintDictionaryContents(std::ostream& os, T dict) {
75
  DisallowGarbageCollection no_gc;
76 77
  ReadOnlyRoots roots = dict.GetReadOnlyRoots();

78 79 80 81
  if (dict.Capacity() == 0) {
    return;
  }

82
#ifdef V8_ENABLE_SWISS_NAME_DICTIONARY
83 84 85
  Isolate* isolate = GetIsolateFromWritableObject(dict);
  // IterateEntries for SwissNameDictionary needs to create a handle.
  HandleScope scope(isolate);
86
#endif
87 88 89 90 91 92 93 94 95 96 97 98 99
  for (InternalIndex i : dict.IterateEntries()) {
    Object k;
    if (!dict.ToKey(roots, i, &k)) continue;
    os << "\n   ";
    if (k.IsString()) {
      String::cast(k).PrintUC16(os);
    } else {
      os << Brief(k);
    }
    os << ": " << Brief(dict.ValueAt(i)) << " ";
    dict.DetailsAt(i).PrintAsSlowTo(os, !T::kIsOrderedDictionaryType);
  }
}
100 101
}  // namespace

102
void HeapObject::PrintHeader(std::ostream& os, const char* id) {
103
  PrintHeapObjectHeaderWithoutMap(*this, os, id);
104 105 106
  if (!IsMap()) os << "\n - map: " << Brief(map());
}

107
void HeapObject::HeapObjectPrint(std::ostream& os) {
108
  InstanceType instance_type = map().instance_type();
109 110

  if (instance_type < FIRST_NONSTRING_TYPE) {
111
    String::cast(*this).StringPrint(os);
112
    os << "\n";
113 114 115 116
    return;
  }

  switch (instance_type) {
117
    case AWAIT_CONTEXT_TYPE:
118 119 120 121 122 123 124 125
    case BLOCK_CONTEXT_TYPE:
    case CATCH_CONTEXT_TYPE:
    case DEBUG_EVALUATE_CONTEXT_TYPE:
    case EVAL_CONTEXT_TYPE:
    case FUNCTION_CONTEXT_TYPE:
    case MODULE_CONTEXT_TYPE:
    case SCRIPT_CONTEXT_TYPE:
    case WITH_CONTEXT_TYPE:
126
    case SCRIPT_CONTEXT_TABLE_TYPE:
127
      Context::cast(*this).ContextPrint(os);
128 129
      break;
    case NATIVE_CONTEXT_TYPE:
130
      NativeContext::cast(*this).NativeContextPrint(os);
131
      break;
132
    case HASH_TABLE_TYPE:
133 134
      ObjectHashTable::cast(*this).ObjectHashTablePrint(os);
      break;
135
    case ORDERED_HASH_MAP_TYPE:
136 137
      OrderedHashMap::cast(*this).OrderedHashMapPrint(os);
      break;
138
    case ORDERED_HASH_SET_TYPE:
139 140
      OrderedHashSet::cast(*this).OrderedHashSetPrint(os);
      break;
141
    case ORDERED_NAME_DICTIONARY_TYPE:
142 143
      OrderedNameDictionary::cast(*this).OrderedNameDictionaryPrint(os);
      break;
144
    case NAME_DICTIONARY_TYPE:
145 146
      NameDictionary::cast(*this).NameDictionaryPrint(os);
      break;
147
    case GLOBAL_DICTIONARY_TYPE:
148 149
      GlobalDictionary::cast(*this).GlobalDictionaryPrint(os);
      break;
150
    case SIMPLE_NUMBER_DICTIONARY_TYPE:
151
      FixedArray::cast(*this).FixedArrayPrint(os);
152
      break;
153
    case NUMBER_DICTIONARY_TYPE:
154
      NumberDictionary::cast(*this).NumberDictionaryPrint(os);
155
      break;
156
    case EPHEMERON_HASH_TABLE_TYPE:
157
      EphemeronHashTable::cast(*this).EphemeronHashTablePrint(os);
158
      break;
159
    case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
160
      ObjectBoilerplateDescription::cast(*this)
161
          .ObjectBoilerplateDescriptionPrint(os);
162
      break;
163
    case TRANSITION_ARRAY_TYPE:
164
      TransitionArray::cast(*this).TransitionArrayPrint(os);
165
      break;
166
    case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
167
      ClosureFeedbackCellArray::cast(*this).ClosureFeedbackCellArrayPrint(os);
168
      break;
169

170
    case FILLER_TYPE:
171
      os << "filler";
172
      break;
173
    case JS_API_OBJECT_TYPE:
174
    case JS_ARRAY_ITERATOR_PROTOTYPE_TYPE:
175
    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
176
    case JS_ERROR_TYPE:
177 178 179 180 181 182 183 184 185
    case JS_ITERATOR_PROTOTYPE_TYPE:
    case JS_MAP_ITERATOR_PROTOTYPE_TYPE:
    case JS_OBJECT_PROTOTYPE_TYPE:
    case JS_PROMISE_PROTOTYPE_TYPE:
    case JS_REG_EXP_PROTOTYPE_TYPE:
    case JS_SET_ITERATOR_PROTOTYPE_TYPE:
    case JS_SET_PROTOTYPE_TYPE:
    case JS_SPECIAL_API_OBJECT_TYPE:
    case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
186
    case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
187
      JSObject::cast(*this).JSObjectPrint(os);
188
      break;
189
#if V8_ENABLE_WEBASSEMBLY
190
    case WASM_INSTANCE_OBJECT_TYPE:
191
      WasmInstanceObject::cast(*this).WasmInstanceObjectPrint(os);
192
      break;
193 194 195
    case WASM_VALUE_OBJECT_TYPE:
      WasmValueObject::cast(*this).WasmValueObjectPrint(os);
      break;
196
#endif  // V8_ENABLE_WEBASSEMBLY
197
    case CODE_TYPE:
198
      Code::cast(*this).CodePrint(os);
199
      break;
200
    case CODE_DATA_CONTAINER_TYPE:
201
      CodeDataContainer::cast(*this).CodeDataContainerPrint(os);
202
      break;
203 204
    case JS_SET_KEY_VALUE_ITERATOR_TYPE:
    case JS_SET_VALUE_ITERATOR_TYPE:
205
      JSSetIterator::cast(*this).JSSetIteratorPrint(os);
206
      break;
207 208 209
    case JS_MAP_KEY_ITERATOR_TYPE:
    case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
    case JS_MAP_VALUE_ITERATOR_TYPE:
210
      JSMapIterator::cast(*this).JSMapIteratorPrint(os);
211
      break;
212 213 214
#define MAKE_TORQUE_CASE(Name, TYPE)   \
  case TYPE:                           \
    Name::cast(*this).Name##Print(os); \
215
    break;
216 217 218
      // Every class that has its fields defined in a .tq file and corresponds
      // to exactly one InstanceType value is included in the following list.
      TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
219
      TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
220
#undef MAKE_TORQUE_CASE
221

222
    case ALLOCATION_SITE_TYPE:
223
      AllocationSite::cast(*this).AllocationSitePrint(os);
224
      break;
225
    case LOAD_HANDLER_TYPE:
226
      LoadHandler::cast(*this).LoadHandlerPrint(os);
227 228
      break;
    case STORE_HANDLER_TYPE:
229
      StoreHandler::cast(*this).StoreHandlerPrint(os);
230
      break;
231
    case FEEDBACK_METADATA_TYPE:
232
      FeedbackMetadata::cast(*this).FeedbackMetadataPrint(os);
233
      break;
234 235 236 237 238 239 240 241 242
    case JS_PROMISE_CONSTRUCTOR_TYPE:
    case JS_REG_EXP_CONSTRUCTOR_TYPE:
    case JS_ARRAY_CONSTRUCTOR_TYPE:
#define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
  case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
      TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
#undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
      JSFunction::cast(*this).JSFunctionPrint(os);
      break;
243 244 245 246
    case INTERNALIZED_STRING_TYPE:
    case EXTERNAL_INTERNALIZED_STRING_TYPE:
    case ONE_BYTE_INTERNALIZED_STRING_TYPE:
    case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
247 248
    case UNCACHED_EXTERNAL_INTERNALIZED_STRING_TYPE:
    case UNCACHED_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
249 250 251 252 253 254 255 256 257 258
    case STRING_TYPE:
    case CONS_STRING_TYPE:
    case EXTERNAL_STRING_TYPE:
    case SLICED_STRING_TYPE:
    case THIN_STRING_TYPE:
    case ONE_BYTE_STRING_TYPE:
    case CONS_ONE_BYTE_STRING_TYPE:
    case EXTERNAL_ONE_BYTE_STRING_TYPE:
    case SLICED_ONE_BYTE_STRING_TYPE:
    case THIN_ONE_BYTE_STRING_TYPE:
259 260
    case UNCACHED_EXTERNAL_STRING_TYPE:
    case UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE:
261
      // TODO(all): Handle these types too.
262
      os << "UNKNOWN TYPE " << map().instance_type();
263 264 265 266
      UNREACHABLE();
  }
}

267
void ByteArray::ByteArrayPrint(std::ostream& os) {
268 269 270 271
  PrintHeader(os, "ByteArray");
  os << "\n - length: " << length()
     << "\n - data-start: " << static_cast<void*>(GetDataStartAddress())
     << "\n";
272 273
}

274
void BytecodeArray::BytecodeArrayPrint(std::ostream& os) {
275
  PrintHeader(os, "BytecodeArray");
276
  os << "\n";
277
  Disassemble(os);
278 279
}

280
void FreeSpace::FreeSpacePrint(std::ostream& os) {
281
  os << "free space, size " << Size() << "\n";
282 283
}

284
bool JSObject::PrintProperties(std::ostream& os) {
285
  if (HasFastProperties()) {
286
    DescriptorArray descs = map().instance_descriptors(GetIsolate());
287
    int nof_inobject_properties = map().GetInObjectProperties();
288
    for (InternalIndex i : map().IterateOwnDescriptors()) {
289
      os << "\n    ";
290
      descs.GetKey(i).NamePrint(os);
291
      os << ": ";
292
      PropertyDetails details = descs.GetDetails(i);
293 294
      switch (details.location()) {
        case kField: {
295
          FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
296
          os << Brief(RawFastPropertyAt(field_index));
297 298
          break;
        }
299
        case kDescriptor:
300
          os << Brief(descs.GetStrongValue(i));
301
          break;
302
      }
303 304
      os << " ";
      details.PrintAsFastTo(os, PropertyDetails::kForProperties);
305 306 307 308 309 310 311 312 313 314
      if (details.location() == kField) {
        int field_index = details.field_index();
        if (field_index < nof_inobject_properties) {
          os << ", location: in-object";
        } else {
          field_index -= nof_inobject_properties;
          os << ", location: properties[" << field_index << "]";
        }
      } else {
        os << ", location: descriptor";
315
      }
316
    }
317
    return map().NumberOfOwnDescriptors() > 0;
318
  } else if (IsJSGlobalObject()) {
319 320
    PrintDictionaryContents(
        os, JSGlobalObject::cast(*this).global_dictionary(kAcquireLoad));
321
  } else if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
322
    PrintDictionaryContents(os, property_dictionary_swiss());
323
  } else {
324
    PrintDictionaryContents(os, property_dictionary());
325
  }
326
  return true;
327 328
}

329 330 331
namespace {

template <class T>
332
bool IsTheHoleAt(T array, int index) {
333
  return false;
334 335
}

336
template <>
337
bool IsTheHoleAt(FixedDoubleArray array, int index) {
338
  return array.is_the_hole(index);
339 340
}

341
template <class T>
342
double GetScalarElement(T array, int index) {
343 344 345
  if (IsTheHoleAt(array, index)) {
    return std::numeric_limits<double>::quiet_NaN();
  }
346
  return array.get_scalar(index);
347 348
}

349
template <class T>
350
void DoPrintElements(std::ostream& os, Object object, int length) {
351
  const bool print_the_hole = std::is_same<T, FixedDoubleArray>::value;
352
  T array = T::cast(object);
353
  if (length == 0) return;
354
  int previous_index = 0;
355
  double previous_value = GetScalarElement(array, 0);
356 357
  double value = 0.0;
  int i;
358 359
  for (i = 1; i <= length; i++) {
    if (i < length) value = GetScalarElement(array, i);
360
    bool values_are_nan = std::isnan(previous_value) && std::isnan(value);
361
    if (i != length && (previous_value == value || values_are_nan) &&
362
        IsTheHoleAt(array, i - 1) == IsTheHoleAt(array, i)) {
363 364 365 366 367 368 369 370 371
      continue;
    }
    os << "\n";
    std::stringstream ss;
    ss << previous_index;
    if (previous_index != i - 1) {
      ss << '-' << (i - 1);
    }
    os << std::setw(12) << ss.str() << ": ";
372
    if (print_the_hole && IsTheHoleAt(array, i - 1)) {
373 374 375 376 377 378
      os << "<the_hole>";
    } else {
      os << previous_value;
    }
    previous_index = i;
    previous_value = value;
379 380 381
  }
}

382 383
template <typename ElementType>
void PrintTypedArrayElements(std::ostream& os, const ElementType* data_ptr,
384
                             size_t length, bool is_on_heap) {
385 386
  if (length == 0) return;
  size_t previous_index = 0;
387 388 389 390 391 392
  if (i::FLAG_mock_arraybuffer_allocator && !is_on_heap) {
    // Don't try to print data that's not actually allocated.
    os << "\n    0-" << length << ": <mocked array buffer bytes>";
    return;
  }

393 394 395 396 397 398 399 400 401 402 403 404 405
  ElementType previous_value = data_ptr[0];
  ElementType value = 0;
  for (size_t i = 1; i <= length; i++) {
    if (i < length) value = data_ptr[i];
    if (i != length && previous_value == value) {
      continue;
    }
    os << "\n";
    std::stringstream ss;
    ss << previous_index;
    if (previous_index != i - 1) {
      ss << '-' << (i - 1);
    }
406
    os << std::setw(12) << ss.str() << ": " << +previous_value;
407 408 409 410 411
    previous_index = i;
    previous_value = value;
  }
}

412
template <typename T>
413
void PrintFixedArrayElements(std::ostream& os, T array) {
414
  // Print in array notation for non-sparse arrays.
415
  Object previous_value = array.length() > 0 ? array.get(0) : Object();
416
  Object value;
417 418
  int previous_index = 0;
  int i;
419 420 421
  for (i = 1; i <= array.length(); i++) {
    if (i < array.length()) value = array.get(i);
    if (previous_value == value && i != array.length()) {
422 423 424 425 426 427 428 429 430 431 432 433 434 435
      continue;
    }
    os << "\n";
    std::stringstream ss;
    ss << previous_index;
    if (previous_index != i - 1) {
      ss << '-' << (i - 1);
    }
    os << std::setw(12) << ss.str() << ": " << Brief(previous_value);
    previous_index = i;
    previous_value = value;
  }
}

436
void PrintDictionaryElements(std::ostream& os, FixedArrayBase elements) {
437
  // Print some internal fields
438
  NumberDictionary dict = NumberDictionary::cast(elements);
439
  if (dict.requires_slow_elements()) {
440 441
    os << "\n   - requires_slow_elements";
  } else {
442
    os << "\n   - max_number_key: " << dict.max_number_key();
443
  }
444
  PrintDictionaryContents(os, dict);
445 446
}

447
void PrintSloppyArgumentElements(std::ostream& os, ElementsKind kind,
448
                                 SloppyArgumentsElements elements) {
449 450
  FixedArray arguments_store = elements.arguments();
  os << "\n    0: context: " << Brief(elements.context())
451
     << "\n    1: arguments_store: " << Brief(arguments_store)
452
     << "\n    parameter to context slot map:";
453
  for (int i = 0; i < elements.length(); i++) {
454
    Object mapped_entry = elements.mapped_entries(i, kRelaxedLoad);
455
    os << "\n    " << i << ": param(" << i << "): " << Brief(mapped_entry);
456
    if (mapped_entry.IsTheHole()) {
Mathias Bynens's avatar
Mathias Bynens committed
457
      os << " in the arguments_store[" << i << "]";
458 459 460
    } else {
      os << " in the context";
    }
461
  }
462
  if (arguments_store.length() == 0) return;
463
  os << "\n }"
464
     << "\n - arguments_store: " << Brief(arguments_store) << " "
465
     << ElementsKindToString(arguments_store.map().elements_kind()) << " {";
466 467 468 469
  if (kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
    PrintFixedArrayElements(os, arguments_store);
  } else {
    DCHECK_EQ(kind, SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
470
    PrintDictionaryElements(os, arguments_store);
471 472 473
  }
}

474
void PrintEmbedderData(Isolate* isolate, std::ostream& os,
475
                       EmbedderDataSlot slot) {
476
  DisallowGarbageCollection no_gc;
477
  Object value = slot.load_tagged();
478 479
  os << Brief(value);
  void* raw_pointer;
480
  if (slot.ToAlignedPointer(isolate, &raw_pointer)) {
481 482 483 484
    os << ", aligned pointer: " << raw_pointer;
  }
}

485
}  // namespace
486

487
void JSObject::PrintElements(std::ostream& os) {
488 489
  // Don't call GetElementsKind, its validation code can cause the printer to
  // fail when debugging.
490
  os << " - elements: " << Brief(elements()) << " {";
491
  switch (map().elements_kind()) {
492 493 494
    case HOLEY_SMI_ELEMENTS:
    case PACKED_SMI_ELEMENTS:
    case HOLEY_ELEMENTS:
495 496
    case HOLEY_FROZEN_ELEMENTS:
    case HOLEY_SEALED_ELEMENTS:
497
    case HOLEY_NONEXTENSIBLE_ELEMENTS:
498
    case PACKED_ELEMENTS:
499 500
    case PACKED_FROZEN_ELEMENTS:
    case PACKED_SEALED_ELEMENTS:
501
    case PACKED_NONEXTENSIBLE_ELEMENTS:
502
    case FAST_STRING_WRAPPER_ELEMENTS: {
503
      PrintFixedArrayElements(os, FixedArray::cast(elements()));
504 505
      break;
    }
506 507
    case HOLEY_DOUBLE_ELEMENTS:
    case PACKED_DOUBLE_ELEMENTS: {
508
      DoPrintElements<FixedDoubleArray>(os, elements(), elements().length());
509 510
      break;
    }
511

512 513
#define PRINT_ELEMENTS(Type, type, TYPE, elementType)                         \
  case TYPE##_ELEMENTS: {                                                     \
514
    size_t length = JSTypedArray::cast(*this).GetLength();                    \
515
    bool is_on_heap = JSTypedArray::cast(*this).is_on_heap();                 \
516 517
    const elementType* data_ptr =                                             \
        static_cast<const elementType*>(JSTypedArray::cast(*this).DataPtr()); \
518
    PrintTypedArrayElements<elementType>(os, data_ptr, length, is_on_heap);   \
519
    break;                                                                    \
520
  }
521
      TYPED_ARRAYS(PRINT_ELEMENTS)
522
      RAB_GSAB_TYPED_ARRAYS(PRINT_ELEMENTS)
523 524
#undef PRINT_ELEMENTS

525
    case DICTIONARY_ELEMENTS:
526
    case SLOW_STRING_WRAPPER_ELEMENTS:
527
      PrintDictionaryElements(os, elements());
528
      break;
529
    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
530
    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
531
      PrintSloppyArgumentElements(os, map().elements_kind(),
532
                                  SloppyArgumentsElements::cast(elements()));
533
      break;
534 535 536 537
    case WASM_ARRAY_ELEMENTS:
      // WasmArrayPrint() should be called intead.
      UNREACHABLE();
      break;
538 539
    case NO_ELEMENTS:
      break;
540
  }
541
  os << "\n }\n";
542 543
}

544
static void JSObjectPrintHeader(std::ostream& os, JSObject obj,
545
                                const char* id) {
546 547
  Isolate* isolate = obj.GetIsolate();
  obj.PrintHeader(os, id);
548 549
  // Don't call GetElementsKind, its validation code can cause the printer to
  // fail when debugging.
550
  os << " [";
551
  if (obj.HasFastProperties()) {
552 553 554
    os << "FastProperties";
  } else {
    os << "DictionaryProperties";
555
  }
556
  PrototypeIterator iter(isolate, obj);
557
  os << "]\n - prototype: " << Brief(iter.GetCurrent());
558 559 560
  os << "\n - elements: " << Brief(obj.elements()) << " ["
     << ElementsKindToString(obj.map().elements_kind());
  if (obj.elements().IsCowArray()) os << " (COW)";
561
  os << "]";
562 563
  Object hash = obj.GetHash();
  if (hash.IsSmi()) {
564
    os << "\n - hash: " << Brief(hash);
565
  }
566 567
  if (obj.GetEmbedderFieldCount() > 0) {
    os << "\n - embedder fields: " << obj.GetEmbedderFieldCount();
568
  }
569 570
}

571
static void JSObjectPrintBody(std::ostream& os, JSObject obj,
572
                              bool print_elements = true) {
573
  os << "\n - properties: ";
574
  Object properties_or_hash = obj.raw_properties_or_hash(kRelaxedLoad);
575
  if (!properties_or_hash.IsSmi()) {
576 577
    os << Brief(properties_or_hash);
  }
578
  os << "\n - All own properties (excluding elements): {";
579
  if (obj.PrintProperties(os)) os << "\n ";
580
  os << "}\n";
581

582
  if (print_elements) {
583
    size_t length = obj.IsJSTypedArray() ? JSTypedArray::cast(obj).GetLength()
584
                                         : obj.elements().length();
585
    if (length > 0) obj.PrintElements(os);
586
  }
587
  int embedder_fields = obj.GetEmbedderFieldCount();
588
  if (embedder_fields > 0) {
589
    Isolate* isolate = GetIsolateForHeapSandbox(obj);
590
    os << " - embedder fields = {";
591
    for (int i = 0; i < embedder_fields; i++) {
592
      os << "\n    ";
593
      PrintEmbedderData(isolate, os, EmbedderDataSlot(obj, i));
594 595 596
    }
    os << "\n }\n";
  }
597 598
}

599
void JSObject::JSObjectPrint(std::ostream& os) {
600 601
  JSObjectPrintHeader(os, *this, nullptr);
  JSObjectPrintBody(os, *this);
602 603
}

604
void JSGeneratorObject::JSGeneratorObjectPrint(std::ostream& os) {
605
  JSObjectPrintHeader(os, *this, "JSGeneratorObject");
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
  os << "\n - function: " << Brief(function());
  os << "\n - context: " << Brief(context());
  os << "\n - receiver: " << Brief(receiver());
  if (is_executing() || is_closed()) {
    os << "\n - input: " << Brief(input_or_debug_pos());
  } else {
    DCHECK(is_suspended());
    os << "\n - debug pos: " << Brief(input_or_debug_pos());
  }
  const char* mode = "(invalid)";
  switch (resume_mode()) {
    case kNext:
      mode = ".next()";
      break;
    case kReturn:
      mode = ".return()";
      break;
    case kThrow:
      mode = ".throw()";
      break;
  }
  os << "\n - resume mode: " << mode;
  os << "\n - continuation: " << continuation();
  if (is_closed()) os << " (closed)";
  if (is_executing()) os << " (executing)";
  if (is_suspended()) os << " (suspended)";
  if (is_suspended()) {
633
    DisallowGarbageCollection no_gc;
634 635 636 637 638
    SharedFunctionInfo fun_info = function().shared();
    if (fun_info.HasSourceCode()) {
      Script script = Script::cast(fun_info.script());
      String script_name = script.name().IsString()
                               ? String::cast(script.name())
639
                               : GetReadOnlyRoots().empty_string();
640 641 642 643

      os << "\n - source position: ";
      // Can't collect source positions here if not available as that would
      // allocate memory.
644
      Isolate* isolate = GetIsolate();
645
      if (fun_info.HasBytecodeArray() &&
646
          fun_info.GetBytecodeArray(isolate).HasSourcePositionTable()) {
647 648
        os << source_position();
        os << " (";
649 650 651
        script_name.PrintUC16(os);
        int lin = script.GetLineNumber(source_position()) + 1;
        int col = script.GetColumnNumber(source_position()) + 1;
652 653 654 655 656
        os << ", lin " << lin;
        os << ", col " << col;
      } else {
        os << "unavailable";
      }
657 658 659
      os << ")";
    }
  }
660
  os << "\n - register file: " << Brief(parameters_and_registers());
661
  JSObjectPrintBody(os, *this);
662 663
}

664
void JSArray::JSArrayPrint(std::ostream& os) {
665
  JSObjectPrintHeader(os, *this, "JSArray");
666
  os << "\n - length: " << Brief(this->length());
667
  JSObjectPrintBody(os, *this);
668 669
}

670
void JSPromise::JSPromisePrint(std::ostream& os) {
671
  JSObjectPrintHeader(os, *this, "JSPromise");
672
  os << "\n - status: " << JSPromise::Status(status());
673
  if (status() == Promise::kPending) {
674
    os << "\n - reactions: " << Brief(reactions());
675
  } else {
676
    os << "\n - result: " << Brief(result());
677
  }
678
  os << "\n - has_handler: " << has_handler();
679
  os << "\n - handled_hint: " << handled_hint();
680
  JSObjectPrintBody(os, *this);
681
}
682

683
void JSRegExp::JSRegExpPrint(std::ostream& os) {
684
  JSObjectPrintHeader(os, *this, "JSRegExp");
685 686
  os << "\n - data: " << Brief(data());
  os << "\n - source: " << Brief(source());
687
  JSObjectPrintBody(os, *this);
688 689
}

690
void JSRegExpStringIterator::JSRegExpStringIteratorPrint(std::ostream& os) {
691
  JSObjectPrintHeader(os, *this, "JSRegExpStringIterator");
692 693
  os << "\n - regex: " << Brief(iterating_reg_exp());
  os << "\n - string: " << Brief(iterated_string());
694 695 696
  os << "\n - done: " << done();
  os << "\n - global: " << global();
  os << "\n - unicode: " << unicode();
697
  JSObjectPrintBody(os, *this);
698
}
699

700
void Symbol::SymbolPrint(std::ostream& os) {
701
  PrintHeader(os, "Symbol");
702
  os << "\n - hash: " << hash();
703 704
  os << "\n - description: " << Brief(description());
  if (description().IsUndefined()) {
705
    os << " (" << PrivateSymbolToName() << ")";
706
  }
707
  os << "\n - private: " << is_private();
708
  os << "\n";
709 710
}

711
void DescriptorArray::DescriptorArrayPrint(std::ostream& os) {
712
  PrintHeader(os, "DescriptorArray");
713
  os << "\n - enum_cache: ";
714
  if (enum_cache().keys().length() == 0) {
715 716
    os << "empty";
  } else {
717 718 719
    os << enum_cache().keys().length();
    os << "\n   - keys: " << Brief(enum_cache().keys());
    os << "\n   - indices: " << Brief(enum_cache().indices());
720
  }
721
  os << "\n - nof slack descriptors: " << number_of_slack_descriptors();
722
  os << "\n - nof descriptors: " << number_of_descriptors();
723 724 725 726
  int16_t raw_marked = raw_number_of_marked_descriptors();
  os << "\n - raw marked descriptors: mc epoch "
     << NumberOfMarkedDescriptors::Epoch::decode(raw_marked) << ", marked "
     << NumberOfMarkedDescriptors::Marked::decode(raw_marked);
727 728
  PrintDescriptors(os);
}
729

730
namespace {
731
void PrintFixedArrayWithHeader(std::ostream& os, FixedArray array,
732
                               const char* type) {
733 734
  array.PrintHeader(os, type);
  os << "\n - length: " << array.length();
735 736 737
  PrintFixedArrayElements(os, array);
  os << "\n";
}
738

739 740
template <typename T>
void PrintWeakArrayElements(std::ostream& os, T* array) {
741
  // Print in array notation for non-sparse arrays.
742 743 744
  MaybeObject previous_value =
      array->length() > 0 ? array->Get(0) : MaybeObject(kNullAddress);
  MaybeObject value;
745 746 747 748 749 750 751 752 753 754 755 756 757
  int previous_index = 0;
  int i;
  for (i = 1; i <= array->length(); i++) {
    if (i < array->length()) value = array->Get(i);
    if (previous_value == value && i != array->length()) {
      continue;
    }
    os << "\n";
    std::stringstream ss;
    ss << previous_index;
    if (previous_index != i - 1) {
      ss << '-' << (i - 1);
    }
758
    os << std::setw(12) << ss.str() << ": " << Brief(previous_value);
759 760 761 762 763
    previous_index = i;
    previous_value = value;
  }
}

764
}  // namespace
765

766 767 768 769 770
void ObjectBoilerplateDescription::ObjectBoilerplateDescriptionPrint(
    std::ostream& os) {
  PrintFixedArrayWithHeader(os, *this, "ObjectBoilerplateDescription");
}

771
void EmbedderDataArray::EmbedderDataArrayPrint(std::ostream& os) {
772
  Isolate* isolate = GetIsolateForHeapSandbox(*this);
773 774
  PrintHeader(os, "EmbedderDataArray");
  os << "\n - length: " << length();
775 776 777
  EmbedderDataSlot start(*this, 0);
  EmbedderDataSlot end(*this, length());
  for (EmbedderDataSlot slot = start; slot < end; ++slot) {
778
    os << "\n    ";
779
    PrintEmbedderData(isolate, os, slot);
780 781 782 783 784
  }
  os << "\n";
}

void FixedArray::FixedArrayPrint(std::ostream& os) {
785
  PrintFixedArrayWithHeader(os, *this, "FixedArray");
786
}
787

788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815
namespace {
const char* SideEffectType2String(SideEffectType type) {
  switch (type) {
    case SideEffectType::kHasSideEffect:
      return "kHasSideEffect";
    case SideEffectType::kHasNoSideEffect:
      return "kHasNoSideEffect";
    case SideEffectType::kHasSideEffectToReceiver:
      return "kHasSideEffectToReceiver";
  }
}
}  // namespace

void AccessorInfo::AccessorInfoPrint(std::ostream& os) {
  TorqueGeneratedAccessorInfo<AccessorInfo, Struct>::AccessorInfoPrint(os);
  os << " - all_can_read: " << all_can_read();
  os << "\n - all_can_write: " << all_can_write();
  os << "\n - is_special_data_property: " << is_special_data_property();
  os << "\n - is_sloppy: " << is_sloppy();
  os << "\n - replace_on_access: " << replace_on_access();
  os << "\n - getter_side_effect_type: "
     << SideEffectType2String(getter_side_effect_type());
  os << "\n - setter_side_effect_type: "
     << SideEffectType2String(setter_side_effect_type());
  os << "\n - initial_attributes: " << initial_property_attributes();
  os << '\n';
}

816 817 818
namespace {
void PrintContextWithHeader(std::ostream& os, Context context,
                            const char* type) {
819 820 821 822 823
  context.PrintHeader(os, type);
  os << "\n - length: " << context.length();
  os << "\n - scope_info: " << Brief(context.scope_info());
  os << "\n - previous: " << Brief(context.unchecked_previous());
  os << "\n - native_context: " << Brief(context.native_context());
824 825 826 827 828
  PrintFixedArrayElements(os, context);
  os << "\n";
}
}  // namespace

829
void Context::ContextPrint(std::ostream& os) {
830
  PrintContextWithHeader(os, *this, "Context");
831 832 833
}

void NativeContext::NativeContextPrint(std::ostream& os) {
834
  PrintContextWithHeader(os, *this, "NativeContext");
835 836 837
  os << " - microtask_queue: " << microtask_queue() << "\n";
}

838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
namespace {
using DataPrinter = std::function<void(InternalIndex)>;

// Prints the data associated with each key (but no headers or other meta
// data) in a hash table. Works on different hash table types, like the
// subtypes of HashTable and OrderedHashTable. |print_data_at| is given an
// index into the table (where a valid key resides) and prints the data at
// that index, like just the value (in case of a hash map), or value and
// property details (in case of a property dictionary). No leading space
// required or trailing newline required. It can be null/non-callable
// std::function to indicate that there is no associcated data to be printed
// (for example in case of a hash set).
template <typename T>
void PrintTableContentsGeneric(std::ostream& os, T dict,
                               DataPrinter print_data_at) {
853
  DisallowGarbageCollection no_gc;
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905
  ReadOnlyRoots roots = dict.GetReadOnlyRoots();

  for (InternalIndex i : dict.IterateEntries()) {
    Object k;
    if (!dict.ToKey(roots, i, &k)) continue;
    os << "\n   " << std::setw(12) << i.as_int() << ": ";
    if (k.IsString()) {
      String::cast(k).PrintUC16(os);
    } else {
      os << Brief(k);
    }
    if (print_data_at) {
      os << " -> ";
      print_data_at(i);
    }
  }
}

// Used for ordered and unordered dictionaries.
template <typename T>
void PrintDictionaryContentsFull(std::ostream& os, T dict) {
  os << "\n - elements: {";
  auto print_value_and_property_details = [&](InternalIndex i) {
    os << Brief(dict.ValueAt(i)) << " ";
    dict.DetailsAt(i).PrintAsSlowTo(os, !T::kIsOrderedDictionaryType);
  };
  PrintTableContentsGeneric(os, dict, print_value_and_property_details);
  os << "\n }\n";
}

// Used for ordered and unordered hash maps.
template <typename T>
void PrintHashMapContentsFull(std::ostream& os, T dict) {
  os << "\n - elements: {";
  auto print_value = [&](InternalIndex i) { os << Brief(dict.ValueAt(i)); };
  PrintTableContentsGeneric(os, dict, print_value);
  os << "\n }\n";
}

// Used for ordered and unordered hash sets.
template <typename T>
void PrintHashSetContentsFull(std::ostream& os, T dict) {
  os << "\n - elements: {";
  // Passing non-callable std::function as there are no values to print.
  PrintTableContentsGeneric(os, dict, nullptr);
  os << "\n }\n";
}

// Used for subtypes of OrderedHashTable.
template <typename T>
void PrintOrderedHashTableHeaderAndBuckets(std::ostream& os, T table,
                                           const char* type) {
906
  DisallowGarbageCollection no_gc;
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934

  PrintHeapObjectHeaderWithoutMap(table, os, type);
  os << "\n - FixedArray length: " << table.length();
  os << "\n - elements: " << table.NumberOfElements();
  os << "\n - deleted: " << table.NumberOfDeletedElements();
  os << "\n - buckets: " << table.NumberOfBuckets();
  os << "\n - capacity: " << table.Capacity();

  os << "\n - buckets: {";
  for (int bucket = 0; bucket < table.NumberOfBuckets(); bucket++) {
    Object entry = table.get(T::HashTableStartIndex() + bucket);
    DCHECK(entry.IsSmi());
    os << "\n   " << std::setw(12) << bucket << ": " << Brief(entry);
  }
  os << "\n }";
}

// Used for subtypes of HashTable.
template <typename T>
void PrintHashTableHeader(std::ostream& os, T table, const char* type) {
  PrintHeapObjectHeaderWithoutMap(table, os, type);
  os << "\n - FixedArray length: " << table.length();
  os << "\n - elements: " << table.NumberOfElements();
  os << "\n - deleted: " << table.NumberOfDeletedElements();
  os << "\n - capacity: " << table.Capacity();
}
}  // namespace

935
void ObjectHashTable::ObjectHashTablePrint(std::ostream& os) {
936 937
  PrintHashTableHeader(os, *this, "ObjectHashTable");
  PrintHashMapContentsFull(os, *this);
938
}
939

940
void NumberDictionary::NumberDictionaryPrint(std::ostream& os) {
941 942
  PrintHashTableHeader(os, *this, "NumberDictionary");
  PrintDictionaryContentsFull(os, *this);
943 944
}

945
void EphemeronHashTable::EphemeronHashTablePrint(std::ostream& os) {
946 947
  PrintHashTableHeader(os, *this, "EphemeronHashTable");
  PrintHashMapContentsFull(os, *this);
948 949
}

950 951 952 953 954 955 956 957 958 959 960 961
void NameDictionary::NameDictionaryPrint(std::ostream& os) {
  PrintHashTableHeader(os, *this, "NameDictionary");
  PrintDictionaryContentsFull(os, *this);
}

void GlobalDictionary::GlobalDictionaryPrint(std::ostream& os) {
  PrintHashTableHeader(os, *this, "GlobalDictionary");
  PrintDictionaryContentsFull(os, *this);
}

void SmallOrderedHashSet::SmallOrderedHashSetPrint(std::ostream& os) {
  PrintHeader(os, "SmallOrderedHashSet");
962
  // TODO(turbofan): Print all fields.
963 964 965 966
}

void SmallOrderedHashMap::SmallOrderedHashMapPrint(std::ostream& os) {
  PrintHeader(os, "SmallOrderedHashMap");
967
  // TODO(turbofan): Print all fields.
968 969 970
}

void SmallOrderedNameDictionary::SmallOrderedNameDictionaryPrint(
971
    std::ostream& os) {
972
  PrintHeader(os, "SmallOrderedNameDictionary");
973
  // TODO(turbofan): Print all fields.
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988
}

void OrderedHashSet::OrderedHashSetPrint(std::ostream& os) {
  PrintOrderedHashTableHeaderAndBuckets(os, *this, "OrderedHashSet");
  PrintHashSetContentsFull(os, *this);
}

void OrderedHashMap::OrderedHashMapPrint(std::ostream& os) {
  PrintOrderedHashTableHeaderAndBuckets(os, *this, "OrderedHashMap");
  PrintHashMapContentsFull(os, *this);
}

void OrderedNameDictionary::OrderedNameDictionaryPrint(std::ostream& os) {
  PrintOrderedHashTableHeaderAndBuckets(os, *this, "OrderedNameDictionary");
  PrintDictionaryContentsFull(os, *this);
989 990
}

991 992 993 994 995
void print_hex_byte(std::ostream& os, int value) {
  os << "0x" << std::setfill('0') << std::setw(2) << std::right << std::hex
     << (value & 0xff) << std::setfill(' ');
}

996
void SwissNameDictionary::SwissNameDictionaryPrint(std::ostream& os) {
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
  this->PrintHeader(os, "SwissNameDictionary");
  os << "\n - meta table ByteArray: "
     << reinterpret_cast<void*>(this->meta_table().ptr());
  os << "\n - capacity: " << this->Capacity();
  os << "\n - elements: " << this->NumberOfElements();
  os << "\n - deleted: " << this->NumberOfDeletedElements();

  std::ios_base::fmtflags sav_flags = os.flags();
  os << "\n - ctrl table (omitting buckets where key is hole value): {";
  for (int i = 0; i < this->Capacity() + kGroupWidth; i++) {
    ctrl_t ctrl = CtrlTable()[i];

    if (ctrl == Ctrl::kEmpty) continue;

    os << "\n   " << std::setw(12) << std::dec << i << ": ";
    switch (ctrl) {
      case Ctrl::kEmpty:
        UNREACHABLE();
        break;
      case Ctrl::kDeleted:
        print_hex_byte(os, ctrl);
        os << " (= kDeleted)";
        break;
      case Ctrl::kSentinel:
        print_hex_byte(os, ctrl);
        os << " (= kSentinel)";
        break;
      default:
        print_hex_byte(os, ctrl);
        os << " (= H2 of a key)";
        break;
    }
  }
  os << "\n }";

  os << "\n - enumeration table: {";
  for (int enum_index = 0; enum_index < this->UsedCapacity(); enum_index++) {
    int entry = EntryForEnumerationIndex(enum_index);
    os << "\n   " << std::setw(12) << std::dec << enum_index << ": " << entry;
  }
  os << "\n }";

  os << "\n - data table (omitting slots where key is the hole): {";
  for (int bucket = 0; bucket < this->Capacity(); ++bucket) {
    Object k;
    if (!this->ToKey(this->GetReadOnlyRoots(), bucket, &k)) continue;

    Object value = this->ValueAtRaw(bucket);
    PropertyDetails details = this->DetailsAt(bucket);
    os << "\n   " << std::setw(12) << std::dec << bucket << ": ";
    if (k.IsString()) {
      String::cast(k).PrintUC16(os);
    } else {
      os << Brief(k);
    }
    os << " -> " << Brief(value);
    details.PrintAsSlowTo(os, false);
  }
  os << "\n }\n";
  os.flags(sav_flags);
1057 1058
}

1059
void PropertyArray::PropertyArrayPrint(std::ostream& os) {
1060
  PrintHeader(os, "PropertyArray");
1061
  os << "\n - length: " << length();
1062
  os << "\n - hash: " << Hash();
1063
  PrintFixedArrayElements(os, *this);
1064 1065
  os << "\n";
}
1066

1067
void FixedDoubleArray::FixedDoubleArrayPrint(std::ostream& os) {
1068
  PrintHeader(os, "FixedDoubleArray");
1069
  os << "\n - length: " << length();
1070
  DoPrintElements<FixedDoubleArray>(os, *this, length());
1071
  os << "\n";
1072 1073
}

1074
void WeakFixedArray::WeakFixedArrayPrint(std::ostream& os) {
1075 1076 1077 1078
  PrintHeader(os, "WeakFixedArray");
  os << "\n - length: " << length() << "\n";
  PrintWeakArrayElements(os, this);
  os << "\n";
1079
}
1080

1081
void WeakArrayList::WeakArrayListPrint(std::ostream& os) {
1082 1083 1084 1085 1086
  PrintHeader(os, "WeakArrayList");
  os << "\n - capacity: " << capacity();
  os << "\n - length: " << length() << "\n";
  PrintWeakArrayElements(os, this);
  os << "\n";
1087 1088
}

1089
void TransitionArray::TransitionArrayPrint(std::ostream& os) {
1090
  PrintHeader(os, "TransitionArray");
1091
  PrintInternal(os);
1092 1093
}

1094
void FeedbackCell::FeedbackCellPrint(std::ostream& os) {
1095
  PrintHeader(os, "FeedbackCell");
1096 1097
  ReadOnlyRoots roots = GetReadOnlyRoots();
  if (map() == roots.no_closures_cell_map()) {
1098
    os << "\n - no closures";
1099
  } else if (map() == roots.one_closure_cell_map()) {
1100
    os << "\n - one closure";
1101
  } else if (map() == roots.many_closures_cell_map()) {
1102 1103 1104 1105
    os << "\n - many closures";
  } else {
    os << "\n - Invalid FeedbackCell map";
  }
1106 1107
  os << "\n - value: " << Brief(value());
  os << "\n - interrupt_budget: " << interrupt_budget();
1108 1109 1110
  os << "\n";
}

1111
void FeedbackVectorSpec::Print() {
1112
  StdoutStream os;
1113

1114
  FeedbackVectorSpecPrint(os);
1115

1116 1117 1118
  os << std::flush;
}

1119
void FeedbackVectorSpec::FeedbackVectorSpecPrint(std::ostream& os) {
1120 1121
  os << " - slot_count: " << slot_count();
  if (slot_count() == 0) {
1122 1123 1124 1125
    os << " (empty)\n";
    return;
  }

1126
  for (int slot = 0; slot < slot_count();) {
1127
    FeedbackSlotKind kind = GetKind(FeedbackSlot(slot));
1128
    int entry_size = FeedbackMetadata::GetSlotSize(kind);
1129 1130 1131 1132 1133 1134
    DCHECK_LT(0, entry_size);
    os << "\n Slot #" << slot << " " << kind;
    slot += entry_size;
  }
  os << "\n";
}
1135

1136
void FeedbackMetadata::FeedbackMetadataPrint(std::ostream& os) {
1137
  PrintHeader(os, "FeedbackMetadata");
1138
  os << "\n - slot_count: " << slot_count();
1139
  os << "\n - create_closure_slot_count: " << create_closure_slot_count();
1140

1141
  FeedbackMetadataIterator iter(*this);
1142
  while (iter.HasNext()) {
1143 1144
    FeedbackSlot slot = iter.Next();
    FeedbackSlotKind kind = iter.kind();
1145 1146 1147 1148 1149
    os << "\n Slot " << slot << " " << kind;
  }
  os << "\n";
}

1150 1151 1152 1153
void ClosureFeedbackCellArray::ClosureFeedbackCellArrayPrint(std::ostream& os) {
  PrintFixedArrayWithHeader(os, *this, "ClosureFeedbackCellArray");
}

1154
void FeedbackVector::FeedbackVectorPrint(std::ostream& os) {
1155
  PrintHeader(os, "FeedbackVector");
1156
  os << "\n - length: " << length();
1157 1158 1159 1160 1161
  if (length() == 0) {
    os << " (empty)\n";
    return;
  }

1162
  os << "\n - shared function info: " << Brief(shared_function_info());
1163
  if (has_optimized_code()) {
1164
    os << "\n - optimized code: " << Brief(optimized_code());
1165
  } else {
1166
    os << "\n - no optimized code";
1167
  }
1168
  os << "\n - optimization marker: " << optimization_marker();
1169
  os << "\n - optimization tier: " << optimization_tier();
1170
  os << "\n - invocation count: " << invocation_count();
1171
  os << "\n - profiler ticks: " << profiler_ticks();
1172 1173
  os << "\n - closure feedback cell array: ";
  closure_feedback_cell_array().ClosureFeedbackCellArrayPrint(os);
1174

1175
  FeedbackMetadataIterator iter(metadata());
1176
  while (iter.HasNext()) {
1177 1178
    FeedbackSlot slot = iter.Next();
    FeedbackSlotKind kind = iter.kind();
1179

1180
    os << "\n - slot " << slot << " " << kind << " ";
1181
    FeedbackSlotPrint(os, slot);
1182

1183
    int entry_size = iter.entry_size();
1184
    if (entry_size > 0) os << " {";
1185
    for (int i = 0; i < entry_size; i++) {
1186 1187 1188
      FeedbackSlot slot_with_offset = slot.WithOffset(i);
      os << "\n     [" << slot_with_offset.ToInt()
         << "]: " << Brief(Get(slot_with_offset));
1189
    }
1190
    if (entry_size > 0) os << "\n  }";
1191 1192 1193 1194
  }
  os << "\n";
}

1195
void FeedbackVector::FeedbackSlotPrint(std::ostream& os, FeedbackSlot slot) {
1196
  FeedbackNexus nexus(*this, slot);
1197
  nexus.Print(os);
1198 1199
}

1200
void FeedbackNexus::Print(std::ostream& os) {
1201 1202
  switch (kind()) {
    case FeedbackSlotKind::kCall:
1203 1204 1205
    case FeedbackSlotKind::kCloneObject:
    case FeedbackSlotKind::kHasKeyed:
    case FeedbackSlotKind::kInstanceOf:
1206
    case FeedbackSlotKind::kLoadGlobalInsideTypeof:
1207
    case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
1208 1209 1210
    case FeedbackSlotKind::kLoadKeyed:
    case FeedbackSlotKind::kLoadProperty:
    case FeedbackSlotKind::kStoreDataPropertyInLiteral:
1211
    case FeedbackSlotKind::kStoreGlobalSloppy:
1212
    case FeedbackSlotKind::kStoreGlobalStrict:
1213
    case FeedbackSlotKind::kStoreInArrayLiteral:
1214
    case FeedbackSlotKind::kStoreKeyedSloppy:
1215
    case FeedbackSlotKind::kStoreKeyedStrict:
1216 1217 1218
    case FeedbackSlotKind::kStoreNamedSloppy:
    case FeedbackSlotKind::kStoreNamedStrict:
    case FeedbackSlotKind::kStoreOwnNamed: {
1219
      os << InlineCacheState2String(ic_state());
1220 1221 1222
      break;
    }
    case FeedbackSlotKind::kBinaryOp: {
1223
      os << "BinaryOp:" << GetBinaryOperationFeedback();
1224 1225 1226
      break;
    }
    case FeedbackSlotKind::kCompareOp: {
1227
      os << "CompareOp:" << GetCompareOperationFeedback();
1228 1229 1230
      break;
    }
    case FeedbackSlotKind::kForIn: {
1231
      os << "ForIn:" << GetForInFeedback();
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
      break;
    }
    case FeedbackSlotKind::kLiteral:
    case FeedbackSlotKind::kTypeProfile:
      break;
    case FeedbackSlotKind::kInvalid:
    case FeedbackSlotKind::kKindsNumber:
      UNREACHABLE();
  }
}
1242

1243
void Oddball::OddballPrint(std::ostream& os) {
1244 1245 1246 1247 1248 1249 1250
  PrintHeapObjectHeaderWithoutMap(*this, os, "Oddball");
  os << ": ";
  String s = to_string();
  os << s.PrefixForDebugPrint();
  s.PrintUC16(os);
  os << s.SuffixForDebugPrint();
  os << std::endl;
1251 1252
}

1253
void JSAsyncFunctionObject::JSAsyncFunctionObjectPrint(std::ostream& os) {
1254 1255 1256
  JSGeneratorObjectPrint(os);
}

1257
void JSAsyncGeneratorObject::JSAsyncGeneratorObjectPrint(std::ostream& os) {
1258 1259 1260
  JSGeneratorObjectPrint(os);
}

1261
void JSArgumentsObject::JSArgumentsObjectPrint(std::ostream& os) {
1262 1263 1264
  JSObjectPrint(os);
}

1265
void JSStringIterator::JSStringIteratorPrint(std::ostream& os) {
1266 1267 1268 1269 1270 1271
  JSObjectPrintHeader(os, *this, "JSStringIterator");
  os << "\n - string: " << Brief(string());
  os << "\n - index: " << index();
  JSObjectPrintBody(os, *this);
}

1272
void JSAsyncFromSyncIterator::JSAsyncFromSyncIteratorPrint(std::ostream& os) {
1273 1274 1275 1276 1277 1278
  JSObjectPrintHeader(os, *this, "JSAsyncFromSyncIterator");
  os << "\n - sync_iterator: " << Brief(sync_iterator());
  os << "\n - next: " << Brief(next());
  JSObjectPrintBody(os, *this);
}

1279
void JSPrimitiveWrapper::JSPrimitiveWrapperPrint(std::ostream& os) {
1280
  JSObjectPrintHeader(os, *this, "JSPrimitiveWrapper");
1281
  os << "\n - value: " << Brief(value());
1282
  JSObjectPrintBody(os, *this);
1283 1284
}

1285
void JSMessageObject::JSMessageObjectPrint(std::ostream& os) {
1286
  JSObjectPrintHeader(os, *this, "JSMessageObject");
1287
  os << "\n - type: " << static_cast<int>(type());
1288
  os << "\n - arguments: " << Brief(argument());
1289 1290 1291 1292
  os << "\n - start_position: " << start_position();
  os << "\n - end_position: " << end_position();
  os << "\n - script: " << Brief(script());
  os << "\n - stack_frames: " << Brief(stack_frames());
1293
  JSObjectPrintBody(os, *this);
1294 1295
}

1296
void String::StringPrint(std::ostream& os) {
1297 1298
  PrintHeapObjectHeaderWithoutMap(*this, os, "String");
  os << ": ";
1299 1300 1301
  os << PrefixForDebugPrint();
  PrintUC16(os, 0, length());
  os << SuffixForDebugPrint();
1302 1303
}

1304
void Name::NamePrint(std::ostream& os) {
1305
  if (IsString()) {
1306
    String::cast(*this).StringPrint(os);
1307
  } else {
1308
    os << Brief(*this);
1309
  }
1310 1311
}

1312 1313
static const char* const weekdays[] = {"???", "Sun", "Mon", "Tue",
                                       "Wed", "Thu", "Fri", "Sat"};
1314

1315
void JSDate::JSDatePrint(std::ostream& os) {
1316
  JSObjectPrintHeader(os, *this, "JSDate");
1317
  os << "\n - value: " << Brief(value());
1318
  if (!year().IsSmi()) {
1319
    os << "\n - time = NaN\n";
1320
  } else {
1321
    // TODO(svenpanne) Add some basic formatting to our streams.
1322
    ScopedVector<char> buf(100);
jgruber's avatar
jgruber committed
1323
    SNPrintF(buf, "\n - time = %s %04d/%02d/%02d %02d:%02d:%02d\n",
1324 1325 1326 1327 1328 1329 1330
             weekdays[weekday().IsSmi() ? Smi::ToInt(weekday()) + 1 : 0],
             year().IsSmi() ? Smi::ToInt(year()) : -1,
             month().IsSmi() ? Smi::ToInt(month()) : -1,
             day().IsSmi() ? Smi::ToInt(day()) : -1,
             hour().IsSmi() ? Smi::ToInt(hour()) : -1,
             min().IsSmi() ? Smi::ToInt(min()) : -1,
             sec().IsSmi() ? Smi::ToInt(sec()) : -1);
1331
    os << buf.begin();
1332
  }
1333
  JSObjectPrintBody(os, *this);
1334 1335
}

1336
void JSProxy::JSProxyPrint(std::ostream& os) {
1337
  PrintHeader(os, "JSProxy");
1338
  os << "\n - target: ";
1339
  target().ShortPrint(os);
1340
  os << "\n - handler: ";
1341
  handler().ShortPrint(os);
1342
  os << "\n";
1343 1344
}

1345
void JSSet::JSSetPrint(std::ostream& os) {
1346
  JSObjectPrintHeader(os, *this, "JSSet");
1347
  os << " - table: " << Brief(table());
1348
  JSObjectPrintBody(os, *this);
1349 1350
}

1351
void JSMap::JSMapPrint(std::ostream& os) {
1352
  JSObjectPrintHeader(os, *this, "JSMap");
1353
  os << " - table: " << Brief(table());
1354
  JSObjectPrintBody(os, *this);
1355 1356
}

1357 1358
void JSCollectionIterator::JSCollectionIteratorPrint(std::ostream& os,
                                                     const char* name) {
1359
  JSObjectPrintHeader(os, *this, name);
1360 1361
  os << "\n - table: " << Brief(table());
  os << "\n - index: " << Brief(index());
1362
  JSObjectPrintBody(os, *this);
1363 1364
}

1365
void JSSetIterator::JSSetIteratorPrint(std::ostream& os) {
1366
  JSCollectionIteratorPrint(os, "JSSetIterator");
1367 1368
}

1369
void JSMapIterator::JSMapIteratorPrint(std::ostream& os) {
1370
  JSCollectionIteratorPrint(os, "JSMapIterator");
1371 1372
}

1373 1374
void WeakCell::WeakCellPrint(std::ostream& os) {
  PrintHeader(os, "WeakCell");
1375
  os << "\n - finalization_registry: " << Brief(finalization_registry());
1376
  os << "\n - target: " << Brief(target());
1377
  os << "\n - holdings: " << Brief(holdings());
1378 1379
  os << "\n - prev: " << Brief(prev());
  os << "\n - next: " << Brief(next());
1380
  os << "\n - unregister_token: " << Brief(unregister_token());
1381 1382
  os << "\n - key_list_prev: " << Brief(key_list_prev());
  os << "\n - key_list_next: " << Brief(key_list_next());
1383 1384
}

1385 1386 1387 1388 1389 1390
void JSWeakRef::JSWeakRefPrint(std::ostream& os) {
  JSObjectPrintHeader(os, *this, "JSWeakRef");
  os << "\n - target: " << Brief(target());
  JSObjectPrintBody(os, *this);
}

1391 1392
void JSFinalizationRegistry::JSFinalizationRegistryPrint(std::ostream& os) {
  JSObjectPrintHeader(os, *this, "JSFinalizationRegistry");
1393
  os << "\n - native_context: " << Brief(native_context());
1394 1395
  os << "\n - cleanup: " << Brief(cleanup());
  os << "\n - active_cells: " << Brief(active_cells());
1396 1397 1398 1399 1400
  Object active_cell = active_cells();
  while (active_cell.IsWeakCell()) {
    os << "\n   - " << Brief(active_cell);
    active_cell = WeakCell::cast(active_cell).next();
  }
1401
  os << "\n - cleared_cells: " << Brief(cleared_cells());
1402 1403 1404 1405 1406
  Object cleared_cell = cleared_cells();
  while (cleared_cell.IsWeakCell()) {
    os << "\n   - " << Brief(cleared_cell);
    cleared_cell = WeakCell::cast(cleared_cell).next();
  }
1407
  os << "\n - key_map: " << Brief(key_map());
1408
  JSObjectPrintBody(os, *this);
1409 1410
}

1411
void JSWeakMap::JSWeakMapPrint(std::ostream& os) {
1412
  JSObjectPrintHeader(os, *this, "JSWeakMap");
1413
  os << "\n - table: " << Brief(table());
1414
  JSObjectPrintBody(os, *this);
1415 1416
}

1417
void JSWeakSet::JSWeakSetPrint(std::ostream& os) {
1418
  JSObjectPrintHeader(os, *this, "JSWeakSet");
1419
  os << "\n - table: " << Brief(table());
1420
  JSObjectPrintBody(os, *this);
1421 1422
}

1423
void JSArrayBuffer::JSArrayBufferPrint(std::ostream& os) {
1424
  JSObjectPrintHeader(os, *this, "JSArrayBuffer");
1425
  os << "\n - backing_store: " << backing_store();
1426
  os << "\n - byte_length: " << byte_length();
1427
  if (is_external()) os << "\n - external";
1428 1429
  if (is_detachable()) os << "\n - detachable";
  if (was_detached()) os << "\n - detached";
1430
  if (is_shared()) os << "\n - shared";
1431
  if (is_resizable()) os << "\n - resizable";
1432
  JSObjectPrintBody(os, *this, !was_detached());
1433 1434
}

1435
void JSTypedArray::JSTypedArrayPrint(std::ostream& os) {
1436
  JSObjectPrintHeader(os, *this, "JSTypedArray");
1437
  os << "\n - buffer: " << Brief(buffer());
1438 1439
  os << "\n - byte_offset: " << byte_offset();
  os << "\n - byte_length: " << byte_length();
1440
  os << "\n - length: " << GetLength();
1441 1442 1443 1444 1445 1446
  os << "\n - data_ptr: " << DataPtr();
  Tagged_t base_ptr = static_cast<Tagged_t>(base_pointer().ptr());
  os << "\n   - base_pointer: "
     << reinterpret_cast<void*>(static_cast<Address>(base_ptr));
  os << "\n   - external_pointer: "
     << reinterpret_cast<void*>(external_pointer());
1447
  if (!buffer().IsJSArrayBuffer()) {
1448 1449 1450
    os << "\n <invalid buffer>\n";
    return;
  }
1451
  if (WasDetached()) os << "\n - detached";
1452 1453
  if (is_length_tracking()) os << "\n - length-tracking";
  if (is_backed_by_rab()) os << "\n - backed-by-rab";
1454
  JSObjectPrintBody(os, *this, !WasDetached());
1455 1456
}

1457
void JSArrayIterator::JSArrayIteratorPrint(std::ostream& os) {  // NOLING
1458
  JSObjectPrintHeader(os, *this, "JSArrayIterator");
1459 1460 1461
  os << "\n - iterated_object: " << Brief(iterated_object());
  os << "\n - next_index: " << Brief(next_index());
  os << "\n - kind: " << kind();
1462
  JSObjectPrintBody(os, *this);
1463 1464
}

1465
void JSDataView::JSDataViewPrint(std::ostream& os) {
1466
  JSObjectPrintHeader(os, *this, "JSDataView");
1467
  os << "\n - buffer =" << Brief(buffer());
1468 1469
  os << "\n - byte_offset: " << byte_offset();
  os << "\n - byte_length: " << byte_length();
1470
  if (!buffer().IsJSArrayBuffer()) {
1471 1472 1473
    os << "\n <invalid buffer>";
    return;
  }
1474 1475
  if (WasDetached()) os << "\n - detached";
  JSObjectPrintBody(os, *this, !WasDetached());
1476 1477
}

1478
void JSBoundFunction::JSBoundFunctionPrint(std::ostream& os) {
1479
  JSObjectPrintHeader(os, *this, "JSBoundFunction");
1480 1481 1482
  os << "\n - bound_target_function: " << Brief(bound_target_function());
  os << "\n - bound_this: " << Brief(bound_this());
  os << "\n - bound_arguments: " << Brief(bound_arguments());
1483
  JSObjectPrintBody(os, *this);
1484 1485
}

1486
void JSFunction::JSFunctionPrint(std::ostream& os) {
1487
  Isolate* isolate = GetIsolate();
1488
  JSObjectPrintHeader(os, *this, "Function");
1489
  os << "\n - function prototype: ";
1490 1491 1492
  if (has_prototype_slot()) {
    if (has_prototype()) {
      os << Brief(prototype());
1493
      if (map().has_non_instance_prototype()) {
1494 1495 1496
        os << " (non-instance prototype)";
      }
    }
1497
    os << "\n - initial_map: ";
1498 1499 1500 1501
    if (has_initial_map()) os << Brief(initial_map());
  } else {
    os << "<no-prototype-slot>";
  }
1502
  os << "\n - shared_info: " << Brief(shared());
1503
  os << "\n - name: " << Brief(shared().Name());
1504 1505

  // Print Builtin name for builtin functions
1506 1507 1508
  Builtin builtin = code().builtin_id();
  if (Builtins::IsBuiltinId(builtin)) {
    os << "\n - builtin: " << isolate->builtins()->name(builtin);
1509 1510
  }

1511
  os << "\n - formal_parameter_count: "
1512 1513
     << shared().internal_formal_parameter_count();
  os << "\n - kind: " << shared().kind();
1514
  os << "\n - context: " << Brief(context());
1515
  os << "\n - code: " << Brief(raw_code());
1516 1517
  if (code().kind() == CodeKind::FOR_TESTING) {
    os << "\n - FOR_TESTING";
1518
  } else if (ActiveTierIsIgnition()) {
1519
    os << "\n - interpreted";
1520
    if (shared().HasBytecodeArray()) {
1521
      os << "\n - bytecode: " << shared().GetBytecodeArray(isolate);
1522 1523
    }
  }
1524
#if V8_ENABLE_WEBASSEMBLY
1525 1526
  if (WasmExportedFunction::IsWasmExportedFunction(*this)) {
    WasmExportedFunction function = WasmExportedFunction::cast(*this);
1527 1528
    os << "\n - Wasm instance: " << Brief(function.instance());
    os << "\n - Wasm function index: " << function.function_index();
1529 1530 1531
  }
  if (WasmJSFunction::IsWasmJSFunction(*this)) {
    WasmJSFunction function = WasmJSFunction::cast(*this);
1532
    os << "\n - Wasm wrapper around: " << Brief(function.GetCallable());
1533
  }
1534
#endif  // V8_ENABLE_WEBASSEMBLY
1535
  shared().PrintSourceCode(os);
1536
  JSObjectPrintBody(os, *this);
1537
  os << " - feedback vector: ";
1538
  if (!shared().HasFeedbackMetadata()) {
1539 1540
    os << "feedback metadata is not available in SFI\n";
  } else if (has_feedback_vector()) {
1541
    feedback_vector().FeedbackVectorPrint(os);
1542 1543 1544
  } else if (has_closure_feedback_cell_array()) {
    os << "No feedback vector, but we have a closure feedback cell array\n";
    closure_feedback_cell_array().ClosureFeedbackCellArrayPrint(os);
1545 1546 1547
  } else {
    os << "not available\n";
  }
1548 1549
}

1550 1551
void SharedFunctionInfo::PrintSourceCode(std::ostream& os) {
  if (HasSourceCode()) {
1552
    os << "\n - source code: ";
1553
    String source = String::cast(Script::cast(script()).source());
1554 1555
    int start = StartPosition();
    int length = EndPosition() - start;
1556
    std::unique_ptr<char[]> source_string = source.ToCString(
1557
        DISALLOW_NULLS, FAST_STRING_TRAVERSAL, start, length, nullptr);
1558 1559 1560 1561
    os << source_string.get();
  }
}

1562
void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) {
1563
  PrintHeader(os, "SharedFunctionInfo");
1564
  os << "\n - name: ";
1565 1566
  if (HasSharedName()) {
    os << Brief(Name());
1567 1568 1569
  } else {
    os << "<no-shared-name>";
  }
1570 1571 1572
  if (HasInferredName()) {
    os << "\n - inferred name: " << Brief(inferred_name());
  }
1573 1574 1575
  if (class_scope_has_private_brand()) {
    os << "\n - class_scope_has_private_brand";
  }
1576 1577 1578
  if (has_static_private_methods_or_accessors()) {
    os << "\n - has_static_private_methods_or_accessors";
  }
1579
  os << "\n - kind: " << kind();
1580
  os << "\n - syntax kind: " << syntax_kind();
1581 1582 1583 1584
  os << "\n - function_map_index: " << function_map_index();
  os << "\n - formal_parameter_count: " << internal_formal_parameter_count();
  os << "\n - expected_nof_properties: " << expected_nof_properties();
  os << "\n - language_mode: " << language_mode();
1585
  os << "\n - data: " << Brief(function_data(kAcquireLoad));
1586
  os << "\n - code (from data): ";
1587
  os << Brief(GetCode());
1588
  PrintSourceCode(os);
1589 1590
  // Script files are often large, thus only print their {Brief} representation.
  os << "\n - script: " << Brief(script());
1591
  os << "\n - function token position: " << function_token_position();
1592 1593
  os << "\n - start position: " << StartPosition();
  os << "\n - end position: " << EndPosition();
1594
  if (HasDebugInfo()) {
1595
    os << "\n - debug info: " << Brief(GetDebugInfo());
1596 1597 1598
  } else {
    os << "\n - no debug info";
  }
1599
  os << "\n - scope info: " << Brief(scope_info());
1600 1601 1602
  if (HasOuterScopeInfo()) {
    os << "\n - outer scope info: " << Brief(GetOuterScopeInfo());
  }
1603 1604
  os << "\n - length: " << length();
  os << "\n - feedback_metadata: ";
1605
  if (HasFeedbackMetadata()) {
1606
    feedback_metadata().FeedbackMetadataPrint(os);
1607 1608 1609
  } else {
    os << "<none>";
  }
1610
  os << "\n";
1611 1612
}

1613
void JSGlobalProxy::JSGlobalProxyPrint(std::ostream& os) {
1614
  JSObjectPrintHeader(os, *this, "JSGlobalProxy");
1615
  if (!GetIsolate()->bootstrapper()->IsActive()) {
1616
    os << "\n - native context: " << Brief(native_context());
1617
  }
1618
  JSObjectPrintBody(os, *this);
1619 1620
}

1621
void JSGlobalObject::JSGlobalObjectPrint(std::ostream& os) {
1622
  JSObjectPrintHeader(os, *this, "JSGlobalObject");
1623
  if (!GetIsolate()->bootstrapper()->IsActive()) {
1624
    os << "\n - native context: " << Brief(native_context());
1625
  }
1626
  os << "\n - global proxy: " << Brief(global_proxy());
1627
  JSObjectPrintBody(os, *this);
1628 1629
}

1630
void PropertyCell::PropertyCellPrint(std::ostream& os) {
1631
  PrintHeader(os, "PropertyCell");
1632
  os << "\n - name: ";
1633
  name().NamePrint(os);
1634
  os << "\n - value: " << Brief(value(kAcquireLoad));
1635
  os << "\n - details: ";
1636 1637 1638
  PropertyDetails details = property_details(kAcquireLoad);
  details.PrintAsSlowTo(os, true);
  os << "\n - cell_type: " << details.cell_type();
1639
  os << "\n";
1640 1641
}

1642
void Code::CodePrint(std::ostream& os) {
1643
  PrintHeader(os, "Code");
1644 1645 1646 1647 1648
  os << "\n - code_data_container: "
     << Brief(code_data_container(kAcquireLoad));
  if (is_builtin()) {
    os << "\n - builtin_id: " << Builtins::name(builtin_id());
  }
1649
  os << "\n";
1650
#ifdef ENABLE_DISASSEMBLER
1651
  Disassemble(nullptr, os, GetIsolate());
1652 1653 1654
#endif
}

1655
void CodeDataContainer::CodeDataContainerPrint(std::ostream& os) {
1656
  PrintHeader(os, "CodeDataContainer");
1657
  os << "\n - kind_specific_flags: " << kind_specific_flags();
1658 1659 1660 1661 1662
  if (V8_EXTERNAL_CODE_SPACE_BOOL) {
    os << "\n - code: " << Brief(code());
    os << "\n - code_entry_point: "
       << reinterpret_cast<void*>(code_entry_point());
  }
1663 1664
  os << "\n";
}
1665

1666
void Foreign::ForeignPrint(std::ostream& os) {
1667 1668
  PrintHeader(os, "Foreign");
  os << "\n - foreign address : " << reinterpret_cast<void*>(foreign_address());
1669
  os << "\n";
1670 1671
}

1672
void CallbackTask::CallbackTaskPrint(std::ostream& os) {
1673
  PrintHeader(os, "CallbackTask");
1674 1675 1676 1677 1678
  os << "\n - callback: " << Brief(callback());
  os << "\n - data: " << Brief(data());
  os << "\n";
}

1679
void CallableTask::CallableTaskPrint(std::ostream& os) {
1680
  PrintHeader(os, "CallableTask");
1681 1682
  os << "\n - context: " << Brief(context());
  os << "\n - callable: " << Brief(callable());
1683 1684 1685
  os << "\n";
}

1686
void PromiseFulfillReactionJobTask::PromiseFulfillReactionJobTaskPrint(
1687
    std::ostream& os) {
1688
  PrintHeader(os, "PromiseFulfillReactionJobTask");
1689 1690 1691
  os << "\n - argument: " << Brief(argument());
  os << "\n - context: " << Brief(context());
  os << "\n - handler: " << Brief(handler());
1692
  os << "\n - promise_or_capability: " << Brief(promise_or_capability());
1693 1694 1695 1696
  os << "\n";
}

void PromiseRejectReactionJobTask::PromiseRejectReactionJobTaskPrint(
1697
    std::ostream& os) {
1698
  PrintHeader(os, "PromiseRejectReactionJobTask");
1699 1700 1701
  os << "\n - argument: " << Brief(argument());
  os << "\n - context: " << Brief(context());
  os << "\n - handler: " << Brief(handler());
1702
  os << "\n - promise_or_capability: " << Brief(promise_or_capability());
1703 1704 1705 1706
  os << "\n";
}

void PromiseResolveThenableJobTask::PromiseResolveThenableJobTaskPrint(
1707
    std::ostream& os) {
1708
  PrintHeader(os, "PromiseResolveThenableJobTask");
1709 1710
  os << "\n - context: " << Brief(context());
  os << "\n - promise_to_resolve: " << Brief(promise_to_resolve());
1711
  os << "\n - then: " << Brief(then());
1712 1713 1714 1715
  os << "\n - thenable: " << Brief(thenable());
  os << "\n";
}

1716
void PromiseCapability::PromiseCapabilityPrint(std::ostream& os) {
1717
  PrintHeader(os, "PromiseCapability");
1718
  os << "\n - promise: " << Brief(promise());
1719 1720 1721 1722 1723
  os << "\n - resolve: " << Brief(resolve());
  os << "\n - reject: " << Brief(reject());
  os << "\n";
}

1724
void PromiseReaction::PromiseReactionPrint(std::ostream& os) {
1725
  PrintHeader(os, "PromiseReaction");
1726 1727 1728
  os << "\n - next: " << Brief(next());
  os << "\n - reject_handler: " << Brief(reject_handler());
  os << "\n - fulfill_handler: " << Brief(fulfill_handler());
1729
  os << "\n - promise_or_capability: " << Brief(promise_or_capability());
1730 1731 1732
  os << "\n";
}

1733
void AsyncGeneratorRequest::AsyncGeneratorRequestPrint(std::ostream& os) {
1734
  PrintHeader(os, "AsyncGeneratorRequest");
1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752
  const char* mode = "Invalid!";
  switch (resume_mode()) {
    case JSGeneratorObject::kNext:
      mode = ".next()";
      break;
    case JSGeneratorObject::kReturn:
      mode = ".return()";
      break;
    case JSGeneratorObject::kThrow:
      mode = ".throw()";
      break;
  }
  os << "\n - resume mode: " << mode;
  os << "\n - value: " << Brief(value());
  os << "\n - next: " << Brief(next());
  os << "\n";
}

1753
void SourceTextModuleInfoEntry::SourceTextModuleInfoEntryPrint(
1754
    std::ostream& os) {
1755
  PrintHeader(os, "SourceTextModuleInfoEntry");
1756 1757 1758 1759 1760 1761 1762 1763 1764 1765
  os << "\n - export_name: " << Brief(export_name());
  os << "\n - local_name: " << Brief(local_name());
  os << "\n - import_name: " << Brief(import_name());
  os << "\n - module_request: " << module_request();
  os << "\n - cell_index: " << cell_index();
  os << "\n - beg_pos: " << beg_pos();
  os << "\n - end_pos: " << end_pos();
  os << "\n";
}

1766 1767 1768 1769 1770 1771
static void PrintModuleFields(Module module, std::ostream& os) {
  os << "\n - exports: " << Brief(module.exports());
  os << "\n - status: " << module.status();
  os << "\n - exception: " << Brief(module.exception());
}

1772
void Module::ModulePrint(std::ostream& os) {
1773 1774
  if (this->IsSourceTextModule()) {
    SourceTextModule::cast(*this).SourceTextModulePrint(os);
1775 1776
  } else if (this->IsSyntheticModule()) {
    SyntheticModule::cast(*this).SyntheticModulePrint(os);
1777 1778 1779 1780 1781
  } else {
    UNREACHABLE();
  }
}

1782
void SourceTextModule::SourceTextModulePrint(std::ostream& os) {
1783 1784
  PrintHeader(os, "SourceTextModule");
  PrintModuleFields(*this, os);
1785 1786 1787 1788
  os << "\n - sfi/code/info: " << Brief(code());
  Script script = GetScript();
  os << "\n - script: " << Brief(script);
  os << "\n - origin: " << Brief(script.GetNameOrSourceURL());
1789
  os << "\n - requested_modules: " << Brief(requested_modules());
1790
  os << "\n - import_meta: " << Brief(import_meta(kAcquireLoad));
1791
  os << "\n - cycle_root: " << Brief(cycle_root());
1792
  os << "\n - async_evaluating_ordinal: " << async_evaluating_ordinal();
1793 1794
  os << "\n";
}
1795

1796
void SyntheticModule::SyntheticModulePrint(std::ostream& os) {
1797 1798 1799
  PrintHeader(os, "SyntheticModule");
  PrintModuleFields(*this, os);
  os << "\n - export_names: " << Brief(export_names());
1800
  os << "\n - name: " << Brief(name());
1801 1802 1803
  os << "\n";
}

1804
void JSModuleNamespace::JSModuleNamespacePrint(std::ostream& os) {
1805
  JSObjectPrintHeader(os, *this, "JSModuleNamespace");
1806
  os << "\n - module: " << Brief(module());
1807
  JSObjectPrintBody(os, *this);
1808 1809
}

1810
void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) {
1811
  PrintHeader(os, "PrototypeInfo");
1812
  os << "\n - module namespace: " << Brief(module_namespace());
1813
  os << "\n - prototype users: " << Brief(prototype_users());
1814
  os << "\n - registry slot: " << registry_slot();
1815
  os << "\n - object create map: " << Brief(object_create_map());
1816
  os << "\n - should_be_fast_map: " << should_be_fast_map();
1817 1818 1819
  os << "\n";
}

1820
void ClassPositions::ClassPositionsPrint(std::ostream& os) {
1821 1822 1823 1824 1825 1826
  PrintHeader(os, "ClassPositions");
  os << "\n - start position: " << start();
  os << "\n - end position: " << end();
  os << "\n";
}

1827
void ArrayBoilerplateDescription::ArrayBoilerplateDescriptionPrint(
1828
    std::ostream& os) {
1829
  PrintHeader(os, "ArrayBoilerplateDescription");
1830
  os << "\n - elements kind: " << ElementsKindToString(elements_kind());
1831 1832 1833 1834
  os << "\n - constant elements: " << Brief(constant_elements());
  os << "\n";
}

1835
void RegExpBoilerplateDescription::RegExpBoilerplateDescriptionPrint(
1836
    std::ostream& os) {
1837 1838 1839 1840 1841 1842 1843
  PrintHeader(os, "RegExpBoilerplateDescription");
  os << "\n - data: " << Brief(data());
  os << "\n - source: " << Brief(source());
  os << "\n - flags: " << flags();
  os << "\n";
}

1844
#if V8_ENABLE_WEBASSEMBLY
1845
void AsmWasmData::AsmWasmDataPrint(std::ostream& os) {
1846
  PrintHeader(os, "AsmWasmData");
1847 1848
  os << "\n - native module: " << Brief(managed_native_module());
  os << "\n - export_wrappers: " << Brief(export_wrappers());
1849
  os << "\n - uses bitset: " << uses_bitset().value();
1850 1851 1852
  os << "\n";
}

1853
void WasmTypeInfo::WasmTypeInfoPrint(std::ostream& os) {
1854 1855
  PrintHeader(os, "WasmTypeInfo");
  os << "\n - type address: " << reinterpret_cast<void*>(foreign_address());
1856 1857
  os << "\n - supertypes: " << Brief(supertypes());
  os << "\n - subtypes: " << Brief(subtypes());
1858 1859 1860
  os << "\n";
}

1861
void WasmStruct::WasmStructPrint(std::ostream& os) {
1862 1863 1864 1865 1866 1867 1868
  PrintHeader(os, "WasmStruct");
  wasm::StructType* struct_type = type();
  os << "\n - fields (" << struct_type->field_count() << "):";
  for (uint32_t i = 0; i < struct_type->field_count(); i++) {
    wasm::ValueType field = struct_type->field(i);
    os << "\n   - " << field.short_name() << ": ";
    uint32_t field_offset = struct_type->field_offset(i);
1869
    Address field_address = RawFieldAddress(field_offset);
1870
    switch (field.kind()) {
1871
      case wasm::kI32:
1872 1873
        os << base::ReadUnalignedValue<int32_t>(field_address);
        break;
1874
      case wasm::kI64:
1875 1876
        os << base::ReadUnalignedValue<int64_t>(field_address);
        break;
1877
      case wasm::kF32:
1878 1879
        os << base::ReadUnalignedValue<float>(field_address);
        break;
1880
      case wasm::kF64:
1881 1882
        os << base::ReadUnalignedValue<double>(field_address);
        break;
1883
      case wasm::kI8:
1884 1885
        os << base::ReadUnalignedValue<int8_t>(field_address);
        break;
1886
      case wasm::kI16:
1887 1888
        os << base::ReadUnalignedValue<int16_t>(field_address);
        break;
1889 1890 1891 1892
      case wasm::kRef:
      case wasm::kOptRef:
      case wasm::kRtt:
      case wasm::kRttWithDepth:
1893 1894 1895
        os << Brief(base::ReadUnalignedValue<Object>(field_address));
        break;
      case wasm::kS128:
1896
      case wasm::kBottom:
1897
      case wasm::kVoid:
1898
        os << "UNIMPLEMENTED";  // TODO(7748): Implement.
1899 1900 1901 1902 1903 1904
        break;
    }
  }
  os << "\n";
}

1905
void WasmArray::WasmArrayPrint(std::ostream& os) {
1906 1907 1908
  PrintHeader(os, "WasmArray");
  wasm::ArrayType* array_type = type();
  uint32_t len = length();
1909
  os << "\n - type: " << array_type->element_type().name();
1910 1911 1912
  os << "\n - length: " << len;
  Address data_ptr = ptr() + WasmArray::kHeaderSize - kHeapObjectTag;
  switch (array_type->element_type().kind()) {
1913
    case wasm::kI32:
1914 1915 1916
      PrintTypedArrayElements(os, reinterpret_cast<int32_t*>(data_ptr), len,
                              true);
      break;
1917
    case wasm::kI64:
1918 1919 1920
      PrintTypedArrayElements(os, reinterpret_cast<int64_t*>(data_ptr), len,
                              true);
      break;
1921
    case wasm::kF32:
1922 1923 1924
      PrintTypedArrayElements(os, reinterpret_cast<float*>(data_ptr), len,
                              true);
      break;
1925
    case wasm::kF64:
1926 1927 1928
      PrintTypedArrayElements(os, reinterpret_cast<double*>(data_ptr), len,
                              true);
      break;
1929 1930 1931 1932 1933 1934 1935 1936
    case wasm::kI8:
    case wasm::kI16:
    case wasm::kS128:
    case wasm::kRef:
    case wasm::kOptRef:
    case wasm::kRtt:
    case wasm::kRttWithDepth:
    case wasm::kBottom:
1937
    case wasm::kVoid:
1938 1939
      os << "\n   Printing elements of this type is unimplemented, sorry";
      // TODO(7748): Implement.
1940 1941 1942 1943 1944
      break;
  }
  os << "\n";
}

1945
void WasmExceptionTag::WasmExceptionTagPrint(std::ostream& os) {
1946
  PrintHeader(os, "WasmExceptionTag");
1947 1948 1949 1950
  os << "\n - index: " << index();
  os << "\n";
}

1951
void WasmInstanceObject::WasmInstanceObjectPrint(std::ostream& os) {
1952
  JSObjectPrintHeader(os, *this, "WasmInstanceObject");
1953 1954 1955
  os << "\n - module_object: " << Brief(module_object());
  os << "\n - exports_object: " << Brief(exports_object());
  os << "\n - native_context: " << Brief(native_context());
1956 1957 1958
  if (has_memory_object()) {
    os << "\n - memory_object: " << Brief(memory_object());
  }
1959 1960 1961 1962 1963
  if (has_untagged_globals_buffer()) {
    os << "\n - untagged_globals_buffer: " << Brief(untagged_globals_buffer());
  }
  if (has_tagged_globals_buffer()) {
    os << "\n - tagged_globals_buffer: " << Brief(tagged_globals_buffer());
1964 1965 1966 1967 1968
  }
  if (has_imported_mutable_globals_buffers()) {
    os << "\n - imported_mutable_globals_buffers: "
       << Brief(imported_mutable_globals_buffers());
  }
1969 1970
  for (int i = 0; i < tables().length(); i++) {
    os << "\n - table " << i << ": " << Brief(tables().get(i));
1971
  }
1972 1973 1974 1975
  os << "\n - imported_function_refs: " << Brief(imported_function_refs());
  if (has_indirect_function_table_refs()) {
    os << "\n - indirect_function_table_refs: "
       << Brief(indirect_function_table_refs());
1976 1977 1978 1979 1980
  }
  if (has_managed_native_allocations()) {
    os << "\n - managed_native_allocations: "
       << Brief(managed_native_allocations());
  }
1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993
  os << "\n - memory_start: " << static_cast<void*>(memory_start());
  os << "\n - memory_size: " << memory_size();
  os << "\n - memory_mask: " << AsHex(memory_mask());
  os << "\n - imported_function_targets: "
     << static_cast<void*>(imported_function_targets());
  os << "\n - globals_start: " << static_cast<void*>(globals_start());
  os << "\n - imported_mutable_globals: "
     << static_cast<void*>(imported_mutable_globals());
  os << "\n - indirect_function_table_size: " << indirect_function_table_size();
  os << "\n - indirect_function_table_sig_ids: "
     << static_cast<void*>(indirect_function_table_sig_ids());
  os << "\n - indirect_function_table_targets: "
     << static_cast<void*>(indirect_function_table_targets());
1994
  JSObjectPrintBody(os, *this);
1995 1996 1997
  os << "\n";
}

1998
// Never called directly, as WasmFunctionData is an "abstract" class.
1999
void WasmFunctionData::WasmFunctionDataPrint(std::ostream& os) {
2000 2001
  os << "\n - target: " << reinterpret_cast<void*>(foreign_address());
  os << "\n - ref: " << Brief(ref());
2002
  os << "\n - wrapper_code: " << Brief(wrapper_code());
2003 2004
}

2005
void WasmExportedFunctionData::WasmExportedFunctionDataPrint(std::ostream& os) {
2006
  PrintHeader(os, "WasmExportedFunctionData");
2007
  WasmFunctionDataPrint(os);
2008 2009
  os << "\n - instance: " << Brief(instance());
  os << "\n - function_index: " << function_index();
2010 2011
  os << "\n - signature: " << Brief(signature());
  os << "\n - wrapper_budget: " << wrapper_budget();
2012 2013 2014
  os << "\n";
}

2015
void WasmJSFunctionData::WasmJSFunctionDataPrint(std::ostream& os) {
2016
  PrintHeader(os, "WasmJSFunctionData");
2017 2018 2019 2020
  WasmFunctionDataPrint(os);
  os << "\n - wasm_to_js_wrapper_code: " << Brief(wasm_to_js_wrapper_code());
  os << "\n - serialized_return_count: " << serialized_return_count();
  os << "\n - serialized_parameter_count: " << serialized_parameter_count();
2021 2022 2023 2024 2025 2026 2027 2028 2029
  os << "\n - serialized_signature: " << Brief(serialized_signature());
  os << "\n";
}

void WasmCapiFunctionData::WasmCapiFunctionDataPrint(std::ostream& os) {
  PrintHeader(os, "WasmCapiFunctionData");
  WasmFunctionDataPrint(os);
  os << "\n - embedder_data: " << Brief(embedder_data());
  os << "\n - serialized_signature: " << Brief(serialized_signature());
2030 2031 2032
  os << "\n";
}

2033
void WasmModuleObject::WasmModuleObjectPrint(std::ostream& os) {
2034
  PrintHeader(os, "WasmModuleObject");
2035
  os << "\n - module: " << module();
2036 2037 2038
  os << "\n - native module: " << native_module();
  os << "\n - export wrappers: " << Brief(export_wrappers());
  os << "\n - script: " << Brief(script());
2039 2040 2041
  os << "\n";
}

2042
void WasmTableObject::WasmTableObjectPrint(std::ostream& os) {
2043 2044 2045 2046 2047 2048 2049 2050
  PrintHeader(os, "WasmTableObject");
  os << "\n - elements: " << Brief(elements());
  os << "\n - maximum_length: " << Brief(maximum_length());
  os << "\n - dispatch_tables: " << Brief(dispatch_tables());
  os << "\n - raw_type: " << raw_type();
  os << "\n";
}

2051
void WasmGlobalObject::WasmGlobalObjectPrint(std::ostream& os) {
2052
  PrintHeader(os, "WasmGlobalObject");
2053
  if (type().is_reference()) {
2054 2055 2056 2057
    os << "\n - tagged_buffer: " << Brief(tagged_buffer());
  } else {
    os << "\n - untagged_buffer: " << Brief(untagged_buffer());
  }
2058
  os << "\n - offset: " << offset();
2059 2060
  os << "\n - raw_type: " << raw_type();
  os << "\n - is_mutable: " << is_mutable();
2061
  os << "\n - type: " << type();
2062 2063 2064 2065
  os << "\n - is_mutable: " << is_mutable();
  os << "\n";
}

2066
void WasmMemoryObject::WasmMemoryObjectPrint(std::ostream& os) {
2067 2068 2069 2070 2071 2072 2073
  PrintHeader(os, "WasmMemoryObject");
  os << "\n - array_buffer: " << Brief(array_buffer());
  os << "\n - maximum_pages: " << maximum_pages();
  os << "\n - instances: " << Brief(instances());
  os << "\n";
}

2074
void WasmExceptionObject::WasmExceptionObjectPrint(std::ostream& os) {
2075 2076 2077 2078 2079 2080
  PrintHeader(os, "WasmExceptionObject");
  os << "\n - serialized_signature: " << Brief(serialized_signature());
  os << "\n - exception_tag: " << Brief(exception_tag());
  os << "\n";
}

2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094
void WasmIndirectFunctionTable::WasmIndirectFunctionTablePrint(
    std::ostream& os) {
  PrintHeader(os, "WasmIndirectFunctionTable");
  os << "\n - size: " << size();
  os << "\n - sig_ids: " << static_cast<void*>(sig_ids());
  os << "\n - targets: " << static_cast<void*>(targets());
  if (has_managed_native_allocations()) {
    os << "\n - managed_native_allocations: "
       << Brief(managed_native_allocations());
  }
  os << "\n - refs: " << Brief(refs());
  os << "\n";
}

2095
void WasmValueObject::WasmValueObjectPrint(std::ostream& os) {
2096 2097 2098 2099 2100 2101
  PrintHeader(os, "WasmValueObject");
  os << "\n - value: " << Brief(value());
  os << "\n";
}
#endif  // V8_ENABLE_WEBASSEMBLY

2102
void LoadHandler::LoadHandlerPrint(std::ostream& os) {
2103
  PrintHeader(os, "LoadHandler");
2104 2105 2106
  // TODO(ishell): implement printing based on handler kind
  os << "\n - handler: " << Brief(smi_handler());
  os << "\n - validity_cell: " << Brief(validity_cell());
2107 2108
  int data_count = data_field_count();
  if (data_count >= 1) {
2109
    os << "\n - data1: " << Brief(data1());
2110 2111
  }
  if (data_count >= 2) {
2112
    os << "\n - data2: " << Brief(data2());
2113
  }
2114
  if (data_count >= 3) {
2115
    os << "\n - data3: " << Brief(data3());
2116
  }
2117 2118 2119
  os << "\n";
}

2120
void StoreHandler::StoreHandlerPrint(std::ostream& os) {
2121
  PrintHeader(os, "StoreHandler");
2122 2123 2124
  // TODO(ishell): implement printing based on handler kind
  os << "\n - handler: " << Brief(smi_handler());
  os << "\n - validity_cell: " << Brief(validity_cell());
2125 2126
  int data_count = data_field_count();
  if (data_count >= 1) {
2127
    os << "\n - data1: " << Brief(data1());
2128 2129
  }
  if (data_count >= 2) {
2130
    os << "\n - data2: " << Brief(data2());
2131
  }
2132
  if (data_count >= 3) {
2133
    os << "\n - data3: " << Brief(data3());
2134
  }
2135 2136 2137
  os << "\n";
}

2138
void AccessorPair::AccessorPairPrint(std::ostream& os) {
2139
  PrintHeader(os, "AccessorPair");
2140 2141 2142 2143 2144
  os << "\n - getter: " << Brief(getter());
  os << "\n - setter: " << Brief(setter());
  os << "\n";
}

2145
void CallHandlerInfo::CallHandlerInfoPrint(std::ostream& os) {
2146
  PrintHeader(os, "CallHandlerInfo");
2147 2148 2149 2150
  os << "\n - callback: " << Brief(callback());
  os << "\n - js_callback: " << Brief(js_callback());
  os << "\n - data: " << Brief(data());
  os << "\n - side_effect_free: "
2151
     << (IsSideEffectFreeCallHandlerInfo() ? "true" : "false");
2152 2153
  os << "\n";
}
2154

2155
void FunctionTemplateInfo::FunctionTemplateInfoPrint(std::ostream& os) {
2156
  PrintHeader(os, "FunctionTemplateInfo");
2157
  os << "\n - class name: " << Brief(class_name());
2158 2159
  os << "\n - tag: " << tag();
  os << "\n - serial_number: " << serial_number();
2160
  os << "\n - property_list: " << Brief(property_list());
2161
  os << "\n - call_code: " << Brief(call_code(kAcquireLoad));
2162 2163
  os << "\n - property_accessors: " << Brief(property_accessors());
  os << "\n - signature: " << Brief(signature());
2164
  os << "\n - cached_property_name: " << Brief(cached_property_name());
2165 2166
  os << "\n - undetectable: " << (undetectable() ? "true" : "false");
  os << "\n - need_access_check: " << (needs_access_check() ? "true" : "false");
2167
  os << "\n - instantiated: " << (instantiated() ? "true" : "false");
2168
  os << "\n - rare_data: " << Brief(rare_data(kAcquireLoad));
2169 2170 2171
  os << "\n";
}

2172
void ObjectTemplateInfo::ObjectTemplateInfoPrint(std::ostream& os) {
2173
  PrintHeader(os, "ObjectTemplateInfo");
2174 2175
  os << "\n - tag: " << tag();
  os << "\n - serial_number: " << serial_number();
2176 2177 2178
  os << "\n - property_list: " << Brief(property_list());
  os << "\n - property_accessors: " << Brief(property_accessors());
  os << "\n - constructor: " << Brief(constructor());
2179
  os << "\n - embedder_field_count: " << embedder_field_count();
2180
  os << "\n - immutable_proto: " << (immutable_proto() ? "true" : "false");
2181 2182 2183
  os << "\n";
}

2184
void AllocationSite::AllocationSitePrint(std::ostream& os) {
2185
  PrintHeader(os, "AllocationSite");
2186
  if (this->HasWeakNext()) os << "\n - weak_next: " << Brief(weak_next());
2187 2188 2189 2190 2191 2192 2193 2194 2195
  os << "\n - dependent code: " << Brief(dependent_code());
  os << "\n - nested site: " << Brief(nested_site());
  os << "\n - memento found count: "
     << Brief(Smi::FromInt(memento_found_count()));
  os << "\n - memento create count: "
     << Brief(Smi::FromInt(memento_create_count()));
  os << "\n - pretenure decision: "
     << Brief(Smi::FromInt(pretenure_decision()));
  os << "\n - transition_info: ";
2196
  if (!PointsToLiteral()) {
2197
    ElementsKind kind = GetElementsKind();
2198
    os << "Array allocation with ElementsKind " << ElementsKindToString(kind);
2199
  } else if (boilerplate().IsJSArray()) {
2200
    os << "Array literal with boilerplate " << Brief(boilerplate());
2201
  } else {
2202
    os << "Object literal with boilerplate " << Brief(boilerplate());
2203
  }
2204
  os << "\n";
2205 2206
}

2207
void AllocationMemento::AllocationMementoPrint(std::ostream& os) {
2208
  PrintHeader(os, "AllocationMemento");
2209
  os << "\n - allocation site: ";
2210
  if (IsValid()) {
2211
    GetAllocationSite().AllocationSitePrint(os);
2212
  } else {
2213
    os << "<invalid>\n";
2214 2215 2216
  }
}

2217
void Script::ScriptPrint(std::ostream& os) {
2218
  PrintHeader(os, "Script");
2219 2220
  os << "\n - source: " << Brief(source());
  os << "\n - name: " << Brief(name());
2221
  os << "\n - source_url: " << Brief(source_url());
2222 2223 2224 2225
  os << "\n - line_offset: " << line_offset();
  os << "\n - column_offset: " << column_offset();
  os << "\n - type: " << type();
  os << "\n - id: " << id();
2226 2227 2228
  os << "\n - context data: " << Brief(context_data());
  os << "\n - compilation type: " << compilation_type();
  os << "\n - line ends: " << Brief(line_ends());
2229 2230 2231
  bool is_wasm = false;
#if V8_ENABLE_WEBASSEMBLY
  if ((is_wasm = (type() == TYPE_WASM))) {
2232 2233 2234
    if (has_wasm_breakpoint_infos()) {
      os << "\n - wasm_breakpoint_infos: " << Brief(wasm_breakpoint_infos());
    }
2235 2236 2237
  }
#endif  // V8_ENABLE_WEBASSEMBLY
  if (!is_wasm) {
2238 2239
    if (has_eval_from_shared()) {
      os << "\n - eval from shared: " << Brief(eval_from_shared());
2240
    } else if (is_wrapped()) {
2241
      os << "\n - wrapped arguments: " << Brief(wrapped_arguments());
2242 2243 2244
    } else if (type() == TYPE_WEB_SNAPSHOT) {
      os << "\n - shared function info table: "
         << Brief(shared_function_info_table());
2245 2246
    }
    os << "\n - eval from position: " << eval_from_position();
2247
  }
2248
  os << "\n - shared function infos: " << Brief(shared_function_infos());
2249 2250 2251
  os << "\n";
}

2252
#ifdef V8_INTL_SUPPORT
2253
void JSV8BreakIterator::JSV8BreakIteratorPrint(std::ostream& os) {
2254
  JSObjectPrintHeader(os, *this, "JSV8BreakIterator");
2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265
  os << "\n - locale: " << Brief(locale());
  os << "\n - break iterator: " << Brief(break_iterator());
  os << "\n - unicode string: " << Brief(unicode_string());
  os << "\n - bound adopt text: " << Brief(bound_adopt_text());
  os << "\n - bound first: " << Brief(bound_first());
  os << "\n - bound next: " << Brief(bound_next());
  os << "\n - bound current: " << Brief(bound_current());
  os << "\n - bound break type: " << Brief(bound_break_type());
  os << "\n";
}

2266
void JSCollator::JSCollatorPrint(std::ostream& os) {
2267
  JSObjectPrintHeader(os, *this, "JSCollator");
2268
  os << "\n - icu collator: " << Brief(icu_collator());
2269
  os << "\n - bound compare: " << Brief(bound_compare());
2270
  JSObjectPrintBody(os, *this);
2271 2272
}

2273
void JSDateTimeFormat::JSDateTimeFormatPrint(std::ostream& os) {
2274
  JSObjectPrintHeader(os, *this, "JSDateTimeFormat");
2275
  os << "\n - locale: " << Brief(locale());
2276
  os << "\n - icu locale: " << Brief(icu_locale());
2277
  os << "\n - icu simple date format: " << Brief(icu_simple_date_format());
2278
  os << "\n - icu date interval format: " << Brief(icu_date_interval_format());
2279
  os << "\n - bound format: " << Brief(bound_format());
2280
  os << "\n - hour cycle: " << HourCycleAsString();
2281
  JSObjectPrintBody(os, *this);
2282 2283
}

2284
void JSDisplayNames::JSDisplayNamesPrint(std::ostream& os) {
2285 2286 2287 2288 2289 2290 2291
  JSObjectPrintHeader(os, *this, "JSDisplayNames");
  os << "\n - internal: " << Brief(internal());
  os << "\n - style: " << StyleAsString();
  os << "\n - fallback: " << FallbackAsString();
  JSObjectPrintBody(os, *this);
}

2292
void JSListFormat::JSListFormatPrint(std::ostream& os) {
2293
  JSObjectPrintHeader(os, *this, "JSListFormat");
2294 2295 2296
  os << "\n - locale: " << Brief(locale());
  os << "\n - style: " << StyleAsString();
  os << "\n - type: " << TypeAsString();
2297
  os << "\n - icu formatter: " << Brief(icu_formatter());
2298
  JSObjectPrintBody(os, *this);
2299 2300
}

2301
void JSLocale::JSLocalePrint(std::ostream& os) {
2302
  JSObjectPrintHeader(os, *this, "JSLocale");
2303 2304
  os << "\n - icu locale: " << Brief(icu_locale());
  JSObjectPrintBody(os, *this);
2305
}
2306

2307
void JSNumberFormat::JSNumberFormatPrint(std::ostream& os) {
2308
  JSObjectPrintHeader(os, *this, "JSNumberFormat");
2309
  os << "\n - locale: " << Brief(locale());
2310
  os << "\n - icu_number_formatter: " << Brief(icu_number_formatter());
2311
  os << "\n - bound_format: " << Brief(bound_format());
2312
  JSObjectPrintBody(os, *this);
2313 2314
}

2315
void JSPluralRules::JSPluralRulesPrint(std::ostream& os) {
2316
  JSObjectPrintHeader(os, *this, "JSPluralRules");
2317
  os << "\n - locale: " << Brief(locale());
2318
  os << "\n - type: " << TypeAsString();
2319
  os << "\n - icu plural rules: " << Brief(icu_plural_rules());
2320
  os << "\n - icu_number_formatter: " << Brief(icu_number_formatter());
2321
  JSObjectPrintBody(os, *this);
2322 2323
}

2324
void JSRelativeTimeFormat::JSRelativeTimeFormatPrint(std::ostream& os) {
2325
  JSObjectPrintHeader(os, *this, "JSRelativeTimeFormat");
2326
  os << "\n - locale: " << Brief(locale());
2327
  os << "\n - numberingSystem: " << Brief(numberingSystem());
2328
  os << "\n - numeric: " << NumericAsString();
2329
  os << "\n - icu formatter: " << Brief(icu_formatter());
2330 2331
  os << "\n";
}
2332

2333
void JSSegmentIterator::JSSegmentIteratorPrint(std::ostream& os) {
2334
  JSObjectPrintHeader(os, *this, "JSSegmentIterator");
2335
  os << "\n - icu break iterator: " << Brief(icu_break_iterator());
2336
  os << "\n - granularity: " << GranularityAsString(GetIsolate());
2337 2338 2339
  os << "\n";
}

2340
void JSSegmenter::JSSegmenterPrint(std::ostream& os) {
2341
  JSObjectPrintHeader(os, *this, "JSSegmenter");
2342
  os << "\n - locale: " << Brief(locale());
2343 2344 2345 2346 2347
  os << "\n - granularity: " << GranularityAsString(GetIsolate());
  os << "\n - icu break iterator: " << Brief(icu_break_iterator());
  JSObjectPrintBody(os, *this);
}

2348
void JSSegments::JSSegmentsPrint(std::ostream& os) {
2349
  JSObjectPrintHeader(os, *this, "JSSegments");
2350
  os << "\n - icu break iterator: " << Brief(icu_break_iterator());
2351 2352
  os << "\n - unicode string: " << Brief(unicode_string());
  os << "\n - granularity: " << GranularityAsString(GetIsolate());
2353
  JSObjectPrintBody(os, *this);
2354
}
2355 2356
#endif  // V8_INTL_SUPPORT

2357
namespace {
2358
void PrintScopeInfoList(ScopeInfo scope_info, std::ostream& os,
2359
                        const char* list_name, int length) {
2360 2361 2362
  if (length <= 0) return;
  os << "\n - " << list_name;
  os << " {\n";
2363
  for (int i = 0; i < length; ++i) {
2364
    os << "    - " << i << ": ";
2365
    scope_info.context_local_names(i).ShortPrint(os);
2366 2367 2368 2369 2370 2371
    os << "\n";
  }
  os << "  }";
}
}  // namespace

2372
void ScopeInfo::ScopeInfoPrint(std::ostream& os) {
2373
  PrintHeader(os, "ScopeInfo");
2374 2375
  if (IsEmpty()) {
    os << "\n - empty\n";
2376 2377
    return;
  }
2378 2379 2380 2381
  int flags = Flags();

  os << "\n - parameters: " << ParameterCount();
  os << "\n - context locals : " << ContextLocalCount();
2382

2383
  os << "\n - scope type: " << scope_type();
2384
  if (SloppyEvalCanExtendVars()) os << "\n - sloppy eval";
2385
  os << "\n - language mode: " << language_mode();
2386 2387
  if (is_declaration_scope()) os << "\n - declaration scope";
  if (HasReceiver()) {
2388
    os << "\n - receiver: " << ReceiverVariableBits::decode(flags);
2389
  }
2390
  if (HasClassBrand()) os << "\n - has class brand";
2391
  if (HasSavedClassVariableIndex()) os << "\n - has saved class variable index";
2392
  if (HasNewTarget()) os << "\n - needs new target";
2393
  if (HasFunctionName()) {
2394
    os << "\n - function name(" << FunctionVariableBits::decode(flags) << "): ";
2395
    FunctionName().ShortPrint(os);
2396 2397 2398 2399
  }
  if (IsAsmModule()) os << "\n - asm module";
  if (HasSimpleParameters()) os << "\n - simple parameters";
  os << "\n - function kind: " << function_kind();
2400 2401 2402
  if (HasOuterScopeInfo()) {
    os << "\n - outer scope info: " << Brief(OuterScopeInfo());
  }
Dan Elphick's avatar
Dan Elphick committed
2403 2404
  if (HasLocalsBlockList()) {
    os << "\n - locals blocklist: " << Brief(LocalsBlockList());
2405
  }
2406
  if (HasFunctionName()) {
2407
    os << "\n - function name: " << Brief(FunctionName());
2408
  }
2409 2410 2411
  if (HasInferredFunctionName()) {
    os << "\n - inferred function name: " << Brief(InferredFunctionName());
  }
2412 2413
  if (HasContextExtensionSlot()) {
    os << "\n - has context extension slot";
2414
  }
2415

2416
  if (HasPositionInfo()) {
2417 2418
    os << "\n - start position: " << StartPosition();
    os << "\n - end position: " << EndPosition();
2419
  }
2420 2421
  os << "\n - length: " << length();
  if (length() > 0) {
2422
    PrintScopeInfoList(*this, os, "context slots", ContextLocalCount());
2423 2424 2425 2426
    // TODO(neis): Print module stuff if present.
  }
  os << "\n";
}
2427

2428
void StackFrameInfo::StackFrameInfoPrint(std::ostream& os) {
2429 2430 2431 2432
  PrintHeader(os, "StackFrameInfo");
  os << "\n - receiver_or_instance: " << Brief(receiver_or_instance());
  os << "\n - function: " << Brief(function());
  os << "\n - code_object: " << Brief(code_object());
2433 2434
  os << "\n - code_offset_or_source_position: "
     << code_offset_or_source_position();
2435 2436
  os << "\n - flags: " << flags();
  os << "\n - parameters: " << Brief(parameters());
2437 2438
  os << "\n";
}
2439

2440
void PreparseData::PreparseDataPrint(std::ostream& os) {
2441
  PrintHeader(os, "PreparseData");
2442 2443
  os << "\n - data_length: " << data_length();
  os << "\n - children_length: " << children_length();
2444 2445 2446 2447 2448 2449
  if (data_length() > 0) {
    os << "\n - data-start: " << (address() + kDataStartOffset);
  }
  if (children_length() > 0) {
    os << "\n - children-start: " << inner_start_offset();
  }
2450 2451
  for (int i = 0; i < children_length(); ++i) {
    os << "\n - [" << i << "]: " << Brief(get_child(i));
2452
  }
2453 2454
  os << "\n";
}
2455

2456
void InterpreterData::InterpreterDataPrint(std::ostream& os) {
2457
  PrintHeader(os, "InterpreterData");
2458 2459 2460 2461 2462
  os << "\n - bytecode_array: " << Brief(bytecode_array());
  os << "\n - interpreter_trampoline: " << Brief(interpreter_trampoline());
  os << "\n";
}

2463 2464
template <HeapObjectReferenceType kRefType, typename StorageType>
void TaggedImpl<kRefType, StorageType>::Print() {
2465
  StdoutStream os;
2466
  this->Print(os);
2467 2468 2469
  os << std::flush;
}

2470 2471
template <HeapObjectReferenceType kRefType, typename StorageType>
void TaggedImpl<kRefType, StorageType>::Print(std::ostream& os) {
2472
  Smi smi;
2473
  HeapObject heap_object;
2474
  if (ToSmi(&smi)) {
2475
    smi.SmiPrint(os);
2476
  } else if (IsCleared()) {
2477
    os << "[cleared]";
2478
  } else if (GetHeapObjectIfWeak(&heap_object)) {
2479
    os << "[weak] ";
2480
    heap_object.HeapObjectPrint(os);
2481
  } else if (GetHeapObjectIfStrong(&heap_object)) {
2482
    heap_object.HeapObjectPrint(os);
2483 2484 2485 2486 2487
  } else {
    UNREACHABLE();
  }
}

2488 2489 2490 2491 2492
void HeapNumber::HeapNumberPrint(std::ostream& os) {
  HeapNumberShortPrint(os);
  os << "\n";
}

2493 2494
#endif  // OBJECT_PRINT

2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512
void HeapNumber::HeapNumberShortPrint(std::ostream& os) {
  static constexpr uint64_t kUint64AllBitsSet =
      static_cast<uint64_t>(int64_t{-1});
  // Min/max integer values representable by 52 bits of mantissa and 1 sign bit.
  static constexpr int64_t kMinSafeInteger =
      static_cast<int64_t>(kUint64AllBitsSet << 53);
  static constexpr int64_t kMaxSafeInteger = -(kMinSafeInteger + 1);

  double val = value();
  if (val == DoubleToInteger(val) &&
      val >= static_cast<double>(kMinSafeInteger) &&
      val <= static_cast<double>(kMaxSafeInteger)) {
    int64_t i = static_cast<int64_t>(val);
    os << i << ".0";
  } else {
    os << val;
  }
}
2513

2514
// TODO(cbruni): remove once the new maptracer is in place.
2515
void Name::NameShortPrint() {
2516
  if (this->IsString()) {
2517
    PrintF("%s", String::cast(*this).ToCString().get());
2518 2519
  } else {
    DCHECK(this->IsSymbol());
2520
    Symbol s = Symbol::cast(*this);
2521
    if (s.description().IsUndefined()) {
2522
      PrintF("#<%s>", s.PrivateSymbolToName());
2523
    } else {
2524
      PrintF("<%s>", String::cast(s.description()).ToCString().get());
2525 2526 2527 2528
    }
  }
}

2529
// TODO(cbruni): remove once the new maptracer is in place.
2530
int Name::NameShortPrint(Vector<char> str) {
2531
  if (this->IsString()) {
2532
    return SNPrintF(str, "%s", String::cast(*this).ToCString().get());
2533 2534
  } else {
    DCHECK(this->IsSymbol());
2535
    Symbol s = Symbol::cast(*this);
2536
    if (s.description().IsUndefined()) {
2537
      return SNPrintF(str, "#<%s>", s.PrivateSymbolToName());
2538
    } else {
2539 2540
      return SNPrintF(str, "<%s>",
                      String::cast(s.description()).ToCString().get());
2541 2542 2543 2544
    }
  }
}

2545
void Map::PrintMapDetails(std::ostream& os) {
2546
  DisallowGarbageCollection no_gc;
2547
  this->MapPrint(os);
2548
  instance_descriptors().PrintDescriptors(os);
2549 2550
}

2551
void Map::MapPrint(std::ostream& os) {
2552 2553
#ifdef OBJECT_PRINT
  PrintHeader(os, "Map");
2554
#else
2555
  os << "Map=" << reinterpret_cast<void*>(ptr());
2556
#endif
2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590
  os << "\n - type: " << instance_type();
  os << "\n - instance size: ";
  if (instance_size() == kVariableSizeSentinel) {
    os << "variable";
  } else {
    os << instance_size();
  }
  if (IsJSObjectMap()) {
    os << "\n - inobject properties: " << GetInObjectProperties();
  }
  os << "\n - elements kind: " << ElementsKindToString(elements_kind());
  os << "\n - unused property fields: " << UnusedPropertyFields();
  os << "\n - enum length: ";
  if (EnumLength() == kInvalidEnumCacheSentinel) {
    os << "invalid";
  } else {
    os << EnumLength();
  }
  if (is_deprecated()) os << "\n - deprecated_map";
  if (is_stable()) os << "\n - stable_map";
  if (is_migration_target()) os << "\n - migration_target";
  if (is_dictionary_map()) os << "\n - dictionary_map";
  if (has_named_interceptor()) os << "\n - named_interceptor";
  if (has_indexed_interceptor()) os << "\n - indexed_interceptor";
  if (may_have_interesting_symbols()) os << "\n - may_have_interesting_symbols";
  if (is_undetectable()) os << "\n - undetectable";
  if (is_callable()) os << "\n - callable";
  if (is_constructor()) os << "\n - constructor";
  if (has_prototype_slot()) {
    os << "\n - has_prototype_slot";
    if (has_non_instance_prototype()) os << " (non-instance prototype)";
  }
  if (is_access_check_needed()) os << "\n - access_check_needed";
  if (!is_extensible()) os << "\n - non-extensible";
2591 2592 2593
  if (IsContextMap()) {
    os << "\n - native context: " << Brief(native_context());
  } else if (is_prototype_map()) {
2594 2595 2596 2597 2598 2599 2600 2601
    os << "\n - prototype_map";
    os << "\n - prototype info: " << Brief(prototype_info());
  } else {
    os << "\n - back pointer: " << Brief(GetBackPointer());
  }
  os << "\n - prototype_validity cell: " << Brief(prototype_validity_cell());
  os << "\n - instance descriptors " << (owns_descriptors() ? "(own) " : "")
     << "#" << NumberOfOwnDescriptors() << ": "
2602
     << Brief(instance_descriptors());
2603 2604 2605

  // Read-only maps can't have transitions, which is fortunate because we need
  // the isolate to iterate over the transitions.
2606 2607
  if (!IsReadOnlyHeapObject(*this)) {
    Isolate* isolate = GetIsolateFromWritableObject(*this);
2608
    DisallowGarbageCollection no_gc;
2609 2610 2611 2612
    TransitionsAccessor transitions(isolate, *this, &no_gc);
    int nof_transitions = transitions.NumberOfTransitions();
    if (nof_transitions > 0) {
      os << "\n - transitions #" << nof_transitions << ": ";
2613
      HeapObject heap_object;
2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625
      Smi smi;
      if (raw_transitions()->ToSmi(&smi)) {
        os << Brief(smi);
      } else if (raw_transitions()->GetHeapObject(&heap_object)) {
        os << Brief(heap_object);
      }
#ifdef OBJECT_PRINT
      transitions.PrintTransitions(os);
#endif  // OBJECT_PRINT
    }
  }
  os << "\n - prototype: " << Brief(prototype());
2626 2627 2628
  if (!IsContextMap()) {
    os << "\n - constructor: " << Brief(GetConstructor());
  }
2629 2630
  os << "\n - dependent code: " << Brief(dependent_code());
  os << "\n - construction counter: " << construction_counter();
2631
  os << "\n";
2632 2633
}

2634
void DescriptorArray::PrintDescriptors(std::ostream& os) {
2635
  for (InternalIndex i : InternalIndex::Range(number_of_descriptors())) {
2636
    Name key = GetKey(i);
2637
    os << "\n  [" << i.as_int() << "]: ";
2638
#ifdef OBJECT_PRINT
2639
    key.NamePrint(os);
2640
#else
2641
    key.ShortPrint(os);
2642 2643 2644
#endif
    os << " ";
    PrintDescriptorDetails(os, i, PropertyDetails::kPrintFull);
2645 2646 2647 2648
  }
  os << "\n";
}

2649 2650
void DescriptorArray::PrintDescriptorDetails(std::ostream& os,
                                             InternalIndex descriptor,
2651 2652 2653 2654 2655 2656
                                             PropertyDetails::PrintMode mode) {
  PropertyDetails details = GetDetails(descriptor);
  details.PrintAsFastTo(os, mode);
  os << " @ ";
  switch (details.location()) {
    case kField: {
2657
      FieldType field_type = GetFieldType(descriptor);
2658
      field_type.PrintTo(os);
2659 2660 2661
      break;
    }
    case kDescriptor:
2662
      Object value = GetStrongValue(descriptor);
2663
      os << Brief(value);
2664
      if (value.IsAccessorPair()) {
2665
        AccessorPair pair = AccessorPair::cast(value);
2666 2667
        os << "(get: " << Brief(pair.getter())
           << ", set: " << Brief(pair.setter()) << ")";
2668 2669 2670 2671
      }
      break;
  }
}
2672

2673 2674 2675 2676 2677 2678 2679 2680 2681 2682
#if defined(DEBUG) || defined(OBJECT_PRINT)
// This method is only meant to be called from gdb for debugging purposes.
// Since the string can also be in two-byte encoding, non-Latin1 characters
// will be ignored in the output.
char* String::ToAsciiArray() {
  // Static so that subsequent calls frees previously allocated space.
  // This also means that previous results will be overwritten.
  static char* buffer = nullptr;
  if (buffer != nullptr) delete[] buffer;
  buffer = new char[length() + 1];
2683
  WriteToFlat(*this, reinterpret_cast<uint8_t*>(buffer), 0, length());
2684 2685 2686 2687
  buffer[length()] = 0;
  return buffer;
}

2688
// static
2689
void TransitionsAccessor::PrintOneTransition(std::ostream& os, Name key,
2690
                                             Map target) {
2691 2692
  os << "\n     ";
#ifdef OBJECT_PRINT
2693
  key.NamePrint(os);
2694
#else
2695
  key.ShortPrint(os);
2696 2697
#endif
  os << ": ";
2698
  ReadOnlyRoots roots = key.GetReadOnlyRoots();
2699
  if (key == roots.nonextensible_symbol()) {
2700
    os << "(transition to non-extensible)";
2701
  } else if (key == roots.sealed_symbol()) {
2702
    os << "(transition to sealed)";
2703
  } else if (key == roots.frozen_symbol()) {
2704
    os << "(transition to frozen)";
2705
  } else if (key == roots.elements_transition_symbol()) {
2706
    os << "(transition to " << ElementsKindToString(target.elements_kind())
2707
       << ")";
2708
  } else if (key == roots.strict_function_transition_symbol()) {
2709 2710
    os << " (transition to strict function)";
  } else {
2711
    DCHECK(!IsSpecialTransition(roots, key));
2712
    os << "(transition to ";
2713
    InternalIndex descriptor = target.LastAdded();
2714
    DescriptorArray descriptors = target.instance_descriptors();
2715 2716
    descriptors.PrintDescriptorDetails(os, descriptor,
                                       PropertyDetails::kForTransitions);
2717 2718 2719 2720 2721
    os << ")";
  }
  os << " -> " << Brief(target);
}

2722
void TransitionArray::PrintInternal(std::ostream& os) {
2723 2724
  int num_transitions = number_of_transitions();
  os << "Transition array #" << num_transitions << ":";
2725
  for (int i = 0; i < num_transitions; i++) {
2726
    Name key = GetKey(i);
2727
    Map target = GetTarget(i);
2728
    TransitionsAccessor::PrintOneTransition(os, key, target);
2729
  }
2730 2731 2732
  os << "\n" << std::flush;
}

2733
void TransitionsAccessor::PrintTransitions(std::ostream& os) {
2734 2735 2736
  switch (encoding()) {
    case kPrototypeInfo:
    case kUninitialized:
2737
    case kMigrationTarget:
2738
      return;
2739
    case kWeakRef: {
2740
      Map target = Map::cast(raw_transitions_->GetHeapObjectAssumeWeak());
2741
      Name key = GetSimpleTransitionKey(target);
2742
      PrintOneTransition(os, key, target);
2743
      break;
2744
    }
2745
    case kFullTransitionArray:
2746
      return transitions().PrintInternal(os);
2747
  }
2748 2749
}

2750
void TransitionsAccessor::PrintTransitionTree() {
2751
  StdoutStream os;
2752
  os << "map= " << Brief(map_);
2753
  DisallowGarbageCollection no_gc;
2754
  PrintTransitionTree(os, 0, &no_gc);
2755 2756 2757
  os << "\n" << std::flush;
}

2758 2759
void TransitionsAccessor::PrintTransitionTree(
    std::ostream& os, int level, DisallowGarbageCollection* no_gc) {
2760
  ReadOnlyRoots roots = ReadOnlyRoots(isolate_);
2761
  int num_transitions = NumberOfTransitions();
2762 2763
  if (num_transitions == 0) return;
  for (int i = 0; i < num_transitions; i++) {
2764
    Name key = GetKey(i);
2765
    Map target = GetTarget(i);
2766 2767
    os << std::endl
       << "  " << level << "/" << i << ":" << std::setw(level * 2 + 2) << " ";
2768 2769 2770 2771
    std::stringstream ss;
    ss << Brief(target);
    os << std::left << std::setw(50) << ss.str() << ": ";

2772
    if (key == roots.nonextensible_symbol()) {
2773
      os << "to non-extensible";
2774
    } else if (key == roots.sealed_symbol()) {
2775
      os << "to sealed ";
2776
    } else if (key == roots.frozen_symbol()) {
2777
      os << "to frozen";
2778
    } else if (key == roots.elements_transition_symbol()) {
2779
      os << "to " << ElementsKindToString(target.elements_kind());
2780
    } else if (key == roots.strict_function_transition_symbol()) {
2781 2782 2783
      os << "to strict function";
    } else {
#ifdef OBJECT_PRINT
2784
      key.NamePrint(os);
2785
#else
2786
      key.ShortPrint(os);
2787 2788
#endif
      os << " ";
2789
      DCHECK(!IsSpecialTransition(ReadOnlyRoots(isolate_), key));
2790
      os << "to ";
2791
      InternalIndex descriptor = target.LastAdded();
2792
      DescriptorArray descriptors = target.instance_descriptors(isolate_);
2793 2794
      descriptors.PrintDescriptorDetails(os, descriptor,
                                         PropertyDetails::kForTransitions);
2795
    }
2796
    TransitionsAccessor transitions(isolate_, target, no_gc);
2797
    transitions.PrintTransitionTree(os, level + 1, no_gc);
2798 2799
  }
}
2800

2801
void JSObject::PrintTransitions(std::ostream& os) {
2802
  DisallowGarbageCollection no_gc;
2803
  TransitionsAccessor ta(GetIsolate(), map(), &no_gc);
2804
  if (ta.NumberOfTransitions() == 0) return;
2805
  os << "\n - transitions";
2806
  ta.PrintTransitions(os);
2807
}
2808

2809
#endif  // defined(DEBUG) || defined(OBJECT_PRINT)
2810 2811
}  // namespace internal
}  // namespace v8
2812

2813 2814 2815 2816 2817
namespace {

inline i::Object GetObjectFromRaw(void* object) {
  i::Address object_ptr = reinterpret_cast<i::Address>(object);
#ifdef V8_COMPRESS_POINTERS
2818
  if (RoundDown<i::kPtrComprCageBaseAlignment>(object_ptr) == i::kNullAddress) {
2819 2820
    // Try to decompress pointer.
    i::Isolate* isolate = i::Isolate::Current();
2821 2822
    object_ptr =
        i::DecompressTaggedAny(isolate, static_cast<i::Tagged_t>(object_ptr));
2823 2824 2825 2826 2827 2828 2829
  }
#endif
  return i::Object(object_ptr);
}

}  // namespace

2830 2831 2832
//
// The following functions are used by our gdb macros.
//
2833 2834 2835 2836
V8_EXPORT_PRIVATE extern i::Object _v8_internal_Get_Object(void* object) {
  return GetObjectFromRaw(object);
}

2837
V8_EXPORT_PRIVATE extern void _v8_internal_Print_Object(void* object) {
2838
  GetObjectFromRaw(object).Print();
2839 2840
}

2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856
V8_EXPORT_PRIVATE extern void _v8_internal_Print_LoadHandler(void* object) {
#ifdef OBJECT_PRINT
  i::StdoutStream os;
  i::LoadHandler::PrintHandler(GetObjectFromRaw(object), os);
  os << std::flush;
#endif
}

V8_EXPORT_PRIVATE extern void _v8_internal_Print_StoreHandler(void* object) {
#ifdef OBJECT_PRINT
  i::StdoutStream os;
  i::StoreHandler::PrintHandler(GetObjectFromRaw(object), os);
  os << std::flush;
#endif
}

2857
V8_EXPORT_PRIVATE extern void _v8_internal_Print_Code(void* object) {
2858
  i::Address address = reinterpret_cast<i::Address>(object);
2859
  i::Isolate* isolate = i::Isolate::Current();
2860

2861
#if V8_ENABLE_WEBASSEMBLY
2862 2863 2864 2865 2866 2867 2868 2869 2870
  {
    i::wasm::WasmCodeRefScope scope;
    i::wasm::WasmCode* wasm_code =
        isolate->wasm_engine()->code_manager()->LookupCode(address);
    if (wasm_code) {
      i::StdoutStream os;
      wasm_code->Disassemble(nullptr, os, address);
      return;
    }
2871
  }
2872
#endif  // V8_ENABLE_WEBASSEMBLY
2873 2874

  if (!isolate->heap()->InSpaceSlow(address, i::CODE_SPACE) &&
2875
      !isolate->heap()->InSpaceSlow(address, i::CODE_LO_SPACE) &&
2876 2877
      !i::InstructionStream::PcIsOffHeap(isolate, address) &&
      !i::ReadOnlyHeap::Contains(address)) {
2878
    i::PrintF(
2879 2880
        "%p is not within the current isolate's code, read_only or embedded "
        "spaces\n",
2881
        object);
2882 2883 2884
    return;
  }

2885
  i::Code code = isolate->FindCodeObject(address);
2886
  if (!code.IsCode()) {
2887
    i::PrintF("No code object found containing %p\n", object);
2888 2889 2890
    return;
  }
#ifdef ENABLE_DISASSEMBLER
2891
  i::StdoutStream os;
2892
  code.Disassemble(nullptr, os, isolate, address);
2893
#else   // ENABLE_DISASSEMBLER
2894
  code.Print();
2895
#endif  // ENABLE_DISASSEMBLER
2896 2897
}

2898
V8_EXPORT_PRIVATE extern void _v8_internal_Print_StackTrace() {
2899 2900 2901
  i::Isolate* isolate = i::Isolate::Current();
  isolate->PrintStack(stdout);
}
2902

2903
V8_EXPORT_PRIVATE extern void _v8_internal_Print_TransitionTree(void* object) {
2904
  i::Object o(GetObjectFromRaw(object));
2905
  if (!o.IsMap()) {
2906 2907 2908
    printf("Please provide a valid Map\n");
  } else {
#if defined(DEBUG) || defined(OBJECT_PRINT)
2909
    i::DisallowGarbageCollection no_gc;
2910
    i::Map map = i::Map::unchecked_cast(o);
2911
    i::TransitionsAccessor transitions(i::Isolate::Current(), map, &no_gc);
2912
    transitions.PrintTransitionTree();
2913 2914 2915
#endif
  }
}