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

5
#include "src/objects.h"
6

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

10
#include "src/disasm.h"
11
#include "src/disassembler.h"
12
#include "src/interpreter/bytecodes.h"
13
#include "src/objects-inl.h"
14
#include "src/ostreams.h"
15
#include "src/regexp/jsregexp.h"
16 17 18 19 20 21

namespace v8 {
namespace internal {

#ifdef OBJECT_PRINT

22
void Object::Print() {
23 24
  OFStream os(stdout);
  this->Print(os);
25
  os << std::flush;
26 27 28
}


29
void Object::Print(std::ostream& os) {  // NOLINT
30
  if (IsSmi()) {
31
    Smi::cast(this)->SmiPrint(os);
32
  } else {
33
    HeapObject::cast(this)->HeapObjectPrint(os);
34 35 36 37
  }
}


38
void HeapObject::PrintHeader(std::ostream& os, const char* id) {  // NOLINT
39 40 41 42 43 44 45
  os << reinterpret_cast<void*>(this) << ": [";
  if (id != nullptr) {
    os << id;
  } else {
    os << map()->instance_type();
  }
  os << "]";
46 47 48
}


49
void HeapObject::HeapObjectPrint(std::ostream& os) {  // NOLINT
50 51
  InstanceType instance_type = map()->instance_type();

52
  HandleScope scope(GetIsolate());
53
  if (instance_type < FIRST_NONSTRING_TYPE) {
54
    String::cast(this)->StringPrint(os);
55 56 57 58
    return;
  }

  switch (instance_type) {
59
    case SYMBOL_TYPE:
60
      Symbol::cast(this)->SymbolPrint(os);
61
      break;
62
    case MAP_TYPE:
63
      Map::cast(this)->MapPrint(os);
64 65
      break;
    case HEAP_NUMBER_TYPE:
66
      HeapNumber::cast(this)->HeapNumberPrint(os);
67
      break;
68
    case MUTABLE_HEAP_NUMBER_TYPE:
69 70 71
      os << "<mutable ";
      HeapNumber::cast(this)->HeapNumberPrint(os);
      os << ">";
72
      break;
73 74
    case SIMD128_VALUE_TYPE:
      Simd128Value::cast(this)->Simd128ValuePrint(os);
75
      break;
76
    case FIXED_DOUBLE_ARRAY_TYPE:
77
      FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(os);
78
      break;
79
    case FIXED_ARRAY_TYPE:
80
      FixedArray::cast(this)->FixedArrayPrint(os);
81 82
      break;
    case BYTE_ARRAY_TYPE:
83
      ByteArray::cast(this)->ByteArrayPrint(os);
84
      break;
85 86 87
    case BYTECODE_ARRAY_TYPE:
      BytecodeArray::cast(this)->BytecodeArrayPrint(os);
      break;
88 89 90
    case TRANSITION_ARRAY_TYPE:
      TransitionArray::cast(this)->TransitionArrayPrint(os);
      break;
91
    case FREE_SPACE_TYPE:
92
      FreeSpace::cast(this)->FreeSpacePrint(os);
93
      break;
94

95 96 97 98
#define PRINT_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
  case Fixed##Type##Array::kInstanceType:                      \
    Fixed##Type##Array::cast(this)->FixedTypedArrayPrint(os);  \
    break;
99

100 101
    TYPED_ARRAYS(PRINT_FIXED_TYPED_ARRAY)
#undef PRINT_FIXED_TYPED_ARRAY
102

103
    case FILLER_TYPE:
104
      os << "filler";
105 106
      break;
    case JS_OBJECT_TYPE:  // fall through
107
    case JS_API_OBJECT_TYPE:
108
    case JS_SPECIAL_API_OBJECT_TYPE:
109
    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
110
    case JS_GENERATOR_OBJECT_TYPE:
111
    case JS_PROMISE_TYPE:
112 113
    case JS_ARGUMENTS_TYPE:
    case JS_ERROR_TYPE:
114
      JSObject::cast(this)->JSObjectPrint(os);
115
      break;
116 117 118
    case JS_ARRAY_TYPE:
      JSArray::cast(this)->JSArrayPrint(os);
      break;
119 120 121
    case JS_REGEXP_TYPE:
      JSRegExp::cast(this)->JSRegExpPrint(os);
      break;
122
    case ODDBALL_TYPE:
123
      Oddball::cast(this)->to_string()->Print(os);
124
      break;
125 126 127
    case JS_BOUND_FUNCTION_TYPE:
      JSBoundFunction::cast(this)->JSBoundFunctionPrint(os);
      break;
128
    case JS_FUNCTION_TYPE:
129
      JSFunction::cast(this)->JSFunctionPrint(os);
130 131
      break;
    case JS_GLOBAL_PROXY_TYPE:
132
      JSGlobalProxy::cast(this)->JSGlobalProxyPrint(os);
133 134
      break;
    case JS_GLOBAL_OBJECT_TYPE:
135
      JSGlobalObject::cast(this)->JSGlobalObjectPrint(os);
136 137
      break;
    case JS_VALUE_TYPE:
138
      JSValue::cast(this)->JSValuePrint(os);
139
      break;
140
    case JS_DATE_TYPE:
141
      JSDate::cast(this)->JSDatePrint(os);
142
      break;
143
    case CODE_TYPE:
144
      Code::cast(this)->CodePrint(os);
145
      break;
146
    case JS_PROXY_TYPE:
147
      JSProxy::cast(this)->JSProxyPrint(os);
148
      break;
149
    case JS_SET_TYPE:
150
      JSSet::cast(this)->JSSetPrint(os);
151 152
      break;
    case JS_MAP_TYPE:
153
      JSMap::cast(this)->JSMapPrint(os);
154
      break;
155
    case JS_SET_ITERATOR_TYPE:
156
      JSSetIterator::cast(this)->JSSetIteratorPrint(os);
157 158
      break;
    case JS_MAP_ITERATOR_TYPE:
159
      JSMapIterator::cast(this)->JSMapIteratorPrint(os);
160
      break;
161
    case JS_WEAK_MAP_TYPE:
162
      JSWeakMap::cast(this)->JSWeakMapPrint(os);
163
      break;
164
    case JS_WEAK_SET_TYPE:
165
      JSWeakSet::cast(this)->JSWeakSetPrint(os);
166
      break;
167
    case FOREIGN_TYPE:
168
      Foreign::cast(this)->ForeignPrint(os);
169 170
      break;
    case SHARED_FUNCTION_INFO_TYPE:
171
      SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(os);
172
      break;
173
    case JS_MESSAGE_OBJECT_TYPE:
174
      JSMessageObject::cast(this)->JSMessageObjectPrint(os);
175
      break;
176
    case CELL_TYPE:
177
      Cell::cast(this)->CellPrint(os);
178 179
      break;
    case PROPERTY_CELL_TYPE:
180
      PropertyCell::cast(this)->PropertyCellPrint(os);
181
      break;
ulan@chromium.org's avatar
ulan@chromium.org committed
182 183 184
    case WEAK_CELL_TYPE:
      WeakCell::cast(this)->WeakCellPrint(os);
      break;
185
    case JS_ARRAY_BUFFER_TYPE:
186
      JSArrayBuffer::cast(this)->JSArrayBufferPrint(os);
187
      break;
188
    case JS_TYPED_ARRAY_TYPE:
189
      JSTypedArray::cast(this)->JSTypedArrayPrint(os);
190
      break;
191
    case JS_DATA_VIEW_TYPE:
192
      JSDataView::cast(this)->JSDataViewPrint(os);
193
      break;
194 195
#define MAKE_STRUCT_CASE(NAME, Name, name) \
  case NAME##_TYPE:                        \
196
    Name::cast(this)->Name##Print(os);     \
197 198 199 200 201
    break;
  STRUCT_LIST(MAKE_STRUCT_CASE)
#undef MAKE_STRUCT_CASE

    default:
202
      os << "UNKNOWN TYPE " << map()->instance_type();
203 204 205 206 207 208
      UNREACHABLE();
      break;
  }
}


209 210 211 212 213 214 215 216 217
void Simd128Value::Simd128ValuePrint(std::ostream& os) {  // NOLINT
#define PRINT_SIMD128_VALUE(TYPE, Type, type, lane_count, lane_type) \
  if (Is##Type()) return Type::cast(this)->Type##Print(os);
  SIMD128_TYPES(PRINT_SIMD128_VALUE)
#undef PRINT_SIMD128_VALUE
  UNREACHABLE();
}


218 219 220 221 222 223 224 225 226 227
void Float32x4::Float32x4Print(std::ostream& os) {  // NOLINT
  char arr[100];
  Vector<char> buffer(arr, arraysize(arr));
  os << std::string(DoubleToCString(get_lane(0), buffer)) << ", "
     << std::string(DoubleToCString(get_lane(1), buffer)) << ", "
     << std::string(DoubleToCString(get_lane(2), buffer)) << ", "
     << std::string(DoubleToCString(get_lane(3), buffer));
}


228 229 230 231 232 233 234 235
#define SIMD128_INT_PRINT_FUNCTION(type, lane_count)                \
  void type::type##Print(std::ostream& os) {                        \
    char arr[100];                                                  \
    Vector<char> buffer(arr, arraysize(arr));                       \
    os << std::string(IntToCString(get_lane(0), buffer));           \
    for (int i = 1; i < lane_count; i++) {                          \
      os << ", " << std::string(IntToCString(get_lane(i), buffer)); \
    }                                                               \
236
  }
237
SIMD128_INT_PRINT_FUNCTION(Int32x4, 4)
238
SIMD128_INT_PRINT_FUNCTION(Uint32x4, 4)
239
SIMD128_INT_PRINT_FUNCTION(Int16x8, 8)
240
SIMD128_INT_PRINT_FUNCTION(Uint16x8, 8)
241
SIMD128_INT_PRINT_FUNCTION(Int8x16, 16)
242
SIMD128_INT_PRINT_FUNCTION(Uint8x16, 16)
243 244 245 246 247 248 249 250 251 252 253
#undef SIMD128_INT_PRINT_FUNCTION


#define SIMD128_BOOL_PRINT_FUNCTION(type, lane_count)            \
  void type::type##Print(std::ostream& os) {                     \
    char arr[100];                                               \
    Vector<char> buffer(arr, arraysize(arr));                    \
    os << std::string(get_lane(0) ? "true" : "false");           \
    for (int i = 1; i < lane_count; i++) {                       \
      os << ", " << std::string(get_lane(i) ? "true" : "false"); \
    }                                                            \
254
  }
255 256 257 258
SIMD128_BOOL_PRINT_FUNCTION(Bool32x4, 4)
SIMD128_BOOL_PRINT_FUNCTION(Bool16x8, 8)
SIMD128_BOOL_PRINT_FUNCTION(Bool8x16, 16)
#undef SIMD128_BOOL_PRINT_FUNCTION
259 260


261
void ByteArray::ByteArrayPrint(std::ostream& os) {  // NOLINT
262
  os << "byte array, data starts at " << GetDataStartAddress();
263 264 265
}


266 267 268 269 270
void BytecodeArray::BytecodeArrayPrint(std::ostream& os) {  // NOLINT
  Disassemble(os);
}


271
void FreeSpace::FreeSpacePrint(std::ostream& os) {  // NOLINT
272
  os << "free space, size " << Size();
273 274 275
}


276
template <class Traits>
277 278
void FixedTypedArray<Traits>::FixedTypedArrayPrint(
    std::ostream& os) {  // NOLINT
279
  os << "fixed " << Traits::Designator();
280 281
}

282

283
void JSObject::PrintProperties(std::ostream& os) {  // NOLINT
284 285
  if (HasFastProperties()) {
    DescriptorArray* descs = map()->instance_descriptors();
286
    for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
287
      os << "\n   ";
288 289
      descs->GetKey(i)->NamePrint(os);
      os << ": ";
290
      switch (descs->GetType(i)) {
291
        case DATA: {
292
          FieldIndex index = FieldIndex::ForDescriptor(map(), i);
293 294 295 296 297
          if (IsUnboxedDoubleField(index)) {
            os << "<unboxed double> " << RawFastDoublePropertyAt(index);
          } else {
            os << Brief(RawFastPropertyAt(index));
          }
298
          os << " (data field at offset " << index.property_index() << ")";
299 300
          break;
        }
301
        case ACCESSOR: {
302
          FieldIndex index = FieldIndex::ForDescriptor(map(), i);
303
          os << " (accessor field at offset " << index.property_index() << ")";
304 305
          break;
        }
306
        case DATA_CONSTANT:
307
          os << Brief(descs->GetConstant(i)) << " (data constant)";
308
          break;
309
        case ACCESSOR_CONSTANT:
310
          os << Brief(descs->GetCallbacksObject(i)) << " (accessor constant)";
311 312 313
          break;
      }
    }
314
  } else if (IsJSGlobalObject()) {
315
    global_dictionary()->Print(os);
316
  } else {
317
    property_dictionary()->Print(os);
318 319 320
  }
}

