objects-printer.cc 83.8 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 "src/objects.h"
6

7
#include <iomanip>
8 9
#include <memory>

10
#include "src/bootstrapper.h"
11
#include "src/disasm.h"
12
#include "src/disassembler.h"
13
#include "src/instruction-stream.h"
14
#include "src/interpreter/bytecodes.h"
15
#include "src/objects-inl.h"
16
#include "src/objects/arguments-inl.h"
17
#include "src/objects/data-handler-inl.h"
18
#include "src/objects/debug-objects-inl.h"
19
#include "src/objects/hash-table-inl.h"
20 21
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h"
22
#ifdef V8_INTL_SUPPORT
23
#include "src/objects/js-break-iterator-inl.h"
24 25
#include "src/objects/js-collator-inl.h"
#endif  // V8_INTL_SUPPORT
26
#include "src/objects/js-collection-inl.h"
27 28 29
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-date-time-format-inl.h"
#endif  // V8_INTL_SUPPORT
30
#include "src/objects/js-generator-inl.h"
31
#ifdef V8_INTL_SUPPORT
32
#include "src/objects/js-list-format-inl.h"
33
#include "src/objects/js-locale-inl.h"
34 35
#include "src/objects/js-number-format-inl.h"
#include "src/objects/js-plural-rules-inl.h"
36
#endif  // V8_INTL_SUPPORT
37 38
#include "src/objects/js-regexp-inl.h"
#include "src/objects/js-regexp-string-iterator-inl.h"
39 40
#ifdef V8_INTL_SUPPORT
#include "src/objects/js-relative-time-format-inl.h"
41
#include "src/objects/js-segmenter-inl.h"
42
#endif  // V8_INTL_SUPPORT
43
#include "src/objects/js-weak-refs-inl.h"
44
#include "src/objects/literal-objects-inl.h"
45
#include "src/objects/microtask-inl.h"
46
#include "src/objects/microtask-queue-inl.h"
47
#include "src/objects/module-inl.h"
48
#include "src/objects/promise-inl.h"
49
#include "src/objects/stack-frame-info-inl.h"
50
#include "src/ostreams.h"
51
#include "src/regexp/jsregexp.h"
52
#include "src/transitions-inl.h"
53
#include "src/wasm/wasm-code-manager.h"
54
#include "src/wasm/wasm-engine.h"
55
#include "src/wasm/wasm-objects-inl.h"
56 57 58 59 60 61

