Bug Summary

File:out/../deps/v8/src/handles/handles-inl.h
Warning:line 184, column 27
Called C++ object pointer is null

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name objects-printer.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/home/maurizio/node-v18.6.0/out -resource-dir /usr/local/lib/clang/16.0.0 -D _GLIBCXX_USE_CXX11_ABI=1 -D NODE_OPENSSL_CONF_NAME=nodejs_conf -D NODE_OPENSSL_HAS_QUIC -D V8_GYP_BUILD -D V8_TYPED_ARRAY_MAX_SIZE_IN_HEAP=64 -D __STDC_FORMAT_MACROS -D OPENSSL_NO_PINSHARED -D OPENSSL_THREADS -D V8_TARGET_ARCH_X64 -D V8_HAVE_TARGET_OS -D V8_TARGET_OS_LINUX -D V8_EMBEDDER_STRING="-node.8" -D ENABLE_DISASSEMBLER -D V8_PROMISE_INTERNAL_FIELD_COUNT=1 -D V8_SHORT_BUILTIN_CALLS -D OBJECT_PRINT -D V8_INTL_SUPPORT -D V8_ATOMIC_OBJECT_FIELD_WRITES -D V8_ENABLE_LAZY_SOURCE_POSITIONS -D V8_USE_SIPHASH -D V8_SHARED_RO_HEAP -D V8_WIN64_UNWINDING_INFO -D V8_ENABLE_REGEXP_INTERPRETER_THREADED_DISPATCH -D V8_SNAPSHOT_COMPRESSION -D V8_ENABLE_WEBASSEMBLY -D V8_ENABLE_JAVASCRIPT_PROMISE_HOOKS -D V8_ALLOCATION_FOLDING -D V8_ALLOCATION_SITE_TRACKING -D V8_SCRIPTORMODULE_LEGACY_LIFETIME -D V8_ADVANCED_BIGINT_ALGORITHMS -D ICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_STATIC -D UCONFIG_NO_SERVICE=1 -D U_ENABLE_DYLOAD=0 -D U_STATIC_IMPLEMENTATION=1 -D U_HAVE_STD_STRING=1 -D UCONFIG_NO_BREAK_ITERATION=0 -I ../deps/v8 -I ../deps/v8/include -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/inspector-generated-output-root -I ../deps/v8/third_party/inspector_protocol -I /home/maurizio/node-v18.6.0/out/Release/obj/gen -I /home/maurizio/node-v18.6.0/out/Release/obj/gen/generate-bytecode-output-root -I ../deps/icu-small/source/i18n -I ../deps/icu-small/source/common -I ../deps/v8/third_party/zlib -I ../deps/v8/third_party/zlib/google -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8 -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/x86_64-redhat-linux -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../include/c++/8/backward -internal-isystem /usr/local/lib/clang/16.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-redhat-linux/8/../../../../x86_64-redhat-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-unused-parameter -Wno-return-type -std=gnu++17 -fdeprecated-macro -fdebug-compilation-dir=/home/maurizio/node-v18.6.0/out -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2022-08-22-142216-507842-1 -x c++ ../deps/v8/src/diagnostics/objects-printer.cc

