chromium/v8/test/cctest/test-heap-profiler.cc

// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Tests for heap profiler

#include <ctype.h>

#include <memory>
#include <optional>
#include <vector>

#include "include/v8-function.h"
#include "include/v8-json.h"
#include "include/v8-profiler.h"
#include "src/api/api-inl.h"
#include "src/base/hashmap.h"
#include "src/base/logging.h"
#include "src/base/strings.h"
#include "src/codegen/assembler-inl.h"
#include "src/debug/debug.h"
#include "src/handles/global-handles.h"
#include "src/heap/heap-inl.h"
#include "src/heap/pretenuring-handler.h"
#include "src/objects/objects-inl.h"
#include "src/profiler/allocation-tracker.h"
#include "src/profiler/heap-profiler.h"
#include "src/profiler/heap-snapshot-generator-inl.h"
#include "test/cctest/cctest.h"
#include "test/cctest/collector.h"
#include "test/cctest/heap/heap-utils.h"
#include "test/cctest/jsonstream-helper.h"

#if V8_ENABLE_WEBASSEMBLY
#include "src/wasm/wasm-module-builder.h"
#endif

AllocationTraceNode;
AllocationTraceTree;
AllocationTracker;
EntrySourceLocation;
GrowNewSpaceToMaximumCapacity;
optional;
ArrayVector;
OS;
Vector;
VectorOf;

namespace {

class NamedEntriesDetector {};

}  // namespace


static const v8::HeapGraphNode* GetGlobalObject(
    const v8::HeapSnapshot* snapshot) {}

static const char* GetName(const v8::HeapGraphNode* node) {}

static const char* GetName(const v8::HeapGraphEdge* edge) {}

static size_t GetSize(const v8::HeapGraphNode* node) {}

static const v8::HeapGraphNode* GetChildByName(const v8::HeapGraphNode* node,
                                               const char* name) {}

static const v8::HeapGraphEdge* GetEdgeByChildName(
    const v8::HeapGraphNode* node, const char* name) {}

static const v8::HeapGraphNode* GetRootChild(const v8::HeapSnapshot* snapshot,
                                             const char* name) {}

static optional<EntrySourceLocation> GetLocation(
    const v8::HeapSnapshot* s, const v8::HeapGraphNode* node) {}

static const v8::HeapGraphNode* GetProperty(v8::Isolate* isolate,
                                            const v8::HeapGraphNode* node,
                                            v8::HeapGraphEdge::Type type,
                                            const char* name) {}

// The following functions are not Wasm-specific, but are only used in a
// Wasm-specific test. As long as this is the case we only define them if Wasm
// is enabled to avoid warnings about unused functions.
#if V8_ENABLE_WEBASSEMBLY
static const std::vector<std::string> GetProperties(
    v8::Isolate* isolate, const v8::HeapGraphNode* node) {}

static void CheckProperties(
    v8::Isolate* isolate, const v8::HeapGraphNode* node,
    std::initializer_list<std::string> expected_properties) {}
#endif  // V8_ENABLE_WEBASSEMBLY

static bool HasString(v8::Isolate* isolate, const v8::HeapGraphNode* node,
                      const char* contents) {}

static void EnsureNoUninstrumentedInternals(v8::Isolate* isolate,
                                            const v8::HeapGraphNode* node) {}

// Check that snapshot has no unretained entries except root.
static bool ValidateSnapshot(const v8::HeapSnapshot* snapshot, int depth = 3) {}

bool EndsWith(const char* a, const char* b) {}

TEST(HeapSnapshot) {}

TEST(HeapSnapshotLocations) {}

TEST(HeapSnapshotObjectSizes) {}


TEST(BoundFunctionInSnapshot) {}


TEST(HeapSnapshotEntryChildren) {}


TEST(HeapSnapshotCodeObjects) {}


TEST(HeapSnapshotHeapNumbers) {}

TEST(HeapSnapshotHeapNumbersCaptureNumericValue) {}

TEST(HeapSnapshotHeapBigInts) {}

TEST(HeapSnapshotSlicedString) {}

// Allow usages of v8::Object::GetPrototype() for now.
// TODO(https://crbug.com/333672197): remove.
START_ALLOW_USE_DEPRECATED()

TEST(HeapSnapshotConsString) {}

// Allow usages of v8::Object::GetPrototype() for now.
// TODO(https://crbug.com/333672197): remove.
END_ALLOW_USE_DEPRECATED()

TEST(HeapSnapshotSymbol) {}

TEST(HeapSnapshotWeakCollection) {}


TEST(HeapSnapshotCollection) {}

TEST(HeapSnapshotMap) {}

