1// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/objects.h"
6
7#include "src/disasm.h"
8#include "src/disassembler.h"
9#include "src/interpreter/bytecodes.h"
10#include "src/objects-inl.h"
11#include "src/ostreams.h"
12#include "src/regexp/jsregexp.h"
13
14namespace v8 {
15namespace internal {
16
17#ifdef OBJECT_PRINT
18
19void Object::Print() {
20  OFStream os(stdout);
21  this->Print(os);
22  os << std::flush;
23}
24
25
26void Object::Print(std::ostream& os) {  // NOLINT
27  if (IsSmi()) {
28    Smi::cast(this)->SmiPrint(os);
29  } else {
30    HeapObject::cast(this)->HeapObjectPrint(os);
31  }
32}
33
34
35void HeapObject::PrintHeader(std::ostream& os, const char* id) {  // NOLINT
36  os << reinterpret_cast<void*>(this) << ": [" << id << "]\n";
37}
38
39
40void HeapObject::HeapObjectPrint(std::ostream& os) {  // NOLINT
41  InstanceType instance_type = map()->instance_type();
42
43  HandleScope scope(GetIsolate());
44  if (instance_type < FIRST_NONSTRING_TYPE) {
45    String::cast(this)->StringPrint(os);
46    return;
47  }
48
49  switch (instance_type) {
50    case SYMBOL_TYPE:
51      Symbol::cast(this)->SymbolPrint(os);
52      break;
53    case MAP_TYPE:
54      Map::cast(this)->MapPrint(os);
55      break;
56    case HEAP_NUMBER_TYPE:
57      HeapNumber::cast(this)->HeapNumberPrint(os);
58      break;
59    case MUTABLE_HEAP_NUMBER_TYPE:
60      os << "<mutable ";
61      HeapNumber::cast(this)->HeapNumberPrint(os);
62      os << ">";
63      break;
64    case SIMD128_VALUE_TYPE:
65      Simd128Value::cast(this)->Simd128ValuePrint(os);
66      break;
67    case FIXED_DOUBLE_ARRAY_TYPE:
68      FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(os);
69      break;
70    case FIXED_ARRAY_TYPE:
71      FixedArray::cast(this)->FixedArrayPrint(os);
72      break;
73    case BYTE_ARRAY_TYPE:
74      ByteArray::cast(this)->ByteArrayPrint(os);
75      break;
76    case BYTECODE_ARRAY_TYPE:
77      BytecodeArray::cast(this)->BytecodeArrayPrint(os);
78      break;
79    case TRANSITION_ARRAY_TYPE:
80      TransitionArray::cast(this)->TransitionArrayPrint(os);
81      break;
82    case FREE_SPACE_TYPE:
83      FreeSpace::cast(this)->FreeSpacePrint(os);
84      break;
85
86#define PRINT_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype, size) \
87  case Fixed##Type##Array::kInstanceType:                      \
88    Fixed##Type##Array::cast(this)->FixedTypedArrayPrint(os);  \
89    break;
90
91    TYPED_ARRAYS(PRINT_FIXED_TYPED_ARRAY)
92#undef PRINT_FIXED_TYPED_ARRAY
93
94    case FILLER_TYPE:
95      os << "filler";
96      break;
97    case JS_OBJECT_TYPE:  // fall through
98    case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
99    case JS_ARRAY_TYPE:
100    case JS_GENERATOR_OBJECT_TYPE:
101    case JS_PROMISE_TYPE:
102      JSObject::cast(this)->JSObjectPrint(os);
103      break;
104    case JS_REGEXP_TYPE:
105      JSRegExp::cast(this)->JSRegExpPrint(os);
106      break;
107    case ODDBALL_TYPE:
108      Oddball::cast(this)->to_string()->Print(os);
109      break;
110    case JS_MODULE_TYPE:
111      JSModule::cast(this)->JSModulePrint(os);
112      break;
113    case JS_BOUND_FUNCTION_TYPE:
114      JSBoundFunction::cast(this)->JSBoundFunctionPrint(os);
115      break;
116    case JS_FUNCTION_TYPE:
117      JSFunction::cast(this)->JSFunctionPrint(os);
118      break;
119    case JS_GLOBAL_PROXY_TYPE:
120      JSGlobalProxy::cast(this)->JSGlobalProxyPrint(os);
121      break;
122    case JS_GLOBAL_OBJECT_TYPE:
123      JSGlobalObject::cast(this)->JSGlobalObjectPrint(os);
124      break;
125    case JS_VALUE_TYPE:
126      JSValue::cast(this)->JSValuePrint(os);
127      break;
128    case JS_DATE_TYPE:
129      JSDate::cast(this)->JSDatePrint(os);
130      break;
131    case CODE_TYPE:
132      Code::cast(this)->CodePrint(os);
133      break;
134    case JS_PROXY_TYPE:
135      JSProxy::cast(this)->JSProxyPrint(os);
136      break;
137    case JS_SET_TYPE:
138      JSSet::cast(this)->JSSetPrint(os);
139      break;
140    case JS_MAP_TYPE:
141      JSMap::cast(this)->JSMapPrint(os);
142      break;
143    case JS_SET_ITERATOR_TYPE:
144      JSSetIterator::cast(this)->JSSetIteratorPrint(os);
145      break;
146    case JS_MAP_ITERATOR_TYPE:
147      JSMapIterator::cast(this)->JSMapIteratorPrint(os);
148      break;
149    case JS_ITERATOR_RESULT_TYPE:
150      JSIteratorResult::cast(this)->JSIteratorResultPrint(os);
151      break;
152    case JS_WEAK_MAP_TYPE:
153      JSWeakMap::cast(this)->JSWeakMapPrint(os);
154      break;
155    case JS_WEAK_SET_TYPE:
156      JSWeakSet::cast(this)->JSWeakSetPrint(os);
157      break;
158    case FOREIGN_TYPE:
159      Foreign::cast(this)->ForeignPrint(os);
160      break;
161    case SHARED_FUNCTION_INFO_TYPE:
162      SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(os);
163      break;
164    case JS_MESSAGE_OBJECT_TYPE:
165      JSMessageObject::cast(this)->JSMessageObjectPrint(os);
166      break;
167    case CELL_TYPE:
168      Cell::cast(this)->CellPrint(os);
169      break;
170    case PROPERTY_CELL_TYPE:
171      PropertyCell::cast(this)->PropertyCellPrint(os);
172      break;
173    case WEAK_CELL_TYPE:
174      WeakCell::cast(this)->WeakCellPrint(os);
175      break;
176    case JS_ARRAY_BUFFER_TYPE:
177      JSArrayBuffer::cast(this)->JSArrayBufferPrint(os);
178      break;
179    case JS_TYPED_ARRAY_TYPE:
180      JSTypedArray::cast(this)->JSTypedArrayPrint(os);
181      break;
182    case JS_DATA_VIEW_TYPE:
183      JSDataView::cast(this)->JSDataViewPrint(os);
184      break;
185#define MAKE_STRUCT_CASE(NAME, Name, name) \
186  case NAME##_TYPE:                        \
187    Name::cast(this)->Name##Print(os);     \
188    break;
189  STRUCT_LIST(MAKE_STRUCT_CASE)
190#undef MAKE_STRUCT_CASE
191
192    default:
193      os << "UNKNOWN TYPE " << map()->instance_type();
194      UNREACHABLE();
195      break;
196  }
197}
198
199
200void Simd128Value::Simd128ValuePrint(std::ostream& os) {  // NOLINT
201#define PRINT_SIMD128_VALUE(TYPE, Type, type, lane_count, lane_type) \
202  if (Is##Type()) return Type::cast(this)->Type##Print(os);
203  SIMD128_TYPES(PRINT_SIMD128_VALUE)
204#undef PRINT_SIMD128_VALUE
205  UNREACHABLE();
206}
207
208
209void Float32x4::Float32x4Print(std::ostream& os) {  // NOLINT
210  char arr[100];
211  Vector<char> buffer(arr, arraysize(arr));
212  os << std::string(DoubleToCString(get_lane(0), buffer)) << ", "
213     << std::string(DoubleToCString(get_lane(1), buffer)) << ", "
214     << std::string(DoubleToCString(get_lane(2), buffer)) << ", "
215     << std::string(DoubleToCString(get_lane(3), buffer));
216}
217
218
219#define SIMD128_INT_PRINT_FUNCTION(type, lane_count)                \
220  void type::type##Print(std::ostream& os) {                        \
221    char arr[100];                                                  \
222    Vector<char> buffer(arr, arraysize(arr));                       \
223    os << std::string(IntToCString(get_lane(0), buffer));           \
224    for (int i = 1; i < lane_count; i++) {                          \
225      os << ", " << std::string(IntToCString(get_lane(i), buffer)); \
226    }                                                               \
227  }
228SIMD128_INT_PRINT_FUNCTION(Int32x4, 4)
229SIMD128_INT_PRINT_FUNCTION(Uint32x4, 4)
230SIMD128_INT_PRINT_FUNCTION(Int16x8, 8)
231SIMD128_INT_PRINT_FUNCTION(Uint16x8, 8)
232SIMD128_INT_PRINT_FUNCTION(Int8x16, 16)
233SIMD128_INT_PRINT_FUNCTION(Uint8x16, 16)
234#undef SIMD128_INT_PRINT_FUNCTION
235
236
237#define SIMD128_BOOL_PRINT_FUNCTION(type, lane_count)            \
238  void type::type##Print(std::ostream& os) {                     \
239    char arr[100];                                               \
240    Vector<char> buffer(arr, arraysize(arr));                    \
241    os << std::string(get_lane(0) ? "true" : "false");           \
242    for (int i = 1; i < lane_count; i++) {                       \
243      os << ", " << std::string(get_lane(i) ? "true" : "false"); \
244    }                                                            \
245  }
246SIMD128_BOOL_PRINT_FUNCTION(Bool32x4, 4)
247SIMD128_BOOL_PRINT_FUNCTION(Bool16x8, 8)
248SIMD128_BOOL_PRINT_FUNCTION(Bool8x16, 16)
249#undef SIMD128_BOOL_PRINT_FUNCTION
250
251
252void ByteArray::ByteArrayPrint(std::ostream& os) {  // NOLINT
253  os << "byte array, data starts at " << GetDataStartAddress();
254}
255
256
257void BytecodeArray::BytecodeArrayPrint(std::ostream& os) {  // NOLINT
258  Disassemble(os);
259}
260
261
262void FreeSpace::FreeSpacePrint(std::ostream& os) {  // NOLINT
263  os << "free space, size " << Size();
264}
265
266
267template <class Traits>
268void FixedTypedArray<Traits>::FixedTypedArrayPrint(
269    std::ostream& os) {  // NOLINT
270  os << "fixed " << Traits::Designator();
271}
272
273
274void JSObject::PrintProperties(std::ostream& os) {  // NOLINT
275  if (HasFastProperties()) {
276    DescriptorArray* descs = map()->instance_descriptors();
277    for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) {
278      os << "\n   ";
279      descs->GetKey(i)->NamePrint(os);
280      os << ": ";
281      switch (descs->GetType(i)) {
282        case DATA: {
283          FieldIndex index = FieldIndex::ForDescriptor(map(), i);
284          if (IsUnboxedDoubleField(index)) {
285            os << "<unboxed double> " << RawFastDoublePropertyAt(index);
286          } else {
287            os << Brief(RawFastPropertyAt(index));
288          }
289          os << " (data field at offset " << index.property_index() << ")";
290          break;
291        }
292        case ACCESSOR: {
293          FieldIndex index = FieldIndex::ForDescriptor(map(), i);
294          os << " (accessor field at offset " << index.property_index() << ")";
295          break;
296        }
297        case DATA_CONSTANT:
298          os << Brief(descs->GetConstant(i)) << " (data constant)";
299          break;
300        case ACCESSOR_CONSTANT:
301          os << Brief(descs->GetCallbacksObject(i)) << " (accessor constant)";
302          break;
303      }
304    }
305  } else if (IsJSGlobalObject()) {
306    global_dictionary()->Print(os);
307  } else {
308    property_dictionary()->Print(os);
309  }
310}
311
312
313template <class T>
314static void DoPrintElements(std::ostream& os, Object* object) {  // NOLINT
315  T* p = T::cast(object);
316  for (int i = 0; i < p->length(); i++) {
317    os << "\n   " << i << ": " << p->get_scalar(i);
318  }
319}
320
321
322void JSObject::PrintElements(std::ostream& os) {  // NOLINT
323  // Don't call GetElementsKind, its validation code can cause the printer to
324  // fail when debugging.
325  switch (map()->elements_kind()) {
326    case FAST_HOLEY_SMI_ELEMENTS:
327    case FAST_SMI_ELEMENTS:
328    case FAST_HOLEY_ELEMENTS:
329    case FAST_ELEMENTS: {
330      // Print in array notation for non-sparse arrays.
331      FixedArray* p = FixedArray::cast(elements());
332      for (int i = 0; i < p->length(); i++) {
333        os << "\n   " << i << ": " << Brief(p->get(i));
334      }
335      break;
336    }
337    case FAST_HOLEY_DOUBLE_ELEMENTS:
338    case FAST_DOUBLE_ELEMENTS: {
339      // Print in array notation for non-sparse arrays.
340      if (elements()->length() > 0) {
341        FixedDoubleArray* p = FixedDoubleArray::cast(elements());
342        for (int i = 0; i < p->length(); i++) {
343          os << "\n   " << i << ": ";
344          if (p->is_the_hole(i)) {
345            os << "<the hole>";
346          } else {
347            os << p->get_scalar(i);
348          }
349        }
350      }
351      break;
352    }
353
354
355#define PRINT_ELEMENTS(Kind, Type)         \
356  case Kind: {                             \
357    DoPrintElements<Type>(os, elements()); \
358    break;                                 \
359  }
360
361    PRINT_ELEMENTS(UINT8_ELEMENTS, FixedUint8Array)
362    PRINT_ELEMENTS(UINT8_CLAMPED_ELEMENTS, FixedUint8ClampedArray)
363    PRINT_ELEMENTS(INT8_ELEMENTS, FixedInt8Array)
364    PRINT_ELEMENTS(UINT16_ELEMENTS, FixedUint16Array)
365    PRINT_ELEMENTS(INT16_ELEMENTS, FixedInt16Array)
366    PRINT_ELEMENTS(UINT32_ELEMENTS, FixedUint32Array)
367    PRINT_ELEMENTS(INT32_ELEMENTS, FixedInt32Array)
368    PRINT_ELEMENTS(FLOAT32_ELEMENTS, FixedFloat32Array)
369    PRINT_ELEMENTS(FLOAT64_ELEMENTS, FixedFloat64Array)
370
371#undef PRINT_ELEMENTS
372
373    case DICTIONARY_ELEMENTS:
374      elements()->Print(os);
375      break;
376    case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
377    case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
378      FixedArray* p = FixedArray::cast(elements());
379      os << "\n   parameter map:";
380      for (int i = 2; i < p->length(); i++) {
381        os << " " << (i - 2) << ":" << Brief(p->get(i));
382      }
383      os << "\n   context: " << Brief(p->get(0))
384         << "\n   arguments: " << Brief(p->get(1));
385      break;
386    }
387  }
388}
389
390
391static void JSObjectPrintHeader(std::ostream& os, JSObject* obj,
392                                const char* id) {  // NOLINT
393  obj->PrintHeader(os, id);
394  // Don't call GetElementsKind, its validation code can cause the printer to
395  // fail when debugging.
396  PrototypeIterator iter(obj->GetIsolate(), obj);
397  os << " - map = " << reinterpret_cast<void*>(obj->map()) << " ["
398     << ElementsKindToString(obj->map()->elements_kind())
399     << "]\n - prototype = " << reinterpret_cast<void*>(iter.GetCurrent());
400}
401
402
403static void JSObjectPrintBody(std::ostream& os, JSObject* obj,  // NOLINT
404                              bool print_elements = true) {
405  os << "\n {";
406  obj->PrintProperties(os);
407  obj->PrintTransitions(os);
408  if (print_elements) obj->PrintElements(os);
409  os << "\n }\n";
410}
411
412
413void JSObject::JSObjectPrint(std::ostream& os) {  // NOLINT
414  JSObjectPrintHeader(os, this, "JSObject");
415  JSObjectPrintBody(os, this);
416}
417
418
419void JSRegExp::JSRegExpPrint(std::ostream& os) {  // NOLINT
420  JSObjectPrintHeader(os, this, "JSRegExp");
421  os << "\n - data = " << Brief(data());
422  JSObjectPrintBody(os, this);
423}
424
425
426void JSModule::JSModulePrint(std::ostream& os) {  // NOLINT
427  JSObjectPrintHeader(os, this, "JSModule");
428  os << "\n - context = " << Brief(context());
429  os << " - scope_info = " << Brief(scope_info());
430  JSObjectPrintBody(os, this);
431}
432
433
434void Symbol::SymbolPrint(std::ostream& os) {  // NOLINT
435  HeapObject::PrintHeader(os, "Symbol");
436  os << " - hash: " << Hash();
437  os << "\n - name: " << Brief(name());
438  if (name()->IsUndefined()) {
439    os << " (" << PrivateSymbolToName() << ")";
440  }
441  os << "\n - private: " << is_private();
442  os << "\n";
443}
444
445
446void Map::MapPrint(std::ostream& os) {  // NOLINT
447  HeapObject::PrintHeader(os, "Map");
448  os << " - type: " << instance_type() << "\n";
449  os << " - instance size: " << instance_size() << "\n";
450  if (IsJSObjectMap()) {
451    os << " - inobject properties: " << GetInObjectProperties() << "\n";
452  }
453  os << " - elements kind: " << ElementsKindToString(elements_kind()) << "\n";
454  os << " - unused property fields: " << unused_property_fields() << "\n";
455  if (is_deprecated()) os << " - deprecated_map\n";
456  if (is_stable()) os << " - stable_map\n";
457  if (is_dictionary_map()) os << " - dictionary_map\n";
458  if (is_hidden_prototype()) os << " - hidden_prototype\n";
459  if (has_named_interceptor()) os << " - named_interceptor\n";
460  if (has_indexed_interceptor()) os << " - indexed_interceptor\n";
461  if (is_undetectable()) os << " - undetectable\n";
462  if (is_callable()) os << " - callable\n";
463  if (is_constructor()) os << " - constructor\n";
464  if (is_access_check_needed()) os << " - access_check_needed\n";
465  if (!is_extensible()) os << " - non-extensible\n";
466  if (is_observed()) os << " - observed\n";
467  if (is_strong()) os << " - strong_map\n";
468  if (is_prototype_map()) {
469    os << " - prototype_map\n";
470    os << " - prototype info: " << Brief(prototype_info());
471  } else {
472    os << " - back pointer: " << Brief(GetBackPointer());
473  }
474  os << "\n - instance descriptors " << (owns_descriptors() ? "(own) " : "")
475     << "#" << NumberOfOwnDescriptors() << ": "
476     << Brief(instance_descriptors());
477  if (FLAG_unbox_double_fields) {
478    os << "\n - layout descriptor: " << Brief(layout_descriptor());
479  }
480  int nof_transitions = TransitionArray::NumberOfTransitions(raw_transitions());
481  if (nof_transitions > 0) {
482    os << "\n - transitions #" << nof_transitions << ": "
483       << Brief(raw_transitions());
484    TransitionArray::PrintTransitions(os, raw_transitions(), false);
485  }
486  os << "\n - prototype: " << Brief(prototype());
487  os << "\n - constructor: " << Brief(GetConstructor());
488  os << "\n - code cache: " << Brief(code_cache());
489  os << "\n - dependent code: " << Brief(dependent_code());
490  os << "\n - construction counter: " << construction_counter();
491  os << "\n";
492}
493
494
495void CodeCache::CodeCachePrint(std::ostream& os) {  // NOLINT
496  HeapObject::PrintHeader(os, "CodeCache");
497  os << "\n - default_cache: " << Brief(default_cache());
498  os << "\n - normal_type_cache: " << Brief(normal_type_cache());
499}
500
501
502void PolymorphicCodeCache::PolymorphicCodeCachePrint(
503    std::ostream& os) {  // NOLINT
504  HeapObject::PrintHeader(os, "PolymorphicCodeCache");
505  os << "\n - cache: " << Brief(cache());
506}
507
508
509void TypeFeedbackInfo::TypeFeedbackInfoPrint(std::ostream& os) {  // NOLINT
510  HeapObject::PrintHeader(os, "TypeFeedbackInfo");
511  os << " - ic_total_count: " << ic_total_count()
512     << ", ic_with_type_info_count: " << ic_with_type_info_count()
513     << ", ic_generic_count: " << ic_generic_count() << "\n";
514}
515
516
517void AliasedArgumentsEntry::AliasedArgumentsEntryPrint(
518    std::ostream& os) {  // NOLINT
519  HeapObject::PrintHeader(os, "AliasedArgumentsEntry");
520  os << "\n - aliased_context_slot: " << aliased_context_slot();
521}
522
523
524void FixedArray::FixedArrayPrint(std::ostream& os) {  // NOLINT
525  HeapObject::PrintHeader(os, "FixedArray");
526  os << " - length: " << length();
527  for (int i = 0; i < length(); i++) {
528    os << "\n  [" << i << "]: " << Brief(get(i));
529  }
530  os << "\n";
531}
532
533
534void FixedDoubleArray::FixedDoubleArrayPrint(std::ostream& os) {  // NOLINT
535  HeapObject::PrintHeader(os, "FixedDoubleArray");
536  os << " - length: " << length();
537  for (int i = 0; i < length(); i++) {
538    os << "\n  [" << i << "]: ";
539    if (is_the_hole(i)) {
540      os << "<the hole>";
541    } else {
542      os << get_scalar(i);
543    }
544  }
545  os << "\n";
546}
547
548
549void TransitionArray::TransitionArrayPrint(std::ostream& os) {  // NOLINT
550  HeapObject::PrintHeader(os, "TransitionArray");
551  os << " - capacity: " << length();
552  for (int i = 0; i < length(); i++) {
553    os << "\n  [" << i << "]: " << Brief(get(i));
554    if (i == kNextLinkIndex) os << " (next link)";
555    if (i == kPrototypeTransitionsIndex) os << " (prototype transitions)";
556    if (i == kTransitionLengthIndex) os << " (number of transitions)";
557  }
558  os << "\n";
559}
560
561
562void TypeFeedbackMetadata::Print() {
563  OFStream os(stdout);
564  TypeFeedbackMetadataPrint(os);
565  os << std::flush;
566}
567
568
569void TypeFeedbackMetadata::TypeFeedbackMetadataPrint(
570    std::ostream& os) {  // NOLINT
571  HeapObject::PrintHeader(os, "TypeFeedbackMetadata");
572  os << " - length: " << length();
573  if (length() == 0) {
574    os << " (empty)\n";
575    return;
576  }
577
578  TypeFeedbackMetadataIterator iter(this);
579  while (iter.HasNext()) {
580    FeedbackVectorSlot slot = iter.Next();
581    FeedbackVectorSlotKind kind = iter.kind();
582    os << "\n Slot " << slot << " " << kind;
583  }
584  os << "\n";
585}
586
587
588void TypeFeedbackVector::Print() {
589  OFStream os(stdout);
590  TypeFeedbackVectorPrint(os);
591  os << std::flush;
592}
593
594
595void TypeFeedbackVector::TypeFeedbackVectorPrint(std::ostream& os) {  // NOLINT
596  HeapObject::PrintHeader(os, "TypeFeedbackVector");
597  os << " - length: " << length();
598  if (length() == 0) {
599    os << " (empty)\n";
600    return;
601  }
602
603  TypeFeedbackMetadataIterator iter(metadata());
604  while (iter.HasNext()) {
605    FeedbackVectorSlot slot = iter.Next();
606    FeedbackVectorSlotKind kind = iter.kind();
607
608    os << "\n Slot " << slot << " " << kind << " ";
609    switch (kind) {
610      case FeedbackVectorSlotKind::LOAD_IC: {
611        LoadICNexus nexus(this, slot);
612        os << Code::ICState2String(nexus.StateFromFeedback());
613        break;
614      }
615      case FeedbackVectorSlotKind::KEYED_LOAD_IC: {
616        KeyedLoadICNexus nexus(this, slot);
617        os << Code::ICState2String(nexus.StateFromFeedback());
618        break;
619      }
620      case FeedbackVectorSlotKind::CALL_IC: {
621        CallICNexus nexus(this, slot);
622        os << Code::ICState2String(nexus.StateFromFeedback());
623        break;
624      }
625      case FeedbackVectorSlotKind::STORE_IC: {
626        StoreICNexus nexus(this, slot);
627        os << Code::ICState2String(nexus.StateFromFeedback());
628        break;
629      }
630      case FeedbackVectorSlotKind::KEYED_STORE_IC: {
631        KeyedStoreICNexus nexus(this, slot);
632        os << Code::ICState2String(nexus.StateFromFeedback());
633        break;
634      }
635      case FeedbackVectorSlotKind::GENERAL:
636        break;
637      case FeedbackVectorSlotKind::INVALID:
638      case FeedbackVectorSlotKind::KINDS_NUMBER:
639        UNREACHABLE();
640        break;
641    }
642
643    int entry_size = iter.entry_size();
644    for (int i = 0; i < entry_size; i++) {
645      int index = GetIndex(slot) + i;
646      os << "\n  [" << index << "]: " << Brief(get(index));
647    }
648  }
649  os << "\n";
650}
651
652
653void JSValue::JSValuePrint(std::ostream& os) {  // NOLINT
654  JSObjectPrintHeader(os, this, "JSValue");
655  os << "\n - value = " << Brief(value());
656  JSObjectPrintBody(os, this);
657}
658
659
660void JSMessageObject::JSMessageObjectPrint(std::ostream& os) {  // NOLINT
661  JSObjectPrintHeader(os, this, "JSMessageObject");
662  os << "\n - type: " << type();
663  os << "\n - arguments: " << Brief(argument());
664  os << "\n - start_position: " << start_position();
665  os << "\n - end_position: " << end_position();
666  os << "\n - script: " << Brief(script());
667  os << "\n - stack_frames: " << Brief(stack_frames());
668  JSObjectPrintBody(os, this);
669}
670
671
672void String::StringPrint(std::ostream& os) {  // NOLINT
673  if (StringShape(this).IsInternalized()) {
674    os << "#";
675  } else if (StringShape(this).IsCons()) {
676    os << "c\"";
677  } else {
678    os << "\"";
679  }
680
681  const char truncated_epilogue[] = "...<truncated>";
682  int len = length();
683  if (!FLAG_use_verbose_printer) {
684    if (len > 100) {
685      len = 100 - sizeof(truncated_epilogue);
686    }
687  }
688  for (int i = 0; i < len; i++) {
689    os << AsUC16(Get(i));
690  }
691  if (len != length()) {
692    os << truncated_epilogue;
693  }
694
695  if (!StringShape(this).IsInternalized()) os << "\"";
696}
697
698
699void Name::NamePrint(std::ostream& os) {  // NOLINT
700  if (IsString()) {
701    String::cast(this)->StringPrint(os);
702  } else if (IsSymbol()) {
703    Symbol::cast(this)->name()->Print(os);
704  } else {
705    os << Brief(this);
706  }
707}
708
709
710static const char* const weekdays[] = {
711  "???", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
712};
713
714
715void JSDate::JSDatePrint(std::ostream& os) {  // NOLINT
716  JSObjectPrintHeader(os, this, "JSDate");
717  os << "\n - value = " << Brief(value());
718  if (!year()->IsSmi()) {
719    os << "\n - time = NaN\n";
720  } else {
721    // TODO(svenpanne) Add some basic formatting to our streams.
722    ScopedVector<char> buf(100);
723    SNPrintF(
724        buf, "\n - time = %s %04d/%02d/%02d %02d:%02d:%02d\n",
725        weekdays[weekday()->IsSmi() ? Smi::cast(weekday())->value() + 1 : 0],
726        year()->IsSmi() ? Smi::cast(year())->value() : -1,
727        month()->IsSmi() ? Smi::cast(month())->value() : -1,
728        day()->IsSmi() ? Smi::cast(day())->value() : -1,
729        hour()->IsSmi() ? Smi::cast(hour())->value() : -1,
730        min()->IsSmi() ? Smi::cast(min())->value() : -1,
731        sec()->IsSmi() ? Smi::cast(sec())->value() : -1);
732    os << buf.start();
733  }
734  JSObjectPrintBody(os, this);
735}
736
737
738void JSProxy::JSProxyPrint(std::ostream& os) {  // NOLINT
739  HeapObject::PrintHeader(os, "JSProxy");
740  os << " - map = " << reinterpret_cast<void*>(map());
741  os << "\n - target = ";
742  target()->ShortPrint(os);
743  os << "\n - handler = ";
744  handler()->ShortPrint(os);
745  os << "\n - hash = ";
746  hash()->ShortPrint(os);
747  os << "\n";
748}
749
750
751void JSSet::JSSetPrint(std::ostream& os) {  // NOLINT
752  JSObjectPrintHeader(os, this, "JSSet");
753  os << " - table = " << Brief(table());
754  JSObjectPrintBody(os, this);
755}
756
757
758void JSMap::JSMapPrint(std::ostream& os) {  // NOLINT
759  JSObjectPrintHeader(os, this, "JSMap");
760  os << " - table = " << Brief(table());
761  JSObjectPrintBody(os, this);
762}
763
764
765template <class Derived, class TableType>
766void
767OrderedHashTableIterator<Derived, TableType>::OrderedHashTableIteratorPrint(
768    std::ostream& os) {  // NOLINT
769  os << "\n - table = " << Brief(table());
770  os << "\n - index = " << Brief(index());
771  os << "\n - kind = " << Brief(kind());
772  os << "\n";
773}
774
775
776template void OrderedHashTableIterator<
777    JSSetIterator,
778    OrderedHashSet>::OrderedHashTableIteratorPrint(std::ostream& os);  // NOLINT
779
780
781template void OrderedHashTableIterator<
782    JSMapIterator,
783    OrderedHashMap>::OrderedHashTableIteratorPrint(std::ostream& os);  // NOLINT
784
785
786void JSSetIterator::JSSetIteratorPrint(std::ostream& os) {  // NOLINT
787  JSObjectPrintHeader(os, this, "JSSetIterator");
788  OrderedHashTableIteratorPrint(os);
789}
790
791
792void JSMapIterator::JSMapIteratorPrint(std::ostream& os) {  // NOLINT
793  JSObjectPrintHeader(os, this, "JSMapIterator");
794  OrderedHashTableIteratorPrint(os);
795}
796
797
798void JSIteratorResult::JSIteratorResultPrint(std::ostream& os) {  // NOLINT
799  JSObjectPrintHeader(os, this, "JSIteratorResult");
800  os << "\n - done = " << Brief(done());
801  os << "\n - value = " << Brief(value());
802  os << "\n";
803}
804
805
806void JSWeakMap::JSWeakMapPrint(std::ostream& os) {  // NOLINT
807  JSObjectPrintHeader(os, this, "JSWeakMap");
808  os << "\n - table = " << Brief(table());
809  JSObjectPrintBody(os, this);
810}
811
812
813void JSWeakSet::JSWeakSetPrint(std::ostream& os) {  // NOLINT
814  JSObjectPrintHeader(os, this, "JSWeakSet");
815  os << "\n - table = " << Brief(table());
816  JSObjectPrintBody(os, this);
817}
818
819
820void JSArrayBuffer::JSArrayBufferPrint(std::ostream& os) {  // NOLINT
821  JSObjectPrintHeader(os, this, "JSArrayBuffer");
822  os << "\n - backing_store = " << backing_store();
823  os << "\n - byte_length = " << Brief(byte_length());
824  if (was_neutered()) os << " - neutered\n";
825  JSObjectPrintBody(os, this, !was_neutered());
826}
827
828
829void JSTypedArray::JSTypedArrayPrint(std::ostream& os) {  // NOLINT
830  JSObjectPrintHeader(os, this, "JSTypedArray");
831  os << "\n - buffer = " << Brief(buffer());
832  os << "\n - byte_offset = " << Brief(byte_offset());
833  os << "\n - byte_length = " << Brief(byte_length());
834  os << "\n - length = " << Brief(length());
835  if (WasNeutered()) os << " - neutered\n";
836  JSObjectPrintBody(os, this, !WasNeutered());
837}
838
839
840void JSDataView::JSDataViewPrint(std::ostream& os) {  // NOLINT
841  JSObjectPrintHeader(os, this, "JSDataView");
842  os << "\n - buffer =" << Brief(buffer());
843  os << "\n - byte_offset = " << Brief(byte_offset());
844  os << "\n - byte_length = " << Brief(byte_length());
845  if (WasNeutered()) os << " - neutered\n";
846  JSObjectPrintBody(os, this, !WasNeutered());
847}
848
849
850void JSBoundFunction::JSBoundFunctionPrint(std::ostream& os) {  // NOLINT
851  JSObjectPrintHeader(os, this, "JSBoundFunction");
852  os << "\n - bound_target_function = " << Brief(bound_target_function());
853  os << "\n - bound_this = " << Brief(bound_this());
854  os << "\n - bound_arguments = " << Brief(bound_arguments());
855  JSObjectPrintBody(os, this);
856}
857
858
859void JSFunction::JSFunctionPrint(std::ostream& os) {  // NOLINT
860  JSObjectPrintHeader(os, this, "Function");
861  os << "\n - initial_map = ";
862  if (has_initial_map()) os << Brief(initial_map());
863  os << "\n - shared_info = " << Brief(shared());
864  os << "\n - name = " << Brief(shared()->name());
865  if (shared()->is_generator()) {
866    os << "\n   - generator";
867  }
868  os << "\n - context = " << Brief(context());
869  os << "\n - literals = " << Brief(literals());
870  os << "\n - code = " << Brief(code());
871  JSObjectPrintBody(os, this);
872}
873
874
875void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) {  // NOLINT
876  HeapObject::PrintHeader(os, "SharedFunctionInfo");
877  os << " - name: " << Brief(name());
878  os << "\n - expected_nof_properties: " << expected_nof_properties();
879  os << "\n - ast_node_count: " << ast_node_count();
880  os << "\n - instance class name = ";
881  instance_class_name()->Print(os);
882  os << "\n - code = " << Brief(code());
883  if (HasSourceCode()) {
884    os << "\n - source code = ";
885    String* source = String::cast(Script::cast(script())->source());
886    int start = start_position();
887    int length = end_position() - start;
888    base::SmartArrayPointer<char> source_string = source->ToCString(
889        DISALLOW_NULLS, FAST_STRING_TRAVERSAL, start, length, NULL);
890    os << source_string.get();
891  }
892  // Script files are often large, hard to read.
893  // os << "\n - script =";
894  // script()->Print(os);
895  os << "\n - function token position = " << function_token_position();
896  os << "\n - start position = " << start_position();
897  os << "\n - end position = " << end_position();
898  os << "\n - is expression = " << is_expression();
899  os << "\n - debug info = " << Brief(debug_info());
900  os << "\n - length = " << length();
901  os << "\n - optimized_code_map = " << Brief(optimized_code_map());
902  os << "\n - feedback_vector = ";
903  feedback_vector()->TypeFeedbackVectorPrint(os);
904  if (HasBytecodeArray()) {
905    os << "\n - bytecode_array = " << bytecode_array();
906  }
907  os << "\n";
908}
909
910
911void JSGlobalProxy::JSGlobalProxyPrint(std::ostream& os) {  // NOLINT
912  os << "global_proxy ";
913  JSObjectPrint(os);
914  os << "native context : " << Brief(native_context());
915  os << "\n";
916}
917
918
919void JSGlobalObject::JSGlobalObjectPrint(std::ostream& os) {  // NOLINT
920  os << "global ";
921  JSObjectPrint(os);
922  os << "native context : " << Brief(native_context());
923  os << "\n";
924}
925
926
927void Cell::CellPrint(std::ostream& os) {  // NOLINT
928  HeapObject::PrintHeader(os, "Cell");
929  os << " - value: " << Brief(value());
930  os << "\n";
931}
932
933
934void PropertyCell::PropertyCellPrint(std::ostream& os) {  // NOLINT
935  HeapObject::PrintHeader(os, "PropertyCell");
936  os << " - value: " << Brief(value());
937  os << "\n - details: " << property_details();
938  os << "\n";
939}
940
941
942void WeakCell::WeakCellPrint(std::ostream& os) {  // NOLINT
943  HeapObject::PrintHeader(os, "WeakCell");
944  if (cleared()) {
945    os << "\n - cleared";
946  } else {
947    os << "\n - value: " << Brief(value());
948  }
949  os << "\n";
950}
951
952
953void Code::CodePrint(std::ostream& os) {  // NOLINT
954  HeapObject::PrintHeader(os, "Code");
955#ifdef ENABLE_DISASSEMBLER
956  if (FLAG_use_verbose_printer) {
957    Disassemble(NULL, os);
958  }
959#endif
960}
961
962
963void Foreign::ForeignPrint(std::ostream& os) {  // NOLINT
964  os << "foreign address : " << foreign_address();
965  os << "\n";
966}
967
968
969void ExecutableAccessorInfo::ExecutableAccessorInfoPrint(
970    std::ostream& os) {  // NOLINT
971  HeapObject::PrintHeader(os, "ExecutableAccessorInfo");
972  os << "\n - name: " << Brief(name());
973  os << "\n - flag: " << flag();
974  os << "\n - getter: " << Brief(getter());
975  os << "\n - setter: " << Brief(setter());
976  os << "\n - data: " << Brief(data());
977  os << "\n";
978}
979
980
981void Box::BoxPrint(std::ostream& os) {  // NOLINT
982  HeapObject::PrintHeader(os, "Box");
983  os << "\n - value: " << Brief(value());
984  os << "\n";
985}
986
987
988void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) {  // NOLINT
989  HeapObject::PrintHeader(os, "PrototypeInfo");
990  os << "\n - prototype users: " << Brief(prototype_users());
991  os << "\n - registry slot: " << registry_slot();
992  os << "\n - validity cell: " << Brief(validity_cell());
993  os << "\n";
994}
995
996
997void SloppyBlockWithEvalContextExtension::
998    SloppyBlockWithEvalContextExtensionPrint(std::ostream& os) {  // NOLINT
999  HeapObject::PrintHeader(os, "SloppyBlockWithEvalContextExtension");
1000  os << "\n - scope_info: " << Brief(scope_info());
1001  os << "\n - extension: " << Brief(extension());
1002  os << "\n";
1003}
1004
1005
1006void AccessorPair::AccessorPairPrint(std::ostream& os) {  // NOLINT
1007  HeapObject::PrintHeader(os, "AccessorPair");
1008  os << "\n - getter: " << Brief(getter());
1009  os << "\n - setter: " << Brief(setter());
1010  os << "\n";
1011}
1012
1013
1014void AccessCheckInfo::AccessCheckInfoPrint(std::ostream& os) {  // NOLINT
1015  HeapObject::PrintHeader(os, "AccessCheckInfo");
1016  os << "\n - named_callback: " << Brief(named_callback());
1017  os << "\n - indexed_callback: " << Brief(indexed_callback());
1018  os << "\n - callback: " << Brief(callback());
1019  os << "\n - data: " << Brief(data());
1020  os << "\n";
1021}
1022
1023
1024void InterceptorInfo::InterceptorInfoPrint(std::ostream& os) {  // NOLINT
1025  HeapObject::PrintHeader(os, "InterceptorInfo");
1026  os << "\n - getter: " << Brief(getter());
1027  os << "\n - setter: " << Brief(setter());
1028  os << "\n - query: " << Brief(query());
1029  os << "\n - deleter: " << Brief(deleter());
1030  os << "\n - enumerator: " << Brief(enumerator());
1031  os << "\n - data: " << Brief(data());
1032  os << "\n";
1033}
1034
1035
1036void CallHandlerInfo::CallHandlerInfoPrint(std::ostream& os) {  // NOLINT
1037  HeapObject::PrintHeader(os, "CallHandlerInfo");
1038  os << "\n - callback: " << Brief(callback());
1039  os << "\n - data: " << Brief(data());
1040  os << "\n";
1041}
1042
1043
1044void FunctionTemplateInfo::FunctionTemplateInfoPrint(
1045    std::ostream& os) {  // NOLINT
1046  HeapObject::PrintHeader(os, "FunctionTemplateInfo");
1047  os << "\n - class name: " << Brief(class_name());
1048  os << "\n - tag: " << Brief(tag());
1049  os << "\n - property_list: " << Brief(property_list());
1050  os << "\n - serial_number: " << Brief(serial_number());
1051  os << "\n - call_code: " << Brief(call_code());
1052  os << "\n - property_accessors: " << Brief(property_accessors());
1053  os << "\n - prototype_template: " << Brief(prototype_template());
1054  os << "\n - parent_template: " << Brief(parent_template());
1055  os << "\n - named_property_handler: " << Brief(named_property_handler());
1056  os << "\n - indexed_property_handler: " << Brief(indexed_property_handler());
1057  os << "\n - instance_template: " << Brief(instance_template());
1058  os << "\n - signature: " << Brief(signature());
1059  os << "\n - access_check_info: " << Brief(access_check_info());
1060  os << "\n - hidden_prototype: " << (hidden_prototype() ? "true" : "false");
1061  os << "\n - undetectable: " << (undetectable() ? "true" : "false");
1062  os << "\n - need_access_check: " << (needs_access_check() ? "true" : "false");
1063  os << "\n - instantiated: " << (instantiated() ? "true" : "false");
1064  os << "\n";
1065}
1066
1067
1068void ObjectTemplateInfo::ObjectTemplateInfoPrint(std::ostream& os) {  // NOLINT
1069  HeapObject::PrintHeader(os, "ObjectTemplateInfo");
1070  os << " - tag: " << Brief(tag());
1071  os << "\n - property_list: " << Brief(property_list());
1072  os << "\n - property_accessors: " << Brief(property_accessors());
1073  os << "\n - constructor: " << Brief(constructor());
1074  os << "\n - internal_field_count: " << Brief(internal_field_count());
1075  os << "\n";
1076}
1077
1078
1079void AllocationSite::AllocationSitePrint(std::ostream& os) {  // NOLINT
1080  HeapObject::PrintHeader(os, "AllocationSite");
1081  os << " - weak_next: " << Brief(weak_next());
1082  os << "\n - dependent code: " << Brief(dependent_code());
1083  os << "\n - nested site: " << Brief(nested_site());
1084  os << "\n - memento found count: "
1085     << Brief(Smi::FromInt(memento_found_count()));
1086  os << "\n - memento create count: "
1087     << Brief(Smi::FromInt(memento_create_count()));
1088  os << "\n - pretenure decision: "
1089     << Brief(Smi::FromInt(pretenure_decision()));
1090  os << "\n - transition_info: ";
1091  if (transition_info()->IsSmi()) {
1092    ElementsKind kind = GetElementsKind();
1093    os << "Array allocation with ElementsKind " << ElementsKindToString(kind);
1094  } else if (transition_info()->IsJSArray()) {
1095    os << "Array literal " << Brief(transition_info());
1096  } else {
1097    os << "unknown transition_info" << Brief(transition_info());
1098  }
1099  os << "\n";
1100}
1101
1102
1103void AllocationMemento::AllocationMementoPrint(std::ostream& os) {  // NOLINT
1104  HeapObject::PrintHeader(os, "AllocationMemento");
1105  os << " - allocation site: ";
1106  if (IsValid()) {
1107    GetAllocationSite()->Print(os);
1108  } else {
1109    os << "<invalid>\n";
1110  }
1111}
1112
1113
1114void Script::ScriptPrint(std::ostream& os) {  // NOLINT
1115  HeapObject::PrintHeader(os, "Script");
1116  os << "\n - source: " << Brief(source());
1117  os << "\n - name: " << Brief(name());
1118  os << "\n - line_offset: " << line_offset();
1119  os << "\n - column_offset: " << column_offset();
1120  os << "\n - type: " << type();
1121  os << "\n - id: " << id();
1122  os << "\n - context data: " << Brief(context_data());
1123  os << "\n - wrapper: " << Brief(wrapper());
1124  os << "\n - compilation type: " << compilation_type();
1125  os << "\n - line ends: " << Brief(line_ends());
1126  os << "\n - eval from shared: " << Brief(eval_from_shared());
1127  os << "\n - eval from instructions offset: "
1128     << eval_from_instructions_offset();
1129  os << "\n - shared function infos: " << Brief(shared_function_infos());
1130  os << "\n";
1131}
1132
1133
1134void DebugInfo::DebugInfoPrint(std::ostream& os) {  // NOLINT
1135  HeapObject::PrintHeader(os, "DebugInfo");
1136  os << "\n - shared: " << Brief(shared());
1137  os << "\n - code: " << Brief(code());
1138  os << "\n - break_points: ";
1139  break_points()->Print(os);
1140}
1141
1142
1143void BreakPointInfo::BreakPointInfoPrint(std::ostream& os) {  // NOLINT
1144  HeapObject::PrintHeader(os, "BreakPointInfo");
1145  os << "\n - code_position: " << code_position();
1146  os << "\n - source_position: " << source_position();
1147  os << "\n - statement_position: " << statement_position();
1148  os << "\n - break_point_objects: " << Brief(break_point_objects());
1149  os << "\n";
1150}
1151
1152
1153static void PrintBitMask(std::ostream& os, uint32_t value) {  // NOLINT
1154  for (int i = 0; i < 32; i++) {
1155    if ((i & 7) == 0) os << " ";
1156    os << (((value & 1) == 0) ? "_" : "x");
1157    value >>= 1;
1158  }
1159}
1160
1161
1162void LayoutDescriptor::Print() {
1163  OFStream os(stdout);
1164  this->Print(os);
1165  os << std::flush;
1166}
1167
1168
1169void LayoutDescriptor::Print(std::ostream& os) {  // NOLINT
1170  os << "Layout descriptor: ";
1171  if (IsUninitialized()) {
1172    os << "<uninitialized>";
1173  } else if (IsFastPointerLayout()) {
1174    os << "<all tagged>";
1175  } else if (IsSmi()) {
1176    os << "fast";
1177    PrintBitMask(os, static_cast<uint32_t>(Smi::cast(this)->value()));
1178  } else {
1179    os << "slow";
1180    int len = length();
1181    for (int i = 0; i < len; i++) {
1182      if (i > 0) os << " |";
1183      PrintBitMask(os, get_scalar(i));
1184    }
1185  }
1186  os << "\n";
1187}
1188
1189
1190#endif  // OBJECT_PRINT
1191
1192
1193#if TRACE_MAPS
1194
1195
1196void Name::NameShortPrint() {
1197  if (this->IsString()) {
1198    PrintF("%s", String::cast(this)->ToCString().get());
1199  } else {
1200    DCHECK(this->IsSymbol());
1201    Symbol* s = Symbol::cast(this);
1202    if (s->name()->IsUndefined()) {
1203      PrintF("#<%s>", s->PrivateSymbolToName());
1204    } else {
1205      PrintF("<%s>", String::cast(s->name())->ToCString().get());
1206    }
1207  }
1208}
1209
1210
1211int Name::NameShortPrint(Vector<char> str) {
1212  if (this->IsString()) {
1213    return SNPrintF(str, "%s", String::cast(this)->ToCString().get());
1214  } else {
1215    DCHECK(this->IsSymbol());
1216    Symbol* s = Symbol::cast(this);
1217    if (s->name()->IsUndefined()) {
1218      return SNPrintF(str, "#<%s>", s->PrivateSymbolToName());
1219    } else {
1220      return SNPrintF(str, "<%s>", String::cast(s->name())->ToCString().get());
1221    }
1222  }
1223}
1224
1225
1226#endif  // TRACE_MAPS
1227
1228
1229#if defined(DEBUG) || defined(OBJECT_PRINT)
1230// This method is only meant to be called from gdb for debugging purposes.
1231// Since the string can also be in two-byte encoding, non-Latin1 characters
1232// will be ignored in the output.
1233char* String::ToAsciiArray() {
1234  // Static so that subsequent calls frees previously allocated space.
1235  // This also means that previous results will be overwritten.
1236  static char* buffer = NULL;
1237  if (buffer != NULL) delete[] buffer;
1238  buffer = new char[length() + 1];
1239  WriteToFlat(this, reinterpret_cast<uint8_t*>(buffer), 0, length());
1240  buffer[length()] = 0;
1241  return buffer;
1242}
1243
1244
1245void DescriptorArray::Print() {
1246  OFStream os(stdout);
1247  this->PrintDescriptors(os);
1248  os << std::flush;
1249}
1250
1251
1252void DescriptorArray::PrintDescriptors(std::ostream& os) {  // NOLINT
1253  HandleScope scope(GetIsolate());
1254  os << "Descriptor array #" << number_of_descriptors();
1255  for (int i = 0; i < number_of_descriptors(); i++) {
1256    Descriptor desc;
1257    Get(i, &desc);
1258    os << "\n " << i << ": " << desc;
1259  }
1260  os << "\n";
1261}
1262
1263
1264void TransitionArray::Print() {
1265  OFStream os(stdout);
1266  TransitionArray::PrintTransitions(os, this);
1267  os << "\n" << std::flush;
1268}
1269
1270
1271void TransitionArray::PrintTransitions(std::ostream& os, Object* transitions,
1272                                       bool print_header) {  // NOLINT
1273  int num_transitions = NumberOfTransitions(transitions);
1274  if (print_header) {
1275    os << "Transition array #" << num_transitions << ":";
1276  }
1277  for (int i = 0; i < num_transitions; i++) {
1278    Name* key = GetKey(transitions, i);
1279    Map* target = GetTarget(transitions, i);
1280    os << "\n   ";
1281#ifdef OBJECT_PRINT
1282    key->NamePrint(os);
1283#else
1284    key->ShortPrint(os);
1285#endif
1286    os << ": ";
1287    Heap* heap = key->GetHeap();
1288    if (key == heap->nonextensible_symbol()) {
1289      os << "(transition to non-extensible)";
1290    } else if (key == heap->sealed_symbol()) {
1291      os << "(transition to sealed)";
1292    } else if (key == heap->frozen_symbol()) {
1293      os << "(transition to frozen)";
1294    } else if (key == heap->elements_transition_symbol()) {
1295      os << "(transition to " << ElementsKindToString(target->elements_kind())
1296         << ")";
1297    } else if (key == heap->strict_function_transition_symbol()) {
1298      os << " (transition to strict function)";
1299    } else if (key == heap->strong_function_transition_symbol()) {
1300      os << " (transition to strong function)";
1301    } else if (key == heap->observed_symbol()) {
1302      os << " (transition to Object.observe)";
1303    } else {
1304      PropertyDetails details = GetTargetDetails(key, target);
1305      os << "(transition to ";
1306      if (details.location() == kDescriptor) {
1307        os << "immutable ";
1308      }
1309      os << (details.kind() == kData ? "data" : "accessor");
1310      if (details.location() == kDescriptor) {
1311        Object* value =
1312            target->instance_descriptors()->GetValue(target->LastAdded());
1313        os << " " << Brief(value);
1314      }
1315      os << "), attrs: " << details.attributes();
1316    }
1317    os << " -> " << Brief(target);
1318  }
1319}
1320
1321
1322void JSObject::PrintTransitions(std::ostream& os) {  // NOLINT
1323  Object* transitions = map()->raw_transitions();
1324  int num_transitions = TransitionArray::NumberOfTransitions(transitions);
1325  if (num_transitions == 0) return;
1326  os << "\n - transitions";
1327  TransitionArray::PrintTransitions(os, transitions, false);
1328}
1329#endif  // defined(DEBUG) || defined(OBJECT_PRINT)
1330}  // namespace internal
1331}  // namespace v8
1332