../deps/v8/src/diagnostics/objects-printer.cc

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_WEBASSEMBLY1
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
30namespace v8 {
31namespace internal {
32
33#ifdef OBJECT_PRINT1
34
35void 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
46void 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
55namespace {
56
57void 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
74template <typename T>
75void PrintDictionaryContents(std::ostream& os, T dict) {
76 DisallowGarbageCollection no_gc;
77 ReadOnlyRoots roots = dict.GetReadOnlyRoots();
78
79 if (dict.Capacity() == 0) {
1
Assuming the condition is false
2
Taking false branch
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()) {
3
Calling 'SwissNameDictionary::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
103void 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
109void 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_WEBASSEMBLY1
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)MAKE_TORQUE_CASE(Symbol, SYMBOL_TYPE) MAKE_TORQUE_CASE(HeapNumber
, HEAP_NUMBER_TYPE) MAKE_TORQUE_CASE(Oddball, ODDBALL_TYPE) MAKE_TORQUE_CASE
(PromiseFulfillReactionJobTask, PROMISE_FULFILL_REACTION_JOB_TASK_TYPE
) MAKE_TORQUE_CASE(PromiseRejectReactionJobTask, PROMISE_REJECT_REACTION_JOB_TASK_TYPE
) MAKE_TORQUE_CASE(CallableTask, CALLABLE_TASK_TYPE) MAKE_TORQUE_CASE
(CallbackTask, CALLBACK_TASK_TYPE) MAKE_TORQUE_CASE(PromiseResolveThenableJobTask
, PROMISE_RESOLVE_THENABLE_JOB_TASK_TYPE) MAKE_TORQUE_CASE(FunctionTemplateInfo
, FUNCTION_TEMPLATE_INFO_TYPE) MAKE_TORQUE_CASE(ObjectTemplateInfo
, OBJECT_TEMPLATE_INFO_TYPE) MAKE_TORQUE_CASE(AccessCheckInfo
, ACCESS_CHECK_INFO_TYPE) MAKE_TORQUE_CASE(AccessorInfo, ACCESSOR_INFO_TYPE
) MAKE_TORQUE_CASE(AccessorPair, ACCESSOR_PAIR_TYPE) MAKE_TORQUE_CASE
(AliasedArgumentsEntry, ALIASED_ARGUMENTS_ENTRY_TYPE) MAKE_TORQUE_CASE
(AllocationMemento, ALLOCATION_MEMENTO_TYPE) MAKE_TORQUE_CASE
(ArrayBoilerplateDescription, ARRAY_BOILERPLATE_DESCRIPTION_TYPE
) MAKE_TORQUE_CASE(AsmWasmData, ASM_WASM_DATA_TYPE) MAKE_TORQUE_CASE
(AsyncGeneratorRequest, ASYNC_GENERATOR_REQUEST_TYPE) MAKE_TORQUE_CASE
(BreakPoint, BREAK_POINT_TYPE) MAKE_TORQUE_CASE(BreakPointInfo
, BREAK_POINT_INFO_TYPE) MAKE_TORQUE_CASE(CachedTemplateObject
, CACHED_TEMPLATE_OBJECT_TYPE) MAKE_TORQUE_CASE(CallHandlerInfo
, CALL_HANDLER_INFO_TYPE) MAKE_TORQUE_CASE(CallSiteInfo, CALL_SITE_INFO_TYPE
) MAKE_TORQUE_CASE(ClassPositions, CLASS_POSITIONS_TYPE) MAKE_TORQUE_CASE
(DebugInfo, DEBUG_INFO_TYPE) MAKE_TORQUE_CASE(EnumCache, ENUM_CACHE_TYPE
) MAKE_TORQUE_CASE(ErrorStackData, ERROR_STACK_DATA_TYPE) MAKE_TORQUE_CASE
(FeedbackCell, FEEDBACK_CELL_TYPE) MAKE_TORQUE_CASE(FunctionTemplateRareData
, FUNCTION_TEMPLATE_RARE_DATA_TYPE) MAKE_TORQUE_CASE(InterceptorInfo
, INTERCEPTOR_INFO_TYPE) MAKE_TORQUE_CASE(InterpreterData, INTERPRETER_DATA_TYPE
) MAKE_TORQUE_CASE(ModuleRequest, MODULE_REQUEST_TYPE) MAKE_TORQUE_CASE
(PromiseCapability, PROMISE_CAPABILITY_TYPE) MAKE_TORQUE_CASE
(PromiseOnStack, PROMISE_ON_STACK_TYPE) MAKE_TORQUE_CASE(PromiseReaction
, PROMISE_REACTION_TYPE) MAKE_TORQUE_CASE(PropertyDescriptorObject
, PROPERTY_DESCRIPTOR_OBJECT_TYPE) MAKE_TORQUE_CASE(PrototypeInfo
, PROTOTYPE_INFO_TYPE) MAKE_TORQUE_CASE(RegExpBoilerplateDescription
, REG_EXP_BOILERPLATE_DESCRIPTION_TYPE) MAKE_TORQUE_CASE(Script
, SCRIPT_TYPE) MAKE_TORQUE_CASE(ScriptOrModule, SCRIPT_OR_MODULE_TYPE
) MAKE_TORQUE_CASE(SourceTextModuleInfoEntry, SOURCE_TEXT_MODULE_INFO_ENTRY_TYPE
) MAKE_TORQUE_CASE(StackFrameInfo, STACK_FRAME_INFO_TYPE) MAKE_TORQUE_CASE
(TemplateObjectDescription, TEMPLATE_OBJECT_DESCRIPTION_TYPE)
MAKE_TORQUE_CASE(Tuple2, TUPLE2_TYPE) MAKE_TORQUE_CASE(WasmContinuationObject
, WASM_CONTINUATION_OBJECT_TYPE) MAKE_TORQUE_CASE(WasmExceptionTag
, WASM_EXCEPTION_TAG_TYPE) MAKE_TORQUE_CASE(WasmIndirectFunctionTable
, WASM_INDIRECT_FUNCTION_TABLE_TYPE) MAKE_TORQUE_CASE(ByteArray
, BYTE_ARRAY_TYPE) MAKE_TORQUE_CASE(BytecodeArray, BYTECODE_ARRAY_TYPE
) MAKE_TORQUE_CASE(FixedDoubleArray, FIXED_DOUBLE_ARRAY_TYPE)
MAKE_TORQUE_CASE(InternalClassWithSmiElements, INTERNAL_CLASS_WITH_SMI_ELEMENTS_TYPE
) MAKE_TORQUE_CASE(SloppyArgumentsElements, SLOPPY_ARGUMENTS_ELEMENTS_TYPE
) MAKE_TORQUE_CASE(TurbofanBitsetType, TURBOFAN_BITSET_TYPE_TYPE
) MAKE_TORQUE_CASE(TurbofanHeapConstantType, TURBOFAN_HEAP_CONSTANT_TYPE_TYPE
) MAKE_TORQUE_CASE(TurbofanOtherNumberConstantType, TURBOFAN_OTHER_NUMBER_CONSTANT_TYPE_TYPE
) MAKE_TORQUE_CASE(TurbofanRangeType, TURBOFAN_RANGE_TYPE_TYPE
) MAKE_TORQUE_CASE(TurbofanUnionType, TURBOFAN_UNION_TYPE_TYPE
) MAKE_TORQUE_CASE(WasmInternalFunction, WASM_INTERNAL_FUNCTION_TYPE
) MAKE_TORQUE_CASE(WasmTypeInfo, WASM_TYPE_INFO_TYPE) MAKE_TORQUE_CASE
(UncompiledDataWithPreparseDataAndJob, UNCOMPILED_DATA_WITH_PREPARSE_DATA_AND_JOB_TYPE
) MAKE_TORQUE_CASE(UncompiledDataWithoutPreparseDataWithJob, UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_WITH_JOB_TYPE
) MAKE_TORQUE_CASE(WasmCapiFunctionData, WASM_CAPI_FUNCTION_DATA_TYPE
) MAKE_TORQUE_CASE(WasmExportedFunctionData, WASM_EXPORTED_FUNCTION_DATA_TYPE
) MAKE_TORQUE_CASE(WasmJSFunctionData, WASM_JS_FUNCTION_DATA_TYPE
) MAKE_TORQUE_CASE(ExportedSubClass, EXPORTED_SUB_CLASS_TYPE)
MAKE_TORQUE_CASE(ExportedSubClass2, EXPORTED_SUB_CLASS2_TYPE
) MAKE_TORQUE_CASE(SmallOrderedHashMap, SMALL_ORDERED_HASH_MAP_TYPE
) MAKE_TORQUE_CASE(SmallOrderedHashSet, SMALL_ORDERED_HASH_SET_TYPE
) MAKE_TORQUE_CASE(SmallOrderedNameDictionary, SMALL_ORDERED_NAME_DICTIONARY_TYPE
) MAKE_TORQUE_CASE(AbstractInternalClassSubclass1, ABSTRACT_INTERNAL_CLASS_SUBCLASS1_TYPE
) MAKE_TORQUE_CASE(AbstractInternalClassSubclass2, ABSTRACT_INTERNAL_CLASS_SUBCLASS2_TYPE
) MAKE_TORQUE_CASE(StrongDescriptorArray, STRONG_DESCRIPTOR_ARRAY_TYPE
) MAKE_TORQUE_CASE(SourceTextModule, SOURCE_TEXT_MODULE_TYPE)
MAKE_TORQUE_CASE(SyntheticModule, SYNTHETIC_MODULE_TYPE) MAKE_TORQUE_CASE
(Cell, CELL_TYPE) MAKE_TORQUE_CASE(CoverageInfo, COVERAGE_INFO_TYPE
) MAKE_TORQUE_CASE(EmbedderDataArray, EMBEDDER_DATA_ARRAY_TYPE
) MAKE_TORQUE_CASE(FeedbackVector, FEEDBACK_VECTOR_TYPE) MAKE_TORQUE_CASE
(FreeSpace, FREE_SPACE_TYPE) MAKE_TORQUE_CASE(InternalClass, INTERNAL_CLASS_TYPE
) MAKE_TORQUE_CASE(InternalClassWithStructElements, INTERNAL_CLASS_WITH_STRUCT_ELEMENTS_TYPE
) MAKE_TORQUE_CASE(Map, MAP_TYPE) MAKE_TORQUE_CASE(MegaDomHandler
, MEGA_DOM_HANDLER_TYPE) MAKE_TORQUE_CASE(OnHeapBasicBlockProfilerData
, ON_HEAP_BASIC_BLOCK_PROFILER_DATA_TYPE) MAKE_TORQUE_CASE(PreparseData
, PREPARSE_DATA_TYPE) MAKE_TORQUE_CASE(PropertyArray, PROPERTY_ARRAY_TYPE
) MAKE_TORQUE_CASE(PropertyCell, PROPERTY_CELL_TYPE) MAKE_TORQUE_CASE
(ScopeInfo, SCOPE_INFO_TYPE) MAKE_TORQUE_CASE(SharedFunctionInfo
, SHARED_FUNCTION_INFO_TYPE) MAKE_TORQUE_CASE(SmiBox, SMI_BOX_TYPE
) MAKE_TORQUE_CASE(SmiPair, SMI_PAIR_TYPE) MAKE_TORQUE_CASE(SortState
, SORT_STATE_TYPE) MAKE_TORQUE_CASE(SwissNameDictionary, SWISS_NAME_DICTIONARY_TYPE
) MAKE_TORQUE_CASE(WasmApiFunctionRef, WASM_API_FUNCTION_REF_TYPE
) MAKE_TORQUE_CASE(WasmOnFulfilledData, WASM_ON_FULFILLED_DATA_TYPE
) MAKE_TORQUE_CASE(WeakArrayList, WEAK_ARRAY_LIST_TYPE) MAKE_TORQUE_CASE
(WeakCell, WEAK_CELL_TYPE) MAKE_TORQUE_CASE(WasmArray, WASM_ARRAY_TYPE
) MAKE_TORQUE_CASE(WasmStruct, WASM_STRUCT_TYPE) MAKE_TORQUE_CASE
(JSProxy, JS_PROXY_TYPE) MAKE_TORQUE_CASE(JSGlobalObject, JS_GLOBAL_OBJECT_TYPE
) MAKE_TORQUE_CASE(JSGlobalProxy, JS_GLOBAL_PROXY_TYPE) MAKE_TORQUE_CASE
(JSModuleNamespace, JS_MODULE_NAMESPACE_TYPE) MAKE_TORQUE_CASE
(JSPrimitiveWrapper, JS_PRIMITIVE_WRAPPER_TYPE) MAKE_TORQUE_CASE
(JSDataView, JS_DATA_VIEW_TYPE) MAKE_TORQUE_CASE(JSTypedArray
, JS_TYPED_ARRAY_TYPE) MAKE_TORQUE_CASE(JSArrayBuffer, JS_ARRAY_BUFFER_TYPE
) MAKE_TORQUE_CASE(JSPromise, JS_PROMISE_TYPE) MAKE_TORQUE_CASE
(JSBoundFunction, JS_BOUND_FUNCTION_TYPE) MAKE_TORQUE_CASE(JSWrappedFunction
, JS_WRAPPED_FUNCTION_TYPE) MAKE_TORQUE_CASE(JSAsyncFunctionObject
, JS_ASYNC_FUNCTION_OBJECT_TYPE) MAKE_TORQUE_CASE(JSAsyncGeneratorObject
, JS_ASYNC_GENERATOR_OBJECT_TYPE) MAKE_TORQUE_CASE(JSMap, JS_MAP_TYPE
) MAKE_TORQUE_CASE(JSSet, JS_SET_TYPE) MAKE_TORQUE_CASE(JSWeakMap
, JS_WEAK_MAP_TYPE) MAKE_TORQUE_CASE(JSWeakSet, JS_WEAK_SET_TYPE
) MAKE_TORQUE_CASE(JSArgumentsObject, JS_ARGUMENTS_OBJECT_TYPE
) MAKE_TORQUE_CASE(JSArray, JS_ARRAY_TYPE) MAKE_TORQUE_CASE(JSArrayIterator
, JS_ARRAY_ITERATOR_TYPE) MAKE_TORQUE_CASE(JSAsyncFromSyncIterator
, JS_ASYNC_FROM_SYNC_ITERATOR_TYPE) MAKE_TORQUE_CASE(JSCollator
, JS_COLLATOR_TYPE) MAKE_TORQUE_CASE(JSDate, JS_DATE_TYPE) MAKE_TORQUE_CASE
(JSDateTimeFormat, JS_DATE_TIME_FORMAT_TYPE) MAKE_TORQUE_CASE
(JSDisplayNames, JS_DISPLAY_NAMES_TYPE) MAKE_TORQUE_CASE(JSExternalObject
, JS_EXTERNAL_OBJECT_TYPE) MAKE_TORQUE_CASE(JSFinalizationRegistry
, JS_FINALIZATION_REGISTRY_TYPE) MAKE_TORQUE_CASE(JSListFormat
, JS_LIST_FORMAT_TYPE) MAKE_TORQUE_CASE(JSLocale, JS_LOCALE_TYPE
) MAKE_TORQUE_CASE(JSMessageObject, JS_MESSAGE_OBJECT_TYPE) MAKE_TORQUE_CASE
(JSNumberFormat, JS_NUMBER_FORMAT_TYPE) MAKE_TORQUE_CASE(JSPluralRules
, JS_PLURAL_RULES_TYPE) MAKE_TORQUE_CASE(JSRegExp, JS_REG_EXP_TYPE
) MAKE_TORQUE_CASE(JSRegExpStringIterator, JS_REG_EXP_STRING_ITERATOR_TYPE
) MAKE_TORQUE_CASE(JSRelativeTimeFormat, JS_RELATIVE_TIME_FORMAT_TYPE
) MAKE_TORQUE_CASE(JSSegmentIterator, JS_SEGMENT_ITERATOR_TYPE
) MAKE_TORQUE_CASE(JSSegmenter, JS_SEGMENTER_TYPE) MAKE_TORQUE_CASE
(JSSegments, JS_SEGMENTS_TYPE) MAKE_TORQUE_CASE(JSShadowRealm
, JS_SHADOW_REALM_TYPE) MAKE_TORQUE_CASE(JSSharedStruct, JS_SHARED_STRUCT_TYPE
) MAKE_TORQUE_CASE(JSStringIterator, JS_STRING_ITERATOR_TYPE)
MAKE_TORQUE_CASE(JSTemporalCalendar, JS_TEMPORAL_CALENDAR_TYPE
) MAKE_TORQUE_CASE(JSTemporalDuration, JS_TEMPORAL_DURATION_TYPE
) MAKE_TORQUE_CASE(JSTemporalInstant, JS_TEMPORAL_INSTANT_TYPE
) MAKE_TORQUE_CASE(JSTemporalPlainDate, JS_TEMPORAL_PLAIN_DATE_TYPE
) MAKE_TORQUE_CASE(JSTemporalPlainDateTime, JS_TEMPORAL_PLAIN_DATE_TIME_TYPE
) MAKE_TORQUE_CASE(JSTemporalPlainMonthDay, JS_TEMPORAL_PLAIN_MONTH_DAY_TYPE
) MAKE_TORQUE_CASE(JSTemporalPlainTime, JS_TEMPORAL_PLAIN_TIME_TYPE
) MAKE_TORQUE_CASE(JSTemporalPlainYearMonth, JS_TEMPORAL_PLAIN_YEAR_MONTH_TYPE
) MAKE_TORQUE_CASE(JSTemporalTimeZone, JS_TEMPORAL_TIME_ZONE_TYPE
) MAKE_TORQUE_CASE(JSTemporalZonedDateTime, JS_TEMPORAL_ZONED_DATE_TIME_TYPE
) MAKE_TORQUE_CASE(JSV8BreakIterator, JS_V8_BREAK_ITERATOR_TYPE
) MAKE_TORQUE_CASE(JSWeakRef, JS_WEAK_REF_TYPE) MAKE_TORQUE_CASE
(WasmGlobalObject, WASM_GLOBAL_OBJECT_TYPE) MAKE_TORQUE_CASE(
WasmMemoryObject, WASM_MEMORY_OBJECT_TYPE) MAKE_TORQUE_CASE(WasmModuleObject
, WASM_MODULE_OBJECT_TYPE) MAKE_TORQUE_CASE(WasmSuspenderObject
, WASM_SUSPENDER_OBJECT_TYPE) MAKE_TORQUE_CASE(WasmTableObject
, WASM_TABLE_OBJECT_TYPE) MAKE_TORQUE_CASE(WasmTagObject, WASM_TAG_OBJECT_TYPE
)
231 TORQUE_INSTANCE_CHECKERS_MULTIPLE_FULLY_DEFINED(MAKE_TORQUE_CASE)MAKE_TORQUE_CASE(FixedArray, FIXED_ARRAY_TYPE) MAKE_TORQUE_CASE
(Foreign, FOREIGN_TYPE) MAKE_TORQUE_CASE(UncompiledDataWithPreparseData
, UNCOMPILED_DATA_WITH_PREPARSE_DATA_TYPE) MAKE_TORQUE_CASE(UncompiledDataWithoutPreparseData
, UNCOMPILED_DATA_WITHOUT_PREPARSE_DATA_TYPE) MAKE_TORQUE_CASE
(WasmFunctionData, WASM_FUNCTION_DATA_TYPE) MAKE_TORQUE_CASE(
ExportedSubClassBase, EXPORTED_SUB_CLASS_BASE_TYPE) MAKE_TORQUE_CASE
(DescriptorArray, DESCRIPTOR_ARRAY_TYPE) MAKE_TORQUE_CASE(WeakFixedArray
, WEAK_FIXED_ARRAY_TYPE) MAKE_TORQUE_CASE(JSObject, JS_OBJECT_TYPE
) MAKE_TORQUE_CASE(JSFunction, JS_FUNCTION_TYPE) MAKE_TORQUE_CASE
(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
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)TYPED_ARRAY_CONSTRUCTORS_SWITCH(Uint8, uint8, UINT8, uint8_t)
TYPED_ARRAY_CONSTRUCTORS_SWITCH(Int8, int8, INT8, int8_t) TYPED_ARRAY_CONSTRUCTORS_SWITCH
(Uint16, uint16, UINT16, uint16_t) TYPED_ARRAY_CONSTRUCTORS_SWITCH
(Int16, int16, INT16, int16_t) TYPED_ARRAY_CONSTRUCTORS_SWITCH
(Uint32, uint32, UINT32, uint32_t) TYPED_ARRAY_CONSTRUCTORS_SWITCH
(Int32, int32, INT32, int32_t) TYPED_ARRAY_CONSTRUCTORS_SWITCH
(Float32, float32, FLOAT32, float) TYPED_ARRAY_CONSTRUCTORS_SWITCH
(Float64, float64, FLOAT64, double) TYPED_ARRAY_CONSTRUCTORS_SWITCH
(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t) TYPED_ARRAY_CONSTRUCTORS_SWITCH
(BigUint64, biguint64, BIGUINT64, uint64_t) TYPED_ARRAY_CONSTRUCTORS_SWITCH
(BigInt64, bigint64, BIGINT64, int64_t)
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()V8_Fatal("unreachable code");
285 }
286}
287
288void 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
295void BytecodeArray::BytecodeArrayPrint(std::ostream& os) {
296 PrintHeader(os, "BytecodeArray");
297 os << "\n";
298 Disassemble(os);
299}
300
301void FreeSpace::FreeSpacePrint(std::ostream& os) {
302 os << "free space, size " << Size() << "\n";
303}
304
305bool 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_BOOLfalse) {
343 PrintDictionaryContents(os, property_dictionary_swiss());
344 } else {
345 PrintDictionaryContents(os, property_dictionary());
346 }
347 return true;
348}
349
350namespace {
351
352template <class T>
353bool IsTheHoleAt(T array, int index) {
354 return false;
355}
356
357template <>
358bool IsTheHoleAt(FixedDoubleArray array, int index) {
359 return array.is_the_hole(index);
360}
361
362template <class T>
363double 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
370template <class T>
371void 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
403template <typename ElementType>
404void 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
433template <typename T>
434void 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
457void 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
468void 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)((void) 0);
491 PrintDictionaryElements(os, arguments_store);
492 }
493}
494
495void 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
508void 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)PRINT_ELEMENTS(Uint8, uint8, UINT8, uint8_t) PRINT_ELEMENTS(Int8
, int8, INT8, int8_t) PRINT_ELEMENTS(Uint16, uint16, UINT16, uint16_t
) PRINT_ELEMENTS(Int16, int16, INT16, int16_t) PRINT_ELEMENTS
(Uint32, uint32, UINT32, uint32_t) PRINT_ELEMENTS(Int32, int32
, INT32, int32_t) PRINT_ELEMENTS(Float32, float32, FLOAT32, float
) PRINT_ELEMENTS(Float64, float64, FLOAT64, double) PRINT_ELEMENTS
(Uint8Clamped, uint8_clamped, UINT8_CLAMPED, uint8_t) PRINT_ELEMENTS
(BigUint64, biguint64, BIGUINT64, uint64_t) PRINT_ELEMENTS(BigInt64
, bigint64, BIGINT64, int64_t)
543 RAB_GSAB_TYPED_ARRAYS(PRINT_ELEMENTS)PRINT_ELEMENTS(RabGsabUint8, rab_gsab_uint8, RAB_GSAB_UINT8, uint8_t
) PRINT_ELEMENTS(RabGsabInt8, rab_gsab_int8, RAB_GSAB_INT8, int8_t
) PRINT_ELEMENTS(RabGsabUint16, rab_gsab_uint16, RAB_GSAB_UINT16
, uint16_t) PRINT_ELEMENTS(RabGsabInt16, rab_gsab_int16, RAB_GSAB_INT16
, int16_t) PRINT_ELEMENTS(RabGsabUint32, rab_gsab_uint32, RAB_GSAB_UINT32
, uint32_t) PRINT_ELEMENTS(RabGsabInt32, rab_gsab_int32, RAB_GSAB_INT32
, int32_t) PRINT_ELEMENTS(RabGsabFloat32, rab_gsab_float32, RAB_GSAB_FLOAT32
, float) PRINT_ELEMENTS(RabGsabFloat64, rab_gsab_float64, RAB_GSAB_FLOAT64
, double) PRINT_ELEMENTS(RabGsabUint8Clamped, rab_gsab_uint8_clamped
, RAB_GSAB_UINT8_CLAMPED, uint8_t) PRINT_ELEMENTS(RabGsabBigUint64
, rab_gsab_biguint64, RAB_GSAB_BIGUINT64, uint64_t) PRINT_ELEMENTS
(RabGsabBigInt64, rab_gsab_bigint64, RAB_GSAB_BIGINT64, int64_t
)
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()V8_Fatal("unreachable code");
558 case NO_ELEMENTS:
559 break;
560 }
561 os << "\n }\n";
562}
563
564static 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
591static 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
619void JSObject::JSObjectPrint(std::ostream& os) {
620 JSObjectPrintHeader(os, *this, nullptr);
621 JSObjectPrintBody(os, *this);
622}
623
624void 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())((void) 0);
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
684void JSArray::JSArrayPrint(std::ostream& os) {
685 JSObjectPrintHeader(os, *this, "JSArray");
686 os << "\n - length: " << Brief(this->length());
687 JSObjectPrintBody(os, *this);
688}
689
690void 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
704void 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
713void 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
723void 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
736void 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
755namespace {
756void 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
764template <typename T>
765void 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
791void ObjectBoilerplateDescription::ObjectBoilerplateDescriptionPrint(
792 std::ostream& os) {
793 PrintFixedArrayWithHeader(os, *this, "ObjectBoilerplateDescription");
794}
795
796void 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
809void FixedArray::FixedArrayPrint(std::ostream& os) {
810 PrintFixedArrayWithHeader(os, *this, "FixedArray");
811}
812
813namespace {
814const 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
826void 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
841namespace {
842void 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
859void Context::ContextPrint(std::ostream& os) {
860 PrintContextWithHeader(os, *this, "Context");
861}
862
863void NativeContext::NativeContextPrint(std::ostream& os) {
864 PrintContextWithHeader(os, *this, "NativeContext");
865 os << " - microtask_queue: " << microtask_queue() << "\n";
866}
867
868namespace {
869using 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).
880template <typename T>
881void 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.
903template <typename T>
904void 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.
915template <typename T>
916void 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.
924template <typename T>
925void 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.
933template <typename T>
934void 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())((void) 0);
949 os << "\n " << std::setw(12) << bucket << ": " << Brief(entry);
950 }
951 os << "\n }";
952}
953
954// Used for subtypes of HashTable.
955template <typename T>
956void 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
965void ObjectHashTable::ObjectHashTablePrint(std::ostream& os) {
966 PrintHashTableHeader(os, *this, "ObjectHashTable");
967 PrintHashMapContentsFull(os, *this);
968}
969
970void NameToIndexHashTable::NameToIndexHashTablePrint(std::ostream& os) {
971 PrintHashTableHeader(os, *this, "NameToIndexHashTable");
972 PrintHashMapContentsFull(os, *this);
973}
974
975void RegisteredSymbolTable::RegisteredSymbolTablePrint(std::ostream& os) {
976 PrintHashTableHeader(os, *this, "RegisteredSymbolTable");
977 PrintHashMapContentsFull(os, *this);
978}
979
980void NumberDictionary::NumberDictionaryPrint(std::ostream& os) {
981 PrintHashTableHeader(os, *this, "NumberDictionary");
982 PrintDictionaryContentsFull(os, *this);
983}
984
985void EphemeronHashTable::EphemeronHashTablePrint(std::ostream& os) {
986 PrintHashTableHeader(os, *this, "EphemeronHashTable");
987 PrintHashMapContentsFull(os, *this);
988}
989
990void NameDictionary::NameDictionaryPrint(std::ostream& os) {
991 PrintHashTableHeader(os, *this, "NameDictionary");
992 PrintDictionaryContentsFull(os, *this);
993}
994
995void GlobalDictionary::GlobalDictionaryPrint(std::ostream& os) {
996 PrintHashTableHeader(os, *this, "GlobalDictionary");
997 PrintDictionaryContentsFull(os, *this);
998}
999
1000void SmallOrderedHashSet::SmallOrderedHashSetPrint(std::ostream& os) {
1001 PrintHeader(os, "SmallOrderedHashSet");
1002 // TODO(turbofan): Print all fields.
1003}
1004
1005void SmallOrderedHashMap::SmallOrderedHashMapPrint(std::ostream& os) {
1006 PrintHeader(os, "SmallOrderedHashMap");
1007 // TODO(turbofan): Print all fields.
1008}
1009
1010void SmallOrderedNameDictionary::SmallOrderedNameDictionaryPrint(
1011 std::ostream& os) {
1012 PrintHeader(os, "SmallOrderedNameDictionary");
1013 // TODO(turbofan): Print all fields.
1014}
1015
1016void OrderedHashSet::OrderedHashSetPrint(std::ostream& os) {
1017 PrintOrderedHashTableHeaderAndBuckets(os, *this, "OrderedHashSet");
1018 PrintHashSetContentsFull(os, *this);
1019}
1020
1021void OrderedHashMap::OrderedHashMapPrint(std::ostream& os) {
1022 PrintOrderedHashTableHeaderAndBuckets(os, *this, "OrderedHashMap");
1023 PrintHashMapContentsFull(os, *this);
1024}
1025
1026void OrderedNameDictionary::OrderedNameDictionaryPrint(std::ostream& os) {
1027 PrintOrderedHashTableHeaderAndBuckets(os, *this, "OrderedNameDictionary");
1028 PrintDictionaryContentsFull(os, *this);
1029}
1030
1031void 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
1036void 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()V8_Fatal("unreachable code");
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
1098void 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
1106void 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
1113void WeakFixedArray::WeakFixedArrayPrint(std::ostream& os) {
1114 PrintHeader(os, "WeakFixedArray");
1115 os << "\n - length: " << length() << "\n";
1116 PrintWeakArrayElements(os, this);
1117 os << "\n";
1118}
1119
1120void 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
1128void TransitionArray::TransitionArrayPrint(std::ostream& os) {
1129 PrintHeader(os, "TransitionArray");
1130 PrintInternal(os);
1131}
1132
1133void 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
1150void FeedbackVectorSpec::Print() {
1151 StdoutStream os;
1152
1153 FeedbackVectorSpecPrint(os);
1154
1155 os << std::flush;
1156}
1157
1158void 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)((void) 0);
1169 os << "\n Slot #" << slot << " " << kind;
1170 slot += entry_size;
1171 }
1172 os << "\n";
1173}
1174
1175void 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
1189void ClosureFeedbackCellArray::ClosureFeedbackCellArrayPrint(std::ostream& os) {
1190 PrintFixedArrayWithHeader(os, *this, "ClosureFeedbackCellArray");
1191}
1192
1193void 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
1234void FeedbackVector::FeedbackSlotPrint(std::ostream& os, FeedbackSlot slot) {
1235 FeedbackNexus nexus(*this, slot);
1236 nexus.Print(os);
1237}
1238
1239void 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()V8_Fatal("unreachable code");
1280 }
1281}
1282
1283void 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
1293void JSAsyncFunctionObject::JSAsyncFunctionObjectPrint(std::ostream& os) {
1294 JSGeneratorObjectPrint(os);
1295}
1296
1297void JSAsyncGeneratorObject::JSAsyncGeneratorObjectPrint(std::ostream& os) {
1298 JSGeneratorObjectPrint(os);
1299}
1300
1301void JSArgumentsObject::JSArgumentsObjectPrint(std::ostream& os) {
1302 JSObjectPrint(os);
1303}
1304
1305void 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
1312void 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
1319void JSPrimitiveWrapper::JSPrimitiveWrapperPrint(std::ostream& os) {
1320 JSObjectPrintHeader(os, *this, "JSPrimitiveWrapper");
1321 os << "\n - value: " << Brief(value());
1322 JSObjectPrintBody(os, *this);
1323}
1324
1325void 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
1336void 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
1344void Name::NamePrint(std::ostream& os) {
1345 if (IsString()) {
1346 String::cast(*this).StringPrint(os);
1347 } else {
1348 os << Brief(*this);
1349 }
1350}
1351
1352static const char* const weekdays[] = {"???", "Sun", "Mon", "Tue",
1353 "Wed", "Thu", "Fri", "Sat"};
1354
1355void 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
1376void JSSet::JSSetPrint(std::ostream& os) {
1377 JSObjectPrintHeader(os, *this, "JSSet");
1378 os << "\n - table: " << Brief(table());
1379 JSObjectPrintBody(os, *this);
1380}
1381
1382void JSMap::JSMapPrint(std::ostream& os) {
1383 JSObjectPrintHeader(os, *this, "JSMap");
1384 os << "\n - table: " << Brief(table());
1385 JSObjectPrintBody(os, *this);
1386}
1387
1388void 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
1396void JSSetIterator::JSSetIteratorPrint(std::ostream& os) {
1397 JSCollectionIteratorPrint(os, "JSSetIterator");
1398}
1399
1400void JSMapIterator::JSMapIteratorPrint(std::ostream& os) {
1401 JSCollectionIteratorPrint(os, "JSMapIterator");
1402}
1403
1404void JSWeakRef::JSWeakRefPrint(std::ostream& os) {
1405 JSObjectPrintHeader(os, *this, "JSWeakRef");
1406 os << "\n - target: " << Brief(target());
1407 JSObjectPrintBody(os, *this);
1408}
1409
1410void JSShadowRealm::JSShadowRealmPrint(std::ostream& os) {
1411 JSObjectPrintHeader(os, *this, "JSShadowRealm");
1412 os << "\n - native_context: " << Brief(native_context());
1413 JSObjectPrintBody(os, *this);
1414}
1415
1416void 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
1422void 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
1442void 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
1450void JSWeakMap::JSWeakMapPrint(std::ostream& os) {
1451 JSObjectPrintHeader(os, *this, "JSWeakMap");
1452 os << "\n - table: " << Brief(table());
1453 JSObjectPrintBody(os, *this);
1454}
1455
1456void JSWeakSet::JSWeakSetPrint(std::ostream& os) {
1457 JSObjectPrintHeader(os, *this, "JSWeakSet");
1458 os << "\n - table: " << Brief(table());
1459 JSObjectPrintBody(os, *this);
1460}
1461
1462void 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
1475void 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
1497void 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
1505void 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
1518void 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
1526void 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_WEBASSEMBLY1
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
1590void 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
1602void 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
1657void 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
1665void 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
1674void 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
1686void 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_DISASSEMBLER1
1695 Disassemble(nullptr, os, GetIsolate());
1696#endif
1697}
1698
1699void 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_BOOLfalse) {
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
1710void Foreign::ForeignPrint(std::ostream& os) {
1711 PrintHeader(os, "Foreign");
1712 os << "\n - foreign address : " << reinterpret_cast<void*>(foreign_address());
1713 os << "\n";
1714}
1715
1716void 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
1736static 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
1742void 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()V8_Fatal("unreachable code");
1749 }
1750}
1751
1752void 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
1766void JSModuleNamespace::JSModuleNamespacePrint(std::ostream& os) {
1767 JSObjectPrintHeader(os, *this, "JSModuleNamespace");
1768 os << "\n - module: " << Brief(module());
1769 JSObjectPrintBody(os, *this);
1770}
1771
1772void 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
1782void 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_WEBASSEMBLY1
1791void 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
1799void 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
1808void 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()V8_Fatal("unreachable code");
1854 }
1855 }
1856 os << "\n";
1857}
1858
1859void 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()V8_Fatal("unreachable code");
1901 }
1902 os << "\n";
1903}
1904
1905void 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
1913void 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
1921void 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.
1973void WasmFunctionData::WasmFunctionDataPrint(std::ostream& os) {
1974 os << "\n - internal: " << Brief(internal());
1975 os << "\n - wrapper_code: " << Brief(TorqueGeneratedClass::wrapper_code());
1976}
1977
1978void 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
1989void 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
1998void WasmOnFulfilledData::WasmOnFulfilledDataPrint(std::ostream& os) {
1999 PrintHeader(os, "WasmOnFulfilledData");
2000 os << "\n - suspender: " << Brief(suspender());
2001 os << '\n';
2002}
2003
2004void 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
2013void 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
2022void 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
2030void 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
2039void 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
2054void 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
2068void 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
2075void 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
2093void 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
2111void 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
2121void 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
2138void 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
2150void 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
2173void 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
2183void 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
2189void 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_WEBASSEMBLY1
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
2224void JSTemporalPlainDate::JSTemporalPlainDatePrint(std::ostream& os) {
2225 JSObjectPrintHeader(os, *this, "JSTemporalPlainDate");
2226 JSObjectPrintBody(os, *this);
2227}
2228
2229void JSTemporalPlainTime::JSTemporalPlainTimePrint(std::ostream& os) {
2230 JSObjectPrintHeader(os, *this, "JSTemporalPlainTime");
2231 JSObjectPrintBody(os, *this);
2232}
2233
2234void JSTemporalPlainDateTime::JSTemporalPlainDateTimePrint(std::ostream& os) {
2235 JSObjectPrintHeader(os, *this, "JSTemporalPlainDateTime");
2236 JSObjectPrintBody(os, *this);
2237}
2238
2239void JSTemporalZonedDateTime::JSTemporalZonedDateTimePrint(std::ostream& os) {
2240 JSObjectPrintHeader(os, *this, "JSTemporalZonedDateTime");
2241 JSObjectPrintBody(os, *this);
2242}
2243
2244void JSTemporalDuration::JSTemporalDurationPrint(std::ostream& os) {
2245 JSObjectPrintHeader(os, *this, "JSTemporalDuration");
2246 JSObjectPrintBody(os, *this);
2247}
2248
2249void JSTemporalInstant::JSTemporalInstantPrint(std::ostream& os) {
2250 JSObjectPrintHeader(os, *this, "JSTemporalInstant");
2251 JSObjectPrintBody(os, *this);
2252}
2253
2254void JSTemporalPlainYearMonth::JSTemporalPlainYearMonthPrint(std::ostream& os) {
2255 JSObjectPrintHeader(os, *this, "JSTemporalPlainYearMonth");
2256 JSObjectPrintBody(os, *this);
2257}
2258
2259void JSTemporalPlainMonthDay::JSTemporalPlainMonthDayPrint(std::ostream& os) {
2260 JSObjectPrintHeader(os, *this, "JSTemporalPlainMonthDay");
2261 JSObjectPrintBody(os, *this);
2262}
2263
2264void JSTemporalTimeZone::JSTemporalTimeZonePrint(std::ostream& os) {
2265 JSObjectPrintHeader(os, *this, "JSTemporalTimeZone");
2266 JSObjectPrintBody(os, *this);
2267}
2268
2269void JSTemporalCalendar::JSTemporalCalendarPrint(std::ostream& os) {
2270 JSObjectPrintHeader(os, *this, "JSTemporalCalendar");
2271 JSObjectPrintBody(os, *this);
2272}
2273#ifdef V8_INTL_SUPPORT1
2274void 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
2287void 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
2294void 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
2305void 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
2313void 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
2322void JSLocale::JSLocalePrint(std::ostream& os) {
2323 JSObjectPrintHeader(os, *this, "JSLocale");
2324 os << "\n - icu locale: " << Brief(icu_locale());
2325 JSObjectPrintBody(os, *this);
2326}
2327
2328void 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
2336void 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
2345void 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
2354void 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
2361void 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
2369void 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
2378namespace {
2379void 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
2392void 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
2456void 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
2472template <HeapObjectReferenceType kRefType, typename StorageType>
2473void TaggedImpl<kRefType, StorageType>::Print() {
2474 StdoutStream os;
2475 this->Print(os);
2476 os << std::flush;
2477}
2478
2479template <HeapObjectReferenceType kRefType, typename StorageType>
2480void 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()V8_Fatal("unreachable code");
2494 }
2495}
2496
2497void HeapNumber::HeapNumberPrint(std::ostream& os) {
2498 HeapNumberShortPrint(os);
2499 os << "\n";
2500}
2501
2502#endif // OBJECT_PRINT
2503
2504void 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.
2524void Name::NameShortPrint() {
2525 if (this->IsString()) {
2526 PrintF("%s", String::cast(*this).ToCString().get());
2527 } else {
2528 DCHECK(this->IsSymbol())((void) 0);
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.
2539int 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())((void) 0);
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
2554void Map::PrintMapDetails(std::ostream& os) {
2555 DisallowGarbageCollection no_gc;
2556 this->MapPrint(os);
2557 instance_descriptors().PrintDescriptors(os);
2558}
2559
2560void Map::MapPrint(std::ostream& os) {
2561#ifdef OBJECT_PRINT1
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_PRINT1
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
2642void 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_PRINT1
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
2657void 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_PRINT1)
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.
2685char* 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
2697void TransitionsAccessor::PrintOneTransition(std::ostream& os, Name key,
2698 Map target) {
2699 os << "\n ";
2700#ifdef OBJECT_PRINT1
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))((void) 0);
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
2730void 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
2741void 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
2758void 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
2766void 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_PRINT1
2792 key.NamePrint(os);
2793#else
2794 key.ShortPrint(os);
2795#endif
2796 os << " ";
2797 DCHECK(!IsSpecialTransition(ReadOnlyRoots(isolate_), key))((void) 0);
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
2809void 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
2820namespace {
2821
2822inline 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//
2840V8_EXPORT_PRIVATE extern i::Object _v8_internal_Get_Object(void* object) {
2841 return GetObjectFromRaw(object);
2842}
2843
2844V8_EXPORT_PRIVATE extern void _v8_internal_Print_Object(void* object) {
2845 GetObjectFromRaw(object).Print();
2846}
2847
2848V8_EXPORT_PRIVATE extern void _v8_internal_Print_LoadHandler(void* object) {
2849#ifdef OBJECT_PRINT1
2850 i::StdoutStream os;
2851 i::LoadHandler::PrintHandler(GetObjectFromRaw(object), os);
2852 os << std::flush;
2853#endif
2854}
2855
2856V8_EXPORT_PRIVATE extern void _v8_internal_Print_StoreHandler(void* object) {
2857#ifdef OBJECT_PRINT1
2858 i::StdoutStream os;
2859 i::StoreHandler::PrintHandler(GetObjectFromRaw(object), os);
2860 os << std::flush;
2861#endif
2862}
2863
2864V8_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_WEBASSEMBLY1
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_DISASSEMBLER1
2896 i::StdoutStream os;
2897 code.Disassemble(nullptr, os, isolate, address);
2898#else // ENABLE_DISASSEMBLER
2899 code.Print();
2900#endif // ENABLE_DISASSEMBLER
2901}
2902
2903V8_EXPORT_PRIVATE extern void _v8_internal_Print_StackTrace() {
2904 i::Isolate* isolate = i::Isolate::Current();
2905 isolate->PrintStack(stdoutstdout);
2906}
2907
2908V8_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_PRINT1)
2914 i::Map map = i::Map::unchecked_cast(o);
2915 i::TransitionsAccessor transitions(i::Isolate::Current(), map);
2916 transitions.PrintTransitionTree();
2917#endif
2918 }
2919}