321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
namespace {

template <class T>
double GetScalarElement(T* array, int index) {
  return array->get_scalar(index);
}

double GetScalarElement(FixedDoubleArray* array, int index) {
  if (array->is_the_hole(index)) return bit_cast<double>(kHoleNanInt64);
  return array->get_scalar(index);
}

bool is_the_hole(double maybe_hole) {
  return bit_cast<uint64_t>(maybe_hole) == kHoleNanInt64;
}

}  // namespace

339
template <class T, bool print_the_hole>
340
static void DoPrintElements(std::ostream& os, Object* object) {  // NOLINT
341 342 343
  T* array = T::cast(object);
  if (array->length() == 0) return;
  int previous_index = 0;
344
  double previous_value = GetScalarElement(array, 0);
345 346 347
  double value = 0.0;
  int i;
  for (i = 1; i <= array->length(); i++) {
348
    if (i < array->length()) value = GetScalarElement(array, i);
349
    bool values_are_nan = std::isnan(previous_value) && std::isnan(value);
350 351
    if (i != array->length() && (previous_value == value || values_are_nan) &&
        is_the_hole(previous_value) == is_the_hole(value)) {
352 353 354 355 356 357 358 359 360
      continue;
    }
    os << "\n";
    std::stringstream ss;
    ss << previous_index;
    if (previous_index != i - 1) {
      ss << '-' << (i - 1);
    }
    os << std::setw(12) << ss.str() << ": ";
361
    if (print_the_hole && is_the_hole(previous_value)) {
362 363 364 365 366 367
      os << "<the_hole>";
    } else {
      os << previous_value;
    }
    previous_index = i;
    previous_value = value;
368 369 370 371
  }
}


