chromium/v8/src/profiler/heap-snapshot-generator.cc

// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/profiler/heap-snapshot-generator.h"

#include <optional>
#include <utility>

#include "src/api/api-inl.h"
#include "src/base/vector.h"
#include "src/codegen/assembler-inl.h"
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
#include "src/debug/debug.h"
#include "src/handles/global-handles.h"
#include "src/heap/combined-heap.h"
#include "src/heap/heap.h"
#include "src/heap/safepoint.h"
#include "src/numbers/conversions.h"
#include "src/objects/allocation-site-inl.h"
#include "src/objects/api-callbacks.h"
#include "src/objects/cell-inl.h"
#include "src/objects/feedback-cell-inl.h"
#include "src/objects/hash-table-inl.h"
#include "src/objects/js-array-buffer-inl.h"
#include "src/objects/js-array-inl.h"
#include "src/objects/js-collection-inl.h"
#include "src/objects/js-generator-inl.h"
#include "src/objects/js-objects.h"
#include "src/objects/js-promise-inl.h"
#include "src/objects/js-regexp-inl.h"
#include "src/objects/js-weak-refs-inl.h"
#include "src/objects/literal-objects-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/prototype.h"
#include "src/objects/slots-inl.h"
#include "src/objects/struct-inl.h"
#include "src/objects/transitions-inl.h"
#include "src/objects/visitors.h"
#include "src/profiler/allocation-tracker.h"
#include "src/profiler/heap-profiler.h"
#include "src/profiler/heap-snapshot-generator-inl.h"
#include "src/profiler/output-stream-writer.h"

#if V8_ENABLE_WEBASSEMBLY
#include "src/wasm/names-provider.h"
#include "src/wasm/string-builder.h"
#include "src/wasm/wasm-objects.h"
#endif  // V8_ENABLE_WEBASSEMBLY

namespace v8::internal {

#ifdef V8_ENABLE_HEAP_SNAPSHOT_VERIFY
class HeapEntryVerifier {};
#endif

HeapGraphEdge::HeapGraphEdge(Type type, const char* name, HeapEntry* from,
                             HeapEntry* to)
    :{}

HeapGraphEdge::HeapGraphEdge(Type type, int index, HeapEntry* from,
                             HeapEntry* to)
    :{}

HeapEntry::HeapEntry(HeapSnapshot* snapshot, int index, Type type,
                     const char* name, SnapshotObjectId id, size_t self_size,
                     unsigned trace_node_id)
    :{}

void HeapEntry::VerifyReference(HeapGraphEdge::Type type, HeapEntry* entry,
                                HeapSnapshotGenerator* generator,
                                ReferenceVerification verification) {}

void HeapEntry::SetNamedReference(HeapGraphEdge::Type type, const char* name,
                                  HeapEntry* entry,
                                  HeapSnapshotGenerator* generator,
                                  ReferenceVerification verification) {}

void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type, int index,
                                    HeapEntry* entry,
                                    HeapSnapshotGenerator* generator,
                                    ReferenceVerification verification) {}

void HeapEntry::SetNamedAutoIndexReference(HeapGraphEdge::Type type,
                                           const char* description,
                                           HeapEntry* child,
                                           StringsStorage* names,
                                           HeapSnapshotGenerator* generator,
                                           ReferenceVerification verification) {}

void HeapEntry::Print(const char* prefix, const char* edge_name, int max_depth,
                      int indent) const {}

const char* HeapEntry::TypeAsString() const {}

HeapSnapshot::HeapSnapshot(HeapProfiler* profiler,
                           v8::HeapProfiler::HeapSnapshotMode snapshot_mode,
                           v8::HeapProfiler::NumericsMode numerics_mode)
    :{}

void HeapSnapshot::Delete() {}

void HeapSnapshot::RememberLastJSObjectId() {}

void HeapSnapshot::AddSyntheticRootEntries() {}

void HeapSnapshot::AddRootEntry() {}

void HeapSnapshot::AddGcRootsEntry() {}

void HeapSnapshot::AddGcSubrootEntry(Root root, SnapshotObjectId id) {}