namespace v8 {
namespace internal {

#ifdef OBJECT_PRINT

62
void Object::Print() {
63
  StdoutStream os;
64
  this->Print(os);
65
  os << std::flush;
66 67
}

68
void Object::Print(std::ostream& os) {  // NOLINT
69
  if (IsSmi()) {
jgruber's avatar
jgruber committed
70 71
    os << "Smi: " << std::hex << "0x" << Smi::ToInt(this);
    os << std::dec << " (" << Smi::ToInt(this) << ")\n";
72
  } else {
73
    HeapObject::cast(this)->HeapObjectPrint(os);
74 75 76
  }
}

77
void HeapObject::PrintHeader(std::ostream& os, const char* id) {  // NOLINT
78 79 80 81 82 83 84
  os << reinterpret_cast<void*>(this) << ": [";
  if (id != nullptr) {
    os << id;
  } else {
    os << map()->instance_type();
  }
  os << "]";
85 86 87
  MemoryChunk* chunk = MemoryChunk::FromAddress(
      reinterpret_cast<Address>(const_cast<HeapObject*>(this)));
  if (chunk->owner()->identity() == OLD_SPACE) os << " in OldSpace";
88
  if (!IsMap()) os << "\n - map: " << Brief(map());
89 90
}

91
void HeapObject::HeapObjectPrint(std::ostream& os) {  // NOLINT
92 93 94
  InstanceType instance_type = map()->instance_type();

  if (instance_type < FIRST_NONSTRING_TYPE) {
95
    String::cast(this)->StringPrint(os);
96
    os << "\n";
97 98 99 100
    return;
  }

  switch (instance_type) {
101
    case SYMBOL_TYPE:
102
      Symbol::cast(this)->SymbolPrint(os);
103
      break;
104
    case MAP_TYPE:
105
      Map::cast(this)->MapPrint(os);
106 107
      break;
    case HEAP_NUMBER_TYPE:
108
      HeapNumber::cast(this)->HeapNumberPrint(os);
109
      os << "\n";
110
      break;
111
    case MUTABLE_HEAP_NUMBER_TYPE:
112
      os << "<mutable ";
113
      MutableHeapNumber::cast(this)->MutableHeapNumberPrint(os);
114
      os << ">\n";
115
      break;
116 117 118 119
    case BIGINT_TYPE:
      BigInt::cast(this)->BigIntPrint(os);
      os << "\n";
      break;
120
    case FIXED_DOUBLE_ARRAY_TYPE:
121
      FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(os);
122
      break;
123
    case FIXED_ARRAY_TYPE:
124
    case AWAIT_CONTEXT_TYPE:
125 126 127 128 129 130 131 132 133
    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 NATIVE_CONTEXT_TYPE:
    case SCRIPT_CONTEXT_TYPE:
    case WITH_CONTEXT_TYPE:
134
    case SCRIPT_CONTEXT_TABLE_TYPE:
135
      FixedArray::cast(this)->FixedArrayPrint(os);
136
      break;
137
    case HASH_TABLE_TYPE:
138 139 140 141 142 143
    case ORDERED_HASH_MAP_TYPE:
    case ORDERED_HASH_SET_TYPE:
    case NAME_DICTIONARY_TYPE:
    case GLOBAL_DICTIONARY_TYPE:
    case SIMPLE_NUMBER_DICTIONARY_TYPE:
    case STRING_TABLE_TYPE:
144 145
      ObjectHashTable::cast(this)->ObjectHashTablePrint(os);
      break;
146 147 148
    case NUMBER_DICTIONARY_TYPE:
      NumberDictionary::cast(this)->NumberDictionaryPrint(os);
      break;
149 150 151
    case EPHEMERON_HASH_TABLE_TYPE:
      EphemeronHashTable::cast(this)->EphemeronHashTablePrint(os);
      break;
152 153 154
    case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
      ObjectBoilerplateDescription::cast(this)
          ->ObjectBoilerplateDescriptionPrint(os);
155
      break;
156 157 158
    case PROPERTY_ARRAY_TYPE:
      PropertyArray::cast(this)->PropertyArrayPrint(os);
      break;
159
    case BYTE_ARRAY_TYPE:
160
      ByteArray::cast(this)->ByteArrayPrint(os);
161
      break;
162
    case BYTECODE_ARRAY_TYPE:
163
      BytecodeArray::cast(this)->BytecodeArrayPrint(os);
164
      break;
165
    case DESCRIPTOR_ARRAY_TYPE:
166
      DescriptorArray::cast(this)->DescriptorArrayPrint(os);
167
      break;
168
    case TRANSITION_ARRAY_TYPE:
169
      TransitionArray::cast(this)->TransitionArrayPrint(os);
170
      break;
171
    case FEEDBACK_CELL_TYPE:
172
      FeedbackCell::cast(this)->FeedbackCellPrint(os);
173
      break;
174 175 176
    case FEEDBACK_VECTOR_TYPE:
      FeedbackVector::cast(this)->FeedbackVectorPrint(os);
      break;
177
    case FREE_SPACE_TYPE:
178
      FreeSpace::cast(this)->FreeSpacePrint(os);
179
      break;
180

181 182 183
#define PRINT_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype)      \
  case Fixed##Type##Array::kInstanceType:                     \
    Fixed##Type##Array::cast(this)->FixedTypedArrayPrint(os); \
184
    break;
185

186
      TYPED_ARRAYS(PRINT_FIXED_TYPED_ARRAY)
187
#undef PRINT_FIXED_TYPED_ARRAY
188

189
    case FILLER_TYPE:
190
      os << "filler";
191 192
      break;
    case JS_OBJECT_TYPE:  // fall through
193
    case JS_API_OBJECT_TYPE:
194
    case JS_SPECIAL_API_OBJECT_TYPE:
195
    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
196
    case JS_ASYNC_FUNCTION_OBJECT_TYPE:
197
    case JS_ASYNC_GENERATOR_OBJECT_TYPE:
198 199
    case JS_ARGUMENTS_TYPE:
    case JS_ERROR_TYPE:
200
    // TODO(titzer): debug printing for more wasm objects
201
    case WASM_EXCEPTION_TYPE:
202
    case WASM_GLOBAL_TYPE:
203 204
    case WASM_MEMORY_TYPE:
    case WASM_TABLE_TYPE:
205
      JSObject::cast(this)->JSObjectPrint(os);
206
      break;
207 208 209
    case WASM_MODULE_TYPE:
      WasmModuleObject::cast(this)->WasmModuleObjectPrint(os);
      break;
210 211 212
    case WASM_INSTANCE_TYPE:
      WasmInstanceObject::cast(this)->WasmInstanceObjectPrint(os);
      break;
213
    case JS_GENERATOR_OBJECT_TYPE:
214
      JSGeneratorObject::cast(this)->JSGeneratorObjectPrint(os);
215
      break;
216
    case JS_PROMISE_TYPE:
217
      JSPromise::cast(this)->JSPromisePrint(os);
218
      break;
219
    case JS_ARRAY_TYPE:
220
      JSArray::cast(this)->JSArrayPrint(os);
221
      break;
222
    case JS_REGEXP_TYPE:
223
      JSRegExp::cast(this)->JSRegExpPrint(os);
224
      break;
225
    case JS_REGEXP_STRING_ITERATOR_TYPE:
226
      JSRegExpStringIterator::cast(this)->JSRegExpStringIteratorPrint(os);
227
      break;
228
    case ODDBALL_TYPE:
229
      Oddball::cast(this)->to_string()->Print(os);
230
      break;
231
    case JS_BOUND_FUNCTION_TYPE:
232
      JSBoundFunction::cast(this)->JSBoundFunctionPrint(os);
233
      break;
234
    case JS_FUNCTION_TYPE:
235
      JSFunction::cast(this)->JSFunctionPrint(os);
236 237
      break;
    case JS_GLOBAL_PROXY_TYPE:
238
      JSGlobalProxy::cast(this)->JSGlobalProxyPrint(os);
239 240
      break;
    case JS_GLOBAL_OBJECT_TYPE:
241
      JSGlobalObject::cast(this)->JSGlobalObjectPrint(os);
242 243
      break;
    case JS_VALUE_TYPE:
244
      JSValue::cast(this)->JSValuePrint(os);
245
      break;
246
    case JS_DATE_TYPE:
247
      JSDate::cast(this)->JSDatePrint(os);
248
      break;
249
    case CODE_TYPE:
250
      Code::cast(this)->CodePrint(os);
251
      break;
252 253 254
    case CODE_DATA_CONTAINER_TYPE:
      CodeDataContainer::cast(this)->CodeDataContainerPrint(os);
      break;
255
    case JS_PROXY_TYPE:
256
      JSProxy::cast(this)->JSProxyPrint(os);
257
      break;
258
    case JS_SET_TYPE:
259
      JSSet::cast(this)->JSSetPrint(os);
260 261
      break;
    case JS_MAP_TYPE:
262
      JSMap::cast(this)->JSMapPrint(os);
263
      break;
264 265
    case JS_SET_KEY_VALUE_ITERATOR_TYPE:
    case JS_SET_VALUE_ITERATOR_TYPE:
266
      JSSetIterator::cast(this)->JSSetIteratorPrint(os);
267
      break;
268 269 270
    case JS_MAP_KEY_ITERATOR_TYPE:
    case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
    case JS_MAP_VALUE_ITERATOR_TYPE:
271
      JSMapIterator::cast(this)->JSMapIteratorPrint(os);
272
      break;
273 274 275 276 277 278 279 280 281 282
    case JS_WEAK_CELL_TYPE:
      JSWeakCell::cast(this)->JSWeakCellPrint(os);
      break;
    case JS_WEAK_FACTORY_TYPE:
      JSWeakFactory::cast(this)->JSWeakFactoryPrint(os);
      break;
    case JS_WEAK_FACTORY_CLEANUP_ITERATOR_TYPE:
      JSWeakFactoryCleanupIterator::cast(this)
          ->JSWeakFactoryCleanupIteratorPrint(os);
      break;
283
    case JS_WEAK_MAP_TYPE:
284
      JSWeakMap::cast(this)->JSWeakMapPrint(os);
285
      break;
286
    case JS_WEAK_SET_TYPE:
287
      JSWeakSet::cast(this)->JSWeakSetPrint(os);
288
      break;
289
    case JS_MODULE_NAMESPACE_TYPE:
290
      JSModuleNamespace::cast(this)->JSModuleNamespacePrint(os);
291
      break;
292
    case FOREIGN_TYPE:
293
      Foreign::cast(this)->ForeignPrint(os);
294
      break;
295
    case CALL_HANDLER_INFO_TYPE:
296
      CallHandlerInfo::cast(this)->CallHandlerInfoPrint(os);
297
      break;
298 299 300
    case PRE_PARSED_SCOPE_DATA_TYPE:
      PreParsedScopeData::cast(this)->PreParsedScopeDataPrint(os);
      break;
301 302 303 304 305 306 307 308
    case UNCOMPILED_DATA_WITHOUT_PRE_PARSED_SCOPE_TYPE:
      UncompiledDataWithoutPreParsedScope::cast(this)
          ->UncompiledDataWithoutPreParsedScopePrint(os);
      break;
    case UNCOMPILED_DATA_WITH_PRE_PARSED_SCOPE_TYPE:
      UncompiledDataWithPreParsedScope::cast(this)
          ->UncompiledDataWithPreParsedScopePrint(os);
      break;
309
    case SHARED_FUNCTION_INFO_TYPE:
310
      SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(os);
311
      break;
312
    case JS_MESSAGE_OBJECT_TYPE:
313
      JSMessageObject::cast(this)->JSMessageObjectPrint(os);
314
      break;
315
    case CELL_TYPE:
316
      Cell::cast(this)->CellPrint(os);
317 318
      break;
    case PROPERTY_CELL_TYPE:
319
      PropertyCell::cast(this)->PropertyCellPrint(os);
320
      break;
321
    case JS_ARRAY_BUFFER_TYPE:
322
      JSArrayBuffer::cast(this)->JSArrayBufferPrint(os);
323
      break;
324
    case JS_ARRAY_ITERATOR_TYPE:
325
      JSArrayIterator::cast(this)->JSArrayIteratorPrint(os);
326
      break;
327
    case JS_TYPED_ARRAY_TYPE:
328
      JSTypedArray::cast(this)->JSTypedArrayPrint(os);
329
      break;
330
    case JS_DATA_VIEW_TYPE:
331
      JSDataView::cast(this)->JSDataViewPrint(os);
332
      break;
333
#ifdef V8_INTL_SUPPORT
334 335 336
    case JS_INTL_V8_BREAK_ITERATOR_TYPE:
      JSV8BreakIterator::cast(this)->JSV8BreakIteratorPrint(os);
      break;
337 338 339
    case JS_INTL_COLLATOR_TYPE:
      JSCollator::cast(this)->JSCollatorPrint(os);
      break;
340 341 342
    case JS_INTL_DATE_TIME_FORMAT_TYPE:
      JSDateTimeFormat::cast(this)->JSDateTimeFormatPrint(os);
      break;
343 344 345
    case JS_INTL_LIST_FORMAT_TYPE:
      JSListFormat::cast(this)->JSListFormatPrint(os);
      break;
346 347 348
    case JS_INTL_LOCALE_TYPE:
      JSLocale::cast(this)->JSLocalePrint(os);
      break;
349 350 351
    case JS_INTL_NUMBER_FORMAT_TYPE:
      JSNumberFormat::cast(this)->JSNumberFormatPrint(os);
      break;
352 353 354
    case JS_INTL_PLURAL_RULES_TYPE:
      JSPluralRules::cast(this)->JSPluralRulesPrint(os);
      break;
355
    case JS_INTL_RELATIVE_TIME_FORMAT_TYPE:
356
      JSRelativeTimeFormat::cast(this)->JSRelativeTimeFormatPrint(os);
357
      break;
358 359 360
    case JS_INTL_SEGMENTER_TYPE:
      JSSegmenter::cast(this)->JSSegmenterPrint(os);
      break;
361
#endif  // V8_INTL_SUPPORT
362 363
#define MAKE_STRUCT_CASE(TYPE, Name, name) \
  case TYPE:                               \
364
    Name::cast(this)->Name##Print(os);     \
365
    break;
366
      STRUCT_LIST(MAKE_STRUCT_CASE)
367 368
#undef MAKE_STRUCT_CASE

369 370 371
    case ALLOCATION_SITE_TYPE:
      AllocationSite::cast(this)->AllocationSitePrint(os);
      break;
372 373 374 375 376 377
    case LOAD_HANDLER_TYPE:
      LoadHandler::cast(this)->LoadHandlerPrint(os);
      break;
    case STORE_HANDLER_TYPE:
      StoreHandler::cast(this)->StoreHandlerPrint(os);
      break;
378 379 380
    case SCOPE_INFO_TYPE:
      ScopeInfo::cast(this)->ScopeInfoPrint(os);
      break;
381 382 383
    case FEEDBACK_METADATA_TYPE:
      FeedbackMetadata::cast(this)->FeedbackMetadataPrint(os);
      break;
384 385 386
    case WEAK_FIXED_ARRAY_TYPE:
      WeakFixedArray::cast(this)->WeakFixedArrayPrint(os);
      break;
387 388 389
    case WEAK_ARRAY_LIST_TYPE:
      WeakArrayList::cast(this)->WeakArrayListPrint(os);
      break;
390 391 392 393 394
    case INTERNALIZED_STRING_TYPE:
    case EXTERNAL_INTERNALIZED_STRING_TYPE:
    case ONE_BYTE_INTERNALIZED_STRING_TYPE:
    case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
    case EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
395 396 397
    case UNCACHED_EXTERNAL_INTERNALIZED_STRING_TYPE:
    case UNCACHED_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
    case UNCACHED_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE:
398 399 400 401 402 403 404 405 406 407 408
    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:
    case EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
409 410 411
    case UNCACHED_EXTERNAL_STRING_TYPE:
    case UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE:
    case UNCACHED_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE:
412 413 414 415 416
    case SMALL_ORDERED_HASH_MAP_TYPE:
    case SMALL_ORDERED_HASH_SET_TYPE:
    case JS_ASYNC_FROM_SYNC_ITERATOR_TYPE:
    case JS_STRING_ITERATOR_TYPE:
      // TODO(all): Handle these types too.
417
      os << "UNKNOWN TYPE " << map()->instance_type();
418 419 420 421 422
      UNREACHABLE();
      break;
  }
}

423
void ByteArray::ByteArrayPrint(std::ostream& os) {  // NOLINT
424 425
  os << "byte array, data starts at "
     << static_cast<void*>(GetDataStartAddress());
426 427
}

428
void BytecodeArray::BytecodeArrayPrint(std::ostream& os) {  // NOLINT
429
  HeapObject::PrintHeader(os, "BytecodeArray");
430
  Disassemble(os);
431 432 433
}


434
void FreeSpace::FreeSpacePrint(std::ostream& os) {  // NOLINT
435
  os << "free space, size " << Size();
436 437 438
}


439
template <class Traits>
440 441
void FixedTypedArray<Traits>::FixedTypedArrayPrint(
    std::ostream& os) {  // NOLINT
442
  os << "fixed " << Traits::Designator();
443 444
}

445
bool JSObject::PrintProperties(std::ostream& os) {  // NOLINT
446 447
  if (HasFastProperties()) {
    DescriptorArray* descs = map()->instance_descriptors();
448
    int nof_inobject_properties = map()->GetInObjectProperties();
449 450 451
    int i = 0;
    for (; i < map()->NumberOfOwnDescriptors(); i++) {
      os << "\n    ";
452 453
      descs->GetKey(i)->NamePrint(os);
      os << ": ";
454 455 456
      PropertyDetails details = descs->GetDetails(i);
      switch (details.location()) {
        case kField: {
457
          FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
458 459
          if (IsUnboxedDoubleField(field_index)) {
            os << "<unboxed double> " << RawFastDoublePropertyAt(field_index);
460
          } else {
461
            os << Brief(RawFastPropertyAt(field_index));
462
          }
463 464
          break;
        }
465
        case kDescriptor:
466
          os << Brief(descs->GetStrongValue(i));
467
          break;
468
      }
469 470
      os << " ";
      details.PrintAsFastTo(os, PropertyDetails::kForProperties);
471 472 473 474 475 476
      if (details.location() != kField) continue;
      int field_index = details.field_index();
      if (nof_inobject_properties <= field_index) {
        field_index -= nof_inobject_properties;
        os << " properties[" << field_index << "]";
      }
477
    }
478
    return i > 0;
479
  } else if (IsJSGlobalObject()) {
480
    JSGlobalObject::cast(this)->global_dictionary()->Print(os);
481
  } else {
482
    property_dictionary()->Print(os);
483
  }
484
  return true;
485 486
}

487 488 489
namespace {

template <class T>
490 491
bool IsTheHoleAt(T* array, int index) {
  return false;
492 493
}

494 495 496
template <>
bool IsTheHoleAt(FixedDoubleArray* array, int index) {
  return array->is_the_hole(index);
497 498
}

499 500 501 502 503 504
template <class T>
double GetScalarElement(T* array, int index) {
  if (IsTheHoleAt(array, index)) {
    return std::numeric_limits<double>::quiet_NaN();
  }
  return array->get_scalar(index);
505 506
}

507
template <class T>
508
void DoPrintElements(std::ostream& os, Object* object) {  // NOLINT
509
  const bool print_the_hole = std::is_same<T, FixedDoubleArray>::value;
510 511 512
  T* array = T::cast(object);
  if (array->length() == 0) return;
  int previous_index = 0;
513
  double previous_value = GetScalarElement(array, 0);
514 515 516
  double value = 0.0;
  int i;
  for (i = 1; i <= array->length(); i++) {
517
    if (i < array->length()) value = GetScalarElement(array, i);
518
    bool values_are_nan = std::isnan(previous_value) && std::isnan(value);
519
    if (i != array->length() && (previous_value == value || values_are_nan) &&
520
        IsTheHoleAt(array, i - 1) == IsTheHoleAt(array, i)) {
521 522 523 524 525 526 527 528 529
      continue;
    }
    os << "\n";
    std::stringstream ss;
    ss << previous_index;
    if (previous_index != i - 1) {
      ss << '-' << (i - 1);
    }
    os << std::setw(12) << ss.str() << ": ";
530
    if (print_the_hole && IsTheHoleAt(array, i - 1)) {
531 532 533 534 535 536
      os << "<the_hole>";
    } else {
      os << previous_value;
    }
    previous_index = i;
    previous_value = value;
537 538 539
  }
}

540 541
template <typename T>
void PrintFixedArrayElements(std::ostream& os, T* array) {
542
  // Print in array notation for non-sparse arrays.
543
  Object* previous_value = array->length() > 0 ? array->get(0) : nullptr;
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
  Object* value = nullptr;
  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);
    }
    os << std::setw(12) << ss.str() << ": " << Brief(previous_value);
    previous_index = i;
    previous_value = value;
  }
}

564 565
void PrintDictionaryElements(std::ostream& os, FixedArrayBase* elements) {
  // Print some internal fields
566
  NumberDictionary* dict = NumberDictionary::cast(elements);
567 568 569 570 571 572 573 574
  if (dict->requires_slow_elements()) {
    os << "\n   - requires_slow_elements";
  } else {
    os << "\n   - max_number_key: " << dict->max_number_key();
  }
  dict->Print(os);
}

575
void PrintSloppyArgumentElements(std::ostream& os, ElementsKind kind,
576 577
                                 SloppyArgumentsElements* elements) {
  FixedArray* arguments_store = elements->arguments();
578 579
  os << "\n    0: context: " << Brief(elements->context())
     << "\n    1: arguments_store: " << Brief(arguments_store)
580 581 582
     << "\n    parameter to context slot map:";
  for (uint32_t i = 0; i < elements->parameter_map_length(); i++) {
    uint32_t raw_index = i + SloppyArgumentsElements::kParameterMapStart;
583
    Object* mapped_entry = elements->get_mapped_entry(i);
584
    os << "\n    " << raw_index << ": param(" << i
585
       << "): " << Brief(mapped_entry);
586
    if (mapped_entry->IsTheHole()) {
Mathias Bynens's avatar
Mathias Bynens committed
587
      os << " in the arguments_store[" << i << "]";
588 589 590
    } else {
      os << " in the context";
    }
591 592 593
  }
  if (arguments_store->length() == 0) return;
  os << "\n }"
594
     << "\n - arguments_store: " << Brief(arguments_store) << " "
595 596 597 598 599
     << ElementsKindToString(arguments_store->map()->elements_kind()) << " {";
  if (kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
    PrintFixedArrayElements(os, arguments_store);
  } else {
    DCHECK_EQ(kind, SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
600
    PrintDictionaryElements(os, arguments_store);
601 602 603
  }
}

604
}  // namespace
605

