[cpu-profiler] Reference counting for code entries

To enable deallocation of CodeEntry objects after they're no longer
being referenced by an active profile or alive on the heap, replace the
|used| bit with a proper reference count maintained by a CodeMap.

Bug: v8:11054
Change-Id: Id3d5941e509504415692f833e406ecdd2553d426
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2945541
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Commit-Queue: Andrew Comminos <acomminos@fb.com>
Cr-Commit-Position: refs/heads/master@{#75164}
This commit is contained in:
Andrew Comminos 2021-06-14 12:39:57 -07:00 committed by V8 LUCI CQ
parent 7d468b70cd
commit 8e44ee5f75
11 changed files with 221 additions and 154 deletions

View File

@ -53,8 +53,8 @@ void ReportBuiltinEventRecord::UpdateCodeMap(CodeMap* code_map) {
if (builtin == Builtin::kGenericJSToWasmWrapper) { if (builtin == Builtin::kGenericJSToWasmWrapper) {
// Make sure to add the generic js-to-wasm wrapper builtin, because that // Make sure to add the generic js-to-wasm wrapper builtin, because that
// one is supposed to show up in profiles. // one is supposed to show up in profiles.
entry = entry = code_map->code_entries().Create(CodeEventListener::BUILTIN_TAG,
new CodeEntry(CodeEventListener::BUILTIN_TAG, Builtins::name(builtin)); Builtins::name(builtin));
code_map->AddCode(instruction_start, entry, instruction_size); code_map->AddCode(instruction_start, entry, instruction_size);
} }
#endif // V8_ENABLE_WEBASSEMBLY #endif // V8_ENABLE_WEBASSEMBLY

View File

@ -336,9 +336,11 @@ void* SamplingEventsProcessor::operator new(size_t size) {
void SamplingEventsProcessor::operator delete(void* ptr) { AlignedFree(ptr); } void SamplingEventsProcessor::operator delete(void* ptr) { AlignedFree(ptr); }
ProfilerCodeObserver::ProfilerCodeObserver(Isolate* isolate) ProfilerCodeObserver::ProfilerCodeObserver(Isolate* isolate,
CodeEntryStorage& storage)
: isolate_(isolate), : isolate_(isolate),
code_map_(strings_), code_entries_(storage),
code_map_(storage),
weak_code_registry_(isolate), weak_code_registry_(isolate),
processor_(nullptr) { processor_(nullptr) {
CreateEntriesForRuntimeCallStats(); CreateEntriesForRuntimeCallStats();
@ -350,7 +352,7 @@ void ProfilerCodeObserver::ClearCodeMap() {
code_map_.Clear(); code_map_.Clear();
// We don't currently expect any references to refcounted strings to be // We don't currently expect any references to refcounted strings to be
// maintained with zero profiles after the code map is cleared. // maintained with zero profiles after the code map is cleared.
DCHECK(strings_.empty()); DCHECK(code_entries_.strings().empty());
} }
void ProfilerCodeObserver::CodeEventHandler( void ProfilerCodeObserver::CodeEventHandler(
@ -385,8 +387,8 @@ void ProfilerCodeObserver::CreateEntriesForRuntimeCallStats() {
for (int i = 0; i < RuntimeCallStats::kNumberOfCounters; ++i) { for (int i = 0; i < RuntimeCallStats::kNumberOfCounters; ++i) {
RuntimeCallCounter* counter = rcs->GetCounter(i); RuntimeCallCounter* counter = rcs->GetCounter(i);
DCHECK(counter->name()); DCHECK(counter->name());
auto entry = new CodeEntry(CodeEventListener::FUNCTION_TAG, counter->name(), auto entry = code_entries_.Create(CodeEventListener::FUNCTION_TAG,
"native V8Runtime"); counter->name(), "native V8Runtime");
code_map_.AddCode(reinterpret_cast<Address>(counter), entry, 1); code_map_.AddCode(reinterpret_cast<Address>(counter), entry, 1);
} }
#endif // V8_RUNTIME_CALL_STATS #endif // V8_RUNTIME_CALL_STATS
@ -473,7 +475,7 @@ CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
CpuProfilingLoggingMode logging_mode) CpuProfilingLoggingMode logging_mode)
: CpuProfiler(isolate, naming_mode, logging_mode, : CpuProfiler(isolate, naming_mode, logging_mode,
new CpuProfilesCollection(isolate), nullptr, nullptr, new CpuProfilesCollection(isolate), nullptr, nullptr,
new ProfilerCodeObserver(isolate)) {} new ProfilerCodeObserver(isolate, code_entries_)) {}
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode, CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
CpuProfilingLoggingMode logging_mode, CpuProfilingLoggingMode logging_mode,
@ -529,7 +531,7 @@ void CpuProfiler::EnableLogging() {
if (!profiler_listener_) { if (!profiler_listener_) {
profiler_listener_.reset(new ProfilerListener( profiler_listener_.reset(new ProfilerListener(
isolate_, code_observer_.get(), *code_observer_->strings(), isolate_, code_observer_.get(), *code_observer_->code_entries(),
*code_observer_->weak_code_registry(), naming_mode_)); *code_observer_->weak_code_registry(), naming_mode_));
} }
profiling_scope_.reset( profiling_scope_.reset(

View File

@ -256,17 +256,17 @@ class V8_EXPORT_PRIVATE SamplingEventsProcessor
// low sampling intervals on Windows. // low sampling intervals on Windows.
}; };
// Builds and maintains a CodeMap tracking code objects on the VM heap, as well // Builds and maintains a CodeMap tracking code objects on the VM heap. While
// as strings owned by them. While alive, logs generated code, callbacks, and // alive, logs generated code, callbacks, and builtins from the isolate.
// builtins from the isolate. Redirects events to the profiler events // Redirects events to the profiler events processor when present. CodeEntry
// processor when present. // lifetime is associated with the given CodeEntryStorage.
class V8_EXPORT_PRIVATE ProfilerCodeObserver : public CodeEventObserver { class V8_EXPORT_PRIVATE ProfilerCodeObserver : public CodeEventObserver {
public: public:
explicit ProfilerCodeObserver(Isolate*); explicit ProfilerCodeObserver(Isolate*, CodeEntryStorage&);
void CodeEventHandler(const CodeEventsContainer& evt_rec) override; void CodeEventHandler(const CodeEventsContainer& evt_rec) override;
CodeEntryStorage* code_entries() { return &code_entries_; }
CodeMap* code_map() { return &code_map_; } CodeMap* code_map() { return &code_map_; }
StringsStorage* strings() { return &strings_; }
WeakCodeRegistry* weak_code_registry() { return &weak_code_registry_; } WeakCodeRegistry* weak_code_registry() { return &weak_code_registry_; }
void ClearCodeMap(); void ClearCodeMap();
@ -290,7 +290,7 @@ class V8_EXPORT_PRIVATE ProfilerCodeObserver : public CodeEventObserver {
void clear_processor() { processor_ = nullptr; } void clear_processor() { processor_ = nullptr; }
Isolate* const isolate_; Isolate* const isolate_;
StringsStorage strings_; CodeEntryStorage& code_entries_;
CodeMap code_map_; CodeMap code_map_;
WeakCodeRegistry weak_code_registry_; WeakCodeRegistry weak_code_registry_;
ProfilerEventsProcessor* processor_; ProfilerEventsProcessor* processor_;
@ -361,6 +361,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
Symbolizer* symbolizer() const { return symbolizer_.get(); } Symbolizer* symbolizer() const { return symbolizer_.get(); }
ProfilerEventsProcessor* processor() const { return processor_.get(); } ProfilerEventsProcessor* processor() const { return processor_.get(); }
Isolate* isolate() const { return isolate_; } Isolate* isolate() const { return isolate_; }
CodeEntryStorage* code_entries() { return &code_entries_; }
ProfilerListener* profiler_listener_for_test() const { ProfilerListener* profiler_listener_for_test() const {
return profiler_listener_.get(); return profiler_listener_.get();
@ -389,6 +390,11 @@ class V8_EXPORT_PRIVATE CpuProfiler {
// Sampling interval to which per-profile sampling intervals will be clamped // Sampling interval to which per-profile sampling intervals will be clamped
// to a multiple of, or used as the default if unspecified. // to a multiple of, or used as the default if unspecified.
base::TimeDelta base_sampling_interval_; base::TimeDelta base_sampling_interval_;
// Storage for CodeEntry objects allocated by the profiler. May live for
// multiple profiling sessions, independent of heap listener state.
CodeEntryStorage code_entries_;
std::unique_ptr<ProfilerCodeObserver> code_observer_; std::unique_ptr<ProfilerCodeObserver> code_observer_;
std::unique_ptr<CpuProfilesCollection> profiles_; std::unique_ptr<CpuProfilesCollection> profiles_;
std::unique_ptr<Symbolizer> symbolizer_; std::unique_ptr<Symbolizer> symbolizer_;

View File

@ -38,6 +38,7 @@ ProfileNode::ProfileNode(ProfileTree* tree, CodeEntry* entry,
parent_(parent), parent_(parent),
id_(tree->next_node_id()) { id_(tree->next_node_id()) {
tree_->EnqueueNode(this); tree_->EnqueueNode(this);
if (tree_->code_entries()) tree_->code_entries()->AddRef(entry_);
} }
inline Isolate* ProfileNode::isolate() const { return tree_->isolate(); } inline Isolate* ProfileNode::isolate() const { return tree_->isolate(); }

View File

@ -231,6 +231,8 @@ CodeEntry::RareData* CodeEntry::EnsureRareData() {
} }
void CodeEntry::ReleaseStrings(StringsStorage& strings) { void CodeEntry::ReleaseStrings(StringsStorage& strings) {
DCHECK_EQ(ref_count_, 0UL);
if (name_) { if (name_) {
strings.Release(name_); strings.Release(name_);
name_ = nullptr; name_ = nullptr;
@ -296,6 +298,10 @@ void CodeEntry::print() const {
base::OS::Print("\n"); base::OS::Print("\n");
} }
ProfileNode::~ProfileNode() {
if (tree_->code_entries()) tree_->code_entries()->DecRef(entry_);
}
CpuProfileNode::SourceType ProfileNode::source_type() const { CpuProfileNode::SourceType ProfileNode::source_type() const {
// Handle metadata and VM state code entry types. // Handle metadata and VM state code entry types.
if (entry_ == CodeEntry::program_entry() || if (entry_ == CodeEntry::program_entry() ||
@ -433,10 +439,11 @@ class DeleteNodesCallback {
void AfterChildTraversed(ProfileNode*, ProfileNode*) { } void AfterChildTraversed(ProfileNode*, ProfileNode*) { }
}; };
ProfileTree::ProfileTree(Isolate* isolate) ProfileTree::ProfileTree(Isolate* isolate, CodeEntryStorage* storage)
: next_node_id_(1), : next_node_id_(1),
root_(new ProfileNode(this, CodeEntry::root_entry(), nullptr)), root_(new ProfileNode(this, CodeEntry::root_entry(), nullptr)),
isolate_(isolate) {} isolate_(isolate),
code_entries_(storage) {}
ProfileTree::~ProfileTree() { ProfileTree::~ProfileTree() {
DeleteNodesCallback cb; DeleteNodesCallback cb;
@ -548,7 +555,7 @@ CpuProfile::CpuProfile(CpuProfiler* profiler, const char* title,
options_(options), options_(options),
delegate_(std::move(delegate)), delegate_(std::move(delegate)),
start_time_(base::TimeTicks::HighResolutionNow()), start_time_(base::TimeTicks::HighResolutionNow()),
top_down_(profiler->isolate()), top_down_(profiler->isolate(), profiler->code_entries()),
profiler_(profiler), profiler_(profiler),
streaming_next_sample_(0), streaming_next_sample_(0),
id_(++last_id_) { id_(++last_id_) {
@ -739,31 +746,32 @@ void CpuProfile::Print() const {
ProfilerStats::Instance()->Clear(); ProfilerStats::Instance()->Clear();
} }
CodeMap::CodeMap(StringsStorage& function_and_resource_names) void CodeEntryStorage::AddRef(CodeEntry* entry) {
: function_and_resource_names_(function_and_resource_names) {} if (entry->is_ref_counted()) entry->AddRef();
}
void CodeEntryStorage::DecRef(CodeEntry* entry) {
if (entry->is_ref_counted() && entry->DecRef() == 0) {
entry->ReleaseStrings(function_and_resource_names_);
delete entry;
}
}
CodeMap::CodeMap(CodeEntryStorage& storage) : code_entries_(storage) {}
CodeMap::~CodeMap() { Clear(); } CodeMap::~CodeMap() { Clear(); }
void CodeMap::Clear() { void CodeMap::Clear() {
for (auto& slot : code_map_) { for (auto& slot : code_map_) {
if (CodeEntry* entry = slot.second.entry) { if (CodeEntry* entry = slot.second.entry) {
entry->ReleaseStrings(function_and_resource_names_); code_entries_.DecRef(entry);
delete entry;
} else { } else {
// We expect all entries in the code mapping to contain a CodeEntry. // We expect all entries in the code mapping to contain a CodeEntry.
UNREACHABLE(); UNREACHABLE();
} }
} }
// Free all CodeEntry objects that are no longer in the map, but in a profile.
// TODO(acomminos): Remove this deque after we refcount CodeEntry objects.
for (CodeEntry* entry : used_entries_) {
DCHECK(entry->used());
DeleteCodeEntry(entry);
}
code_map_.clear(); code_map_.clear();
used_entries_.clear();
} }
void CodeMap::AddCode(Address addr, CodeEntry* entry, unsigned size) { void CodeMap::AddCode(Address addr, CodeEntry* entry, unsigned size) {
@ -775,11 +783,7 @@ bool CodeMap::RemoveCode(CodeEntry* entry) {
auto range = code_map_.equal_range(entry->instruction_start()); auto range = code_map_.equal_range(entry->instruction_start());
for (auto i = range.first; i != range.second; ++i) { for (auto i = range.first; i != range.second; ++i) {
if (i->second.entry == entry) { if (i->second.entry == entry) {
if (!entry->used()) { code_entries_.DecRef(entry);
DeleteCodeEntry(entry);
} else {
used_entries_.push_back(entry);
}
code_map_.erase(i); code_map_.erase(i);
return true; return true;
} }
@ -795,11 +799,7 @@ void CodeMap::ClearCodesInRange(Address start, Address end) {
} }
auto right = left; auto right = left;
for (; right != code_map_.end() && right->first < end; ++right) { for (; right != code_map_.end() && right->first < end; ++right) {
if (!right->second.entry->used()) { code_entries_.DecRef(right->second.entry);
DeleteCodeEntry(right->second.entry);
} else {
used_entries_.push_back(right->second.entry);
}
} }
code_map_.erase(left, right); code_map_.erase(left, right);
} }
@ -842,11 +842,6 @@ void CodeMap::MoveCode(Address from, Address to) {
code_map_.erase(range.first, it); code_map_.erase(range.first, it);
} }
void CodeMap::DeleteCodeEntry(CodeEntry* entry) {
entry->ReleaseStrings(function_and_resource_names_);
delete entry;
}
void CodeMap::Print() { void CodeMap::Print() {
for (const auto& pair : code_map_) { for (const auto& pair : code_map_) {
base::OS::Print("%p %5d %s\n", reinterpret_cast<void*>(pair.first), base::OS::Print("%p %5d %s\n", reinterpret_cast<void*>(pair.first),

View File

@ -76,6 +76,7 @@ class CodeEntry {
// No alive handles should be associated with the CodeEntry at time of // No alive handles should be associated with the CodeEntry at time of
// destruction. // destruction.
DCHECK(!heap_object_location_); DCHECK(!heap_object_location_);
DCHECK_EQ(ref_count_, 0UL);
} }
const char* name() const { return name_; } const char* name() const { return name_; }
@ -107,8 +108,6 @@ class CodeEntry {
rare_data_->deopt_reason_ = kNoDeoptReason; rare_data_->deopt_reason_ = kNoDeoptReason;
rare_data_->deopt_id_ = kNoDeoptimizationId; rare_data_->deopt_id_ = kNoDeoptimizationId;
} }
void mark_used() { bit_field_ = UsedField::update(bit_field_, true); }
bool used() const { return UsedField::decode(bit_field_); }
const char* code_type_string() const { const char* code_type_string() const {
switch (CodeTypeField::decode(bit_field_)) { switch (CodeTypeField::decode(bit_field_)) {
@ -137,6 +136,10 @@ class CodeEntry {
return SharedCrossOriginField::decode(bit_field_); return SharedCrossOriginField::decode(bit_field_);
} }
// Returns whether or not the lifetime of this CodeEntry is reference
// counted, and managed by a CodeMap.
bool is_ref_counted() const { return RefCountedField::decode(bit_field_); }
uint32_t GetHash() const; uint32_t GetHash() const;
bool IsSameFunctionAs(const CodeEntry* entry) const; bool IsSameFunctionAs(const CodeEntry* entry) const;
@ -193,6 +196,8 @@ class CodeEntry {
void print() const; void print() const;
private: private:
friend class CodeEntryStorage;
struct RareData { struct RareData {
const char* deopt_reason_ = kNoDeoptReason; const char* deopt_reason_ = kNoDeoptReason;
const char* bailout_reason_ = kEmptyBailoutReason; const char* bailout_reason_ = kEmptyBailoutReason;
@ -205,17 +210,35 @@ class CodeEntry {
RareData* EnsureRareData(); RareData* EnsureRareData();
void mark_ref_counted() {
bit_field_ = RefCountedField::update(bit_field_, true);
ref_count_ = 1;
}
size_t AddRef() {
DCHECK(is_ref_counted());
DCHECK_LT(ref_count_, std::numeric_limits<size_t>::max());
ref_count_++;
return ref_count_;
}
size_t DecRef() {
DCHECK(is_ref_counted());
DCHECK_GT(ref_count_, 0UL);
ref_count_--;
return ref_count_;
}
using TagField = base::BitField<CodeEventListener::LogEventsAndTags, 0, 8>; using TagField = base::BitField<CodeEventListener::LogEventsAndTags, 0, 8>;
using BuiltinField = base::BitField<Builtin, 8, 20>; using BuiltinField = base::BitField<Builtin, 8, 20>;
static_assert(Builtins::kBuiltinCount <= BuiltinField::kNumValues, static_assert(Builtins::kBuiltinCount <= BuiltinField::kNumValues,
"builtin_count exceeds size of bitfield"); "builtin_count exceeds size of bitfield");
using CodeTypeField = base::BitField<CodeType, 28, 2>; using RefCountedField = base::BitField<bool, 28, 1>;
using UsedField = base::BitField<bool, 30, 1>; using CodeTypeField = base::BitField<CodeType, 29, 2>;
using SharedCrossOriginField = base::BitField<bool, 31, 1>; using SharedCrossOriginField = base::BitField<bool, 31, 1>;
// Atomic because Used is written from the profiler thread while CodeType is std::uint32_t bit_field_;
// read from the main thread. std::atomic<std::size_t> ref_count_ = {0};
std::atomic<std::uint32_t> bit_field_;
const char* name_; const char* name_;
const char* resource_name_; const char* resource_name_;
int line_number_; int line_number_;
@ -266,6 +289,7 @@ class V8_EXPORT_PRIVATE ProfileNode {
public: public:
inline ProfileNode(ProfileTree* tree, CodeEntry* entry, ProfileNode* parent, inline ProfileNode(ProfileTree* tree, CodeEntry* entry, ProfileNode* parent,
int line_number = 0); int line_number = 0);
~ProfileNode();
ProfileNode(const ProfileNode&) = delete; ProfileNode(const ProfileNode&) = delete;
ProfileNode& operator=(const ProfileNode&) = delete; ProfileNode& operator=(const ProfileNode&) = delete;
@ -329,9 +353,11 @@ class V8_EXPORT_PRIVATE ProfileNode {
std::vector<CpuProfileDeoptInfo> deopt_infos_; std::vector<CpuProfileDeoptInfo> deopt_infos_;
}; };
class CodeEntryStorage;
class V8_EXPORT_PRIVATE ProfileTree { class V8_EXPORT_PRIVATE ProfileTree {
public: public:
explicit ProfileTree(Isolate* isolate); explicit ProfileTree(Isolate* isolate, CodeEntryStorage* storage = nullptr);
~ProfileTree(); ~ProfileTree();
ProfileTree(const ProfileTree&) = delete; ProfileTree(const ProfileTree&) = delete;
ProfileTree& operator=(const ProfileTree&) = delete; ProfileTree& operator=(const ProfileTree&) = delete;
@ -360,6 +386,8 @@ class V8_EXPORT_PRIVATE ProfileTree {
return std::move(pending_nodes_); return std::move(pending_nodes_);
} }
CodeEntryStorage* code_entries() { return code_entries_; }
private: private:
template <typename Callback> template <typename Callback>
void TraverseDepthFirst(Callback* callback); void TraverseDepthFirst(Callback* callback);
@ -369,6 +397,7 @@ class V8_EXPORT_PRIVATE ProfileTree {
unsigned next_node_id_; unsigned next_node_id_;
ProfileNode* root_; ProfileNode* root_;
Isolate* isolate_; Isolate* isolate_;
CodeEntryStorage* code_entries_;
}; };
class CpuProfiler; class CpuProfiler;
@ -450,13 +479,13 @@ class CpuProfileMaxSamplesCallbackTask : public v8::Task {
class V8_EXPORT_PRIVATE CodeMap { class V8_EXPORT_PRIVATE CodeMap {
public: public:
// Creates a new CodeMap with an associated StringsStorage to store the explicit CodeMap(CodeEntryStorage& storage);
// strings of CodeEntry objects within.
explicit CodeMap(StringsStorage& function_and_resource_names);
~CodeMap(); ~CodeMap();
CodeMap(const CodeMap&) = delete; CodeMap(const CodeMap&) = delete;
CodeMap& operator=(const CodeMap&) = delete; CodeMap& operator=(const CodeMap&) = delete;
// Adds the given CodeEntry to the CodeMap. The CodeMap takes ownership of
// the CodeEntry.
void AddCode(Address addr, CodeEntry* entry, unsigned size); void AddCode(Address addr, CodeEntry* entry, unsigned size);
void MoveCode(Address from, Address to); void MoveCode(Address from, Address to);
// Attempts to remove the given CodeEntry from the CodeMap. // Attempts to remove the given CodeEntry from the CodeMap.
@ -467,6 +496,8 @@ class V8_EXPORT_PRIVATE CodeMap {
void Print(); void Print();
size_t size() const { return code_map_.size(); } size_t size() const { return code_map_.size(); }
CodeEntryStorage& code_entries() { return code_entries_; }
void Clear(); void Clear();
private: private:
@ -475,12 +506,28 @@ class V8_EXPORT_PRIVATE CodeMap {
unsigned size; unsigned size;
}; };
void DeleteCodeEntry(CodeEntry*);
std::multimap<Address, CodeEntryMapInfo> code_map_; std::multimap<Address, CodeEntryMapInfo> code_map_;
std::deque<CodeEntry*> used_entries_; // Entries that are no longer in the CodeEntryStorage& code_entries_;
// map, but used by a profile. };
StringsStorage& function_and_resource_names_;
// Manages the lifetime of CodeEntry objects, and stores shared resources
// between them.
class V8_EXPORT_PRIVATE CodeEntryStorage {
public:
template <typename... Args>
static CodeEntry* Create(Args&&... args) {
CodeEntry* const entry = new CodeEntry(std::forward<Args>(args)...);
entry->mark_ref_counted();
return entry;
}
void AddRef(CodeEntry*);
void DecRef(CodeEntry*);
StringsStorage& strings() { return function_and_resource_names_; }
private:
StringsStorage function_and_resource_names_;
}; };
class V8_EXPORT_PRIVATE CpuProfilesCollection { class V8_EXPORT_PRIVATE CpuProfilesCollection {

View File

@ -29,12 +29,12 @@ namespace internal {
ProfilerListener::ProfilerListener(Isolate* isolate, ProfilerListener::ProfilerListener(Isolate* isolate,
CodeEventObserver* observer, CodeEventObserver* observer,
StringsStorage& function_and_resource_names, CodeEntryStorage& code_entry_storage,
WeakCodeRegistry& weak_code_registry, WeakCodeRegistry& weak_code_registry,
CpuProfilingNamingMode naming_mode) CpuProfilingNamingMode naming_mode)
: isolate_(isolate), : isolate_(isolate),
observer_(observer), observer_(observer),
function_and_resource_names_(function_and_resource_names), code_entries_(code_entry_storage),
weak_code_registry_(weak_code_registry), weak_code_registry_(weak_code_registry),
naming_mode_(naming_mode) {} naming_mode_(naming_mode) {}
@ -46,9 +46,10 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = code->InstructionStart(); rec->instruction_start = code->InstructionStart();
rec->entry = new CodeEntry(tag, GetName(name), CodeEntry::kEmptyResourceName, rec->entry =
CpuProfileNode::kNoLineNumberInfo, code_entries_.Create(tag, GetName(name), CodeEntry::kEmptyResourceName,
CpuProfileNode::kNoColumnNumberInfo, nullptr); CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, nullptr);
rec->instruction_size = code->InstructionSize(); rec->instruction_size = code->InstructionSize();
weak_code_registry_.Track(rec->entry, code); weak_code_registry_.Track(rec->entry, code);
DispatchCodeEvent(evt_rec); DispatchCodeEvent(evt_rec);
@ -60,9 +61,10 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = code->InstructionStart(); rec->instruction_start = code->InstructionStart();
rec->entry = new CodeEntry(tag, GetName(*name), CodeEntry::kEmptyResourceName, rec->entry =
CpuProfileNode::kNoLineNumberInfo, code_entries_.Create(tag, GetName(*name), CodeEntry::kEmptyResourceName,
CpuProfileNode::kNoColumnNumberInfo, nullptr); CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, nullptr);
rec->instruction_size = code->InstructionSize(); rec->instruction_size = code->InstructionSize();
weak_code_registry_.Track(rec->entry, code); weak_code_registry_.Track(rec->entry, code);
DispatchCodeEvent(evt_rec); DispatchCodeEvent(evt_rec);
@ -75,10 +77,11 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = code->InstructionStart(); rec->instruction_start = code->InstructionStart();
rec->entry = new CodeEntry(tag, GetName(shared->DebugNameCStr().get()), rec->entry =
GetName(InferScriptName(*script_name, *shared)), code_entries_.Create(tag, GetName(shared->DebugNameCStr().get()),
CpuProfileNode::kNoLineNumberInfo, GetName(InferScriptName(*script_name, *shared)),
CpuProfileNode::kNoColumnNumberInfo, nullptr); CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, nullptr);
DCHECK_IMPLIES(code->IsCode(), code->kind() == CodeKind::BASELINE); DCHECK_IMPLIES(code->IsCode(), code->kind() == CodeKind::BASELINE);
rec->entry->FillFunctionInfo(*shared); rec->entry->FillFunctionInfo(*shared);
rec->instruction_size = code->InstructionSize(); rec->instruction_size = code->InstructionSize();
@ -91,10 +94,10 @@ namespace {
CodeEntry* GetOrInsertCachedEntry( CodeEntry* GetOrInsertCachedEntry(
std::unordered_set<std::unique_ptr<CodeEntry>, CodeEntry::Hasher, std::unordered_set<std::unique_ptr<CodeEntry>, CodeEntry::Hasher,
CodeEntry::Equals>* entries, CodeEntry::Equals>* entries,
std::unique_ptr<CodeEntry> search_value, StringsStorage& strings) { std::unique_ptr<CodeEntry> search_value, CodeEntryStorage& storage) {
auto it = entries->find(search_value); auto it = entries->find(search_value);
if (it != entries->end()) { if (it != entries->end()) {
search_value->ReleaseStrings(strings); search_value->ReleaseStrings(storage.strings());
return it->get(); return it->get();
} }
CodeEntry* ret = search_value.get(); CodeEntry* ret = search_value.get();
@ -204,8 +207,7 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
// Create a canonical CodeEntry for each inlined frame and then re-use // Create a canonical CodeEntry for each inlined frame and then re-use
// them for subsequent inline stacks to avoid a lot of duplication. // them for subsequent inline stacks to avoid a lot of duplication.
CodeEntry* cached_entry = GetOrInsertCachedEntry( CodeEntry* cached_entry = GetOrInsertCachedEntry(
&cached_inline_entries, std::move(inline_entry), &cached_inline_entries, std::move(inline_entry), code_entries_);
function_and_resource_names_);
inline_stack.push_back({cached_entry, line_number}); inline_stack.push_back({cached_entry, line_number});
} }
@ -214,10 +216,10 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
} }
} }
} }
rec->entry = rec->entry = code_entries_.Create(
new CodeEntry(tag, GetFunctionName(*shared), tag, GetFunctionName(*shared),
GetName(InferScriptName(*script_name, *shared)), line, GetName(InferScriptName(*script_name, *shared)), line, column,
column, std::move(line_table), is_shared_cross_origin); std::move(line_table), is_shared_cross_origin);
if (!inline_stacks.empty()) { if (!inline_stacks.empty()) {
rec->entry->SetInlineStacks(std::move(cached_inline_entries), rec->entry->SetInlineStacks(std::move(cached_inline_entries),
std::move(inline_stacks)); std::move(inline_stacks));
@ -238,9 +240,9 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = code->instruction_start(); rec->instruction_start = code->instruction_start();
rec->entry = rec->entry = code_entries_.Create(tag, GetName(name), GetName(source_url), 1,
new CodeEntry(tag, GetName(name), GetName(source_url), 1, code_offset + 1, code_offset + 1, nullptr, true,
nullptr, true, CodeEntry::CodeType::WASM); CodeEntry::CodeType::WASM);
rec->entry->set_script_id(script_id); rec->entry->set_script_id(script_id);
rec->entry->set_position(code_offset); rec->entry->set_position(code_offset);
rec->instruction_size = code->instructions().length(); rec->instruction_size = code->instructions().length();
@ -252,7 +254,8 @@ void ProfilerListener::CallbackEvent(Handle<Name> name, Address entry_point) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = entry_point; rec->instruction_start = entry_point;
rec->entry = new CodeEntry(CodeEventListener::CALLBACK_TAG, GetName(*name)); rec->entry =
code_entries_.Create(CodeEventListener::CALLBACK_TAG, GetName(*name));
rec->instruction_size = 1; rec->instruction_size = 1;
DispatchCodeEvent(evt_rec); DispatchCodeEvent(evt_rec);
} }
@ -262,8 +265,8 @@ void ProfilerListener::GetterCallbackEvent(Handle<Name> name,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = entry_point; rec->instruction_start = entry_point;
rec->entry = new CodeEntry(CodeEventListener::CALLBACK_TAG, rec->entry = code_entries_.Create(CodeEventListener::CALLBACK_TAG,
GetConsName("get ", *name)); GetConsName("get ", *name));
rec->instruction_size = 1; rec->instruction_size = 1;
DispatchCodeEvent(evt_rec); DispatchCodeEvent(evt_rec);
} }
@ -273,8 +276,8 @@ void ProfilerListener::SetterCallbackEvent(Handle<Name> name,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = entry_point; rec->instruction_start = entry_point;
rec->entry = new CodeEntry(CodeEventListener::CALLBACK_TAG, rec->entry = code_entries_.Create(CodeEventListener::CALLBACK_TAG,
GetConsName("set ", *name)); GetConsName("set ", *name));
rec->instruction_size = 1; rec->instruction_size = 1;
DispatchCodeEvent(evt_rec); DispatchCodeEvent(evt_rec);
} }
@ -284,7 +287,7 @@ void ProfilerListener::RegExpCodeCreateEvent(Handle<AbstractCode> code,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION); CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_; CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = code->InstructionStart(); rec->instruction_start = code->InstructionStart();
rec->entry = new CodeEntry( rec->entry = code_entries_.Create(
CodeEventListener::REG_EXP_TAG, GetConsName("RegExp: ", *source), CodeEventListener::REG_EXP_TAG, GetConsName("RegExp: ", *source),
CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo, CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, nullptr); CpuProfileNode::kNoColumnNumberInfo, nullptr);

View File

@ -29,7 +29,7 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener,
public WeakCodeRegistry::Listener { public WeakCodeRegistry::Listener {
public: public:
ProfilerListener(Isolate*, CodeEventObserver*, ProfilerListener(Isolate*, CodeEventObserver*,
StringsStorage& function_and_resource_names, CodeEntryStorage& code_entry_storage,
WeakCodeRegistry& weak_code_registry, WeakCodeRegistry& weak_code_registry,
CpuProfilingNamingMode mode = kDebugNaming); CpuProfilingNamingMode mode = kDebugNaming);
~ProfilerListener() override; ~ProfilerListener() override;
@ -76,17 +76,17 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener,
void CodeSweepEvent(); void CodeSweepEvent();
const char* GetName(Name name) { const char* GetName(Name name) {
return function_and_resource_names_.GetName(name); return code_entries_.strings().GetName(name);
} }
const char* GetName(int args_count) { const char* GetName(int args_count) {
return function_and_resource_names_.GetName(args_count); return code_entries_.strings().GetName(args_count);
} }
const char* GetName(const char* name) { const char* GetName(const char* name) {
return function_and_resource_names_.GetCopy(name); return code_entries_.strings().GetCopy(name);
} }
const char* GetName(Vector<const char> name); const char* GetName(Vector<const char> name);
const char* GetConsName(const char* prefix, Name name) { const char* GetConsName(const char* prefix, Name name) {
return function_and_resource_names_.GetConsName(prefix, name); return code_entries_.strings().GetConsName(prefix, name);
} }
void set_observer(CodeEventObserver* observer) { observer_ = observer; } void set_observer(CodeEventObserver* observer) { observer_ = observer; }
@ -102,7 +102,7 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener,
Isolate* isolate_; Isolate* isolate_;
CodeEventObserver* observer_; CodeEventObserver* observer_;
StringsStorage& function_and_resource_names_; CodeEntryStorage& code_entries_;
WeakCodeRegistry& weak_code_registry_; WeakCodeRegistry& weak_code_registry_;
const CpuProfilingNamingMode naming_mode_; const CpuProfilingNamingMode naming_mode_;
}; };

View File

@ -16,9 +16,7 @@ Symbolizer::Symbolizer(CodeMap* code_map) : code_map_(code_map) {}
CodeEntry* Symbolizer::FindEntry(Address address, CodeEntry* Symbolizer::FindEntry(Address address,
Address* out_instruction_start) { Address* out_instruction_start) {
CodeEntry* entry = code_map_->FindEntry(address, out_instruction_start); return code_map_->FindEntry(address, out_instruction_start);
if (entry) entry->mark_used();
return entry;
} }
namespace { namespace {

View File

@ -88,8 +88,9 @@ static const char* reason(const i::DeoptimizeReason reason) {
TEST(StartStop) { TEST(StartStop) {
i::Isolate* isolate = CcTest::i_isolate(); i::Isolate* isolate = CcTest::i_isolate();
CodeEntryStorage storage;
CpuProfilesCollection profiles(isolate); CpuProfilesCollection profiles(isolate);
ProfilerCodeObserver code_observer(isolate); ProfilerCodeObserver code_observer(isolate, storage);
Symbolizer symbolizer(code_observer.code_map()); Symbolizer symbolizer(code_observer.code_map());
std::unique_ptr<ProfilerEventsProcessor> processor( std::unique_ptr<ProfilerEventsProcessor> processor(
new SamplingEventsProcessor( new SamplingEventsProcessor(
@ -171,15 +172,16 @@ TEST(CodeEvents) {
i::Handle<i::AbstractCode> comment2_code(CreateCode(isolate, &env), isolate); i::Handle<i::AbstractCode> comment2_code(CreateCode(isolate, &env), isolate);
i::Handle<i::AbstractCode> moved_code(CreateCode(isolate, &env), isolate); i::Handle<i::AbstractCode> moved_code(CreateCode(isolate, &env), isolate);
CodeEntryStorage storage;
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver code_observer(isolate); ProfilerCodeObserver code_observer(isolate, storage);
Symbolizer* symbolizer = new Symbolizer(code_observer.code_map()); Symbolizer* symbolizer = new Symbolizer(code_observer.code_map());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor( ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
isolate, symbolizer, &code_observer, profiles, isolate, symbolizer, &code_observer, profiles,
v8::base::TimeDelta::FromMicroseconds(100), true); v8::base::TimeDelta::FromMicroseconds(100), true);
CHECK(processor->Start()); CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor, ProfilerListener profiler_listener(isolate, processor,
*code_observer.strings(), *code_observer.code_entries(),
*code_observer.weak_code_registry()); *code_observer.weak_code_registry());
isolate->logger()->AddCodeEventListener(&profiler_listener); isolate->logger()->AddCodeEventListener(&profiler_listener);
@ -234,8 +236,10 @@ TEST(TickEvents) {
i::Handle<i::AbstractCode> frame2_code(CreateCode(isolate, &env), isolate); i::Handle<i::AbstractCode> frame2_code(CreateCode(isolate, &env), isolate);
i::Handle<i::AbstractCode> frame3_code(CreateCode(isolate, &env), isolate); i::Handle<i::AbstractCode> frame3_code(CreateCode(isolate, &env), isolate);
CodeEntryStorage storage;
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate); ProfilerCodeObserver* code_observer =
new ProfilerCodeObserver(isolate, storage);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map()); Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor( ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), symbolizer, code_observer, profiles, CcTest::i_isolate(), symbolizer, code_observer, profiles,
@ -245,7 +249,7 @@ TEST(TickEvents) {
profiles->StartProfiling(""); profiles->StartProfiling("");
CHECK(processor->Start()); CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor, ProfilerListener profiler_listener(isolate, processor,
*code_observer->strings(), *code_observer->code_entries(),
*code_observer->weak_code_registry()); *code_observer->weak_code_registry());
isolate->logger()->AddCodeEventListener(&profiler_listener); isolate->logger()->AddCodeEventListener(&profiler_listener);
@ -396,8 +400,10 @@ TEST(Issue1398) {
i::Handle<i::AbstractCode> code(CreateCode(isolate, &env), isolate); i::Handle<i::AbstractCode> code(CreateCode(isolate, &env), isolate);
CodeEntryStorage storage;
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate); ProfilerCodeObserver* code_observer =
new ProfilerCodeObserver(isolate, storage);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map()); Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor( ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), symbolizer, code_observer, profiles, CcTest::i_isolate(), symbolizer, code_observer, profiles,
@ -407,7 +413,7 @@ TEST(Issue1398) {
profiles->StartProfiling(""); profiles->StartProfiling("");
CHECK(processor->Start()); CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor, ProfilerListener profiler_listener(isolate, processor,
*code_observer->strings(), *code_observer->code_entries(),
*code_observer->weak_code_registry()); *code_observer->weak_code_registry());
profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb"); profiler_listener.CodeCreateEvent(i::Logger::BUILTIN_TAG, code, "bbb");
@ -1262,8 +1268,10 @@ static void TickLines(bool optimize) {
i::Address code_address = code->raw_instruction_start(); i::Address code_address = code->raw_instruction_start();
CHECK_NE(code_address, kNullAddress); CHECK_NE(code_address, kNullAddress);
CodeEntryStorage storage;
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate); ProfilerCodeObserver* code_observer =
new ProfilerCodeObserver(isolate, storage);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map()); Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor( ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), symbolizer, code_observer, profiles, CcTest::i_isolate(), symbolizer, code_observer, profiles,
@ -1278,7 +1286,7 @@ static void TickLines(bool optimize) {
isolate->logger()->LogCompiledFunctions(); isolate->logger()->LogCompiledFunctions();
CHECK(processor->Start()); CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor, ProfilerListener profiler_listener(isolate, processor,
*code_observer->strings(), *code_observer->code_entries(),
*code_observer->weak_code_registry()); *code_observer->weak_code_registry());
// Enqueue code creation events. // Enqueue code creation events.
@ -3474,8 +3482,9 @@ TEST(MaxSimultaneousProfiles) {
TEST(LowPrecisionSamplingStartStopInternal) { TEST(LowPrecisionSamplingStartStopInternal) {
i::Isolate* isolate = CcTest::i_isolate(); i::Isolate* isolate = CcTest::i_isolate();
CodeEntryStorage storage;
CpuProfilesCollection profiles(isolate); CpuProfilesCollection profiles(isolate);
ProfilerCodeObserver code_observer(isolate); ProfilerCodeObserver code_observer(isolate, storage);
Symbolizer symbolizer(code_observer.code_map()); Symbolizer symbolizer(code_observer.code_map());
std::unique_ptr<ProfilerEventsProcessor> processor( std::unique_ptr<ProfilerEventsProcessor> processor(
new SamplingEventsProcessor( new SamplingEventsProcessor(
@ -3600,8 +3609,10 @@ TEST(ProflilerSubsampling) {
i::Isolate* isolate = CcTest::i_isolate(); i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
CodeEntryStorage storage;
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate); ProfilerCodeObserver* code_observer =
new ProfilerCodeObserver(isolate, storage);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map()); Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor = ProfilerEventsProcessor* processor =
new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles, new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles,
@ -3644,8 +3655,10 @@ TEST(DynamicResampling) {
i::Isolate* isolate = CcTest::i_isolate(); i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
CodeEntryStorage storage;
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate); ProfilerCodeObserver* code_observer =
new ProfilerCodeObserver(isolate, storage);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map()); Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor = ProfilerEventsProcessor* processor =
new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles, new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles,
@ -3705,8 +3718,10 @@ TEST(DynamicResamplingWithBaseInterval) {
i::Isolate* isolate = CcTest::i_isolate(); i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
CodeEntryStorage storage;
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate); CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
ProfilerCodeObserver* code_observer = new ProfilerCodeObserver(isolate); ProfilerCodeObserver* code_observer =
new ProfilerCodeObserver(isolate, storage);
Symbolizer* symbolizer = new Symbolizer(code_observer->code_map()); Symbolizer* symbolizer = new Symbolizer(code_observer->code_map());
ProfilerEventsProcessor* processor = ProfilerEventsProcessor* processor =
new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles, new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles,

View File

@ -311,12 +311,12 @@ static inline i::Address ToAddress(int n) { return static_cast<i::Address>(n); }
static inline void* ToPointer(int n) { return reinterpret_cast<void*>(n); } static inline void* ToPointer(int n) { return reinterpret_cast<void*>(n); }
TEST(CodeMapAddCode) { TEST(CodeMapAddCode) {
StringsStorage strings; CodeEntryStorage storage;
CodeMap code_map(strings); CodeMap code_map(storage);
CodeEntry* entry1 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa"); CodeEntry* entry1 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb"); CodeEntry* entry2 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "bbb");
CodeEntry* entry3 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "ccc"); CodeEntry* entry3 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "ccc");
CodeEntry* entry4 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "ddd"); CodeEntry* entry4 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "ddd");
code_map.AddCode(ToAddress(0x1500), entry1, 0x200); code_map.AddCode(ToAddress(0x1500), entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), entry2, 0x100); code_map.AddCode(ToAddress(0x1700), entry2, 0x100);
code_map.AddCode(ToAddress(0x1900), entry3, 0x50); code_map.AddCode(ToAddress(0x1900), entry3, 0x50);
@ -341,10 +341,10 @@ TEST(CodeMapAddCode) {
} }
TEST(CodeMapMoveAndDeleteCode) { TEST(CodeMapMoveAndDeleteCode) {
StringsStorage strings; CodeEntryStorage storage;
CodeMap code_map(strings); CodeMap code_map(storage);
CodeEntry* entry1 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa"); CodeEntry* entry1 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb"); CodeEntry* entry2 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "bbb");
code_map.AddCode(ToAddress(0x1500), entry1, 0x200); code_map.AddCode(ToAddress(0x1500), entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), entry2, 0x100); code_map.AddCode(ToAddress(0x1700), entry2, 0x100);
CHECK_EQ(entry1, code_map.FindEntry(ToAddress(0x1500))); CHECK_EQ(entry1, code_map.FindEntry(ToAddress(0x1500)));
@ -355,10 +355,10 @@ TEST(CodeMapMoveAndDeleteCode) {
} }
TEST(CodeMapClear) { TEST(CodeMapClear) {
StringsStorage strings; CodeEntryStorage storage;
CodeMap code_map(strings); CodeMap code_map(storage);
CodeEntry* entry1 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa"); CodeEntry* entry1 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb"); CodeEntry* entry2 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "bbb");
code_map.AddCode(ToAddress(0x1500), entry1, 0x200); code_map.AddCode(ToAddress(0x1500), entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), entry2, 0x100); code_map.AddCode(ToAddress(0x1700), entry2, 0x100);
@ -391,12 +391,12 @@ class TestSetup {
TEST(SymbolizeTickSample) { TEST(SymbolizeTickSample) {
TestSetup test_setup; TestSetup test_setup;
StringsStorage strings; CodeEntryStorage storage;
CodeMap code_map(strings); CodeMap code_map(storage);
Symbolizer symbolizer(&code_map); Symbolizer symbolizer(&code_map);
CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa"); CodeEntry* entry1 = storage.Create(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::Logger::FUNCTION_TAG, "bbb"); CodeEntry* entry2 = storage.Create(i::Logger::FUNCTION_TAG, "bbb");
CodeEntry* entry3 = new CodeEntry(i::Logger::FUNCTION_TAG, "ccc"); CodeEntry* entry3 = storage.Create(i::Logger::FUNCTION_TAG, "ccc");
symbolizer.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200); symbolizer.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
symbolizer.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100); symbolizer.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100);
symbolizer.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50); symbolizer.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50);
@ -456,16 +456,16 @@ static void CheckNodeIds(const ProfileNode* node, unsigned* expectedId) {
TEST(SampleIds) { TEST(SampleIds) {
TestSetup test_setup; TestSetup test_setup;
i::Isolate* isolate = CcTest::i_isolate(); i::Isolate* isolate = CcTest::i_isolate();
CpuProfilesCollection profiles(isolate);
CpuProfiler profiler(isolate); CpuProfiler profiler(isolate);
CpuProfilesCollection profiles(isolate);
profiles.set_cpu_profiler(&profiler); profiles.set_cpu_profiler(&profiler);
profiles.StartProfiling("", {CpuProfilingMode::kLeafNodeLineNumbers}); profiles.StartProfiling("", {CpuProfilingMode::kLeafNodeLineNumbers});
StringsStorage strings; CodeEntryStorage storage;
CodeMap code_map(strings); CodeMap code_map(storage);
Symbolizer symbolizer(&code_map); Symbolizer symbolizer(&code_map);
CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa"); CodeEntry* entry1 = storage.Create(i::Logger::FUNCTION_TAG, "aaa");
CodeEntry* entry2 = new CodeEntry(i::Logger::FUNCTION_TAG, "bbb"); CodeEntry* entry2 = storage.Create(i::Logger::FUNCTION_TAG, "bbb");
CodeEntry* entry3 = new CodeEntry(i::Logger::FUNCTION_TAG, "ccc"); CodeEntry* entry3 = storage.Create(i::Logger::FUNCTION_TAG, "ccc");
symbolizer.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200); symbolizer.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
symbolizer.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100); symbolizer.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100);
symbolizer.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50); symbolizer.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50);
@ -592,8 +592,8 @@ TEST(MaxSamplesCallback) {
MaybeLocal<v8::Context>()}, MaybeLocal<v8::Context>()},
std::move(impl)); std::move(impl));
StringsStorage strings; CodeEntryStorage storage;
CodeMap code_map(strings); CodeMap code_map(storage);
Symbolizer symbolizer(&code_map); Symbolizer symbolizer(&code_map);
TickSample sample1; TickSample sample1;
sample1.timestamp = v8::base::TimeTicks::HighResolutionNow(); sample1.timestamp = v8::base::TimeTicks::HighResolutionNow();
@ -633,14 +633,14 @@ TEST(MaxSamplesCallback) {
TEST(NoSamples) { TEST(NoSamples) {
TestSetup test_setup; TestSetup test_setup;
i::Isolate* isolate = CcTest::i_isolate(); i::Isolate* isolate = CcTest::i_isolate();
CpuProfilesCollection profiles(isolate);
CpuProfiler profiler(isolate); CpuProfiler profiler(isolate);
CpuProfilesCollection profiles(isolate);
profiles.set_cpu_profiler(&profiler); profiles.set_cpu_profiler(&profiler);
profiles.StartProfiling(""); profiles.StartProfiling("");
StringsStorage strings; CodeEntryStorage storage;
CodeMap code_map(strings); CodeMap code_map(storage);
Symbolizer symbolizer(&code_map); Symbolizer symbolizer(&code_map);
CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa"); CodeEntry* entry1 = storage.Create(i::Logger::FUNCTION_TAG, "aaa");
symbolizer.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200); symbolizer.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
// We are building the following calls tree: // We are building the following calls tree:
@ -959,10 +959,10 @@ TEST(NodeSourceTypes) {
} }
TEST(CodeMapRemoveCode) { TEST(CodeMapRemoveCode) {
StringsStorage strings; CodeEntryStorage storage;
CodeMap code_map(strings); CodeMap code_map(storage);
CodeEntry* entry = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa"); CodeEntry* entry = storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
code_map.AddCode(ToAddress(0x1000), entry, 0x100); code_map.AddCode(ToAddress(0x1000), entry, 0x100);
CHECK(code_map.RemoveCode(entry)); CHECK(code_map.RemoveCode(entry));
CHECK(!code_map.FindEntry(ToAddress(0x1000))); CHECK(!code_map.FindEntry(ToAddress(0x1000)));
@ -970,9 +970,9 @@ TEST(CodeMapRemoveCode) {
// Test that when two entries share the same address, we remove only the // Test that when two entries share the same address, we remove only the
// entry that we desired to. // entry that we desired to.
CodeEntry* colliding_entry1 = CodeEntry* colliding_entry1 =
new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa"); storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
CodeEntry* colliding_entry2 = CodeEntry* colliding_entry2 =
new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa"); storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
code_map.AddCode(ToAddress(0x1000), colliding_entry1, 0x100); code_map.AddCode(ToAddress(0x1000), colliding_entry1, 0x100);
code_map.AddCode(ToAddress(0x1000), colliding_entry2, 0x100); code_map.AddCode(ToAddress(0x1000), colliding_entry2, 0x100);
@ -984,14 +984,14 @@ TEST(CodeMapRemoveCode) {
} }
TEST(CodeMapMoveOverlappingCode) { TEST(CodeMapMoveOverlappingCode) {
StringsStorage strings; CodeEntryStorage storage;
CodeMap code_map(strings); CodeMap code_map(storage);
CodeEntry* colliding_entry1 = CodeEntry* colliding_entry1 =
new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa"); storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
CodeEntry* colliding_entry2 = CodeEntry* colliding_entry2 =
new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb"); storage.Create(i::CodeEventListener::FUNCTION_TAG, "bbb");
CodeEntry* after_entry = CodeEntry* after_entry =
new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "ccc"); storage.Create(i::CodeEventListener::FUNCTION_TAG, "ccc");
code_map.AddCode(ToAddress(0x1400), colliding_entry1, 0x200); code_map.AddCode(ToAddress(0x1400), colliding_entry1, 0x200);
code_map.AddCode(ToAddress(0x1400), colliding_entry2, 0x200); code_map.AddCode(ToAddress(0x1400), colliding_entry2, 0x200);