../deps/v8/src/objects/swiss-name-dictionary-inl.h

1// Copyright 2021 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#ifndef V8_OBJECTS_SWISS_NAME_DICTIONARY_INL_H_
6#define V8_OBJECTS_SWISS_NAME_DICTIONARY_INL_H_
7
8#include <algorithm>
9
10#include "src/base/macros.h"
11#include "src/base/optional.h"
12#include "src/execution/isolate-utils-inl.h"
13#include "src/heap/heap.h"
14#include "src/objects/fixed-array-inl.h"
15#include "src/objects/instance-type-inl.h"
16#include "src/objects/js-collection-iterator.h"
17#include "src/objects/objects-inl.h"
18#include "src/objects/smi.h"
19#include "src/objects/swiss-name-dictionary.h"
20
21// Has to be the last include (doesn't have include guards):
22#include "src/objects/object-macros.h"
23
24namespace v8 {
25namespace internal {
26
27#include "torque-generated/src/objects/swiss-name-dictionary-tq-inl.inc"
28
29CAST_ACCESSOR(SwissNameDictionary)
30OBJECT_CONSTRUCTORS_IMPL(SwissNameDictionary, HeapObject)
31
32swiss_table::ctrl_t* SwissNameDictionary::CtrlTable() {
33 return reinterpret_cast<ctrl_t*>(
34 field_address(CtrlTableStartOffset(Capacity())));
35}
36
37uint8_t* SwissNameDictionary::PropertyDetailsTable() {
38 return reinterpret_cast<uint8_t*>(
39 field_address(PropertyDetailsTableStartOffset(Capacity())));
40}
41
42int SwissNameDictionary::Capacity() {
43 return ReadField<int32_t>(CapacityOffset());
44}
45
46void SwissNameDictionary::SetCapacity(int capacity) {
47 DCHECK(IsValidCapacity(capacity))((void) 0);
48
49 WriteField<int32_t>(CapacityOffset(), capacity);
50}
51
52int SwissNameDictionary::NumberOfElements() {
53 return GetMetaTableField(kMetaTableElementCountFieldIndex);
54}
55
56int SwissNameDictionary::NumberOfDeletedElements() {
57 return GetMetaTableField(kMetaTableDeletedElementCountFieldIndex);
58}
59
60void SwissNameDictionary::SetNumberOfElements(int elements) {
61 SetMetaTableField(kMetaTableElementCountFieldIndex, elements);
62}
63
64void SwissNameDictionary::SetNumberOfDeletedElements(int deleted_elements) {
65 SetMetaTableField(kMetaTableDeletedElementCountFieldIndex, deleted_elements);
66}
67
68int SwissNameDictionary::UsedCapacity() {
69 return NumberOfElements() + NumberOfDeletedElements();
70}
71
72// static
73constexpr bool SwissNameDictionary::IsValidCapacity(int capacity) {
74 return capacity == 0 || (capacity >= kInitialCapacity &&
75 // Must be power of 2.
76 ((capacity & (capacity - 1)) == 0));
77}
78
79// static
80constexpr int SwissNameDictionary::DataTableSize(int capacity) {
81 return capacity * kTaggedSize * kDataTableEntryCount;
82}
83
84// static
85constexpr int SwissNameDictionary::CtrlTableSize(int capacity) {
86 // Doing + |kGroupWidth| due to the copy of first group at the end of control
87 // table.
88 return (capacity + kGroupWidth) * kOneByteSize;
89}
90
91// static
92constexpr int SwissNameDictionary::SizeFor(int capacity) {
93 DCHECK(IsValidCapacity(capacity))((void) 0);
94 return PropertyDetailsTableStartOffset(capacity) + capacity;
95}
96
97// We use 7/8th as maximum load factor for non-special cases.
98// For 16-wide groups, that gives an average of two empty slots per group.
99// Similar to Abseil's CapacityToGrowth.
100// static
101constexpr int SwissNameDictionary::MaxUsableCapacity(int capacity) {
102 DCHECK(IsValidCapacity(capacity))((void) 0);
103
104 if (Group::kWidth == 8 && capacity == 4) {
105 // If the group size is 16 we can fully utilize capacity 4: There will be
106 // enough kEmpty entries in the ctrl table.
107 return 3;
108 }
109 return capacity - capacity / 8;
110}
111
112// Returns |at_least_space_for| * 8/7 for non-special cases. Similar to Abseil's
113// GrowthToLowerboundCapacity.
114// static
115int SwissNameDictionary::CapacityFor(int at_least_space_for) {
116 if (at_least_space_for <= 4) {
117 if (at_least_space_for == 0) {
118 return 0;
119 } else if (at_least_space_for < 4) {
120 return 4;
121 } else if (kGroupWidth == 16) {
122 DCHECK_EQ(4, at_least_space_for)((void) 0);
123 return 4;
124 } else if (kGroupWidth == 8) {
125 DCHECK_EQ(4, at_least_space_for)((void) 0);
126 return 8;
127 }
128 }
129
130 int non_normalized = at_least_space_for + at_least_space_for / 7;
131 return base::bits::RoundUpToPowerOfTwo32(non_normalized);
132}
133
134int SwissNameDictionary::EntryForEnumerationIndex(int enumeration_index) {
135 DCHECK_LT(enumeration_index, UsedCapacity())((void) 0);
136 return GetMetaTableField(kMetaTableEnumerationDataStartIndex +
137 enumeration_index);
138}
139
140void SwissNameDictionary::SetEntryForEnumerationIndex(int enumeration_index,
141 int entry) {
142 DCHECK_LT(enumeration_index, UsedCapacity())((void) 0);
143 DCHECK_LT(static_cast<unsigned>(entry), static_cast<unsigned>(Capacity()))((void) 0);
144 DCHECK(IsFull(GetCtrl(entry)))((void) 0);
145
146 SetMetaTableField(kMetaTableEnumerationDataStartIndex + enumeration_index,
147 entry);
148}
149
150template <typename IsolateT>
151InternalIndex SwissNameDictionary::FindEntry(IsolateT* isolate, Object key) {
152 Name name = Name::cast(key);
153 DCHECK(name.IsUniqueName())((void) 0);
154 uint32_t hash = name.hash();
155
156 // We probe the hash table in groups of |kGroupWidth| buckets. One bucket
157 // corresponds to a 1-byte entry in the control table.
158 // Each group can be uniquely identified by the index of its first bucket,
159 // which must be a value between 0 (inclusive) and Capacity() (exclusive).
160 // Note that logically, groups wrap around after index Capacity() - 1. This
161 // means that probing the group starting at, for example, index Capacity() - 1
162 // means probing CtrlTable()[Capacity() - 1] followed by CtrlTable()[0] to
163 // CtrlTable()[6], assuming a group width of 8. However, in memory, this is
164 // achieved by maintaining an additional |kGroupWidth| bytes after the first
165 // Capacity() entries of the control table. These contain a copy of the first
166 // max(Capacity(), kGroupWidth) entries of the control table. If Capacity() <
167 // |kGroupWidth|, then the remaining |kGroupWidth| - Capacity() control bytes
168 // are left as |kEmpty|.
169 // This means that actually, probing the group starting
170 // at index Capacity() - 1 is achieved by probing CtrlTable()[Capacity() - 1],
171 // followed by CtrlTable()[Capacity()] to CtrlTable()[Capacity() + 7].
172
173 ctrl_t* ctrl = CtrlTable();
174 auto seq = probe(hash, Capacity());
175 // At this point, seq.offset() denotes the index of the first bucket in the
176 // first group to probe. Note that this doesn't have to be divisible by
177 // |kGroupWidth|, but can have any value between 0 (inclusive) and Capacity()
178 // (exclusive).
179 while (true) {
180 Group g{ctrl + seq.offset()};
181 for (int i : g.Match(swiss_table::H2(hash))) {
182 int candidate_entry = seq.offset(i);
183 Object candidate_key = KeyAt(candidate_entry);
184 // This key matching is SwissNameDictionary specific!
185 if (candidate_key == key) return InternalIndex(candidate_entry);
186 }
187 if (g.MatchEmpty()) return InternalIndex::NotFound();
188
189 // The following selects the next group to probe. Note that seq.offset()
190 // always advances by a multiple of |kGroupWidth|, modulo Capacity(). This
191 // is done in a way such that we visit Capacity() / |kGroupWidth|
192 // non-overlapping (!) groups before we would visit the same group (or
193 // bucket) again.
194 seq.next();
195
196 // If the following DCHECK weren't true, we would have probed all Capacity()
197 // different buckets without finding one containing |kEmpty| (which would
198 // haved triggered the g.MatchEmpty() check above). This must not be the
199 // case because the maximum load factor of 7/8 guarantees that there must
200 // always remain empty buckets.
201 //
202 // The only exception from this rule are small tables, where 2 * Capacity()
203 // < |kGroupWidth|, in which case all Capacity() entries can be filled
204 // without leaving empty buckets. The layout of the control
205 // table guarantees that after the first Capacity() entries of the control
206 // table, the control table contains a copy of those first Capacity()
207 // entries, followed by kGroupWidth - 2 * Capacity() entries containing
208 // |kEmpty|. This guarantees that the g.MatchEmpty() check above will
209 // always trigger if the element wasn't found, correctly preventing us from
210 // probing more than one group in this special case.
211 DCHECK_LT(seq.index(), Capacity())((void) 0);
212 }
213}
214
215template <typename IsolateT>
216InternalIndex SwissNameDictionary::FindEntry(IsolateT* isolate,
217 Handle<Object> key) {
218 return FindEntry(isolate, *key);
219}
220
221Object SwissNameDictionary::LoadFromDataTable(int entry, int data_offset) {
222 return LoadFromDataTable(GetPtrComprCageBase(*this), entry, data_offset);
223}
224
225Object SwissNameDictionary::LoadFromDataTable(PtrComprCageBase cage_base,
226 int entry, int data_offset) {
227 DCHECK_LT(static_cast<unsigned>(entry), static_cast<unsigned>(Capacity()))((void) 0);
228 int offset = DataTableStartOffset() +
229 (entry * kDataTableEntryCount + data_offset) * kTaggedSize;
230 return TaggedField<Object>::Relaxed_Load(cage_base, *this, offset);
231}
232
233void SwissNameDictionary::StoreToDataTable(int entry, int data_offset,
234 Object data) {
235 DCHECK_LT(static_cast<unsigned>(entry), static_cast<unsigned>(Capacity()))((void) 0);
236
237 int offset = DataTableStartOffset() +
238 (entry * kDataTableEntryCount + data_offset) * kTaggedSize;
239
240 RELAXED_WRITE_FIELD(*this, offset, data);
241 WRITE_BARRIER(*this, offset, data);
242}
243
244void SwissNameDictionary::StoreToDataTableNoBarrier(int entry, int data_offset,
245 Object data) {
246 DCHECK_LT(static_cast<unsigned>(entry), static_cast<unsigned>(Capacity()))((void) 0);
247
248 int offset = DataTableStartOffset() +
249 (entry * kDataTableEntryCount + data_offset) * kTaggedSize;
250
251 RELAXED_WRITE_FIELD(*this, offset, data);
252}
253
254void SwissNameDictionary::ClearDataTableEntry(Isolate* isolate, int entry) {
255 ReadOnlyRoots roots(isolate);
256
257 StoreToDataTable(entry, kDataTableKeyEntryIndex, roots.the_hole_value());
258 StoreToDataTable(entry, kDataTableValueEntryIndex, roots.the_hole_value());
259}
260
261void SwissNameDictionary::ValueAtPut(int entry, Object value) {
262 DCHECK(!value.IsTheHole())((void) 0);
263 StoreToDataTable(entry, kDataTableValueEntryIndex, value);
264}
265
266void SwissNameDictionary::ValueAtPut(InternalIndex entry, Object value) {
267 ValueAtPut(entry.as_int(), value);
268}
269
270void SwissNameDictionary::SetKey(int entry, Object key) {
271 DCHECK(!key.IsTheHole())((void) 0);
272 StoreToDataTable(entry, kDataTableKeyEntryIndex, key);
273}
274
275void SwissNameDictionary::DetailsAtPut(int entry, PropertyDetails details) {
276 DCHECK_LT(static_cast<unsigned>(entry), static_cast<unsigned>(Capacity()))((void) 0);
277 uint8_t encoded_details = details.ToByte();
278 PropertyDetailsTable()[entry] = encoded_details;
279}
280
281void SwissNameDictionary::DetailsAtPut(InternalIndex entry,
282 PropertyDetails details) {
283 DetailsAtPut(entry.as_int(), details);
284}
285
286Object SwissNameDictionary::KeyAt(int entry) {
287 return LoadFromDataTable(entry, kDataTableKeyEntryIndex);
288}
289
290Object SwissNameDictionary::KeyAt(InternalIndex entry) {
291 return KeyAt(entry.as_int());
292}
293
294Name SwissNameDictionary::NameAt(InternalIndex entry) {
295 return Name::cast(KeyAt(entry));
296}
297
298// This version can be called on empty buckets.
299Object SwissNameDictionary::ValueAtRaw(int entry) {
300 return LoadFromDataTable(entry, kDataTableValueEntryIndex);
301}
302
303Object SwissNameDictionary::ValueAt(InternalIndex entry) {
304 DCHECK(IsFull(GetCtrl(entry.as_int())))((void) 0);
305 return ValueAtRaw(entry.as_int());
306}
307
308base::Optional<Object> SwissNameDictionary::TryValueAt(InternalIndex entry) {
309#if DEBUG
310 Isolate* isolate;
311 GetIsolateFromHeapObject(*this, &isolate);
312 DCHECK_NE(isolate, nullptr)((void) 0);
313 SLOW_DCHECK(!isolate->heap()->IsPendingAllocation(*this))((void)0);
314#endif // DEBUG
315 // We can read Capacity() in a non-atomic way since we are reading an
316 // initialized object which is not pending allocation.
317 if (static_cast<unsigned>(entry.as_int()) >=
318 static_cast<unsigned>(Capacity())) {
319 return {};
320 }
321 return ValueAtRaw(entry.as_int());
322}
323
324PropertyDetails SwissNameDictionary::DetailsAt(int entry) {
325 // GetCtrl(entry) does a bounds check for |entry| value.
326 DCHECK(IsFull(GetCtrl(entry)))((void) 0);
327
328 uint8_t encoded_details = PropertyDetailsTable()[entry];
329 return PropertyDetails::FromByte(encoded_details);
330}
331
332PropertyDetails SwissNameDictionary::DetailsAt(InternalIndex entry) {
333 return DetailsAt(entry.as_int());
334}
335
336// static
337template <typename IsolateT>
338Handle<SwissNameDictionary> SwissNameDictionary::EnsureGrowable(
339 IsolateT* isolate, Handle<SwissNameDictionary> table) {
340 int capacity = table->Capacity();
341
342 if (table->UsedCapacity() < MaxUsableCapacity(capacity)) {
343 // We have room for at least one more entry, nothing to do.
344 return table;
345 }
346
347 int new_capacity = capacity == 0 ? kInitialCapacity : capacity * 2;
348 return Rehash(isolate, table, new_capacity);
349}
350
351swiss_table::ctrl_t SwissNameDictionary::GetCtrl(int entry) {
352 DCHECK_LT(static_cast<unsigned>(entry), static_cast<unsigned>(Capacity()))((void) 0);
353
354 return CtrlTable()[entry];
355}
356
357void SwissNameDictionary::SetCtrl(int entry, ctrl_t h) {
358 int capacity = Capacity();
359 DCHECK_LT(static_cast<unsigned>(entry), static_cast<unsigned>(capacity))((void) 0);
360
361 ctrl_t* ctrl = CtrlTable();
362 ctrl[entry] = h;
363
364 // The ctrl table contains a copy of the first group (i.e., the group starting
365 // at entry 0) after the first |capacity| entries of the ctrl table. This
366 // means that the ctrl table always has size |capacity| + |kGroupWidth|.
367 // However, note that we may have |capacity| < |kGroupWidth|. For example, if
368 // Capacity() == 8 and |kGroupWidth| == 16, then ctrl[0] is copied to ctrl[8],
369 // ctrl[1] to ctrl[9], etc. In this case, ctrl[16] to ctrl[23] remain unused,
370 // which means that their values are always Ctrl::kEmpty.
371 // We achieve the necessary copying without branching here using some bit
372 // magic: We set {copy_entry = entry} in those cases where we don't actually
373 // have to perform a copy (meaning that we just repeat the {ctrl[entry] = h}
374 // from above). If we do need to do some actual copying, we set {copy_entry =
375 // Capacity() + entry}.
376
377 int mask = capacity - 1;
378 int copy_entry =
379 ((entry - Group::kWidth) & mask) + 1 + ((Group::kWidth - 1) & mask);
380 DCHECK_IMPLIES(entry < static_cast<int>(Group::kWidth),((void) 0)
381 copy_entry == capacity + entry)((void) 0);
382 DCHECK_IMPLIES(entry >= static_cast<int>(Group::kWidth), copy_entry == entry)((void) 0);
383 ctrl[copy_entry] = h;
384}
385
386// static
387inline int SwissNameDictionary::FindFirstEmpty(uint32_t hash) {
388 // See SwissNameDictionary::FindEntry for description of probing algorithm.
389
390 auto seq = probe(hash, Capacity());
391 while (true) {
392 Group g{CtrlTable() + seq.offset()};
393 auto mask = g.MatchEmpty();
394 if (mask) {
395 // Note that picking the lowest bit set here means using the leftmost
396 // empty bucket in the group. Here, "left" means smaller entry/bucket
397 // index.
398 return seq.offset(mask.LowestBitSet());
399 }
400 seq.next();
401 DCHECK_LT(seq.index(), Capacity())((void) 0);
402 }
403}
404
405void SwissNameDictionary::SetMetaTableField(int field_index, int value) {
406 // See the STATIC_ASSERTs on |kMax1ByteMetaTableCapacity| and
407 // |kMax2ByteMetaTableCapacity| in the .cc file for an explanation of these
408 // constants.
409 int capacity = Capacity();
410 ByteArray meta_table = this->meta_table();
411 if (capacity <= kMax1ByteMetaTableCapacity) {
412 SetMetaTableField<uint8_t>(meta_table, field_index, value);
413 } else if (capacity <= kMax2ByteMetaTableCapacity) {
414 SetMetaTableField<uint16_t>(meta_table, field_index, value);
415 } else {
416 SetMetaTableField<uint32_t>(meta_table, field_index, value);
417 }
418}
419
420int SwissNameDictionary::GetMetaTableField(int field_index) {
421 // See the STATIC_ASSERTs on |kMax1ByteMetaTableCapacity| and
422 // |kMax2ByteMetaTableCapacity| in the .cc file for an explanation of these
423 // constants.
424 int capacity = Capacity();
425 ByteArray meta_table = this->meta_table();
426 if (capacity <= kMax1ByteMetaTableCapacity) {
427 return GetMetaTableField<uint8_t>(meta_table, field_index);
428 } else if (capacity <= kMax2ByteMetaTableCapacity) {
429 return GetMetaTableField<uint16_t>(meta_table, field_index);
430 } else {
431 return GetMetaTableField<uint32_t>(meta_table, field_index);
432 }
433}
434
435// static
436template <typename T>
437void SwissNameDictionary::SetMetaTableField(ByteArray meta_table,
438 int field_index, int value) {
439 STATIC_ASSERT((std::is_same<T, uint8_t>::value) ||static_assert((std::is_same<T, uint8_t>::value) || (std
::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t
>::value), "(std::is_same<T, uint8_t>::value) || (std::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t>::value)"
)
440 (std::is_same<T, uint16_t>::value) ||static_assert((std::is_same<T, uint8_t>::value) || (std
::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t
>::value), "(std::is_same<T, uint8_t>::value) || (std::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t>::value)"
)
441 (std::is_same<T, uint32_t>::value))static_assert((std::is_same<T, uint8_t>::value) || (std
::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t
>::value), "(std::is_same<T, uint8_t>::value) || (std::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t>::value)"
)
;
442 DCHECK_LE(value, std::numeric_limits<T>::max())((void) 0);
443 DCHECK_LT(meta_table.GetDataStartAddress() + field_index * sizeof(T),((void) 0)
444 meta_table.GetDataEndAddress())((void) 0);
445 T* raw_data = reinterpret_cast<T*>(meta_table.GetDataStartAddress());
446 raw_data[field_index] = value;
447}
448
449// static
450template <typename T>
451int SwissNameDictionary::GetMetaTableField(ByteArray meta_table,
452 int field_index) {
453 STATIC_ASSERT((std::is_same<T, uint8_t>::value) ||static_assert((std::is_same<T, uint8_t>::value) || (std
::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t
>::value), "(std::is_same<T, uint8_t>::value) || (std::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t>::value)"
)
454 (std::is_same<T, uint16_t>::value) ||static_assert((std::is_same<T, uint8_t>::value) || (std
::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t
>::value), "(std::is_same<T, uint8_t>::value) || (std::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t>::value)"
)
455 (std::is_same<T, uint32_t>::value))static_assert((std::is_same<T, uint8_t>::value) || (std
::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t
>::value), "(std::is_same<T, uint8_t>::value) || (std::is_same<T, uint16_t>::value) || (std::is_same<T, uint32_t>::value)"
)
;
456 DCHECK_LT(meta_table.GetDataStartAddress() + field_index * sizeof(T),((void) 0)
457 meta_table.GetDataEndAddress())((void) 0);
458 T* raw_data = reinterpret_cast<T*>(meta_table.GetDataStartAddress());
459 return raw_data[field_index];
460}
461
462constexpr int SwissNameDictionary::MetaTableSizePerEntryFor(int capacity) {
463 DCHECK(IsValidCapacity(capacity))((void) 0);
464
465 // See the STATIC_ASSERTs on |kMax1ByteMetaTableCapacity| and
466 // |kMax2ByteMetaTableCapacity| in the .cc file for an explanation of these
467 // constants.
468 if (capacity <= kMax1ByteMetaTableCapacity) {
469 return sizeof(uint8_t);
470 } else if (capacity <= kMax2ByteMetaTableCapacity) {
471 return sizeof(uint16_t);
472 } else {
473 return sizeof(uint32_t);
474 }
475}
476
477constexpr int SwissNameDictionary::MetaTableSizeFor(int capacity) {
478 DCHECK(IsValidCapacity(capacity))((void) 0);
479
480 int per_entry_size = MetaTableSizePerEntryFor(capacity);
481
482 // The enumeration table only needs to have as many slots as there can be
483 // present + deleted entries in the hash table (= maximum load factor *
484 // capactiy). Two more slots to store the number of present and deleted
485 // entries.
486 return per_entry_size * (MaxUsableCapacity(capacity) + 2);
487}
488
489bool SwissNameDictionary::IsKey(ReadOnlyRoots roots, Object key_candidate) {
490 return key_candidate != roots.the_hole_value();
491}
492
493bool SwissNameDictionary::ToKey(ReadOnlyRoots roots, int entry,
494 Object* out_key) {
495 Object k = KeyAt(entry);
496 if (!IsKey(roots, k)) return false;
497 *out_key = k;
498 return true;
499}
500
501bool SwissNameDictionary::ToKey(ReadOnlyRoots roots, InternalIndex entry,
502 Object* out_key) {
503 return ToKey(roots, entry.as_int(), out_key);
504}
505
506// static
507template <typename IsolateT>
508Handle<SwissNameDictionary> SwissNameDictionary::Add(
509 IsolateT* isolate, Handle<SwissNameDictionary> original_table,
510 Handle<Name> key, Handle<Object> value, PropertyDetails details,
511 InternalIndex* entry_out) {
512 DCHECK(original_table->FindEntry(isolate, *key).is_not_found())((void) 0);
513
514 Handle<SwissNameDictionary> table = EnsureGrowable(isolate, original_table);
515
516 int nof = table->NumberOfElements();
517 int nod = table->NumberOfDeletedElements();
518 int new_enum_index = nof + nod;
519
520 int new_entry = table->AddInternal(*key, *value, details);
521
522 table->SetNumberOfElements(nof + 1);
523 table->SetEntryForEnumerationIndex(new_enum_index, new_entry);
524
525 if (entry_out) {
526 *entry_out = InternalIndex(new_entry);
527 }
528
529 return table;
530}
531
532int SwissNameDictionary::AddInternal(Name key, Object value,
533 PropertyDetails details) {
534 DisallowHeapAllocation no_gc;
535
536 DCHECK(key.IsUniqueName())((void) 0);
537 DCHECK_LE(UsedCapacity(), MaxUsableCapacity(Capacity()))((void) 0);
538
539 uint32_t hash = key.hash();
540
541 // For now we don't re-use deleted buckets (due to enumeration table
542 // complications), which is why we only look for empty buckets here, not
543 // deleted ones.
544 int target = FindFirstEmpty(hash);
545
546 SetCtrl(target, swiss_table::H2(hash));
547 SetKey(target, key);
548 ValueAtPut(target, value);
549 DetailsAtPut(target, details);
550
551 // Note that we do not update the number of elements or the enumeration table
552 // in this function.
553
554 return target;
555}
556
557template <typename IsolateT>
558void SwissNameDictionary::Initialize(IsolateT* isolate, ByteArray meta_table,
559 int capacity) {
560 DCHECK(IsValidCapacity(capacity))((void) 0);
561 DisallowHeapAllocation no_gc;
562 ReadOnlyRoots roots(isolate);
563
564 SetCapacity(capacity);
565 SetHash(PropertyArray::kNoHashSentinel);
566
567 memset(CtrlTable(), Ctrl::kEmpty, CtrlTableSize(capacity));
568
569 MemsetTagged(RawField(DataTableStartOffset()), roots.the_hole_value(),
570 capacity * kDataTableEntryCount);
571
572 set_meta_table(meta_table);
573
574 SetNumberOfElements(0);
575 SetNumberOfDeletedElements(0);
576
577 // We leave the enumeration table PropertyDetails table and uninitialized.
578}
579
580SwissNameDictionary::IndexIterator::IndexIterator(
581 Handle<SwissNameDictionary> dict, int start)
582 : enum_index_{start}, dict_{dict} {
583 if (!COMPRESS_POINTERS_IN_ISOLATE_CAGE_BOOLfalse && dict.is_null()) {
584 used_capacity_ = 0;
585 } else {
586 used_capacity_ = dict->UsedCapacity();
587 }
588}
589
590SwissNameDictionary::IndexIterator&
591SwissNameDictionary::IndexIterator::operator++() {
592 DCHECK_LT(enum_index_, used_capacity_)((void) 0);
593 ++enum_index_;
594 return *this;
595}
596
597bool SwissNameDictionary::IndexIterator::operator==(
598 const SwissNameDictionary::IndexIterator& b) const {
599 DCHECK_LE(enum_index_, used_capacity_)((void) 0);
600 DCHECK_LE(b.enum_index_, used_capacity_)((void) 0);
601 DCHECK(dict_.equals(b.dict_))((void) 0);
602
603 return this->enum_index_ == b.enum_index_;
604}
605
606bool SwissNameDictionary::IndexIterator::operator!=(
607 const IndexIterator& b) const {
608 return !(*this == b);
609}
610
611InternalIndex SwissNameDictionary::IndexIterator::operator*() {
612 DCHECK_LE(enum_index_, used_capacity_)((void) 0);
613
614 if (enum_index_ == used_capacity_) return InternalIndex::NotFound();
615
616 return InternalIndex(dict_->EntryForEnumerationIndex(enum_index_));
617}
618
619SwissNameDictionary::IndexIterable::IndexIterable(
620 Handle<SwissNameDictionary> dict)
621 : dict_{dict} {}
622
623SwissNameDictionary::IndexIterator SwissNameDictionary::IndexIterable::begin() {
624 return IndexIterator(dict_, 0);
625}
626
627SwissNameDictionary::IndexIterator SwissNameDictionary::IndexIterable::end() {
628 if (!COMPRESS_POINTERS_IN_ISOLATE_CAGE_BOOLfalse && dict_.is_null()) {
629 return IndexIterator(dict_, 0);
630 } else {
631 DCHECK(!dict_.is_null())((void) 0);
632 return IndexIterator(dict_, dict_->UsedCapacity());
633 }
634}
635
636SwissNameDictionary::IndexIterable
637SwissNameDictionary::IterateEntriesOrdered() {
638 // If we are supposed to iterate the empty dictionary (which is non-writable)
639 // and pointer compression with a per-Isolate cage is disabled, we have no
640 // simple way to get the isolate, which we would need to create a handle.
641 // TODO(emrich): Consider always using roots.empty_swiss_dictionary_handle()
642 // in the condition once this function gets Isolate as a parameter in order to
643 // avoid empty dict checks.
644 if (!COMPRESS_POINTERS_IN_ISOLATE_CAGE_BOOLfalse && Capacity() == 0)
5
Assuming the condition is false
6
Taking false branch
645 return IndexIterable(Handle<SwissNameDictionary>::null());
646
647 Isolate* isolate;
648 GetIsolateFromHeapObject(*this, &isolate);
7
Calling 'GetIsolateFromHeapObject'
11
Returning from 'GetIsolateFromHeapObject'
649 DCHECK_NE(isolate, nullptr)((void) 0);
650 return IndexIterable(handle(*this, isolate));
12
Passing null pointer value via 2nd parameter 'isolate'
13
Calling 'handle<v8::internal::SwissNameDictionary>'
651}
652
653SwissNameDictionary::IndexIterable SwissNameDictionary::IterateEntries() {
654 return IterateEntriesOrdered();
4
Calling 'SwissNameDictionary::IterateEntriesOrdered'
655}
656
657void SwissNameDictionary::SetHash(int32_t hash) {
658 WriteField(PrefixOffset(), hash);
659}
660
661int SwissNameDictionary::Hash() { return ReadField<int32_t>(PrefixOffset()); }
662
663// static
664constexpr int SwissNameDictionary::MaxCapacity() {
665 int const_size =
666 DataTableStartOffset() + ByteArray::kHeaderSize +
667 // Size for present and deleted element count at max capacity:
668 2 * sizeof(uint32_t);
669 int per_entry_size =
670 // size of data table entries:
671 kDataTableEntryCount * kTaggedSize +
672 // ctrl table entry size:
673 kOneByteSize +
674 // PropertyDetails table entry size:
675 kOneByteSize +
676 // Enumeration table entry size at maximum capacity:
677 sizeof(uint32_t);
678
679 int result = (FixedArray::kMaxSize - const_size) / per_entry_size;
680 DCHECK_GE(Smi::kMaxValue, result)((void) 0);
681
682 return result;
683}
684
685// static
686constexpr int SwissNameDictionary::PrefixOffset() {
687 return HeapObject::kHeaderSize;
688}
689
690// static
691constexpr int SwissNameDictionary::CapacityOffset() {
692 return PrefixOffset() + sizeof(uint32_t);
693}
694
695// static
696constexpr int SwissNameDictionary::MetaTablePointerOffset() {
697 return CapacityOffset() + sizeof(int32_t);
698}
699
700// static
701constexpr int SwissNameDictionary::DataTableStartOffset() {
702 return MetaTablePointerOffset() + kTaggedSize;
703}
704
705// static
706constexpr int SwissNameDictionary::DataTableEndOffset(int capacity) {
707 return CtrlTableStartOffset(capacity);
708}
709
710// static
711constexpr int SwissNameDictionary::CtrlTableStartOffset(int capacity) {
712 return DataTableStartOffset() + DataTableSize(capacity);
713}
714
715// static
716constexpr int SwissNameDictionary::PropertyDetailsTableStartOffset(
717 int capacity) {
718 return CtrlTableStartOffset(capacity) + CtrlTableSize(capacity);
719}
720
721// static
722bool SwissNameDictionary::IsEmpty(ctrl_t c) { return c == Ctrl::kEmpty; }
723
724// static
725bool SwissNameDictionary::IsFull(ctrl_t c) {
726 STATIC_ASSERT(Ctrl::kEmpty < 0)static_assert(Ctrl::kEmpty < 0, "Ctrl::kEmpty < 0");
727 STATIC_ASSERT(Ctrl::kDeleted < 0)static_assert(Ctrl::kDeleted < 0, "Ctrl::kDeleted < 0");
728 STATIC_ASSERT(Ctrl::kSentinel < 0)static_assert(Ctrl::kSentinel < 0, "Ctrl::kSentinel < 0"
)
;
729 return c >= 0;
730}
731
732// static
733bool SwissNameDictionary::IsDeleted(ctrl_t c) { return c == Ctrl::kDeleted; }
734
735// static
736bool SwissNameDictionary::IsEmptyOrDeleted(ctrl_t c) {
737 STATIC_ASSERT(Ctrl::kDeleted < Ctrl::kSentinel)static_assert(Ctrl::kDeleted < Ctrl::kSentinel, "Ctrl::kDeleted < Ctrl::kSentinel"
)
;
738 STATIC_ASSERT(Ctrl::kEmpty < Ctrl::kSentinel)static_assert(Ctrl::kEmpty < Ctrl::kSentinel, "Ctrl::kEmpty < Ctrl::kSentinel"
)
;
739 STATIC_ASSERT(Ctrl::kSentinel < 0)static_assert(Ctrl::kSentinel < 0, "Ctrl::kSentinel < 0"
)
;
740 return c < Ctrl::kSentinel;
741}
742
743// static
744swiss_table::ProbeSequence<SwissNameDictionary::kGroupWidth>
745SwissNameDictionary::probe(uint32_t hash, int capacity) {
746 // If |capacity| is 0, we must produce 1 here, such that the - 1 below
747 // yields 0, which is the correct modulo mask for a table of capacity 0.
748 int non_zero_capacity = capacity | (capacity == 0);
749 return swiss_table::ProbeSequence<SwissNameDictionary::kGroupWidth>(
750 swiss_table::H1(hash), static_cast<uint32_t>(non_zero_capacity - 1));
751}
752
753ACCESSORS_CHECKED2(SwissNameDictionary, meta_table, ByteArray,
754 MetaTablePointerOffset(), true,
755 value.length() >= kMetaTableEnumerationDataStartIndex)
756
757} // namespace internal
758} // namespace v8
759
760#endif // V8_OBJECTS_SWISS_NAME_DICTIONARY_INL_H_