606
void JSObject::PrintElements(std::ostream& os) {  // NOLINT
607 608
  // Don't call GetElementsKind, its validation code can cause the printer to
  // fail when debugging.
609
  os << " - elements: " << Brief(elements()) << " {";
610 611 612 613
  if (elements()->length() == 0) {
    os << " }\n";
    return;
  }
614
  switch (map()->elements_kind()) {
615 616 617 618
    case HOLEY_SMI_ELEMENTS:
    case PACKED_SMI_ELEMENTS:
    case HOLEY_ELEMENTS:
    case PACKED_ELEMENTS:
619
    case FAST_STRING_WRAPPER_ELEMENTS: {
620
      PrintFixedArrayElements(os, FixedArray::cast(elements()));
621 622
      break;
    }
623 624
    case HOLEY_DOUBLE_ELEMENTS:
    case PACKED_DOUBLE_ELEMENTS: {
625
      DoPrintElements<FixedDoubleArray>(os, elements());
626 627
      break;
    }
628

629 630 631 632
#define PRINT_ELEMENTS(Type, type, TYPE, elementType)    \
  case TYPE##_ELEMENTS: {                                \
    DoPrintElements<Fixed##Type##Array>(os, elements()); \
    break;                                               \
633
  }
634
      TYPED_ARRAYS(PRINT_ELEMENTS)
635 636
#undef PRINT_ELEMENTS

637
    case DICTIONARY_ELEMENTS:
638
    case SLOW_STRING_WRAPPER_ELEMENTS:
639
      PrintDictionaryElements(os, elements());
640
      break;
641
    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
642
    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
643
      PrintSloppyArgumentElements(os, map()->elements_kind(),
644
                                  SloppyArgumentsElements::cast(elements()));
645
      break;
646 647
    case NO_ELEMENTS:
      break;
648
  }
649
  os << "\n }\n";
650 651
}

652
static void JSObjectPrintHeader(std::ostream& os, JSObject* obj,
653
                                const char* id) {  // NOLINT
654
  Isolate* isolate = obj->GetIsolate();
655
  obj->PrintHeader(os, id);
656 657
  // Don't call GetElementsKind, its validation code can cause the printer to
  // fail when debugging.
658
  os << " [";
659 660 661 662
  if (obj->HasFastProperties()) {
    os << "FastProperties";
  } else {
    os << "DictionaryProperties";
663
  }
664
  PrototypeIterator iter(isolate, obj);
665 666
  os << "]\n - prototype: " << Brief(iter.GetCurrent());
  os << "\n - elements: " << Brief(obj->elements()) << " ["
667
     << ElementsKindToString(obj->map()->elements_kind());
668
  if (obj->elements()->IsCowArray()) os << " (COW)";
669
  os << "]";
670 671
  Object* hash = obj->GetHash();
  if (hash->IsSmi()) {
672
    os << "\n - hash: " << Brief(hash);
673
  }
674
  if (obj->GetEmbedderFieldCount() > 0) {
675
    os << "\n - embedder fields: " << obj->GetEmbedderFieldCount();
676
  }
677 678
}

679
static void JSObjectPrintBody(std::ostream& os,
680
                              JSObject* obj,  // NOLINT
681
                              bool print_elements = true) {
682
  os << "\n - properties: ";
683 684 685 686 687
  Object* properties_or_hash = obj->raw_properties_or_hash();
  if (!properties_or_hash->IsSmi()) {
    os << Brief(properties_or_hash);
  }
  os << " {";
688 689
  if (obj->PrintProperties(os)) os << "\n ";
  os << "}\n";
690
  if (print_elements && obj->elements()->length() > 0) {
691
    obj->PrintElements(os);
692
  }
693 694
  int embedder_fields = obj->GetEmbedderFieldCount();
  if (embedder_fields > 0) {
695
    os << " - embedder fields = {";
696 697
    for (int i = 0; i < embedder_fields; i++) {
      os << "\n    " << obj->GetEmbedderField(i);
698 699 700
    }
    os << "\n }\n";
  }
701 702
}

703 704
void JSObject::JSObjectPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, nullptr);
705
  JSObjectPrintBody(os, this);
706 707
}

708 709
void JSGeneratorObject::JSGeneratorObjectPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSGeneratorObject");
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
  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()) {
    DisallowHeapAllocation no_gc;
    SharedFunctionInfo* fun_info = function()->shared();
    if (fun_info->HasSourceCode()) {
      Script* script = Script::cast(fun_info->script());
      int lin = script->GetLineNumber(source_position()) + 1;
      int col = script->GetColumnNumber(source_position()) + 1;
      String* script_name = script->name()->IsString()
                                ? String::cast(script->name())
745
                                : GetReadOnlyRoots().empty_string();
746 747 748 749 750 751 752 753
      os << "\n - source position: " << source_position();
      os << " (";
      script_name->PrintUC16(os);
      os << ", lin " << lin;
      os << ", col " << col;
      os << ")";
    }
  }
754
  os << "\n - register file: " << Brief(parameters_and_registers());
755 756 757
  os << "\n";
}

758 759
void JSArray::JSArrayPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSArray");
760
  os << "\n - length: " << Brief(this->length());
761
  JSObjectPrintBody(os, this);
762 763
}

764 765
void JSPromise::JSPromisePrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSPromise");
766
  os << "\n - status: " << JSPromise::Status(status());
767
  if (status() == Promise::kPending) {
768
    os << "\n - reactions: " << Brief(reactions());
769
  } else {
770
    os << "\n - result: " << Brief(result());
771
  }
772
  os << "\n - has_handler: " << has_handler();
773
  os << "\n ";
774
}
775

776 777
void JSRegExp::JSRegExpPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSRegExp");
778 779
  os << "\n - data: " << Brief(data());
  os << "\n - source: " << Brief(source());
780
  JSObjectPrintBody(os, this);
781 782
}

783 784
void JSRegExpStringIterator::JSRegExpStringIteratorPrint(
    std::ostream& os) {  // NOLINT
785
  JSObjectPrintHeader(os, this, "JSRegExpStringIterator");
786 787 788 789 790
  os << "\n - regex: " << Brief(iterating_regexp());
  os << "\n - string: " << Brief(iterating_string());
  os << "\n - done: " << done();
  os << "\n - global: " << global();
  os << "\n - unicode: " << unicode();
791
  JSObjectPrintBody(os, this);
792
}
793

794
void Symbol::SymbolPrint(std::ostream& os) {  // NOLINT
795
  HeapObject::PrintHeader(os, "Symbol");
796
  os << "\n - hash: " << Hash();
797
  os << "\n - name: " << Brief(name());
798 799
  if (name()->IsUndefined()) {
    os << " (" << PrivateSymbolToName() << ")";
800
  }
801
  os << "\n - private: " << is_private();
802
  os << "\n";
803 804
}

805
void Map::MapPrint(std::ostream& os) {  // NOLINT
806
  HeapObject::PrintHeader(os, "Map");
807
  os << "\n - type: " << instance_type();
808 809 810 811 812 813
  os << "\n - instance size: ";
  if (instance_size() == kVariableSizeSentinel) {
    os << "variable";
  } else {
    os << instance_size();
  }
814
  if (IsJSObjectMap()) {
815
    os << "\n - inobject properties: " << GetInObjectProperties();
816
  }
817
  os << "\n - elements kind: " << ElementsKindToString(elements_kind());
818
  os << "\n - unused property fields: " << UnusedPropertyFields();
819 820 821 822 823 824
  os << "\n - enum length: ";
  if (EnumLength() == kInvalidEnumCacheSentinel) {
    os << "invalid";
  } else {
    os << EnumLength();
  }
825 826
  if (is_deprecated()) os << "\n - deprecated_map";
  if (is_stable()) os << "\n - stable_map";
827
  if (is_migration_target()) os << "\n - migration_target";
828
  if (is_dictionary_map()) os << "\n - dictionary_map";
829
  if (has_hidden_prototype()) os << "\n - has_hidden_prototype";
830
  if (has_named_interceptor()) os << "\n - named_interceptor";
831
  if (has_indexed_interceptor()) os << "\n - indexed_interceptor";
832
  if (may_have_interesting_symbols()) os << "\n - may_have_interesting_symbols";
833 834 835
  if (is_undetectable()) os << "\n - undetectable";
  if (is_callable()) os << "\n - callable";
  if (is_constructor()) os << "\n - constructor";
836 837 838 839
  if (has_prototype_slot()) {
    os << "\n - has_prototype_slot";
    if (has_non_instance_prototype()) os << " (non-instance prototype)";
  }
840 841
  if (is_access_check_needed()) os << "\n - access_check_needed";
  if (!is_extensible()) os << "\n - non-extensible";
842
  if (is_prototype_map()) {
843 844
    os << "\n - prototype_map";
    os << "\n - prototype info: " << Brief(prototype_info());
845
  } else {
846
    os << "\n - back pointer: " << Brief(GetBackPointer());
847
  }
848
  os << "\n - prototype_validity cell: " << Brief(prototype_validity_cell());
849 850 851
  os << "\n - instance descriptors " << (owns_descriptors() ? "(own) " : "")
     << "#" << NumberOfOwnDescriptors() << ": "
     << Brief(instance_descriptors());
852
  if (FLAG_unbox_double_fields) {
853 854
    os << "\n - layout descriptor: ";
    layout_descriptor()->ShortPrint(os);
855
  }
856

857
  Isolate* isolate;
858 859
  // Read-only maps can't have transitions, which is fortunate because we need
  // the isolate to iterate over the transitions.
860
  if (Isolate::FromWritableHeapObject(this, &isolate)) {
861
    DisallowHeapAllocation no_gc;
862
    TransitionsAccessor transitions(isolate, this, &no_gc);
863 864
    int nof_transitions = transitions.NumberOfTransitions();
    if (nof_transitions > 0) {
865 866 867 868 869
      os << "\n - transitions #" << nof_transitions << ": ";
      HeapObject* heap_object;
      Smi* smi;
      if (raw_transitions()->ToSmi(&smi)) {
        os << Brief(smi);
870
      } else if (raw_transitions()->GetHeapObject(&heap_object)) {
871 872
        os << Brief(heap_object);
      }
873 874
      transitions.PrintTransitions(os);
    }
875
  }
876
  os << "\n - prototype: " << Brief(prototype());
877
  os << "\n - constructor: " << Brief(GetConstructor());
878
  os << "\n - dependent code: " << Brief(dependent_code());
879
  os << "\n - construction counter: " << construction_counter();
880
  os << "\n";
881 882
}

883 884 885 886 887 888 889 890 891 892 893 894 895 896 897
void DescriptorArray::DescriptorArrayPrint(std::ostream& os) {
  HeapObject::PrintHeader(os, "DescriptorArray");
  os << "\n - capacity: " << length();
  EnumCache* enum_cache = GetEnumCache();
  os << "\n - enum_cache: ";
  if (enum_cache->keys()->length() == 0) {
    os << "empty";
  } else {
    os << enum_cache->keys()->length();
    os << "\n   - keys: " << Brief(enum_cache->keys());
    os << "\n   - indices: " << Brief(enum_cache->indices());
  }
  os << "\n - nof descriptors: " << number_of_descriptors();
  PrintDescriptors(os);
}
898

899 900
void AliasedArgumentsEntry::AliasedArgumentsEntryPrint(
    std::ostream& os) {  // NOLINT
901 902
  HeapObject::PrintHeader(os, "AliasedArgumentsEntry");
  os << "\n - aliased_context_slot: " << aliased_context_slot();
903 904
}

905 906 907 908 909 910 911 912
namespace {
void PrintFixedArrayWithHeader(std::ostream& os, FixedArray* array,
                               const char* type) {
  array->PrintHeader(os, type);
  os << "\n - length: " << array->length();
  PrintFixedArrayElements(os, array);
  os << "\n";
}
913

914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
template <typename T>
void PrintHashTableWithHeader(std::ostream& os, T* table, const char* type) {
  table->PrintHeader(os, type);
  os << "\n - length: " << table->length();
  os << "\n - elements: " << table->NumberOfElements();
  os << "\n - deleted: " << table->NumberOfDeletedElements();
  os << "\n - capacity: " << table->Capacity();

  os << "\n - elements: {";
  for (int i = 0; i < table->Capacity(); i++) {
    os << '\n'
       << std::setw(12) << i << ": " << Brief(table->KeyAt(i)) << " -> "
       << Brief(table->ValueAt(i));
  }
  os << "\n }\n";
}

931 932
template <typename T>
void PrintWeakArrayElements(std::ostream& os, T* array) {
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948
  // Print in array notation for non-sparse arrays.
  MaybeObject* previous_value = array->length() > 0 ? array->Get(0) : nullptr;
  MaybeObject* value = nullptr;
  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);
    }
949
    os << std::setw(12) << ss.str() << ": " << Brief(previous_value);
950 951 952 953 954
    previous_index = i;
    previous_value = value;
  }
}

955
}  // namespace
956

957
void FixedArray::FixedArrayPrint(std::ostream& os) {  // NOLINT
958 959
  PrintFixedArrayWithHeader(os, this, "FixedArray");
}
960

961 962 963
void ObjectHashTable::ObjectHashTablePrint(std::ostream& os) {
  PrintHashTableWithHeader(os, this, "ObjectHashTable");
}
964

