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
This commit is contained in:
mikhail.naganov@gmail.com 2010-09-20 09:29:12 +00:00
parent fc9915b770
commit c1903ce332
6 changed files with 47 additions and 17 deletions

View File

@ -4433,7 +4433,7 @@ double CpuProfileNode::GetSelfSamplesCount() const {
unsigned CpuProfileNode::GetCallUid() const { unsigned CpuProfileNode::GetCallUid() const {
IsDeadCheck("v8::CpuProfileNode::GetCallUid"); IsDeadCheck("v8::CpuProfileNode::GetCallUid");
return reinterpret_cast<const i::ProfileNode*>(this)->entry()->call_uid(); return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
} }

View File

@ -82,14 +82,11 @@ TickSample* ProfilerEventsProcessor::TickSampleEvent() {
bool ProfilerEventsProcessor::FilterOutCodeCreateEvent( bool ProfilerEventsProcessor::FilterOutCodeCreateEvent(
Logger::LogEventsAndTags tag) { 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 return FLAG_prof_browser_mode
&& (tag != Logger::CALLBACK_TAG && (tag != Logger::CALLBACK_TAG
&& tag != Logger::FUNCTION_TAG && tag != Logger::FUNCTION_TAG
&& tag != Logger::LAZY_COMPILE_TAG && tag != Logger::LAZY_COMPILE_TAG
&& tag != Logger::REG_EXP_TAG
&& tag != Logger::SCRIPT_TAG); && tag != Logger::SCRIPT_TAG);
} }

View File

@ -46,8 +46,7 @@ const char* StringsStorage::GetFunctionName(const char* name) {
CodeEntry::CodeEntry(int security_token_id) CodeEntry::CodeEntry(int security_token_id)
: call_uid_(0), : tag_(Logger::FUNCTION_TAG),
tag_(Logger::FUNCTION_TAG),
name_prefix_(kEmptyNamePrefix), name_prefix_(kEmptyNamePrefix),
name_(""), name_(""),
resource_name_(""), resource_name_(""),
@ -62,8 +61,7 @@ CodeEntry::CodeEntry(Logger::LogEventsAndTags tag,
const char* resource_name, const char* resource_name,
int line_number, int line_number,
int security_token_id) int security_token_id)
: call_uid_(next_call_uid_++), : tag_(tag),
tag_(tag),
name_prefix_(name_prefix), name_prefix_(name_prefix),
name_(name), name_(name),
resource_name_(resource_name), resource_name_(resource_name),

View File

@ -121,11 +121,9 @@ const char* StringsStorage::GetName(String* name) {
const char* CodeEntry::kEmptyNamePrefix = ""; const char* CodeEntry::kEmptyNamePrefix = "";
unsigned CodeEntry::next_call_uid_ = 1;
void CodeEntry::CopyData(const CodeEntry& source) { void CodeEntry::CopyData(const CodeEntry& source) {
call_uid_ = source.call_uid_;
tag_ = source.tag_; tag_ = source.tag_;
name_prefix_ = source.name_prefix_; name_prefix_ = source.name_prefix_;
name_ = source.name_; 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<int32_t>(reinterpret_cast<intptr_t>(name_prefix_));
hash ^= static_cast<int32_t>(reinterpret_cast<intptr_t>(name_));
hash ^= static_cast<int32_t>(reinterpret_cast<intptr_t>(resource_name_));
hash ^= static_cast<int32_t>(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) { ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
HashMap::Entry* map_entry = HashMap::Entry* map_entry =
children_.Lookup(entry, CodeEntryHash(entry), false); children_.Lookup(entry, CodeEntryHash(entry), false);

View File

@ -100,17 +100,17 @@ class CodeEntry {
INLINE(const char* name() const) { return name_; } INLINE(const char* name() const) { return name_; }
INLINE(const char* resource_name() const) { return resource_name_; } INLINE(const char* resource_name() const) { return resource_name_; }
INLINE(int line_number() const) { return line_number_; } 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(int security_token_id() const) { return security_token_id_; }
INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag)); INLINE(static bool is_js_function_tag(Logger::LogEventsAndTags tag));
void CopyData(const CodeEntry& source); void CopyData(const CodeEntry& source);
uint32_t GetCallUid() const;
bool IsSameAs(CodeEntry* entry) const;
static const char* kEmptyNamePrefix; static const char* kEmptyNamePrefix;
private: private:
unsigned call_uid_;
Logger::LogEventsAndTags tag_; Logger::LogEventsAndTags tag_;
const char* name_prefix_; const char* name_prefix_;
const char* name_; const char* name_;
@ -118,8 +118,6 @@ class CodeEntry {
int line_number_; int line_number_;
int security_token_id_; int security_token_id_;
static unsigned next_call_uid_;
DISALLOW_COPY_AND_ASSIGN(CodeEntry); DISALLOW_COPY_AND_ASSIGN(CodeEntry);
}; };
@ -147,11 +145,12 @@ class ProfileNode {
private: private:
INLINE(static bool CodeEntriesMatch(void* entry1, void* entry2)) { INLINE(static bool CodeEntriesMatch(void* entry1, void* entry2)) {
return entry1 == entry2; return reinterpret_cast<CodeEntry*>(entry1)->IsSameAs(
reinterpret_cast<CodeEntry*>(entry2));
} }
INLINE(static uint32_t CodeEntryHash(CodeEntry* entry)) { INLINE(static uint32_t CodeEntryHash(CodeEntry* entry)) {
return static_cast<int32_t>(reinterpret_cast<intptr_t>(entry)); return entry->GetCallUid();
} }
ProfileTree* tree_; ProfileTree* tree_;

View File

@ -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 { namespace {
class ProfileTreeTestHelper { class ProfileTreeTestHelper {