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
unsigned CpuProfileNode::GetCallUid() const {
IsDeadCheck("v8::CpuProfileNode::GetCallUid");
- return reinterpret_cast<const i::ProfileNode*>(this)->entry()->call_uid();
+ return reinterpret_cast<const i::ProfileNode*>(this)->entry()->GetCallUid();
}
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);
}
CodeEntry::CodeEntry(int security_token_id)
- : call_uid_(0),
- tag_(Logger::FUNCTION_TAG),
+ : tag_(Logger::FUNCTION_TAG),
name_prefix_(kEmptyNamePrefix),
name_(""),
resource_name_(""),
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),
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_;
}
+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) {
HashMap::Entry* map_entry =
children_.Lookup(entry, CodeEntryHash(entry), false);
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_;
int line_number_;
int security_token_id_;
- static unsigned next_call_uid_;
-
DISALLOW_COPY_AND_ASSIGN(CodeEntry);
};
private:
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)) {
- return static_cast<int32_t>(reinterpret_cast<intptr_t>(entry));
+ return entry->GetCallUid();
}
ProfileTree* tree_;
}
+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 {