void HeapSnapshot::AddLocation(HeapEntry* entry, int scriptId, int line,
                               int col) {}

HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type, const char* name,
                                  SnapshotObjectId id, size_t size,
                                  unsigned trace_node_id) {}

void HeapSnapshot::AddScriptLineEnds(int script_id,
                                     String::LineEndsVector&& line_ends) {}

String::LineEndsVector& HeapSnapshot::GetScriptLineEnds(int script_id) {}

void HeapSnapshot::FillChildren() {}

HeapEntry* HeapSnapshot::GetEntryById(SnapshotObjectId id) {}

void HeapSnapshot::Print(int max_depth) {}

// We split IDs on evens for embedder objects (see
// HeapObjectsMap::GenerateId) and odds for native objects.
const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId =;
const SnapshotObjectId HeapObjectsMap::kGcRootsObjectId =;
const SnapshotObjectId HeapObjectsMap::kGcRootsFirstSubrootId =;
const SnapshotObjectId HeapObjectsMap::kFirstAvailableObjectId =;
const SnapshotObjectId HeapObjectsMap::kFirstAvailableNativeId =;

HeapObjectsMap::HeapObjectsMap(Heap* heap)
    :{}

bool HeapObjectsMap::MoveObject(Address from, Address to, int object_size) {}

void HeapObjectsMap::UpdateObjectSize(Address addr, int size) {}

SnapshotObjectId HeapObjectsMap::FindEntry(Address addr) {}

SnapshotObjectId HeapObjectsMap::FindOrAddEntry(
    Address addr, unsigned int size, MarkEntryAccessed accessed,
    IsNativeObject is_native_object) {}

SnapshotObjectId HeapObjectsMap::FindMergedNativeEntry(NativeObject addr) {}

void HeapObjectsMap::AddMergedNativeEntry(NativeObject addr,
                                          Address canonical_addr) {}

void HeapObjectsMap::StopHeapObjectsTracking() {}

void HeapObjectsMap::UpdateHeapObjectsMap() {}

SnapshotObjectId HeapObjectsMap::PushHeapObjectsStats(OutputStream* stream,
                                                      int64_t* timestamp_us) {}

void HeapObjectsMap::RemoveDeadEntries() {}

V8HeapExplorer::V8HeapExplorer(HeapSnapshot* snapshot,
                               SnapshottingProgressReportingInterface* progress,
                               v8::HeapProfiler::ObjectNameResolver* resolver)
    :{}

HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) {}

HeapEntry* V8HeapExplorer::AllocateEntry(Tagged<Smi> smi) {}

Tagged<JSFunction> V8HeapExplorer::GetLocationFunction(
    Tagged<HeapObject> object) {}

void V8HeapExplorer::ExtractLocation(HeapEntry* entry,
                                     Tagged<HeapObject> object) {}

void V8HeapExplorer::ExtractLocationForJSFunction(HeapEntry* entry,
                                                  Tagged<JSFunction> func) {}

namespace {
// Templatized struct to statically generate the string "system / Managed<Foo>"
// from "kFooTag".
template <const char kTagNameCStr[]>
struct ManagedName {};

// A little inline test:
constexpr const char kTagNameForTesting[] =;
static_assert(std::string_view{
                  ManagedName<kTagNameForTesting>::str_arr.data()} ==
              std::string_view{"system / Managed<Foo>"});
}  // namespace

HeapEntry* V8HeapExplorer::AddEntry(Tagged<HeapObject> object) {}

HeapEntry* V8HeapExplorer::AddEntry(Tagged<HeapObject> object,
                                    HeapEntry::Type type, const char* name) {}

HeapEntry* V8HeapExplorer::AddEntry(Address address, HeapEntry::Type type,
                                    const char* name, size_t size) {}

const char* V8HeapExplorer::GetSystemEntryName(Tagged<HeapObject> object) {}

HeapEntry::Type V8HeapExplorer::GetSystemEntryType(Tagged<HeapObject> object) {}

void V8HeapExplorer::PopulateLineEnds() {}

uint32_t V8HeapExplorer::EstimateObjectsCount() {}