// Allow usages of v8::Object::GetPrototype() for now.
// TODO(https://crbug.com/333672197): remove.
START_ALLOW_USE_DEPRECATED()

TEST(HeapSnapshotInternalReferences) {}

// Allow usages of v8::Object::GetPrototype() for now.
// TODO(https://crbug.com/333672197): remove.
END_ALLOW_USE_DEPRECATED()

TEST(HeapSnapshotEphemeron) {}

TEST(HeapSnapshotAddressReuse) {}


TEST(HeapEntryIdsAndArrayShift) {}


TEST(HeapEntryIdsAndGC) {}

TEST(HeapSnapshotJSONSerialization) {}


TEST(HeapSnapshotJSONSerializationAborting) {}

namespace {

class TestStatsStream : public v8::OutputStream {};

}  // namespace

static TestStatsStream GetHeapStatsUpdate(
    v8::HeapProfiler* heap_profiler,
    v8::SnapshotObjectId* object_id = nullptr) {}


TEST(HeapSnapshotObjectsStats) {}


TEST(HeapObjectIds) {}


static void CheckChildrenIds(const v8::HeapSnapshot* snapshot,
                             const v8::HeapGraphNode* node,
                             int level, int max_level) {}


TEST(HeapSnapshotGetNodeById) {}


TEST(HeapSnapshotGetSnapshotObjectId) {}


TEST(HeapSnapshotUnknownSnapshotObjectId) {}


namespace {

class TestActivityControl : public v8::ActivityControl {};

}  // namespace


TEST(TakeHeapSnapshotAborting) {}

TEST(TakeHeapSnapshotReportFinishOnce) {}

namespace {

class EmbedderGraphBuilder : public v8::PersistentHandleVisitor {};

}  // namespace


static const v8::HeapGraphNode* GetNode(const v8::HeapGraphNode* parent,
                                        v8::HeapGraphNode::Type type,
                                        const char* name) {}


TEST(HeapSnapshotRetainedObjectInfo) {}

namespace {

class EmbedderGraphBuilderForNativeSnapshotObjectId final {};

}  // namespace

TEST(NativeSnapshotObjectId) {}

TEST(NativeSnapshotObjectIdMoving) {}

TEST(DeleteAllHeapSnapshots) {}


static bool FindHeapSnapshot(v8::HeapProfiler* profiler,
                             const v8::HeapSnapshot* snapshot) {}


TEST(DeleteHeapSnapshot) {}


class NameResolver : public v8::HeapProfiler::ObjectNameResolver {};


TEST(GlobalObjectName) {}


TEST(GlobalObjectFields) {}


TEST(NoHandleLeaks) {}


TEST(NodesIteration) {}

// Allow usages of v8::Object::GetPrototype() for now.
// TODO(https://crbug.com/333672197): remove.
START_ALLOW_USE_DEPRECATED()

TEST(GetHeapValueForNode) {}


TEST(GetHeapValueForDeletedObject) {}

static int StringCmp(const char* ref, i::Tagged<i::String> act) {}

TEST(GetConstructor) {}

TEST(GetConstructorName) {}

// Allow usages of v8::Object::GetPrototype() for now.
// TODO(https://crbug.com/333672197): remove.
END_ALLOW_USE_DEPRECATED()

TEST(FastCaseAccessors) {}

// Allow usages of v8::Object::GetPrototype() for now.
// TODO(https://crbug.com/333672197): remove.
START_ALLOW_USE_DEPRECATED()

TEST(FastCaseRedefinedAccessors) {}

// Allow usages of v8::Object::GetPrototype() for now.
// TODO(https://crbug.com/333672197): remove.
END_ALLOW_USE_DEPRECATED()

TEST(SlowCaseAccessors) {}


TEST(HiddenPropertiesFastCase) {}

TEST(SymbolsAndPrivateClassFields) {}

TEST(AccessorInfo) {}

TEST(JSGeneratorObject) {}

bool HasWeakEdge(const v8::HeapGraphNode* node) {}


bool HasWeakGlobalHandle() {}


TEST(WeakGlobalHandle) {}


TEST(SfiAndJsFunctionWeakRefs) {}


TEST(AllStrongGcRootsHaveNames) {}


TEST(NoRefsToNonEssentialEntries) {}


TEST(MapHasDescriptorsAndTransitions) {}


TEST(ManyLocalsInSharedContext) {}

TEST(AllocationSitesAreVisible) {}


TEST(JSFunctionHasCodeLink) {}

static const v8::HeapGraphNode* GetNodeByPath(v8::Isolate* isolate,
                                              const v8::HeapSnapshot* snapshot,
                                              const char* path[], int depth) {}


TEST(CheckCodeNames) {}


