[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:
parent
7d468b70cd
commit
8e44ee5f75
@ -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
|
||||
|
@ -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<Address>(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(
|
||||
|
@ -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<ProfilerCodeObserver> code_observer_;
|
||||
std::unique_ptr<CpuProfilesCollection> profiles_;
|
||||
std::unique_ptr<Symbolizer> symbolizer_;
|
||||
|
@ -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(); }
|
||||
|
@ -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<void*>(pair.first),
|
||||
|
@ -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<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 BuiltinField = base::BitField<Builtin, 8, 20>;
|
||||
static_assert(Builtins::kBuiltinCount <= BuiltinField::kNumValues,
|
||||
"builtin_count exceeds size of bitfield");
|
||||
using CodeTypeField = base::BitField<CodeType, 28, 2>;
|
||||
using UsedField = base::BitField<bool, 30, 1>;
|
||||
using RefCountedField = base::BitField<bool, 28, 1>;
|
||||
using CodeTypeField = base::BitField<CodeType, 29, 2>;
|
||||
using SharedCrossOriginField = base::BitField<bool, 31, 1>;
|
||||
|
||||
// Atomic because Used is written from the profiler thread while CodeType is
|
||||
// read from the main thread.
|
||||
std::atomic<std::uint32_t> bit_field_;
|
||||
std::uint32_t bit_field_;
|
||||
std::atomic<std::size_t> 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<CpuProfileDeoptInfo> 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 <typename Callback>
|
||||
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<Address, CodeEntryMapInfo> code_map_;
|
||||
std::deque<CodeEntry*> 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 <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 {
|
||||
|
@ -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<std::unique_ptr<CodeEntry>, CodeEntry::Hasher,
|
||||
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);
|
||||
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> 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> 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> 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<AbstractCode> 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);
|
||||
|
@ -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<const char> 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_;
|
||||
};
|
||||
|
@ -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 {
|
||||
|
@ -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<ProfilerEventsProcessor> processor(
|
||||
new SamplingEventsProcessor(
|
||||
@ -171,15 +172,16 @@ TEST(CodeEvents) {
|
||||
i::Handle<i::AbstractCode> comment2_code(CreateCode(isolate, &env), isolate);
|
||||
i::Handle<i::AbstractCode> 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<i::AbstractCode> frame2_code(CreateCode(isolate, &env), isolate);
|
||||
i::Handle<i::AbstractCode> 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<i::AbstractCode> 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<ProfilerEventsProcessor> 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,
|
||||
|
@ -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); }
|
||||
|
||||
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<v8::Context>()},
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user