965 966 967 968
void NumberDictionary::NumberDictionaryPrint(std::ostream& os) {
  PrintHashTableWithHeader(os, this, "NumberDictionary");
}

969 970
void EphemeronHashTable::EphemeronHashTablePrint(std::ostream& os) {
  PrintHashTableWithHeader(os, this, "EphemeronHashTable");
971 972
}

973 974 975
void ObjectBoilerplateDescription::ObjectBoilerplateDescriptionPrint(
    std::ostream& os) {
  PrintFixedArrayWithHeader(os, this, "ObjectBoilerplateDescription");
976 977
}

978 979 980
void PropertyArray::PropertyArrayPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "PropertyArray");
  os << "\n - length: " << length();
981 982
  os << "\n - hash: " << Hash();
  PrintFixedArrayElements(os, this);
983 984
  os << "\n";
}
985

986
void FixedDoubleArray::FixedDoubleArrayPrint(std::ostream& os) {  // NOLINT
987
  HeapObject::PrintHeader(os, "FixedDoubleArray");
988
  os << "\n - length: " << length();
989
  DoPrintElements<FixedDoubleArray>(os, this);
990
  os << "\n";
991 992
}

993
void WeakFixedArray::WeakFixedArrayPrint(std::ostream& os) {
994 995 996 997
  PrintHeader(os, "WeakFixedArray");
  os << "\n - length: " << length() << "\n";
  PrintWeakArrayElements(os, this);
  os << "\n";
998
}
999

1000
void WeakArrayList::WeakArrayListPrint(std::ostream& os) {
1001 1002 1003 1004 1005
  PrintHeader(os, "WeakArrayList");
  os << "\n - capacity: " << capacity();
  os << "\n - length: " << length() << "\n";
  PrintWeakArrayElements(os, this);
  os << "\n";
1006 1007
}

1008
void TransitionArray::TransitionArrayPrint(std::ostream& os) {  // NOLINT
1009
  HeapObject::PrintHeader(os, "TransitionArray");
1010
  PrintInternal(os);
1011 1012
}

1013
void FeedbackCell::FeedbackCellPrint(std::ostream& os) {  // NOLINT
1014
  HeapObject::PrintHeader(os, "FeedbackCell");
1015 1016
  ReadOnlyRoots roots = GetReadOnlyRoots();
  if (map() == roots.no_closures_cell_map()) {
1017
    os << "\n - no closures";
1018
  } else if (map() == roots.one_closure_cell_map()) {
1019
    os << "\n - one closure";
1020
  } else if (map() == roots.many_closures_cell_map()) {
1021 1022 1023 1024 1025 1026 1027 1028
    os << "\n - many closures";
  } else {
    os << "\n - Invalid FeedbackCell map";
  }
  os << " - value: " << Brief(value());
  os << "\n";
}

1029
void FeedbackVectorSpec::Print() {
1030
  StdoutStream os;
1031

1032
  FeedbackVectorSpecPrint(os);
1033

1034 1035 1036
  os << std::flush;
}

1037 1038
void FeedbackVectorSpec::FeedbackVectorSpecPrint(std::ostream& os) {  // NOLINT
  int slot_count = slots();
1039 1040 1041 1042 1043 1044
  os << " - slot_count: " << slot_count;
  if (slot_count == 0) {
    os << " (empty)\n";
    return;
  }

1045
  for (int slot = 0; slot < slot_count;) {
1046
    FeedbackSlotKind kind = GetKind(FeedbackSlot(slot));
1047
    int entry_size = FeedbackMetadata::GetSlotSize(kind);
1048 1049 1050 1051 1052 1053
    DCHECK_LT(0, entry_size);
    os << "\n Slot #" << slot << " " << kind;
    slot += entry_size;
  }
  os << "\n";
}
1054

1055
void FeedbackMetadata::FeedbackMetadataPrint(std::ostream& os) {
1056
  HeapObject::PrintHeader(os, "FeedbackMetadata");
1057
  os << "\n - slot_count: " << slot_count();
1058

1059
  FeedbackMetadataIterator iter(this);
1060
  while (iter.HasNext()) {
1061 1062
    FeedbackSlot slot = iter.Next();
    FeedbackSlotKind kind = iter.kind();
1063 1064 1065 1066 1067
    os << "\n Slot " << slot << " " << kind;
  }
  os << "\n";
}

1068 1069
void FeedbackVector::FeedbackVectorPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "FeedbackVector");
1070
  os << "\n - length: " << length();
1071 1072 1073 1074 1075
  if (length() == 0) {
    os << " (empty)\n";
    return;
  }

1076 1077
  os << "\n - shared function info: " << Brief(shared_function_info());
  os << "\n - optimized code/marker: ";
1078 1079 1080 1081 1082
  if (has_optimized_code()) {
    os << Brief(optimized_code());
  } else {
    os << optimization_marker();
  }
1083 1084
  os << "\n - invocation count: " << invocation_count();
  os << "\n - profiler ticks: " << profiler_ticks();
1085

1086
  FeedbackMetadataIterator iter(metadata());
1087
  while (iter.HasNext()) {
1088 1089
    FeedbackSlot slot = iter.Next();
    FeedbackSlotKind kind = iter.kind();
1090

1091
    os << "\n - slot " << slot << " " << kind << " ";
1092
    FeedbackSlotPrint(os, slot);
1093

1094
    int entry_size = iter.entry_size();
1095
    if (entry_size > 0) os << " {";
1096 1097
    for (int i = 0; i < entry_size; i++) {
      int index = GetIndex(slot) + i;
1098
      os << "\n     [" << index << "]: " << Brief(get(index));
1099
    }
1100
    if (entry_size > 0) os << "\n  }";
1101 1102 1103 1104
  }
  os << "\n";
}

1105 1106
void FeedbackVector::FeedbackSlotPrint(std::ostream& os,
                                       FeedbackSlot slot) {  // NOLINT
1107 1108
  FeedbackNexus nexus(this, slot);
  nexus.Print(os);
1109 1110
}

1111 1112 1113 1114 1115
void FeedbackNexus::Print(std::ostream& os) {  // NOLINT
  switch (kind()) {
    case FeedbackSlotKind::kCall:
    case FeedbackSlotKind::kLoadProperty:
    case FeedbackSlotKind::kLoadKeyed:
1116
    case FeedbackSlotKind::kLoadGlobalInsideTypeof:
1117
    case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
1118 1119 1120 1121
    case FeedbackSlotKind::kStoreNamedSloppy:
    case FeedbackSlotKind::kStoreNamedStrict:
    case FeedbackSlotKind::kStoreOwnNamed:
    case FeedbackSlotKind::kStoreGlobalSloppy:
1122
    case FeedbackSlotKind::kStoreGlobalStrict:
1123
    case FeedbackSlotKind::kStoreKeyedSloppy:
1124 1125
    case FeedbackSlotKind::kInstanceOf:
    case FeedbackSlotKind::kStoreDataPropertyInLiteral:
1126
    case FeedbackSlotKind::kStoreKeyedStrict:
1127 1128
    case FeedbackSlotKind::kStoreInArrayLiteral:
    case FeedbackSlotKind::kCloneObject: {
1129
      os << InlineCacheState2String(StateFromFeedback());
1130 1131 1132
      break;
    }
    case FeedbackSlotKind::kBinaryOp: {
1133
      os << "BinaryOp:" << GetBinaryOperationFeedback();
1134 1135 1136
      break;
    }
    case FeedbackSlotKind::kCompareOp: {
1137
      os << "CompareOp:" << GetCompareOperationFeedback();
1138 1139 1140
      break;
    }
    case FeedbackSlotKind::kForIn: {
1141
      os << "ForIn:" << GetForInFeedback();
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
      break;
    }
    case FeedbackSlotKind::kCreateClosure:
    case FeedbackSlotKind::kLiteral:
    case FeedbackSlotKind::kTypeProfile:
      break;
    case FeedbackSlotKind::kInvalid:
    case FeedbackSlotKind::kKindsNumber:
      UNREACHABLE();
      break;
  }
}
1154

1155 1156
void JSValue::JSValuePrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSValue");
1157
  os << "\n - value: " << Brief(value());
1158
  JSObjectPrintBody(os, this);
1159 1160
}

1161 1162
void JSMessageObject::JSMessageObjectPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSMessageObject");
1163
  os << "\n - type: " << static_cast<int>(type());
1164
  os << "\n - arguments: " << Brief(argument());
1165 1166 1167 1168
  os << "\n - start_position: " << start_position();
  os << "\n - end_position: " << end_position();
  os << "\n - script: " << Brief(script());
  os << "\n - stack_frames: " << Brief(stack_frames());
1169
  JSObjectPrintBody(os, this);
1170 1171 1172
}


1173
void String::StringPrint(std::ostream& os) {  // NOLINT
1174 1175 1176
  if (!HasOnlyOneByteChars()) {
    os << "u";
  }
1177
  if (StringShape(this).IsInternalized()) {
1178
    os << "#";
1179
  } else if (StringShape(this).IsCons()) {
1180
    os << "c\"";
1181 1182
  } else if (StringShape(this).IsThin()) {
    os << ">\"";
1183
  } else {
1184
    os << "\"";
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194
  }

  const char truncated_epilogue[] = "...<truncated>";
  int len = length();
  if (!FLAG_use_verbose_printer) {
    if (len > 100) {
      len = 100 - sizeof(truncated_epilogue);
    }
  }
  for (int i = 0; i < len; i++) {
1195
    os << AsUC16(Get(i));
1196 1197
  }
  if (len != length()) {
1198
    os << truncated_epilogue;
1199 1200
  }

1201
  if (!StringShape(this).IsInternalized()) os << "\"";
1202 1203 1204
}


1205
void Name::NamePrint(std::ostream& os) {  // NOLINT
1206
  if (IsString()) {
1207
    String::cast(this)->StringPrint(os);
1208
  } else {
1209
    os << Brief(this);
1210
  }
1211 1212 1213
}


1214 1215 1216 1217
static const char* const weekdays[] = {
  "???", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

1218 1219
void JSDate::JSDatePrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSDate");
1220
  os << "\n - value: " << Brief(value());
1221
  if (!year()->IsSmi()) {
1222
    os << "\n - time = NaN\n";
1223
  } else {
1224
    // TODO(svenpanne) Add some basic formatting to our streams.
1225
    ScopedVector<char> buf(100);
jgruber's avatar
jgruber committed
1226 1227 1228 1229 1230 1231 1232 1233
    SNPrintF(buf, "\n - time = %s %04d/%02d/%02d %02d:%02d:%02d\n",
             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);
1234
    os << buf.start();
1235
  }
1236
  JSObjectPrintBody(os, this);
1237 1238 1239
}


1240
void JSProxy::JSProxyPrint(std::ostream& os) {  // NOLINT
1241
  HeapObject::PrintHeader(os, "JSProxy");
1242
  os << "\n - target: ";
1243
  target()->ShortPrint(os);
1244
  os << "\n - handler: ";
1245
  handler()->ShortPrint(os);
1246
  os << "\n";
1247 1248
}

1249 1250
void JSSet::JSSetPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSSet");
1251
  os << " - table: " << Brief(table());
1252
  JSObjectPrintBody(os, this);
1253 1254
}

1255 1256
void JSMap::JSMapPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSMap");
1257
  os << " - table: " << Brief(table());
1258
  JSObjectPrintBody(os, this);
1259 1260
}

1261
void JSCollectionIterator::JSCollectionIteratorPrint(
1262
    std::ostream& os) {  // NOLINT
1263 1264
  os << "\n - table: " << Brief(table());
  os << "\n - index: " << Brief(index());
1265
  os << "\n";
1266 1267
}

1268 1269
void JSSetIterator::JSSetIteratorPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSSetIterator");
1270
  JSCollectionIteratorPrint(os);
1271 1272
}

1273 1274
void JSMapIterator::JSMapIteratorPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSMapIterator");
1275
  JSCollectionIteratorPrint(os);
1276 1277
}

1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
void JSWeakCell::JSWeakCellPrint(std::ostream& os) {
  JSObjectPrintHeader(os, this, "JSWeakCell");
  os << "\n - factory: " << Brief(factory());
  os << "\n - target: " << Brief(target());
  os << "\n - prev: " << Brief(prev());
  os << "\n - next: " << Brief(next());
  os << "\n";
}

void JSWeakFactory::JSWeakFactoryPrint(std::ostream& os) {
  JSObjectPrintHeader(os, this, "JSWeakFactory");
  os << "\n - cleanup: " << Brief(cleanup());
  os << "\n - active_cells: " << Brief(active_cells());
  os << "\n - cleared_cells: " << Brief(cleared_cells());
  os << "\n";
}