../deps/v8/src/execution/isolate-utils-inl.h

1// Copyright 2019 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#ifndef V8_EXECUTION_ISOLATE_UTILS_INL_H_
6#define V8_EXECUTION_ISOLATE_UTILS_INL_H_
7
8#include "src/common/ptr-compr-inl.h"
9#include "src/execution/isolate-utils.h"
10#include "src/execution/isolate.h"
11#include "src/heap/heap-write-barrier-inl.h"
12
13namespace v8 {
14namespace internal {
15
16#ifdef V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE
17
18// Aliases for GetPtrComprCageBase when
19// V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE. Each Isolate has its own cage, whose
20// base address is also the Isolate root.
21V8_INLINEinline __attribute__((always_inline)) constexpr Address GetIsolateRootAddress(Address on_heap_addr) {
22 return GetPtrComprCageBaseAddress(on_heap_addr);
23}
24
25V8_INLINEinline __attribute__((always_inline)) Address GetIsolateRootAddress(PtrComprCageBase cage_base) {
26 return cage_base.address();
27}
28
29#else
30
31V8_INLINEinline __attribute__((always_inline)) Address GetIsolateRootAddress(Address on_heap_addr) { UNREACHABLE()V8_Fatal("unreachable code"); }
32
33V8_INLINEinline __attribute__((always_inline)) Address GetIsolateRootAddress(PtrComprCageBase cage_base) {
34 UNREACHABLE()V8_Fatal("unreachable code");
35}
36
37#endif // V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE
38
39V8_INLINEinline __attribute__((always_inline)) Heap* GetHeapFromWritableObject(HeapObject object) {
40 // Avoid using the below GetIsolateFromWritableObject because we want to be
41 // able to get the heap, but not the isolate, for off-thread objects.
42
43#if defined V8_ENABLE_THIRD_PARTY_HEAP
44 return Heap::GetIsolateFromWritableObject(object)->heap();
45#elif defined(V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE) && \
46 !defined(V8_EXTERNAL_CODE_SPACE)
47 Isolate* isolate =
48 Isolate::FromRootAddress(GetIsolateRootAddress(object.ptr()));
49 DCHECK_NOT_NULL(isolate)((void) 0);
50 return isolate->heap();
51#else
52 heap_internals::MemoryChunk* chunk =
53 heap_internals::MemoryChunk::FromHeapObject(object);
54 return chunk->GetHeap();
55#endif // V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE, V8_ENABLE_THIRD_PARTY_HEAP
56}
57
58V8_INLINEinline __attribute__((always_inline)) Isolate* GetIsolateFromWritableObject(HeapObject object) {
59#ifdef V8_ENABLE_THIRD_PARTY_HEAP
60 return Heap::GetIsolateFromWritableObject(object);
61#elif defined(V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE) && \
62 !defined(V8_EXTERNAL_CODE_SPACE)
63 Isolate* isolate =
64 Isolate::FromRootAddress(GetIsolateRootAddress(object.ptr()));
65 DCHECK_NOT_NULL(isolate)((void) 0);
66 return isolate;
67#else
68 return Isolate::FromHeap(GetHeapFromWritableObject(object));
69#endif // V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE, V8_ENABLE_THIRD_PARTY_HEAP
70}
71
72V8_INLINEinline __attribute__((always_inline)) bool GetIsolateFromHeapObject(HeapObject object, Isolate** isolate) {
73#ifdef V8_ENABLE_THIRD_PARTY_HEAP
74 *isolate = Heap::GetIsolateFromWritableObject(object);
75 return true;
76#elif defined V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE
77 *isolate = GetIsolateFromWritableObject(object);
78 return true;
79#else
80 heap_internals::MemoryChunk* chunk =
81 heap_internals::MemoryChunk::FromHeapObject(object);
82 if (chunk->InReadOnlySpace()) {
8
Assuming the condition is true
9
Taking true branch
83 *isolate = nullptr;
10
Null pointer value stored to 'isolate'
84 return false;
85 }
86 *isolate = Isolate::FromHeap(chunk->GetHeap());
87 return true;
88#endif // V8_COMPRESS_POINTERS_IN_ISOLATE_CAGE, V8_ENABLE_THIRD_PARTY_HEAP
89}
90
91// Use this function instead of Internals::GetIsolateForSandbox for internal
92// code, as this function is fully inlinable.
93V8_INLINEinline __attribute__((always_inline)) static Isolate* GetIsolateForSandbox(HeapObject object) {
94#ifdef V8_SANDBOXED_EXTERNAL_POINTERS
95 return GetIsolateFromWritableObject(object);
96#else
97 // Not used in non-sandbox mode.
98 return nullptr;
99#endif
100}
101
102// This is an external code space friendly version of GetPtrComprCageBase(..)
103// which also works for objects located in external code space.
104//
105// NOTE: it's supposed to be used only for the cases where performance doesn't
106// matter. For example, in debug only code or in debugging macros.
107// In production code the preferred way is to use precomputed cage base value
108// which is a result of PtrComprCageBase{isolate} or GetPtrComprCageBase()
109// applied to a heap object which is known to not be a part of external code
110// space.
111V8_INLINEinline __attribute__((always_inline)) PtrComprCageBase GetPtrComprCageBaseSlow(HeapObject object) {
112 if (V8_EXTERNAL_CODE_SPACE_BOOLfalse) {
113 Isolate* isolate;
114 if (GetIsolateFromHeapObject(object, &isolate)) {
115 return PtrComprCageBase{isolate};
116 }
117 // If the Isolate can't be obtained then the heap object is a read-only
118 // one and therefore not a Code object, so fallback to auto-computing cage
119 // base value.
120 }
121 return GetPtrComprCageBase(object);
122}
123
124} // namespace internal
125} // namespace v8
126
127#endif // V8_EXECUTION_ISOLATE_UTILS_INL_H_