#ifdef V8_TARGET_BIG_ENDIAN
namespace {
int AdjustEmbedderFieldIndex(Tagged<HeapObject> heap_obj, int field_index) {
  Tagged<Map> map = heap_obj->map();
  if (JSObject::MayHaveEmbedderFields(map)) {
    int emb_start_index = (JSObject::GetEmbedderFieldsStartOffset(map) +
                           EmbedderDataSlot::kTaggedPayloadOffset) /
                          kTaggedSize;
    int emb_field_count = JSObject::GetEmbedderFieldCount(map);
    int emb_end_index = emb_start_index + emb_field_count;
    if (base::IsInRange(field_index, emb_start_index, emb_end_index)) {
      return -EmbedderDataSlot::kTaggedPayloadOffset / kTaggedSize;
    }
  }
  return 0;
}
}  // namespace
#endif  // V8_TARGET_BIG_ENDIAN
class IndexedReferencesExtractor : public ObjectVisitorWithCageBases {};

void V8HeapExplorer::ExtractReferences(HeapEntry* entry,
                                       Tagged<HeapObject> obj) {}

void V8HeapExplorer::ExtractJSGlobalProxyReferences(
    HeapEntry* entry, Tagged<JSGlobalProxy> proxy) {}

void V8HeapExplorer::ExtractJSObjectReferences(HeapEntry* entry,
                                               Tagged<JSObject> js_obj) {}

void V8HeapExplorer::ExtractStringReferences(HeapEntry* entry,
                                             Tagged<String> string) {}

void V8HeapExplorer::ExtractSymbolReferences(HeapEntry* entry,
                                             Tagged<Symbol> symbol) {}

void V8HeapExplorer::ExtractJSCollectionReferences(
    HeapEntry* entry, Tagged<JSCollection> collection) {}

void V8HeapExplorer::ExtractJSWeakCollectionReferences(
    HeapEntry* entry, Tagged<JSWeakCollection> obj) {}

void V8HeapExplorer::ExtractEphemeronHashTableReferences(
    HeapEntry* entry, Tagged<EphemeronHashTable> table) {}

// These static arrays are used to prevent excessive code-size in
// ExtractContextReferences below, which would happen if we called
// SetInternalReference for every native context field in a macro.
static const struct {} native_context_names[] =;

void V8HeapExplorer::ExtractContextReferences(HeapEntry* entry,
                                              Tagged<Context> context) {}

void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Tagged<Map> map) {}

void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
    HeapEntry* entry, Tagged<SharedFunctionInfo> shared) {}

void V8HeapExplorer::ExtractScriptReferences(HeapEntry* entry,
                                             Tagged<Script> script) {}

void V8HeapExplorer::ExtractAccessorInfoReferences(
    HeapEntry* entry, Tagged<AccessorInfo> accessor_info) {}

void V8HeapExplorer::ExtractAccessorPairReferences(
    HeapEntry* entry, Tagged<AccessorPair> accessors) {}

void V8HeapExplorer::ExtractJSWeakRefReferences(HeapEntry* entry,
                                                Tagged<JSWeakRef> js_weak_ref) {}

void V8HeapExplorer::ExtractWeakCellReferences(HeapEntry* entry,
                                               Tagged<WeakCell> weak_cell) {}

void V8HeapExplorer::TagBuiltinCodeObject(Tagged<Code> code, const char* name) {}

void V8HeapExplorer::ExtractCodeReferences(HeapEntry* entry,
                                           Tagged<Code> code) {}

void V8HeapExplorer::ExtractInstructionStreamReferences(
    HeapEntry* entry, Tagged<InstructionStream> istream) {}

void V8HeapExplorer::ExtractCellReferences(HeapEntry* entry,
                                           Tagged<Cell> cell) {}

void V8HeapExplorer::ExtractFeedbackCellReferences(
    HeapEntry* entry, Tagged<FeedbackCell> feedback_cell) {}

void V8HeapExplorer::ExtractPropertyCellReferences(HeapEntry* entry,
                                                   Tagged<PropertyCell> cell) {}

void V8HeapExplorer::ExtractPrototypeInfoReferences(
    HeapEntry* entry, Tagged<PrototypeInfo> info) {}

