From b2b5d2777e1ba05f8127c28e5f006896ef0fc12c Mon Sep 17 00:00:00 2001 From: "mikhail.naganov@gmail.com" Date: Tue, 22 Mar 2011 16:10:01 +0000 Subject: [PATCH] Add support for CPU and heap profiles deletion. R=vitalyr@chromium.org BUG=none TEST=none Review URL: http://codereview.chromium.org/6685084 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7308 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- include/v8-profiler.h | 30 +++++++++ src/api.cc | 38 +++++++++++ src/cpu-profiler.cc | 59 ++++++++++++----- src/cpu-profiler.h | 5 ++ src/heap-profiler.cc | 14 ++++ src/heap-profiler.h | 2 + src/profile-generator.cc | 76 +++++++++++++++++---- src/profile-generator.h | 6 ++ test/cctest/test-cpu-profiler.cc | 135 ++++++++++++++++++++++++++++++++++++++ test/cctest/test-heap-profiler.cc | 58 ++++++++++++++++ 10 files changed, 396 insertions(+), 27 deletions(-) diff --git a/include/v8-profiler.h b/include/v8-profiler.h index d466d5e..a7b4d31 100644 --- a/include/v8-profiler.h +++ b/include/v8-profiler.h @@ -131,6 +131,16 @@ class V8EXPORT CpuProfile { /** Returns the root node of the top down call tree. */ const CpuProfileNode* GetTopDownRoot() const; + + /** + * Deletes the profile and removes it from CpuProfiler's list. + * All pointers to nodes previously returned become invalid. + * Profiles with the same uid but obtained using different + * security token are not deleted, but become inaccessible + * using FindProfile method. It is embedder's responsibility + * to call Delete on these profiles. + */ + void Delete(); }; @@ -181,6 +191,13 @@ class V8EXPORT CpuProfiler { static const CpuProfile* StopProfiling( Handle title, Handle security_token = Handle()); + + /** + * Deletes all existing profiles, also cancelling all profiling + * activity. All previously returned pointers to profiles and their + * contents become invalid after this call. + */ + static void DeleteAllProfiles(); }; @@ -368,6 +385,13 @@ class V8EXPORT HeapSnapshot { const HeapSnapshotsDiff* CompareWith(const HeapSnapshot* snapshot) const; /** + * Deletes the snapshot and removes it from HeapProfiler's list. + * All pointers to nodes, edges and paths previously returned become + * invalid. + */ + void Delete(); + + /** * Prepare a serialized representation of the snapshot. The result * is written into the stream provided in chunks of specified size. * The total length of the serialized snapshot is unknown in @@ -427,6 +451,12 @@ class V8EXPORT HeapProfiler { HeapSnapshot::Type type = HeapSnapshot::kFull, ActivityControl* control = NULL); + /** + * Deletes all snapshots taken. All previously returned pointers to + * snapshots and their contents become invalid after this call. + */ + static void DeleteAllSnapshots(); + /** Binds a callback to embedder's class ID. */ static void DefineWrapperClass( uint16_t class_id, diff --git a/src/api.cc b/src/api.cc index b101dc3..20d3f39 100644 --- a/src/api.cc +++ b/src/api.cc @@ -5078,6 +5078,18 @@ const CpuProfileNode* CpuProfileNode::GetChild(int index) const { } +void CpuProfile::Delete() { + i::Isolate* isolate = i::Isolate::Current(); + IsDeadCheck(isolate, "v8::CpuProfile::Delete"); + i::CpuProfiler::DeleteProfile(reinterpret_cast(this)); + if (i::CpuProfiler::GetProfilesCount() == 0 && + !i::CpuProfiler::HasDetachedProfiles()) { + // If this was the last profile, clean up all accessory data as well. + i::CpuProfiler::DeleteAllProfiles(); + } +} + + unsigned CpuProfile::GetUid() const { i::Isolate* isolate = i::Isolate::Current(); IsDeadCheck(isolate, "v8::CpuProfile::GetUid"); @@ -5157,6 +5169,13 @@ const CpuProfile* CpuProfiler::StopProfiling(Handle title, } +void CpuProfiler::DeleteAllProfiles() { + i::Isolate* isolate = i::Isolate::Current(); + IsDeadCheck(isolate, "v8::CpuProfiler::DeleteAllProfiles"); + i::CpuProfiler::DeleteAllProfiles(); +} + + static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) { return const_cast( reinterpret_cast(edge)); @@ -5363,6 +5382,18 @@ static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) { } +void HeapSnapshot::Delete() { + i::Isolate* isolate = i::Isolate::Current(); + IsDeadCheck(isolate, "v8::HeapSnapshot::Delete"); + if (i::HeapProfiler::GetSnapshotsCount() > 1) { + ToInternal(this)->Delete(); + } else { + // If this is the last snapshot, clean up all accessory data as well. + i::HeapProfiler::DeleteAllSnapshots(); + } +} + + HeapSnapshot::Type HeapSnapshot::GetType() const { i::Isolate* isolate = i::Isolate::Current(); IsDeadCheck(isolate, "v8::HeapSnapshot::GetType"); @@ -5472,6 +5503,13 @@ const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle title, } +void HeapProfiler::DeleteAllSnapshots() { + i::Isolate* isolate = i::Isolate::Current(); + IsDeadCheck(isolate, "v8::HeapProfiler::DeleteAllSnapshots"); + i::HeapProfiler::DeleteAllSnapshots(); +} + + void HeapProfiler::DefineWrapperClass(uint16_t class_id, WrapperInfoCallback callback) { i::Isolate::Current()->heap_profiler()->DefineWrapperClass(class_id, diff --git a/src/cpu-profiler.cc b/src/cpu-profiler.cc index 7387a4c..bc53c68 100644 --- a/src/cpu-profiler.cc +++ b/src/cpu-profiler.cc @@ -331,6 +331,27 @@ TickSample* CpuProfiler::TickSampleEvent(Isolate* isolate) { } +void CpuProfiler::DeleteAllProfiles() { + ASSERT(Isolate::Current()->cpu_profiler() != NULL); + if (is_profiling()) + Isolate::Current()->cpu_profiler()->StopProcessor(); + Isolate::Current()->cpu_profiler()->ResetProfiles(); +} + + +void CpuProfiler::DeleteProfile(CpuProfile* profile) { + ASSERT(Isolate::Current()->cpu_profiler() != NULL); + Isolate::Current()->cpu_profiler()->profiles_->RemoveProfile(profile); + delete profile; +} + + +bool CpuProfiler::HasDetachedProfiles() { + ASSERT(Isolate::Current()->cpu_profiler() != NULL); + return Isolate::Current()->cpu_profiler()->profiles_->HasDetachedProfiles(); +} + + void CpuProfiler::CallbackEvent(String* name, Address entry_point) { Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent( Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point); @@ -452,6 +473,11 @@ CpuProfiler::~CpuProfiler() { } +void CpuProfiler::ResetProfiles() { + delete profiles_; + profiles_ = new CpuProfilesCollection(); +} + void CpuProfiler::StartCollectingProfile(const char* title) { if (profiles_->StartProfiling(title, next_profile_uid_++)) { StartProcessorIfNotStarted(); @@ -521,22 +547,25 @@ CpuProfile* CpuProfiler::StopCollectingProfile(Object* security_token, void CpuProfiler::StopProcessorIfLastProfile(const char* title) { - if (profiles_->IsLastProfile(title)) { - Sampler* sampler = reinterpret_cast(LOGGER->ticker_); - sampler->DecreaseProfilingDepth(); - if (need_to_stop_sampler_) { - sampler->Stop(); - need_to_stop_sampler_ = false; - } - processor_->Stop(); - processor_->Join(); - delete processor_; - delete generator_; - processor_ = NULL; - NoBarrier_Store(&is_profiling_, false); - generator_ = NULL; - LOGGER->logging_nesting_ = saved_logging_nesting_; + if (profiles_->IsLastProfile(title)) StopProcessor(); +} + + +void CpuProfiler::StopProcessor() { + Sampler* sampler = reinterpret_cast(LOGGER->ticker_); + sampler->DecreaseProfilingDepth(); + if (need_to_stop_sampler_) { + sampler->Stop(); + need_to_stop_sampler_ = false; } + processor_->Stop(); + processor_->Join(); + delete processor_; + delete generator_; + processor_ = NULL; + NoBarrier_Store(&is_profiling_, false); + generator_ = NULL; + LOGGER->logging_nesting_ = saved_logging_nesting_; } } } // namespace v8::internal diff --git a/src/cpu-profiler.h b/src/cpu-profiler.h index b06f6ab..e04cf85 100644 --- a/src/cpu-profiler.h +++ b/src/cpu-profiler.h @@ -227,6 +227,9 @@ class CpuProfiler { static int GetProfilesCount(); static CpuProfile* GetProfile(Object* security_token, int index); static CpuProfile* FindProfile(Object* security_token, unsigned uid); + static void DeleteAllProfiles(); + static void DeleteProfile(CpuProfile* profile); + static bool HasDetachedProfiles(); // Invoked from stack sampler (thread or signal handler.) static TickSample* TickSampleEvent(Isolate* isolate); @@ -276,6 +279,8 @@ class CpuProfiler { CpuProfile* StopCollectingProfile(const char* title); CpuProfile* StopCollectingProfile(Object* security_token, String* title); void StopProcessorIfLastProfile(const char* title); + void StopProcessor(); + void ResetProfiles(); CpuProfilesCollection* profiles_; unsigned next_profile_uid_; diff --git a/src/heap-profiler.cc b/src/heap-profiler.cc index c78f474..4815f82 100644 --- a/src/heap-profiler.cc +++ b/src/heap-profiler.cc @@ -326,6 +326,13 @@ HeapProfiler::~HeapProfiler() { delete snapshots_; } + +void HeapProfiler::ResetSnapshots() { + delete snapshots_; + snapshots_ = new HeapSnapshotsCollection(); +} + + #endif // ENABLE_LOGGING_AND_PROFILING void HeapProfiler::Setup() { @@ -450,6 +457,13 @@ HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) { } +void HeapProfiler::DeleteAllSnapshots() { + HeapProfiler* profiler = Isolate::Current()->heap_profiler(); + ASSERT(profiler != NULL); + profiler->ResetSnapshots(); +} + + void HeapProfiler::ObjectMoveEvent(Address from, Address to) { snapshots_->ObjectMoveEvent(from, to); } diff --git a/src/heap-profiler.h b/src/heap-profiler.h index b425635..89a2e8a 100644 --- a/src/heap-profiler.h +++ b/src/heap-profiler.h @@ -67,6 +67,7 @@ class HeapProfiler { static int GetSnapshotsCount(); static HeapSnapshot* GetSnapshot(int index); static HeapSnapshot* FindSnapshot(unsigned uid); + static void DeleteAllSnapshots(); void ObjectMoveEvent(Address from, Address to); @@ -92,6 +93,7 @@ class HeapProfiler { HeapSnapshot* TakeSnapshotImpl(String* name, int type, v8::ActivityControl* control); + void ResetSnapshots(); HeapSnapshotsCollection* snapshots_; unsigned next_snapshot_uid_; diff --git a/src/profile-generator.cc b/src/profile-generator.cc index f836583..39b1a8d 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -320,7 +320,7 @@ struct NodesPair { class FilteredCloneCallback { public: - explicit FilteredCloneCallback(ProfileNode* dst_root, int security_token_id) + FilteredCloneCallback(ProfileNode* dst_root, int security_token_id) : stack_(10), security_token_id_(security_token_id) { stack_.Add(NodesPair(NULL, dst_root)); @@ -550,13 +550,16 @@ static void DeleteCpuProfile(CpuProfile** profile_ptr) { } static void DeleteProfilesList(List** list_ptr) { - (*list_ptr)->Iterate(DeleteCpuProfile); - delete *list_ptr; + if (*list_ptr != NULL) { + (*list_ptr)->Iterate(DeleteCpuProfile); + delete *list_ptr; + } } CpuProfilesCollection::~CpuProfilesCollection() { delete current_profiles_semaphore_; current_profiles_.Iterate(DeleteCpuProfile); + detached_profiles_.Iterate(DeleteCpuProfile); profiles_by_token_.Iterate(DeleteProfilesList); code_entries_.Iterate(DeleteCodeEntry); } @@ -621,15 +624,8 @@ CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id, CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id, unsigned uid) { - HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast(uid), - static_cast(uid), - false); - int index; - if (entry != NULL) { - index = static_cast(reinterpret_cast(entry->value)); - } else { - return NULL; - } + int index = GetProfileIndex(uid); + if (index < 0) return NULL; List* unabridged_list = profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)]; if (security_token_id == TokenEnumerator::kNoSecurityToken) { @@ -644,6 +640,15 @@ CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id, } +int CpuProfilesCollection::GetProfileIndex(unsigned uid) { + HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast(uid), + static_cast(uid), + false); + return entry != NULL ? + static_cast(reinterpret_cast(entry->value)) : -1; +} + + bool CpuProfilesCollection::IsLastProfile(const char* title) { // Called from VM thread, and only it can mutate the list, // so no locking is needed here. @@ -653,6 +658,39 @@ bool CpuProfilesCollection::IsLastProfile(const char* title) { } +void CpuProfilesCollection::RemoveProfile(CpuProfile* profile) { + // Called from VM thread for a completed profile. + unsigned uid = profile->uid(); + int index = GetProfileIndex(uid); + if (index < 0) { + detached_profiles_.RemoveElement(profile); + return; + } + profiles_uids_.Remove(reinterpret_cast(uid), + static_cast(uid)); + // Decrement all indexes above the deleted one. + for (HashMap::Entry* p = profiles_uids_.Start(); + p != NULL; + p = profiles_uids_.Next(p)) { + intptr_t p_index = reinterpret_cast(p->value); + if (p_index > index) { + p->value = reinterpret_cast(p_index - 1); + } + } + for (int i = 0; i < profiles_by_token_.length(); ++i) { + List* list = profiles_by_token_[i]; + if (list != NULL && index < list->length()) { + // Move all filtered clones into detached_profiles_, + // so we can know that they are still in use. + CpuProfile* cloned_profile = list->Remove(index); + if (cloned_profile != NULL && cloned_profile != profile) { + detached_profiles_.Add(cloned_profile); + } + } + } +} + + int CpuProfilesCollection::TokenToIndex(int security_token_id) { ASSERT(TokenEnumerator::kNoSecurityToken == -1); return security_token_id + 1; // kNoSecurityToken -> 0, 0 -> 1, ... @@ -1268,6 +1306,12 @@ HeapSnapshot::~HeapSnapshot() { } +void HeapSnapshot::Delete() { + collection_->RemoveSnapshot(this); + delete this; +} + + void HeapSnapshot::AllocateEntries(int entries_count, int children_count, int retainers_count) { @@ -1579,6 +1623,14 @@ HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) { } +void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) { + snapshots_.RemoveElement(snapshot); + unsigned uid = snapshot->uid(); + snapshots_uids_.Remove(reinterpret_cast(uid), + static_cast(uid)); +} + + HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots( HeapSnapshot* snapshot1, HeapSnapshot* snapshot2) { diff --git a/src/profile-generator.h b/src/profile-generator.h index d444e75..c817913 100644 --- a/src/profile-generator.h +++ b/src/profile-generator.h @@ -300,6 +300,8 @@ class CpuProfilesCollection { } CpuProfile* GetProfile(int security_token_id, unsigned uid); bool IsLastProfile(const char* title); + void RemoveProfile(CpuProfile* profile); + bool HasDetachedProfiles() { return detached_profiles_.length() > 0; } CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, String* name, String* resource_name, int line_number); @@ -322,6 +324,7 @@ class CpuProfilesCollection { const char* GetFunctionName(const char* name) { return function_and_resource_names_.GetFunctionName(name); } + int GetProfileIndex(unsigned uid); List* GetProfilesList(int security_token_id); int TokenToIndex(int security_token_id); @@ -335,6 +338,7 @@ class CpuProfilesCollection { // Mapping from profiles' uids to indexes in the second nested list // of profiles_by_token_. HashMap profiles_uids_; + List detached_profiles_; // Accessed by VM thread and profile generator thread. List current_profiles_; @@ -673,6 +677,7 @@ class HeapSnapshot { const char* title, unsigned uid); ~HeapSnapshot(); + void Delete(); HeapSnapshotsCollection* collection() { return collection_; } Type type() { return type_; } @@ -840,6 +845,7 @@ class HeapSnapshotsCollection { void SnapshotGenerationFinished(HeapSnapshot* snapshot); List* snapshots() { return &snapshots_; } HeapSnapshot* GetSnapshot(unsigned uid); + void RemoveSnapshot(HeapSnapshot* snapshot); StringsStorage* names() { return &names_; } TokenEnumerator* token_enumerator() { return token_enumerator_; } diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc index 507f236..749ac15 100644 --- a/test/cctest/test-cpu-profiler.cc +++ b/test/cctest/test-cpu-profiler.cc @@ -7,6 +7,7 @@ #include "v8.h" #include "cpu-profiler-inl.h" #include "cctest.h" +#include "../include/v8-profiler.h" namespace i = v8::internal; @@ -236,4 +237,138 @@ TEST(CrashIfStoppingLastNonExistentProfile) { CpuProfiler::TearDown(); } + +TEST(DeleteAllCpuProfiles) { + InitializeVM(); + TestSetup test_setup; + CpuProfiler::Setup(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CpuProfiler::DeleteAllProfiles(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + + CpuProfiler::StartProfiling("1"); + CpuProfiler::StopProfiling("1"); + CHECK_EQ(1, CpuProfiler::GetProfilesCount()); + CpuProfiler::DeleteAllProfiles(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CpuProfiler::StartProfiling("1"); + CpuProfiler::StartProfiling("2"); + CpuProfiler::StopProfiling("2"); + CpuProfiler::StopProfiling("1"); + CHECK_EQ(2, CpuProfiler::GetProfilesCount()); + CpuProfiler::DeleteAllProfiles(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + + // Test profiling cancellation by the 'delete' command. + CpuProfiler::StartProfiling("1"); + CpuProfiler::StartProfiling("2"); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CpuProfiler::DeleteAllProfiles(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + + CpuProfiler::TearDown(); +} + + +TEST(DeleteCpuProfile) { + v8::HandleScope scope; + LocalContext env; + + CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount()); + v8::Local name1 = v8::String::New("1"); + v8::CpuProfiler::StartProfiling(name1); + const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1); + CHECK_NE(NULL, p1); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + unsigned uid1 = p1->GetUid(); + CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1)); + const_cast(p1)->Delete(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1)); + + v8::Local name2 = v8::String::New("2"); + v8::CpuProfiler::StartProfiling(name2); + const v8::CpuProfile* p2 = v8::CpuProfiler::StopProfiling(name2); + CHECK_NE(NULL, p2); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + unsigned uid2 = p2->GetUid(); + CHECK_NE(static_cast(uid1), static_cast(uid2)); + CHECK_EQ(p2, v8::CpuProfiler::FindProfile(uid2)); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1)); + v8::Local name3 = v8::String::New("3"); + v8::CpuProfiler::StartProfiling(name3); + const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3); + CHECK_NE(NULL, p3); + CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount()); + unsigned uid3 = p3->GetUid(); + CHECK_NE(static_cast(uid1), static_cast(uid3)); + CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3)); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1)); + const_cast(p2)->Delete(); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2)); + CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3)); + const_cast(p3)->Delete(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3)); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2)); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1)); +} + + +TEST(DeleteCpuProfileDifferentTokens) { + v8::HandleScope scope; + LocalContext env; + + CHECK_EQ(0, v8::CpuProfiler::GetProfilesCount()); + v8::Local name1 = v8::String::New("1"); + v8::CpuProfiler::StartProfiling(name1); + const v8::CpuProfile* p1 = v8::CpuProfiler::StopProfiling(name1); + CHECK_NE(NULL, p1); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + unsigned uid1 = p1->GetUid(); + CHECK_EQ(p1, v8::CpuProfiler::FindProfile(uid1)); + v8::Local token1 = v8::String::New("token1"); + const v8::CpuProfile* p1_t1 = v8::CpuProfiler::FindProfile(uid1, token1); + CHECK_NE(NULL, p1_t1); + CHECK_NE(p1, p1_t1); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + const_cast(p1)->Delete(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1)); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1, token1)); + const_cast(p1_t1)->Delete(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + + v8::Local name2 = v8::String::New("2"); + v8::CpuProfiler::StartProfiling(name2); + v8::Local token2 = v8::String::New("token2"); + const v8::CpuProfile* p2_t2 = v8::CpuProfiler::StopProfiling(name2, token2); + CHECK_NE(NULL, p2_t2); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + unsigned uid2 = p2_t2->GetUid(); + CHECK_NE(static_cast(uid1), static_cast(uid2)); + const v8::CpuProfile* p2 = v8::CpuProfiler::FindProfile(uid2); + CHECK_NE(p2_t2, p2); + v8::Local name3 = v8::String::New("3"); + v8::CpuProfiler::StartProfiling(name3); + const v8::CpuProfile* p3 = v8::CpuProfiler::StopProfiling(name3); + CHECK_NE(NULL, p3); + CHECK_EQ(2, v8::CpuProfiler::GetProfilesCount()); + unsigned uid3 = p3->GetUid(); + CHECK_NE(static_cast(uid1), static_cast(uid3)); + CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3)); + const_cast(p2_t2)->Delete(); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2)); + CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3)); + const_cast(p2)->Delete(); + CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2)); + CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3)); + const_cast(p3)->Delete(); + CHECK_EQ(0, CpuProfiler::GetProfilesCount()); + CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3)); +} + #endif // ENABLE_LOGGING_AND_PROFILING diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc index bda97a4..4908325 100644 --- a/test/cctest/test-heap-profiler.cc +++ b/test/cctest/test-heap-profiler.cc @@ -1395,4 +1395,62 @@ TEST(HeapSnapshotRetainedObjectInfo) { CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "Native")); } + +TEST(DeleteAllHeapSnapshots) { + v8::HandleScope scope; + LocalContext env; + + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + v8::HeapProfiler::DeleteAllSnapshots(); + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("1"))); + CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); + v8::HeapProfiler::DeleteAllSnapshots(); + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("1"))); + CHECK_NE(NULL, v8::HeapProfiler::TakeSnapshot(v8::String::New("2"))); + CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount()); + v8::HeapProfiler::DeleteAllSnapshots(); + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); +} + + +TEST(DeleteHeapSnapshot) { + v8::HandleScope scope; + LocalContext env; + + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + const v8::HeapSnapshot* s1 = + v8::HeapProfiler::TakeSnapshot(v8::String::New("1")); + CHECK_NE(NULL, s1); + CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); + unsigned uid1 = s1->GetUid(); + CHECK_EQ(s1, v8::HeapProfiler::FindSnapshot(uid1)); + const_cast(s1)->Delete(); + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid1)); + + const v8::HeapSnapshot* s2 = + v8::HeapProfiler::TakeSnapshot(v8::String::New("2")); + CHECK_NE(NULL, s2); + CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); + unsigned uid2 = s2->GetUid(); + CHECK_NE(static_cast(uid1), static_cast(uid2)); + CHECK_EQ(s2, v8::HeapProfiler::FindSnapshot(uid2)); + const v8::HeapSnapshot* s3 = + v8::HeapProfiler::TakeSnapshot(v8::String::New("3")); + CHECK_NE(NULL, s3); + CHECK_EQ(2, v8::HeapProfiler::GetSnapshotsCount()); + unsigned uid3 = s3->GetUid(); + CHECK_NE(static_cast(uid1), static_cast(uid3)); + CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3)); + const_cast(s2)->Delete(); + CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid2)); + CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3)); + const_cast(s3)->Delete(); + CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount()); + CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid3)); +} + #endif // ENABLE_LOGGING_AND_PROFILING -- 2.7.4