void JSWeakFactoryCleanupIterator::JSWeakFactoryCleanupIteratorPrint(
    std::ostream& os) {
  JSObjectPrintHeader(os, this, "JSWeakFactoryCleanupIterator");
  os << "\n - factory: " << Brief(factory());
  os << "\n";
}

1302 1303
void JSWeakMap::JSWeakMapPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSWeakMap");
1304
  os << "\n - table: " << Brief(table());
1305
  JSObjectPrintBody(os, this);
1306 1307
}

1308 1309
void JSWeakSet::JSWeakSetPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSWeakSet");
1310
  os << "\n - table: " << Brief(table());
1311
  JSObjectPrintBody(os, this);
1312 1313
}

1314 1315
void JSArrayBuffer::JSArrayBufferPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSArrayBuffer");
1316
  os << "\n - backing_store: " << backing_store();
1317
  os << "\n - byte_length: " << byte_length();
1318 1319
  if (is_external()) os << "\n - external";
  if (is_neuterable()) os << "\n - neuterable";
1320
  if (was_neutered()) os << "\n - neutered";
1321
  if (is_shared()) os << "\n - shared";
1322
  if (is_wasm_memory()) os << "\n - is_wasm_memory";
1323
  if (is_growable()) os << "\n - growable";
1324
  JSObjectPrintBody(os, this, !was_neutered());
1325 1326
}

1327 1328
void JSTypedArray::JSTypedArrayPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSTypedArray");
1329
  os << "\n - buffer: " << Brief(buffer());
1330 1331
  os << "\n - byte_offset: " << byte_offset();
  os << "\n - byte_length: " << byte_length();
1332
  os << "\n - length: " << Brief(length());
1333
  if (WasNeutered()) os << "\n - neutered";
1334
  JSObjectPrintBody(os, this, !WasNeutered());
1335 1336
}

1337 1338
void JSArrayIterator::JSArrayIteratorPrint(std::ostream& os) {  // NOLING
  JSObjectPrintHeader(os, this, "JSArrayIterator");
1339 1340 1341
  os << "\n - iterated_object: " << Brief(iterated_object());
  os << "\n - next_index: " << Brief(next_index());
  os << "\n - kind: " << kind();
1342
  JSObjectPrintBody(os, this);
1343 1344
}

1345 1346
void JSDataView::JSDataViewPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSDataView");
1347
  os << "\n - buffer =" << Brief(buffer());
1348 1349
  os << "\n - byte_offset: " << byte_offset();
  os << "\n - byte_length: " << byte_length();
1350
  if (WasNeutered()) os << "\n - neutered";
1351
  JSObjectPrintBody(os, this, !WasNeutered());
1352 1353
}

1354 1355
void JSBoundFunction::JSBoundFunctionPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSBoundFunction");
1356 1357 1358
  os << "\n - bound_target_function: " << Brief(bound_target_function());
  os << "\n - bound_this: " << Brief(bound_this());
  os << "\n - bound_arguments: " << Brief(bound_arguments());
1359
  JSObjectPrintBody(os, this);
1360 1361
}

1362 1363 1364
void JSFunction::JSFunctionPrint(std::ostream& os) {  // NOLINT
  Isolate* isolate = GetIsolate();
  JSObjectPrintHeader(os, this, "Function");
1365
  os << "\n - function prototype: ";
1366 1367 1368 1369 1370 1371 1372
  if (has_prototype_slot()) {
    if (has_prototype()) {
      os << Brief(prototype());
      if (map()->has_non_instance_prototype()) {
        os << " (non-instance prototype)";
      }
    }
1373
    os << "\n - initial_map: ";
1374 1375 1376 1377
    if (has_initial_map()) os << Brief(initial_map());
  } else {
    os << "<no-prototype-slot>";
  }
1378
  os << "\n - shared_info: " << Brief(shared());
1379
  os << "\n - name: " << Brief(shared()->Name());
1380 1381 1382 1383 1384

  // Print Builtin name for builtin functions
  int builtin_index = code()->builtin_index();
  if (builtin_index != -1 && !IsInterpreted()) {
    if (builtin_index == Builtins::kDeserializeLazy) {
1385 1386
      if (shared()->HasBuiltinId()) {
        builtin_index = shared()->builtin_id();
1387
        os << "\n - builtin: " << isolate->builtins()->name(builtin_index)
1388 1389 1390
           << "(lazy)";
      }
    } else {
1391
      os << "\n - builtin: " << isolate->builtins()->name(builtin_index);
1392 1393 1394
    }
  }

1395
  os << "\n - formal_parameter_count: "
1396
     << shared()->internal_formal_parameter_count();
1397 1398 1399
  os << "\n - kind: " << shared()->kind();
  os << "\n - context: " << Brief(context());
  os << "\n - code: " << Brief(code());
1400 1401 1402
  if (IsInterpreted()) {
    os << "\n - interpreted";
    if (shared()->HasBytecodeArray()) {
1403
      os << "\n - bytecode: " << shared()->GetBytecodeArray();
1404 1405
    }
  }
1406 1407 1408 1409 1410 1411
  if (WasmExportedFunction::IsWasmExportedFunction(this)) {
    WasmExportedFunction* function = WasmExportedFunction::cast(this);
    os << "\n - WASM instance "
       << reinterpret_cast<void*>(function->instance());
    os << "\n - WASM function index " << function->function_index();
  }
1412
  shared()->PrintSourceCode(os);
1413
  JSObjectPrintBody(os, this);
1414
  os << "\n - feedback vector: ";
1415 1416 1417
  if (!shared()->HasFeedbackMetadata()) {
    os << "feedback metadata is not available in SFI\n";
  } else if (has_feedback_vector()) {
1418 1419 1420 1421
    feedback_vector()->FeedbackVectorPrint(os);
  } else {
    os << "not available\n";
  }
1422 1423
}

1424 1425
void SharedFunctionInfo::PrintSourceCode(std::ostream& os) {
  if (HasSourceCode()) {
1426
    os << "\n - source code: ";
1427
    String* source = String::cast(Script::cast(script())->source());
1428 1429
    int start = StartPosition();
    int length = EndPosition() - start;
1430
    std::unique_ptr<char[]> source_string = source->ToCString(
1431
        DISALLOW_NULLS, FAST_STRING_TRAVERSAL, start, length, nullptr);
1432 1433 1434 1435
    os << source_string.get();
  }
}

1436
void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) {  // NOLINT
1437
  HeapObject::PrintHeader(os, "SharedFunctionInfo");
1438
  os << "\n - name: ";
1439 1440
  if (HasSharedName()) {
    os << Brief(Name());
1441 1442 1443
  } else {
    os << "<no-shared-name>";
  }
1444 1445 1446
  if (HasInferredName()) {
    os << "\n - inferred name: " << Brief(inferred_name());
  }
1447
  os << "\n - kind: " << kind();
1448 1449 1450
  if (needs_home_object()) {
    os << "\n - needs_home_object";
  }
1451 1452 1453 1454
  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();
1455 1456
  os << "\n - data: " << Brief(function_data());
  os << "\n - code (from data): " << Brief(GetCode());
1457
  PrintSourceCode(os);
1458
  // Script files are often large, hard to read.
1459 1460
  // os << "\n - script =";
  // script()->Print(os);
1461 1462 1463 1464 1465 1466 1467
  if (is_named_expression()) {
    os << "\n - named expression";
  } else if (is_anonymous_expression()) {
    os << "\n - anonymous expression";
  } else if (is_declaration()) {
    os << "\n - declaration";
  }
1468
  os << "\n - function token position: " << function_token_position();
1469 1470
  os << "\n - start position: " << StartPosition();
  os << "\n - end position: " << EndPosition();
1471
  if (HasDebugInfo()) {
1472
    os << "\n - debug info: " << Brief(GetDebugInfo());
1473 1474 1475
  } else {
    os << "\n - no debug info";
  }
1476
  os << "\n - scope info: " << Brief(scope_info());
1477 1478 1479
  if (HasOuterScopeInfo()) {
    os << "\n - outer scope info: " << Brief(GetOuterScopeInfo());
  }
1480 1481
  os << "\n - length: " << length();
  os << "\n - feedback_metadata: ";
1482 1483 1484 1485 1486
  if (HasFeedbackMetadata()) {
    feedback_metadata()->FeedbackMetadataPrint(os);
  } else {
    os << "<none>";
  }
1487
  os << "\n";
1488 1489
}

1490 1491 1492
void JSGlobalProxy::JSGlobalProxyPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSGlobalProxy");
  if (!GetIsolate()->bootstrapper()->IsActive()) {
1493
    os << "\n - native context: " << Brief(native_context());
1494
  }
1495
  JSObjectPrintBody(os, this);
1496 1497
}

1498 1499 1500
void JSGlobalObject::JSGlobalObjectPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSGlobalObject");
  if (!GetIsolate()->bootstrapper()->IsActive()) {
1501
    os << "\n - native context: " << Brief(native_context());
1502
  }
1503
  os << "\n - global proxy: " << Brief(global_proxy());
1504
  JSObjectPrintBody(os, this);
1505 1506
}

1507
void Cell::CellPrint(std::ostream& os) {  // NOLINT
1508
  HeapObject::PrintHeader(os, "Cell");
1509
  os << "\n - value: " << Brief(value());
1510
  os << "\n";
1511 1512
}

1513
void PropertyCell::PropertyCellPrint(std::ostream& os) {  // NOLINT
1514
  HeapObject::PrintHeader(os, "PropertyCell");
1515 1516
  os << "\n - name: ";
  name()->NamePrint(os);
1517
  os << "\n - value: " << Brief(value());
1518 1519
  os << "\n - details: ";
  property_details().PrintAsSlowTo(os);
1520 1521
  PropertyCellType cell_type = property_details().cell_type();
  os << "\n - cell_type: ";
1522
  if (value()->IsTheHole()) {
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559
    switch (cell_type) {
      case PropertyCellType::kUninitialized:
        os << "Uninitialized";
        break;
      case PropertyCellType::kInvalidated:
        os << "Invalidated";
        break;
      default:
        os << "??? " << static_cast<int>(cell_type);
        break;
    }
  } else {
    switch (cell_type) {
      case PropertyCellType::kUndefined:
        os << "Undefined";
        break;
      case PropertyCellType::kConstant:
        os << "Constant";
        break;
      case PropertyCellType::kConstantType:
        os << "ConstantType"
           << " (";
        switch (GetConstantType()) {
          case PropertyCellConstantType::kSmi:
            os << "Smi";
            break;
          case PropertyCellConstantType::kStableMap:
            os << "StableMap";
            break;
        }
        os << ")";
        break;
      case PropertyCellType::kMutable:
        os << "Mutable";
        break;
    }
  }
1560
  os << "\n";
1561 1562
}

1563
void Code::CodePrint(std::ostream& os) {  // NOLINT
1564
  HeapObject::PrintHeader(os, "Code");
1565
  os << "\n";
1566 1567
#ifdef ENABLE_DISASSEMBLER
  if (FLAG_use_verbose_printer) {
1568
    Disassemble(nullptr, os);
1569 1570 1571 1572
  }
#endif
}

1573 1574 1575 1576 1577
void CodeDataContainer::CodeDataContainerPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "CodeDataContainer");
  os << "\n - kind_specific_flags: " << kind_specific_flags();
  os << "\n";
}
1578

1579
void Foreign::ForeignPrint(std::ostream& os) {  // NOLINT
1580
  os << "foreign address : " << reinterpret_cast<void*>(foreign_address());
1581
  os << "\n";
1582 1583 1584
}


1585 1586
void AccessorInfo::AccessorInfoPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "AccessorInfo");
1587
  os << "\n - name: " << Brief(name());
1588
  os << "\n - flags: " << flags();
1589 1590
  os << "\n - getter: " << Brief(getter());
  os << "\n - setter: " << Brief(setter());
1591
  os << "\n - js_getter: " << Brief(js_getter());
1592 1593
  os << "\n - data: " << Brief(data());
  os << "\n";
1594 1595
}

1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606
void CallbackTask::CallbackTaskPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "CallbackTask");
  os << "\n - callback: " << Brief(callback());
  os << "\n - data: " << Brief(data());
  os << "\n";
}

void CallableTask::CallableTaskPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "CallableTask");
  os << "\n - context: " << Brief(context());
  os << "\n - callable: " << Brief(callable());
1607 1608 1609
  os << "\n";
}

1610
void PromiseFulfillReactionJobTask::PromiseFulfillReactionJobTaskPrint(
1611
    std::ostream& os) {  // NOLINT
1612 1613 1614 1615
  HeapObject::PrintHeader(os, "PromiseFulfillReactionJobTask");
  os << "\n - argument: " << Brief(argument());
  os << "\n - context: " << Brief(context());
  os << "\n - handler: " << Brief(handler());
1616
  os << "\n - promise_or_capability: " << Brief(promise_or_capability());
1617 1618 1619 1620 1621 1622 1623 1624 1625
  os << "\n";
}