372
void JSObject::PrintElements(std::ostream& os) {  // NOLINT
373 374
  // Don't call GetElementsKind, its validation code can cause the printer to
  // fail when debugging.
375
  if (elements()->length() == 0) return;
376
  switch (map()->elements_kind()) {
377 378 379
    case FAST_HOLEY_SMI_ELEMENTS:
    case FAST_SMI_ELEMENTS:
    case FAST_HOLEY_ELEMENTS:
380 381
    case FAST_ELEMENTS:
    case FAST_STRING_WRAPPER_ELEMENTS: {
382
      // Print in array notation for non-sparse arrays.
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401
      FixedArray* array = FixedArray::cast(elements());
      Object* previous_value = array->get(0);
      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;
402 403 404
      }
      break;
    }
405
    case FAST_HOLEY_DOUBLE_ELEMENTS:
406
    case FAST_DOUBLE_ELEMENTS: {
407
      DoPrintElements<FixedDoubleArray, true>(os, elements());
408 409
      break;
    }
410

411 412 413 414
#define PRINT_ELEMENTS(Kind, Type)                \
  case Kind: {                                    \
    DoPrintElements<Type, false>(os, elements()); \
    break;                                        \
415
  }
416

417 418 419 420 421 422 423 424 425
      PRINT_ELEMENTS(UINT8_ELEMENTS, FixedUint8Array)
      PRINT_ELEMENTS(UINT8_CLAMPED_ELEMENTS, FixedUint8ClampedArray)
      PRINT_ELEMENTS(INT8_ELEMENTS, FixedInt8Array)
      PRINT_ELEMENTS(UINT16_ELEMENTS, FixedUint16Array)
      PRINT_ELEMENTS(INT16_ELEMENTS, FixedInt16Array)
      PRINT_ELEMENTS(UINT32_ELEMENTS, FixedUint32Array)
      PRINT_ELEMENTS(INT32_ELEMENTS, FixedInt32Array)
      PRINT_ELEMENTS(FLOAT32_ELEMENTS, FixedFloat32Array)
      PRINT_ELEMENTS(FLOAT64_ELEMENTS, FixedFloat64Array)
426 427 428

#undef PRINT_ELEMENTS

429
    case DICTIONARY_ELEMENTS:
430
    case SLOW_STRING_WRAPPER_ELEMENTS:
431
      SeededNumberDictionary::cast(elements())->Print(os);
432
      break;
433 434
    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
435
      FixedArray* p = FixedArray::cast(elements());
436
      os << "\n   parameter map:";
437
      for (int i = 2; i < p->length(); i++) {
438
        os << " " << (i - 2) << ":" << Brief(p->get(i));
439
      }
440
      os << "\n   context: " << Brief(p->get(0))
441
         << "\n   arguments: " << Brief(p->get(1));
442 443
      break;
    }
444 445
    case NO_ELEMENTS:
      break;
446 447 448 449
  }
}


450 451 452
static void JSObjectPrintHeader(std::ostream& os, JSObject* obj,
                                const char* id) {  // NOLINT
  obj->PrintHeader(os, id);
453 454
  // Don't call GetElementsKind, its validation code can cause the printer to
  // fail when debugging.
455 456 457 458 459
  os << "\n - map = " << reinterpret_cast<void*>(obj->map()) << " [";
  if (obj->HasFastProperties()) {
    os << "FastProperties";
  } else {
    os << "DictionaryProperties";
460 461 462
  }
  PrototypeIterator iter(obj->GetIsolate(), obj);
  os << "]\n - prototype = " << reinterpret_cast<void*>(iter.GetCurrent());
463 464 465 466
  os << "\n - elements = " << Brief(obj->elements()) << " ["
     << ElementsKindToString(obj->map()->elements_kind());
  if (obj->elements()->map() == obj->GetHeap()->fixed_cow_array_map()) {
    os << " (COW)";
467
  }
468
  os << "]";
469 470 471
  if (obj->GetInternalFieldCount() > 0) {
    os << "\n - internal fields: " << obj->GetInternalFieldCount();
  }
472 473 474
}


475 476
static void JSObjectPrintBody(std::ostream& os, JSObject* obj,  // NOLINT
                              bool print_elements = true) {
477
  os << "\n - properties = {";
478
  obj->PrintProperties(os);
479
  os << "\n }\n";
480 481 482 483 484
  if (print_elements && obj->elements()->length() > 0) {
    os << " - elements = {";
    obj->PrintElements(os);
    os << "\n }\n";
  }
485 486 487 488 489 490 491 492
  int internal_fields = obj->GetInternalFieldCount();
  if (internal_fields > 0) {
    os << " - internal fields = {";
    for (int i = 0; i < internal_fields; i++) {
      os << "\n    " << Brief(obj->GetInternalField(i));
    }
    os << "\n }\n";
  }
493 494 495
}


496
void JSObject::JSObjectPrint(std::ostream& os) {  // NOLINT
497 498 499 500 501 502 503
  JSObjectPrintHeader(os, this, nullptr);
  JSObjectPrintBody(os, this);
}

void JSArray::JSArrayPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSArray");
  os << "\n - length = " << Brief(this->length());
504 505 506 507
  JSObjectPrintBody(os, this);
}


508 509 510 511 512 513 514
void JSRegExp::JSRegExpPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSRegExp");
  os << "\n - data = " << Brief(data());
  JSObjectPrintBody(os, this);
}


515
void Symbol::SymbolPrint(std::ostream& os) {  // NOLINT
516
  HeapObject::PrintHeader(os, "Symbol");
517
  os << "\n - hash: " << Hash();
518
  os << "\n - name: " << Brief(name());
519
  if (name()->IsUndefined(GetIsolate())) {
520 521
    os << " (" << PrivateSymbolToName() << ")";
  }
522
  os << "\n - private: " << is_private();
523
  os << "\n";
524 525 526
}


527
void Map::MapPrint(std::ostream& os) {  // NOLINT
528
  HeapObject::PrintHeader(os, "Map");
529 530
  os << "\n - type: " << instance_type();
  os << "\n - instance size: " << instance_size();
531
  if (IsJSObjectMap()) {
532
    os << "\n - inobject properties: " << GetInObjectProperties();
533
  }
534 535
  os << "\n - elements kind: " << ElementsKindToString(elements_kind());
  os << "\n - unused property fields: " << unused_property_fields();
536 537 538 539 540 541
  os << "\n - enum length: ";
  if (EnumLength() == kInvalidEnumCacheSentinel) {
    os << "invalid";
  } else {
    os << EnumLength();
  }
542 543 544
  if (is_deprecated()) os << "\n - deprecated_map";
  if (is_stable()) os << "\n - stable_map";
  if (is_dictionary_map()) os << "\n - dictionary_map";
545
  if (has_hidden_prototype()) os << "\n - has_hidden_prototype";
546
  if (has_named_interceptor()) os << "\n - named_interceptor";
547 548 549 550 551 552
  if (has_indexed_interceptor()) os << "\n - indexed_interceptor";
  if (is_undetectable()) os << "\n - undetectable";
  if (is_callable()) os << "\n - callable";
  if (is_constructor()) os << "\n - constructor";
  if (is_access_check_needed()) os << "\n - access_check_needed";
  if (!is_extensible()) os << "\n - non-extensible";
553
  if (is_prototype_map()) {
554 555
    os << "\n - prototype_map";
    os << "\n - prototype info: " << Brief(prototype_info());
556
  } else {
557
    os << "\n - back pointer: " << Brief(GetBackPointer());
558
  }
559 560 561
  os << "\n - instance descriptors " << (owns_descriptors() ? "(own) " : "")
     << "#" << NumberOfOwnDescriptors() << ": "
     << Brief(instance_descriptors());
562 563 564
  if (FLAG_unbox_double_fields) {
    os << "\n - layout descriptor: " << Brief(layout_descriptor());
  }
565 566 567 568 569
  int nof_transitions = TransitionArray::NumberOfTransitions(raw_transitions());
  if (nof_transitions > 0) {
    os << "\n - transitions #" << nof_transitions << ": "
       << Brief(raw_transitions());
    TransitionArray::PrintTransitions(os, raw_transitions(), false);
570
  }
571
  os << "\n - prototype: " << Brief(prototype());
572
  os << "\n - constructor: " << Brief(GetConstructor());
573 574
  os << "\n - code cache: " << Brief(code_cache());
  os << "\n - dependent code: " << Brief(dependent_code());
575
  os << "\n - construction counter: " << construction_counter();
576
  os << "\n";
577 578 579
}