../deps/v8/src/handles/handles-inl.h

1// Copyright 2006-2008 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#ifndef V8_HANDLES_HANDLES_INL_H_
6#define V8_HANDLES_HANDLES_INL_H_
7
8#include "src/base/sanitizer/msan.h"
9#include "src/execution/isolate.h"
10#include "src/execution/local-isolate.h"
11#include "src/handles/handles.h"
12#include "src/handles/local-handles-inl.h"
13#include "src/objects/objects.h"
14
15namespace v8 {
16namespace internal {
17
18class LocalHeap;
19
20HandleBase::HandleBase(Address object, Isolate* isolate)
21 : location_(HandleScope::GetHandle(isolate, object)) {}
18
Passing null pointer value via 1st parameter 'isolate'
19
Calling 'HandleScope::GetHandle'
22
23HandleBase::HandleBase(Address object, LocalIsolate* isolate)
24 : location_(LocalHandleScope::GetHandle(isolate->heap(), object)) {}
25
26HandleBase::HandleBase(Address object, LocalHeap* local_heap)
27 : location_(LocalHandleScope::GetHandle(local_heap, object)) {}
28
29bool HandleBase::is_identical_to(const HandleBase that) const {
30 SLOW_DCHECK((this->location_ == nullptr || this->IsDereferenceAllowed()) &&((void)0)
31 (that.location_ == nullptr || that.IsDereferenceAllowed()))((void)0);
32 if (this->location_ == that.location_) return true;
33 if (this->location_ == nullptr || that.location_ == nullptr) return false;
34 return Object(*this->location_) == Object(*that.location_);
35}
36
37// Allocate a new handle for the object, do not canonicalize.
38template <typename T>
39Handle<T> Handle<T>::New(T object, Isolate* isolate) {
40 return Handle(HandleScope::CreateHandle(isolate, object.ptr()));
41}
42
43template <typename T>
44template <typename S>
45const Handle<T> Handle<T>::cast(Handle<S> that) {
46 T::cast(*FullObjectSlot(that.location()));
47 return Handle<T>(that.location_);
48}
49
50template <typename T>
51Handle<T>::Handle(T object, Isolate* isolate)
52 : HandleBase(object.ptr(), isolate) {}
16
Passing null pointer value via 2nd parameter 'isolate'
17
Calling constructor for 'HandleBase'
53
54template <typename T>
55Handle<T>::Handle(T object, LocalIsolate* isolate)
56 : HandleBase(object.ptr(), isolate) {}
57
58template <typename T>
59Handle<T>::Handle(T object, LocalHeap* local_heap)
60 : HandleBase(object.ptr(), local_heap) {}
61
62template <typename T>
63V8_INLINEinline __attribute__((always_inline)) Handle<T> handle(T object, Isolate* isolate) {
64 return Handle<T>(object, isolate);
14
Passing null pointer value via 2nd parameter 'isolate'
15
Calling constructor for 'Handle<v8::internal::SwissNameDictionary>'
65}
66
67template <typename T>
68V8_INLINEinline __attribute__((always_inline)) Handle<T> handle(T object, LocalIsolate* isolate) {
69 return Handle<T>(object, isolate);
70}
71
72template <typename T>
73V8_INLINEinline __attribute__((always_inline)) Handle<T> handle(T object, LocalHeap* local_heap) {
74 return Handle<T>(object, local_heap);
75}
76
77template <typename T>
78inline std::ostream& operator<<(std::ostream& os, Handle<T> handle) {
79 return os << Brief(*handle);
80}
81
82HandleScope::HandleScope(Isolate* isolate) {
83 HandleScopeData* data = isolate->handle_scope_data();
84 isolate_ = isolate;
85 prev_next_ = data->next;
86 prev_limit_ = data->limit;
87 data->level++;
88}
89
90HandleScope::HandleScope(HandleScope&& other) V8_NOEXCEPTnoexcept
91 : isolate_(other.isolate_),
92 prev_next_(other.prev_next_),
93 prev_limit_(other.prev_limit_) {
94 other.isolate_ = nullptr;
95}
96
97HandleScope::~HandleScope() {
98 if (V8_UNLIKELY(isolate_ == nullptr)(__builtin_expect(!!(isolate_ == nullptr), 0))) return;
99 CloseScope(isolate_, prev_next_, prev_limit_);
100}
101
102HandleScope& HandleScope::operator=(HandleScope&& other) V8_NOEXCEPTnoexcept {
103 if (isolate_ == nullptr) {
104 isolate_ = other.isolate_;
105 } else {
106 DCHECK_EQ(isolate_, other.isolate_)((void) 0);
107 CloseScope(isolate_, prev_next_, prev_limit_);
108 }
109 prev_next_ = other.prev_next_;
110 prev_limit_ = other.prev_limit_;
111 other.isolate_ = nullptr;
112 return *this;
113}
114
115void HandleScope::CloseScope(Isolate* isolate, Address* prev_next,
116 Address* prev_limit) {
117#ifdef DEBUG
118 int before = FLAG_check_handle_count ? NumberOfHandles(isolate) : 0;
119#endif
120 DCHECK_NOT_NULL(isolate)((void) 0);
121 HandleScopeData* current = isolate->handle_scope_data();
122
123 std::swap(current->next, prev_next);
124 current->level--;
125 Address* limit = prev_next;
126 if (V8_UNLIKELY(current->limit != prev_limit)(__builtin_expect(!!(current->limit != prev_limit), 0))) {
127 current->limit = prev_limit;
128 limit = prev_limit;
129 DeleteExtensions(isolate);
130 }
131#ifdef ENABLE_HANDLE_ZAPPING
132 ZapRange(current->next, limit);
133#endif
134 MSAN_ALLOCATED_UNINITIALIZED_MEMORY(static_assert((std::is_pointer<decltype(current->next)>
::value || std::is_same<v8::base::Address, decltype(current
->next)>::value), "static type violation"); static_assert
(std::is_convertible<decltype(static_cast<size_t>(reinterpret_cast
<Address>(limit) - reinterpret_cast<Address>(current
->next))), size_t>::value, "static type violation"); do
{ ::v8::base::Use unused_tmp_array_for_use_macro[]{current->
next, static_cast<size_t>(reinterpret_cast<Address>
(limit) - reinterpret_cast<Address>(current->next))}
; (void)unused_tmp_array_for_use_macro; } while (false)
135 current->next,static_assert((std::is_pointer<decltype(current->next)>
::value || std::is_same<v8::base::Address, decltype(current
->next)>::value), "static type violation"); static_assert
(std::is_convertible<decltype(static_cast<size_t>(reinterpret_cast
<Address>(limit) - reinterpret_cast<Address>(current
->next))), size_t>::value, "static type violation"); do
{ ::v8::base::Use unused_tmp_array_for_use_macro[]{current->
next, static_cast<size_t>(reinterpret_cast<Address>
(limit) - reinterpret_cast<Address>(current->next))}
; (void)unused_tmp_array_for_use_macro; } while (false)
136 static_cast<size_t>(reinterpret_cast<Address>(limit) -static_assert((std::is_pointer<decltype(current->next)>
::value || std::is_same<v8::base::Address, decltype(current
->next)>::value), "static type violation"); static_assert
(std::is_convertible<decltype(static_cast<size_t>(reinterpret_cast
<Address>(limit) - reinterpret_cast<Address>(current
->next))), size_t>::value, "static type violation"); do
{ ::v8::base::Use unused_tmp_array_for_use_macro[]{current->
next, static_cast<size_t>(reinterpret_cast<Address>
(limit) - reinterpret_cast<Address>(current->next))}
; (void)unused_tmp_array_for_use_macro; } while (false)
137 reinterpret_cast<Address>(current->next)))static_assert((std::is_pointer<decltype(current->next)>
::value || std::is_same<v8::base::Address, decltype(current
->next)>::value), "static type violation"); static_assert
(std::is_convertible<decltype(static_cast<size_t>(reinterpret_cast
<Address>(limit) - reinterpret_cast<Address>(current
->next))), size_t>::value, "static type violation"); do
{ ::v8::base::Use unused_tmp_array_for_use_macro[]{current->
next, static_cast<size_t>(reinterpret_cast<Address>
(limit) - reinterpret_cast<Address>(current->next))}
; (void)unused_tmp_array_for_use_macro; } while (false)
;
138#ifdef DEBUG
139 int after = FLAG_check_handle_count ? NumberOfHandles(isolate) : 0;
140 DCHECK_LT(after - before, kCheckHandleThreshold)((void) 0);
141 DCHECK_LT(before, kCheckHandleThreshold)((void) 0);
142#endif
143}
144
145template <typename T>
146Handle<T> HandleScope::CloseAndEscape(Handle<T> handle_value) {
147 HandleScopeData* current = isolate_->handle_scope_data();
148 T value = *handle_value;
149 // Throw away all handles in the current scope.
150 CloseScope(isolate_, prev_next_, prev_limit_);
151 // Allocate one handle in the parent scope.
152 DCHECK(current->level > current->sealed_level)((void) 0);
153 Handle<T> result(value, isolate_);
154 // Reinitialize the current scope (so that it's ready
155 // to be used or closed again).
156 prev_next_ = current->next;
157 prev_limit_ = current->limit;
158 current->level++;
159 return result;
160}
161
162Address* HandleScope::CreateHandle(Isolate* isolate, Address value) {
163 DCHECK(AllowHandleAllocation::IsAllowed())((void) 0);
164 HandleScopeData* data = isolate->handle_scope_data();
165 Address* result = data->next;
166 if (result == data->limit) {
167 result = Extend(isolate);
168 }
169 // Update the current next field, set the value in the created handle,
170 // and return the result.
171 DCHECK_LT(reinterpret_cast<Address>(result),((void) 0)
172 reinterpret_cast<Address>(data->limit))((void) 0);
173 data->next = reinterpret_cast<Address*>(reinterpret_cast<Address>(result) +
174 sizeof(Address));
175 *result = value;
176 return result;
177}
178
179Address* HandleScope::GetHandle(Isolate* isolate, Address value) {
180 DCHECK(AllowHandleAllocation::IsAllowed())((void) 0);
181 DCHECK(isolate->main_thread_local_heap()->IsRunning())((void) 0);
182 DCHECK_WITH_MSG(isolate->thread_id() == ThreadId::Current(),void(0);
183 "main-thread handle can only be created on the main thread.")void(0);;
184 HandleScopeData* data = isolate->handle_scope_data();
20
Called C++ object pointer is null
185 CanonicalHandleScope* canonical = data->canonical_scope;
186 return canonical ? canonical->Lookup(value) : CreateHandle(isolate, value);
187}
188
189#ifdef DEBUG
190inline SealHandleScope::SealHandleScope(Isolate* isolate) : isolate_(isolate) {
191 // Make sure the current thread is allowed to create handles to begin with.
192 DCHECK(AllowHandleAllocation::IsAllowed())((void) 0);
193 HandleScopeData* current = isolate_->handle_scope_data();
194 // Shrink the current handle scope to make it impossible to do
195 // handle allocations without an explicit handle scope.
196 prev_limit_ = current->limit;
197 current->limit = current->next;
198 prev_sealed_level_ = current->sealed_level;
199 current->sealed_level = current->level;
200}
201
202inline SealHandleScope::~SealHandleScope() {
203 // Restore state in current handle scope to re-enable handle
204 // allocations.
205 HandleScopeData* current = isolate_->handle_scope_data();
206 DCHECK_EQ(current->next, current->limit)((void) 0);
207 current->limit = prev_limit_;
208 DCHECK_EQ(current->level, current->sealed_level)((void) 0);
209 current->sealed_level = prev_sealed_level_;
210}
211
212#endif
213
214} // namespace internal
215} // namespace v8
216
217#endif // V8_HANDLES_HANDLES_INL_H_