Revision: 7308
Author:   [email protected]
Date:     Tue Mar 22 09:10:01 2011
Log:      Add support for CPU and heap profiles deletion.

[email protected]
BUG=none
TEST=none

Review URL: http://codereview.chromium.org/6685084
http://code.google.com/p/v8/source/detail?r=7308

Modified:
 /branches/bleeding_edge/include/v8-profiler.h
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/cpu-profiler.cc
 /branches/bleeding_edge/src/cpu-profiler.h
 /branches/bleeding_edge/src/heap-profiler.cc
 /branches/bleeding_edge/src/heap-profiler.h
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/src/profile-generator.h
 /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc
 /branches/bleeding_edge/test/cctest/test-heap-profiler.cc

=======================================
--- /branches/bleeding_edge/include/v8-profiler.h       Thu Mar 10 04:05:31 2011
+++ /branches/bleeding_edge/include/v8-profiler.h       Tue Mar 22 09:10:01 2011
@@ -131,6 +131,16 @@

   /** 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 @@
   static const CpuProfile* StopProfiling(
       Handle<String> title,
       Handle<Value> security_token = Handle<Value>());
+
+  /**
+   * 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();
 };


@@ -367,6 +384,13 @@
    */
   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.
@@ -427,6 +451,12 @@
       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,
=======================================
--- /branches/bleeding_edge/src/api.cc  Tue Mar 22 08:16:29 2011
+++ /branches/bleeding_edge/src/api.cc  Tue Mar 22 09:10:01 2011
@@ -5076,6 +5076,18 @@
       reinterpret_cast<const i::ProfileNode*>(this)->children()->at(index);
   return reinterpret_cast<const CpuProfileNode*>(child);
 }
