From c1903ce3322b6eebda29f39663ffd800b51e7559 Mon Sep 17 00:00:00 2001 From: "mikhail.naganov@gmail.com" Date: Mon, 20 Sep 2010 09:29:12 +0000 Subject: [PATCH] Show RegExp calls in the profile. It turns out they were filtered out. But when I unfiltered them, I discovered another issue: when DevTools run, regexp literals get recompiled each time they called (looks like this is concerned with switching to full compiler), so I ended up having multiple entries for the same regexp. To fix this, I changed the way of how code entries equivalence is considered. BUG=crbug/55999 TEST=cctest/test-profile-generator/ProfileNodeFindOrAddChildForSameFunction (the test isn't for the whole issue, but rather for equivalence testing) Review URL: http://codereview.chromium.org/3426008 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@5492 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/api.cc | 2 +- src/cpu-profiler-inl.h | 5 +---- src/profile-generator-inl.h | 6 ++---- src/profile-generator.cc | 22 ++++++++++++++++++++-- src/profile-generator.h | 11 +++++------ test/cctest/test-profile-generator.cc | 18 ++++++++++++++++++ 6 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/api.cc b/src/api.cc index e09d4c9..d6ed8ae 100644 --- a/src/api.cc +++ b/src/api.cc @@ -4433,7 +4433,7 @@ double CpuProfileNode::GetSelfSamplesCount() const { unsigned CpuProfileNode::GetCallUid() const { IsDeadCheck("v8::CpuProfileNode::GetCallUid"); - return reinterpret_cast(this)->entry()->call_uid(); + return reinterpret_cast(this)->entry()->GetCallUid(); } diff --git a/src/cpu-profiler-inl.h b/src/cpu-profiler-inl.h index cb7fdd8..5df5893 100644 --- a/src/cpu-profiler-inl.h +++ b/src/cpu-profiler-inl.h @@ -82,14 +82,11 @@ TickSample* ProfilerEventsProcessor::TickSampleEvent() { bool ProfilerEventsProcessor::FilterOutCodeCreateEvent( Logger::LogEventsAndTags tag) { - // In browser mode, leave only callbacks and non-native JS entries. - // We filter out regular expressions as currently we can't tell - // whether they origin from native scripts, so let's not confise people by - // showing them weird regexes they didn't wrote. return FLAG_prof_browser_mode && (tag != Logger::CALLBACK_TAG && tag != Logger::FUNCTION_TAG && tag != Logger::LAZY_COMPILE_TAG + && tag != Logger::REG_EXP_TAG && tag != Logger::SCRIPT_TAG); } diff --git a/src/profile-generator-inl.h b/src/profile-generator-inl.h index cef825d..cdfa9e2 100644 --- a/src/profile-generator-inl.h +++ b/src/profile-generator-inl.h @@ -46,8 +46,7 @@ const char* StringsStorage::GetFunctionName(const char* name) { CodeEntry::CodeEntry(int security_token_id) - : call_uid_(0), - tag_(Logger::FUNCTION_TAG), + : tag_(Logger::FUNCTION_TAG), name_prefix_(kEmptyNamePrefix), name_(""), resource_name_(""), @@ -62,8 +61,7 @@ CodeEntry::CodeEntry(Logger::LogEventsAndTags tag, const char* resource_name, int line_number, int security_token_id) - : call_uid_(next_call_uid_++), - tag_(tag), + : tag_(tag), name_prefix_(name_prefix), name_(name), resource_name_(resource_name), diff --git a/src/profile-generator.cc b/src/profile-generator.cc index f8fa23d..a7cb7a2 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -121,11 +121,9 @@ const char* StringsStorage::GetName(String* name) { const char* CodeEntry::kEmptyNamePrefix = ""; -unsigned CodeEntry::next_call_uid_ = 1; void CodeEntry::CopyData(const CodeEntry& source) { - call_uid_ = source.call_uid_; tag_ = source.tag_; name_prefix_ = source.name_prefix_; name_ = source.name_; @@ -134,6 +132,26 @@ void CodeEntry::CopyData(const CodeEntry& source) { } +uint32_t CodeEntry::GetCallUid() const { + uint32_t hash = ComputeIntegerHash(tag_); + hash ^= static_cast(reinterpret_cast(name_prefix_)); + hash ^= static_cast(reinterpret_cast(name_)); + hash ^= static_cast(reinterpret_cast(resource_name_)); + hash ^= static_cast(line_number_); + return hash; +} + + +bool CodeEntry::IsSameAs(CodeEntry* entry) const { + return this == entry + || (tag_ == entry->tag_ + && name_prefix_ == entry->name_prefix_ + && name_ == entry->name_ + && resource_name_ == entry->resource_name_ + && line_number_ == entry->line_number_); +} + + ProfileNode* ProfileNode::FindChild(CodeEntry* entry) { HashMap::Entry* map_entry = children_.Lookup(entry, CodeEntryHash(entry), false); diff --git a/src/profile-generator.h b/src/profile-generator.h index c2bc4ce..a2ac820 100644 --- a/src/profile-generator.h +++ b/src/profile-generator.h @@ -100,17 +100,17 @@ class CodeEntry { INLINE(const char* name() const) { return name_; } INLINE(const char* resource_name() const) { return resource_name_; } INLINE(int line_number() const) { return line_number_; } - INLINE(unsigned call_uid() const) { return call_uid_; } INLINE(int security_token_id() const) { return security_token_id_; } INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag)); void CopyData(const CodeEntry& source); + uint32_t GetCallUid() const; + bool IsSameAs(CodeEntry* entry) const; static const char* kEmptyNamePrefix; private: - unsigned call_uid_; Logger::LogEventsAndTags tag_; const char* name_prefix_; const char* name_; @@ -118,8 +118,6 @@ class CodeEntry { int line_number_; int security_token_id_; - static unsigned next_call_uid_; - DISALLOW_COPY_AND_ASSIGN(CodeEntry); }; @@ -147,11 +145,12 @@ class ProfileNode { private: INLINE(static bool CodeEntriesMatch(void* entry1, void* entry2)) { - return entry1 == entry2; + return reinterpret_cast(entry1)->IsSameAs( + reinterpret_cast(entry2)); } INLINE(static uint32_t CodeEntryHash(CodeEntry* entry)) { - return static_cast(reinterpret_cast(entry)); + return entry->GetCallUid(); } ProfileTree* tree_; diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc index b362202..d8f1c10 100644 --- a/test/cctest/test-profile-generator.cc +++ b/test/cctest/test-profile-generator.cc @@ -89,6 +89,24 @@ TEST(ProfileNodeFindOrAddChild) { } +TEST(ProfileNodeFindOrAddChildForSameFunction) { + ProfileNode node(NULL, NULL); + CodeEntry entry1(i::Logger::FUNCTION_TAG, "", "aaa", "", 0, + TokenEnumerator::kNoSecurityToken); + ProfileNode* childNode1 = node.FindOrAddChild(&entry1); + CHECK_NE(NULL, childNode1); + CHECK_EQ(childNode1, node.FindOrAddChild(&entry1)); + // The same function again. + CodeEntry entry2(i::Logger::FUNCTION_TAG, "", "aaa", "", 0, + TokenEnumerator::kNoSecurityToken); + CHECK_EQ(childNode1, node.FindOrAddChild(&entry2)); + // Now with a different security token. + CodeEntry entry3(i::Logger::FUNCTION_TAG, "", "aaa", "", 0, + TokenEnumerator::kNoSecurityToken + 1); + CHECK_EQ(childNode1, node.FindOrAddChild(&entry3)); +} + + namespace { class ProfileTreeTestHelper { -- 2.7.4