void V8HeapExplorer::ExtractAllocationSiteReferences(
    HeapEntry* entry, Tagged<AllocationSite> site) {}

void V8HeapExplorer::ExtractArrayBoilerplateDescriptionReferences(
    HeapEntry* entry, Tagged<ArrayBoilerplateDescription> value) {}

void V8HeapExplorer::ExtractRegExpBoilerplateDescriptionReferences(
    HeapEntry* entry, Tagged<RegExpBoilerplateDescription> value) {}

class JSArrayBufferDataEntryAllocator : public HeapEntriesAllocator {};

void V8HeapExplorer::ExtractJSArrayBufferReferences(
    HeapEntry* entry, Tagged<JSArrayBuffer> buffer) {}

void V8HeapExplorer::ExtractJSPromiseReferences(HeapEntry* entry,
                                                Tagged<JSPromise> promise) {}

void V8HeapExplorer::ExtractJSGeneratorObjectReferences(
    HeapEntry* entry, Tagged<JSGeneratorObject> generator) {}

void V8HeapExplorer::ExtractFixedArrayReferences(HeapEntry* entry,
                                                 Tagged<FixedArray> array) {}

void V8HeapExplorer::ExtractNumberReference(HeapEntry* entry,
                                            Tagged<Object> number) {}

void V8HeapExplorer::ExtractBytecodeArrayReferences(
    HeapEntry* entry, Tagged<BytecodeArray> bytecode) {}

void V8HeapExplorer::ExtractScopeInfoReferences(HeapEntry* entry,
                                                Tagged<ScopeInfo> info) {}

void V8HeapExplorer::ExtractFeedbackVectorReferences(
    HeapEntry* entry, Tagged<FeedbackVector> feedback_vector) {}

void V8HeapExplorer::ExtractDescriptorArrayReferences(
    HeapEntry* entry, Tagged<DescriptorArray> array) {}

void V8HeapExplorer::ExtractEnumCacheReferences(HeapEntry* entry,
                                                Tagged<EnumCache> cache) {}

void V8HeapExplorer::ExtractTransitionArrayReferences(
    HeapEntry* entry, Tagged<TransitionArray> transitions) {}

template <typename T>
void V8HeapExplorer::ExtractWeakArrayReferences(int header_size,
                                                HeapEntry* entry,
                                                Tagged<T> array) {}

void V8HeapExplorer::ExtractPropertyReferences(Tagged<JSObject> js_obj,
                                               HeapEntry* entry) {}

void V8HeapExplorer::ExtractAccessorPairProperty(HeapEntry* entry,
                                                 Tagged<Name> key,
                                                 Tagged<Object> callback_obj,
                                                 int field_offset) {}

void V8HeapExplorer::ExtractElementReferences(Tagged<JSObject> js_obj,
                                              HeapEntry* entry) {}

void V8HeapExplorer::ExtractInternalReferences(Tagged<JSObject> js_obj,
                                               HeapEntry* entry) {}

#if V8_ENABLE_WEBASSEMBLY

void V8HeapExplorer::ExtractWasmStructReferences(Tagged<WasmStruct> obj,
                                                 HeapEntry* entry) {}

void V8HeapExplorer::ExtractWasmArrayReferences(Tagged<WasmArray> obj,
                                                HeapEntry* entry) {}

void V8HeapExplorer::ExtractWasmTrustedInstanceDataReferences(
    Tagged<WasmTrustedInstanceData> trusted_data, HeapEntry* entry) {}

#define ASSERT_FIRST_FIELD
#define ASSERT_CONSECUTIVE_FIELDS
#define ASSERT_LAST_FIELD

void V8HeapExplorer::ExtractWasmInstanceObjectReferences(
    Tagged<WasmInstanceObject> instance_object, HeapEntry* entry) {}

void V8HeapExplorer::ExtractWasmModuleObjectReferences(
    Tagged<WasmModuleObject> module_object, HeapEntry* entry) {}

#undef ASSERT_FIRST_FIELD
#undef ASSERT_CONSECUTIVE_FIELDS
#undef ASSERT_LAST_FIELD