void PromiseRejectReactionJobTask::PromiseRejectReactionJobTaskPrint(
    std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "PromiseRejectReactionJobTask");
  os << "\n - argument: " << Brief(argument());
  os << "\n - context: " << Brief(context());
  os << "\n - handler: " << Brief(handler());
1626
  os << "\n - promise_or_capability: " << Brief(promise_or_capability());
1627 1628 1629 1630 1631 1632 1633 1634
  os << "\n";
}

void PromiseResolveThenableJobTask::PromiseResolveThenableJobTaskPrint(
    std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "PromiseResolveThenableJobTask");
  os << "\n - context: " << Brief(context());
  os << "\n - promise_to_resolve: " << Brief(promise_to_resolve());
1635
  os << "\n - then: " << Brief(then());
1636 1637 1638 1639 1640 1641 1642
  os << "\n - thenable: " << Brief(thenable());
  os << "\n";
}

void PromiseCapability::PromiseCapabilityPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "PromiseCapability");
  os << "\n - promise: " << Brief(promise());
1643 1644 1645 1646 1647
  os << "\n - resolve: " << Brief(resolve());
  os << "\n - reject: " << Brief(reject());
  os << "\n";
}

1648 1649 1650 1651 1652
void PromiseReaction::PromiseReactionPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "PromiseReaction");
  os << "\n - next: " << Brief(next());
  os << "\n - reject_handler: " << Brief(reject_handler());
  os << "\n - fulfill_handler: " << Brief(fulfill_handler());
1653
  os << "\n - promise_or_capability: " << Brief(promise_or_capability());
1654 1655 1656
  os << "\n";
}

1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677
void AsyncGeneratorRequest::AsyncGeneratorRequestPrint(
    std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "AsyncGeneratorRequest");
  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";
}

1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689
void ModuleInfoEntry::ModuleInfoEntryPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "ModuleInfoEntry");
  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";
}

1690 1691
void Module::ModulePrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "Module");
1692
  os << "\n - origin: " << Brief(script()->GetNameOrSourceURL());
1693
  os << "\n - code: " << Brief(code());
1694
  os << "\n - exports: " << Brief(exports());
1695
  os << "\n - requested_modules: " << Brief(requested_modules());
1696
  os << "\n - script: " << Brief(script());
1697
  os << "\n - import_meta: " << Brief(import_meta());
1698 1699
  os << "\n - status: " << status();
  os << "\n - exception: " << Brief(exception());
1700 1701
  os << "\n";
}
1702

1703 1704
void JSModuleNamespace::JSModuleNamespacePrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSModuleNamespace");
1705
  os << "\n - module: " << Brief(module());
1706
  JSObjectPrintBody(os, this);
1707 1708
}

1709 1710
void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "PrototypeInfo");
1711
  os << "\n - module namespace: " << Brief(module_namespace());
1712
  os << "\n - prototype users: " << Brief(prototype_users());
1713
  os << "\n - registry slot: " << registry_slot();
1714
  os << "\n - object create map: " << Brief(object_create_map());
1715
  os << "\n - should_be_fast_map: " << should_be_fast_map();
1716 1717 1718
  os << "\n";
}

1719 1720 1721 1722 1723 1724 1725
void Tuple2::Tuple2Print(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "Tuple2");
  os << "\n - value1: " << Brief(value1());
  os << "\n - value2: " << Brief(value2());
  os << "\n";
}

1726 1727 1728 1729 1730 1731 1732 1733
void Tuple3::Tuple3Print(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "Tuple3");
  os << "\n - value1: " << Brief(value1());
  os << "\n - value2: " << Brief(value2());
  os << "\n - value3: " << Brief(value3());
  os << "\n";
}

1734 1735 1736 1737 1738 1739 1740 1741
void ArrayBoilerplateDescription::ArrayBoilerplateDescriptionPrint(
    std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "ArrayBoilerplateDescription");
  os << "\n - elements kind: " << elements_kind();
  os << "\n - constant elements: " << Brief(constant_elements());
  os << "\n";
}

1742 1743 1744 1745 1746 1747
void WasmDebugInfo::WasmDebugInfoPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "WasmDebugInfo");
  os << "\n - wasm_instance: " << Brief(wasm_instance());
  os << "\n";
}

1748 1749 1750 1751 1752
void WasmInstanceObject::WasmInstanceObjectPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "WasmInstanceObject");
  os << "\n - module_object: " << Brief(module_object());
  os << "\n - exports_object: " << Brief(exports_object());
  os << "\n - native_context: " << Brief(native_context());
1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768
  if (has_memory_object()) {
    os << "\n - memory_object: " << Brief(memory_object());
  }
  if (has_globals_buffer()) {
    os << "\n - globals_buffer: " << Brief(globals_buffer());
  }
  if (has_imported_mutable_globals_buffers()) {
    os << "\n - imported_mutable_globals_buffers: "
       << Brief(imported_mutable_globals_buffers());
  }
  if (has_debug_info()) {
    os << "\n - debug_info: " << Brief(debug_info());
  }
  if (has_table_object()) {
    os << "\n - table_object: " << Brief(table_object());
  }
1769 1770 1771 1772
  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());
1773 1774 1775 1776 1777
  }
  if (has_managed_native_allocations()) {
    os << "\n - managed_native_allocations: "
       << Brief(managed_native_allocations());
  }
1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793
  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());
  os << "\n";
}

1794 1795 1796 1797 1798 1799 1800 1801 1802
void WasmExportedFunctionData::WasmExportedFunctionDataPrint(
    std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "WasmExportedFunctionData");
  os << "\n - wrapper_code: " << Brief(wrapper_code());
  os << "\n - instance: " << Brief(instance());
  os << "\n - function_index: " << function_index();
  os << "\n";
}

1803
void WasmModuleObject::WasmModuleObjectPrint(std::ostream& os) {  // NOLINT
1804
  HeapObject::PrintHeader(os, "WasmModuleObject");
1805
  os << "\n - module: " << module();
1806 1807 1808
  os << "\n - native module: " << native_module();
  os << "\n - export wrappers: " << Brief(export_wrappers());
  os << "\n - script: " << Brief(script());
1809 1810 1811 1812 1813 1814
  if (has_asm_js_offset_table()) {
    os << "\n - asm_js_offset_table: " << Brief(asm_js_offset_table());
  }
  if (has_breakpoint_infos()) {
    os << "\n - breakpoint_infos: " << Brief(breakpoint_infos());
  }
1815 1816 1817
  os << "\n";
}

1818 1819 1820 1821 1822
void LoadHandler::LoadHandlerPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "LoadHandler");
  // TODO(ishell): implement printing based on handler kind
  os << "\n - handler: " << Brief(smi_handler());
  os << "\n - validity_cell: " << Brief(validity_cell());
1823 1824
  int data_count = data_field_count();
  if (data_count >= 1) {
1825
    os << "\n - data1: " << Brief(data1());
1826 1827
  }
  if (data_count >= 2) {
1828
    os << "\n - data2: " << Brief(data2());
1829
  }
1830
  if (data_count >= 3) {
1831
    os << "\n - data3: " << Brief(data3());
1832
  }
1833 1834 1835 1836 1837 1838 1839 1840
  os << "\n";
}

void StoreHandler::StoreHandlerPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "StoreHandler");
  // TODO(ishell): implement printing based on handler kind
  os << "\n - handler: " << Brief(smi_handler());
  os << "\n - validity_cell: " << Brief(validity_cell());
1841 1842
  int data_count = data_field_count();
  if (data_count >= 1) {
1843
    os << "\n - data1: " << Brief(data1());
1844 1845
  }
  if (data_count >= 2) {
1846
    os << "\n - data2: " << Brief(data2());
1847
  }
1848
  if (data_count >= 3) {
1849
    os << "\n - data3: " << Brief(data3());
1850
  }
1851 1852 1853
  os << "\n";
}

1854
void AccessorPair::AccessorPairPrint(std::ostream& os) {  // NOLINT
1855 1856 1857 1858 1859 1860 1861
  HeapObject::PrintHeader(os, "AccessorPair");
  os << "\n - getter: " << Brief(getter());
  os << "\n - setter: " << Brief(setter());
  os << "\n";
}


1862
void AccessCheckInfo::AccessCheckInfoPrint(std::ostream& os) {  // NOLINT
1863
  HeapObject::PrintHeader(os, "AccessCheckInfo");
1864
  os << "\n - callback: " << Brief(callback());
1865 1866
  os << "\n - named_interceptor: " << Brief(named_interceptor());
  os << "\n - indexed_interceptor: " << Brief(indexed_interceptor());
1867 1868 1869 1870
  os << "\n - data: " << Brief(data());
  os << "\n";
}

1871
void CallHandlerInfo::CallHandlerInfoPrint(std::ostream& os) {  // NOLINT
1872 1873 1874 1875 1876
  HeapObject::PrintHeader(os, "CallHandlerInfo");
  os << "\n - callback: " << Brief(callback());
  os << "\n - js_callback: " << Brief(js_callback());
  os << "\n - data: " << Brief(data());
  os << "\n - side_effect_free: "
1877
     << (IsSideEffectFreeCallHandlerInfo() ? "true" : "false");
1878 1879
  os << "\n";
}
1880

1881
void InterceptorInfo::InterceptorInfoPrint(std::ostream& os) {  // NOLINT
1882 1883 1884 1885 1886 1887 1888 1889
  HeapObject::PrintHeader(os, "InterceptorInfo");
  os << "\n - getter: " << Brief(getter());
  os << "\n - setter: " << Brief(setter());
  os << "\n - query: " << Brief(query());
  os << "\n - deleter: " << Brief(deleter());
  os << "\n - enumerator: " << Brief(enumerator());
  os << "\n - data: " << Brief(data());
  os << "\n";
1890 1891 1892
}


1893 1894
void FunctionTemplateInfo::FunctionTemplateInfoPrint(
    std::ostream& os) {  // NOLINT
1895 1896 1897
  HeapObject::PrintHeader(os, "FunctionTemplateInfo");
  os << "\n - class name: " << Brief(class_name());
  os << "\n - tag: " << Brief(tag());
1898
  os << "\n - serial_number: " << Brief(serial_number());
1899
  os << "\n - property_list: " << Brief(property_list());
1900 1901 1902 1903 1904 1905 1906 1907 1908
  os << "\n - call_code: " << Brief(call_code());
  os << "\n - property_accessors: " << Brief(property_accessors());
  os << "\n - prototype_template: " << Brief(prototype_template());
  os << "\n - parent_template: " << Brief(parent_template());
  os << "\n - named_property_handler: " << Brief(named_property_handler());
  os << "\n - indexed_property_handler: " << Brief(indexed_property_handler());
  os << "\n - instance_template: " << Brief(instance_template());
  os << "\n - signature: " << Brief(signature());
  os << "\n - access_check_info: " << Brief(access_check_info());
1909
  os << "\n - cached_property_name: " << Brief(cached_property_name());
1910 1911 1912
  os << "\n - hidden_prototype: " << (hidden_prototype() ? "true" : "false");
  os << "\n - undetectable: " << (undetectable() ? "true" : "false");
  os << "\n - need_access_check: " << (needs_access_check() ? "true" : "false");
1913
  os << "\n - instantiated: " << (instantiated() ? "true" : "false");
1914 1915 1916 1917
  os << "\n";
}


1918
void ObjectTemplateInfo::ObjectTemplateInfoPrint(std::ostream& os) {  // NOLINT
1919
  HeapObject::PrintHeader(os, "ObjectTemplateInfo");
1920 1921
  os << "\n - tag: " << Brief(tag());
  os << "\n - serial_number: " << Brief(serial_number());
1922 1923 1924
  os << "\n - property_list: " << Brief(property_list());
  os << "\n - property_accessors: " << Brief(property_accessors());
  os << "\n - constructor: " << Brief(constructor());
1925
  os << "\n - embedder_field_count: " << embedder_field_count();
1926
  os << "\n - immutable_proto: " << (immutable_proto() ? "true" : "false");
1927 1928 1929 1930
  os << "\n";
}


1931
void AllocationSite::AllocationSitePrint(std::ostream& os) {  // NOLINT
1932
  HeapObject::PrintHeader(os, "AllocationSite");
1933
  if (this->HasWeakNext()) os << "\n - weak_next: " << Brief(weak_next());
1934 1935 1936 1937 1938 1939 1940 1941 1942
  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: ";
1943
  if (!PointsToLiteral()) {
1944
    ElementsKind kind = GetElementsKind();
1945
    os << "Array allocation with ElementsKind " << ElementsKindToString(kind);
1946 1947
  } else if (boilerplate()->IsJSArray()) {
    os << "Array literal with boilerplate " << Brief(boilerplate());
1948
  } else {
1949
    os << "Object literal with boilerplate " << Brief(boilerplate());
1950
  }
1951
  os << "\n";
1952 1953 1954
}


