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
parent 5051d2c6
...@@ -131,6 +131,16 @@ class V8EXPORT CpuProfile { ...@@ -131,6 +131,16 @@ class V8EXPORT CpuProfile {
/** Returns the root node of the top down call tree. */ /** Returns the root node of the top down call tree. */
const CpuProfileNode* GetTopDownRoot() const; 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 { ...@@ -181,6 +191,13 @@ class V8EXPORT CpuProfiler {
static const CpuProfile* StopProfiling( static const CpuProfile* StopProfiling(
Handle<String> title, Handle<String> title,
Handle<Value> security_token = Handle<Value>()); 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 @@ class V8EXPORT HeapSnapshot { ...@@ -367,6 +384,13 @@ class V8EXPORT HeapSnapshot {
*/ */
const HeapSnapshotsDiff* CompareWith(const HeapSnapshot* snapshot) const; 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 * Prepare a serialized representation of the snapshot. The result
* is written into the stream provided in chunks of specified size. * is written into the stream provided in chunks of specified size.
...@@ -427,6 +451,12 @@ class V8EXPORT HeapProfiler { ...@@ -427,6 +451,12 @@ class V8EXPORT HeapProfiler {
HeapSnapshot::Type type = HeapSnapshot::kFull, HeapSnapshot::Type type = HeapSnapshot::kFull,
ActivityControl* control = NULL); 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. */ /** Binds a callback to embedder's class ID. */
static void DefineWrapperClass( static void DefineWrapperClass(
uint16_t class_id, uint16_t class_id,
......
...@@ -5078,6 +5078,18 @@ const CpuProfileNode* CpuProfileNode::GetChild(int index) const { ...@@ -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<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 { unsigned CpuProfile::GetUid() const {
i::Isolate* isolate = i::Isolate::Current(); i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::CpuProfile::GetUid"); IsDeadCheck(isolate, "v8::CpuProfile::GetUid");
...@@ -5157,6 +5169,13 @@ const CpuProfile* CpuProfiler::StopProfiling(Handle<String> title, ...@@ -5157,6 +5169,13 @@ const CpuProfile* CpuProfiler::StopProfiling(Handle<String> 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) { static i::HeapGraphEdge* ToInternal(const HeapGraphEdge* edge) {
return const_cast<i::HeapGraphEdge*>( return const_cast<i::HeapGraphEdge*>(
reinterpret_cast<const i::HeapGraphEdge*>(edge)); reinterpret_cast<const i::HeapGraphEdge*>(edge));
...@@ -5363,6 +5382,18 @@ static i::HeapSnapshot* ToInternal(const HeapSnapshot* snapshot) { ...@@ -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 { HeapSnapshot::Type HeapSnapshot::GetType() const {
i::Isolate* isolate = i::Isolate::Current(); i::Isolate* isolate = i::Isolate::Current();
IsDeadCheck(isolate, "v8::HeapSnapshot::GetType"); IsDeadCheck(isolate, "v8::HeapSnapshot::GetType");
...@@ -5472,6 +5503,13 @@ const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> title, ...@@ -5472,6 +5503,13 @@ const HeapSnapshot* HeapProfiler::TakeSnapshot(Handle<String> 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, void HeapProfiler::DefineWrapperClass(uint16_t class_id,
WrapperInfoCallback callback) { WrapperInfoCallback callback) {
i::Isolate::Current()->heap_profiler()->DefineWrapperClass(class_id, i::Isolate::Current()->heap_profiler()->DefineWrapperClass(class_id,
......
...@@ -331,6 +331,27 @@ TickSample* CpuProfiler::TickSampleEvent(Isolate* isolate) { ...@@ -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) { void CpuProfiler::CallbackEvent(String* name, Address entry_point) {
Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent( Isolate::Current()->cpu_profiler()->processor_->CallbackCreateEvent(
Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point); Logger::CALLBACK_TAG, CodeEntry::kEmptyNamePrefix, name, entry_point);
...@@ -452,6 +473,11 @@ CpuProfiler::~CpuProfiler() { ...@@ -452,6 +473,11 @@ CpuProfiler::~CpuProfiler() {
} }
void CpuProfiler::ResetProfiles() {
delete profiles_;
profiles_ = new CpuProfilesCollection();
}
void CpuProfiler::StartCollectingProfile(const char* title) { void CpuProfiler::StartCollectingProfile(const char* title) {
if (profiles_->StartProfiling(title, next_profile_uid_++)) { if (profiles_->StartProfiling(title, next_profile_uid_++)) {
StartProcessorIfNotStarted(); StartProcessorIfNotStarted();
...@@ -521,22 +547,25 @@ CpuProfile* CpuProfiler::StopCollectingProfile(Object* security_token, ...@@ -521,22 +547,25 @@ CpuProfile* CpuProfiler::StopCollectingProfile(Object* security_token,
void CpuProfiler::StopProcessorIfLastProfile(const char* title) { void CpuProfiler::StopProcessorIfLastProfile(const char* title) {
if (profiles_->IsLastProfile(title)) { if (profiles_->IsLastProfile(title)) StopProcessor();
Sampler* sampler = reinterpret_cast<Sampler*>(LOGGER->ticker_); }
sampler->DecreaseProfilingDepth();
if (need_to_stop_sampler_) {
sampler->Stop(); void CpuProfiler::StopProcessor() {
need_to_stop_sampler_ = false; Sampler* sampler = reinterpret_cast<Sampler*>(LOGGER->ticker_);
} sampler->DecreaseProfilingDepth();
processor_->Stop(); if (need_to_stop_sampler_) {
processor_->Join(); sampler->Stop();
delete processor_; need_to_stop_sampler_ = false;
delete generator_;
processor_ = NULL;
NoBarrier_Store(&is_profiling_, false);
generator_ = NULL;
LOGGER->logging_nesting_ = saved_logging_nesting_;
} }
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 } } // namespace v8::internal
......
...@@ -227,6 +227,9 @@ class CpuProfiler { ...@@ -227,6 +227,9 @@ class CpuProfiler {
static int GetProfilesCount(); static int GetProfilesCount();
static CpuProfile* GetProfile(Object* security_token, int index); static CpuProfile* GetProfile(Object* security_token, int index);
static CpuProfile* FindProfile(Object* security_token, unsigned uid); 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.) // Invoked from stack sampler (thread or signal handler.)
static TickSample* TickSampleEvent(Isolate* isolate); static TickSample* TickSampleEvent(Isolate* isolate);
...@@ -276,6 +279,8 @@ class CpuProfiler { ...@@ -276,6 +279,8 @@ class CpuProfiler {
CpuProfile* StopCollectingProfile(const char* title); CpuProfile* StopCollectingProfile(const char* title);
CpuProfile* StopCollectingProfile(Object* security_token, String* title); CpuProfile* StopCollectingProfile(Object* security_token, String* title);
void StopProcessorIfLastProfile(const char* title); void StopProcessorIfLastProfile(const char* title);
void StopProcessor();
void ResetProfiles();
CpuProfilesCollection* profiles_; CpuProfilesCollection* profiles_;
unsigned next_profile_uid_; unsigned next_profile_uid_;
......
...@@ -326,6 +326,13 @@ HeapProfiler::~HeapProfiler() { ...@@ -326,6 +326,13 @@ HeapProfiler::~HeapProfiler() {
delete snapshots_; delete snapshots_;
} }
void HeapProfiler::ResetSnapshots() {
delete snapshots_;
snapshots_ = new HeapSnapshotsCollection();
}
#endif // ENABLE_LOGGING_AND_PROFILING #endif // ENABLE_LOGGING_AND_PROFILING
void HeapProfiler::Setup() { void HeapProfiler::Setup() {
...@@ -450,6 +457,13 @@ HeapSnapshot* HeapProfiler::FindSnapshot(unsigned uid) { ...@@ -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) { void HeapProfiler::ObjectMoveEvent(Address from, Address to) {
snapshots_->ObjectMoveEvent(from, to); snapshots_->ObjectMoveEvent(from, to);
} }
......
...@@ -67,6 +67,7 @@ class HeapProfiler { ...@@ -67,6 +67,7 @@ class HeapProfiler {
static int GetSnapshotsCount(); static int GetSnapshotsCount();
static HeapSnapshot* GetSnapshot(int index); static HeapSnapshot* GetSnapshot(int index);
static HeapSnapshot* FindSnapshot(unsigned uid); static HeapSnapshot* FindSnapshot(unsigned uid);
static void DeleteAllSnapshots();
void ObjectMoveEvent(Address from, Address to); void ObjectMoveEvent(Address from, Address to);
...@@ -92,6 +93,7 @@ class HeapProfiler { ...@@ -92,6 +93,7 @@ class HeapProfiler {
HeapSnapshot* TakeSnapshotImpl(String* name, HeapSnapshot* TakeSnapshotImpl(String* name,
int type, int type,
v8::ActivityControl* control); v8::ActivityControl* control);
void ResetSnapshots();
HeapSnapshotsCollection* snapshots_; HeapSnapshotsCollection* snapshots_;
unsigned next_snapshot_uid_; unsigned next_snapshot_uid_;
......
...@@ -320,7 +320,7 @@ struct NodesPair { ...@@ -320,7 +320,7 @@ struct NodesPair {
class FilteredCloneCallback { class FilteredCloneCallback {
public: public:
explicit FilteredCloneCallback(ProfileNode* dst_root, int security_token_id) FilteredCloneCallback(ProfileNode* dst_root, int security_token_id)
: stack_(10), : stack_(10),
security_token_id_(security_token_id) { security_token_id_(security_token_id) {
stack_.Add(NodesPair(NULL, dst_root)); stack_.Add(NodesPair(NULL, dst_root));
...@@ -550,13 +550,16 @@ static void DeleteCpuProfile(CpuProfile** profile_ptr) { ...@@ -550,13 +550,16 @@ static void DeleteCpuProfile(CpuProfile** profile_ptr) {
} }
static void DeleteProfilesList(List<CpuProfile*>** list_ptr) { static void DeleteProfilesList(List<CpuProfile*>** list_ptr) {
(*list_ptr)->Iterate(DeleteCpuProfile); if (*list_ptr != NULL) {
delete *list_ptr; (*list_ptr)->Iterate(DeleteCpuProfile);
delete *list_ptr;
}
} }
CpuProfilesCollection::~CpuProfilesCollection() { CpuProfilesCollection::~CpuProfilesCollection() {
delete current_profiles_semaphore_; delete current_profiles_semaphore_;
current_profiles_.Iterate(DeleteCpuProfile); current_profiles_.Iterate(DeleteCpuProfile);
detached_profiles_.Iterate(DeleteCpuProfile);
profiles_by_token_.Iterate(DeleteProfilesList); profiles_by_token_.Iterate(DeleteProfilesList);
code_entries_.Iterate(DeleteCodeEntry); code_entries_.Iterate(DeleteCodeEntry);
} }
...@@ -621,15 +624,8 @@ CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id, ...@@ -621,15 +624,8 @@ CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id,
CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id, CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id,
unsigned uid) { unsigned uid) {
HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid), int index = GetProfileIndex(uid);
static_cast<uint32_t>(uid), if (index < 0) return NULL;
false);
int index;
if (entry != NULL) {
index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
} else {
return NULL;
}
List<CpuProfile*>* unabridged_list = List<CpuProfile*>* unabridged_list =
profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)]; profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
if (security_token_id == TokenEnumerator::kNoSecurityToken) { if (security_token_id == TokenEnumerator::kNoSecurityToken) {
...@@ -644,6 +640,15 @@ CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id, ...@@ -644,6 +640,15 @@ CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id,
} }
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) { bool CpuProfilesCollection::IsLastProfile(const char* title) {
// Called from VM thread, and only it can mutate the list, // Called from VM thread, and only it can mutate the list,
// so no locking is needed here. // so no locking is needed here.
...@@ -653,6 +658,39 @@ bool CpuProfilesCollection::IsLastProfile(const char* title) { ...@@ -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<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) { int CpuProfilesCollection::TokenToIndex(int security_token_id) {
ASSERT(TokenEnumerator::kNoSecurityToken == -1); ASSERT(TokenEnumerator::kNoSecurityToken == -1);
return security_token_id + 1; // kNoSecurityToken -> 0, 0 -> 1, ... return security_token_id + 1; // kNoSecurityToken -> 0, 0 -> 1, ...
...@@ -1268,6 +1306,12 @@ HeapSnapshot::~HeapSnapshot() { ...@@ -1268,6 +1306,12 @@ HeapSnapshot::~HeapSnapshot() {
} }
void HeapSnapshot::Delete() {
collection_->RemoveSnapshot(this);
delete this;
}
void HeapSnapshot::AllocateEntries(int entries_count, void HeapSnapshot::AllocateEntries(int entries_count,
int children_count, int children_count,
int retainers_count) { int retainers_count) {
...@@ -1579,6 +1623,14 @@ HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) { ...@@ -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<void*>(uid),
static_cast<uint32_t>(uid));
}
HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots( HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots(
HeapSnapshot* snapshot1, HeapSnapshot* snapshot1,
HeapSnapshot* snapshot2) { HeapSnapshot* snapshot2) {
......
...@@ -300,6 +300,8 @@ class CpuProfilesCollection { ...@@ -300,6 +300,8 @@ class CpuProfilesCollection {
} }
CpuProfile* GetProfile(int security_token_id, unsigned uid); CpuProfile* GetProfile(int security_token_id, unsigned uid);
bool IsLastProfile(const char* title); bool IsLastProfile(const char* title);
void RemoveProfile(CpuProfile* profile);
bool HasDetachedProfiles() { return detached_profiles_.length() > 0; }
CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag, CodeEntry* NewCodeEntry(Logger::LogEventsAndTags tag,
String* name, String* resource_name, int line_number); String* name, String* resource_name, int line_number);
...@@ -322,6 +324,7 @@ class CpuProfilesCollection { ...@@ -322,6 +324,7 @@ class CpuProfilesCollection {
const char* GetFunctionName(const char* name) { const char* GetFunctionName(const char* name) {
return function_and_resource_names_.GetFunctionName(name); return function_and_resource_names_.GetFunctionName(name);
} }
int GetProfileIndex(unsigned uid);
List<CpuProfile*>* GetProfilesList(int security_token_id); List<CpuProfile*>* GetProfilesList(int security_token_id);
int TokenToIndex(int security_token_id); int TokenToIndex(int security_token_id);
...@@ -335,6 +338,7 @@ class CpuProfilesCollection { ...@@ -335,6 +338,7 @@ class CpuProfilesCollection {
// Mapping from profiles' uids to indexes in the second nested list // Mapping from profiles' uids to indexes in the second nested list
// of profiles_by_token_. // of profiles_by_token_.
HashMap profiles_uids_; HashMap profiles_uids_;
List<CpuProfile*> detached_profiles_;
// Accessed by VM thread and profile generator thread. // Accessed by VM thread and profile generator thread.
List<CpuProfile*> current_profiles_; List<CpuProfile*> current_profiles_;
...@@ -673,6 +677,7 @@ class HeapSnapshot { ...@@ -673,6 +677,7 @@ class HeapSnapshot {
const char* title, const char* title,
unsigned uid); unsigned uid);
~HeapSnapshot(); ~HeapSnapshot();
void Delete();
HeapSnapshotsCollection* collection() { return collection_; } HeapSnapshotsCollection* collection() { return collection_; }
Type type() { return type_; } Type type() { return type_; }
...@@ -840,6 +845,7 @@ class HeapSnapshotsCollection { ...@@ -840,6 +845,7 @@ class HeapSnapshotsCollection {
void SnapshotGenerationFinished(HeapSnapshot* snapshot); void SnapshotGenerationFinished(HeapSnapshot* snapshot);
List<HeapSnapshot*>* snapshots() { return &snapshots_; } List<HeapSnapshot*>* snapshots() { return &snapshots_; }
HeapSnapshot* GetSnapshot(unsigned uid); HeapSnapshot* GetSnapshot(unsigned uid);
void RemoveSnapshot(HeapSnapshot* snapshot);
StringsStorage* names() { return &names_; } StringsStorage* names() { return &names_; }
TokenEnumerator* token_enumerator() { return token_enumerator_; } TokenEnumerator* token_enumerator() { return token_enumerator_; }
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "v8.h" #include "v8.h"
#include "cpu-profiler-inl.h" #include "cpu-profiler-inl.h"
#include "cctest.h" #include "cctest.h"
#include "../include/v8-profiler.h"
namespace i = v8::internal; namespace i = v8::internal;
...@@ -236,4 +237,138 @@ TEST(CrashIfStoppingLastNonExistentProfile) { ...@@ -236,4 +237,138 @@ TEST(CrashIfStoppingLastNonExistentProfile) {
CpuProfiler::TearDown(); 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 #endif // ENABLE_LOGGING_AND_PROFILING
...@@ -1395,4 +1395,62 @@ TEST(HeapSnapshotRetainedObjectInfo) { ...@@ -1395,4 +1395,62 @@ TEST(HeapSnapshotRetainedObjectInfo) {
CHECK_EQ(ccc, GetProperty(n_CCC, 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 #endif // ENABLE_LOGGING_AND_PROFILING
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment