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