580
void TypeFeedbackInfo::TypeFeedbackInfoPrint(std::ostream& os) {  // NOLINT
581
  HeapObject::PrintHeader(os, "TypeFeedbackInfo");
582
  os << "\n - ic_total_count: " << ic_total_count()
583 584
     << ", ic_with_type_info_count: " << ic_with_type_info_count()
     << ", ic_generic_count: " << ic_generic_count() << "\n";
585 586 587
}


588 589
void AliasedArgumentsEntry::AliasedArgumentsEntryPrint(
    std::ostream& os) {  // NOLINT
590 591
  HeapObject::PrintHeader(os, "AliasedArgumentsEntry");
  os << "\n - aliased_context_slot: " << aliased_context_slot();
592 593 594
}


595
void FixedArray::FixedArrayPrint(std::ostream& os) {  // NOLINT
596
  HeapObject::PrintHeader(os, "FixedArray");
597
  os << "\n - length: " << length();
598
  for (int i = 0; i < length(); i++) {
599
    os << "\n  [" << i << "]: " << Brief(get(i));
600
  }
601
  os << "\n";
602 603 604
}


605
void FixedDoubleArray::FixedDoubleArrayPrint(std::ostream& os) {  // NOLINT
606
  HeapObject::PrintHeader(os, "FixedDoubleArray");
607
  os << "\n - length: " << length();
608
  for (int i = 0; i < length(); i++) {
609
    os << "\n  [" << i << "]: ";
610
    if (is_the_hole(i)) {
611
      os << "<the hole>";
612
    } else {
613
      os << get_scalar(i);
614
    }
615
  }
616
  os << "\n";
617 618 619
}


620 621
void TransitionArray::TransitionArrayPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "TransitionArray");
622
  os << "\n - capacity: " << length();
623 624 625 626 627 628 629 630 631
  for (int i = 0; i < length(); i++) {
    os << "\n  [" << i << "]: " << Brief(get(i));
    if (i == kNextLinkIndex) os << " (next link)";
    if (i == kPrototypeTransitionsIndex) os << " (prototype transitions)";
    if (i == kTransitionLengthIndex) os << " (number of transitions)";
  }
  os << "\n";
}

632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
template void FeedbackVectorSpecBase<StaticFeedbackVectorSpec>::Print();
template void FeedbackVectorSpecBase<FeedbackVectorSpec>::Print();

template <typename Derived>
void FeedbackVectorSpecBase<Derived>::Print() {
  OFStream os(stdout);
  FeedbackVectorSpecPrint(os);
  os << std::flush;
}

template <typename Derived>
void FeedbackVectorSpecBase<Derived>::FeedbackVectorSpecPrint(
    std::ostream& os) {  // NOLINT
  int slot_count = This()->slots();
  os << " - slot_count: " << slot_count;
  if (slot_count == 0) {
    os << " (empty)\n";
    return;
  }

  for (int slot = 0, name_index = 0; slot < slot_count;) {
    FeedbackVectorSlotKind kind = This()->GetKind(slot);
    int entry_size = TypeFeedbackMetadata::GetSlotSize(kind);
    DCHECK_LT(0, entry_size);

    os << "\n Slot #" << slot << " " << kind;
    if (TypeFeedbackMetadata::SlotRequiresName(kind)) {
      os << ", " << Brief(*This()->GetName(name_index++));
    }

    slot += entry_size;
  }
  os << "\n";
}
666

667 668 669 670 671 672 673 674 675 676
void TypeFeedbackMetadata::Print() {
  OFStream os(stdout);
  TypeFeedbackMetadataPrint(os);
  os << std::flush;
}


void TypeFeedbackMetadata::TypeFeedbackMetadataPrint(
    std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "TypeFeedbackMetadata");
677
  os << "\n - length: " << length();
678 679 680 681
  if (length() == 0) {
    os << " (empty)\n";
    return;
  }
682
  os << "\n - slot_count: " << slot_count();
683 684 685 686 687 688

  TypeFeedbackMetadataIterator iter(this);
  while (iter.HasNext()) {
    FeedbackVectorSlot slot = iter.Next();
    FeedbackVectorSlotKind kind = iter.kind();
    os << "\n Slot " << slot << " " << kind;
689 690 691
    if (TypeFeedbackMetadata::SlotRequiresName(kind)) {
      os << ", " << Brief(iter.name());
    }
692 693 694 695 696
  }
  os << "\n";
}


697 698 699 700 701 702 703 704 705
void TypeFeedbackVector::Print() {
  OFStream os(stdout);
  TypeFeedbackVectorPrint(os);
  os << std::flush;
}


void TypeFeedbackVector::TypeFeedbackVectorPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "TypeFeedbackVector");
706
  os << "\n - length: " << length();
707 708 709 710 711
  if (length() == 0) {
    os << " (empty)\n";
    return;
  }

712
  TypeFeedbackMetadataIterator iter(metadata());