static const char* record_trace_tree_source =;

static AllocationTraceNode* FindNode(AllocationTracker* tracker,
                                     v8::base::Vector<const char*> names) {}

TEST(ArrayGrowLeftTrim) {}

TEST(TrackHeapAllocationsWithInlining) {}

TEST(TrackHeapAllocationsWithoutInlining) {}


static const char* inline_heap_allocation_source =;


TEST(TrackBumpPointerAllocations) {}


TEST(TrackV8ApiAllocation) {}


TEST(ArrayBufferAndArrayBufferView) {}


static int GetRetainersCount(const v8::HeapSnapshot* snapshot,
                             const v8::HeapGraphNode* node) {}


TEST(ArrayBufferSharedBackingStore) {}


TEST(WeakContainers) {}

TEST(JSPromise) {}

TEST(HeapSnapshotScriptContext) {}

class EmbedderNode : public v8::EmbedderGraph::Node {};

class EmbedderRootNode : public EmbedderNode {};

// Used to pass the global object to the BuildEmbedderGraph callback.
// Otherwise, the callback has to iterate the global handles to find the
// global object.
v8::Local<v8::Value>* global_object_pointer;

void BuildEmbedderGraph(v8::Isolate* v8_isolate, v8::EmbedderGraph* graph,
                        void* data) {}

void CheckEmbedderGraphSnapshot(v8::Isolate* isolate,
                                const v8::HeapSnapshot* snapshot) {}

TEST(EmbedderGraph) {}

void BuildEmbedderGraphWithNamedEdges(v8::Isolate* v8_isolate,
                                      v8::EmbedderGraph* graph, void* data) {}

void CheckEmbedderGraphWithNamedEdges(v8::Isolate* isolate,
                                      const v8::HeapSnapshot* snapshot) {}

TEST(EmbedderGraphWithNamedEdges) {}

struct GraphBuildingContext {};

void CheckEmbedderGraphSnapshotWithContext(
    v8::Isolate* isolate, const v8::HeapSnapshot* snapshot,
    const GraphBuildingContext* context) {}

void BuildEmbedderGraphWithContext(v8::Isolate* v8_isolate,
                                   v8::EmbedderGraph* graph, void* data) {}

TEST(EmbedderGraphMultipleCallbacks) {}

TEST(StrongHandleAnnotation) {}

void BuildEmbedderGraphWithWrapperNode(v8::Isolate* v8_isolate,
                                       v8::EmbedderGraph* graph, void* data) {}

TEST(EmbedderGraphWithWrapperNode) {}

class EmbedderNodeWithPrefix : public v8::EmbedderGraph::Node {};

void BuildEmbedderGraphWithPrefix(v8::Isolate* v8_isolate,
                                  v8::EmbedderGraph* graph, void* data) {}

TEST(EmbedderGraphWithPrefix) {}

static inline i::Address ToAddress(int n) {}

TEST(AddressToTraceMap) {}

static const v8::AllocationProfile::Node* FindAllocationProfileNode(
    v8::Isolate* isolate, v8::AllocationProfile* profile,
    v8::base::Vector<const char*> names) {}

static void CheckNoZeroCountNodes(v8::AllocationProfile::Node* node) {}

static int NumberOfAllocations(const v8::AllocationProfile::Node* node) {}

static const char* simple_sampling_heap_profiler_script =;

TEST(SamplingHeapProfiler) {}

TEST(SamplingHeapProfilerRateAgnosticEstimates) {}

TEST(SamplingHeapProfilerApiAllocation) {}

TEST(SamplingHeapProfilerApiSamples) {}

TEST(SamplingHeapProfilerLeftTrimming) {}

TEST(SamplingHeapProfilerPretenuredInlineAllocations) {}

TEST(SamplingHeapProfilerLargeInterval) {}

TEST(HeapSnapshotPrototypeNotJSReceiver) {}

TEST(SamplingHeapProfilerSampleDuringDeopt) {}

namespace {
class TestQueryObjectPredicate : public v8::QueryObjectPredicate {};

class IncludeAllQueryObjectPredicate : public v8::QueryObjectPredicate {};
}  // anonymous namespace

TEST(QueryObjects) {}

TEST(WeakReference) {}

TEST(Bug8373_1) {}

TEST(Bug8373_2) {}

TEST(HeapSnapshotDeleteDuringTakeSnapshot) {}

TEST(ObjectRetainedInHandle) {}

TEST(ObjectRetainedInDirectHandle) {}

#if V8_ENABLE_WEBASSEMBLY
TEST(HeapSnapshotWithWasmInstance) {}
#endif  // V8_ENABLE_WEBASSEMBLY