• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <iomanip>
6 #include <memory>
7 
8 #include "src/common/globals.h"
9 #include "src/diagnostics/disasm.h"
10 #include "src/diagnostics/disassembler.h"
11 #include "src/execution/isolate-utils-inl.h"
12 #include "src/heap/heap-inl.h"                // For InOldSpace.
13 #include "src/heap/heap-write-barrier-inl.h"  // For GetIsolateFromWritableObj.
14 #include "src/ic/handler-configuration-inl.h"
15 #include "src/init/bootstrapper.h"
16 #include "src/interpreter/bytecodes.h"
17 #include "src/objects/all-objects-inl.h"
18 #include "src/objects/code-kind.h"
19 #include "src/regexp/regexp.h"
20 #include "src/snapshot/embedded/embedded-data.h"
21 #include "src/utils/ostreams.h"
22 
23 #if V8_ENABLE_WEBASSEMBLY
24 #include "src/debug/debug-wasm-objects-inl.h"
25 #include "src/wasm/wasm-code-manager.h"
26 #include "src/wasm/wasm-engine.h"
27 #include "src/wasm/wasm-objects-inl.h"
28 #endif  // V8_ENABLE_WEBASSEMBLY
29 
30 namespace v8 {
31 namespace internal {
32 
33 #ifdef OBJECT_PRINT
34 
Print() const35 void Object::Print() const {
36   // Output into debugger's command window if a debugger is attached.
37   DbgStdoutStream dbg_os;
38   this->Print(dbg_os);
39   dbg_os << std::flush;
40 
41   StdoutStream os;
42   this->Print(os);
43   os << std::flush;
44 }
45 
Print(std::ostream & os) const46 void Object::Print(std::ostream& os) const {
47   if (IsSmi()) {
48     os << "Smi: " << std::hex << "0x" << Smi::ToInt(*this);
49     os << std::dec << " (" << Smi::ToInt(*this) << ")\n";
50   } else {
51     HeapObject::cast(*this).HeapObjectPrint(os);
52   }
53 }
54 
55 namespace {
56 
PrintHeapObjectHeaderWithoutMap(HeapObject object,std::ostream & os,const char * id)57 void PrintHeapObjectHeaderWithoutMap(HeapObject object, std::ostream& os,
58                                      const char* id) {
59   PtrComprCageBase cage_base = GetPtrComprCageBaseSlow(object);
60   os << reinterpret_cast<void*>(object.ptr()) << ": [";
61   if (id != nullptr) {
62     os << id;
63   } else {
64     os << object.map(cage_base).instance_type();
65   }
66   os << "]";
67   if (ReadOnlyHeap::Contains(object)) {
68     os << " in ReadOnlySpace";
69   } else if (GetHeapFromWritableObject(object)->InOldSpace(object)) {
70     os << " in OldSpace";
71   }
72 }
73 
74 template <typename T>
PrintDictionaryContents(std::ostream & os,T dict)75 void PrintDictionaryContents(std::ostream& os, T dict) {
76   DisallowGarbageCollection no_gc;
77   ReadOnlyRoots roots = dict.GetReadOnlyRoots();
78 
79   if (dict.Capacity() == 0) {
80     return;
81   }
82 
83 #ifdef V8_ENABLE_SWISS_NAME_DICTIONARY
84   Isolate* isolate = GetIsolateFromWritableObject(dict);
85   // IterateEntries for SwissNameDictionary needs to create a handle.
86   HandleScope scope(isolate);
87 #endif
88   for (InternalIndex i : dict.IterateEntries()) {
89     Object k;
90     if (!dict.ToKey(roots, i, &k)) continue;
91     os << "\n   ";
92     if (k.IsString()) {
93       String::cast(k).PrintUC16(os);
94     } else {
95       os << Brief(k);
96     }
97     os << ": " << Brief(dict.ValueAt(i)) << " ";
98     dict.DetailsAt(i).PrintAsSlowTo(os, !T::kIsOrderedDictionaryType);
99   }
100 }
101 }  // namespace
102 
PrintHeader(std::ostream & os,const char * id)103 void HeapObject::PrintHeader(std::ostream& os, const char* id) {
104   PrintHeapObjectHeaderWithoutMap(*this, os, id);
105   PtrComprCageBase cage_base = GetPtrComprCageBaseSlow(*this);
106   if (!IsMap(cage_base)) os << "\n - map: " << Brief(map(cage_base));
107 }
108 
HeapObjectPrint(std::ostream & os)109 void HeapObject::HeapObjectPrint(std::ostream& os) {
110   PtrComprCageBase cage_base = GetPtrComprCageBaseSlow(*this);
111 
112   InstanceType instance_type = map(cage_base).instance_type();
113 
114   if (instance_type < FIRST_NONSTRING_TYPE) {
115     String::cast(*this).StringPrint(os);
116     os << "\n";
117     return;
118   }
119 
120   switch (instance_type) {
121     case AWAIT_CONTEXT_TYPE:
122     case BLOCK_CONTEXT_TYPE:
123     case CATCH_CONTEXT_TYPE:
124     case DEBUG_EVALUATE_CONTEXT_TYPE:
125     case EVAL_CONTEXT_TYPE:
126     case FUNCTION_CONTEXT_TYPE:
127     case MODULE_CONTEXT_TYPE:
128     case SCRIPT_CONTEXT_TYPE:
129     case WITH_CONTEXT_TYPE:
130       Context::cast(*this).ContextPrint(os);
131       break;
132     case SCRIPT_CONTEXT_TABLE_TYPE:
133       FixedArray::cast(*this).FixedArrayPrint(os);
134       break;
135     case NATIVE_CONTEXT_TYPE:
136       NativeContext::cast(*this).NativeContextPrint(os);
137       break;
138     case HASH_TABLE_TYPE:
139       ObjectHashTable::cast(*this).ObjectHashTablePrint(os);
140       break;
141     case NAME_TO_INDEX_HASH_TABLE_TYPE:
142       NameToIndexHashTable::cast(*this).NameToIndexHashTablePrint(os);
143       break;
144     case REGISTERED_SYMBOL_TABLE_TYPE:
145       RegisteredSymbolTable::cast(*this).RegisteredSymbolTablePrint(os);
146       break;
147     case ORDERED_HASH_MAP_TYPE:
148       OrderedHashMap::cast(*this).OrderedHashMapPrint(os);
149       break;
150     case ORDERED_HASH_SET_TYPE:
151       OrderedHashSet::cast(*this).OrderedHashSetPrint(os);
152       break;
153     case ORDERED_NAME_DICTIONARY_TYPE:
154       OrderedNameDictionary::cast(*this).OrderedNameDictionaryPrint(os);
155       break;
156     case NAME_DICTIONARY_TYPE:
157       NameDictionary::cast(*this).NameDictionaryPrint(os);
158       break;
159     case GLOBAL_DICTIONARY_TYPE:
160       GlobalDictionary::cast(*this).GlobalDictionaryPrint(os);
161       break;
162     case SIMPLE_NUMBER_DICTIONARY_TYPE:
163       FixedArray::cast(*this).FixedArrayPrint(os);
164       break;
165     case NUMBER_DICTIONARY_TYPE:
166       NumberDictionary::cast(*this).NumberDictionaryPrint(os);
167       break;
168     case EPHEMERON_HASH_TABLE_TYPE:
169       EphemeronHashTable::cast(*this).EphemeronHashTablePrint(os);
170       break;
171     case OBJECT_BOILERPLATE_DESCRIPTION_TYPE:
172       ObjectBoilerplateDescription::cast(*this)
173           .ObjectBoilerplateDescriptionPrint(os);
174       break;
175     case TRANSITION_ARRAY_TYPE:
176       TransitionArray::cast(*this).TransitionArrayPrint(os);
177       break;
178     case CLOSURE_FEEDBACK_CELL_ARRAY_TYPE:
179       ClosureFeedbackCellArray::cast(*this).ClosureFeedbackCellArrayPrint(os);
180       break;
181 
182     case FILLER_TYPE:
183       os << "filler";
184       break;
185     case JS_API_OBJECT_TYPE:
186     case JS_ARRAY_ITERATOR_PROTOTYPE_TYPE:
187     case JS_CONTEXT_EXTENSION_OBJECT_TYPE:
188     case JS_ERROR_TYPE:
189     case JS_ITERATOR_PROTOTYPE_TYPE:
190     case JS_MAP_ITERATOR_PROTOTYPE_TYPE:
191     case JS_OBJECT_PROTOTYPE_TYPE:
192     case JS_PROMISE_PROTOTYPE_TYPE:
193     case JS_REG_EXP_PROTOTYPE_TYPE:
194     case JS_SET_ITERATOR_PROTOTYPE_TYPE:
195     case JS_SET_PROTOTYPE_TYPE:
196     case JS_SPECIAL_API_OBJECT_TYPE:
197     case JS_STRING_ITERATOR_PROTOTYPE_TYPE:
198     case JS_TYPED_ARRAY_PROTOTYPE_TYPE:
199       JSObject::cast(*this).JSObjectPrint(os);
200       break;
201 #if V8_ENABLE_WEBASSEMBLY
202     case WASM_INSTANCE_OBJECT_TYPE:
203       WasmInstanceObject::cast(*this).WasmInstanceObjectPrint(os);
204       break;
205     case WASM_VALUE_OBJECT_TYPE:
206       WasmValueObject::cast(*this).WasmValueObjectPrint(os);
207       break;
208 #endif  // V8_ENABLE_WEBASSEMBLY
209     case CODE_TYPE:
210       Code::cast(*this).CodePrint(os);
211       break;
212     case CODE_DATA_CONTAINER_TYPE:
213       CodeDataContainer::cast(*this).CodeDataContainerPrint(os);
214       break;
215     case JS_SET_KEY_VALUE_ITERATOR_TYPE:
216     case JS_SET_VALUE_ITERATOR_TYPE:
217       JSSetIterator::cast(*this).JSSetIteratorPrint(os);
218       break;
219     case JS_MAP_KEY_ITERATOR_TYPE:
220     case JS_MAP_KEY_VALUE_ITERATOR_TYPE:
221     case JS_MAP_VALUE_ITERATOR_TYPE:
222       JSMapIterator::cast(*this).JSMapIteratorPrint(os);
223       break;
224 #define MAKE_TORQUE_CASE(Name, TYPE)   \
225   case TYPE:                           \
226     Name::cast(*this).Name##Print(os); \
227     break;
228       // Every class that has its fields defined in a .tq file and corresponds
229       // to exactly one InstanceType value is included in the following list.
230       TORQUE_INSTANCE_CHECKERS_SINGLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
231       TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)
232 #undef MAKE_TORQUE_CASE
233 
234     case ALLOCATION_SITE_TYPE:
235       AllocationSite::cast(*this).AllocationSitePrint(os);
236       break;
237     case LOAD_HANDLER_TYPE:
238       LoadHandler::cast(*this).LoadHandlerPrint(os);
239       break;
240     case STORE_HANDLER_TYPE:
241       StoreHandler::cast(*this).StoreHandlerPrint(os);
242       break;
243     case FEEDBACK_METADATA_TYPE:
244       FeedbackMetadata::cast(*this).FeedbackMetadataPrint(os);
245       break;
246     case BIG_INT_BASE_TYPE:
247       BigIntBase::cast(*this).BigIntBasePrint(os);
248       break;
249     case JS_CLASS_CONSTRUCTOR_TYPE:
250     case JS_PROMISE_CONSTRUCTOR_TYPE:
251     case JS_REG_EXP_CONSTRUCTOR_TYPE:
252     case JS_ARRAY_CONSTRUCTOR_TYPE:
253 #define TYPED_ARRAY_CONSTRUCTORS_SWITCH(Type, type, TYPE, Ctype) \
254   case TYPE##_TYPED_ARRAY_CONSTRUCTOR_TYPE:
255       TYPED_ARRAYS(TYPED_ARRAY_CONSTRUCTORS_SWITCH)
256 #undef TYPED_ARRAY_CONSTRUCTORS_SWITCH
257       JSFunction::cast(*this).JSFunctionPrint(os);
258       break;
259     case INTERNALIZED_STRING_TYPE:
260     case EXTERNAL_INTERNALIZED_STRING_TYPE:
261     case ONE_BYTE_INTERNALIZED_STRING_TYPE:
262     case EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
263     case UNCACHED_EXTERNAL_INTERNALIZED_STRING_TYPE:
264     case UNCACHED_EXTERNAL_ONE_BYTE_INTERNALIZED_STRING_TYPE:
265     case STRING_TYPE:
266     case CONS_STRING_TYPE:
267     case EXTERNAL_STRING_TYPE:
268     case SLICED_STRING_TYPE:
269     case THIN_STRING_TYPE:
270     case ONE_BYTE_STRING_TYPE:
271     case CONS_ONE_BYTE_STRING_TYPE:
272     case EXTERNAL_ONE_BYTE_STRING_TYPE:
273     case SLICED_ONE_BYTE_STRING_TYPE:
274     case THIN_ONE_BYTE_STRING_TYPE:
275     case UNCACHED_EXTERNAL_STRING_TYPE:
276     case UNCACHED_EXTERNAL_ONE_BYTE_STRING_TYPE:
277     case SHARED_STRING_TYPE:
278     case SHARED_ONE_BYTE_STRING_TYPE:
279     case SHARED_THIN_STRING_TYPE:
280     case SHARED_THIN_ONE_BYTE_STRING_TYPE:
281     case JS_LAST_DUMMY_API_OBJECT_TYPE:
282       // TODO(all): Handle these types too.
283       os << "UNKNOWN TYPE " << map().instance_type();
284       UNREACHABLE();
285   }
286 }
287 
ByteArrayPrint(std::ostream & os)288 void ByteArray::ByteArrayPrint(std::ostream& os) {
289   PrintHeader(os, "ByteArray");
290   os << "\n - length: " << length()
291      << "\n - data-start: " << static_cast<void*>(GetDataStartAddress())
292      << "\n";
293 }
294 
BytecodeArrayPrint(std::ostream & os)295 void BytecodeArray::BytecodeArrayPrint(std::ostream& os) {
296   PrintHeader(os, "BytecodeArray");
297   os << "\n";
298   Disassemble(os);
299 }
300 
FreeSpacePrint(std::ostream & os)301 void FreeSpace::FreeSpacePrint(std::ostream& os) {
302   os << "free space, size " << Size() << "\n";
303 }
304 
PrintProperties(std::ostream & os)305 bool JSObject::PrintProperties(std::ostream& os) {
306   if (HasFastProperties()) {
307     DescriptorArray descs = map().instance_descriptors(GetIsolate());
308     int nof_inobject_properties = map().GetInObjectProperties();
309     for (InternalIndex i : map().IterateOwnDescriptors()) {
310       os << "\n    ";
311       descs.GetKey(i).NamePrint(os);
312       os << ": ";
313       PropertyDetails details = descs.GetDetails(i);
314       switch (details.location()) {
315         case PropertyLocation::kField: {
316           FieldIndex field_index = FieldIndex::ForDescriptor(map(), i);
317           os << Brief(RawFastPropertyAt(field_index));
318           break;
319         }
320         case PropertyLocation::kDescriptor:
321           os << Brief(descs.GetStrongValue(i));
322           break;
323       }
324       os << " ";
325       details.PrintAsFastTo(os, PropertyDetails::kForProperties);
326       if (details.location() == PropertyLocation::kField) {
327         int field_index = details.field_index();
328         if (field_index < nof_inobject_properties) {
329           os << ", location: in-object";
330         } else {
331           field_index -= nof_inobject_properties;
332           os << ", location: properties[" << field_index << "]";
333         }
334       } else {
335         os << ", location: descriptor";
336       }
337     }
338     return map().NumberOfOwnDescriptors() > 0;
339   } else if (IsJSGlobalObject()) {
340     PrintDictionaryContents(
341         os, JSGlobalObject::cast(*this).global_dictionary(kAcquireLoad));
342   } else if (V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL) {
343     PrintDictionaryContents(os, property_dictionary_swiss());
344   } else {
345     PrintDictionaryContents(os, property_dictionary());
346   }
347   return true;
348 }
349 
350 namespace {
351 
352 template <class T>
IsTheHoleAt(T array,int index)353 bool IsTheHoleAt(T array, int index) {
354   return false;
355 }
356 
357 template <>
IsTheHoleAt(FixedDoubleArray array,int index)358 bool IsTheHoleAt(FixedDoubleArray array, int index) {
359   return array.is_the_hole(index);
360 }
361 
362 template <class T>
GetScalarElement(T array,int index)363 double GetScalarElement(T array, int index) {
364   if (IsTheHoleAt(array, index)) {
365     return std::numeric_limits<double>::quiet_NaN();
366   }
367   return array.get_scalar(index);
368 }
369 
370 template <class T>
DoPrintElements(std::ostream & os,Object object,int length)371 void DoPrintElements(std::ostream& os, Object object, int length) {
372   const bool print_the_hole = std::is_same<T, FixedDoubleArray>::value;
373   T array = T::cast(object);
374   if (length == 0) return;
375   int previous_index = 0;
376   double previous_value = GetScalarElement(array, 0);
377   double value = 0.0;
378   int i;
379   for (i = 1; i <= length; i++) {
380     if (i < length) value = GetScalarElement(array, i);
381     bool values_are_nan = std::isnan(previous_value) && std::isnan(value);
382     if (i != length && (previous_value == value || values_are_nan) &&
383         IsTheHoleAt(array, i - 1) == IsTheHoleAt(array, i)) {
384       continue;
385     }
386     os << "\n";
387     std::stringstream ss;
388     ss << previous_index;
389     if (previous_index != i - 1) {
390       ss << '-' << (i - 1);
391     }
392     os << std::setw(12) << ss.str() << ": ";
393     if (print_the_hole && IsTheHoleAt(array, i - 1)) {
394       os << "<the_hole>";
395     } else {
396       os << previous_value;
397     }
398     previous_index = i;
399     previous_value = value;
400   }
401 }
402 
403 template <typename ElementType>
PrintTypedArrayElements(std::ostream & os,const ElementType * data_ptr,size_t length,bool is_on_heap)404 void PrintTypedArrayElements(std::ostream& os, const ElementType* data_ptr,
405                              size_t length, bool is_on_heap) {
406   if (length == 0) return;
407   size_t previous_index = 0;
408   if (i::FLAG_mock_arraybuffer_allocator && !is_on_heap) {
409     // Don't try to print data that's not actually allocated.
410     os << "\n    0-" << length << ": <mocked array buffer bytes>";
411     return;
412   }
413 
414   ElementType previous_value = data_ptr[0];
415   ElementType value = 0;
416   for (size_t i = 1; i <= length; i++) {
417     if (i < length) value = data_ptr[i];
418     if (i != length && previous_value == value) {
419       continue;
420     }
421     os << "\n";
422     std::stringstream ss;
423     ss << previous_index;
424     if (previous_index != i - 1) {
425       ss << '-' << (i - 1);
426     }
427     os << std::setw(12) << ss.str() << ": " << +previous_value;
428     previous_index = i;
429     previous_value = value;
430   }
431 }
432 
433 template <typename T>
PrintFixedArrayElements(std::ostream & os,T array)434 void PrintFixedArrayElements(std::ostream& os, T array) {
435   // Print in array notation for non-sparse arrays.
436   Object previous_value = array.length() > 0 ? array.get(0) : Object();
437   Object value;
438   int previous_index = 0;
439   int i;
440   for (i = 1; i <= array.length(); i++) {
441     if (i < array.length()) value = array.get(i);
442     if (previous_value == value && i != array.length()) {
443       continue;
444     }
445     os << "\n";
446     std::stringstream ss;
447     ss << previous_index;
448     if (previous_index != i - 1) {
449       ss << '-' << (i - 1);
450     }
451     os << std::setw(12) << ss.str() << ": " << Brief(previous_value);
452     previous_index = i;
453     previous_value = value;
454   }
455 }
456 
PrintDictionaryElements(std::ostream & os,FixedArrayBase elements)457 void PrintDictionaryElements(std::ostream& os, FixedArrayBase elements) {
458   // Print some internal fields
459   NumberDictionary dict = NumberDictionary::cast(elements);
460   if (dict.requires_slow_elements()) {
461     os << "\n   - requires_slow_elements";
462   } else {
463     os << "\n   - max_number_key: " << dict.max_number_key();
464   }
465   PrintDictionaryContents(os, dict);
466 }
467 
PrintSloppyArgumentElements(std::ostream & os,ElementsKind kind,SloppyArgumentsElements elements)468 void PrintSloppyArgumentElements(std::ostream& os, ElementsKind kind,
469                                  SloppyArgumentsElements elements) {
470   FixedArray arguments_store = elements.arguments();
471   os << "\n    0: context: " << Brief(elements.context())
472      << "\n    1: arguments_store: " << Brief(arguments_store)
473      << "\n    parameter to context slot map:";
474   for (int i = 0; i < elements.length(); i++) {
475     Object mapped_entry = elements.mapped_entries(i, kRelaxedLoad);
476     os << "\n    " << i << ": param(" << i << "): " << Brief(mapped_entry);
477     if (mapped_entry.IsTheHole()) {
478       os << " in the arguments_store[" << i << "]";
479     } else {
480       os << " in the context";
481     }
482   }
483   if (arguments_store.length() == 0) return;
484   os << "\n }"
485      << "\n - arguments_store: " << Brief(arguments_store) << " "
486      << ElementsKindToString(arguments_store.map().elements_kind()) << " {";
487   if (kind == FAST_SLOPPY_ARGUMENTS_ELEMENTS) {
488     PrintFixedArrayElements(os, arguments_store);
489   } else {
490     DCHECK_EQ(kind, SLOW_SLOPPY_ARGUMENTS_ELEMENTS);
491     PrintDictionaryElements(os, arguments_store);
492   }
493 }
494 
PrintEmbedderData(Isolate * isolate,std::ostream & os,EmbedderDataSlot slot)495 void PrintEmbedderData(Isolate* isolate, std::ostream& os,
496                        EmbedderDataSlot slot) {
497   DisallowGarbageCollection no_gc;
498   Object value = slot.load_tagged();
499   os << Brief(value);
500   void* raw_pointer;
501   if (slot.ToAlignedPointer(isolate, &raw_pointer)) {
502     os << ", aligned pointer: " << raw_pointer;
503   }
504 }
505 
506 }  // namespace
507 
PrintElements(std::ostream & os)508 void JSObject::PrintElements(std::ostream& os) {
509   // Don't call GetElementsKind, its validation code can cause the printer to
510   // fail when debugging.
511   os << " - elements: " << Brief(elements()) << " {";
512   switch (map().elements_kind()) {
513     case HOLEY_SMI_ELEMENTS:
514     case PACKED_SMI_ELEMENTS:
515     case HOLEY_ELEMENTS:
516     case HOLEY_FROZEN_ELEMENTS:
517     case HOLEY_SEALED_ELEMENTS:
518     case HOLEY_NONEXTENSIBLE_ELEMENTS:
519     case PACKED_ELEMENTS:
520     case PACKED_FROZEN_ELEMENTS:
521     case PACKED_SEALED_ELEMENTS:
522     case PACKED_NONEXTENSIBLE_ELEMENTS:
523     case FAST_STRING_WRAPPER_ELEMENTS: {
524       PrintFixedArrayElements(os, FixedArray::cast(elements()));
525       break;
526     }
527     case HOLEY_DOUBLE_ELEMENTS:
528     case PACKED_DOUBLE_ELEMENTS: {
529       DoPrintElements<FixedDoubleArray>(os, elements(), elements().length());
530       break;
531     }
532 
533 #define PRINT_ELEMENTS(Type, type, TYPE, elementType)                         \
534   case TYPE##_ELEMENTS: {                                                     \
535     size_t length = JSTypedArray::cast(*this).GetLength();                    \
536     bool is_on_heap = JSTypedArray::cast(*this).is_on_heap();                 \
537     const elementType* data_ptr =                                             \
538         static_cast<const elementType*>(JSTypedArray::cast(*this).DataPtr()); \
539     PrintTypedArrayElements<elementType>(os, data_ptr, length, is_on_heap);   \
540     break;                                                                    \
541   }
542       TYPED_ARRAYS(PRINT_ELEMENTS)
543       RAB_GSAB_TYPED_ARRAYS(PRINT_ELEMENTS)
544 #undef PRINT_ELEMENTS
545 
546     case DICTIONARY_ELEMENTS:
547     case SLOW_STRING_WRAPPER_ELEMENTS:
548       PrintDictionaryElements(os, elements());
549       break;
550     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
551     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
552       PrintSloppyArgumentElements(os, map().elements_kind(),
553                                   SloppyArgumentsElements::cast(elements()));
554       break;
555     case WASM_ARRAY_ELEMENTS:
556       // WasmArrayPrint() should be called intead.
557       UNREACHABLE();
558     case NO_ELEMENTS:
559       break;
560   }
561   os << "\n }\n";
562 }
563 
JSObjectPrintHeader(std::ostream & os,JSObject obj,const char * id)564 static void JSObjectPrintHeader(std::ostream& os, JSObject obj,
565                                 const char* id) {
566   Isolate* isolate = obj.GetIsolate();
567   obj.PrintHeader(os, id);
568   // Don't call GetElementsKind, its validation code can cause the printer to
569   // fail when debugging.
570   os << " [";
571   if (obj.HasFastProperties()) {
572     os << "FastProperties";
573   } else {
574     os << "DictionaryProperties";
575   }
576   PrototypeIterator iter(isolate, obj);
577   os << "]\n - prototype: " << Brief(iter.GetCurrent());
578   os << "\n - elements: " << Brief(obj.elements()) << " ["
579      << ElementsKindToString(obj.map().elements_kind());
580   if (obj.elements().IsCowArray()) os << " (COW)";
581   os << "]";
582   Object hash = obj.GetHash();
583   if (hash.IsSmi()) {
584     os << "\n - hash: " << Brief(hash);
585   }
586   if (obj.GetEmbedderFieldCount() > 0) {
587     os << "\n - embedder fields: " << obj.GetEmbedderFieldCount();
588   }
589 }
590 
JSObjectPrintBody(std::ostream & os,JSObject obj,bool print_elements=true)591 static void JSObjectPrintBody(std::ostream& os, JSObject obj,
592                               bool print_elements = true) {
593   os << "\n - properties: ";
594   Object properties_or_hash = obj.raw_properties_or_hash(kRelaxedLoad);
595   if (!properties_or_hash.IsSmi()) {
596     os << Brief(properties_or_hash);
597   }
598   os << "\n - All own properties (excluding elements): {";
599   if (obj.PrintProperties(os)) os << "\n ";
600   os << "}\n";
601 
602   if (print_elements) {
603     size_t length = obj.IsJSTypedArray() ? JSTypedArray::cast(obj).GetLength()
604                                          : obj.elements().length();
605     if (length > 0) obj.PrintElements(os);
606   }
607   int embedder_fields = obj.GetEmbedderFieldCount();
608   if (embedder_fields > 0) {
609     Isolate* isolate = GetIsolateForSandbox(obj);
610     os << " - embedder fields = {";
611     for (int i = 0; i < embedder_fields; i++) {
612       os << "\n    ";
613       PrintEmbedderData(isolate, os, EmbedderDataSlot(obj, i));
614     }
615     os << "\n }\n";
616   }
617 }
618 
JSObjectPrint(std::ostream & os)619 void JSObject::JSObjectPrint(std::ostream& os) {
620   JSObjectPrintHeader(os, *this, nullptr);
621   JSObjectPrintBody(os, *this);
622 }
623 
JSGeneratorObjectPrint(std::ostream & os)624 void JSGeneratorObject::JSGeneratorObjectPrint(std::ostream& os) {
625   JSObjectPrintHeader(os, *this, "JSGeneratorObject");
626   os << "\n - function: " << Brief(function());
627   os << "\n - context: " << Brief(context());
628   os << "\n - receiver: " << Brief(receiver());
629   if (is_executing() || is_closed()) {
630     os << "\n - input: " << Brief(input_or_debug_pos());
631   } else {
632     DCHECK(is_suspended());
633     os << "\n - debug pos: " << Brief(input_or_debug_pos());
634   }
635   const char* mode = "(invalid)";
636   switch (resume_mode()) {
637     case kNext:
638       mode = ".next()";
639       break;
640     case kReturn:
641       mode = ".return()";
642       break;
643     case kThrow:
644       mode = ".throw()";
645       break;
646   }
647   os << "\n - resume mode: " << mode;
648   os << "\n - continuation: " << continuation();
649   if (is_closed()) os << " (closed)";
650   if (is_executing()) os << " (executing)";
651   if (is_suspended()) os << " (suspended)";
652   if (is_suspended()) {
653     DisallowGarbageCollection no_gc;
654     SharedFunctionInfo fun_info = function().shared();
655     if (fun_info.HasSourceCode()) {
656       Script script = Script::cast(fun_info.script());
657       String script_name = script.name().IsString()
658                                ? String::cast(script.name())
659                                : GetReadOnlyRoots().empty_string();
660 
661       os << "\n - source position: ";
662       // Can't collect source positions here if not available as that would
663       // allocate memory.
664       Isolate* isolate = GetIsolate();
665       if (fun_info.HasBytecodeArray() &&
666           fun_info.GetBytecodeArray(isolate).HasSourcePositionTable()) {
667         os << source_position();
668         os << " (";
669         script_name.PrintUC16(os);
670         int lin = script.GetLineNumber(source_position()) + 1;
671         int col = script.GetColumnNumber(source_position()) + 1;
672         os << ", lin " << lin;
673         os << ", col " << col;
674       } else {
675         os << "unavailable";
676       }
677       os << ")";
678     }
679   }
680   os << "\n - register file: " << Brief(parameters_and_registers());
681   JSObjectPrintBody(os, *this);
682 }
683 
JSArrayPrint(std::ostream & os)684 void JSArray::JSArrayPrint(std::ostream& os) {
685   JSObjectPrintHeader(os, *this, "JSArray");
686   os << "\n - length: " << Brief(this->length());
687   JSObjectPrintBody(os, *this);
688 }
689 
JSPromisePrint(std::ostream & os)690 void JSPromise::JSPromisePrint(std::ostream& os) {
691   JSObjectPrintHeader(os, *this, "JSPromise");
692   os << "\n - status: " << JSPromise::Status(status());
693   if (status() == Promise::kPending) {
694     os << "\n - reactions: " << Brief(reactions());
695   } else {
696     os << "\n - result: " << Brief(result());
697   }
698   os << "\n - has_handler: " << has_handler();
699   os << "\n - handled_hint: " << handled_hint();
700   os << "\n - is_silent: " << is_silent();
701   JSObjectPrintBody(os, *this);
702 }
703 
JSRegExpPrint(std::ostream & os)704 void JSRegExp::JSRegExpPrint(std::ostream& os) {
705   Isolate* isolate = GetIsolate();
706   JSObjectPrintHeader(os, *this, "JSRegExp");
707   os << "\n - data: " << Brief(data());
708   os << "\n - source: " << Brief(source());
709   os << "\n - flags: " << Brief(*JSRegExp::StringFromFlags(isolate, flags()));
710   JSObjectPrintBody(os, *this);
711 }
712 
JSRegExpStringIteratorPrint(std::ostream & os)713 void JSRegExpStringIterator::JSRegExpStringIteratorPrint(std::ostream& os) {
714   JSObjectPrintHeader(os, *this, "JSRegExpStringIterator");
715   os << "\n - regex: " << Brief(iterating_reg_exp());
716   os << "\n - string: " << Brief(iterated_string());
717   os << "\n - done: " << done();
718   os << "\n - global: " << global();
719   os << "\n - unicode: " << unicode();
720   JSObjectPrintBody(os, *this);
721 }
722 
SymbolPrint(std::ostream & os)723 void Symbol::SymbolPrint(std::ostream& os) {
724   PrintHeader(os, "Symbol");
725   os << "\n - hash: " << hash();
726   os << "\n - description: " << Brief(description());
727   if (description().IsUndefined()) {
728     os << " (" << PrivateSymbolToName() << ")";
729   }
730   os << "\n - private: " << is_private();
731   os << "\n - private_name: " << is_private_name();
732   os << "\n - private_brand: " << is_private_brand();
733   os << "\n";
734 }
735 
DescriptorArrayPrint(std::ostream & os)736 void DescriptorArray::DescriptorArrayPrint(std::ostream& os) {
737   PrintHeader(os, "DescriptorArray");
738   os << "\n - enum_cache: ";
739   if (enum_cache().keys().length() == 0) {
740     os << "empty";
741   } else {
742     os << enum_cache().keys().length();
743     os << "\n   - keys: " << Brief(enum_cache().keys());
744     os << "\n   - indices: " << Brief(enum_cache().indices());
745   }
746   os << "\n - nof slack descriptors: " << number_of_slack_descriptors();
747   os << "\n - nof descriptors: " << number_of_descriptors();
748   int16_t raw_marked = raw_number_of_marked_descriptors();
749   os << "\n - raw marked descriptors: mc epoch "
750      << NumberOfMarkedDescriptors::Epoch::decode(raw_marked) << ", marked "
751      << NumberOfMarkedDescriptors::Marked::decode(raw_marked);
752   PrintDescriptors(os);
753 }
754 
755 namespace {
PrintFixedArrayWithHeader(std::ostream & os,FixedArray array,const char * type)756 void PrintFixedArrayWithHeader(std::ostream& os, FixedArray array,
757                                const char* type) {
758   array.PrintHeader(os, type);
759   os << "\n - length: " << array.length();
760   PrintFixedArrayElements(os, array);
761   os << "\n";
762 }
763 
764 template <typename T>
PrintWeakArrayElements(std::ostream & os,T * array)765 void PrintWeakArrayElements(std::ostream& os, T* array) {
766   // Print in array notation for non-sparse arrays.
767   MaybeObject previous_value =
768       array->length() > 0 ? array->Get(0) : MaybeObject(kNullAddress);
769   MaybeObject value;
770   int previous_index = 0;
771   int i;
772   for (i = 1; i <= array->length(); i++) {
773     if (i < array->length()) value = array->Get(i);
774     if (previous_value == value && i != array->length()) {
775       continue;
776     }
777     os << "\n";
778     std::stringstream ss;
779     ss << previous_index;
780     if (previous_index != i - 1) {
781       ss << '-' << (i - 1);
782     }
783     os << std::setw(12) << ss.str() << ": " << Brief(previous_value);
784     previous_index = i;
785     previous_value = value;
786   }
787 }
788 
789 }  // namespace
790 
ObjectBoilerplateDescriptionPrint(std::ostream & os)791 void ObjectBoilerplateDescription::ObjectBoilerplateDescriptionPrint(
792     std::ostream& os) {
793   PrintFixedArrayWithHeader(os, *this, "ObjectBoilerplateDescription");
794 }
795 
EmbedderDataArrayPrint(std::ostream & os)796 void EmbedderDataArray::EmbedderDataArrayPrint(std::ostream& os) {
797   Isolate* isolate = GetIsolateForSandbox(*this);
798   PrintHeader(os, "EmbedderDataArray");
799   os << "\n - length: " << length();
800   EmbedderDataSlot start(*this, 0);
801   EmbedderDataSlot end(*this, length());
802   for (EmbedderDataSlot slot = start; slot < end; ++slot) {
803     os << "\n    ";
804     PrintEmbedderData(isolate, os, slot);
805   }
806   os << "\n";
807 }
808 
FixedArrayPrint(std::ostream & os)809 void FixedArray::FixedArrayPrint(std::ostream& os) {
810   PrintFixedArrayWithHeader(os, *this, "FixedArray");
811 }
812 
813 namespace {
SideEffectType2String(SideEffectType type)814 const char* SideEffectType2String(SideEffectType type) {
815   switch (type) {
816     case SideEffectType::kHasSideEffect:
817       return "kHasSideEffect";
818     case SideEffectType::kHasNoSideEffect:
819       return "kHasNoSideEffect";
820     case SideEffectType::kHasSideEffectToReceiver:
821       return "kHasSideEffectToReceiver";
822   }
823 }
824 }  // namespace
825 
AccessorInfoPrint(std::ostream & os)826 void AccessorInfo::AccessorInfoPrint(std::ostream& os) {
827   TorqueGeneratedAccessorInfo<AccessorInfo, Struct>::AccessorInfoPrint(os);
828   os << " - all_can_read: " << all_can_read();
829   os << "\n - all_can_write: " << all_can_write();
830   os << "\n - is_special_data_property: " << is_special_data_property();
831   os << "\n - is_sloppy: " << is_sloppy();
832   os << "\n - replace_on_access: " << replace_on_access();
833   os << "\n - getter_side_effect_type: "
834      << SideEffectType2String(getter_side_effect_type());
835   os << "\n - setter_side_effect_type: "
836      << SideEffectType2String(setter_side_effect_type());
837   os << "\n - initial_attributes: " << initial_property_attributes();
838   os << '\n';
839 }
840 
841 namespace {
PrintContextWithHeader(std::ostream & os,Context context,const char * type)842 void PrintContextWithHeader(std::ostream& os, Context context,
843                             const char* type) {
844   context.PrintHeader(os, type);
845   os << "\n - type: " << context.map().instance_type();
846   os << "\n - scope_info: " << Brief(context.scope_info());
847   os << "\n - previous: " << Brief(context.unchecked_previous());
848   os << "\n - native_context: " << Brief(context.native_context());
849   if (context.scope_info().HasContextExtensionSlot()) {
850     os << "\n - extension: " << context.extension();
851   }
852   os << "\n - length: " << context.length();
853   os << "\n - elements:";
854   PrintFixedArrayElements(os, context);
855   os << "\n";
856 }
857 }  // namespace
858 
ContextPrint(std::ostream & os)859 void Context::ContextPrint(std::ostream& os) {
860   PrintContextWithHeader(os, *this, "Context");
861 }
862 
NativeContextPrint(std::ostream & os)863 void NativeContext::NativeContextPrint(std::ostream& os) {
864   PrintContextWithHeader(os, *this, "NativeContext");
865   os << " - microtask_queue: " << microtask_queue() << "\n";
866 }
867 
868 namespace {
869 using DataPrinter = std::function<void(InternalIndex)>;
870 
871 // Prints the data associated with each key (but no headers or other meta
872 // data) in a hash table. Works on different hash table types, like the
873 // subtypes of HashTable and OrderedHashTable. |print_data_at| is given an
874 // index into the table (where a valid key resides) and prints the data at
875 // that index, like just the value (in case of a hash map), or value and
876 // property details (in case of a property dictionary). No leading space
877 // required or trailing newline required. It can be null/non-callable
878 // std::function to indicate that there is no associcated data to be printed
879 // (for example in case of a hash set).
880 template <typename T>
PrintTableContentsGeneric(std::ostream & os,T dict,DataPrinter print_data_at)881 void PrintTableContentsGeneric(std::ostream& os, T dict,
882                                DataPrinter print_data_at) {
883   DisallowGarbageCollection no_gc;
884   ReadOnlyRoots roots = dict.GetReadOnlyRoots();
885 
886   for (InternalIndex i : dict.IterateEntries()) {
887     Object k;
888     if (!dict.ToKey(roots, i, &k)) continue;
889     os << "\n   " << std::setw(12) << i.as_int() << ": ";
890     if (k.IsString()) {
891       String::cast(k).PrintUC16(os);
892     } else {
893       os << Brief(k);
894     }
895     if (print_data_at) {
896       os << " -> ";
897       print_data_at(i);
898     }
899   }
900 }
901 
902 // Used for ordered and unordered dictionaries.
903 template <typename T>
PrintDictionaryContentsFull(std::ostream & os,T dict)904 void PrintDictionaryContentsFull(std::ostream& os, T dict) {
905   os << "\n - elements: {";
906   auto print_value_and_property_details = [&](InternalIndex i) {
907     os << Brief(dict.ValueAt(i)) << " ";
908     dict.DetailsAt(i).PrintAsSlowTo(os, !T::kIsOrderedDictionaryType);
909   };
910   PrintTableContentsGeneric(os, dict, print_value_and_property_details);
911   os << "\n }\n";
912 }
913 
914 // Used for ordered and unordered hash maps.
915 template <typename T>
PrintHashMapContentsFull(std::ostream & os,T dict)916 void PrintHashMapContentsFull(std::ostream& os, T dict) {
917   os << "\n - elements: {";
918   auto print_value = [&](InternalIndex i) { os << Brief(dict.ValueAt(i)); };
919   PrintTableContentsGeneric(os, dict, print_value);
920   os << "\n }\n";
921 }
922 
923 // Used for ordered and unordered hash sets.
924 template <typename T>
PrintHashSetContentsFull(std::ostream & os,T dict)925 void PrintHashSetContentsFull(std::ostream& os, T dict) {
926   os << "\n - elements: {";
927   // Passing non-callable std::function as there are no values to print.
928   PrintTableContentsGeneric(os, dict, nullptr);
929   os << "\n }\n";
930 }
931 
932 // Used for subtypes of OrderedHashTable.
933 template <typename T>
PrintOrderedHashTableHeaderAndBuckets(std::ostream & os,T table,const char * type)934 void PrintOrderedHashTableHeaderAndBuckets(std::ostream& os, T table,
935                                            const char* type) {
936   DisallowGarbageCollection no_gc;
937 
938   PrintHeapObjectHeaderWithoutMap(table, os, type);
939   os << "\n - FixedArray length: " << table.length();
940   os << "\n - elements: " << table.NumberOfElements();
941   os << "\n - deleted: " << table.NumberOfDeletedElements();
942   os << "\n - buckets: " << table.NumberOfBuckets();
943   os << "\n - capacity: " << table.Capacity();
944 
945   os << "\n - buckets: {";
946   for (int bucket = 0; bucket < table.NumberOfBuckets(); bucket++) {
947     Object entry = table.get(T::HashTableStartIndex() + bucket);
948     DCHECK(entry.IsSmi());
949     os << "\n   " << std::setw(12) << bucket << ": " << Brief(entry);
950   }
951   os << "\n }";
952 }
953 
954 // Used for subtypes of HashTable.
955 template <typename T>
PrintHashTableHeader(std::ostream & os,T table,const char * type)956 void PrintHashTableHeader(std::ostream& os, T table, const char* type) {
957   PrintHeapObjectHeaderWithoutMap(table, os, type);
958   os << "\n - FixedArray length: " << table.length();
959   os << "\n - elements: " << table.NumberOfElements();
960   os << "\n - deleted: " << table.NumberOfDeletedElements();
961   os << "\n - capacity: " << table.Capacity();
962 }
963 }  // namespace
964 
ObjectHashTablePrint(std::ostream & os)965 void ObjectHashTable::ObjectHashTablePrint(std::ostream& os) {
966   PrintHashTableHeader(os, *this, "ObjectHashTable");
967   PrintHashMapContentsFull(os, *this);
968 }
969 
NameToIndexHashTablePrint(std::ostream & os)970 void NameToIndexHashTable::NameToIndexHashTablePrint(std::ostream& os) {
971   PrintHashTableHeader(os, *this, "NameToIndexHashTable");
972   PrintHashMapContentsFull(os, *this);
973 }
974 
RegisteredSymbolTablePrint(std::ostream & os)975 void RegisteredSymbolTable::RegisteredSymbolTablePrint(std::ostream& os) {
976   PrintHashTableHeader(os, *this, "RegisteredSymbolTable");
977   PrintHashMapContentsFull(os, *this);
978 }
979 
NumberDictionaryPrint(std::ostream & os)980 void NumberDictionary::NumberDictionaryPrint(std::ostream& os) {
981   PrintHashTableHeader(os, *this, "NumberDictionary");
982   PrintDictionaryContentsFull(os, *this);
983 }
984 
EphemeronHashTablePrint(std::ostream & os)985 void EphemeronHashTable::EphemeronHashTablePrint(std::ostream& os) {
986   PrintHashTableHeader(os, *this, "EphemeronHashTable");
987   PrintHashMapContentsFull(os, *this);
988 }
989 
NameDictionaryPrint(std::ostream & os)990 void NameDictionary::NameDictionaryPrint(std::ostream& os) {
991   PrintHashTableHeader(os, *this, "NameDictionary");
992   PrintDictionaryContentsFull(os, *this);
993 }
994 
GlobalDictionaryPrint(std::ostream & os)995 void GlobalDictionary::GlobalDictionaryPrint(std::ostream& os) {
996   PrintHashTableHeader(os, *this, "GlobalDictionary");
997   PrintDictionaryContentsFull(os, *this);
998 }
999 
SmallOrderedHashSetPrint(std::ostream & os)1000 void SmallOrderedHashSet::SmallOrderedHashSetPrint(std::ostream& os) {
1001   PrintHeader(os, "SmallOrderedHashSet");
1002   // TODO(turbofan): Print all fields.
1003 }
1004 
SmallOrderedHashMapPrint(std::ostream & os)1005 void SmallOrderedHashMap::SmallOrderedHashMapPrint(std::ostream& os) {
1006   PrintHeader(os, "SmallOrderedHashMap");
1007   // TODO(turbofan): Print all fields.
1008 }
1009 
SmallOrderedNameDictionaryPrint(std::ostream & os)1010 void SmallOrderedNameDictionary::SmallOrderedNameDictionaryPrint(
1011     std::ostream& os) {
1012   PrintHeader(os, "SmallOrderedNameDictionary");
1013   // TODO(turbofan): Print all fields.
1014 }
1015 
OrderedHashSetPrint(std::ostream & os)1016 void OrderedHashSet::OrderedHashSetPrint(std::ostream& os) {
1017   PrintOrderedHashTableHeaderAndBuckets(os, *this, "OrderedHashSet");
1018   PrintHashSetContentsFull(os, *this);
1019 }
1020 
OrderedHashMapPrint(std::ostream & os)1021 void OrderedHashMap::OrderedHashMapPrint(std::ostream& os) {
1022   PrintOrderedHashTableHeaderAndBuckets(os, *this, "OrderedHashMap");
1023   PrintHashMapContentsFull(os, *this);
1024 }
1025 
OrderedNameDictionaryPrint(std::ostream & os)1026 void OrderedNameDictionary::OrderedNameDictionaryPrint(std::ostream& os) {
1027   PrintOrderedHashTableHeaderAndBuckets(os, *this, "OrderedNameDictionary");
1028   PrintDictionaryContentsFull(os, *this);
1029 }
1030 
print_hex_byte(std::ostream & os,int value)1031 void print_hex_byte(std::ostream& os, int value) {
1032   os << "0x" << std::setfill('0') << std::setw(2) << std::right << std::hex
1033      << (value & 0xff) << std::setfill(' ');
1034 }
1035 
SwissNameDictionaryPrint(std::ostream & os)1036 void SwissNameDictionary::SwissNameDictionaryPrint(std::ostream& os) {
1037   this->PrintHeader(os, "SwissNameDictionary");
1038   os << "\n - meta table ByteArray: "
1039      << reinterpret_cast<void*>(this->meta_table().ptr());
1040   os << "\n - capacity: " << this->Capacity();
1041   os << "\n - elements: " << this->NumberOfElements();
1042   os << "\n - deleted: " << this->NumberOfDeletedElements();
1043 
1044   std::ios_base::fmtflags sav_flags = os.flags();
1045   os << "\n - ctrl table (omitting buckets where key is hole value): {";
1046   for (int i = 0; i < this->Capacity() + kGroupWidth; i++) {
1047     ctrl_t ctrl = CtrlTable()[i];
1048 
1049     if (ctrl == Ctrl::kEmpty) continue;
1050 
1051     os << "\n   " << std::setw(12) << std::dec << i << ": ";
1052     switch (ctrl) {
1053       case Ctrl::kEmpty:
1054         UNREACHABLE();
1055       case Ctrl::kDeleted:
1056         print_hex_byte(os, ctrl);
1057         os << " (= kDeleted)";
1058         break;
1059       case Ctrl::kSentinel:
1060         print_hex_byte(os, ctrl);
1061         os << " (= kSentinel)";
1062         break;
1063       default:
1064         print_hex_byte(os, ctrl);
1065         os << " (= H2 of a key)";
1066         break;
1067     }
1068   }
1069   os << "\n }";
1070 
1071   os << "\n - enumeration table: {";
1072   for (int enum_index = 0; enum_index < this->UsedCapacity(); enum_index++) {
1073     int entry = EntryForEnumerationIndex(enum_index);
1074     os << "\n   " << std::setw(12) << std::dec << enum_index << ": " << entry;
1075   }
1076   os << "\n }";
1077 
1078   os << "\n - data table (omitting slots where key is the hole): {";
1079   for (int bucket = 0; bucket < this->Capacity(); ++bucket) {
1080     Object k;
1081     if (!this->ToKey(this->GetReadOnlyRoots(), bucket, &k)) continue;
1082 
1083     Object value = this->ValueAtRaw(bucket);
1084     PropertyDetails details = this->DetailsAt(bucket);
1085     os << "\n   " << std::setw(12) << std::dec << bucket << ": ";
1086     if (k.IsString()) {
1087       String::cast(k).PrintUC16(os);
1088     } else {
1089       os << Brief(k);
1090     }
1091     os << " -> " << Brief(value);
1092     details.PrintAsSlowTo(os, false);
1093   }
1094   os << "\n }\n";
1095   os.flags(sav_flags);
1096 }
1097 
PropertyArrayPrint(std::ostream & os)1098 void PropertyArray::PropertyArrayPrint(std::ostream& os) {
1099   PrintHeader(os, "PropertyArray");
1100   os << "\n - length: " << length();
1101   os << "\n - hash: " << Hash();
1102   PrintFixedArrayElements(os, *this);
1103   os << "\n";
1104 }
1105 
FixedDoubleArrayPrint(std::ostream & os)1106 void FixedDoubleArray::FixedDoubleArrayPrint(std::ostream& os) {
1107   PrintHeader(os, "FixedDoubleArray");
1108   os << "\n - length: " << length();
1109   DoPrintElements<FixedDoubleArray>(os, *this, length());
1110   os << "\n";
1111 }
1112 
WeakFixedArrayPrint(std::ostream & os)1113 void WeakFixedArray::WeakFixedArrayPrint(std::ostream& os) {
1114   PrintHeader(os, "WeakFixedArray");
1115   os << "\n - length: " << length() << "\n";
1116   PrintWeakArrayElements(os, this);
1117   os << "\n";
1118 }
1119 
WeakArrayListPrint(std::ostream & os)1120 void WeakArrayList::WeakArrayListPrint(std::ostream& os) {
1121   PrintHeader(os, "WeakArrayList");
1122   os << "\n - capacity: " << capacity();
1123   os << "\n - length: " << length() << "\n";
1124   PrintWeakArrayElements(os, this);
1125   os << "\n";
1126 }
1127 
TransitionArrayPrint(std::ostream & os)1128 void TransitionArray::TransitionArrayPrint(std::ostream& os) {
1129   PrintHeader(os, "TransitionArray");
1130   PrintInternal(os);
1131 }
1132 
FeedbackCellPrint(std::ostream & os)1133 void FeedbackCell::FeedbackCellPrint(std::ostream& os) {
1134   PrintHeader(os, "FeedbackCell");
1135   ReadOnlyRoots roots = GetReadOnlyRoots();
1136   if (map() == roots.no_closures_cell_map()) {
1137     os << "\n - no closures";
1138   } else if (map() == roots.one_closure_cell_map()) {
1139     os << "\n - one closure";
1140   } else if (map() == roots.many_closures_cell_map()) {
1141     os << "\n - many closures";
1142   } else {
1143     os << "\n - Invalid FeedbackCell map";
1144   }
1145   os << "\n - value: " << Brief(value());
1146   os << "\n - interrupt_budget: " << interrupt_budget();
1147   os << "\n";
1148 }
1149 
Print()1150 void FeedbackVectorSpec::Print() {
1151   StdoutStream os;
1152 
1153   FeedbackVectorSpecPrint(os);
1154 
1155   os << std::flush;
1156 }
1157 
FeedbackVectorSpecPrint(std::ostream & os)1158 void FeedbackVectorSpec::FeedbackVectorSpecPrint(std::ostream& os) {
1159   os << " - slot_count: " << slot_count();
1160   if (slot_count() == 0) {
1161     os << " (empty)\n";
1162     return;
1163   }
1164 
1165   for (int slot = 0; slot < slot_count();) {
1166     FeedbackSlotKind kind = GetKind(FeedbackSlot(slot));
1167     int entry_size = FeedbackMetadata::GetSlotSize(kind);
1168     DCHECK_LT(0, entry_size);
1169     os << "\n Slot #" << slot << " " << kind;
1170     slot += entry_size;
1171   }
1172   os << "\n";
1173 }
1174 
FeedbackMetadataPrint(std::ostream & os)1175 void FeedbackMetadata::FeedbackMetadataPrint(std::ostream& os) {
1176   PrintHeader(os, "FeedbackMetadata");
1177   os << "\n - slot_count: " << slot_count();
1178   os << "\n - create_closure_slot_count: " << create_closure_slot_count();
1179 
1180   FeedbackMetadataIterator iter(*this);
1181   while (iter.HasNext()) {
1182     FeedbackSlot slot = iter.Next();
1183     FeedbackSlotKind kind = iter.kind();
1184     os << "\n Slot " << slot << " " << kind;
1185   }
1186   os << "\n";
1187 }
1188 
ClosureFeedbackCellArrayPrint(std::ostream & os)1189 void ClosureFeedbackCellArray::ClosureFeedbackCellArrayPrint(std::ostream& os) {
1190   PrintFixedArrayWithHeader(os, *this, "ClosureFeedbackCellArray");
1191 }
1192 
FeedbackVectorPrint(std::ostream & os)1193 void FeedbackVector::FeedbackVectorPrint(std::ostream& os) {
1194   PrintHeader(os, "FeedbackVector");
1195   os << "\n - length: " << length();
1196   if (length() == 0) {
1197     os << " (empty)\n";
1198     return;
1199   }
1200 
1201   os << "\n - shared function info: " << Brief(shared_function_info());
1202   if (has_optimized_code()) {
1203     os << "\n - optimized code: " << Brief(optimized_code());
1204   } else {
1205     os << "\n - no optimized code";
1206   }
1207   os << "\n - tiering state: " << tiering_state();
1208   os << "\n - maybe has optimized code: " << maybe_has_optimized_code();
1209   os << "\n - invocation count: " << invocation_count();
1210   os << "\n - profiler ticks: " << profiler_ticks();
1211   os << "\n - closure feedback cell array: ";
1212   closure_feedback_cell_array().ClosureFeedbackCellArrayPrint(os);
1213 
1214   FeedbackMetadataIterator iter(metadata());
1215   while (iter.HasNext()) {
1216     FeedbackSlot slot = iter.Next();
1217     FeedbackSlotKind kind = iter.kind();
1218 
1219     os << "\n - slot " << slot << " " << kind << " ";
1220     FeedbackSlotPrint(os, slot);
1221 
1222     int entry_size = iter.entry_size();
1223     if (entry_size > 0) os << " {";
1224     for (int i = 0; i < entry_size; i++) {
1225       FeedbackSlot slot_with_offset = slot.WithOffset(i);
1226       os << "\n     [" << slot_with_offset.ToInt()
1227          << "]: " << Brief(Get(slot_with_offset));
1228     }
1229     if (entry_size > 0) os << "\n  }";
1230   }
1231   os << "\n";
1232 }
1233 
FeedbackSlotPrint(std::ostream & os,FeedbackSlot slot)1234 void FeedbackVector::FeedbackSlotPrint(std::ostream& os, FeedbackSlot slot) {
1235   FeedbackNexus nexus(*this, slot);
1236   nexus.Print(os);
1237 }
1238 
Print(std::ostream & os)1239 void FeedbackNexus::Print(std::ostream& os) {
1240   switch (kind()) {
1241     case FeedbackSlotKind::kCall:
1242     case FeedbackSlotKind::kCloneObject:
1243     case FeedbackSlotKind::kDefineKeyedOwn:
1244     case FeedbackSlotKind::kHasKeyed:
1245     case FeedbackSlotKind::kInstanceOf:
1246     case FeedbackSlotKind::kLoadGlobalInsideTypeof:
1247     case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
1248     case FeedbackSlotKind::kLoadKeyed:
1249     case FeedbackSlotKind::kLoadProperty:
1250     case FeedbackSlotKind::kDefineKeyedOwnPropertyInLiteral:
1251     case FeedbackSlotKind::kStoreGlobalSloppy:
1252     case FeedbackSlotKind::kStoreGlobalStrict:
1253     case FeedbackSlotKind::kStoreInArrayLiteral:
1254     case FeedbackSlotKind::kSetKeyedSloppy:
1255     case FeedbackSlotKind::kSetKeyedStrict:
1256     case FeedbackSlotKind::kSetNamedSloppy:
1257     case FeedbackSlotKind::kSetNamedStrict:
1258     case FeedbackSlotKind::kDefineNamedOwn: {
1259       os << InlineCacheState2String(ic_state());
1260       break;
1261     }
1262     case FeedbackSlotKind::kBinaryOp: {
1263       os << "BinaryOp:" << GetBinaryOperationFeedback();
1264       break;
1265     }
1266     case FeedbackSlotKind::kCompareOp: {
1267       os << "CompareOp:" << GetCompareOperationFeedback();
1268       break;
1269     }
1270     case FeedbackSlotKind::kForIn: {
1271       os << "ForIn:" << GetForInFeedback();
1272       break;
1273     }
1274     case FeedbackSlotKind::kLiteral:
1275     case FeedbackSlotKind::kTypeProfile:
1276       break;
1277     case FeedbackSlotKind::kInvalid:
1278     case FeedbackSlotKind::kKindsNumber:
1279       UNREACHABLE();
1280   }
1281 }
1282 
OddballPrint(std::ostream & os)1283 void Oddball::OddballPrint(std::ostream& os) {
1284   PrintHeapObjectHeaderWithoutMap(*this, os, "Oddball");
1285   os << ": ";
1286   String s = to_string();
1287   os << s.PrefixForDebugPrint();
1288   s.PrintUC16(os);
1289   os << s.SuffixForDebugPrint();
1290   os << std::endl;
1291 }
1292 
JSAsyncFunctionObjectPrint(std::ostream & os)1293 void JSAsyncFunctionObject::JSAsyncFunctionObjectPrint(std::ostream& os) {
1294   JSGeneratorObjectPrint(os);
1295 }
1296 
JSAsyncGeneratorObjectPrint(std::ostream & os)1297 void JSAsyncGeneratorObject::JSAsyncGeneratorObjectPrint(std::ostream& os) {
1298   JSGeneratorObjectPrint(os);
1299 }
1300 
JSArgumentsObjectPrint(std::ostream & os)1301 void JSArgumentsObject::JSArgumentsObjectPrint(std::ostream& os) {
1302   JSObjectPrint(os);
1303 }
1304 
JSStringIteratorPrint(std::ostream & os)1305 void JSStringIterator::JSStringIteratorPrint(std::ostream& os) {
1306   JSObjectPrintHeader(os, *this, "JSStringIterator");
1307   os << "\n - string: " << Brief(string());
1308   os << "\n - index: " << index();
1309   JSObjectPrintBody(os, *this);
1310 }
1311 
JSAsyncFromSyncIteratorPrint(std::ostream & os)1312 void JSAsyncFromSyncIterator::JSAsyncFromSyncIteratorPrint(std::ostream& os) {
1313   JSObjectPrintHeader(os, *this, "JSAsyncFromSyncIterator");
1314   os << "\n - sync_iterator: " << Brief(sync_iterator());
1315   os << "\n - next: " << Brief(next());
1316   JSObjectPrintBody(os, *this);
1317 }
1318 
JSPrimitiveWrapperPrint(std::ostream & os)1319 void JSPrimitiveWrapper::JSPrimitiveWrapperPrint(std::ostream& os) {
1320   JSObjectPrintHeader(os, *this, "JSPrimitiveWrapper");
1321   os << "\n - value: " << Brief(value());
1322   JSObjectPrintBody(os, *this);
1323 }
1324 
JSMessageObjectPrint(std::ostream & os)1325 void JSMessageObject::JSMessageObjectPrint(std::ostream& os) {
1326   JSObjectPrintHeader(os, *this, "JSMessageObject");
1327   os << "\n - type: " << static_cast<int>(type());
1328   os << "\n - arguments: " << Brief(argument());
1329   os << "\n - start_position: " << start_position();
1330   os << "\n - end_position: " << end_position();
1331   os << "\n - script: " << Brief(script());
1332   os << "\n - stack_frames: " << Brief(stack_frames());
1333   JSObjectPrintBody(os, *this);
1334 }
1335 
StringPrint(std::ostream & os)1336 void String::StringPrint(std::ostream& os) {
1337   PrintHeapObjectHeaderWithoutMap(*this, os, "String");
1338   os << ": ";
1339   os << PrefixForDebugPrint();
1340   PrintUC16(os, 0, length());
1341   os << SuffixForDebugPrint();
1342 }
1343 
NamePrint(std::ostream & os)1344 void Name::NamePrint(std::ostream& os) {
1345   if (IsString()) {
1346     String::cast(*this).StringPrint(os);
1347   } else {
1348     os << Brief(*this);
1349   }
1350 }
1351 
1352 static const char* const weekdays[] = {"???", "Sun", "Mon", "Tue",
1353                                        "Wed", "Thu", "Fri", "Sat"};
1354 
JSDatePrint(std::ostream & os)1355 void JSDate::JSDatePrint(std::ostream& os) {
1356   JSObjectPrintHeader(os, *this, "JSDate");
1357   os << "\n - value: " << Brief(value());
1358   if (!year().IsSmi()) {
1359     os << "\n - time = NaN\n";
1360   } else {
1361     // TODO(svenpanne) Add some basic formatting to our streams.
1362     base::ScopedVector<char> buf(100);
1363     SNPrintF(buf, "\n - time = %s %04d/%02d/%02d %02d:%02d:%02d\n",
1364              weekdays[weekday().IsSmi() ? Smi::ToInt(weekday()) + 1 : 0],
1365              year().IsSmi() ? Smi::ToInt(year()) : -1,
1366              month().IsSmi() ? Smi::ToInt(month()) : -1,
1367              day().IsSmi() ? Smi::ToInt(day()) : -1,
1368              hour().IsSmi() ? Smi::ToInt(hour()) : -1,
1369              min().IsSmi() ? Smi::ToInt(min()) : -1,
1370              sec().IsSmi() ? Smi::ToInt(sec()) : -1);
1371     os << buf.begin();
1372   }
1373   JSObjectPrintBody(os, *this);
1374 }
1375 
JSSetPrint(std::ostream & os)1376 void JSSet::JSSetPrint(std::ostream& os) {
1377   JSObjectPrintHeader(os, *this, "JSSet");
1378   os << "\n - table: " << Brief(table());
1379   JSObjectPrintBody(os, *this);
1380 }
1381 
JSMapPrint(std::ostream & os)1382 void JSMap::JSMapPrint(std::ostream& os) {
1383   JSObjectPrintHeader(os, *this, "JSMap");
1384   os << "\n - table: " << Brief(table());
1385   JSObjectPrintBody(os, *this);
1386 }
1387 
JSCollectionIteratorPrint(std::ostream & os,const char * name)1388 void JSCollectionIterator::JSCollectionIteratorPrint(std::ostream& os,
1389                                                      const char* name) {
1390   JSObjectPrintHeader(os, *this, name);
1391   os << "\n - table: " << Brief(table());
1392   os << "\n - index: " << Brief(index());
1393   JSObjectPrintBody(os, *this);
1394 }
1395 
JSSetIteratorPrint(std::ostream & os)1396 void JSSetIterator::JSSetIteratorPrint(std::ostream& os) {
1397   JSCollectionIteratorPrint(os, "JSSetIterator");
1398 }
1399 
JSMapIteratorPrint(std::ostream & os)1400 void JSMapIterator::JSMapIteratorPrint(std::ostream& os) {
1401   JSCollectionIteratorPrint(os, "JSMapIterator");
1402 }
1403 
JSWeakRefPrint(std::ostream & os)1404 void JSWeakRef::JSWeakRefPrint(std::ostream& os) {
1405   JSObjectPrintHeader(os, *this, "JSWeakRef");
1406   os << "\n - target: " << Brief(target());
1407   JSObjectPrintBody(os, *this);
1408 }
1409 
JSShadowRealmPrint(std::ostream & os)1410 void JSShadowRealm::JSShadowRealmPrint(std::ostream& os) {
1411   JSObjectPrintHeader(os, *this, "JSShadowRealm");
1412   os << "\n - native_context: " << Brief(native_context());
1413   JSObjectPrintBody(os, *this);
1414 }
1415 
JSWrappedFunctionPrint(std::ostream & os)1416 void JSWrappedFunction::JSWrappedFunctionPrint(std::ostream& os) {
1417   JSObjectPrintHeader(os, *this, "JSWrappedFunction");
1418   os << "\n - wrapped_target_function: " << Brief(wrapped_target_function());
1419   JSObjectPrintBody(os, *this);
1420 }
1421 
JSFinalizationRegistryPrint(std::ostream & os)1422 void JSFinalizationRegistry::JSFinalizationRegistryPrint(std::ostream& os) {
1423   JSObjectPrintHeader(os, *this, "JSFinalizationRegistry");
1424   os << "\n - native_context: " << Brief(native_context());
1425   os << "\n - cleanup: " << Brief(cleanup());
1426   os << "\n - active_cells: " << Brief(active_cells());
1427   Object active_cell = active_cells();
1428   while (active_cell.IsWeakCell()) {
1429     os << "\n   - " << Brief(active_cell);
1430     active_cell = WeakCell::cast(active_cell).next();
1431   }
1432   os << "\n - cleared_cells: " << Brief(cleared_cells());
1433   Object cleared_cell = cleared_cells();
1434   while (cleared_cell.IsWeakCell()) {
1435     os << "\n   - " << Brief(cleared_cell);
1436     cleared_cell = WeakCell::cast(cleared_cell).next();
1437   }
1438   os << "\n - key_map: " << Brief(key_map());
1439   JSObjectPrintBody(os, *this);
1440 }
1441 
JSSharedStructPrint(std::ostream & os)1442 void JSSharedStruct::JSSharedStructPrint(std::ostream& os) {
1443   JSObjectPrintHeader(os, *this, "JSSharedStruct");
1444   Isolate* isolate = GetIsolateFromWritableObject(*this);
1445   os << "\n - isolate: " << isolate;
1446   if (isolate->is_shared()) os << " (shared)";
1447   JSObjectPrintBody(os, *this);
1448 }
1449 
JSWeakMapPrint(std::ostream & os)1450 void JSWeakMap::JSWeakMapPrint(std::ostream& os) {
1451   JSObjectPrintHeader(os, *this, "JSWeakMap");
1452   os << "\n - table: " << Brief(table());
1453   JSObjectPrintBody(os, *this);
1454 }
1455 
JSWeakSetPrint(std::ostream & os)1456 void JSWeakSet::JSWeakSetPrint(std::ostream& os) {
1457   JSObjectPrintHeader(os, *this, "JSWeakSet");
1458   os << "\n - table: " << Brief(table());
1459   JSObjectPrintBody(os, *this);
1460 }
1461 
JSArrayBufferPrint(std::ostream & os)1462 void JSArrayBuffer::JSArrayBufferPrint(std::ostream& os) {
1463   JSObjectPrintHeader(os, *this, "JSArrayBuffer");
1464   os << "\n - backing_store: " << backing_store();
1465   os << "\n - byte_length: " << byte_length();
1466   os << "\n - max_byte_length: " << max_byte_length();
1467   if (is_external()) os << "\n - external";
1468   if (is_detachable()) os << "\n - detachable";
1469   if (was_detached()) os << "\n - detached";
1470   if (is_shared()) os << "\n - shared";
1471   if (is_resizable()) os << "\n - resizable";
1472   JSObjectPrintBody(os, *this, !was_detached());
1473 }
1474 
JSTypedArrayPrint(std::ostream & os)1475 void JSTypedArray::JSTypedArrayPrint(std::ostream& os) {
1476   JSObjectPrintHeader(os, *this, "JSTypedArray");
1477   os << "\n - buffer: " << Brief(buffer());
1478   os << "\n - byte_offset: " << byte_offset();
1479   os << "\n - byte_length: " << byte_length();
1480   os << "\n - length: " << GetLength();
1481   os << "\n - data_ptr: " << DataPtr();
1482   Tagged_t base_ptr = static_cast<Tagged_t>(base_pointer().ptr());
1483   os << "\n   - base_pointer: "
1484      << reinterpret_cast<void*>(static_cast<Address>(base_ptr));
1485   os << "\n   - external_pointer: "
1486      << reinterpret_cast<void*>(external_pointer());
1487   if (!buffer().IsJSArrayBuffer()) {
1488     os << "\n <invalid buffer>\n";
1489     return;
1490   }
1491   if (WasDetached()) os << "\n - detached";
1492   if (is_length_tracking()) os << "\n - length-tracking";
1493   if (is_backed_by_rab()) os << "\n - backed-by-rab";
1494   JSObjectPrintBody(os, *this, !WasDetached());
1495 }
1496 
JSArrayIteratorPrint(std::ostream & os)1497 void JSArrayIterator::JSArrayIteratorPrint(std::ostream& os) {  // NOLING
1498   JSObjectPrintHeader(os, *this, "JSArrayIterator");
1499   os << "\n - iterated_object: " << Brief(iterated_object());
1500   os << "\n - next_index: " << Brief(next_index());
1501   os << "\n - kind: " << kind();
1502   JSObjectPrintBody(os, *this);
1503 }
1504 
JSDataViewPrint(std::ostream & os)1505 void JSDataView::JSDataViewPrint(std::ostream& os) {
1506   JSObjectPrintHeader(os, *this, "JSDataView");
1507   os << "\n - buffer =" << Brief(buffer());
1508   os << "\n - byte_offset: " << byte_offset();
1509   os << "\n - byte_length: " << byte_length();
1510   if (!buffer().IsJSArrayBuffer()) {
1511     os << "\n <invalid buffer>";
1512     return;
1513   }
1514   if (WasDetached()) os << "\n - detached";
1515   JSObjectPrintBody(os, *this, !WasDetached());
1516 }
1517 
JSBoundFunctionPrint(std::ostream & os)1518 void JSBoundFunction::JSBoundFunctionPrint(std::ostream& os) {
1519   JSObjectPrintHeader(os, *this, "JSBoundFunction");
1520   os << "\n - bound_target_function: " << Brief(bound_target_function());
1521   os << "\n - bound_this: " << Brief(bound_this());
1522   os << "\n - bound_arguments: " << Brief(bound_arguments());
1523   JSObjectPrintBody(os, *this);
1524 }
1525 
JSFunctionPrint(std::ostream & os)1526 void JSFunction::JSFunctionPrint(std::ostream& os) {
1527   Isolate* isolate = GetIsolate();
1528   JSObjectPrintHeader(os, *this, "Function");
1529   os << "\n - function prototype: ";
1530   if (has_prototype_slot()) {
1531     if (has_prototype()) {
1532       os << Brief(prototype());
1533       if (map().has_non_instance_prototype()) {
1534         os << " (non-instance prototype)";
1535       }
1536     }
1537     os << "\n - initial_map: ";
1538     if (has_initial_map()) os << Brief(initial_map());
1539   } else {
1540     os << "<no-prototype-slot>";
1541   }
1542   os << "\n - shared_info: " << Brief(shared());
1543   os << "\n - name: " << Brief(shared().Name());
1544 
1545   // Print Builtin name for builtin functions
1546   Builtin builtin = code().builtin_id();
1547   if (Builtins::IsBuiltinId(builtin)) {
1548     os << "\n - builtin: " << isolate->builtins()->name(builtin);
1549   }
1550 
1551   os << "\n - formal_parameter_count: "
1552      << shared().internal_formal_parameter_count_without_receiver();
1553   os << "\n - kind: " << shared().kind();
1554   os << "\n - context: " << Brief(context());
1555   os << "\n - code: " << Brief(code());
1556   if (code().kind() == CodeKind::FOR_TESTING) {
1557     os << "\n - FOR_TESTING";
1558   } else if (ActiveTierIsIgnition()) {
1559     os << "\n - interpreted";
1560     if (shared().HasBytecodeArray()) {
1561       os << "\n - bytecode: " << shared().GetBytecodeArray(isolate);
1562     }
1563   }
1564 #if V8_ENABLE_WEBASSEMBLY
1565   if (WasmExportedFunction::IsWasmExportedFunction(*this)) {
1566     WasmExportedFunction function = WasmExportedFunction::cast(*this);
1567     os << "\n - Wasm instance: " << Brief(function.instance());
1568     os << "\n - Wasm function index: " << function.function_index();
1569   }
1570   if (WasmJSFunction::IsWasmJSFunction(*this)) {
1571     WasmJSFunction function = WasmJSFunction::cast(*this);
1572     os << "\n - Wasm wrapper around: " << Brief(function.GetCallable());
1573   }
1574 #endif  // V8_ENABLE_WEBASSEMBLY
1575   shared().PrintSourceCode(os);
1576   JSObjectPrintBody(os, *this);
1577   os << " - feedback vector: ";
1578   if (!shared().HasFeedbackMetadata()) {
1579     os << "feedback metadata is not available in SFI\n";
1580   } else if (has_feedback_vector()) {
1581     feedback_vector().FeedbackVectorPrint(os);
1582   } else if (has_closure_feedback_cell_array()) {
1583     os << "No feedback vector, but we have a closure feedback cell array\n";
1584     closure_feedback_cell_array().ClosureFeedbackCellArrayPrint(os);
1585   } else {
1586     os << "not available\n";
1587   }
1588 }
1589 
PrintSourceCode(std::ostream & os)1590 void SharedFunctionInfo::PrintSourceCode(std::ostream& os) {
1591   if (HasSourceCode()) {
1592     os << "\n - source code: ";
1593     String source = String::cast(Script::cast(script()).source());
1594     int start = StartPosition();
1595     int length = EndPosition() - start;
1596     std::unique_ptr<char[]> source_string = source.ToCString(
1597         DISALLOW_NULLS, FAST_STRING_TRAVERSAL, start, length, nullptr);
1598     os << source_string.get();
1599   }
1600 }
1601 
SharedFunctionInfoPrint(std::ostream & os)1602 void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) {
1603   PrintHeader(os, "SharedFunctionInfo");
1604   os << "\n - name: ";
1605   if (HasSharedName()) {
1606     os << Brief(Name());
1607   } else {
1608     os << "<no-shared-name>";
1609   }
1610   if (HasInferredName()) {
1611     os << "\n - inferred name: " << Brief(inferred_name());
1612   }
1613   if (class_scope_has_private_brand()) {
1614     os << "\n - class_scope_has_private_brand";
1615   }
1616   if (has_static_private_methods_or_accessors()) {
1617     os << "\n - has_static_private_methods_or_accessors";
1618   }
1619   if (private_name_lookup_skips_outer_class()) {
1620     os << "\n - private_name_lookup_skips_outer_class";
1621   }
1622   os << "\n - kind: " << kind();
1623   os << "\n - syntax kind: " << syntax_kind();
1624   os << "\n - function_map_index: " << function_map_index();
1625   os << "\n - formal_parameter_count: "
1626      << internal_formal_parameter_count_without_receiver();
1627   os << "\n - expected_nof_properties: " << expected_nof_properties();
1628   os << "\n - language_mode: " << language_mode();
1629   os << "\n - data: " << Brief(function_data(kAcquireLoad));
1630   os << "\n - code (from data): ";
1631   os << Brief(GetCode());
1632   PrintSourceCode(os);
1633   // Script files are often large, thus only print their {Brief} representation.
1634   os << "\n - script: " << Brief(script());
1635   os << "\n - function token position: " << function_token_position();
1636   os << "\n - start position: " << StartPosition();
1637   os << "\n - end position: " << EndPosition();
1638   if (HasDebugInfo()) {
1639     os << "\n - debug info: " << Brief(GetDebugInfo());
1640   } else {
1641     os << "\n - no debug info";
1642   }
1643   os << "\n - scope info: " << Brief(scope_info());
1644   if (HasOuterScopeInfo()) {
1645     os << "\n - outer scope info: " << Brief(GetOuterScopeInfo());
1646   }
1647   os << "\n - length: " << length();
1648   os << "\n - feedback_metadata: ";
1649   if (HasFeedbackMetadata()) {
1650     feedback_metadata().FeedbackMetadataPrint(os);
1651   } else {
1652     os << "<none>";
1653   }
1654   os << "\n";
1655 }
1656 
JSGlobalProxyPrint(std::ostream & os)1657 void JSGlobalProxy::JSGlobalProxyPrint(std::ostream& os) {
1658   JSObjectPrintHeader(os, *this, "JSGlobalProxy");
1659   if (!GetIsolate()->bootstrapper()->IsActive()) {
1660     os << "\n - native context: " << Brief(native_context());
1661   }
1662   JSObjectPrintBody(os, *this);
1663 }
1664 
JSGlobalObjectPrint(std::ostream & os)1665 void JSGlobalObject::JSGlobalObjectPrint(std::ostream& os) {
1666   JSObjectPrintHeader(os, *this, "JSGlobalObject");
1667   if (!GetIsolate()->bootstrapper()->IsActive()) {
1668     os << "\n - native context: " << Brief(native_context());
1669   }
1670   os << "\n - global proxy: " << Brief(global_proxy());
1671   JSObjectPrintBody(os, *this);
1672 }
1673 
PropertyCellPrint(std::ostream & os)1674 void PropertyCell::PropertyCellPrint(std::ostream& os) {
1675   PrintHeader(os, "PropertyCell");
1676   os << "\n - name: ";
1677   name().NamePrint(os);
1678   os << "\n - value: " << Brief(value(kAcquireLoad));
1679   os << "\n - details: ";
1680   PropertyDetails details = property_details(kAcquireLoad);
1681   details.PrintAsSlowTo(os, true);
1682   os << "\n - cell_type: " << details.cell_type();
1683   os << "\n";
1684 }
1685 
CodePrint(std::ostream & os)1686 void Code::CodePrint(std::ostream& os) {
1687   PrintHeader(os, "Code");
1688   os << "\n - code_data_container: "
1689      << Brief(code_data_container(kAcquireLoad));
1690   if (is_builtin()) {
1691     os << "\n - builtin_id: " << Builtins::name(builtin_id());
1692   }
1693   os << "\n";
1694 #ifdef ENABLE_DISASSEMBLER
1695   Disassemble(nullptr, os, GetIsolate());
1696 #endif
1697 }
1698 
CodeDataContainerPrint(std::ostream & os)1699 void CodeDataContainer::CodeDataContainerPrint(std::ostream& os) {
1700   PrintHeader(os, "CodeDataContainer");
1701   os << "\n - kind_specific_flags: " << kind_specific_flags(kRelaxedLoad);
1702   if (V8_EXTERNAL_CODE_SPACE_BOOL) {
1703     os << "\n - code: " << Brief(code());
1704     os << "\n - code_entry_point: "
1705        << reinterpret_cast<void*>(code_entry_point());
1706   }
1707   os << "\n";
1708 }
1709 
ForeignPrint(std::ostream & os)1710 void Foreign::ForeignPrint(std::ostream& os) {
1711   PrintHeader(os, "Foreign");
1712   os << "\n - foreign address : " << reinterpret_cast<void*>(foreign_address());
1713   os << "\n";
1714 }
1715 
AsyncGeneratorRequestPrint(std::ostream & os)1716 void AsyncGeneratorRequest::AsyncGeneratorRequestPrint(std::ostream& os) {
1717   PrintHeader(os, "AsyncGeneratorRequest");
1718   const char* mode = "Invalid!";
1719   switch (resume_mode()) {
1720     case JSGeneratorObject::kNext:
1721       mode = ".next()";
1722       break;
1723     case JSGeneratorObject::kReturn:
1724       mode = ".return()";
1725       break;
1726     case JSGeneratorObject::kThrow:
1727       mode = ".throw()";
1728       break;
1729   }
1730   os << "\n - resume mode: " << mode;
1731   os << "\n - value: " << Brief(value());
1732   os << "\n - next: " << Brief(next());
1733   os << "\n";
1734 }
1735 
PrintModuleFields(Module module,std::ostream & os)1736 static void PrintModuleFields(Module module, std::ostream& os) {
1737   os << "\n - exports: " << Brief(module.exports());
1738   os << "\n - status: " << module.status();
1739   os << "\n - exception: " << Brief(module.exception());
1740 }
1741 
ModulePrint(std::ostream & os)1742 void Module::ModulePrint(std::ostream& os) {
1743   if (this->IsSourceTextModule()) {
1744     SourceTextModule::cast(*this).SourceTextModulePrint(os);
1745   } else if (this->IsSyntheticModule()) {
1746     SyntheticModule::cast(*this).SyntheticModulePrint(os);
1747   } else {
1748     UNREACHABLE();
1749   }
1750 }
1751 
SourceTextModulePrint(std::ostream & os)1752 void SourceTextModule::SourceTextModulePrint(std::ostream& os) {
1753   PrintHeader(os, "SourceTextModule");
1754   PrintModuleFields(*this, os);
1755   os << "\n - sfi/code/info: " << Brief(code());
1756   Script script = GetScript();
1757   os << "\n - script: " << Brief(script);
1758   os << "\n - origin: " << Brief(script.GetNameOrSourceURL());
1759   os << "\n - requested_modules: " << Brief(requested_modules());
1760   os << "\n - import_meta: " << Brief(import_meta(kAcquireLoad));
1761   os << "\n - cycle_root: " << Brief(cycle_root());
1762   os << "\n - async_evaluating_ordinal: " << async_evaluating_ordinal();
1763   os << "\n";
1764 }
1765 
JSModuleNamespacePrint(std::ostream & os)1766 void JSModuleNamespace::JSModuleNamespacePrint(std::ostream& os) {
1767   JSObjectPrintHeader(os, *this, "JSModuleNamespace");
1768   os << "\n - module: " << Brief(module());
1769   JSObjectPrintBody(os, *this);
1770 }
1771 
PrototypeInfoPrint(std::ostream & os)1772 void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) {
1773   PrintHeader(os, "PrototypeInfo");
1774   os << "\n - module namespace: " << Brief(module_namespace());
1775   os << "\n - prototype users: " << Brief(prototype_users());
1776   os << "\n - registry slot: " << registry_slot();
1777   os << "\n - object create map: " << Brief(object_create_map());
1778   os << "\n - should_be_fast_map: " << should_be_fast_map();
1779   os << "\n";
1780 }
1781 
ArrayBoilerplateDescriptionPrint(std::ostream & os)1782 void ArrayBoilerplateDescription::ArrayBoilerplateDescriptionPrint(
1783     std::ostream& os) {
1784   PrintHeader(os, "ArrayBoilerplateDescription");
1785   os << "\n - elements kind: " << ElementsKindToString(elements_kind());
1786   os << "\n - constant elements: " << Brief(constant_elements());
1787   os << "\n";
1788 }
1789 
1790 #if V8_ENABLE_WEBASSEMBLY
AsmWasmDataPrint(std::ostream & os)1791 void AsmWasmData::AsmWasmDataPrint(std::ostream& os) {
1792   PrintHeader(os, "AsmWasmData");
1793   os << "\n - native module: " << Brief(managed_native_module());
1794   os << "\n - export_wrappers: " << Brief(export_wrappers());
1795   os << "\n - uses bitset: " << uses_bitset().value();
1796   os << "\n";
1797 }
1798 
WasmTypeInfoPrint(std::ostream & os)1799 void WasmTypeInfo::WasmTypeInfoPrint(std::ostream& os) {
1800   PrintHeader(os, "WasmTypeInfo");
1801   os << "\n - type address: " << reinterpret_cast<void*>(foreign_address());
1802   os << "\n - supertypes: " << Brief(supertypes());
1803   os << "\n - subtypes: " << Brief(subtypes());
1804   os << "\n - instance: " << Brief(instance());
1805   os << "\n";
1806 }
1807 
WasmStructPrint(std::ostream & os)1808 void WasmStruct::WasmStructPrint(std::ostream& os) {
1809   PrintHeader(os, "WasmStruct");
1810   wasm::StructType* struct_type = type();
1811   os << "\n - fields (" << struct_type->field_count() << "):";
1812   for (uint32_t i = 0; i < struct_type->field_count(); i++) {
1813     wasm::ValueType field = struct_type->field(i);
1814     os << "\n   - " << field.short_name() << ": ";
1815     uint32_t field_offset = struct_type->field_offset(i);
1816     Address field_address = RawFieldAddress(field_offset);
1817     switch (field.kind()) {
1818       case wasm::kI32:
1819         os << base::ReadUnalignedValue<int32_t>(field_address);
1820         break;
1821       case wasm::kI64:
1822         os << base::ReadUnalignedValue<int64_t>(field_address);
1823         break;
1824       case wasm::kF32:
1825         os << base::ReadUnalignedValue<float>(field_address);
1826         break;
1827       case wasm::kF64:
1828         os << base::ReadUnalignedValue<double>(field_address);
1829         break;
1830       case wasm::kI8:
1831         os << base::ReadUnalignedValue<int8_t>(field_address);
1832         break;
1833       case wasm::kI16:
1834         os << base::ReadUnalignedValue<int16_t>(field_address);
1835         break;
1836       case wasm::kRef:
1837       case wasm::kOptRef:
1838       case wasm::kRtt: {
1839         Tagged_t raw = base::ReadUnalignedValue<Tagged_t>(field_address);
1840 #if V8_COMPRESS_POINTERS
1841         Address obj = DecompressTaggedPointer(address(), raw);
1842 #else
1843         Address obj = raw;
1844 #endif
1845         os << Brief(Object(obj));
1846         break;
1847       }
1848       case wasm::kS128:
1849         os << "UNIMPLEMENTED";  // TODO(7748): Implement.
1850         break;
1851       case wasm::kBottom:
1852       case wasm::kVoid:
1853         UNREACHABLE();
1854     }
1855   }
1856   os << "\n";
1857 }
1858 
WasmArrayPrint(std::ostream & os)1859 void WasmArray::WasmArrayPrint(std::ostream& os) {
1860   PrintHeader(os, "WasmArray");
1861   wasm::ArrayType* array_type = type();
1862   uint32_t len = length();
1863   os << "\n - type: " << array_type->element_type().name();
1864   os << "\n - length: " << len;
1865   Address data_ptr = ptr() + WasmArray::kHeaderSize - kHeapObjectTag;
1866   switch (array_type->element_type().kind()) {
1867     case wasm::kI32:
1868       PrintTypedArrayElements(os, reinterpret_cast<int32_t*>(data_ptr), len,
1869                               true);
1870       break;
1871     case wasm::kI64:
1872       PrintTypedArrayElements(os, reinterpret_cast<int64_t*>(data_ptr), len,
1873                               true);
1874       break;
1875     case wasm::kF32:
1876       PrintTypedArrayElements(os, reinterpret_cast<float*>(data_ptr), len,
1877                               true);
1878       break;
1879     case wasm::kF64:
1880       PrintTypedArrayElements(os, reinterpret_cast<double*>(data_ptr), len,
1881                               true);
1882       break;
1883     case wasm::kI8:
1884       PrintTypedArrayElements(os, reinterpret_cast<int8_t*>(data_ptr), len,
1885                               true);
1886       break;
1887     case wasm::kI16:
1888       PrintTypedArrayElements(os, reinterpret_cast<int16_t*>(data_ptr), len,
1889                               true);
1890       break;
1891     case wasm::kS128:
1892     case wasm::kRef:
1893     case wasm::kOptRef:
1894     case wasm::kRtt:
1895       os << "\n   Printing elements of this type is unimplemented, sorry";
1896       // TODO(7748): Implement.
1897       break;
1898     case wasm::kBottom:
1899     case wasm::kVoid:
1900       UNREACHABLE();
1901   }
1902   os << "\n";
1903 }
1904 
WasmContinuationObjectPrint(std::ostream & os)1905 void WasmContinuationObject::WasmContinuationObjectPrint(std::ostream& os) {
1906   PrintHeader(os, "WasmContinuationObject");
1907   os << "\n - parent: " << parent();
1908   os << "\n - jmpbuf: " << jmpbuf();
1909   os << "\n - stack: " << stack();
1910   os << "\n";
1911 }
1912 
WasmSuspenderObjectPrint(std::ostream & os)1913 void WasmSuspenderObject::WasmSuspenderObjectPrint(std::ostream& os) {
1914   PrintHeader(os, "WasmSuspenderObject");
1915   os << "\n - continuation: " << continuation();
1916   os << "\n - parent: " << parent();
1917   os << "\n - state: " << state();
1918   os << "\n";
1919 }
1920 
WasmInstanceObjectPrint(std::ostream & os)1921 void WasmInstanceObject::WasmInstanceObjectPrint(std::ostream& os) {
1922   JSObjectPrintHeader(os, *this, "WasmInstanceObject");
1923   os << "\n - module_object: " << Brief(module_object());
1924   os << "\n - exports_object: " << Brief(exports_object());
1925   os << "\n - native_context: " << Brief(native_context());
1926   if (has_memory_object()) {
1927     os << "\n - memory_object: " << Brief(memory_object());
1928   }
1929   if (has_untagged_globals_buffer()) {
1930     os << "\n - untagged_globals_buffer: " << Brief(untagged_globals_buffer());
1931   }
1932   if (has_tagged_globals_buffer()) {
1933     os << "\n - tagged_globals_buffer: " << Brief(tagged_globals_buffer());
1934   }
1935   if (has_imported_mutable_globals_buffers()) {
1936     os << "\n - imported_mutable_globals_buffers: "
1937        << Brief(imported_mutable_globals_buffers());
1938   }
1939   for (int i = 0; i < tables().length(); i++) {
1940     os << "\n - table " << i << ": " << Brief(tables().get(i));
1941   }
1942   os << "\n - imported_function_refs: " << Brief(imported_function_refs());
1943   if (has_indirect_function_table_refs()) {
1944     os << "\n - indirect_function_table_refs: "
1945        << Brief(indirect_function_table_refs());
1946   }
1947   if (has_managed_native_allocations()) {
1948     os << "\n - managed_native_allocations: "
1949        << Brief(managed_native_allocations());
1950   }
1951   if (has_tags_table()) {
1952     os << "\n - tags table: " << Brief(tags_table());
1953   }
1954   os << "\n - managed object maps: " << Brief(managed_object_maps());
1955   os << "\n - feedback vectors: " << Brief(feedback_vectors());
1956   os << "\n - memory_start: " << static_cast<void*>(memory_start());
1957   os << "\n - memory_size: " << memory_size();
1958   os << "\n - imported_function_targets: "
1959      << static_cast<void*>(imported_function_targets());
1960   os << "\n - globals_start: " << static_cast<void*>(globals_start());
1961   os << "\n - imported_mutable_globals: "
1962      << static_cast<void*>(imported_mutable_globals());
1963   os << "\n - indirect_function_table_size: " << indirect_function_table_size();
1964   os << "\n - indirect_function_table_sig_ids: "
1965      << static_cast<void*>(indirect_function_table_sig_ids());
1966   os << "\n - indirect_function_table_targets: "
1967      << static_cast<void*>(indirect_function_table_targets());
1968   JSObjectPrintBody(os, *this);
1969   os << "\n";
1970 }
1971 
1972 // Never called directly, as WasmFunctionData is an "abstract" class.
WasmFunctionDataPrint(std::ostream & os)1973 void WasmFunctionData::WasmFunctionDataPrint(std::ostream& os) {
1974   os << "\n - internal: " << Brief(internal());
1975   os << "\n - wrapper_code: " << Brief(TorqueGeneratedClass::wrapper_code());
1976 }
1977 
WasmExportedFunctionDataPrint(std::ostream & os)1978 void WasmExportedFunctionData::WasmExportedFunctionDataPrint(std::ostream& os) {
1979   PrintHeader(os, "WasmExportedFunctionData");
1980   WasmFunctionDataPrint(os);
1981   os << "\n - instance: " << Brief(instance());
1982   os << "\n - function_index: " << function_index();
1983   os << "\n - signature: " << Brief(signature());
1984   os << "\n - wrapper_budget: " << wrapper_budget();
1985   os << "\n - suspender: " << suspender();
1986   os << "\n";
1987 }
1988 
WasmJSFunctionDataPrint(std::ostream & os)1989 void WasmJSFunctionData::WasmJSFunctionDataPrint(std::ostream& os) {
1990   PrintHeader(os, "WasmJSFunctionData");
1991   WasmFunctionDataPrint(os);
1992   os << "\n - serialized_return_count: " << serialized_return_count();
1993   os << "\n - serialized_parameter_count: " << serialized_parameter_count();
1994   os << "\n - serialized_signature: " << Brief(serialized_signature());
1995   os << "\n";
1996 }
1997 
WasmOnFulfilledDataPrint(std::ostream & os)1998 void WasmOnFulfilledData::WasmOnFulfilledDataPrint(std::ostream& os) {
1999   PrintHeader(os, "WasmOnFulfilledData");
2000   os << "\n - suspender: " << Brief(suspender());
2001   os << '\n';
2002 }
2003 
WasmApiFunctionRefPrint(std::ostream & os)2004 void WasmApiFunctionRef::WasmApiFunctionRefPrint(std::ostream& os) {
2005   PrintHeader(os, "WasmApiFunctionRef");
2006   os << "\n - isolate_root: " << reinterpret_cast<void*>(isolate_root());
2007   os << "\n - native_context: " << Brief(native_context());
2008   os << "\n - callable: " << Brief(callable());
2009   os << "\n - suspender: " << Brief(suspender());
2010   os << "\n";
2011 }
2012 
WasmInternalFunctionPrint(std::ostream & os)2013 void WasmInternalFunction::WasmInternalFunctionPrint(std::ostream& os) {
2014   PrintHeader(os, "WasmInternalFunction");
2015   os << "\n - call target: " << reinterpret_cast<void*>(foreign_address());
2016   os << "\n - ref: " << Brief(ref());
2017   os << "\n - external: " << Brief(external());
2018   os << "\n - code: " << Brief(code());
2019   os << "\n";
2020 }
2021 
WasmCapiFunctionDataPrint(std::ostream & os)2022 void WasmCapiFunctionData::WasmCapiFunctionDataPrint(std::ostream& os) {
2023   PrintHeader(os, "WasmCapiFunctionData");
2024   WasmFunctionDataPrint(os);
2025   os << "\n - embedder_data: " << Brief(embedder_data());
2026   os << "\n - serialized_signature: " << Brief(serialized_signature());
2027   os << "\n";
2028 }
2029 
WasmModuleObjectPrint(std::ostream & os)2030 void WasmModuleObject::WasmModuleObjectPrint(std::ostream& os) {
2031   PrintHeader(os, "WasmModuleObject");
2032   os << "\n - module: " << module();
2033   os << "\n - native module: " << native_module();
2034   os << "\n - export wrappers: " << Brief(export_wrappers());
2035   os << "\n - script: " << Brief(script());
2036   os << "\n";
2037 }
2038 
WasmGlobalObjectPrint(std::ostream & os)2039 void WasmGlobalObject::WasmGlobalObjectPrint(std::ostream& os) {
2040   PrintHeader(os, "WasmGlobalObject");
2041   if (type().is_reference()) {
2042     os << "\n - tagged_buffer: " << Brief(tagged_buffer());
2043   } else {
2044     os << "\n - untagged_buffer: " << Brief(untagged_buffer());
2045   }
2046   os << "\n - offset: " << offset();
2047   os << "\n - raw_type: " << raw_type();
2048   os << "\n - is_mutable: " << is_mutable();
2049   os << "\n - type: " << type();
2050   os << "\n - is_mutable: " << is_mutable();
2051   os << "\n";
2052 }
2053 
WasmIndirectFunctionTablePrint(std::ostream & os)2054 void WasmIndirectFunctionTable::WasmIndirectFunctionTablePrint(
2055     std::ostream& os) {
2056   PrintHeader(os, "WasmIndirectFunctionTable");
2057   os << "\n - size: " << size();
2058   os << "\n - sig_ids: " << static_cast<void*>(sig_ids());
2059   os << "\n - targets: " << static_cast<void*>(targets());
2060   if (has_managed_native_allocations()) {
2061     os << "\n - managed_native_allocations: "
2062        << Brief(managed_native_allocations());
2063   }
2064   os << "\n - refs: " << Brief(refs());
2065   os << "\n";
2066 }
2067 
WasmValueObjectPrint(std::ostream & os)2068 void WasmValueObject::WasmValueObjectPrint(std::ostream& os) {
2069   PrintHeader(os, "WasmValueObject");
2070   os << "\n - value: " << Brief(value());
2071   os << "\n";
2072 }
2073 #endif  // V8_ENABLE_WEBASSEMBLY
2074 
LoadHandlerPrint(std::ostream & os)2075 void LoadHandler::LoadHandlerPrint(std::ostream& os) {
2076   PrintHeader(os, "LoadHandler");
2077   // TODO(ishell): implement printing based on handler kind
2078   os << "\n - handler: " << Brief(smi_handler());
2079   os << "\n - validity_cell: " << Brief(validity_cell());
2080   int data_count = data_field_count();
2081   if (data_count >= 1) {
2082     os << "\n - data1: " << Brief(data1());
2083   }
2084   if (data_count >= 2) {
2085     os << "\n - data2: " << Brief(data2());
2086   }
2087   if (data_count >= 3) {
2088     os << "\n - data3: " << Brief(data3());
2089   }
2090   os << "\n";
2091 }
2092 
StoreHandlerPrint(std::ostream & os)2093 void StoreHandler::StoreHandlerPrint(std::ostream& os) {
2094   PrintHeader(os, "StoreHandler");
2095   // TODO(ishell): implement printing based on handler kind
2096   os << "\n - handler: " << Brief(smi_handler());
2097   os << "\n - validity_cell: " << Brief(validity_cell());
2098   int data_count = data_field_count();
2099   if (data_count >= 1) {
2100     os << "\n - data1: " << Brief(data1());
2101   }
2102   if (data_count >= 2) {
2103     os << "\n - data2: " << Brief(data2());
2104   }
2105   if (data_count >= 3) {
2106     os << "\n - data3: " << Brief(data3());
2107   }
2108   os << "\n";
2109 }
2110 
CallHandlerInfoPrint(std::ostream & os)2111 void CallHandlerInfo::CallHandlerInfoPrint(std::ostream& os) {
2112   PrintHeader(os, "CallHandlerInfo");
2113   os << "\n - callback: " << Brief(callback());
2114   os << "\n - js_callback: " << Brief(js_callback());
2115   os << "\n - data: " << Brief(data());
2116   os << "\n - side_effect_free: "
2117      << (IsSideEffectFreeCallHandlerInfo() ? "true" : "false");
2118   os << "\n";
2119 }
2120 
FunctionTemplateInfoPrint(std::ostream & os)2121 void FunctionTemplateInfo::FunctionTemplateInfoPrint(std::ostream& os) {
2122   PrintHeader(os, "FunctionTemplateInfo");
2123   os << "\n - class name: " << Brief(class_name());
2124   os << "\n - tag: " << tag();
2125   os << "\n - serial_number: " << serial_number();
2126   os << "\n - property_list: " << Brief(property_list());
2127   os << "\n - call_code: " << Brief(call_code(kAcquireLoad));
2128   os << "\n - property_accessors: " << Brief(property_accessors());
2129   os << "\n - signature: " << Brief(signature());
2130   os << "\n - cached_property_name: " << Brief(cached_property_name());
2131   os << "\n - undetectable: " << (undetectable() ? "true" : "false");
2132   os << "\n - need_access_check: " << (needs_access_check() ? "true" : "false");
2133   os << "\n - instantiated: " << (instantiated() ? "true" : "false");
2134   os << "\n - rare_data: " << Brief(rare_data(kAcquireLoad));
2135   os << "\n";
2136 }
2137 
ObjectTemplateInfoPrint(std::ostream & os)2138 void ObjectTemplateInfo::ObjectTemplateInfoPrint(std::ostream& os) {
2139   PrintHeader(os, "ObjectTemplateInfo");
2140   os << "\n - tag: " << tag();
2141   os << "\n - serial_number: " << serial_number();
2142   os << "\n - property_list: " << Brief(property_list());
2143   os << "\n - property_accessors: " << Brief(property_accessors());
2144   os << "\n - constructor: " << Brief(constructor());
2145   os << "\n - embedder_field_count: " << embedder_field_count();
2146   os << "\n - immutable_proto: " << (immutable_proto() ? "true" : "false");
2147   os << "\n";
2148 }
2149 
AllocationSitePrint(std::ostream & os)2150 void AllocationSite::AllocationSitePrint(std::ostream& os) {
2151   PrintHeader(os, "AllocationSite");
2152   if (this->HasWeakNext()) os << "\n - weak_next: " << Brief(weak_next());
2153   os << "\n - dependent code: " << Brief(dependent_code());
2154   os << "\n - nested site: " << Brief(nested_site());
2155   os << "\n - memento found count: "
2156      << Brief(Smi::FromInt(memento_found_count()));
2157   os << "\n - memento create count: "
2158      << Brief(Smi::FromInt(memento_create_count()));
2159   os << "\n - pretenure decision: "
2160      << Brief(Smi::FromInt(pretenure_decision()));
2161   os << "\n - transition_info: ";
2162   if (!PointsToLiteral()) {
2163     ElementsKind kind = GetElementsKind();
2164     os << "Array allocation with ElementsKind " << ElementsKindToString(kind);
2165   } else if (boilerplate().IsJSArray()) {
2166     os << "Array literal with boilerplate " << Brief(boilerplate());
2167   } else {
2168     os << "Object literal with boilerplate " << Brief(boilerplate());
2169   }
2170   os << "\n";
2171 }
2172 
AllocationMementoPrint(std::ostream & os)2173 void AllocationMemento::AllocationMementoPrint(std::ostream& os) {
2174   PrintHeader(os, "AllocationMemento");
2175   os << "\n - allocation site: ";
2176   if (IsValid()) {
2177     GetAllocationSite().AllocationSitePrint(os);
2178   } else {
2179     os << "<invalid>\n";
2180   }
2181 }
2182 
ScriptOrModulePrint(std::ostream & os)2183 void ScriptOrModule::ScriptOrModulePrint(std::ostream& os) {
2184   PrintHeader(os, "ScriptOrModule");
2185   os << "\n - host_defined_options: " << Brief(host_defined_options());
2186   os << "\n - resource_name: " << Brief(resource_name());
2187 }
2188 
ScriptPrint(std::ostream & os)2189 void Script::ScriptPrint(std::ostream& os) {
2190   PrintHeader(os, "Script");
2191   os << "\n - source: " << Brief(source());
2192   os << "\n - name: " << Brief(name());
2193   os << "\n - source_url: " << Brief(source_url());
2194   os << "\n - line_offset: " << line_offset();
2195   os << "\n - column_offset: " << column_offset();
2196   os << "\n - type: " << type();
2197   os << "\n - id: " << id();
2198   os << "\n - context data: " << Brief(context_data());
2199   os << "\n - compilation type: " << compilation_type();
2200   os << "\n - line ends: " << Brief(line_ends());
2201   bool is_wasm = false;
2202 #if V8_ENABLE_WEBASSEMBLY
2203   if ((is_wasm = (type() == TYPE_WASM))) {
2204     if (has_wasm_breakpoint_infos()) {
2205       os << "\n - wasm_breakpoint_infos: " << Brief(wasm_breakpoint_infos());
2206     }
2207   }
2208 #endif  // V8_ENABLE_WEBASSEMBLY
2209   if (!is_wasm) {
2210     if (has_eval_from_shared()) {
2211       os << "\n - eval from shared: " << Brief(eval_from_shared());
2212     } else if (is_wrapped()) {
2213       os << "\n - wrapped arguments: " << Brief(wrapped_arguments());
2214     } else if (type() == TYPE_WEB_SNAPSHOT) {
2215       os << "\n - shared function info table: "
2216          << Brief(shared_function_info_table());
2217     }
2218     os << "\n - eval from position: " << eval_from_position();
2219   }
2220   os << "\n - shared function infos: " << Brief(shared_function_infos());
2221   os << "\n";
2222 }
2223 
JSTemporalPlainDatePrint(std::ostream & os)2224 void JSTemporalPlainDate::JSTemporalPlainDatePrint(std::ostream& os) {
2225   JSObjectPrintHeader(os, *this, "JSTemporalPlainDate");
2226   JSObjectPrintBody(os, *this);
2227 }
2228 
JSTemporalPlainTimePrint(std::ostream & os)2229 void JSTemporalPlainTime::JSTemporalPlainTimePrint(std::ostream& os) {
2230   JSObjectPrintHeader(os, *this, "JSTemporalPlainTime");
2231   JSObjectPrintBody(os, *this);
2232 }
2233 
JSTemporalPlainDateTimePrint(std::ostream & os)2234 void JSTemporalPlainDateTime::JSTemporalPlainDateTimePrint(std::ostream& os) {
2235   JSObjectPrintHeader(os, *this, "JSTemporalPlainDateTime");
2236   JSObjectPrintBody(os, *this);
2237 }
2238 
JSTemporalZonedDateTimePrint(std::ostream & os)2239 void JSTemporalZonedDateTime::JSTemporalZonedDateTimePrint(std::ostream& os) {
2240   JSObjectPrintHeader(os, *this, "JSTemporalZonedDateTime");
2241   JSObjectPrintBody(os, *this);
2242 }
2243 
JSTemporalDurationPrint(std::ostream & os)2244 void JSTemporalDuration::JSTemporalDurationPrint(std::ostream& os) {
2245   JSObjectPrintHeader(os, *this, "JSTemporalDuration");
2246   JSObjectPrintBody(os, *this);
2247 }
2248 
JSTemporalInstantPrint(std::ostream & os)2249 void JSTemporalInstant::JSTemporalInstantPrint(std::ostream& os) {
2250   JSObjectPrintHeader(os, *this, "JSTemporalInstant");
2251   JSObjectPrintBody(os, *this);
2252 }
2253 
JSTemporalPlainYearMonthPrint(std::ostream & os)2254 void JSTemporalPlainYearMonth::JSTemporalPlainYearMonthPrint(std::ostream& os) {
2255   JSObjectPrintHeader(os, *this, "JSTemporalPlainYearMonth");
2256   JSObjectPrintBody(os, *this);
2257 }
2258 
JSTemporalPlainMonthDayPrint(std::ostream & os)2259 void JSTemporalPlainMonthDay::JSTemporalPlainMonthDayPrint(std::ostream& os) {
2260   JSObjectPrintHeader(os, *this, "JSTemporalPlainMonthDay");
2261   JSObjectPrintBody(os, *this);
2262 }
2263 
JSTemporalTimeZonePrint(std::ostream & os)2264 void JSTemporalTimeZone::JSTemporalTimeZonePrint(std::ostream& os) {
2265   JSObjectPrintHeader(os, *this, "JSTemporalTimeZone");
2266   JSObjectPrintBody(os, *this);
2267 }
2268 
JSTemporalCalendarPrint(std::ostream & os)2269 void JSTemporalCalendar::JSTemporalCalendarPrint(std::ostream& os) {
2270   JSObjectPrintHeader(os, *this, "JSTemporalCalendar");
2271   JSObjectPrintBody(os, *this);
2272 }
2273 #ifdef V8_INTL_SUPPORT
JSV8BreakIteratorPrint(std::ostream & os)2274 void JSV8BreakIterator::JSV8BreakIteratorPrint(std::ostream& os) {
2275   JSObjectPrintHeader(os, *this, "JSV8BreakIterator");
2276   os << "\n - locale: " << Brief(locale());
2277   os << "\n - break iterator: " << Brief(break_iterator());
2278   os << "\n - unicode string: " << Brief(unicode_string());
2279   os << "\n - bound adopt text: " << Brief(bound_adopt_text());
2280   os << "\n - bound first: " << Brief(bound_first());
2281   os << "\n - bound next: " << Brief(bound_next());
2282   os << "\n - bound current: " << Brief(bound_current());
2283   os << "\n - bound break type: " << Brief(bound_break_type());
2284   os << "\n";
2285 }
2286 
JSCollatorPrint(std::ostream & os)2287 void JSCollator::JSCollatorPrint(std::ostream& os) {
2288   JSObjectPrintHeader(os, *this, "JSCollator");
2289   os << "\n - icu collator: " << Brief(icu_collator());
2290   os << "\n - bound compare: " << Brief(bound_compare());
2291   JSObjectPrintBody(os, *this);
2292 }
2293 
JSDateTimeFormatPrint(std::ostream & os)2294 void JSDateTimeFormat::JSDateTimeFormatPrint(std::ostream& os) {
2295   JSObjectPrintHeader(os, *this, "JSDateTimeFormat");
2296   os << "\n - locale: " << Brief(locale());
2297   os << "\n - icu locale: " << Brief(icu_locale());
2298   os << "\n - icu simple date format: " << Brief(icu_simple_date_format());
2299   os << "\n - icu date interval format: " << Brief(icu_date_interval_format());
2300   os << "\n - bound format: " << Brief(bound_format());
2301   os << "\n - hour cycle: " << HourCycleAsString();
2302   JSObjectPrintBody(os, *this);
2303 }
2304 
JSDisplayNamesPrint(std::ostream & os)2305 void JSDisplayNames::JSDisplayNamesPrint(std::ostream& os) {
2306   JSObjectPrintHeader(os, *this, "JSDisplayNames");
2307   os << "\n - internal: " << Brief(internal());
2308   os << "\n - style: " << StyleAsString();
2309   os << "\n - fallback: " << FallbackAsString();
2310   JSObjectPrintBody(os, *this);
2311 }
2312 
JSListFormatPrint(std::ostream & os)2313 void JSListFormat::JSListFormatPrint(std::ostream& os) {
2314   JSObjectPrintHeader(os, *this, "JSListFormat");
2315   os << "\n - locale: " << Brief(locale());
2316   os << "\n - style: " << StyleAsString();
2317   os << "\n - type: " << TypeAsString();
2318   os << "\n - icu formatter: " << Brief(icu_formatter());
2319   JSObjectPrintBody(os, *this);
2320 }
2321 
JSLocalePrint(std::ostream & os)2322 void JSLocale::JSLocalePrint(std::ostream& os) {
2323   JSObjectPrintHeader(os, *this, "JSLocale");
2324   os << "\n - icu locale: " << Brief(icu_locale());
2325   JSObjectPrintBody(os, *this);
2326 }
2327 
JSNumberFormatPrint(std::ostream & os)2328 void JSNumberFormat::JSNumberFormatPrint(std::ostream& os) {
2329   JSObjectPrintHeader(os, *this, "JSNumberFormat");
2330   os << "\n - locale: " << Brief(locale());
2331   os << "\n - icu_number_formatter: " << Brief(icu_number_formatter());
2332   os << "\n - bound_format: " << Brief(bound_format());
2333   JSObjectPrintBody(os, *this);
2334 }
2335 
JSPluralRulesPrint(std::ostream & os)2336 void JSPluralRules::JSPluralRulesPrint(std::ostream& os) {
2337   JSObjectPrintHeader(os, *this, "JSPluralRules");
2338   os << "\n - locale: " << Brief(locale());
2339   os << "\n - type: " << TypeAsString();
2340   os << "\n - icu plural rules: " << Brief(icu_plural_rules());
2341   os << "\n - icu_number_formatter: " << Brief(icu_number_formatter());
2342   JSObjectPrintBody(os, *this);
2343 }
2344 
JSRelativeTimeFormatPrint(std::ostream & os)2345 void JSRelativeTimeFormat::JSRelativeTimeFormatPrint(std::ostream& os) {
2346   JSObjectPrintHeader(os, *this, "JSRelativeTimeFormat");
2347   os << "\n - locale: " << Brief(locale());
2348   os << "\n - numberingSystem: " << Brief(numberingSystem());
2349   os << "\n - numeric: " << NumericAsString();
2350   os << "\n - icu formatter: " << Brief(icu_formatter());
2351   os << "\n";
2352 }
2353 
JSSegmentIteratorPrint(std::ostream & os)2354 void JSSegmentIterator::JSSegmentIteratorPrint(std::ostream& os) {
2355   JSObjectPrintHeader(os, *this, "JSSegmentIterator");
2356   os << "\n - icu break iterator: " << Brief(icu_break_iterator());
2357   os << "\n - granularity: " << GranularityAsString(GetIsolate());
2358   os << "\n";
2359 }
2360 
JSSegmenterPrint(std::ostream & os)2361 void JSSegmenter::JSSegmenterPrint(std::ostream& os) {
2362   JSObjectPrintHeader(os, *this, "JSSegmenter");
2363   os << "\n - locale: " << Brief(locale());
2364   os << "\n - granularity: " << GranularityAsString(GetIsolate());
2365   os << "\n - icu break iterator: " << Brief(icu_break_iterator());
2366   JSObjectPrintBody(os, *this);
2367 }
2368 
JSSegmentsPrint(std::ostream & os)2369 void JSSegments::JSSegmentsPrint(std::ostream& os) {
2370   JSObjectPrintHeader(os, *this, "JSSegments");
2371   os << "\n - icu break iterator: " << Brief(icu_break_iterator());
2372   os << "\n - unicode string: " << Brief(unicode_string());
2373   os << "\n - granularity: " << GranularityAsString(GetIsolate());
2374   JSObjectPrintBody(os, *this);
2375 }
2376 #endif  // V8_INTL_SUPPORT
2377 
2378 namespace {
PrintScopeInfoList(ScopeInfo scope_info,std::ostream & os,const char * list_name,int length)2379 void PrintScopeInfoList(ScopeInfo scope_info, std::ostream& os,
2380                         const char* list_name, int length) {
2381   DisallowGarbageCollection no_gc;
2382   if (length <= 0) return;
2383   os << "\n - " << list_name;
2384   os << " {\n";
2385   for (auto it : ScopeInfo::IterateLocalNames(&scope_info, no_gc)) {
2386     os << "    - " << it->index() << ": " << it->name() << "\n";
2387   }
2388   os << "  }";
2389 }
2390 }  // namespace
2391 
ScopeInfoPrint(std::ostream & os)2392 void ScopeInfo::ScopeInfoPrint(std::ostream& os) {
2393   PrintHeader(os, "ScopeInfo");
2394   if (IsEmpty()) {
2395     os << "\n - empty\n";
2396     return;
2397   }
2398   int flags = Flags();
2399 
2400   os << "\n - parameters: " << ParameterCount();
2401   os << "\n - context locals : " << ContextLocalCount();
2402   if (HasInlinedLocalNames()) {
2403     os << "\n - inlined local names";
2404   } else {
2405     os << "\n - local names in a hashtable: "
2406        << Brief(context_local_names_hashtable());
2407   }
2408 
2409   os << "\n - scope type: " << scope_type();
2410   if (SloppyEvalCanExtendVars()) os << "\n - sloppy eval";
2411   os << "\n - language mode: " << language_mode();
2412   if (is_declaration_scope()) os << "\n - declaration scope";
2413   if (HasReceiver()) {
2414     os << "\n - receiver: " << ReceiverVariableBits::decode(flags);
2415   }
2416   if (ClassScopeHasPrivateBrand()) os << "\n - class scope has private brand";
2417   if (HasSavedClassVariable()) os << "\n - has saved class variable";
2418   if (HasNewTarget()) os << "\n - needs new target";
2419   if (HasFunctionName()) {
2420     os << "\n - function name(" << FunctionVariableBits::decode(flags) << "): ";
2421     FunctionName().ShortPrint(os);
2422   }
2423   if (IsAsmModule()) os << "\n - asm module";
2424   if (HasSimpleParameters()) os << "\n - simple parameters";
2425   if (PrivateNameLookupSkipsOuterClass())
2426     os << "\n - private name lookup skips outer class";
2427   os << "\n - function kind: " << function_kind();
2428   if (HasOuterScopeInfo()) {
2429     os << "\n - outer scope info: " << Brief(OuterScopeInfo());
2430   }
2431   if (HasLocalsBlockList()) {
2432     os << "\n - locals blocklist: " << Brief(LocalsBlockList());
2433   }
2434   if (HasFunctionName()) {
2435     os << "\n - function name: " << Brief(FunctionName());
2436   }
2437   if (HasInferredFunctionName()) {
2438     os << "\n - inferred function name: " << Brief(InferredFunctionName());
2439   }
2440   if (HasContextExtensionSlot()) {
2441     os << "\n - has context extension slot";
2442   }
2443 
2444   if (HasPositionInfo()) {
2445     os << "\n - start position: " << StartPosition();
2446     os << "\n - end position: " << EndPosition();
2447   }
2448   os << "\n - length: " << length();
2449   if (length() > 0) {
2450     PrintScopeInfoList(*this, os, "context slots", ContextLocalCount());
2451     // TODO(neis): Print module stuff if present.
2452   }
2453   os << "\n";
2454 }
2455 
PreparseDataPrint(std::ostream & os)2456 void PreparseData::PreparseDataPrint(std::ostream& os) {
2457   PrintHeader(os, "PreparseData");
2458   os << "\n - data_length: " << data_length();
2459   os << "\n - children_length: " << children_length();
2460   if (data_length() > 0) {
2461     os << "\n - data-start: " << (address() + kDataStartOffset);
2462   }
2463   if (children_length() > 0) {
2464     os << "\n - children-start: " << inner_start_offset();
2465   }
2466   for (int i = 0; i < children_length(); ++i) {
2467     os << "\n - [" << i << "]: " << Brief(get_child(i));
2468   }
2469   os << "\n";
2470 }
2471 
2472 template <HeapObjectReferenceType kRefType, typename StorageType>
Print()2473 void TaggedImpl<kRefType, StorageType>::Print() {
2474   StdoutStream os;
2475   this->Print(os);
2476   os << std::flush;
2477 }
2478 
2479 template <HeapObjectReferenceType kRefType, typename StorageType>
Print(std::ostream & os)2480 void TaggedImpl<kRefType, StorageType>::Print(std::ostream& os) {
2481   Smi smi;
2482   HeapObject heap_object;
2483   if (ToSmi(&smi)) {
2484     smi.SmiPrint(os);
2485   } else if (IsCleared()) {
2486     os << "[cleared]";
2487   } else if (GetHeapObjectIfWeak(&heap_object)) {
2488     os << "[weak] ";
2489     heap_object.HeapObjectPrint(os);
2490   } else if (GetHeapObjectIfStrong(&heap_object)) {
2491     heap_object.HeapObjectPrint(os);
2492   } else {
2493     UNREACHABLE();
2494   }
2495 }
2496 
HeapNumberPrint(std::ostream & os)2497 void HeapNumber::HeapNumberPrint(std::ostream& os) {
2498   HeapNumberShortPrint(os);
2499   os << "\n";
2500 }
2501 
2502 #endif  // OBJECT_PRINT
2503 
HeapNumberShortPrint(std::ostream & os)2504 void HeapNumber::HeapNumberShortPrint(std::ostream& os) {
2505   static constexpr uint64_t kUint64AllBitsSet =
2506       static_cast<uint64_t>(int64_t{-1});
2507   // Min/max integer values representable by 52 bits of mantissa and 1 sign bit.
2508   static constexpr int64_t kMinSafeInteger =
2509       static_cast<int64_t>(kUint64AllBitsSet << 53);
2510   static constexpr int64_t kMaxSafeInteger = -(kMinSafeInteger + 1);
2511 
2512   double val = value();
2513   if (val == DoubleToInteger(val) &&
2514       val >= static_cast<double>(kMinSafeInteger) &&
2515       val <= static_cast<double>(kMaxSafeInteger)) {
2516     int64_t i = static_cast<int64_t>(val);
2517     os << i << ".0";
2518   } else {
2519     os << val;
2520   }
2521 }
2522 
2523 // TODO(cbruni): remove once the new maptracer is in place.
NameShortPrint()2524 void Name::NameShortPrint() {
2525   if (this->IsString()) {
2526     PrintF("%s", String::cast(*this).ToCString().get());
2527   } else {
2528     DCHECK(this->IsSymbol());
2529     Symbol s = Symbol::cast(*this);
2530     if (s.description().IsUndefined()) {
2531       PrintF("#<%s>", s.PrivateSymbolToName());
2532     } else {
2533       PrintF("<%s>", String::cast(s.description()).ToCString().get());
2534     }
2535   }
2536 }
2537 
2538 // TODO(cbruni): remove once the new maptracer is in place.
NameShortPrint(base::Vector<char> str)2539 int Name::NameShortPrint(base::Vector<char> str) {
2540   if (this->IsString()) {
2541     return SNPrintF(str, "%s", String::cast(*this).ToCString().get());
2542   } else {
2543     DCHECK(this->IsSymbol());
2544     Symbol s = Symbol::cast(*this);
2545     if (s.description().IsUndefined()) {
2546       return SNPrintF(str, "#<%s>", s.PrivateSymbolToName());
2547     } else {
2548       return SNPrintF(str, "<%s>",
2549                       String::cast(s.description()).ToCString().get());
2550     }
2551   }
2552 }
2553 
PrintMapDetails(std::ostream & os)2554 void Map::PrintMapDetails(std::ostream& os) {
2555   DisallowGarbageCollection no_gc;
2556   this->MapPrint(os);
2557   instance_descriptors().PrintDescriptors(os);
2558 }
2559 
MapPrint(std::ostream & os)2560 void Map::MapPrint(std::ostream& os) {
2561 #ifdef OBJECT_PRINT
2562   PrintHeader(os, "Map");
2563 #else
2564   os << "Map=" << reinterpret_cast<void*>(ptr());
2565 #endif
2566   os << "\n - type: " << instance_type();
2567   os << "\n - instance size: ";
2568   if (instance_size() == kVariableSizeSentinel) {
2569     os << "variable";
2570   } else {
2571     os << instance_size();
2572   }
2573   if (IsJSObjectMap()) {
2574     os << "\n - inobject properties: " << GetInObjectProperties();
2575   }
2576   os << "\n - elements kind: " << ElementsKindToString(elements_kind());
2577   os << "\n - unused property fields: " << UnusedPropertyFields();
2578   os << "\n - enum length: ";
2579   if (EnumLength() == kInvalidEnumCacheSentinel) {
2580     os << "invalid";
2581   } else {
2582     os << EnumLength();
2583   }
2584   if (is_deprecated()) os << "\n - deprecated_map";
2585   if (is_stable()) os << "\n - stable_map";
2586   if (is_migration_target()) os << "\n - migration_target";
2587   if (is_dictionary_map()) os << "\n - dictionary_map";
2588   if (has_named_interceptor()) os << "\n - named_interceptor";
2589   if (has_indexed_interceptor()) os << "\n - indexed_interceptor";
2590   if (may_have_interesting_symbols()) os << "\n - may_have_interesting_symbols";
2591   if (is_undetectable()) os << "\n - undetectable";
2592   if (is_callable()) os << "\n - callable";
2593   if (is_constructor()) os << "\n - constructor";
2594   if (has_prototype_slot()) {
2595     os << "\n - has_prototype_slot";
2596     if (has_non_instance_prototype()) os << " (non-instance prototype)";
2597   }
2598   if (is_access_check_needed()) os << "\n - access_check_needed";
2599   if (!is_extensible()) os << "\n - non-extensible";
2600   if (IsContextMap()) {
2601     os << "\n - native context: " << Brief(native_context());
2602   } else if (is_prototype_map()) {
2603     os << "\n - prototype_map";
2604     os << "\n - prototype info: " << Brief(prototype_info());
2605   } else {
2606     os << "\n - back pointer: " << Brief(GetBackPointer());
2607   }
2608   os << "\n - prototype_validity cell: " << Brief(prototype_validity_cell());
2609   os << "\n - instance descriptors " << (owns_descriptors() ? "(own) " : "")
2610      << "#" << NumberOfOwnDescriptors() << ": "
2611      << Brief(instance_descriptors());
2612 
2613   // Read-only maps can't have transitions, which is fortunate because we need
2614   // the isolate to iterate over the transitions.
2615   if (!IsReadOnlyHeapObject(*this)) {
2616     Isolate* isolate = GetIsolateFromWritableObject(*this);
2617     TransitionsAccessor transitions(isolate, *this);
2618     int nof_transitions = transitions.NumberOfTransitions();
2619     if (nof_transitions > 0) {
2620       os << "\n - transitions #" << nof_transitions << ": ";
2621       HeapObject heap_object;
2622       Smi smi;
2623       if (raw_transitions()->ToSmi(&smi)) {
2624         os << Brief(smi);
2625       } else if (raw_transitions()->GetHeapObject(&heap_object)) {
2626         os << Brief(heap_object);
2627       }
2628 #ifdef OBJECT_PRINT
2629       transitions.PrintTransitions(os);
2630 #endif  // OBJECT_PRINT
2631     }
2632   }
2633   os << "\n - prototype: " << Brief(prototype());
2634   if (!IsContextMap()) {
2635     os << "\n - constructor: " << Brief(GetConstructor());
2636   }
2637   os << "\n - dependent code: " << Brief(dependent_code());
2638   os << "\n - construction counter: " << construction_counter();
2639   os << "\n";
2640 }
2641 
PrintDescriptors(std::ostream & os)2642 void DescriptorArray::PrintDescriptors(std::ostream& os) {
2643   for (InternalIndex i : InternalIndex::Range(number_of_descriptors())) {
2644     Name key = GetKey(i);
2645     os << "\n  [" << i.as_int() << "]: ";
2646 #ifdef OBJECT_PRINT
2647     key.NamePrint(os);
2648 #else
2649     key.ShortPrint(os);
2650 #endif
2651     os << " ";
2652     PrintDescriptorDetails(os, i, PropertyDetails::kPrintFull);
2653   }
2654   os << "\n";
2655 }
2656 
PrintDescriptorDetails(std::ostream & os,InternalIndex descriptor,PropertyDetails::PrintMode mode)2657 void DescriptorArray::PrintDescriptorDetails(std::ostream& os,
2658                                              InternalIndex descriptor,
2659                                              PropertyDetails::PrintMode mode) {
2660   PropertyDetails details = GetDetails(descriptor);
2661   details.PrintAsFastTo(os, mode);
2662   os << " @ ";
2663   switch (details.location()) {
2664     case PropertyLocation::kField: {
2665       FieldType field_type = GetFieldType(descriptor);
2666       field_type.PrintTo(os);
2667       break;
2668     }
2669     case PropertyLocation::kDescriptor:
2670       Object value = GetStrongValue(descriptor);
2671       os << Brief(value);
2672       if (value.IsAccessorPair()) {
2673         AccessorPair pair = AccessorPair::cast(value);
2674         os << "(get: " << Brief(pair.getter())
2675            << ", set: " << Brief(pair.setter()) << ")";
2676       }
2677       break;
2678   }
2679 }
2680 
2681 #if defined(DEBUG) || defined(OBJECT_PRINT)
2682 // This method is only meant to be called from gdb for debugging purposes.
2683 // Since the string can also be in two-byte encoding, non-Latin1 characters
2684 // will be ignored in the output.
ToAsciiArray()2685 char* String::ToAsciiArray() {
2686   // Static so that subsequent calls frees previously allocated space.
2687   // This also means that previous results will be overwritten.
2688   static char* buffer = nullptr;
2689   if (buffer != nullptr) delete[] buffer;
2690   buffer = new char[length() + 1];
2691   WriteToFlat(*this, reinterpret_cast<uint8_t*>(buffer), 0, length());
2692   buffer[length()] = 0;
2693   return buffer;
2694 }
2695 
2696 // static
PrintOneTransition(std::ostream & os,Name key,Map target)2697 void TransitionsAccessor::PrintOneTransition(std::ostream& os, Name key,
2698                                              Map target) {
2699   os << "\n     ";
2700 #ifdef OBJECT_PRINT
2701   key.NamePrint(os);
2702 #else
2703   key.ShortPrint(os);
2704 #endif
2705   os << ": ";
2706   ReadOnlyRoots roots = key.GetReadOnlyRoots();
2707   if (key == roots.nonextensible_symbol()) {
2708     os << "(transition to non-extensible)";
2709   } else if (key == roots.sealed_symbol()) {
2710     os << "(transition to sealed)";
2711   } else if (key == roots.frozen_symbol()) {
2712     os << "(transition to frozen)";
2713   } else if (key == roots.elements_transition_symbol()) {
2714     os << "(transition to " << ElementsKindToString(target.elements_kind())
2715        << ")";
2716   } else if (key == roots.strict_function_transition_symbol()) {
2717     os << " (transition to strict function)";
2718   } else {
2719     DCHECK(!IsSpecialTransition(roots, key));
2720     os << "(transition to ";
2721     InternalIndex descriptor = target.LastAdded();
2722     DescriptorArray descriptors = target.instance_descriptors();
2723     descriptors.PrintDescriptorDetails(os, descriptor,
2724                                        PropertyDetails::kForTransitions);
2725     os << ")";
2726   }
2727   os << " -> " << Brief(target);
2728 }
2729 
PrintInternal(std::ostream & os)2730 void TransitionArray::PrintInternal(std::ostream& os) {
2731   int num_transitions = number_of_transitions();
2732   os << "Transition array #" << num_transitions << ":";
2733   for (int i = 0; i < num_transitions; i++) {
2734     Name key = GetKey(i);
2735     Map target = GetTarget(i);
2736     TransitionsAccessor::PrintOneTransition(os, key, target);
2737   }
2738   os << "\n" << std::flush;
2739 }
2740 
PrintTransitions(std::ostream & os)2741 void TransitionsAccessor::PrintTransitions(std::ostream& os) {
2742   switch (encoding()) {
2743     case kPrototypeInfo:
2744     case kUninitialized:
2745     case kMigrationTarget:
2746       return;
2747     case kWeakRef: {
2748       Map target = Map::cast(raw_transitions_->GetHeapObjectAssumeWeak());
2749       Name key = GetSimpleTransitionKey(target);
2750       PrintOneTransition(os, key, target);
2751       break;
2752     }
2753     case kFullTransitionArray:
2754       return transitions().PrintInternal(os);
2755   }
2756 }
2757 
PrintTransitionTree()2758 void TransitionsAccessor::PrintTransitionTree() {
2759   StdoutStream os;
2760   os << "map= " << Brief(map_);
2761   DisallowGarbageCollection no_gc;
2762   PrintTransitionTree(os, 0, &no_gc);
2763   os << "\n" << std::flush;
2764 }
2765 
PrintTransitionTree(std::ostream & os,int level,DisallowGarbageCollection * no_gc)2766 void TransitionsAccessor::PrintTransitionTree(
2767     std::ostream& os, int level, DisallowGarbageCollection* no_gc) {
2768   ReadOnlyRoots roots = ReadOnlyRoots(isolate_);
2769   int num_transitions = NumberOfTransitions();
2770   if (num_transitions == 0) return;
2771   for (int i = 0; i < num_transitions; i++) {
2772     Name key = GetKey(i);
2773     Map target = GetTarget(i);
2774     os << std::endl
2775        << "  " << level << "/" << i << ":" << std::setw(level * 2 + 2) << " ";
2776     std::stringstream ss;
2777     ss << Brief(target);
2778     os << std::left << std::setw(50) << ss.str() << ": ";
2779 
2780     if (key == roots.nonextensible_symbol()) {
2781       os << "to non-extensible";
2782     } else if (key == roots.sealed_symbol()) {
2783       os << "to sealed ";
2784     } else if (key == roots.frozen_symbol()) {
2785       os << "to frozen";
2786     } else if (key == roots.elements_transition_symbol()) {
2787       os << "to " << ElementsKindToString(target.elements_kind());
2788     } else if (key == roots.strict_function_transition_symbol()) {
2789       os << "to strict function";
2790     } else {
2791 #ifdef OBJECT_PRINT
2792       key.NamePrint(os);
2793 #else
2794       key.ShortPrint(os);
2795 #endif
2796       os << " ";
2797       DCHECK(!IsSpecialTransition(ReadOnlyRoots(isolate_), key));
2798       os << "to ";
2799       InternalIndex descriptor = target.LastAdded();
2800       DescriptorArray descriptors = target.instance_descriptors(isolate_);
2801       descriptors.PrintDescriptorDetails(os, descriptor,
2802                                          PropertyDetails::kForTransitions);
2803     }
2804     TransitionsAccessor transitions(isolate_, target);
2805     transitions.PrintTransitionTree(os, level + 1, no_gc);
2806   }
2807 }
2808 
PrintTransitions(std::ostream & os)2809 void JSObject::PrintTransitions(std::ostream& os) {
2810   TransitionsAccessor ta(GetIsolate(), map());
2811   if (ta.NumberOfTransitions() == 0) return;
2812   os << "\n - transitions";
2813   ta.PrintTransitions(os);
2814 }
2815 
2816 #endif  // defined(DEBUG) || defined(OBJECT_PRINT)
2817 }  // namespace internal
2818 }  // namespace v8
2819 
2820 namespace {
2821 
GetObjectFromRaw(void * object)2822 inline i::Object GetObjectFromRaw(void* object) {
2823   i::Address object_ptr = reinterpret_cast<i::Address>(object);
2824 #ifdef V8_COMPRESS_POINTERS
2825   if (RoundDown<i::kPtrComprCageBaseAlignment>(object_ptr) == i::kNullAddress) {
2826     // Try to decompress pointer.
2827     i::Isolate* isolate = i::Isolate::Current();
2828     object_ptr =
2829         i::DecompressTaggedAny(isolate, static_cast<i::Tagged_t>(object_ptr));
2830   }
2831 #endif
2832   return i::Object(object_ptr);
2833 }
2834 
2835 }  // namespace
2836 
2837 //
2838 // The following functions are used by our gdb macros.
2839 //
_v8_internal_Get_Object(void * object)2840 V8_EXPORT_PRIVATE extern i::Object _v8_internal_Get_Object(void* object) {
2841   return GetObjectFromRaw(object);
2842 }
2843 
_v8_internal_Print_Object(void * object)2844 V8_EXPORT_PRIVATE extern void _v8_internal_Print_Object(void* object) {
2845   GetObjectFromRaw(object).Print();
2846 }
2847 
_v8_internal_Print_LoadHandler(void * object)2848 V8_EXPORT_PRIVATE extern void _v8_internal_Print_LoadHandler(void* object) {
2849 #ifdef OBJECT_PRINT
2850   i::StdoutStream os;
2851   i::LoadHandler::PrintHandler(GetObjectFromRaw(object), os);
2852   os << std::flush;
2853 #endif
2854 }
2855 
_v8_internal_Print_StoreHandler(void * object)2856 V8_EXPORT_PRIVATE extern void _v8_internal_Print_StoreHandler(void* object) {
2857 #ifdef OBJECT_PRINT
2858   i::StdoutStream os;
2859   i::StoreHandler::PrintHandler(GetObjectFromRaw(object), os);
2860   os << std::flush;
2861 #endif
2862 }
2863 
_v8_internal_Print_Code(void * object)2864 V8_EXPORT_PRIVATE extern void _v8_internal_Print_Code(void* object) {
2865   i::Address address = reinterpret_cast<i::Address>(object);
2866   i::Isolate* isolate = i::Isolate::Current();
2867 
2868 #if V8_ENABLE_WEBASSEMBLY
2869   {
2870     i::wasm::WasmCodeRefScope scope;
2871     if (auto* wasm_code = i::wasm::GetWasmCodeManager()->LookupCode(address)) {
2872       i::StdoutStream os;
2873       wasm_code->Disassemble(nullptr, os, address);
2874       return;
2875     }
2876   }
2877 #endif  // V8_ENABLE_WEBASSEMBLY
2878 
2879   if (!isolate->heap()->InSpaceSlow(address, i::CODE_SPACE) &&
2880       !isolate->heap()->InSpaceSlow(address, i::CODE_LO_SPACE) &&
2881       !i::OffHeapInstructionStream::PcIsOffHeap(isolate, address) &&
2882       !i::ReadOnlyHeap::Contains(address)) {
2883     i::PrintF(
2884         "%p is not within the current isolate's code, read_only or embedded "
2885         "spaces\n",
2886         object);
2887     return;
2888   }
2889 
2890   i::Code code = isolate->FindCodeObject(address);
2891   if (!code.IsCode()) {
2892     i::PrintF("No code object found containing %p\n", object);
2893     return;
2894   }
2895 #ifdef ENABLE_DISASSEMBLER
2896   i::StdoutStream os;
2897   code.Disassemble(nullptr, os, isolate, address);
2898 #else   // ENABLE_DISASSEMBLER
2899   code.Print();
2900 #endif  // ENABLE_DISASSEMBLER
2901 }
2902 
_v8_internal_Print_StackTrace()2903 V8_EXPORT_PRIVATE extern void _v8_internal_Print_StackTrace() {
2904   i::Isolate* isolate = i::Isolate::Current();
2905   isolate->PrintStack(stdout);
2906 }
2907 
_v8_internal_Print_TransitionTree(void * object)2908 V8_EXPORT_PRIVATE extern void _v8_internal_Print_TransitionTree(void* object) {
2909   i::Object o(GetObjectFromRaw(object));
2910   if (!o.IsMap()) {
2911     printf("Please provide a valid Map\n");
2912   } else {
2913 #if defined(DEBUG) || defined(OBJECT_PRINT)
2914     i::Map map = i::Map::unchecked_cast(o);
2915     i::TransitionsAccessor transitions(i::Isolate::Current(), map);
2916     transitions.PrintTransitionTree();
2917 #endif
2918   }
2919 }
2920