// Copyright 2012 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/v8.h" #include "src/disasm.h" #include "src/disassembler.h" #include "src/heap/objects-visiting.h" #include "src/jsregexp.h" #include "src/ostreams.h" namespace v8 { namespace internal { #ifdef OBJECT_PRINT void Object::Print() { OFStream os(stdout); this->Print(os); os << std::flush; } void Object::Print(std::ostream& os) { // NOLINT if (IsSmi()) { Smi::cast(this)->SmiPrint(os); } else { HeapObject::cast(this)->HeapObjectPrint(os); } } void HeapObject::PrintHeader(std::ostream& os, const char* id) { // NOLINT os << "" << reinterpret_cast(this) << ": [" << id << "]\n"; } void HeapObject::HeapObjectPrint(std::ostream& os) { // NOLINT InstanceType instance_type = map()->instance_type(); HandleScope scope(GetIsolate()); if (instance_type < FIRST_NONSTRING_TYPE) { String::cast(this)->StringPrint(os); return; } switch (instance_type) { case SYMBOL_TYPE: Symbol::cast(this)->SymbolPrint(os); break; case MAP_TYPE: Map::cast(this)->MapPrint(os); break; case HEAP_NUMBER_TYPE: HeapNumber::cast(this)->HeapNumberPrint(os); break; case MUTABLE_HEAP_NUMBER_TYPE: os << "HeapNumberPrint(os); os << ">"; break; case FIXED_DOUBLE_ARRAY_TYPE: FixedDoubleArray::cast(this)->FixedDoubleArrayPrint(os); break; case CONSTANT_POOL_ARRAY_TYPE: ConstantPoolArray::cast(this)->ConstantPoolArrayPrint(os); break; case FIXED_ARRAY_TYPE: FixedArray::cast(this)->FixedArrayPrint(os); break; case BYTE_ARRAY_TYPE: ByteArray::cast(this)->ByteArrayPrint(os); break; case FREE_SPACE_TYPE: FreeSpace::cast(this)->FreeSpacePrint(os); break; #define PRINT_EXTERNAL_ARRAY(Type, type, TYPE, ctype, size) \ case EXTERNAL_##TYPE##_ARRAY_TYPE: \ External##Type##Array::cast(this)->External##Type##ArrayPrint(os); \ break; TYPED_ARRAYS(PRINT_EXTERNAL_ARRAY) #undef PRINT_EXTERNAL_ARRAY #define PRINT_FIXED_TYPED_ARRAY(Type, type, TYPE, ctype, size) \ case Fixed##Type##Array::kInstanceType: \ Fixed##Type##Array::cast(this)->FixedTypedArrayPrint(os); \ break; TYPED_ARRAYS(PRINT_FIXED_TYPED_ARRAY) #undef PRINT_FIXED_TYPED_ARRAY case FILLER_TYPE: os << "filler"; break; case JS_OBJECT_TYPE: // fall through case JS_CONTEXT_EXTENSION_OBJECT_TYPE: case JS_ARRAY_TYPE: case JS_GENERATOR_OBJECT_TYPE: case JS_REGEXP_TYPE: JSObject::cast(this)->JSObjectPrint(os); break; case ODDBALL_TYPE: Oddball::cast(this)->to_string()->Print(os); break; case JS_MODULE_TYPE: JSModule::cast(this)->JSModulePrint(os); break; case JS_FUNCTION_TYPE: JSFunction::cast(this)->JSFunctionPrint(os); break; case JS_GLOBAL_PROXY_TYPE: JSGlobalProxy::cast(this)->JSGlobalProxyPrint(os); break; case JS_GLOBAL_OBJECT_TYPE: JSGlobalObject::cast(this)->JSGlobalObjectPrint(os); break; case JS_BUILTINS_OBJECT_TYPE: JSBuiltinsObject::cast(this)->JSBuiltinsObjectPrint(os); break; case JS_VALUE_TYPE: os << "Value wrapper around:"; JSValue::cast(this)->value()->Print(os); break; case JS_DATE_TYPE: JSDate::cast(this)->JSDatePrint(os); break; case CODE_TYPE: Code::cast(this)->CodePrint(os); break; case JS_PROXY_TYPE: JSProxy::cast(this)->JSProxyPrint(os); break; case JS_FUNCTION_PROXY_TYPE: JSFunctionProxy::cast(this)->JSFunctionProxyPrint(os); break; case JS_SET_TYPE: JSSet::cast(this)->JSSetPrint(os); break; case JS_MAP_TYPE: JSMap::cast(this)->JSMapPrint(os); break; case JS_SET_ITERATOR_TYPE: JSSetIterator::cast(this)->JSSetIteratorPrint(os); break; case JS_MAP_ITERATOR_TYPE: JSMapIterator::cast(this)->JSMapIteratorPrint(os); break; case JS_WEAK_MAP_TYPE: JSWeakMap::cast(this)->JSWeakMapPrint(os); break; case JS_WEAK_SET_TYPE: JSWeakSet::cast(this)->JSWeakSetPrint(os); break; case FOREIGN_TYPE: Foreign::cast(this)->ForeignPrint(os); break; case SHARED_FUNCTION_INFO_TYPE: SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(os); break; case JS_MESSAGE_OBJECT_TYPE: JSMessageObject::cast(this)->JSMessageObjectPrint(os); break; case CELL_TYPE: Cell::cast(this)->CellPrint(os); break; case PROPERTY_CELL_TYPE: PropertyCell::cast(this)->PropertyCellPrint(os); break; case WEAK_CELL_TYPE: WeakCell::cast(this)->WeakCellPrint(os); break; case JS_ARRAY_BUFFER_TYPE: JSArrayBuffer::cast(this)->JSArrayBufferPrint(os); break; case JS_TYPED_ARRAY_TYPE: JSTypedArray::cast(this)->JSTypedArrayPrint(os); break; case JS_DATA_VIEW_TYPE: JSDataView::cast(this)->JSDataViewPrint(os); break; #define MAKE_STRUCT_CASE(NAME, Name, name) \ case NAME##_TYPE: \ Name::cast(this)->Name##Print(os); \ break; STRUCT_LIST(MAKE_STRUCT_CASE) #undef MAKE_STRUCT_CASE default: os << "UNKNOWN TYPE " << map()->instance_type(); UNREACHABLE(); break; } } void ByteArray::ByteArrayPrint(std::ostream& os) { // NOLINT os << "byte array, data starts at " << GetDataStartAddress(); } void FreeSpace::FreeSpacePrint(std::ostream& os) { // NOLINT os << "free space, size " << Size(); } #define EXTERNAL_ARRAY_PRINTER(Type, type, TYPE, ctype, size) \ void External##Type##Array::External##Type##ArrayPrint(std::ostream& os) { \ os << "external " #type " array"; \ } TYPED_ARRAYS(EXTERNAL_ARRAY_PRINTER) #undef EXTERNAL_ARRAY_PRINTER template void FixedTypedArray::FixedTypedArrayPrint( std::ostream& os) { // NOLINT os << "fixed " << Traits::Designator(); } void JSObject::PrintProperties(std::ostream& os) { // NOLINT if (HasFastProperties()) { DescriptorArray* descs = map()->instance_descriptors(); for (int i = 0; i < map()->NumberOfOwnDescriptors(); i++) { os << " "; descs->GetKey(i)->NamePrint(os); os << ": "; switch (descs->GetType(i)) { case DATA: { FieldIndex index = FieldIndex::ForDescriptor(map(), i); if (IsUnboxedDoubleField(index)) { os << " " << RawFastDoublePropertyAt(index); } else { os << Brief(RawFastPropertyAt(index)); } os << " (data field at offset " << index.property_index() << ")\n"; break; } case ACCESSOR: { FieldIndex index = FieldIndex::ForDescriptor(map(), i); os << " (accessor field at offset " << index.property_index() << ")\n"; break; } case DATA_CONSTANT: os << Brief(descs->GetConstant(i)) << " (data constant)\n"; break; case ACCESSOR_CONSTANT: os << Brief(descs->GetCallbacksObject(i)) << " (accessor constant)\n"; break; } } } else { property_dictionary()->Print(os); } } template static void DoPrintElements(std::ostream& os, Object* object) { // NOLINT T* p = T::cast(object); for (int i = 0; i < p->length(); i++) { os << " " << i << ": " << p->get_scalar(i) << "\n"; } } void JSObject::PrintElements(std::ostream& os) { // NOLINT // Don't call GetElementsKind, its validation code can cause the printer to // fail when debugging. switch (map()->elements_kind()) { case FAST_HOLEY_SMI_ELEMENTS: case FAST_SMI_ELEMENTS: case FAST_HOLEY_ELEMENTS: case FAST_ELEMENTS: { // Print in array notation for non-sparse arrays. FixedArray* p = FixedArray::cast(elements()); for (int i = 0; i < p->length(); i++) { os << " " << i << ": " << Brief(p->get(i)) << "\n"; } break; } case FAST_HOLEY_DOUBLE_ELEMENTS: case FAST_DOUBLE_ELEMENTS: { // Print in array notation for non-sparse arrays. if (elements()->length() > 0) { FixedDoubleArray* p = FixedDoubleArray::cast(elements()); for (int i = 0; i < p->length(); i++) { os << " " << i << ": "; if (p->is_the_hole(i)) { os << ""; } else { os << p->get_scalar(i); } os << "\n"; } } break; } #define PRINT_ELEMENTS(Kind, Type) \ case Kind: { \ DoPrintElements(os, elements()); \ break; \ } PRINT_ELEMENTS(EXTERNAL_UINT8_CLAMPED_ELEMENTS, ExternalUint8ClampedArray) PRINT_ELEMENTS(EXTERNAL_INT8_ELEMENTS, ExternalInt8Array) PRINT_ELEMENTS(EXTERNAL_UINT8_ELEMENTS, ExternalUint8Array) PRINT_ELEMENTS(EXTERNAL_INT16_ELEMENTS, ExternalInt16Array) PRINT_ELEMENTS(EXTERNAL_UINT16_ELEMENTS, ExternalUint16Array) PRINT_ELEMENTS(EXTERNAL_INT32_ELEMENTS, ExternalInt32Array) PRINT_ELEMENTS(EXTERNAL_UINT32_ELEMENTS, ExternalUint32Array) PRINT_ELEMENTS(EXTERNAL_FLOAT32_ELEMENTS, ExternalFloat32Array) PRINT_ELEMENTS(EXTERNAL_FLOAT64_ELEMENTS, ExternalFloat64Array) PRINT_ELEMENTS(UINT8_ELEMENTS, FixedUint8Array) PRINT_ELEMENTS(UINT8_CLAMPED_ELEMENTS, FixedUint8ClampedArray) PRINT_ELEMENTS(INT8_ELEMENTS, FixedInt8Array) PRINT_ELEMENTS(UINT16_ELEMENTS, FixedUint16Array) PRINT_ELEMENTS(INT16_ELEMENTS, FixedInt16Array) PRINT_ELEMENTS(UINT32_ELEMENTS, FixedUint32Array) PRINT_ELEMENTS(INT32_ELEMENTS, FixedInt32Array) PRINT_ELEMENTS(FLOAT32_ELEMENTS, FixedFloat32Array) PRINT_ELEMENTS(FLOAT64_ELEMENTS, FixedFloat64Array) #undef PRINT_ELEMENTS case DICTIONARY_ELEMENTS: elements()->Print(os); break; case SLOPPY_ARGUMENTS_ELEMENTS: { FixedArray* p = FixedArray::cast(elements()); os << " parameter map:"; for (int i = 2; i < p->length(); i++) { os << " " << (i - 2) << ":" << Brief(p->get(i)); } os << "\n context: " << Brief(p->get(0)) << "\n arguments: " << Brief(p->get(1)) << "\n"; break; } } } void JSObject::JSObjectPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSObject"); // Don't call GetElementsKind, its validation code can cause the printer to // fail when debugging. PrototypeIterator iter(GetIsolate(), this); os << " - map = " << reinterpret_cast(map()) << " [" << ElementsKindToString(this->map()->elements_kind()) << "]\n - prototype = " << reinterpret_cast(iter.GetCurrent()) << "\n {\n"; PrintProperties(os); PrintTransitions(os); PrintElements(os); os << " }\n"; } void JSModule::JSModulePrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSModule"); os << " - map = " << reinterpret_cast(map()) << "\n" << " - context = "; context()->Print(os); os << " - scope_info = " << Brief(scope_info()) << ElementsKindToString(this->map()->elements_kind()) << " {\n"; PrintProperties(os); PrintElements(os); os << " }\n"; } static const char* TypeToString(InstanceType type) { switch (type) { #define TYPE_TO_STRING(TYPE) case TYPE: return #TYPE; INSTANCE_TYPE_LIST(TYPE_TO_STRING) #undef TYPE_TO_STRING } UNREACHABLE(); return "UNKNOWN"; // Keep the compiler happy. } void Symbol::SymbolPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "Symbol"); os << " - hash: " << Hash(); os << "\n - name: " << Brief(name()); if (name()->IsUndefined()) { os << " (" << PrivateSymbolToName() << ")"; } os << "\n - private: " << is_private(); os << "\n - own: " << is_own(); os << "\n"; } void Map::MapPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "Map"); os << " - type: " << TypeToString(instance_type()) << "\n"; os << " - instance size: " << instance_size() << "\n"; os << " - inobject properties: " << inobject_properties() << "\n"; os << " - elements kind: " << ElementsKindToString(elements_kind()); os << "\n - pre-allocated property fields: " << pre_allocated_property_fields() << "\n"; os << " - unused property fields: " << unused_property_fields() << "\n"; if (is_deprecated()) os << " - deprecated_map\n"; if (is_dictionary_map()) os << " - dictionary_map\n"; if (is_prototype_map()) { os << " - prototype_map\n"; os << " - prototype info: " << Brief(prototype_info()); } else { os << " - back pointer: " << Brief(GetBackPointer()); } if (is_hidden_prototype()) os << " - hidden_prototype\n"; if (has_named_interceptor()) os << " - named_interceptor\n"; if (has_indexed_interceptor()) os << " - indexed_interceptor\n"; if (is_undetectable()) os << " - undetectable\n"; if (has_instance_call_handler()) os << " - instance_call_handler\n"; if (is_access_check_needed()) os << " - access_check_needed\n"; if (!is_extensible()) os << " - non-extensible\n"; if (is_observed()) os << " - observed\n"; os << "\n - instance descriptors " << (owns_descriptors() ? "(own) " : "") << "#" << NumberOfOwnDescriptors() << ": " << Brief(instance_descriptors()); if (FLAG_unbox_double_fields) { os << "\n - layout descriptor: " << Brief(layout_descriptor()); } if (TransitionArray::NumberOfTransitions(raw_transitions()) > 0) { os << "\n - transitions: "; TransitionArray::PrintTransitions(os, raw_transitions()); } os << "\n - prototype: " << Brief(prototype()); os << "\n - constructor: " << Brief(GetConstructor()); os << "\n - code cache: " << Brief(code_cache()); os << "\n - dependent code: " << Brief(dependent_code()); os << "\n"; } void CodeCache::CodeCachePrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "CodeCache"); os << "\n - default_cache: " << Brief(default_cache()); os << "\n - normal_type_cache: " << Brief(normal_type_cache()); } void PolymorphicCodeCache::PolymorphicCodeCachePrint( std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "PolymorphicCodeCache"); os << "\n - cache: " << Brief(cache()); } void TypeFeedbackInfo::TypeFeedbackInfoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "TypeFeedbackInfo"); os << " - ic_total_count: " << ic_total_count() << ", ic_with_type_info_count: " << ic_with_type_info_count() << ", ic_generic_count: " << ic_generic_count() << "\n"; } void AliasedArgumentsEntry::AliasedArgumentsEntryPrint( std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "AliasedArgumentsEntry"); os << "\n - aliased_context_slot: " << aliased_context_slot(); } void FixedArray::FixedArrayPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "FixedArray"); os << " - length: " << length(); for (int i = 0; i < length(); i++) { os << "\n [" << i << "]: " << Brief(get(i)); } os << "\n"; } void FixedDoubleArray::FixedDoubleArrayPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "FixedDoubleArray"); os << " - length: " << length(); for (int i = 0; i < length(); i++) { os << "\n [" << i << "]: "; if (is_the_hole(i)) { os << ""; } else { os << get_scalar(i); } } os << "\n"; } void ConstantPoolArray::ConstantPoolArrayPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "ConstantPoolArray"); os << " - length: " << length(); for (int i = 0; i <= last_index(INT32, SMALL_SECTION); i++) { if (i < last_index(INT64, SMALL_SECTION)) { os << "\n [" << i << "]: double: " << get_int64_entry_as_double(i); } else if (i <= last_index(CODE_PTR, SMALL_SECTION)) { os << "\n [" << i << "]: code target pointer: " << reinterpret_cast(get_code_ptr_entry(i)); } else if (i <= last_index(HEAP_PTR, SMALL_SECTION)) { os << "\n [" << i << "]: heap pointer: " << reinterpret_cast(get_heap_ptr_entry(i)); } else if (i <= last_index(INT32, SMALL_SECTION)) { os << "\n [" << i << "]: int32: " << get_int32_entry(i); } } if (is_extended_layout()) { os << "\n Extended section:"; for (int i = first_extended_section_index(); i <= last_index(INT32, EXTENDED_SECTION); i++) { if (i < last_index(INT64, EXTENDED_SECTION)) { os << "\n [" << i << "]: double: " << get_int64_entry_as_double(i); } else if (i <= last_index(CODE_PTR, EXTENDED_SECTION)) { os << "\n [" << i << "]: code target pointer: " << reinterpret_cast(get_code_ptr_entry(i)); } else if (i <= last_index(HEAP_PTR, EXTENDED_SECTION)) { os << "\n [" << i << "]: heap pointer: " << reinterpret_cast(get_heap_ptr_entry(i)); } else if (i <= last_index(INT32, EXTENDED_SECTION)) { os << "\n [" << i << "]: int32: " << get_int32_entry(i); } } } os << "\n"; } void JSValue::JSValuePrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "ValueObject"); value()->Print(os); } void JSMessageObject::JSMessageObjectPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSMessageObject"); os << " - type: " << Brief(type()); os << "\n - arguments: " << Brief(arguments()); os << "\n - start_position: " << start_position(); os << "\n - end_position: " << end_position(); os << "\n - script: " << Brief(script()); os << "\n - stack_frames: " << Brief(stack_frames()); os << "\n"; } void String::StringPrint(std::ostream& os) { // NOLINT if (StringShape(this).IsInternalized()) { os << "#"; } else if (StringShape(this).IsCons()) { os << "c\""; } else { os << "\""; } const char truncated_epilogue[] = "..."; int len = length(); if (!FLAG_use_verbose_printer) { if (len > 100) { len = 100 - sizeof(truncated_epilogue); } } for (int i = 0; i < len; i++) { os << AsUC16(Get(i)); } if (len != length()) { os << truncated_epilogue; } if (!StringShape(this).IsInternalized()) os << "\""; } void Name::NamePrint(std::ostream& os) { // NOLINT if (IsString()) { String::cast(this)->StringPrint(os); } else if (IsSymbol()) { Symbol::cast(this)->name()->Print(os); } else { os << Brief(this); } } static const char* const weekdays[] = { "???", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; void JSDate::JSDatePrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSDate"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - value = "; value()->Print(os); if (!year()->IsSmi()) { os << " - time = NaN\n"; } else { // TODO(svenpanne) Add some basic formatting to our streams. Vector buf = Vector::New(100); SNPrintF( buf, " - time = %s %04d/%02d/%02d %02d:%02d:%02d\n", weekdays[weekday()->IsSmi() ? Smi::cast(weekday())->value() + 1 : 0], year()->IsSmi() ? Smi::cast(year())->value() : -1, month()->IsSmi() ? Smi::cast(month())->value() : -1, day()->IsSmi() ? Smi::cast(day())->value() : -1, hour()->IsSmi() ? Smi::cast(hour())->value() : -1, min()->IsSmi() ? Smi::cast(min())->value() : -1, sec()->IsSmi() ? Smi::cast(sec())->value() : -1); os << buf.start(); } } void JSProxy::JSProxyPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSProxy"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - handler = "; handler()->Print(os); os << "\n - hash = "; hash()->Print(os); os << "\n"; } void JSFunctionProxy::JSFunctionProxyPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSFunctionProxy"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - handler = "; handler()->Print(os); os << "\n - call_trap = "; call_trap()->Print(os); os << "\n - construct_trap = "; construct_trap()->Print(os); os << "\n"; } void JSSet::JSSetPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSSet"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - table = " << Brief(table()); os << "\n"; } void JSMap::JSMapPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSMap"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - table = " << Brief(table()); os << "\n"; } template void OrderedHashTableIterator::OrderedHashTableIteratorPrint( std::ostream& os) { // NOLINT os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - table = " << Brief(table()); os << "\n - index = " << Brief(index()); os << "\n - kind = " << Brief(kind()); os << "\n"; } template void OrderedHashTableIterator< JSSetIterator, OrderedHashSet>::OrderedHashTableIteratorPrint(std::ostream& os); // NOLINT template void OrderedHashTableIterator< JSMapIterator, OrderedHashMap>::OrderedHashTableIteratorPrint(std::ostream& os); // NOLINT void JSSetIterator::JSSetIteratorPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSSetIterator"); OrderedHashTableIteratorPrint(os); } void JSMapIterator::JSMapIteratorPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSMapIterator"); OrderedHashTableIteratorPrint(os); } void JSWeakMap::JSWeakMapPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSWeakMap"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - table = " << Brief(table()); os << "\n"; } void JSWeakSet::JSWeakSetPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSWeakSet"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - table = " << Brief(table()); os << "\n"; } void JSArrayBuffer::JSArrayBufferPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSArrayBuffer"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - backing_store = " << backing_store() << "\n"; os << " - byte_length = " << Brief(byte_length()); if (was_neutered()) os << " - neutered\n"; os << "\n"; } void JSTypedArray::JSTypedArrayPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSTypedArray"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - buffer = " << Brief(buffer()); os << "\n - byte_offset = " << Brief(byte_offset()); os << "\n - byte_length = " << Brief(byte_length()); os << "\n - length = " << Brief(length()); if (WasNeutered()) os << " - neutered\n"; os << "\n"; if (!WasNeutered()) PrintElements(os); } void JSDataView::JSDataViewPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "JSDataView"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - buffer =" << Brief(buffer()); os << "\n - byte_offset = " << Brief(byte_offset()); os << "\n - byte_length = " << Brief(byte_length()); if (WasNeutered()) os << " - neutered\n"; os << "\n"; } void JSFunction::JSFunctionPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "Function"); os << " - map = " << reinterpret_cast(map()) << "\n"; os << " - initial_map = "; if (has_initial_map()) os << Brief(initial_map()); os << "\n - shared_info = " << Brief(shared()); os << "\n - name = " << Brief(shared()->name()); os << "\n - context = " << Brief(context()); if (shared()->bound()) { os << "\n - bindings = " << Brief(function_bindings()); } else { os << "\n - literals = " << Brief(literals()); } os << "\n - code = " << Brief(code()); os << "\n"; PrintProperties(os); PrintElements(os); os << "\n"; } void SharedFunctionInfo::SharedFunctionInfoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "SharedFunctionInfo"); os << " - name: " << Brief(name()); os << "\n - expected_nof_properties: " << expected_nof_properties(); os << "\n - ast_node_count: " << ast_node_count(); os << "\n - instance class name = "; instance_class_name()->Print(os); os << "\n - code = " << Brief(code()); if (HasSourceCode()) { os << "\n - source code = "; String* source = String::cast(Script::cast(script())->source()); int start = start_position(); int length = end_position() - start; SmartArrayPointer source_string = source->ToCString(DISALLOW_NULLS, FAST_STRING_TRAVERSAL, start, length, NULL); os << source_string.get(); } // Script files are often large, hard to read. // os << "\n - script ="; // script()->Print(os); os << "\n - function token position = " << function_token_position(); os << "\n - start position = " << start_position(); os << "\n - end position = " << end_position(); os << "\n - is expression = " << is_expression(); os << "\n - debug info = " << Brief(debug_info()); os << "\n - length = " << length(); os << "\n - optimized_code_map = " << Brief(optimized_code_map()); os << "\n - feedback_vector = "; feedback_vector()->FixedArrayPrint(os); os << "\n"; } void JSGlobalProxy::JSGlobalProxyPrint(std::ostream& os) { // NOLINT os << "global_proxy "; JSObjectPrint(os); os << "native context : " << Brief(native_context()); os << "\n"; } void JSGlobalObject::JSGlobalObjectPrint(std::ostream& os) { // NOLINT os << "global "; JSObjectPrint(os); os << "native context : " << Brief(native_context()); os << "\n"; } void JSBuiltinsObject::JSBuiltinsObjectPrint(std::ostream& os) { // NOLINT os << "builtins "; JSObjectPrint(os); } void Cell::CellPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "Cell"); } void PropertyCell::PropertyCellPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "PropertyCell"); } void WeakCell::WeakCellPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "WeakCell"); if (cleared()) { os << "\n - cleared"; } else { os << "\n - value: " << Brief(value()); } } void Code::CodePrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "Code"); #ifdef ENABLE_DISASSEMBLER if (FLAG_use_verbose_printer) { Disassemble(NULL, os); } #endif } void Foreign::ForeignPrint(std::ostream& os) { // NOLINT os << "foreign address : " << foreign_address(); } void ExecutableAccessorInfo::ExecutableAccessorInfoPrint( std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "ExecutableAccessorInfo"); os << "\n - name: " << Brief(name()); os << "\n - flag: " << Brief(flag()); os << "\n - getter: " << Brief(getter()); os << "\n - setter: " << Brief(setter()); os << "\n - data: " << Brief(data()); os << "\n"; } void Box::BoxPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "Box"); os << "\n - value: " << Brief(value()); os << "\n"; } void PrototypeInfo::PrototypeInfoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "PrototypeInfo"); os << "\n - prototype users: " << Brief(prototype_users()); os << "\n - validity cell: " << Brief(validity_cell()); os << "\n - constructor name: " << Brief(constructor_name()); os << "\n"; } void AccessorPair::AccessorPairPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "AccessorPair"); os << "\n - getter: " << Brief(getter()); os << "\n - setter: " << Brief(setter()); os << "\n"; } void AccessCheckInfo::AccessCheckInfoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "AccessCheckInfo"); os << "\n - named_callback: " << Brief(named_callback()); os << "\n - indexed_callback: " << Brief(indexed_callback()); os << "\n - data: " << Brief(data()); os << "\n"; } void InterceptorInfo::InterceptorInfoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "InterceptorInfo"); os << "\n - getter: " << Brief(getter()); os << "\n - setter: " << Brief(setter()); os << "\n - query: " << Brief(query()); os << "\n - deleter: " << Brief(deleter()); os << "\n - enumerator: " << Brief(enumerator()); os << "\n - data: " << Brief(data()); os << "\n"; } void CallHandlerInfo::CallHandlerInfoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "CallHandlerInfo"); os << "\n - callback: " << Brief(callback()); os << "\n - data: " << Brief(data()); os << "\n"; } void FunctionTemplateInfo::FunctionTemplateInfoPrint( std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "FunctionTemplateInfo"); os << "\n - class name: " << Brief(class_name()); os << "\n - tag: " << Brief(tag()); os << "\n - property_list: " << Brief(property_list()); os << "\n - serial_number: " << Brief(serial_number()); os << "\n - call_code: " << Brief(call_code()); os << "\n - property_accessors: " << Brief(property_accessors()); os << "\n - prototype_template: " << Brief(prototype_template()); os << "\n - parent_template: " << Brief(parent_template()); os << "\n - named_property_handler: " << Brief(named_property_handler()); os << "\n - indexed_property_handler: " << Brief(indexed_property_handler()); os << "\n - instance_template: " << Brief(instance_template()); os << "\n - signature: " << Brief(signature()); os << "\n - access_check_info: " << Brief(access_check_info()); os << "\n - hidden_prototype: " << (hidden_prototype() ? "true" : "false"); os << "\n - undetectable: " << (undetectable() ? "true" : "false"); os << "\n - need_access_check: " << (needs_access_check() ? "true" : "false"); os << "\n - instantiated: " << (instantiated() ? "true" : "false"); os << "\n"; } void ObjectTemplateInfo::ObjectTemplateInfoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "ObjectTemplateInfo"); os << " - tag: " << Brief(tag()); os << "\n - property_list: " << Brief(property_list()); os << "\n - property_accessors: " << Brief(property_accessors()); os << "\n - constructor: " << Brief(constructor()); os << "\n - internal_field_count: " << Brief(internal_field_count()); os << "\n"; } void TypeSwitchInfo::TypeSwitchInfoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "TypeSwitchInfo"); os << "\n - types: " << Brief(types()); os << "\n"; } void AllocationSite::AllocationSitePrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "AllocationSite"); os << " - weak_next: " << Brief(weak_next()); os << "\n - dependent code: " << Brief(dependent_code()); os << "\n - nested site: " << Brief(nested_site()); os << "\n - memento found count: " << Brief(Smi::FromInt(memento_found_count())); os << "\n - memento create count: " << Brief(Smi::FromInt(memento_create_count())); os << "\n - pretenure decision: " << Brief(Smi::FromInt(pretenure_decision())); os << "\n - transition_info: "; if (transition_info()->IsSmi()) { ElementsKind kind = GetElementsKind(); os << "Array allocation with ElementsKind " << ElementsKindToString(kind); } else if (transition_info()->IsJSArray()) { os << "Array literal " << Brief(transition_info()); } else { os << "unknown transition_info" << Brief(transition_info()); } os << "\n"; } void AllocationMemento::AllocationMementoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "AllocationMemento"); os << " - allocation site: "; if (IsValid()) { GetAllocationSite()->Print(os); } else { os << "\n"; } } void Script::ScriptPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "Script"); os << "\n - source: " << Brief(source()); os << "\n - name: " << Brief(name()); os << "\n - line_offset: " << Brief(line_offset()); os << "\n - column_offset: " << Brief(column_offset()); os << "\n - type: " << Brief(type()); os << "\n - id: " << Brief(id()); os << "\n - context data: " << Brief(context_data()); os << "\n - wrapper: " << Brief(wrapper()); os << "\n - compilation type: " << compilation_type(); os << "\n - line ends: " << Brief(line_ends()); os << "\n - eval from shared: " << Brief(eval_from_shared()); os << "\n - eval from instructions offset: " << Brief(eval_from_instructions_offset()); os << "\n"; } void DebugInfo::DebugInfoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "DebugInfo"); os << "\n - shared: " << Brief(shared()); os << "\n - original_code: " << Brief(original_code()); os << "\n - code: " << Brief(code()); os << "\n - break_points: "; break_points()->Print(os); } void BreakPointInfo::BreakPointInfoPrint(std::ostream& os) { // NOLINT HeapObject::PrintHeader(os, "BreakPointInfo"); os << "\n - code_position: " << code_position()->value(); os << "\n - source_position: " << source_position()->value(); os << "\n - statement_position: " << statement_position()->value(); os << "\n - break_point_objects: " << Brief(break_point_objects()); os << "\n"; } static void PrintBitMask(std::ostream& os, uint32_t value) { // NOLINT for (int i = 0; i < 32; i++) { if ((i & 7) == 0) os << " "; os << (((value & 1) == 0) ? "_" : "x"); value >>= 1; } } void LayoutDescriptor::Print() { OFStream os(stdout); this->Print(os); os << std::flush; } void LayoutDescriptor::Print(std::ostream& os) { // NOLINT os << "Layout descriptor: "; if (IsUninitialized()) { os << ""; } else if (IsFastPointerLayout()) { os << ""; } else if (IsSmi()) { os << "fast"; PrintBitMask(os, static_cast(Smi::cast(this)->value())); } else { os << "slow"; int len = length(); for (int i = 0; i < len; i++) { if (i > 0) os << " |"; PrintBitMask(os, get_scalar(i)); } } os << "\n"; } #endif // OBJECT_PRINT #if TRACE_MAPS void Name::NameShortPrint() { if (this->IsString()) { PrintF("%s", String::cast(this)->ToCString().get()); } else { DCHECK(this->IsSymbol()); Symbol* s = Symbol::cast(this); if (s->name()->IsUndefined()) { PrintF("#<%s>", s->PrivateSymbolToName()); } else { PrintF("<%s>", String::cast(s->name())->ToCString().get()); } } } int Name::NameShortPrint(Vector str) { if (this->IsString()) { return SNPrintF(str, "%s", String::cast(this)->ToCString().get()); } else { DCHECK(this->IsSymbol()); Symbol* s = Symbol::cast(this); if (s->name()->IsUndefined()) { return SNPrintF(str, "#<%s>", s->PrivateSymbolToName()); } else { return SNPrintF(str, "<%s>", String::cast(s->name())->ToCString().get()); } } } #endif // TRACE_MAPS #if defined(DEBUG) || defined(OBJECT_PRINT) // This method is only meant to be called from gdb for debugging purposes. // Since the string can also be in two-byte encoding, non-Latin1 characters // will be ignored in the output. char* String::ToAsciiArray() { // Static so that subsequent calls frees previously allocated space. // This also means that previous results will be overwritten. static char* buffer = NULL; if (buffer != NULL) delete[] buffer; buffer = new char[length() + 1]; WriteToFlat(this, reinterpret_cast(buffer), 0, length()); buffer[length()] = 0; return buffer; } void DescriptorArray::Print() { OFStream os(stdout); this->PrintDescriptors(os); os << std::flush; } void DescriptorArray::PrintDescriptors(std::ostream& os) { // NOLINT HandleScope scope(GetIsolate()); os << "Descriptor array " << number_of_descriptors() << "\n"; for (int i = 0; i < number_of_descriptors(); i++) { Descriptor desc; Get(i, &desc); os << " " << i << ": " << desc << "\n"; } os << "\n"; } void TransitionArray::Print() { OFStream os(stdout); TransitionArray::PrintTransitions(os, this); os << std::flush; } void TransitionArray::PrintTransitions(std::ostream& os, Object* transitions, bool print_header) { // NOLINT int num_transitions = NumberOfTransitions(transitions); if (print_header) { os << "Transition array " << num_transitions << "\n"; } for (int i = 0; i < num_transitions; i++) { Name* key = GetKey(transitions, i); Map* target = GetTarget(transitions, i); os << " "; #ifdef OBJECT_PRINT key->NamePrint(os); #else key->ShortPrint(os); #endif os << ": "; Heap* heap = key->GetHeap(); if (key == heap->nonextensible_symbol()) { os << " (transition to non-extensible)"; } else if (key == heap->sealed_symbol()) { os << " (transition to sealed)"; } else if (key == heap->frozen_symbol()) { os << " (transition to frozen)"; } else if (key == heap->elements_transition_symbol()) { os << " (transition to " << ElementsKindToString(target->elements_kind()) << ")"; } else if (key == heap->observed_symbol()) { os << " (transition to Object.observe)"; } else { PropertyDetails details = GetTargetDetails(key, target); os << " (transition to "; if (details.location() == kDescriptor) { os << "immutable "; } os << (details.kind() == kData ? "data" : "accessor"); if (details.location() == kDescriptor) { Object* value = target->instance_descriptors()->GetValue(target->LastAdded()); os << " " << Brief(value); } os << "), attrs: " << details.attributes(); } os << " -> " << Brief(target) << "\n"; } } void JSObject::PrintTransitions(std::ostream& os) { // NOLINT TransitionArray::PrintTransitions(os, map()->raw_transitions()); } #endif // defined(DEBUG) || defined(OBJECT_PRINT) } } // namespace v8::internal