1955
void AllocationMemento::AllocationMementoPrint(std::ostream& os) {  // NOLINT
1956
  HeapObject::PrintHeader(os, "AllocationMemento");
1957
  os << "\n - allocation site: ";
1958
  if (IsValid()) {
1959
    GetAllocationSite()->AllocationSitePrint(os);
1960
  } else {
1961
    os << "<invalid>\n";
1962 1963 1964 1965
  }
}


1966
void Script::ScriptPrint(std::ostream& os) {  // NOLINT
1967 1968 1969
  HeapObject::PrintHeader(os, "Script");
  os << "\n - source: " << Brief(source());
  os << "\n - name: " << Brief(name());
1970 1971 1972 1973
  os << "\n - line_offset: " << line_offset();
  os << "\n - column_offset: " << column_offset();
  os << "\n - type: " << type();
  os << "\n - id: " << id();
1974 1975 1976
  os << "\n - context data: " << Brief(context_data());
  os << "\n - compilation type: " << compilation_type();
  os << "\n - line ends: " << Brief(line_ends());
1977 1978 1979 1980 1981 1982
  if (has_eval_from_shared()) {
    os << "\n - eval from shared: " << Brief(eval_from_shared());
  }
  if (is_wrapped()) {
    os << "\n - wrapped arguments: " << Brief(wrapped_arguments());
  }
1983
  os << "\n - eval from position: " << eval_from_position();
1984
  os << "\n - shared function infos: " << Brief(shared_function_infos());
1985 1986 1987
  os << "\n";
}

1988
#ifdef V8_INTL_SUPPORT
1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002
void JSV8BreakIterator::JSV8BreakIteratorPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSV8BreakIterator");
  os << "\n - locale: " << Brief(locale());
  os << "\n - type: " << TypeAsString();
  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";
}

2003 2004 2005
void JSCollator::JSCollatorPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSCollator");
  os << "\n - icu collator: " << Brief(icu_collator());
2006
  os << "\n - bound compare: " << Brief(bound_compare());
2007 2008 2009
  os << "\n";
}

2010 2011
void JSDateTimeFormat::JSDateTimeFormatPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSDateTimeFormat");
2012
  os << "\n - icu locale: " << Brief(icu_locale());
2013 2014 2015
  os << "\n - icu simple date format: " << Brief(icu_simple_date_format());
  os << "\n - bound format: " << Brief(bound_format());
  os << "\n";
2016 2017
}

2018 2019 2020 2021 2022
void JSListFormat::JSListFormatPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSListFormat");
  os << "\n - locale: " << Brief(locale());
  os << "\n - style: " << StyleAsString();
  os << "\n - type: " << TypeAsString();
2023
  os << "\n - icu formatter: " << Brief(icu_formatter());
2024 2025 2026
  os << "\n";
}

2027 2028 2029 2030 2031 2032 2033 2034
void JSLocale::JSLocalePrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "JSLocale");
  os << "\n - language: " << Brief(language());
  os << "\n - script: " << Brief(script());
  os << "\n - region: " << Brief(region());
  os << "\n - baseName: " << Brief(base_name());
  os << "\n - locale: " << Brief(locale());
  os << "\n - calendar: " << Brief(calendar());
2035
  os << "\n - caseFirst: " << CaseFirstAsString();
2036
  os << "\n - collation: " << Brief(collation());
2037 2038
  os << "\n - hourCycle: " << HourCycleAsString();
  os << "\n - numeric: " << NumericAsString();
2039 2040 2041
  os << "\n - numberingSystem: " << Brief(numbering_system());
  os << "\n";
}
2042

2043 2044 2045 2046 2047 2048 2049 2050 2051 2052
void JSNumberFormat::JSNumberFormatPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSNumberFormat");
  os << "\n - locale: " << Brief(locale());
  os << "\n - icu_number_format: " << Brief(icu_number_format());
  os << "\n - bound_format: " << Brief(bound_format());
  os << "\n - style: " << StyleAsString();
  os << "\n - currency_display: " << CurrencyDisplayAsString();
  os << "\n";
}

2053 2054 2055 2056 2057 2058 2059 2060 2061 2062
void JSPluralRules::JSPluralRulesPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "JSPluralRules");
  JSObjectPrint(os);
  os << "\n - locale: " << Brief(locale());
  os << "\n - type: " << Brief(type());
  os << "\n - icu plural rules: " << Brief(icu_plural_rules());
  os << "\n - icu decimal format: " << Brief(icu_decimal_format());
  os << "\n";
}

2063 2064
void JSRelativeTimeFormat::JSRelativeTimeFormatPrint(
    std::ostream& os) {  // NOLINT
2065
  JSObjectPrintHeader(os, this, "JSRelativeTimeFormat");
2066
  os << "\n - locale: " << Brief(locale());
2067 2068
  os << "\n - style: " << StyleAsString();
  os << "\n - numeric: " << NumericAsString();
2069
  os << "\n - icu formatter: " << Brief(icu_formatter());
2070 2071
  os << "\n";
}
2072 2073 2074 2075 2076 2077 2078 2079 2080

void JSSegmenter::JSSegmenterPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSSegmenter");
  os << "\n - locale: " << Brief(locale());
  os << "\n - granularity: " << GranularityAsString();
  os << "\n - lineBreakStyle: " << LineBreakStyleAsString();
  os << "\n - icubreak iterator: " << Brief(icu_break_iterator());
  os << "\n";
}
2081 2082
#endif  // V8_INTL_SUPPORT

2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104
namespace {
void PrintScopeInfoList(ScopeInfo* scope_info, std::ostream& os,
                        const char* list_name, int nof_internal_slots,
                        int start, int length) {
  if (length <= 0) return;
  int end = start + length;
  os << "\n - " << list_name;
  if (nof_internal_slots > 0) {
    os << " " << start << "-" << end << " [internal slots]";
  }
  os << " {\n";
  for (int i = nof_internal_slots; start < end; ++i, ++start) {
    os << "    - " << i << ": ";
    String::cast(scope_info->get(start))->ShortPrint(os);
    os << "\n";
  }
  os << "  }";
}
}  // namespace

void ScopeInfo::ScopeInfoPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "ScopeInfo");
2105
  if (length() == 0) {
2106
    os << "\n - length = 0\n";
2107 2108
    return;
  }
2109 2110 2111 2112
  int flags = Flags();

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

2114
  os << "\n - scope type: " << scope_type();
2115
  if (CallsSloppyEval()) os << "\n - sloppy eval";
2116
  os << "\n - language mode: " << language_mode();
2117 2118 2119 2120
  if (is_declaration_scope()) os << "\n - declaration scope";
  if (HasReceiver()) {
    os << "\n - receiver: " << ReceiverVariableField::decode(flags);
  }
2121
  if (HasNewTarget()) os << "\n - needs new target";
2122 2123 2124 2125 2126 2127 2128 2129
  if (HasFunctionName()) {
    os << "\n - function name(" << FunctionVariableField::decode(flags)
       << "): ";
    FunctionName()->ShortPrint(os);
  }
  if (IsAsmModule()) os << "\n - asm module";
  if (HasSimpleParameters()) os << "\n - simple parameters";
  os << "\n - function kind: " << function_kind();
2130 2131 2132 2133
  if (HasOuterScopeInfo()) {
    os << "\n - outer scope info: " << Brief(OuterScopeInfo());
  }
  if (HasFunctionName()) {
2134
    os << "\n - function name: " << Brief(FunctionName());
2135
  }
2136 2137 2138 2139
  if (HasInferredFunctionName()) {
    os << "\n - inferred function name: " << Brief(InferredFunctionName());
  }

2140
  if (HasPositionInfo()) {
2141 2142
    os << "\n - start position: " << StartPosition();
    os << "\n - end position: " << EndPosition();
2143
  }
2144 2145 2146 2147 2148 2149 2150 2151
  os << "\n - length: " << length();
  if (length() > 0) {
    PrintScopeInfoList(this, os, "context slots", Context::MIN_CONTEXT_SLOTS,
                       ContextLocalNamesIndex(), ContextLocalCount());
    // TODO(neis): Print module stuff if present.
  }
  os << "\n";
}
2152

2153
void DebugInfo::DebugInfoPrint(std::ostream& os) {  // NOLINT
2154
  HeapObject::PrintHeader(os, "DebugInfo");
2155 2156
  os << "\n - flags: " << flags();
  os << "\n - debugger_hints: " << debugger_hints();
2157
  os << "\n - shared: " << Brief(shared());
2158
  os << "\n - script: " << Brief(script());
2159
  os << "\n - original bytecode array: " << Brief(original_bytecode_array());
2160
  os << "\n - break_points: ";
2161
  break_points()->FixedArrayPrint(os);
2162
  os << "\n - coverage_info: " << Brief(coverage_info());
2163 2164 2165
}


2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178
void StackFrameInfo::StackFrameInfoPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "StackFrame");
  os << "\n - line_number: " << line_number();
  os << "\n - column_number: " << column_number();
  os << "\n - script_id: " << script_id();
  os << "\n - script_name: " << Brief(script_name());
  os << "\n - script_name_or_source_url: "
     << Brief(script_name_or_source_url());
  os << "\n - function_name: " << Brief(function_name());
  os << "\n - is_eval: " << (is_eval() ? "true" : "false");
  os << "\n - is_constructor: " << (is_constructor() ? "true" : "false");
  os << "\n";
}
2179

2180 2181 2182 2183 2184 2185 2186 2187
static void PrintBitMask(std::ostream& os, uint32_t value) {  // NOLINT
  for (int i = 0; i < 32; i++) {
    if ((i & 7) == 0) os << " ";
    os << (((value & 1) == 0) ? "_" : "x");
    value >>= 1;
  }
}

2188
void LayoutDescriptor::Print() {
2189
  StdoutStream os;
2190 2191 2192 2193
  this->Print(os);
  os << std::flush;
}

2194 2195 2196 2197 2198 2199 2200
void LayoutDescriptor::ShortPrint(std::ostream& os) {
  if (IsSmi()) {
    os << this;  // Print tagged value for easy use with "jld" gdb macro.
  } else {
    os << Brief(this);
  }
}
2201 2202 2203

void LayoutDescriptor::Print(std::ostream& os) {  // NOLINT
  os << "Layout descriptor: ";
2204
  if (IsFastPointerLayout()) {
2205 2206 2207
    os << "<all tagged>";
  } else if (IsSmi()) {
    os << "fast";
jgruber's avatar
jgruber committed
2208
    PrintBitMask(os, static_cast<uint32_t>(Smi::ToInt(this)));
2209
  } else if (IsOddball() && IsUninitialized()) {
2210
    os << "<uninitialized>";
2211 2212
  } else {
    os << "slow";
2213 2214
    int num_words = number_of_layout_words();
    for (int i = 0; i < num_words; i++) {
2215
      if (i > 0) os << " |";
2216
      PrintBitMask(os, get_layout_word(i));
2217 2218 2219 2220 2221
    }
  }
  os << "\n";
}

2222 2223 2224
void PreParsedScopeData::PreParsedScopeDataPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "PreParsedScopeData");
  os << "\n - scope_data: " << Brief(scope_data());
2225 2226 2227 2228
  os << "\n - length: " << length();
  for (int i = 0; i < length(); ++i) {
    os << "\n - [" << i << "]: " << Brief(child_data(i));
  }
2229 2230
  os << "\n";
}
2231

2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248
void UncompiledDataWithoutPreParsedScope::
    UncompiledDataWithoutPreParsedScopePrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "UncompiledDataWithoutPreParsedScope");
  os << "\n - start position: " << start_position();
  os << "\n - end position: " << end_position();
  os << "\n";
}

void UncompiledDataWithPreParsedScope::UncompiledDataWithPreParsedScopePrint(
    std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "UncompiledDataWithPreParsedScope");
  os << "\n - start position: " << start_position();
  os << "\n - end position: " << end_position();
  os << "\n - pre_parsed_scope_data: " << Brief(pre_parsed_scope_data());
  os << "\n";
}

2249
void MicrotaskQueue::MicrotaskQueuePrint(std::ostream& os) {  // NOLINT
2250 2251 2252 2253
  HeapObject::PrintHeader(os, "MicrotaskQueue");
  os << "\n - pending_microtask_count: " << pending_microtask_count();
  os << "\n - queue: " << Brief(queue());
  os << "\n";
2254 2255
}

2256 2257 2258 2259 2260 2261 2262
void InterpreterData::InterpreterDataPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "InterpreterData");
  os << "\n - bytecode_array: " << Brief(bytecode_array());
  os << "\n - interpreter_trampoline: " << Brief(interpreter_trampoline());
  os << "\n";
}

2263
void MaybeObject::Print() {
2264
  StdoutStream os;
2265
  this->Print(os);
2266 2267 2268
  os << std::flush;
}

