diff --git a/src/profiler/cpu-profiler-inl.h b/src/profiler/cpu-profiler-inl.h
index ea2b4487a2..b759d85d85 100644
--- a/src/profiler/cpu-profiler-inl.h
+++ b/src/profiler/cpu-profiler-inl.h
@@ -53,8 +53,8 @@ void ReportBuiltinEventRecord::UpdateCodeMap(CodeMap* code_map) {
if (builtin == Builtin::kGenericJSToWasmWrapper) {
// Make sure to add the generic js-to-wasm wrapper builtin, because that
// one is supposed to show up in profiles.
- entry =
- new CodeEntry(CodeEventListener::BUILTIN_TAG, Builtins::name(builtin));
+ entry = code_map->code_entries().Create(CodeEventListener::BUILTIN_TAG,
+ Builtins::name(builtin));
code_map->AddCode(instruction_start, entry, instruction_size);
}
#endif // V8_ENABLE_WEBASSEMBLY
diff --git a/src/profiler/cpu-profiler.cc b/src/profiler/cpu-profiler.cc
index f5221d67d1..80531dfc20 100644
--- a/src/profiler/cpu-profiler.cc
+++ b/src/profiler/cpu-profiler.cc
@@ -336,9 +336,11 @@ void* SamplingEventsProcessor::operator new(size_t size) {
void SamplingEventsProcessor::operator delete(void* ptr) { AlignedFree(ptr); }
-ProfilerCodeObserver::ProfilerCodeObserver(Isolate* isolate)
+ProfilerCodeObserver::ProfilerCodeObserver(Isolate* isolate,
+ CodeEntryStorage& storage)
: isolate_(isolate),
- code_map_(strings_),
+ code_entries_(storage),
+ code_map_(storage),
weak_code_registry_(isolate),
processor_(nullptr) {
CreateEntriesForRuntimeCallStats();
@@ -350,7 +352,7 @@ void ProfilerCodeObserver::ClearCodeMap() {
code_map_.Clear();
// We don't currently expect any references to refcounted strings to be
// maintained with zero profiles after the code map is cleared.
- DCHECK(strings_.empty());
+ DCHECK(code_entries_.strings().empty());
}
void ProfilerCodeObserver::CodeEventHandler(
@@ -385,8 +387,8 @@ void ProfilerCodeObserver::CreateEntriesForRuntimeCallStats() {
for (int i = 0; i < RuntimeCallStats::kNumberOfCounters; ++i) {
RuntimeCallCounter* counter = rcs->GetCounter(i);
DCHECK(counter->name());
- auto entry = new CodeEntry(CodeEventListener::FUNCTION_TAG, counter->name(),
- "native V8Runtime");
+ auto entry = code_entries_.Create(CodeEventListener::FUNCTION_TAG,
+ counter->name(), "native V8Runtime");
code_map_.AddCode(reinterpret_cast
(counter), entry, 1);
}
#endif // V8_RUNTIME_CALL_STATS
@@ -473,7 +475,7 @@ CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
CpuProfilingLoggingMode logging_mode)
: CpuProfiler(isolate, naming_mode, logging_mode,
new CpuProfilesCollection(isolate), nullptr, nullptr,
- new ProfilerCodeObserver(isolate)) {}
+ new ProfilerCodeObserver(isolate, code_entries_)) {}
CpuProfiler::CpuProfiler(Isolate* isolate, CpuProfilingNamingMode naming_mode,
CpuProfilingLoggingMode logging_mode,
@@ -529,7 +531,7 @@ void CpuProfiler::EnableLogging() {
if (!profiler_listener_) {
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_));
}
profiling_scope_.reset(
diff --git a/src/profiler/cpu-profiler.h b/src/profiler/cpu-profiler.h
index 8ffb45c7cf..9fe1e896be 100644
--- a/src/profiler/cpu-profiler.h
+++ b/src/profiler/cpu-profiler.h
@@ -256,17 +256,17 @@ class V8_EXPORT_PRIVATE SamplingEventsProcessor
// low sampling intervals on Windows.
};
-// Builds and maintains a CodeMap tracking code objects on the VM heap, as well
-// as strings owned by them. While alive, logs generated code, callbacks, and
-// builtins from the isolate. Redirects events to the profiler events
-// processor when present.
+// Builds and maintains a CodeMap tracking code objects on the VM heap. While
+// alive, logs generated code, callbacks, and builtins from the isolate.
+// Redirects events to the profiler events processor when present. CodeEntry
+// lifetime is associated with the given CodeEntryStorage.
class V8_EXPORT_PRIVATE ProfilerCodeObserver : public CodeEventObserver {
public:
- explicit ProfilerCodeObserver(Isolate*);
+ explicit ProfilerCodeObserver(Isolate*, CodeEntryStorage&);
void CodeEventHandler(const CodeEventsContainer& evt_rec) override;
+ CodeEntryStorage* code_entries() { return &code_entries_; }
CodeMap* code_map() { return &code_map_; }
- StringsStorage* strings() { return &strings_; }
WeakCodeRegistry* weak_code_registry() { return &weak_code_registry_; }
void ClearCodeMap();
@@ -290,7 +290,7 @@ class V8_EXPORT_PRIVATE ProfilerCodeObserver : public CodeEventObserver {
void clear_processor() { processor_ = nullptr; }
Isolate* const isolate_;
- StringsStorage strings_;
+ CodeEntryStorage& code_entries_;
CodeMap code_map_;
WeakCodeRegistry weak_code_registry_;
ProfilerEventsProcessor* processor_;
@@ -361,6 +361,7 @@ class V8_EXPORT_PRIVATE CpuProfiler {
Symbolizer* symbolizer() const { return symbolizer_.get(); }
ProfilerEventsProcessor* processor() const { return processor_.get(); }
Isolate* isolate() const { return isolate_; }
+ CodeEntryStorage* code_entries() { return &code_entries_; }
ProfilerListener* profiler_listener_for_test() const {
return profiler_listener_.get();
@@ -389,6 +390,11 @@ class V8_EXPORT_PRIVATE CpuProfiler {
// Sampling interval to which per-profile sampling intervals will be clamped
// to a multiple of, or used as the default if unspecified.
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 code_observer_;
std::unique_ptr profiles_;
std::unique_ptr symbolizer_;
diff --git a/src/profiler/profile-generator-inl.h b/src/profiler/profile-generator-inl.h
index da847a240b..291dd3c028 100644
--- a/src/profiler/profile-generator-inl.h
+++ b/src/profiler/profile-generator-inl.h
@@ -38,6 +38,7 @@ ProfileNode::ProfileNode(ProfileTree* tree, CodeEntry* entry,
parent_(parent),
id_(tree->next_node_id()) {
tree_->EnqueueNode(this);
+ if (tree_->code_entries()) tree_->code_entries()->AddRef(entry_);
}
inline Isolate* ProfileNode::isolate() const { return tree_->isolate(); }
diff --git a/src/profiler/profile-generator.cc b/src/profiler/profile-generator.cc
index 7d51fa9165..e0573bf6ca 100644
--- a/src/profiler/profile-generator.cc
+++ b/src/profiler/profile-generator.cc
@@ -231,6 +231,8 @@ CodeEntry::RareData* CodeEntry::EnsureRareData() {
}
void CodeEntry::ReleaseStrings(StringsStorage& strings) {
+ DCHECK_EQ(ref_count_, 0UL);
+
if (name_) {
strings.Release(name_);
name_ = nullptr;
@@ -296,6 +298,10 @@ void CodeEntry::print() const {
base::OS::Print("\n");
}
+ProfileNode::~ProfileNode() {
+ if (tree_->code_entries()) tree_->code_entries()->DecRef(entry_);
+}
+
CpuProfileNode::SourceType ProfileNode::source_type() const {
// Handle metadata and VM state code entry types.
if (entry_ == CodeEntry::program_entry() ||
@@ -433,10 +439,11 @@ class DeleteNodesCallback {
void AfterChildTraversed(ProfileNode*, ProfileNode*) { }
};
-ProfileTree::ProfileTree(Isolate* isolate)
+ProfileTree::ProfileTree(Isolate* isolate, CodeEntryStorage* storage)
: next_node_id_(1),
root_(new ProfileNode(this, CodeEntry::root_entry(), nullptr)),
- isolate_(isolate) {}
+ isolate_(isolate),
+ code_entries_(storage) {}
ProfileTree::~ProfileTree() {
DeleteNodesCallback cb;
@@ -548,7 +555,7 @@ CpuProfile::CpuProfile(CpuProfiler* profiler, const char* title,
options_(options),
delegate_(std::move(delegate)),
start_time_(base::TimeTicks::HighResolutionNow()),
- top_down_(profiler->isolate()),
+ top_down_(profiler->isolate(), profiler->code_entries()),
profiler_(profiler),
streaming_next_sample_(0),
id_(++last_id_) {
@@ -739,31 +746,32 @@ void CpuProfile::Print() const {
ProfilerStats::Instance()->Clear();
}
-CodeMap::CodeMap(StringsStorage& function_and_resource_names)
- : function_and_resource_names_(function_and_resource_names) {}
+void CodeEntryStorage::AddRef(CodeEntry* entry) {
+ 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(); }
void CodeMap::Clear() {
for (auto& slot : code_map_) {
if (CodeEntry* entry = slot.second.entry) {
- entry->ReleaseStrings(function_and_resource_names_);
- delete entry;
+ code_entries_.DecRef(entry);
} else {
// We expect all entries in the code mapping to contain a CodeEntry.
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();
- used_entries_.clear();
}
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());
for (auto i = range.first; i != range.second; ++i) {
if (i->second.entry == entry) {
- if (!entry->used()) {
- DeleteCodeEntry(entry);
- } else {
- used_entries_.push_back(entry);
- }
+ code_entries_.DecRef(entry);
code_map_.erase(i);
return true;
}
@@ -795,11 +799,7 @@ void CodeMap::ClearCodesInRange(Address start, Address end) {
}
auto right = left;
for (; right != code_map_.end() && right->first < end; ++right) {
- if (!right->second.entry->used()) {
- DeleteCodeEntry(right->second.entry);
- } else {
- used_entries_.push_back(right->second.entry);
- }
+ code_entries_.DecRef(right->second.entry);
}
code_map_.erase(left, right);
}
@@ -842,11 +842,6 @@ void CodeMap::MoveCode(Address from, Address to) {
code_map_.erase(range.first, it);
}
-void CodeMap::DeleteCodeEntry(CodeEntry* entry) {
- entry->ReleaseStrings(function_and_resource_names_);
- delete entry;
-}
-
void CodeMap::Print() {
for (const auto& pair : code_map_) {
base::OS::Print("%p %5d %s\n", reinterpret_cast(pair.first),
diff --git a/src/profiler/profile-generator.h b/src/profiler/profile-generator.h
index f00306acab..e66a3d0662 100644
--- a/src/profiler/profile-generator.h
+++ b/src/profiler/profile-generator.h
@@ -76,6 +76,7 @@ class CodeEntry {
// No alive handles should be associated with the CodeEntry at time of
// destruction.
DCHECK(!heap_object_location_);
+ DCHECK_EQ(ref_count_, 0UL);
}
const char* name() const { return name_; }
@@ -107,8 +108,6 @@ class CodeEntry {
rare_data_->deopt_reason_ = kNoDeoptReason;
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 {
switch (CodeTypeField::decode(bit_field_)) {
@@ -137,6 +136,10 @@ class CodeEntry {
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;
bool IsSameFunctionAs(const CodeEntry* entry) const;
@@ -193,6 +196,8 @@ class CodeEntry {
void print() const;
private:
+ friend class CodeEntryStorage;
+
struct RareData {
const char* deopt_reason_ = kNoDeoptReason;
const char* bailout_reason_ = kEmptyBailoutReason;
@@ -205,17 +210,35 @@ class CodeEntry {
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::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;
using BuiltinField = base::BitField;
static_assert(Builtins::kBuiltinCount <= BuiltinField::kNumValues,
"builtin_count exceeds size of bitfield");
- using CodeTypeField = base::BitField;
- using UsedField = base::BitField;
+ using RefCountedField = base::BitField;
+ using CodeTypeField = base::BitField;
using SharedCrossOriginField = base::BitField;
- // Atomic because Used is written from the profiler thread while CodeType is
- // read from the main thread.
- std::atomic bit_field_;
+ std::uint32_t bit_field_;
+ std::atomic ref_count_ = {0};
const char* name_;
const char* resource_name_;
int line_number_;
@@ -266,6 +289,7 @@ class V8_EXPORT_PRIVATE ProfileNode {
public:
inline ProfileNode(ProfileTree* tree, CodeEntry* entry, ProfileNode* parent,
int line_number = 0);
+ ~ProfileNode();
ProfileNode(const ProfileNode&) = delete;
ProfileNode& operator=(const ProfileNode&) = delete;
@@ -329,9 +353,11 @@ class V8_EXPORT_PRIVATE ProfileNode {
std::vector deopt_infos_;
};
+class CodeEntryStorage;
+
class V8_EXPORT_PRIVATE ProfileTree {
public:
- explicit ProfileTree(Isolate* isolate);
+ explicit ProfileTree(Isolate* isolate, CodeEntryStorage* storage = nullptr);
~ProfileTree();
ProfileTree(const ProfileTree&) = delete;
ProfileTree& operator=(const ProfileTree&) = delete;
@@ -360,6 +386,8 @@ class V8_EXPORT_PRIVATE ProfileTree {
return std::move(pending_nodes_);
}
+ CodeEntryStorage* code_entries() { return code_entries_; }
+
private:
template
void TraverseDepthFirst(Callback* callback);
@@ -369,6 +397,7 @@ class V8_EXPORT_PRIVATE ProfileTree {
unsigned next_node_id_;
ProfileNode* root_;
Isolate* isolate_;
+ CodeEntryStorage* code_entries_;
};
class CpuProfiler;
@@ -450,13 +479,13 @@ class CpuProfileMaxSamplesCallbackTask : public v8::Task {
class V8_EXPORT_PRIVATE CodeMap {
public:
- // Creates a new CodeMap with an associated StringsStorage to store the
- // strings of CodeEntry objects within.
- explicit CodeMap(StringsStorage& function_and_resource_names);
+ explicit CodeMap(CodeEntryStorage& storage);
~CodeMap();
CodeMap(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 MoveCode(Address from, Address to);
// Attempts to remove the given CodeEntry from the CodeMap.
@@ -467,6 +496,8 @@ class V8_EXPORT_PRIVATE CodeMap {
void Print();
size_t size() const { return code_map_.size(); }
+ CodeEntryStorage& code_entries() { return code_entries_; }
+
void Clear();
private:
@@ -475,12 +506,28 @@ class V8_EXPORT_PRIVATE CodeMap {
unsigned size;
};
- void DeleteCodeEntry(CodeEntry*);
-
std::multimap code_map_;
- std::deque used_entries_; // Entries that are no longer in the
- // map, but used by a profile.
- StringsStorage& function_and_resource_names_;
+ CodeEntryStorage& code_entries_;
+};
+
+// Manages the lifetime of CodeEntry objects, and stores shared resources
+// between them.
+class V8_EXPORT_PRIVATE CodeEntryStorage {
+ public:
+ template
+ static CodeEntry* Create(Args&&... args) {
+ CodeEntry* const entry = new CodeEntry(std::forward(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 {
diff --git a/src/profiler/profiler-listener.cc b/src/profiler/profiler-listener.cc
index a2cfb8b07b..3c14e20e66 100644
--- a/src/profiler/profiler-listener.cc
+++ b/src/profiler/profiler-listener.cc
@@ -29,12 +29,12 @@ namespace internal {
ProfilerListener::ProfilerListener(Isolate* isolate,
CodeEventObserver* observer,
- StringsStorage& function_and_resource_names,
+ CodeEntryStorage& code_entry_storage,
WeakCodeRegistry& weak_code_registry,
CpuProfilingNamingMode naming_mode)
: isolate_(isolate),
observer_(observer),
- function_and_resource_names_(function_and_resource_names),
+ code_entries_(code_entry_storage),
weak_code_registry_(weak_code_registry),
naming_mode_(naming_mode) {}
@@ -46,9 +46,10 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = code->InstructionStart();
- rec->entry = new CodeEntry(tag, GetName(name), CodeEntry::kEmptyResourceName,
- CpuProfileNode::kNoLineNumberInfo,
- CpuProfileNode::kNoColumnNumberInfo, nullptr);
+ rec->entry =
+ code_entries_.Create(tag, GetName(name), CodeEntry::kEmptyResourceName,
+ CpuProfileNode::kNoLineNumberInfo,
+ CpuProfileNode::kNoColumnNumberInfo, nullptr);
rec->instruction_size = code->InstructionSize();
weak_code_registry_.Track(rec->entry, code);
DispatchCodeEvent(evt_rec);
@@ -60,9 +61,10 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = code->InstructionStart();
- rec->entry = new CodeEntry(tag, GetName(*name), CodeEntry::kEmptyResourceName,
- CpuProfileNode::kNoLineNumberInfo,
- CpuProfileNode::kNoColumnNumberInfo, nullptr);
+ rec->entry =
+ code_entries_.Create(tag, GetName(*name), CodeEntry::kEmptyResourceName,
+ CpuProfileNode::kNoLineNumberInfo,
+ CpuProfileNode::kNoColumnNumberInfo, nullptr);
rec->instruction_size = code->InstructionSize();
weak_code_registry_.Track(rec->entry, code);
DispatchCodeEvent(evt_rec);
@@ -75,10 +77,11 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = code->InstructionStart();
- rec->entry = new CodeEntry(tag, GetName(shared->DebugNameCStr().get()),
- GetName(InferScriptName(*script_name, *shared)),
- CpuProfileNode::kNoLineNumberInfo,
- CpuProfileNode::kNoColumnNumberInfo, nullptr);
+ rec->entry =
+ code_entries_.Create(tag, GetName(shared->DebugNameCStr().get()),
+ GetName(InferScriptName(*script_name, *shared)),
+ CpuProfileNode::kNoLineNumberInfo,
+ CpuProfileNode::kNoColumnNumberInfo, nullptr);
DCHECK_IMPLIES(code->IsCode(), code->kind() == CodeKind::BASELINE);
rec->entry->FillFunctionInfo(*shared);
rec->instruction_size = code->InstructionSize();
@@ -91,10 +94,10 @@ namespace {
CodeEntry* GetOrInsertCachedEntry(
std::unordered_set, CodeEntry::Hasher,
CodeEntry::Equals>* entries,
- std::unique_ptr search_value, StringsStorage& strings) {
+ std::unique_ptr search_value, CodeEntryStorage& storage) {
auto it = entries->find(search_value);
if (it != entries->end()) {
- search_value->ReleaseStrings(strings);
+ search_value->ReleaseStrings(storage.strings());
return it->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
// them for subsequent inline stacks to avoid a lot of duplication.
CodeEntry* cached_entry = GetOrInsertCachedEntry(
- &cached_inline_entries, std::move(inline_entry),
- function_and_resource_names_);
+ &cached_inline_entries, std::move(inline_entry), code_entries_);
inline_stack.push_back({cached_entry, line_number});
}
@@ -214,10 +216,10 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
}
}
}
- rec->entry =
- new CodeEntry(tag, GetFunctionName(*shared),
- GetName(InferScriptName(*script_name, *shared)), line,
- column, std::move(line_table), is_shared_cross_origin);
+ rec->entry = code_entries_.Create(
+ tag, GetFunctionName(*shared),
+ GetName(InferScriptName(*script_name, *shared)), line, column,
+ std::move(line_table), is_shared_cross_origin);
if (!inline_stacks.empty()) {
rec->entry->SetInlineStacks(std::move(cached_inline_entries),
std::move(inline_stacks));
@@ -238,9 +240,9 @@ void ProfilerListener::CodeCreateEvent(LogEventsAndTags tag,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = code->instruction_start();
- rec->entry =
- new CodeEntry(tag, GetName(name), GetName(source_url), 1, code_offset + 1,
- nullptr, true, CodeEntry::CodeType::WASM);
+ rec->entry = code_entries_.Create(tag, GetName(name), GetName(source_url), 1,
+ code_offset + 1, nullptr, true,
+ CodeEntry::CodeType::WASM);
rec->entry->set_script_id(script_id);
rec->entry->set_position(code_offset);
rec->instruction_size = code->instructions().length();
@@ -252,7 +254,8 @@ void ProfilerListener::CallbackEvent(Handle name, Address entry_point) {
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
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;
DispatchCodeEvent(evt_rec);
}
@@ -262,8 +265,8 @@ void ProfilerListener::GetterCallbackEvent(Handle name,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = entry_point;
- rec->entry = new CodeEntry(CodeEventListener::CALLBACK_TAG,
- GetConsName("get ", *name));
+ rec->entry = code_entries_.Create(CodeEventListener::CALLBACK_TAG,
+ GetConsName("get ", *name));
rec->instruction_size = 1;
DispatchCodeEvent(evt_rec);
}
@@ -273,8 +276,8 @@ void ProfilerListener::SetterCallbackEvent(Handle name,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = entry_point;
- rec->entry = new CodeEntry(CodeEventListener::CALLBACK_TAG,
- GetConsName("set ", *name));
+ rec->entry = code_entries_.Create(CodeEventListener::CALLBACK_TAG,
+ GetConsName("set ", *name));
rec->instruction_size = 1;
DispatchCodeEvent(evt_rec);
}
@@ -284,7 +287,7 @@ void ProfilerListener::RegExpCodeCreateEvent(Handle code,
CodeEventsContainer evt_rec(CodeEventRecord::CODE_CREATION);
CodeCreateEventRecord* rec = &evt_rec.CodeCreateEventRecord_;
rec->instruction_start = code->InstructionStart();
- rec->entry = new CodeEntry(
+ rec->entry = code_entries_.Create(
CodeEventListener::REG_EXP_TAG, GetConsName("RegExp: ", *source),
CodeEntry::kEmptyResourceName, CpuProfileNode::kNoLineNumberInfo,
CpuProfileNode::kNoColumnNumberInfo, nullptr);
diff --git a/src/profiler/profiler-listener.h b/src/profiler/profiler-listener.h
index 50a9b81893..de2d1ec997 100644
--- a/src/profiler/profiler-listener.h
+++ b/src/profiler/profiler-listener.h
@@ -29,7 +29,7 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener,
public WeakCodeRegistry::Listener {
public:
ProfilerListener(Isolate*, CodeEventObserver*,
- StringsStorage& function_and_resource_names,
+ CodeEntryStorage& code_entry_storage,
WeakCodeRegistry& weak_code_registry,
CpuProfilingNamingMode mode = kDebugNaming);
~ProfilerListener() override;
@@ -76,17 +76,17 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener,
void CodeSweepEvent();
const char* GetName(Name name) {
- return function_and_resource_names_.GetName(name);
+ return code_entries_.strings().GetName(name);
}
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) {
- return function_and_resource_names_.GetCopy(name);
+ return code_entries_.strings().GetCopy(name);
}
const char* GetName(Vector 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; }
@@ -102,7 +102,7 @@ class V8_EXPORT_PRIVATE ProfilerListener : public CodeEventListener,
Isolate* isolate_;
CodeEventObserver* observer_;
- StringsStorage& function_and_resource_names_;
+ CodeEntryStorage& code_entries_;
WeakCodeRegistry& weak_code_registry_;
const CpuProfilingNamingMode naming_mode_;
};
diff --git a/src/profiler/symbolizer.cc b/src/profiler/symbolizer.cc
index 61e884265d..d3aa629d25 100644
--- a/src/profiler/symbolizer.cc
+++ b/src/profiler/symbolizer.cc
@@ -16,9 +16,7 @@ Symbolizer::Symbolizer(CodeMap* code_map) : code_map_(code_map) {}
CodeEntry* Symbolizer::FindEntry(Address address,
Address* out_instruction_start) {
- CodeEntry* entry = code_map_->FindEntry(address, out_instruction_start);
- if (entry) entry->mark_used();
- return entry;
+ return code_map_->FindEntry(address, out_instruction_start);
}
namespace {
diff --git a/test/cctest/test-cpu-profiler.cc b/test/cctest/test-cpu-profiler.cc
index 2373fd2f3a..f0a6a06079 100644
--- a/test/cctest/test-cpu-profiler.cc
+++ b/test/cctest/test-cpu-profiler.cc
@@ -88,8 +88,9 @@ static const char* reason(const i::DeoptimizeReason reason) {
TEST(StartStop) {
i::Isolate* isolate = CcTest::i_isolate();
+ CodeEntryStorage storage;
CpuProfilesCollection profiles(isolate);
- ProfilerCodeObserver code_observer(isolate);
+ ProfilerCodeObserver code_observer(isolate, storage);
Symbolizer symbolizer(code_observer.code_map());
std::unique_ptr processor(
new SamplingEventsProcessor(
@@ -171,15 +172,16 @@ TEST(CodeEvents) {
i::Handle comment2_code(CreateCode(isolate, &env), isolate);
i::Handle moved_code(CreateCode(isolate, &env), isolate);
+ CodeEntryStorage storage;
CpuProfilesCollection* profiles = new CpuProfilesCollection(isolate);
- ProfilerCodeObserver code_observer(isolate);
+ ProfilerCodeObserver code_observer(isolate, storage);
Symbolizer* symbolizer = new Symbolizer(code_observer.code_map());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
isolate, symbolizer, &code_observer, profiles,
v8::base::TimeDelta::FromMicroseconds(100), true);
CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor,
- *code_observer.strings(),
+ *code_observer.code_entries(),
*code_observer.weak_code_registry());
isolate->logger()->AddCodeEventListener(&profiler_listener);
@@ -234,8 +236,10 @@ TEST(TickEvents) {
i::Handle frame2_code(CreateCode(isolate, &env), isolate);
i::Handle frame3_code(CreateCode(isolate, &env), isolate);
+ CodeEntryStorage storage;
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());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), symbolizer, code_observer, profiles,
@@ -245,7 +249,7 @@ TEST(TickEvents) {
profiles->StartProfiling("");
CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor,
- *code_observer->strings(),
+ *code_observer->code_entries(),
*code_observer->weak_code_registry());
isolate->logger()->AddCodeEventListener(&profiler_listener);
@@ -396,8 +400,10 @@ TEST(Issue1398) {
i::Handle code(CreateCode(isolate, &env), isolate);
+ CodeEntryStorage storage;
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());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), symbolizer, code_observer, profiles,
@@ -407,7 +413,7 @@ TEST(Issue1398) {
profiles->StartProfiling("");
CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor,
- *code_observer->strings(),
+ *code_observer->code_entries(),
*code_observer->weak_code_registry());
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();
CHECK_NE(code_address, kNullAddress);
+ CodeEntryStorage storage;
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());
ProfilerEventsProcessor* processor = new SamplingEventsProcessor(
CcTest::i_isolate(), symbolizer, code_observer, profiles,
@@ -1278,7 +1286,7 @@ static void TickLines(bool optimize) {
isolate->logger()->LogCompiledFunctions();
CHECK(processor->Start());
ProfilerListener profiler_listener(isolate, processor,
- *code_observer->strings(),
+ *code_observer->code_entries(),
*code_observer->weak_code_registry());
// Enqueue code creation events.
@@ -3474,8 +3482,9 @@ TEST(MaxSimultaneousProfiles) {
TEST(LowPrecisionSamplingStartStopInternal) {
i::Isolate* isolate = CcTest::i_isolate();
+ CodeEntryStorage storage;
CpuProfilesCollection profiles(isolate);
- ProfilerCodeObserver code_observer(isolate);
+ ProfilerCodeObserver code_observer(isolate, storage);
Symbolizer symbolizer(code_observer.code_map());
std::unique_ptr processor(
new SamplingEventsProcessor(
@@ -3600,8 +3609,10 @@ TEST(ProflilerSubsampling) {
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
+ CodeEntryStorage storage;
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());
ProfilerEventsProcessor* processor =
new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles,
@@ -3644,8 +3655,10 @@ TEST(DynamicResampling) {
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
+ CodeEntryStorage storage;
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());
ProfilerEventsProcessor* processor =
new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles,
@@ -3705,8 +3718,10 @@ TEST(DynamicResamplingWithBaseInterval) {
i::Isolate* isolate = CcTest::i_isolate();
i::HandleScope scope(isolate);
+ CodeEntryStorage storage;
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());
ProfilerEventsProcessor* processor =
new SamplingEventsProcessor(isolate, symbolizer, code_observer, profiles,
diff --git a/test/cctest/test-profile-generator.cc b/test/cctest/test-profile-generator.cc
index ab56d6e7cc..aec85635b5 100644
--- a/test/cctest/test-profile-generator.cc
+++ b/test/cctest/test-profile-generator.cc
@@ -311,12 +311,12 @@ static inline i::Address ToAddress(int n) { return static_cast(n); }
static inline void* ToPointer(int n) { return reinterpret_cast(n); }
TEST(CodeMapAddCode) {
- StringsStorage strings;
- CodeMap code_map(strings);
- CodeEntry* entry1 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa");
- CodeEntry* entry2 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb");
- CodeEntry* entry3 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "ccc");
- CodeEntry* entry4 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "ddd");
+ CodeEntryStorage storage;
+ CodeMap code_map(storage);
+ CodeEntry* entry1 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
+ CodeEntry* entry2 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "bbb");
+ CodeEntry* entry3 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "ccc");
+ CodeEntry* entry4 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "ddd");
code_map.AddCode(ToAddress(0x1500), entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), entry2, 0x100);
code_map.AddCode(ToAddress(0x1900), entry3, 0x50);
@@ -341,10 +341,10 @@ TEST(CodeMapAddCode) {
}
TEST(CodeMapMoveAndDeleteCode) {
- StringsStorage strings;
- CodeMap code_map(strings);
- CodeEntry* entry1 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa");
- CodeEntry* entry2 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb");
+ CodeEntryStorage storage;
+ CodeMap code_map(storage);
+ CodeEntry* entry1 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
+ CodeEntry* entry2 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "bbb");
code_map.AddCode(ToAddress(0x1500), entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), entry2, 0x100);
CHECK_EQ(entry1, code_map.FindEntry(ToAddress(0x1500)));
@@ -355,10 +355,10 @@ TEST(CodeMapMoveAndDeleteCode) {
}
TEST(CodeMapClear) {
- StringsStorage strings;
- CodeMap code_map(strings);
- CodeEntry* entry1 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa");
- CodeEntry* entry2 = new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb");
+ CodeEntryStorage storage;
+ CodeMap code_map(storage);
+ CodeEntry* entry1 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
+ CodeEntry* entry2 = storage.Create(i::CodeEventListener::FUNCTION_TAG, "bbb");
code_map.AddCode(ToAddress(0x1500), entry1, 0x200);
code_map.AddCode(ToAddress(0x1700), entry2, 0x100);
@@ -391,12 +391,12 @@ class TestSetup {
TEST(SymbolizeTickSample) {
TestSetup test_setup;
- StringsStorage strings;
- CodeMap code_map(strings);
+ CodeEntryStorage storage;
+ CodeMap code_map(storage);
Symbolizer symbolizer(&code_map);
- CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
- CodeEntry* entry2 = new CodeEntry(i::Logger::FUNCTION_TAG, "bbb");
- CodeEntry* entry3 = new CodeEntry(i::Logger::FUNCTION_TAG, "ccc");
+ CodeEntry* entry1 = storage.Create(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry* entry2 = storage.Create(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry* entry3 = storage.Create(i::Logger::FUNCTION_TAG, "ccc");
symbolizer.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
symbolizer.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100);
symbolizer.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50);
@@ -456,16 +456,16 @@ static void CheckNodeIds(const ProfileNode* node, unsigned* expectedId) {
TEST(SampleIds) {
TestSetup test_setup;
i::Isolate* isolate = CcTest::i_isolate();
- CpuProfilesCollection profiles(isolate);
CpuProfiler profiler(isolate);
+ CpuProfilesCollection profiles(isolate);
profiles.set_cpu_profiler(&profiler);
profiles.StartProfiling("", {CpuProfilingMode::kLeafNodeLineNumbers});
- StringsStorage strings;
- CodeMap code_map(strings);
+ CodeEntryStorage storage;
+ CodeMap code_map(storage);
Symbolizer symbolizer(&code_map);
- CodeEntry* entry1 = new CodeEntry(i::Logger::FUNCTION_TAG, "aaa");
- CodeEntry* entry2 = new CodeEntry(i::Logger::FUNCTION_TAG, "bbb");
- CodeEntry* entry3 = new CodeEntry(i::Logger::FUNCTION_TAG, "ccc");
+ CodeEntry* entry1 = storage.Create(i::Logger::FUNCTION_TAG, "aaa");
+ CodeEntry* entry2 = storage.Create(i::Logger::FUNCTION_TAG, "bbb");
+ CodeEntry* entry3 = storage.Create(i::Logger::FUNCTION_TAG, "ccc");
symbolizer.code_map()->AddCode(ToAddress(0x1500), entry1, 0x200);
symbolizer.code_map()->AddCode(ToAddress(0x1700), entry2, 0x100);
symbolizer.code_map()->AddCode(ToAddress(0x1900), entry3, 0x50);
@@ -592,8 +592,8 @@ TEST(MaxSamplesCallback) {
MaybeLocal()},
std::move(impl));
- StringsStorage strings;
- CodeMap code_map(strings);
+ CodeEntryStorage storage;
+ CodeMap code_map(storage);
Symbolizer symbolizer(&code_map);
TickSample sample1;
sample1.timestamp = v8::base::TimeTicks::HighResolutionNow();
@@ -633,14 +633,14 @@ TEST(MaxSamplesCallback) {
TEST(NoSamples) {
TestSetup test_setup;
i::Isolate* isolate = CcTest::i_isolate();
- CpuProfilesCollection profiles(isolate);
CpuProfiler profiler(isolate);
+ CpuProfilesCollection profiles(isolate);
profiles.set_cpu_profiler(&profiler);
profiles.StartProfiling("");
- StringsStorage strings;
- CodeMap code_map(strings);
+ CodeEntryStorage storage;
+ CodeMap code_map(storage);
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);
// We are building the following calls tree:
@@ -959,10 +959,10 @@ TEST(NodeSourceTypes) {
}
TEST(CodeMapRemoveCode) {
- StringsStorage strings;
- CodeMap code_map(strings);
+ CodeEntryStorage storage;
+ 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);
CHECK(code_map.RemoveCode(entry));
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
// entry that we desired to.
CodeEntry* colliding_entry1 =
- new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa");
+ storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
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_entry2, 0x100);
@@ -984,14 +984,14 @@ TEST(CodeMapRemoveCode) {
}
TEST(CodeMapMoveOverlappingCode) {
- StringsStorage strings;
- CodeMap code_map(strings);
+ CodeEntryStorage storage;
+ CodeMap code_map(storage);
CodeEntry* colliding_entry1 =
- new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "aaa");
+ storage.Create(i::CodeEventListener::FUNCTION_TAG, "aaa");
CodeEntry* colliding_entry2 =
- new CodeEntry(i::CodeEventListener::FUNCTION_TAG, "bbb");
+ storage.Create(i::CodeEventListener::FUNCTION_TAG, "bbb");
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_entry2, 0x200);