Merge V8 5.3.332.45. DO NOT MERGE
Test: Manual
FPIIM-449
Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/profiler/profile-generator.cc b/src/profiler/profile-generator.cc
index b07601f..d40cf2a 100644
--- a/src/profiler/profile-generator.cc
+++ b/src/profiler/profile-generator.cc
@@ -9,9 +9,9 @@
#include "src/debug/debug.h"
#include "src/deoptimizer.h"
#include "src/global-handles.h"
+#include "src/profiler/cpu-profiler.h"
#include "src/profiler/profile-generator-inl.h"
#include "src/profiler/tick-sample.h"
-#include "src/splay-tree-inl.h"
#include "src/unicode.h"
namespace v8 {
@@ -48,6 +48,41 @@
const char* const CodeEntry::kEmptyBailoutReason = "";
const char* const CodeEntry::kNoDeoptReason = "";
+const char* const CodeEntry::kProgramEntryName = "(program)";
+const char* const CodeEntry::kIdleEntryName = "(idle)";
+const char* const CodeEntry::kGarbageCollectorEntryName = "(garbage collector)";
+const char* const CodeEntry::kUnresolvedFunctionName = "(unresolved function)";
+
+base::LazyDynamicInstance<CodeEntry, CodeEntry::ProgramEntryCreateTrait>::type
+ CodeEntry::kProgramEntry = LAZY_DYNAMIC_INSTANCE_INITIALIZER;
+
+base::LazyDynamicInstance<CodeEntry, CodeEntry::IdleEntryCreateTrait>::type
+ CodeEntry::kIdleEntry = LAZY_DYNAMIC_INSTANCE_INITIALIZER;
+
+base::LazyDynamicInstance<CodeEntry, CodeEntry::GCEntryCreateTrait>::type
+ CodeEntry::kGCEntry = LAZY_DYNAMIC_INSTANCE_INITIALIZER;
+
+base::LazyDynamicInstance<CodeEntry,
+ CodeEntry::UnresolvedEntryCreateTrait>::type
+ CodeEntry::kUnresolvedEntry = LAZY_DYNAMIC_INSTANCE_INITIALIZER;
+
+CodeEntry* CodeEntry::ProgramEntryCreateTrait::Create() {
+ return new CodeEntry(Logger::FUNCTION_TAG, CodeEntry::kProgramEntryName);
+}
+
+CodeEntry* CodeEntry::IdleEntryCreateTrait::Create() {
+ return new CodeEntry(Logger::FUNCTION_TAG, CodeEntry::kIdleEntryName);
+}
+
+CodeEntry* CodeEntry::GCEntryCreateTrait::Create() {
+ return new CodeEntry(Logger::BUILTIN_TAG,
+ CodeEntry::kGarbageCollectorEntryName);
+}
+
+CodeEntry* CodeEntry::UnresolvedEntryCreateTrait::Create() {
+ return new CodeEntry(Logger::FUNCTION_TAG,
+ CodeEntry::kUnresolvedFunctionName);
+}
CodeEntry::~CodeEntry() {
delete line_info_;
@@ -94,7 +129,7 @@
void CodeEntry::SetBuiltinId(Builtins::Name id) {
- bit_field_ = TagField::update(bit_field_, Logger::BUILTIN_TAG);
+ bit_field_ = TagField::update(bit_field_, CodeEventListener::BUILTIN_TAG);
bit_field_ = BuiltinIdField::update(bit_field_, id);
}
@@ -170,14 +205,15 @@
ProfileNode* ProfileNode::FindChild(CodeEntry* entry) {
- HashMap::Entry* map_entry = children_.Lookup(entry, CodeEntryHash(entry));
+ base::HashMap::Entry* map_entry =
+ children_.Lookup(entry, CodeEntryHash(entry));
return map_entry != NULL ?
reinterpret_cast<ProfileNode*>(map_entry->value) : NULL;
}
ProfileNode* ProfileNode::FindOrAddChild(CodeEntry* entry) {
- HashMap::Entry* map_entry =
+ base::HashMap::Entry* map_entry =
children_.LookupOrInsert(entry, CodeEntryHash(entry));
ProfileNode* node = reinterpret_cast<ProfileNode*>(map_entry->value);
if (node == NULL) {
@@ -194,7 +230,7 @@
if (src_line == v8::CpuProfileNode::kNoLineNumberInfo) return;
// Increment a hit counter of a certain source line.
// Add a new source line if not found.
- HashMap::Entry* e =
+ base::HashMap::Entry* e =
line_ticks_.LookupOrInsert(reinterpret_cast<void*>(src_line), src_line);
DCHECK(e);
e->value = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(e->value) + 1);
@@ -212,7 +248,7 @@
v8::CpuProfileNode::LineTick* entry = entries;
- for (HashMap::Entry* p = line_ticks_.Start(); p != NULL;
+ for (base::HashMap::Entry *p = line_ticks_.Start(); p != NULL;
p = line_ticks_.Next(p), entry++) {
entry->line =
static_cast<unsigned int>(reinterpret_cast<uintptr_t>(p->key));
@@ -250,8 +286,7 @@
base::OS::Print("%*s bailed out due to '%s'\n", indent + 10, "",
bailout_reason);
}
- for (HashMap::Entry* p = children_.Start();
- p != NULL;
+ for (base::HashMap::Entry* p = children_.Start(); p != NULL;
p = children_.Next(p)) {
reinterpret_cast<ProfileNode*>(p->value)->Print(indent + 2);
}
@@ -269,16 +304,14 @@
void AfterChildTraversed(ProfileNode*, ProfileNode*) { }
};
-
ProfileTree::ProfileTree(Isolate* isolate)
- : root_entry_(Logger::FUNCTION_TAG, "(root)"),
+ : root_entry_(CodeEventListener::FUNCTION_TAG, "(root)"),
next_node_id_(1),
root_(new ProfileNode(this, &root_entry_)),
isolate_(isolate),
next_function_id_(1),
function_ids_(ProfileNode::CodeEntriesMatch) {}
-
ProfileTree::~ProfileTree() {
DeleteNodesCallback cb;
TraverseDepthFirst(&cb);
@@ -287,7 +320,7 @@
unsigned ProfileTree::GetFunctionId(const ProfileNode* node) {
CodeEntry* code_entry = node->entry();
- HashMap::Entry* entry =
+ base::HashMap::Entry* entry =
function_ids_.LookupOrInsert(code_entry, code_entry->GetHash());
if (!entry->value) {
entry->value = reinterpret_cast<void*>(next_function_id_++);
@@ -366,12 +399,13 @@
}
}
-
-CpuProfile::CpuProfile(Isolate* isolate, const char* title, bool record_samples)
+CpuProfile::CpuProfile(CpuProfiler* profiler, const char* title,
+ bool record_samples)
: title_(title),
record_samples_(record_samples),
start_time_(base::TimeTicks::HighResolutionNow()),
- top_down_(isolate) {}
+ top_down_(profiler->isolate()),
+ profiler_(profiler) {}
void CpuProfile::AddPath(base::TimeTicks timestamp,
const std::vector<CodeEntry*>& path, int src_line,
@@ -384,92 +418,60 @@
}
}
-
void CpuProfile::CalculateTotalTicksAndSamplingRate() {
end_time_ = base::TimeTicks::HighResolutionNow();
}
-
void CpuProfile::Print() {
base::OS::Print("[Top down]:\n");
top_down_.Print();
}
-
-CodeMap::~CodeMap() {}
-
-
-const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL;
-
-
void CodeMap::AddCode(Address addr, CodeEntry* entry, unsigned size) {
DeleteAllCoveredCode(addr, addr + size);
- CodeTree::Locator locator;
- tree_.Insert(addr, &locator);
- locator.set_value(CodeEntryInfo(entry, size));
+ code_map_.insert({addr, CodeEntryInfo(entry, size)});
}
-
void CodeMap::DeleteAllCoveredCode(Address start, Address end) {
- List<Address> to_delete;
- Address addr = end - 1;
- while (addr >= start) {
- CodeTree::Locator locator;
- if (!tree_.FindGreatestLessThan(addr, &locator)) break;
- Address start2 = locator.key(), end2 = start2 + locator.value().size;
- if (start2 < end && start < end2) to_delete.Add(start2);
- addr = start2 - 1;
+ auto left = code_map_.upper_bound(start);
+ if (left != code_map_.begin()) {
+ --left;
+ if (left->first + left->second.size <= start) ++left;
}
- for (int i = 0; i < to_delete.length(); ++i) tree_.Remove(to_delete[i]);
+ auto right = left;
+ while (right != code_map_.end() && right->first < end) ++right;
+ code_map_.erase(left, right);
}
-
CodeEntry* CodeMap::FindEntry(Address addr) {
- CodeTree::Locator locator;
- if (tree_.FindGreatestLessThan(addr, &locator)) {
- // locator.key() <= addr. Need to check that addr is within entry.
- const CodeEntryInfo& entry = locator.value();
- if (addr < (locator.key() + entry.size)) {
- return entry.entry;
- }
- }
- return NULL;
+ auto it = code_map_.upper_bound(addr);
+ if (it == code_map_.begin()) return nullptr;
+ --it;
+ Address end_address = it->first + it->second.size;
+ return addr < end_address ? it->second.entry : nullptr;
}
-
void CodeMap::MoveCode(Address from, Address to) {
if (from == to) return;
- CodeTree::Locator locator;
- if (!tree_.Find(from, &locator)) return;
- CodeEntryInfo entry = locator.value();
- tree_.Remove(from);
- AddCode(to, entry.entry, entry.size);
+ auto it = code_map_.find(from);
+ if (it == code_map_.end()) return;
+ CodeEntryInfo info = it->second;
+ code_map_.erase(it);
+ AddCode(to, info.entry, info.size);
}
-
-void CodeMap::CodeTreePrinter::Call(
- const Address& key, const CodeMap::CodeEntryInfo& value) {
- base::OS::Print("%p %5d %s\n", key, value.size, value.entry->name());
-}
-
-
void CodeMap::Print() {
- CodeTreePrinter printer;
- tree_.ForEach(&printer);
+ for (auto it = code_map_.begin(); it != code_map_.end(); ++it) {
+ base::OS::Print("%p %5d %s\n", static_cast<void*>(it->first),
+ it->second.size, it->second.entry->name());
+ }
}
-
-CpuProfilesCollection::CpuProfilesCollection(Heap* heap)
- : function_and_resource_names_(heap),
- isolate_(heap->isolate()),
+CpuProfilesCollection::CpuProfilesCollection(Isolate* isolate)
+ : resource_names_(isolate->heap()),
+ profiler_(nullptr),
current_profiles_semaphore_(1) {}
-
-static void DeleteCodeEntry(CodeEntry** entry_ptr) {
- delete *entry_ptr;
-}
-
-
static void DeleteCpuProfile(CpuProfile** profile_ptr) {
delete *profile_ptr;
}
@@ -478,7 +480,6 @@
CpuProfilesCollection::~CpuProfilesCollection() {
finished_profiles_.Iterate(DeleteCpuProfile);
current_profiles_.Iterate(DeleteCpuProfile);
- code_entries_.Iterate(DeleteCodeEntry);
}
@@ -497,7 +498,7 @@
return true;
}
}
- current_profiles_.Add(new CpuProfile(isolate_, title, record_samples));
+ current_profiles_.Add(new CpuProfile(profiler_, title, record_samples));
current_profiles_semaphore_.Signal();
return true;
}
@@ -555,43 +556,8 @@
current_profiles_semaphore_.Signal();
}
-
-CodeEntry* CpuProfilesCollection::NewCodeEntry(
- Logger::LogEventsAndTags tag, const char* name, const char* name_prefix,
- const char* resource_name, int line_number, int column_number,
- JITLineInfoTable* line_info, Address instruction_start) {
- CodeEntry* code_entry =
- new CodeEntry(tag, name, name_prefix, resource_name, line_number,
- column_number, line_info, instruction_start);
- code_entries_.Add(code_entry);
- return code_entry;
-}
-
-
-const char* const ProfileGenerator::kProgramEntryName =
- "(program)";
-const char* const ProfileGenerator::kIdleEntryName =
- "(idle)";
-const char* const ProfileGenerator::kGarbageCollectorEntryName =
- "(garbage collector)";
-const char* const ProfileGenerator::kUnresolvedFunctionName =
- "(unresolved function)";
-
-
ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
- : profiles_(profiles),
- program_entry_(
- profiles->NewCodeEntry(Logger::FUNCTION_TAG, kProgramEntryName)),
- idle_entry_(
- profiles->NewCodeEntry(Logger::FUNCTION_TAG, kIdleEntryName)),
- gc_entry_(
- profiles->NewCodeEntry(Logger::BUILTIN_TAG,
- kGarbageCollectorEntryName)),
- unresolved_entry_(
- profiles->NewCodeEntry(Logger::FUNCTION_TAG,
- kUnresolvedFunctionName)) {
-}
-
+ : profiles_(profiles) {}
void ProfileGenerator::RecordTickSample(const TickSample& sample) {
std::vector<CodeEntry*> entries;
@@ -607,9 +573,8 @@
int src_line = v8::CpuProfileNode::kNoLineNumberInfo;
bool src_line_not_found = true;
- if (sample.pc != NULL) {
- if (sample.has_external_callback && sample.state == EXTERNAL &&
- sample.top_frame_type == StackFrame::EXIT) {
+ if (sample.pc != nullptr) {
+ if (sample.has_external_callback && sample.state == EXTERNAL) {
// Don't use PC when in external callback code, as it can point
// inside callback's code, and we will erroneously report
// that a callback calls itself.
@@ -619,9 +584,7 @@
// If there is no pc_entry we're likely in native code.
// Find out, if top of stack was pointing inside a JS function
// meaning that we have encountered a frameless invocation.
- if (!pc_entry && (sample.top_frame_type == StackFrame::JAVA_SCRIPT ||
- sample.top_frame_type == StackFrame::INTERPRETED ||
- sample.top_frame_type == StackFrame::OPTIMIZED)) {
+ if (!pc_entry && !sample.has_external_callback) {
pc_entry = code_map_.FindEntry(sample.tos);
}
// If pc is in the function code before it set up stack frame or after the
@@ -646,8 +609,8 @@
// In the latter case we know the caller for sure but in the
// former case we don't so we simply replace the frame with
// 'unresolved' entry.
- if (sample.top_frame_type == StackFrame::JAVA_SCRIPT) {
- entries.push_back(unresolved_entry_);
+ if (!sample.has_external_callback) {
+ entries.push_back(CodeEntry::unresolved_entry());
}
}
}
@@ -704,7 +667,7 @@
CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
switch (tag) {
case GC:
- return gc_entry_;
+ return CodeEntry::gc_entry();
case JS:
case COMPILER:
// DOM events handlers are reported as OTHER / EXTERNAL entries.
@@ -712,9 +675,9 @@
// one bucket.
case OTHER:
case EXTERNAL:
- return program_entry_;
+ return CodeEntry::program_entry();
case IDLE:
- return idle_entry_;
+ return CodeEntry::idle_entry();
default: return NULL;
}
}