2269
void MaybeObject::Print(std::ostream& os) {
2270 2271 2272 2273
  Smi* smi;
  HeapObject* heap_object;
  if (ToSmi(&smi)) {
    smi->SmiPrint(os);
2274
  } else if (IsCleared()) {
2275
    os << "[cleared]";
2276
  } else if (GetHeapObjectIfWeak(&heap_object)) {
2277
    os << "[weak] ";
2278
    heap_object->HeapObjectPrint(os);
2279
  } else if (GetHeapObjectIfStrong(&heap_object)) {
2280
    heap_object->HeapObjectPrint(os);
2281 2282 2283 2284 2285
  } else {
    UNREACHABLE();
  }
}

2286 2287
#endif  // OBJECT_PRINT

2288 2289 2290 2291 2292 2293
void HeapNumber::HeapNumberPrint(std::ostream& os) { os << value(); }

void MutableHeapNumber::MutableHeapNumberPrint(std::ostream& os) {
  os << value();
}

2294
// TODO(cbruni): remove once the new maptracer is in place.
2295
void Name::NameShortPrint() {
2296 2297 2298 2299 2300
  if (this->IsString()) {
    PrintF("%s", String::cast(this)->ToCString().get());
  } else {
    DCHECK(this->IsSymbol());
    Symbol* s = Symbol::cast(this);
2301 2302
    if (s->name()->IsUndefined()) {
      PrintF("#<%s>", s->PrivateSymbolToName());
2303 2304 2305 2306 2307 2308
    } else {
      PrintF("<%s>", String::cast(s->name())->ToCString().get());
    }
  }
}

2309
// TODO(cbruni): remove once the new maptracer is in place.
2310
int Name::NameShortPrint(Vector<char> str) {
2311 2312 2313 2314 2315
  if (this->IsString()) {
    return SNPrintF(str, "%s", String::cast(this)->ToCString().get());
  } else {
    DCHECK(this->IsSymbol());
    Symbol* s = Symbol::cast(this);
2316 2317
    if (s->name()->IsUndefined()) {
      return SNPrintF(str, "#<%s>", s->PrivateSymbolToName());
2318 2319 2320 2321 2322 2323
    } else {
      return SNPrintF(str, "<%s>", String::cast(s->name())->ToCString().get());
    }
  }
}

2324
void Map::PrintMapDetails(std::ostream& os) {
2325 2326
  DisallowHeapAllocation no_gc;
#ifdef OBJECT_PRINT
2327
  this->MapPrint(os);
2328 2329 2330 2331 2332
#else
  os << "Map=" << reinterpret_cast<void*>(this);
#endif
  os << "\n";
  instance_descriptors()->PrintDescriptors(os);
2333 2334
}

2335
void DescriptorArray::PrintDescriptors(std::ostream& os) {
2336
  for (int i = 0; i < number_of_descriptors(); i++) {
2337 2338 2339 2340 2341 2342 2343 2344 2345
    Name* key = GetKey(i);
    os << "\n  [" << i << "]: ";
#ifdef OBJECT_PRINT
    key->NamePrint(os);
#else
    key->ShortPrint(os);
#endif
    os << " ";
    PrintDescriptorDetails(os, i, PropertyDetails::kPrintFull);
2346 2347 2348 2349
  }
  os << "\n";
}

2350 2351 2352 2353 2354 2355 2356
void DescriptorArray::PrintDescriptorDetails(std::ostream& os, int descriptor,
                                             PropertyDetails::PrintMode mode) {
  PropertyDetails details = GetDetails(descriptor);
  details.PrintAsFastTo(os, mode);
  os << " @ ";
  switch (details.location()) {
    case kField: {
2357
      FieldType* field_type = GetFieldType(descriptor);
2358 2359 2360 2361
      field_type->PrintTo(os);
      break;
    }
    case kDescriptor:
2362
      Object* value = GetStrongValue(descriptor);
2363 2364 2365 2366 2367 2368 2369 2370 2371
      os << Brief(value);
      if (value->IsAccessorPair()) {
        AccessorPair* pair = AccessorPair::cast(value);
        os << "(get: " << Brief(pair->getter())
           << ", set: " << Brief(pair->setter()) << ")";
      }
      break;
  }
}
2372

2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387
#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];
  WriteToFlat(this, reinterpret_cast<uint8_t*>(buffer), 0, length());
  buffer[length()] = 0;
  return buffer;
}

2388
// static
2389 2390
void TransitionsAccessor::PrintOneTransition(std::ostream& os, Name* key,
                                             Map* target) {
2391 2392 2393 2394 2395 2396 2397
  os << "\n     ";
#ifdef OBJECT_PRINT
  key->NamePrint(os);
#else
  key->ShortPrint(os);
#endif
  os << ": ";
2398 2399
  ReadOnlyRoots roots = key->GetReadOnlyRoots();
  if (key == roots.nonextensible_symbol()) {
2400
    os << "(transition to non-extensible)";
2401
  } else if (key == roots.sealed_symbol()) {
2402
    os << "(transition to sealed)";
2403
  } else if (key == roots.frozen_symbol()) {
2404
    os << "(transition to frozen)";
2405
  } else if (key == roots.elements_transition_symbol()) {
2406 2407
    os << "(transition to " << ElementsKindToString(target->elements_kind())
       << ")";
2408
  } else if (key == roots.strict_function_transition_symbol()) {
2409 2410
    os << " (transition to strict function)";
  } else {
2411
    DCHECK(!IsSpecialTransition(roots, key));
2412 2413 2414 2415 2416 2417 2418 2419 2420 2421
    os << "(transition to ";
    int descriptor = target->LastAdded();
    DescriptorArray* descriptors = target->instance_descriptors();
    descriptors->PrintDescriptorDetails(os, descriptor,
                                        PropertyDetails::kForTransitions);
    os << ")";
  }
  os << " -> " << Brief(target);
}

2422
void TransitionArray::PrintInternal(std::ostream& os) {
2423 2424
  int num_transitions = number_of_transitions();
  os << "Transition array #" << num_transitions << ":";
2425
  for (int i = 0; i < num_transitions; i++) {
2426 2427
    Name* key = GetKey(i);
    Map* target = GetTarget(i);
2428
    TransitionsAccessor::PrintOneTransition(os, key, target);
2429
  }
2430 2431 2432 2433 2434 2435 2436 2437
  os << "\n" << std::flush;
}

void TransitionsAccessor::PrintTransitions(std::ostream& os) {  // NOLINT
  switch (encoding()) {
    case kPrototypeInfo:
    case kUninitialized:
      return;
2438
    case kWeakRef: {
2439
      Map* target = Map::cast(raw_transitions_->GetHeapObjectAssumeWeak());
2440
      Name* key = GetSimpleTransitionKey(target);
2441
      PrintOneTransition(os, key, target);
2442
      break;
2443
    }
2444
    case kFullTransitionArray:
2445
      return transitions()->PrintInternal(os);
2446
  }
2447 2448
}

2449
void TransitionsAccessor::PrintTransitionTree() {
2450
  StdoutStream os;
2451 2452 2453
  os << "map= " << Brief(map_);
  DisallowHeapAllocation no_gc;
  PrintTransitionTree(os, 0, &no_gc);
2454 2455 2456
  os << "\n" << std::flush;
}

2457 2458
void TransitionsAccessor::PrintTransitionTree(std::ostream& os, int level,
                                              DisallowHeapAllocation* no_gc) {
2459
  ReadOnlyRoots roots = ReadOnlyRoots(isolate_);
2460
  int num_transitions = NumberOfTransitions();
2461 2462
  if (num_transitions == 0) return;
  for (int i = 0; i < num_transitions; i++) {
2463 2464
    Name* key = GetKey(i);
    Map* target = GetTarget(i);
2465 2466
    os << std::endl
       << "  " << level << "/" << i << ":" << std::setw(level * 2 + 2) << " ";
2467 2468 2469 2470
    std::stringstream ss;
    ss << Brief(target);
    os << std::left << std::setw(50) << ss.str() << ": ";

2471
    if (key == roots.nonextensible_symbol()) {
2472
      os << "to non-extensible";
2473
    } else if (key == roots.sealed_symbol()) {
2474
      os << "to sealed ";
2475
    } else if (key == roots.frozen_symbol()) {
2476
      os << "to frozen";
2477
    } else if (key == roots.elements_transition_symbol()) {
2478
      os << "to " << ElementsKindToString(target->elements_kind());
2479
    } else if (key == roots.strict_function_transition_symbol()) {
2480 2481 2482 2483 2484 2485 2486 2487
      os << "to strict function";
    } else {
#ifdef OBJECT_PRINT
      key->NamePrint(os);
#else
      key->ShortPrint(os);
#endif
      os << " ";
2488
      DCHECK(!IsSpecialTransition(ReadOnlyRoots(isolate_), key));
2489
      os << "to ";
2490 2491 2492 2493 2494
      int descriptor = target->LastAdded();
      DescriptorArray* descriptors = target->instance_descriptors();
      descriptors->PrintDescriptorDetails(os, descriptor,
                                          PropertyDetails::kForTransitions);
    }
2495
    TransitionsAccessor transitions(isolate_, target, no_gc);
2496
    transitions.PrintTransitionTree(os, level + 1, no_gc);
2497 2498
  }
}
2499

2500
void JSObject::PrintTransitions(std::ostream& os) {  // NOLINT
2501
  DisallowHeapAllocation no_gc;
2502
  TransitionsAccessor ta(GetIsolate(), map(), &no_gc);
2503
  if (ta.NumberOfTransitions() == 0) return;
2504
  os << "\n - transitions";
2505
  ta.PrintTransitions(os);
2506
}
2507

2508
#endif  // defined(DEBUG) || defined(OBJECT_PRINT)
2509 2510
}  // namespace internal
}  // namespace v8
2511 2512 2513 2514

//
// The following functions are used by our gdb macros.
//
2515
V8_EXPORT_PRIVATE extern void _v8_internal_Print_Object(void* object) {
2516
  reinterpret_cast<i::Object*>(object)->Print();
2517 2518
}

2519
V8_EXPORT_PRIVATE extern void _v8_internal_Print_Code(void* object) {
2520
  i::Address address = reinterpret_cast<i::Address>(object);
2521
  i::Isolate* isolate = i::Isolate::Current();
2522

2523
  i::wasm::WasmCode* wasm_code =
2524
      isolate->wasm_engine()->code_manager()->LookupCode(address);
2525
  if (wasm_code) {
2526
    i::StdoutStream os;
2527
    wasm_code->Disassemble(nullptr, os, address);
2528 2529
    return;
  }
2530 2531

  if (!isolate->heap()->InSpaceSlow(address, i::CODE_SPACE) &&
2532 2533
      !isolate->heap()->InSpaceSlow(address, i::LO_SPACE) &&
      !i::InstructionStream::PcIsOffHeap(isolate, address)) {
2534
    i::PrintF(
2535 2536
        "%p is not within the current isolate's large object, code or embedded "
        "spaces\n",
2537
        object);
2538 2539 2540 2541 2542
    return;
  }

  i::Code* code = isolate->FindCodeObject(address);
  if (!code->IsCode()) {
2543
    i::PrintF("No code object found containing %p\n", object);
2544 2545 2546
    return;
  }
#ifdef ENABLE_DISASSEMBLER
2547
  i::StdoutStream os;
2548
  code->Disassemble(nullptr, os, address);
2549
#else   // ENABLE_DISASSEMBLER
2550
  code->Print();
2551
#endif  // ENABLE_DISASSEMBLER
2552 2553
}

2554 2555
V8_EXPORT_PRIVATE extern void _v8_internal_Print_LayoutDescriptor(
    void* object) {
2556 2557
  i::Object* o = reinterpret_cast<i::Object*>(object);
  if (!o->IsLayoutDescriptor()) {
2558
    printf("Please provide a layout descriptor\n");
2559
  } else {
2560
    reinterpret_cast<i::LayoutDescriptor*>(object)->Print();
2561 2562 2563
  }
}

2564
V8_EXPORT_PRIVATE extern void _v8_internal_Print_StackTrace() {
2565 2566 2567
  i::Isolate* isolate = i::Isolate::Current();
  isolate->PrintStack(stdout);
}
2568

2569
V8_EXPORT_PRIVATE extern void _v8_internal_Print_TransitionTree(void* object) {
2570 2571 2572 2573 2574
  i::Object* o = reinterpret_cast<i::Object*>(object);
  if (!o->IsMap()) {
    printf("Please provide a valid Map\n");
  } else {
#if defined(DEBUG) || defined(OBJECT_PRINT)
2575
    i::DisallowHeapAllocation no_gc;
2576
    i::Map* map = reinterpret_cast<i::Map*>(object);
2577
    i::TransitionsAccessor transitions(i::Isolate::Current(), map, &no_gc);
2578
    transitions.PrintTransitionTree();
2579 2580 2581
#endif
  }
}