#endif  // V8_ENABLE_WEBASSEMBLY

Tagged<JSFunction> V8HeapExplorer::GetConstructor(Isolate* isolate,
                                                  Tagged<JSReceiver> receiver) {}

Tagged<String> V8HeapExplorer::GetConstructorName(Isolate* isolate,
                                                  Tagged<JSObject> object) {}

HeapEntry* V8HeapExplorer::GetEntry(Tagged<Object> obj) {}

class RootsReferencesExtractor : public RootVisitor {};

bool V8HeapExplorer::IterateAndExtractReferences(
    HeapSnapshotGenerator* generator) {}

bool V8HeapExplorer::IsEssentialObject(Tagged<Object> object) {}

bool V8HeapExplorer::IsEssentialHiddenReference(Tagged<Object> parent,
                                                int field_offset) {}

void V8HeapExplorer::SetContextReference(HeapEntry* parent_entry,
                                         Tagged<String> reference_name,
                                         Tagged<Object> child_obj,
                                         int field_offset) {}

void V8HeapExplorer::MarkVisitedField(int offset) {}

void V8HeapExplorer::SetNativeBindReference(HeapEntry* parent_entry,
                                            const char* reference_name,
                                            Tagged<Object> child_obj) {}

void V8HeapExplorer::SetElementReference(HeapEntry* parent_entry, int index,
                                         Tagged<Object> child_obj) {}

void V8HeapExplorer::SetInternalReference(HeapEntry* parent_entry,
                                          const char* reference_name,
                                          Tagged<Object> child_obj,
                                          int field_offset) {}

void V8HeapExplorer::SetInternalReference(HeapEntry* parent_entry, int index,
                                          Tagged<Object> child_obj,
                                          int field_offset) {}

void V8HeapExplorer::SetHiddenReference(Tagged<HeapObject> parent_obj,
                                        HeapEntry* parent_entry, int index,
                                        Tagged<Object> child_obj,
                                        int field_offset) {}

void V8HeapExplorer::SetWeakReference(
    HeapEntry* parent_entry, const char* reference_name,
    Tagged<Object> child_obj, int field_offset,
    HeapEntry::ReferenceVerification verification) {}

void V8HeapExplorer::SetWeakReference(HeapEntry* parent_entry, int index,
                                      Tagged<Object> child_obj,
                                      std::optional<int> field_offset) {}

void V8HeapExplorer::SetDataOrAccessorPropertyReference(
    PropertyKind kind, HeapEntry* parent_entry, Tagged<Name> reference_name,
    Tagged<Object> child_obj, const char* name_format_string,
    int field_offset) {}

void V8HeapExplorer::SetPropertyReference(HeapEntry* parent_entry,
                                          Tagged<Name> reference_name,
                                          Tagged<Object> child_obj,
                                          const char* name_format_string,
                                          int field_offset) {}

void V8HeapExplorer::SetRootGcRootsReference() {}

void V8HeapExplorer::SetUserGlobalReference(Tagged<Object> child_obj) {}

void V8HeapExplorer::SetGcRootsReference(Root root) {}

void V8HeapExplorer::SetGcSubrootReference(Root root, const char* description,
                                           bool is_weak,
                                           Tagged<Object> child_obj) {}

const char* V8HeapExplorer::GetStrongGcSubrootName(Tagged<HeapObject> object) {}

void V8HeapExplorer::TagObject(Tagged<Object> obj, const char* tag,
                               std::optional<HeapEntry::Type> type,
                               bool overwrite_existing_name) {}

void V8HeapExplorer::RecursivelyTagConstantPool(Tagged<Object> obj,
                                                const char* tag,
                                                HeapEntry::Type type,
                                                int recursion_limit) {}

class GlobalObjectsEnumerator : public RootVisitor {};

V8HeapExplorer::TemporaryGlobalObjectTags
V8HeapExplorer::CollectTemporaryGlobalObjectsTags() {}

void V8HeapExplorer::MakeGlobalObjectTagMap(
    TemporaryGlobalObjectTags&& global_object_tags) {}

class EmbedderGraphImpl : public EmbedderGraph {};