+
+
+void CpuProfile::Delete() {
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::CpuProfile::Delete");
+  i::CpuProfiler::DeleteProfile(reinterpret_cast<i::CpuProfile*>(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 {
@@ -5155,6 +5167,13 @@
security_token.IsEmpty() ? NULL : *Utils::OpenHandle(*security_token),
           *Utils::OpenHandle(*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) {
@@ -5361,6 +5380,18 @@
   return const_cast<i::HeapSnapshot*>(
       reinterpret_cast<const i::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 {
@@ -5470,6 +5501,13 @@
       i::HeapProfiler::TakeSnapshot(
           *Utils::OpenHandle(*title), internal_type, control));
 }
+
+
+void HeapProfiler::DeleteAllSnapshots() {
+  i::Isolate* isolate = i::Isolate::Current();
+  IsDeadCheck(isolate, "v8::HeapProfiler::DeleteAllSnapshots");
+  i::HeapProfiler::DeleteAllSnapshots();
+}


 void HeapProfiler::DefineWrapperClass(uint16_t class_id,
=======================================
--- /branches/bleeding_edge/src/cpu-profiler.cc Mon Mar 21 10:40:40 2011
+++ /branches/bleeding_edge/src/cpu-profiler.cc Tue Mar 22 09:10:01 2011
@@ -329,6 +329,27 @@
     return NULL;
   }
 }
+
+
+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) {
@@ -452,6 +473,11 @@
 }


+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 @@


 void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
-  if (profiles_->IsLastProfile(title)) {
-    Sampler* sampler = reinterpret_cast<Sampler*>(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<Sampler*>(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
=======================================
--- /branches/bleeding_edge/src/cpu-profiler.h  Mon Mar 21 10:40:40 2011
+++ /branches/bleeding_edge/src/cpu-profiler.h  Tue Mar 22 09:10:01 2011
@@ -227,6 +227,9 @@
   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 @@
   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_;
=======================================
--- /branches/bleeding_edge/src/heap-profiler.cc        Fri Mar 18 13:35:07 2011
+++ /branches/bleeding_edge/src/heap-profiler.cc        Tue Mar 22 09:10:01 2011
@@ -325,6 +325,13 @@
 HeapProfiler::~HeapProfiler() {
   delete snapshots_;
 }
+
+
+void HeapProfiler::ResetSnapshots() {
+  delete snapshots_;
+  snapshots_ = new HeapSnapshotsCollection();
+}
+

 #endif  // ENABLE_LOGGING_AND_PROFILING

@@ -448,6 +455,13 @@
   ASSERT(profiler != NULL);
   return profiler->snapshots_->GetSnapshot(uid);
 }
+
+
+void HeapProfiler::DeleteAllSnapshots() {
+  HeapProfiler* profiler = Isolate::Current()->heap_profiler();
+  ASSERT(profiler != NULL);
+  profiler->ResetSnapshots();
+}


 void HeapProfiler::ObjectMoveEvent(Address from, Address to) {
=======================================
--- /branches/bleeding_edge/src/heap-profiler.h Fri Mar 18 13:35:07 2011
+++ /branches/bleeding_edge/src/heap-profiler.h Tue Mar 22 09:10:01 2011
@@ -67,6 +67,7 @@
   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 @@
   HeapSnapshot* TakeSnapshotImpl(String* name,
                                  int type,
                                  v8::ActivityControl* control);
+  void ResetSnapshots();

   HeapSnapshotsCollection* snapshots_;
   unsigned next_snapshot_uid_;
=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Mon Mar 21 11:13:27 2011 +++ /branches/bleeding_edge/src/profile-generator.cc Tue Mar 22 09:10:01 2011
@@ -320,7 +320,7 @@

 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 DeleteProfilesList(List<CpuProfile*>** 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::GetProfile(int security_token_id,
                                               unsigned uid) {
- HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
-                                                static_cast<uint32_t>(uid),
-                                                false);
-  int index;
-  if (entry != NULL) {
-    index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
-  } else {
-    return NULL;
-  }
+  int index = GetProfileIndex(uid);
+  if (index < 0) return NULL;
   List<CpuProfile*>* unabridged_list =
       profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
   if (security_token_id == TokenEnumerator::kNoSecurityToken) {
@@ -642,6 +638,15 @@
   }
   return list->at(index);
 }
+
+
+int CpuProfilesCollection::GetProfileIndex(unsigned uid) {
+ HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
+                                                static_cast<uint32_t>(uid),
+                                                false);
+  return entry != NULL ?
+      static_cast<int>(reinterpret_cast<intptr_t>(entry->value)) : -1;
+}


 bool CpuProfilesCollection::IsLastProfile(const char* title) {
@@ -651,6 +656,39 @@
   return StrLength(title) == 0
       || strcmp(current_profiles_[0]->title(), title) == 0;
 }
+
+
+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<void*>(uid),
+                        static_cast<uint32_t>(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<intptr_t>(p->value);
+    if (p_index > index) {
+      p->value = reinterpret_cast<void*>(p_index - 1);
+    }
+  }
+  for (int i = 0; i < profiles_by_token_.length(); ++i) {
+    List<CpuProfile*>* 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) {
@@ -1266,6 +1304,12 @@
     delete list;
   }
 }
+
+
+void HeapSnapshot::Delete() {
+  collection_->RemoveSnapshot(this);
+  delete this;
+}


 void HeapSnapshot::AllocateEntries(int entries_count,
@@ -1577,6 +1621,14 @@
                                                  false);
return entry != NULL ? reinterpret_cast<HeapSnapshot*>(entry->value) : NULL;
 }
+
+
+void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) {
+  snapshots_.RemoveElement(snapshot);
+  unsigned uid = snapshot->uid();
+  snapshots_uids_.Remove(reinterpret_cast<void*>(uid),
+                         static_cast<uint32_t>(uid));
+}


 HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots(
=======================================
--- /branches/bleeding_edge/src/profile-generator.h     Fri Mar 18 13:35:07 2011
+++ /branches/bleeding_edge/src/profile-generator.h     Tue Mar 22 09:10:01 2011
@@ -300,6 +300,8 @@
   }
   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 @@
   const char* GetFunctionName(const char* name) {
     return function_and_resource_names_.GetFunctionName(name);
   }
+  int GetProfileIndex(unsigned uid);
   List<CpuProfile*>* GetProfilesList(int security_token_id);
   int TokenToIndex(int security_token_id);

@@ -335,6 +338,7 @@
   // Mapping from profiles' uids to indexes in the second nested list
   // of profiles_by_token_.
   HashMap profiles_uids_;
+  List<CpuProfile*> detached_profiles_;

   // Accessed by VM thread and profile generator thread.
   List<CpuProfile*> current_profiles_;
@@ -673,6 +677,7 @@
                const char* title,
                unsigned uid);
   ~HeapSnapshot();
+  void Delete();

   HeapSnapshotsCollection* collection() { return collection_; }
   Type type() { return type_; }
@@ -840,6 +845,7 @@
   void SnapshotGenerationFinished(HeapSnapshot* snapshot);
   List<HeapSnapshot*>* snapshots() { return &snapshots_; }
   HeapSnapshot* GetSnapshot(unsigned uid);
+  void RemoveSnapshot(HeapSnapshot* snapshot);

   StringsStorage* names() { return &names_; }
   TokenEnumerator* token_enumerator() { return token_enumerator_; }
=======================================
--- /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc Fri Mar 18 13:35:07 2011 +++ /branches/bleeding_edge/test/cctest/test-cpu-profiler.cc Tue Mar 22 09:10:01 2011
@@ -7,6 +7,7 @@
 #include "v8.h"
 #include "cpu-profiler-inl.h"
 #include "cctest.h"
+#include "../include/v8-profiler.h"

 namespace i = v8::internal;

@@ -235,5 +236,139 @@
   CpuProfiler::StopProfiling("");
   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<v8::String> 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<v8::CpuProfile*>(p1)->Delete();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+
+  v8::Local<v8::String> 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<int>(uid1), static_cast<int>(uid2));
+  CHECK_EQ(p2, v8::CpuProfiler::FindProfile(uid2));
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+  v8::Local<v8::String> 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<int>(uid1), static_cast<int>(uid3));
+  CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+  const_cast<v8::CpuProfile*>(p2)->Delete();
+  CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
+  CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+  const_cast<v8::CpuProfile*>(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<v8::String> 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<v8::String> 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<v8::CpuProfile*>(p1)->Delete();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1));
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid1, token1));
+  const_cast<v8::CpuProfile*>(p1_t1)->Delete();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+
+  v8::Local<v8::String> name2 = v8::String::New("2");
+  v8::CpuProfiler::StartProfiling(name2);
+  v8::Local<v8::String> 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<int>(uid1), static_cast<int>(uid2));
+  const v8::CpuProfile* p2 = v8::CpuProfiler::FindProfile(uid2);
+  CHECK_NE(p2_t2, p2);
+  v8::Local<v8::String> 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<int>(uid1), static_cast<int>(uid3));
+  CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+  const_cast<v8::CpuProfile*>(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<v8::CpuProfile*>(p2)->Delete();
+  CHECK_EQ(1, v8::CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid2));
+  CHECK_EQ(p3, v8::CpuProfiler::FindProfile(uid3));
+  const_cast<v8::CpuProfile*>(p3)->Delete();
+  CHECK_EQ(0, CpuProfiler::GetProfilesCount());
+  CHECK_EQ(NULL, v8::CpuProfiler::FindProfile(uid3));
+}

 #endif  // ENABLE_LOGGING_AND_PROFILING
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Fri Mar 18 13:35:07 2011 +++ /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Tue Mar 22 09:10:01 2011
@@ -1394,5 +1394,63 @@
CHECK_EQ(aaa, GetProperty(n_BBB, v8::HeapGraphEdge::kInternal, "Native")); 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<v8::HeapSnapshot*>(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<int>(uid1), static_cast<int>(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<int>(uid1), static_cast<int>(uid3));
+  CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3));
+  const_cast<v8::HeapSnapshot*>(s2)->Delete();
+  CHECK_EQ(1, v8::HeapProfiler::GetSnapshotsCount());
+  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid2));
+  CHECK_EQ(s3, v8::HeapProfiler::FindSnapshot(uid3));
+  const_cast<v8::HeapSnapshot*>(s3)->Delete();
+  CHECK_EQ(0, v8::HeapProfiler::GetSnapshotsCount());
+  CHECK_EQ(NULL, v8::HeapProfiler::FindSnapshot(uid3));
+}

 #endif  // ENABLE_LOGGING_AND_PROFILING

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to