713 714 715 716
  while (iter.HasNext()) {
    FeedbackVectorSlot slot = iter.Next();
    FeedbackVectorSlotKind kind = iter.kind();

717 718 719 720 721
    os << "\n Slot " << slot << " " << kind;
    if (TypeFeedbackMetadata::SlotRequiresName(kind)) {
      os << ", " << Brief(iter.name());
    }
    os << " ";
722 723 724 725 726 727
    switch (kind) {
      case FeedbackVectorSlotKind::LOAD_IC: {
        LoadICNexus nexus(this, slot);
        os << Code::ICState2String(nexus.StateFromFeedback());
        break;
      }
728 729 730 731 732
      case FeedbackVectorSlotKind::LOAD_GLOBAL_IC: {
        LoadGlobalICNexus nexus(this, slot);
        os << Code::ICState2String(nexus.StateFromFeedback());
        break;
      }
733 734 735 736
      case FeedbackVectorSlotKind::KEYED_LOAD_IC: {
        KeyedLoadICNexus nexus(this, slot);
        os << Code::ICState2String(nexus.StateFromFeedback());
        break;
737
      }
738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
      case FeedbackVectorSlotKind::CALL_IC: {
        CallICNexus nexus(this, slot);
        os << Code::ICState2String(nexus.StateFromFeedback());
        break;
      }
      case FeedbackVectorSlotKind::STORE_IC: {
        StoreICNexus nexus(this, slot);
        os << Code::ICState2String(nexus.StateFromFeedback());
        break;
      }
      case FeedbackVectorSlotKind::KEYED_STORE_IC: {
        KeyedStoreICNexus nexus(this, slot);
        os << Code::ICState2String(nexus.StateFromFeedback());
        break;
      }
753 754 755 756 757 758 759 760 761 762
      case FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC: {
        BinaryOpICNexus nexus(this, slot);
        os << Code::ICState2String(nexus.StateFromFeedback());
        break;
      }
      case FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC: {
        CompareICNexus nexus(this, slot);
        os << Code::ICState2String(nexus.StateFromFeedback());
        break;
      }
763 764 765 766 767 768 769
      case FeedbackVectorSlotKind::GENERAL:
        break;
      case FeedbackVectorSlotKind::INVALID:
      case FeedbackVectorSlotKind::KINDS_NUMBER:
        UNREACHABLE();
        break;
    }
770

771 772 773 774
    int entry_size = iter.entry_size();
    for (int i = 0; i < entry_size; i++) {
      int index = GetIndex(slot) + i;
      os << "\n  [" << index << "]: " << Brief(get(index));
775 776 777 778 779 780
    }
  }
  os << "\n";
}


781
void JSValue::JSValuePrint(std::ostream& os) {  // NOLINT
782 783 784
  JSObjectPrintHeader(os, this, "JSValue");
  os << "\n - value = " << Brief(value());
  JSObjectPrintBody(os, this);
785 786 787
}


788
void JSMessageObject::JSMessageObjectPrint(std::ostream& os) {  // NOLINT
789 790
  JSObjectPrintHeader(os, this, "JSMessageObject");
  os << "\n - type: " << type();
791
  os << "\n - arguments: " << Brief(argument());
792 793 794 795
  os << "\n - start_position: " << start_position();
  os << "\n - end_position: " << end_position();
  os << "\n - script: " << Brief(script());
  os << "\n - stack_frames: " << Brief(stack_frames());
796
  JSObjectPrintBody(os, this);
797 798 799
}


800
void String::StringPrint(std::ostream& os) {  // NOLINT
801
  if (StringShape(this).IsInternalized()) {
802
    os << "#";
803
  } else if (StringShape(this).IsCons()) {
804
    os << "c\"";
805
  } else {
806
    os << "\"";
807 808 809 810 811 812 813 814 815 816
  }

  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++) {
817
    os << AsUC16(Get(i));
818 819
  }
  if (len != length()) {
820
    os << truncated_epilogue;
821 822
  }

823
  if (!StringShape(this).IsInternalized()) os << "\"";
824 825 826
}


827
void Name::NamePrint(std::ostream& os) {  // NOLINT
828
  if (IsString()) {
829
    String::cast(this)->StringPrint(os);
830
  } else {
831
    os << Brief(this);
832
  }
833 834 835
}


836 837 838 839
static const char* const weekdays[] = {
  "???", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};

840

841
void JSDate::JSDatePrint(std::ostream& os) {  // NOLINT
842 843
  JSObjectPrintHeader(os, this, "JSDate");
  os << "\n - value = " << Brief(value());
844
  if (!year()->IsSmi()) {
845
    os << "\n - time = NaN\n";
846
  } else {
847
    // TODO(svenpanne) Add some basic formatting to our streams.
848
    ScopedVector<char> buf(100);
849
    SNPrintF(
850
        buf, "\n - time = %s %04d/%02d/%02d %02d:%02d:%02d\n",
851 852 853 854 855 856 857 858
        weekdays[weekday()->IsSmi() ? Smi::cast(weekday())->value() + 1 : 0],
        year()->IsSmi() ? Smi::cast(year())->value() : -1,
        month()->IsSmi() ? Smi::cast(month())->value() : -1,
        day()->IsSmi() ? Smi::cast(day())->value() : -1,
        hour()->IsSmi() ? Smi::cast(hour())->value() : -1,
        min()->IsSmi() ? Smi::cast(min())->value() : -1,
        sec()->IsSmi() ? Smi::cast(sec())->value() : -1);
    os << buf.start();
859
  }
860
  JSObjectPrintBody(os, this);
861 862 863
}


864
void JSProxy::JSProxyPrint(std::ostream& os) {  // NOLINT
865
  HeapObject::PrintHeader(os, "JSProxy");
866
  os << "\n - map = " << reinterpret_cast<void*>(map());
867 868 869 870
  os << "\n - target = ";
  target()->ShortPrint(os);
  os << "\n - handler = ";
  handler()->ShortPrint(os);
871
  os << "\n - hash = ";
872
  hash()->ShortPrint(os);
873
  os << "\n";
874 875 876
}


877
void JSSet::JSSetPrint(std::ostream& os) {  // NOLINT
878
  JSObjectPrintHeader(os, this, "JSSet");
879
  os << " - table = " << Brief(table());
880
  JSObjectPrintBody(os, this);
881 882 883
}


884
void JSMap::JSMapPrint(std::ostream& os) {  // NOLINT
885
  JSObjectPrintHeader(os, this, "JSMap");
886
  os << " - table = " << Brief(table());
887
  JSObjectPrintBody(os, this);
888 889 890
}


891
template <class Derived, class TableType>
892 893 894
void
OrderedHashTableIterator<Derived, TableType>::OrderedHashTableIteratorPrint(
    std::ostream& os) {  // NOLINT
895
  os << "\n - table = " << Brief(table());
896 897 898
  os << "\n - index = " << Brief(index());
  os << "\n - kind = " << Brief(kind());
  os << "\n";
899 900 901
}


902 903
template void OrderedHashTableIterator<
    JSSetIterator,
904
    OrderedHashSet>::OrderedHashTableIteratorPrint(std::ostream& os);  // NOLINT
905 906


907 908
template void OrderedHashTableIterator<
    JSMapIterator,
909
    OrderedHashMap>::OrderedHashTableIteratorPrint(std::ostream& os);  // NOLINT
910 911


912
void JSSetIterator::JSSetIteratorPrint(std::ostream& os) {  // NOLINT
913
  JSObjectPrintHeader(os, this, "JSSetIterator");
914
  OrderedHashTableIteratorPrint(os);
915 916 917
}


918
void JSMapIterator::JSMapIteratorPrint(std::ostream& os) {  // NOLINT
919
  JSObjectPrintHeader(os, this, "JSMapIterator");
920
  OrderedHashTableIteratorPrint(os);
921 922 923
}


924
void JSWeakMap::JSWeakMapPrint(std::ostream& os) {  // NOLINT
925 926 927
  JSObjectPrintHeader(os, this, "JSWeakMap");
  os << "\n - table = " << Brief(table());
  JSObjectPrintBody(os, this);
928 929 930
}


931
void JSWeakSet::JSWeakSetPrint(std::ostream& os) {  // NOLINT
932 933 934
  JSObjectPrintHeader(os, this, "JSWeakSet");
  os << "\n - table = " << Brief(table());
  JSObjectPrintBody(os, this);
935 936 937
}


938
void JSArrayBuffer::JSArrayBufferPrint(std::ostream& os) {  // NOLINT
939 940 941
  JSObjectPrintHeader(os, this, "JSArrayBuffer");
  os << "\n - backing_store = " << backing_store();
  os << "\n - byte_length = " << Brief(byte_length());
942
  if (was_neutered()) os << " - neutered\n";
943
  JSObjectPrintBody(os, this, !was_neutered());
944 945 946
}