class EmbedderGraphEntriesAllocator : public HeapEntriesAllocator {};

namespace {

const char* EmbedderGraphNodeName(StringsStorage* names,
                                  EmbedderGraphImpl::Node* node) {}

HeapEntry::Type EmbedderGraphNodeType(EmbedderGraphImpl::Node* node) {}

// Merges the names of an embedder node and its wrapper node.
// If the wrapper node name contains a tag suffix (part after '/') then the
// result is the embedder node name concatenated with the tag suffix.
// Otherwise, the result is the embedder node name.
const char* MergeNames(StringsStorage* names, const char* embedder_name,
                       const char* wrapper_name) {}

}  // anonymous namespace

HeapEntry* EmbedderGraphEntriesAllocator::AllocateEntry(HeapThing ptr) {}

HeapEntry* EmbedderGraphEntriesAllocator::AllocateEntry(Tagged<Smi> smi) {}

NativeObjectsExplorer::NativeObjectsExplorer(
    HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress)
    :{}

void NativeObjectsExplorer::MergeNodeIntoEntry(
    HeapEntry* entry, EmbedderGraph::Node* original_node,
    EmbedderGraph::Node* wrapper_node) {}

HeapEntry* NativeObjectsExplorer::EntryForEmbedderGraphNode(
    EmbedderGraphImpl::Node* node) {}

bool NativeObjectsExplorer::IterateAndExtractReferences(
    HeapSnapshotGenerator* generator) {}

HeapSnapshotGenerator::HeapSnapshotGenerator(
    HeapSnapshot* snapshot, v8::ActivityControl* control,
    v8::HeapProfiler::ObjectNameResolver* resolver, Heap* heap,
    cppgc::EmbedderStackState stack_state)
    :{}

namespace {
class V8_NODISCARD NullContextForSnapshotScope {};
}  // namespace

bool HeapSnapshotGenerator::GenerateSnapshot() {}

bool HeapSnapshotGenerator::GenerateSnapshotAfterGC() {}

void HeapSnapshotGenerator::ProgressStep() {}

bool HeapSnapshotGenerator::ProgressReport(bool force) {}

void HeapSnapshotGenerator::InitProgressCounter() {}

bool HeapSnapshotGenerator::FillReferences() {}

// type, name, id, self_size, edge_count, trace_node_id, detachedness.
const int HeapSnapshotJSONSerializer::kNodeFieldsCount =;

void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) {}

void HeapSnapshotJSONSerializer::SerializeImpl() {}

int HeapSnapshotJSONSerializer::GetStringId(const char* s) {}

namespace {

template <size_t size>
struct ToUnsigned;

template <>
struct ToUnsigned<1> {};

template <>
struct ToUnsigned<4> {};

template <>
struct ToUnsigned<8> {};

}  // namespace

template <typename T>
static int utoa_impl(T value, base::Vector<char> buffer, int buffer_pos) {}

template <typename T>
static int utoa(T value, base::Vector<char> buffer, int buffer_pos) {}

void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge,
                                               bool first_edge) {}

void HeapSnapshotJSONSerializer::SerializeEdges() {}

void HeapSnapshotJSONSerializer::SerializeNode(const HeapEntry* entry) {}

void HeapSnapshotJSONSerializer::SerializeNodes() {}

void HeapSnapshotJSONSerializer::SerializeSnapshot() {}

static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) {}

void HeapSnapshotJSONSerializer::SerializeTraceTree() {}

void HeapSnapshotJSONSerializer::SerializeTraceNode(AllocationTraceNode* node) {}

// 0-based position is converted to 1-based during the serialization.
static int SerializePosition(int position, base::Vector<char> buffer,
                             int buffer_pos) {}

void HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() {}

void HeapSnapshotJSONSerializer::SerializeSamples() {}

void HeapSnapshotJSONSerializer::SerializeString(const unsigned char* s) {}

void HeapSnapshotJSONSerializer::SerializeStrings() {}

void HeapSnapshotJSONSerializer::SerializeLocation(
    const EntrySourceLocation& location) {}

void HeapSnapshotJSONSerializer::SerializeLocations() {}

}  // namespace v8::internal