947
void JSTypedArray::JSTypedArrayPrint(std::ostream& os) {  // NOLINT
948 949
  JSObjectPrintHeader(os, this, "JSTypedArray");
  os << "\n - buffer = " << Brief(buffer());
950 951 952
  os << "\n - byte_offset = " << Brief(byte_offset());
  os << "\n - byte_length = " << Brief(byte_length());
  os << "\n - length = " << Brief(length());
953
  if (WasNeutered()) os << " - neutered\n";
954
  JSObjectPrintBody(os, this, !WasNeutered());
955 956 957
}


958
void JSDataView::JSDataViewPrint(std::ostream& os) {  // NOLINT
959 960
  JSObjectPrintHeader(os, this, "JSDataView");
  os << "\n - buffer =" << Brief(buffer());
961 962
  os << "\n - byte_offset = " << Brief(byte_offset());
  os << "\n - byte_length = " << Brief(byte_length());
963
  if (WasNeutered()) os << " - neutered\n";
964
  JSObjectPrintBody(os, this, !WasNeutered());
965 966 967
}


968 969 970 971 972 973 974 975 976
void JSBoundFunction::JSBoundFunctionPrint(std::ostream& os) {  // NOLINT
  JSObjectPrintHeader(os, this, "JSBoundFunction");
  os << "\n - bound_target_function = " << Brief(bound_target_function());
  os << "\n - bound_this = " << Brief(bound_this());
  os << "\n - bound_arguments = " << Brief(bound_arguments());
  JSObjectPrintBody(os, this);
}


977
void JSFunction::JSFunctionPrint(std::ostream& os) {  // NOLINT
978 979
  JSObjectPrintHeader(os, this, "Function");
  os << "\n - initial_map = ";
980 981
  if (has_initial_map()) os << Brief(initial_map());
  os << "\n - shared_info = " << Brief(shared());
982
  os << "\n - name = " << Brief(shared()->name());
983 984
  os << "\n - formal_parameter_count = "
     << shared()->internal_formal_parameter_count();
985 986
  if (shared()->is_generator()) {
    os << "\n   - generator";
987 988
  } else if (shared()->is_async()) {
    os << "\n   - async";
989
  }
990
  os << "\n - context = " << Brief(context());
991
  os << "\n - literals = " << Brief(literals());
992
  os << "\n - code = " << Brief(code());
993
  JSObjectPrintBody(os, this);
994 995 996
}


997
void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) {  // NOLINT
998
  HeapObject::PrintHeader(os, "SharedFunctionInfo");
999 1000 1001 1002
  os << "\n - name = " << Brief(name());
  os << "\n - formal_parameter_count = " << internal_formal_parameter_count();
  os << "\n - expected_nof_properties = " << expected_nof_properties();
  os << "\n - ast_node_count = " << ast_node_count();
1003 1004 1005
  os << "\n - instance class name = ";
  instance_class_name()->Print(os);
  os << "\n - code = " << Brief(code());
1006
  if (HasSourceCode()) {
1007
    os << "\n - source code = ";
1008 1009 1010
    String* source = String::cast(Script::cast(script())->source());
    int start = start_position();
    int length = end_position() - start;
1011
    std::unique_ptr<char[]> source_string = source->ToCString(
rmcilroy's avatar
rmcilroy committed
1012
        DISALLOW_NULLS, FAST_STRING_TRAVERSAL, start, length, NULL);
1013
    os << source_string.get();
1014
  }
1015
  // Script files are often large, hard to read.
1016 1017
  // os << "\n - script =";
  // script()->Print(os);
1018 1019 1020 1021 1022 1023 1024
  if (is_named_expression()) {
    os << "\n - named expression";
  } else if (is_anonymous_expression()) {
    os << "\n - anonymous expression";
  } else if (is_declaration()) {
    os << "\n - declaration";
  }
1025 1026 1027 1028 1029
  os << "\n - function token position = " << function_token_position();
  os << "\n - start position = " << start_position();
  os << "\n - end position = " << end_position();
  os << "\n - debug info = " << Brief(debug_info());
  os << "\n - length = " << length();
1030
  os << "\n - num_literals = " << num_literals();
1031
  os << "\n - optimized_code_map = " << Brief(optimized_code_map());
1032 1033
  os << "\n - feedback_metadata = ";
  feedback_metadata()->TypeFeedbackMetadataPrint(os);
1034 1035 1036
  if (HasBytecodeArray()) {
    os << "\n - bytecode_array = " << bytecode_array();
  }
1037
  os << "\n";
1038 1039 1040
}


1041
void JSGlobalProxy::JSGlobalProxyPrint(std::ostream& os) {  // NOLINT
1042 1043 1044 1045
  os << "global_proxy ";
  JSObjectPrint(os);
  os << "native context : " << Brief(native_context());
  os << "\n";
1046 1047 1048
}


1049
void JSGlobalObject::JSGlobalObjectPrint(std::ostream& os) {  // NOLINT
1050 1051 1052 1053
  os << "global ";
  JSObjectPrint(os);
  os << "native context : " << Brief(native_context());
  os << "\n";
1054 1055 1056
}


1057
void Cell::CellPrint(std::ostream& os) {  // NOLINT
1058
  HeapObject::PrintHeader(os, "Cell");
1059
  os << "\n - value: " << Brief(value());
1060
  os << "\n";
1061 1062 1063
}


1064
void PropertyCell::PropertyCellPrint(std::ostream& os) {  // NOLINT
1065
  HeapObject::PrintHeader(os, "PropertyCell");
1066
  os << "\n - value: " << Brief(value());
1067
  os << "\n - details: " << property_details();
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107
  PropertyCellType cell_type = property_details().cell_type();
  os << "\n - cell_type: ";
  if (value()->IsTheHole(GetIsolate())) {
    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;
    }
  }
1108
  os << "\n";
1109 1110 1111
}


ulan@chromium.org's avatar
ulan@chromium.org committed
1112 1113
void WeakCell::WeakCellPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "WeakCell");
1114 1115 1116 1117 1118
  if (cleared()) {
    os << "\n - cleared";
  } else {
    os << "\n - value: " << Brief(value());
  }
1119
  os << "\n";
ulan@chromium.org's avatar
ulan@chromium.org committed
1120 1121 1122
}


1123
void Code::CodePrint(std::ostream& os) {  // NOLINT
1124
  HeapObject::PrintHeader(os, "Code");
1125
  os << "\n";
1126 1127
#ifdef ENABLE_DISASSEMBLER
  if (FLAG_use_verbose_printer) {
1128
    Disassemble(NULL, os);
1129 1130 1131 1132 1133
  }
#endif
}


1134
void Foreign::ForeignPrint(std::ostream& os) {  // NOLINT
1135
  os << "foreign address : " << foreign_address();
1136
  os << "\n";
1137 1138 1139
}


1140 1141
void AccessorInfo::AccessorInfoPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "AccessorInfo");
1142
  os << "\n - name: " << Brief(name());
1143
  os << "\n - flag: " << flag();
1144 1145
  os << "\n - getter: " << Brief(getter());
  os << "\n - setter: " << Brief(setter());
1146
  os << "\n - js_getter: " << Brief(js_getter());
1147 1148
  os << "\n - data: " << Brief(data());
  os << "\n";
1149 1150 1151
}


1152
void Box::BoxPrint(std::ostream& os) {  // NOLINT
1153 1154 1155 1156 1157
  HeapObject::PrintHeader(os, "Box");
  os << "\n - value: " << Brief(value());
  os << "\n";
}

1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
void PromiseContainer::PromiseContainerPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "PromiseContainer");
  os << "\n - thenable: " << Brief(thenable());
  os << "\n - then: " << Brief(then());
  os << "\n - resolve: " << Brief(resolve());
  os << "\n - reject: " << Brief(reject());
  os << "\n - before debug event: " << Brief(before_debug_event());
  os << "\n - after debug event: " << Brief(after_debug_event());
  os << "\n";
}

1169 1170
void Module::ModulePrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "Module");
1171
  os << "\n - code: " << Brief(code());
1172
  os << "\n - exports: " << Brief(exports());
1173
  os << "\n - requested_modules: " << Brief(requested_modules());
1174
  os << "\n - evaluated: " << evaluated();
1175 1176
  os << "\n";
}
1177

1178 1179 1180
void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "PrototypeInfo");
  os << "\n - prototype users: " << Brief(prototype_users());
1181
  os << "\n - registry slot: " << registry_slot();
1182 1183 1184 1185
  os << "\n - validity cell: " << Brief(validity_cell());
  os << "\n";
}

1186 1187
void ContextExtension::ContextExtensionPrint(std::ostream& os) {  // NOLINT
  HeapObject::PrintHeader(os, "ContextExtension");
1188 1189 1190 1191 1192 1193
  os << "\n - scope_info: " << Brief(scope_info());
  os << "\n - extension: " << Brief(extension());
  os << "\n";
}


1194
void AccessorPair::AccessorPairPrint(std::ostream& os) {  // NOLINT
1195 1196 1197 1198 1199 1200 1201
  HeapObject::PrintHeader(os, "AccessorPair");
  os << "\n - getter: " << Brief(getter());
  os << "\n - setter: " << Brief(setter());
  os << "\n";
}


1202
void AccessCheckInfo::AccessCheckInfoPrint(std::ostream& os) {  // NOLINT
1203
  HeapObject::PrintHeader(os, "AccessCheckInfo");
1204
  os << "\n - callback: " << Brief(callback());
1205 1206
  os << "\n - named_interceptor: " << Brief(named_interceptor());
  os << "\n - indexed_interceptor: " << Brief(indexed_interceptor());
1207 1208 1209 1210 1211
  os << "\n - data: " << Brief(data());
  os << "\n";
}


1212
void InterceptorInfo::InterceptorInfoPrint(std::ostream& os) {  // NOLINT
1213 1214 1215 1216 1217 1218 1219 1220
  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";
1221 1222 1223
}


1224
void CallHandlerInfo::CallHandlerInfoPrint(std::ostream& os) {  // NOLINT
1225 1226 1227 1228
  HeapObject::PrintHeader(os, "CallHandlerInfo");
  os << "\n - callback: " << Brief(callback());
  os << "\n - data: " << Brief(data());
  os << "\n";
1229 1230 1231
}


1232 1233
void FunctionTemplateInfo::FunctionTemplateInfoPrint(
    std::ostream& os) {  // NOLINT
1234 1235 1236
  HeapObject::PrintHeader(os, "FunctionTemplateInfo");
  os << "\n - class name: " << Brief(class_name());
  os << "\n - tag: " << Brief(tag());
1237
  os << "\n - serial_number: " << Brief(serial_number());
1238
  os << "\n - property_list: " << Brief(property_list());
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250
  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());
  os << "\n - hidden_prototype: " << (hidden_prototype() ? "true" : "false");
  os << "\n - undetectable: " << (undetectable() ? "true" : "false");
  os << "\n - need_access_check: " << (needs_access_check() ? "true" : "false");
1251
  os << "\n - instantiated: " << (instantiated() ? "true" : "false");
1252 1253 1254 1255
  os << "\n";
}


1256
void ObjectTemplateInfo::ObjectTemplateInfoPrint(std::ostream& os) {  // NOLINT
1257
  HeapObject::PrintHeader(os, "ObjectTemplateInfo");
1258 1259
  os << "\n - tag: " << Brief(tag());
  os << "\n - serial_number: " << Brief(serial_number());
1260 1261 1262
  os << "\n - property_list: " << Brief(property_list());
  os << "\n - property_accessors: " << Brief(property_accessors());
  os << "\n - constructor: " << Brief(constructor());
1263 1264
  os << "\n - internal_field_count: " << internal_field_count();
  os << "\n - immutable_proto: " << (immutable_proto() ? "true" : "false");
1265 1266 1267 1268
  os << "\n";
}


1269
void AllocationSite::AllocationSitePrint(std::ostream& os) {  // NOLINT
1270
  HeapObject::PrintHeader(os, "AllocationSite");
1271
  os << "\n - weak_next: " << Brief(weak_next());
1272 1273 1274 1275 1276 1277 1278 1279 1280
  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: ";
1281 1282
  if (transition_info()->IsSmi()) {
    ElementsKind kind = GetElementsKind();
1283
    os << "Array allocation with ElementsKind " << ElementsKindToString(kind);
1284
  } else if (transition_info()->IsJSArray()) {
1285 1286 1287
    os << "Array literal " << Brief(transition_info());
  } else {
    os << "unknown transition_info" << Brief(transition_info());
1288
  }
1289
  os << "\n";
1290 1291 1292
}


1293
void AllocationMemento::AllocationMementoPrint(std::ostream& os) {  // NOLINT
1294
  HeapObject::PrintHeader(os, "AllocationMemento");
1295
  os << "\n - allocation site: ";
1296
  if (IsValid()) {
1297
    GetAllocationSite()->Print(os);
1298
  } else {
1299
    os << "<invalid>\n";
1300 1301 1302 1303
  }
}


1304
void Script::ScriptPrint(std::ostream& os) {  // NOLINT
1305 1306 1307
  HeapObject::PrintHeader(os, "Script");
  os << "\n - source: " << Brief(source());
  os << "\n - name: " << Brief(name());
1308 1309 1310 1311
  os << "\n - line_offset: " << line_offset();
  os << "\n - column_offset: " << column_offset();
  os << "\n - type: " << type();
  os << "\n - id: " << id();
1312 1313 1314 1315 1316
  os << "\n - context data: " << Brief(context_data());
  os << "\n - wrapper: " << Brief(wrapper());
  os << "\n - compilation type: " << compilation_type();
  os << "\n - line ends: " << Brief(line_ends());
  os << "\n - eval from shared: " << Brief(eval_from_shared());
1317
  os << "\n - eval from position: " << eval_from_position();
1318
  os << "\n - shared function infos: " << Brief(shared_function_infos());
1319 1320 1321 1322
  os << "\n";
}


1323
void DebugInfo::DebugInfoPrint(std::ostream& os) {  // NOLINT
1324 1325
  HeapObject::PrintHeader(os, "DebugInfo");
  os << "\n - shared: " << Brief(shared());
1326
  os << "\n - debug bytecode array: " << Brief(debug_bytecode_array());
1327 1328 1329 1330 1331
  os << "\n - break_points: ";
  break_points()->Print(os);
}


1332
void BreakPointInfo::BreakPointInfoPrint(std::ostream& os) {  // NOLINT
1333
  HeapObject::PrintHeader(os, "BreakPointInfo");
1334
  os << "\n - source_position: " << source_position();
1335 1336 1337 1338 1339
  os << "\n - break_point_objects: " << Brief(break_point_objects());
  os << "\n";
}


1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
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;
  }
}


void LayoutDescriptor::Print() {
  OFStream os(stdout);
  this->Print(os);
  os << std::flush;
}


void LayoutDescriptor::Print(std::ostream& os) {  // NOLINT
  os << "Layout descriptor: ";
1358
  if (IsOddball() && IsUninitialized(HeapObject::cast(this)->GetIsolate())) {
1359 1360 1361 1362 1363 1364 1365 1366
    os << "<uninitialized>";
  } else if (IsFastPointerLayout()) {
    os << "<all tagged>";
  } else if (IsSmi()) {
    os << "fast";
    PrintBitMask(os, static_cast<uint32_t>(Smi::cast(this)->value()));
  } else {
    os << "slow";
1367
    int len = length();
1368 1369 1370 1371 1372 1373 1374 1375 1376
    for (int i = 0; i < len; i++) {
      if (i > 0) os << " |";
      PrintBitMask(os, get_scalar(i));
    }
  }
  os << "\n";
}


1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388
#endif  // OBJECT_PRINT


#if TRACE_MAPS


void Name::NameShortPrint() {
  if (this->IsString()) {
    PrintF("%s", String::cast(this)->ToCString().get());
  } else {
    DCHECK(this->IsSymbol());
    Symbol* s = Symbol::cast(this);
1389
    if (s->name()->IsUndefined(GetIsolate())) {
1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403
      PrintF("#<%s>", s->PrivateSymbolToName());
    } else {
      PrintF("<%s>", String::cast(s->name())->ToCString().get());
    }
  }
}


int Name::NameShortPrint(Vector<char> str) {
  if (this->IsString()) {
    return SNPrintF(str, "%s", String::cast(this)->ToCString().get());
  } else {
    DCHECK(this->IsSymbol());
    Symbol* s = Symbol::cast(this);
1404
    if (s->name()->IsUndefined(GetIsolate())) {
1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
      return SNPrintF(str, "#<%s>", s->PrivateSymbolToName());
    } else {
      return SNPrintF(str, "<%s>", String::cast(s->name())->ToCString().get());
    }
  }
}


#endif  // TRACE_MAPS


1416
#if defined(DEBUG) || defined(OBJECT_PRINT)
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440
// 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 = NULL;
  if (buffer != NULL) delete[] buffer;
  buffer = new char[length() + 1];
  WriteToFlat(this, reinterpret_cast<uint8_t*>(buffer), 0, length());
  buffer[length()] = 0;
  return buffer;
}


void DescriptorArray::Print() {
  OFStream os(stdout);
  this->PrintDescriptors(os);
  os << std::flush;
}


void DescriptorArray::PrintDescriptors(std::ostream& os) {  // NOLINT
  HandleScope scope(GetIsolate());
1441
  os << "Descriptor array #" << number_of_descriptors();
1442 1443 1444
  for (int i = 0; i < number_of_descriptors(); i++) {
    Descriptor desc;
    Get(i, &desc);
1445
    os << "\n " << i << ": " << desc;
1446 1447 1448 1449 1450
  }
  os << "\n";
}


1451 1452
void TransitionArray::Print() {
  OFStream os(stdout);
1453
  TransitionArray::PrintTransitions(os, this);
1454
  os << "\n" << std::flush;
1455 1456 1457
}


1458
void TransitionArray::PrintTransitions(std::ostream& os, Object* transitions,
1459
                                       bool print_header) {  // NOLINT
1460
  int num_transitions = NumberOfTransitions(transitions);
1461
  if (print_header) {
1462
    os << "Transition array #" << num_transitions << ":";
1463
  }
1464 1465 1466
  for (int i = 0; i < num_transitions; i++) {
    Name* key = GetKey(transitions, i);
    Map* target = GetTarget(transitions, i);
1467
    os << "\n     ";
1468
#ifdef OBJECT_PRINT
1469
    key->NamePrint(os);
1470 1471 1472
#else
    key->ShortPrint(os);
#endif
1473
    os << ": ";
1474 1475
    Heap* heap = key->GetHeap();
    if (key == heap->nonextensible_symbol()) {
1476
      os << "(transition to non-extensible)";
1477
    } else if (key == heap->sealed_symbol()) {
1478
      os << "(transition to sealed)";
1479
    } else if (key == heap->frozen_symbol()) {
1480
      os << "(transition to frozen)";
1481
    } else if (key == heap->elements_transition_symbol()) {
1482
      os << "(transition to " << ElementsKindToString(target->elements_kind())
1483
         << ")";
ishell's avatar
ishell committed
1484 1485
    } else if (key == heap->strict_function_transition_symbol()) {
      os << " (transition to strict function)";
1486
    } else {
1487
      PropertyDetails details = GetTargetDetails(key, target);
1488
      os << "(transition to ";
1489
      if (details.location() == kDescriptor) {
1490 1491
        os << "immutable ";
      }
1492 1493
      os << (details.kind() == kData ? "data" : "accessor");
      if (details.location() == kDescriptor) {
1494 1495 1496
        Object* value =
            target->instance_descriptors()->GetValue(target->LastAdded());
        os << " " << Brief(value);
1497
      }
1498
      os << "), attrs: " << details.attributes();
1499
    }
1500
    os << " -> " << Brief(target);
1501 1502 1503 1504
  }
}


1505
void JSObject::PrintTransitions(std::ostream& os) {  // NOLINT
1506 1507 1508 1509 1510
  Object* transitions = map()->raw_transitions();
  int num_transitions = TransitionArray::NumberOfTransitions(transitions);
  if (num_transitions == 0) return;
  os << "\n - transitions";
  TransitionArray::PrintTransitions(os, transitions, false);
1511
}
1512
#endif  // defined(DEBUG) || defined(OBJECT_PRINT)
1513 1514
}  // namespace internal
}  // namespace v8
1515 1516 1517 1518 1519 1520 1521 1522 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

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

extern void _v8_internal_Print_Code(void* object) {
  i::Isolate* isolate = i::Isolate::Current();
  isolate->FindCodeObject(reinterpret_cast<i::Address>(object))->Print();
}

extern void _v8_internal_Print_TypeFeedbackVector(void* object) {
  if (reinterpret_cast<i::Object*>(object)->IsSmi()) {
    printf("Not a type feedback vector\n");
  } else {
    reinterpret_cast<i::TypeFeedbackVector*>(object)->Print();
  }
}

extern void _v8_internal_Print_DescriptorArray(void* object) {
  if (reinterpret_cast<i::Object*>(object)->IsSmi()) {
    printf("Not a descriptor array\n");
  } else {
    reinterpret_cast<i::DescriptorArray*>(object)->Print();
  }
}

extern void _v8_internal_Print_TransitionArray(void* object) {
  if (reinterpret_cast<i::Object*>(object)->IsSmi()) {
    printf("Not a transition array\n");
  } else {
    reinterpret_cast<i::TransitionArray*>(object)->Print();
  }
}

extern void _v8_internal_Print_StackTrace() {
  i::Isolate* isolate = i::Isolate::Current();
  isolate->PrintStack(stdout);
}