Commit 4578e52a authored by machenbach's avatar machenbach Committed by Commit bot

Revert of Sampling heap profiler data structure changes (patchset #10...

Revert of Sampling heap profiler data structure changes (patchset #10 id:180001 of https://codereview.chromium.org/1697903002/ )

Reason for revert:
[Sheriff] Speculative revert for cpu profiler crashes on chromebooks:
https://build.chromium.org/p/client.v8/builders/V8%20Arm%20-%20debug/builds/549
https://build.chromium.org/p/client.v8/builders/V8%20Arm%20-%20debug/builds/550

Original issue's description:
> Sampling heap profiler data structure changes
>
> Previously, the sampling heap profiler stored a list of samples and then
> built a tree representation when the profile was queried by calling
> GetAllocationProfile. This change reduces duplication by removing stacks
> from all samples. Also, less information is stored in the tree
> maintained by the profiler and remaining information (script name, line
> no, etc) is resolved when a profile is requested.
>
> BUG=
>
> Committed: https://crrev.com/cdd55e2a3717723492d76f66810bf56b8de7f198
> Cr-Commit-Position: refs/heads/master@{#34119}

TBR=ofrobots@google.com,ulan@chromium.org,hpayer@chromium.org,mattloring@google.com
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=

Review URL: https://codereview.chromium.org/1708363002

Cr-Commit-Position: refs/heads/master@{#34128}
parent 557adc2c
...@@ -44,7 +44,6 @@ SamplingHeapProfiler::SamplingHeapProfiler(Heap* heap, StringsStorage* names, ...@@ -44,7 +44,6 @@ SamplingHeapProfiler::SamplingHeapProfiler(Heap* heap, StringsStorage* names,
heap_, static_cast<intptr_t>(rate), rate, this, heap_, static_cast<intptr_t>(rate), rate, this,
heap->isolate()->random_number_generator())), heap->isolate()->random_number_generator())),
names_(names), names_(names),
profile_root_("(root)", v8::UnboundScript::kNoScriptId, 0),
samples_(), samples_(),
stack_depth_(stack_depth) { stack_depth_(stack_depth) {
heap->new_space()->AddAllocationObserver(new_space_observer_.get()); heap->new_space()->AddAllocationObserver(new_space_observer_.get());
...@@ -66,10 +65,12 @@ SamplingHeapProfiler::~SamplingHeapProfiler() { ...@@ -66,10 +65,12 @@ SamplingHeapProfiler::~SamplingHeapProfiler() {
} }
} }
for (auto sample : samples_) { // Clear samples and drop all the weak references we are keeping.
delete sample; std::set<SampledAllocation*>::iterator it;
for (it = samples_.begin(); it != samples_.end(); ++it) {
delete *it;
} }
std::set<Sample*> empty; std::set<SampledAllocation*> empty;
samples_.swap(empty); samples_.swap(empty);
} }
...@@ -87,48 +88,51 @@ void SamplingHeapProfiler::SampleObject(Address soon_object, size_t size) { ...@@ -87,48 +88,51 @@ void SamplingHeapProfiler::SampleObject(Address soon_object, size_t size) {
Local<v8::Value> loc = v8::Utils::ToLocal(obj); Local<v8::Value> loc = v8::Utils::ToLocal(obj);
AllocationNode* node = AddStack(); SampledAllocation* sample =
node->allocations_[size]++; new SampledAllocation(this, isolate_, loc, size, stack_depth_);
Sample* sample = new Sample(size, node, loc, this);
samples_.insert(sample); samples_.insert(sample);
sample->global.SetWeak(sample, OnWeakCallback, WeakCallbackType::kParameter);
} }
void SamplingHeapProfiler::OnWeakCallback(
const WeakCallbackInfo<Sample>& data) { void SamplingHeapProfiler::SampledAllocation::OnWeakCallback(
Sample* sample = data.GetParameter(); const WeakCallbackInfo<SampledAllocation>& data) {
AllocationNode* node = sample->owner; SampledAllocation* sample = data.GetParameter();
DCHECK(node->allocations_[sample->size] > 0); sample->sampling_heap_profiler_->samples_.erase(sample);
node->allocations_[sample->size]--;
sample->profiler->samples_.erase(sample);
delete sample; delete sample;
} }
SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::FindOrAddChildNode(
AllocationNode* parent, const char* name, int script_id, SamplingHeapProfiler::FunctionInfo::FunctionInfo(SharedFunctionInfo* shared,
int start_position) { StringsStorage* names)
for (AllocationNode* child : parent->children_) { : name_(names->GetFunctionName(shared->DebugName())),
if (child->script_id_ == script_id && script_name_(""),
child->script_position_ == start_position && script_id_(v8::UnboundScript::kNoScriptId),
strcmp(child->name_, name) == 0) { start_position_(shared->start_position()) {
return child; if (shared->script()->IsScript()) {
Script* script = Script::cast(shared->script());
script_id_ = script->id();
if (script->name()->IsName()) {
Name* name = Name::cast(script->name());
script_name_ = names->GetName(name);
} }
} }
AllocationNode* child = new AllocationNode(name, script_id, start_position);
parent->children_.push_back(child);
return child;
} }
SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() {
AllocationNode* node = &profile_root_;
std::vector<SharedFunctionInfo*> stack; SamplingHeapProfiler::SampledAllocation::SampledAllocation(
StackTraceFrameIterator it(isolate_); SamplingHeapProfiler* sampling_heap_profiler, Isolate* isolate,
Local<Value> local, size_t size, int max_frames)
: sampling_heap_profiler_(sampling_heap_profiler),
global_(reinterpret_cast<v8::Isolate*>(isolate), local),
size_(size) {
global_.SetWeak(this, OnWeakCallback, WeakCallbackType::kParameter);
StackTraceFrameIterator it(isolate);
int frames_captured = 0; int frames_captured = 0;
while (!it.done() && frames_captured < stack_depth_) { while (!it.done() && frames_captured < max_frames) {
JavaScriptFrame* frame = it.frame(); JavaScriptFrame* frame = it.frame();
SharedFunctionInfo* shared = frame->function()->shared(); SharedFunctionInfo* shared = frame->function()->shared();
stack.push_back(shared); stack_.push_back(new FunctionInfo(shared, sampling_heap_profiler->names()));
frames_captured++; frames_captured++;
it.Advance(); it.Advance();
...@@ -136,7 +140,7 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() { ...@@ -136,7 +140,7 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() {
if (frames_captured == 0) { if (frames_captured == 0) {
const char* name = nullptr; const char* name = nullptr;
switch (isolate_->current_vm_state()) { switch (isolate->current_vm_state()) {
case GC: case GC:
name = "(GC)"; name = "(GC)";
break; break;
...@@ -156,63 +160,71 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() { ...@@ -156,63 +160,71 @@ SamplingHeapProfiler::AllocationNode* SamplingHeapProfiler::AddStack() {
name = "(JS)"; name = "(JS)";
break; break;
} }
return FindOrAddChildNode(node, name, v8::UnboundScript::kNoScriptId, 0); stack_.push_back(new FunctionInfo(name));
} }
// We need to process the stack in reverse order as the top of the stack is
// the first element in the list.
for (auto it = stack.rbegin(); it != stack.rend(); ++it) {
SharedFunctionInfo* shared = *it;
const char* name = this->names()->GetFunctionName(shared->DebugName());
int script_id = v8::UnboundScript::kNoScriptId;
if (shared->script()->IsScript()) {
Script* script = Script::cast(shared->script());
script_id = script->id();
}
node = FindOrAddChildNode(node, name, script_id, shared->start_position());
}
return node;
} }
v8::AllocationProfile::Node* SamplingHeapProfiler::TranslateAllocationNode( v8::AllocationProfile::Node* SamplingHeapProfiler::AllocateNode(
AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node, AllocationProfile* profile, const std::map<int, Script*>& scripts,
const std::map<int, Script*>& scripts) { FunctionInfo* function_info) {
Local<v8::String> script_name = DCHECK(function_info->get_name());
ToApiHandle<v8::String>(isolate_->factory()->InternalizeUtf8String("")); DCHECK(function_info->get_script_name());
int line = v8::AllocationProfile::kNoLineNumberInfo; int line = v8::AllocationProfile::kNoLineNumberInfo;
int column = v8::AllocationProfile::kNoColumnNumberInfo; int column = v8::AllocationProfile::kNoColumnNumberInfo;
std::vector<v8::AllocationProfile::Allocation> allocations;
if (node->script_id_ != v8::UnboundScript::kNoScriptId) { if (function_info->get_script_id() != v8::UnboundScript::kNoScriptId) {
// Cannot use std::map<T>::at because it is not available on android. // Cannot use std::map<T>::at because it is not available on android.
auto non_const_scripts = const_cast<std::map<int, Script*>&>(scripts); auto non_const_scripts = const_cast<std::map<int, Script*>&>(scripts);
Script* script = non_const_scripts[node->script_id_]; Handle<Script> script(non_const_scripts[function_info->get_script_id()]);
if (script->name()->IsName()) {
Name* name = Name::cast(script->name());
script_name = ToApiHandle<v8::String>(
isolate_->factory()->InternalizeUtf8String(names_->GetName(name)));
}
Handle<Script> script_handle(script);
line = 1 + Script::GetLineNumber(script_handle, node->script_position_); line =
column = 1 + Script::GetColumnNumber(script_handle, node->script_position_); 1 + Script::GetLineNumber(script, function_info->get_start_position());
for (auto alloc : node->allocations_) { column = 1 + Script::GetColumnNumber(script,
allocations.push_back({alloc.first, alloc.second}); function_info->get_start_position());
}
} }
profile->nodes().push_back(v8::AllocationProfile::Node( profile->nodes().push_back(v8::AllocationProfile::Node(
{ToApiHandle<v8::String>( {ToApiHandle<v8::String>(isolate_->factory()->InternalizeUtf8String(
isolate_->factory()->InternalizeUtf8String(node->name_)), function_info->get_name())),
script_name, node->script_id_, node->script_position_, line, column, ToApiHandle<v8::String>(isolate_->factory()->InternalizeUtf8String(
std::vector<v8::AllocationProfile::Node*>(), allocations})); function_info->get_script_name())),
v8::AllocationProfile::Node* current = &profile->nodes().back(); function_info->get_script_id(), function_info->get_start_position(),
for (auto child : node->children_) { line, column, std::vector<v8::AllocationProfile::Node*>(),
current->children.push_back( std::vector<v8::AllocationProfile::Allocation>()}));
TranslateAllocationNode(profile, child, scripts));
} return &profile->nodes().back();
return current;
} }
v8::AllocationProfile::Node* SamplingHeapProfiler::FindOrAddChildNode(
AllocationProfile* profile, const std::map<int, Script*>& scripts,
v8::AllocationProfile::Node* parent, FunctionInfo* function_info) {
for (v8::AllocationProfile::Node* child : parent->children) {
if (child->script_id == function_info->get_script_id() &&
child->start_position == function_info->get_start_position())
return child;
}
v8::AllocationProfile::Node* child =
AllocateNode(profile, scripts, function_info);
parent->children.push_back(child);
return child;
}
v8::AllocationProfile::Node* SamplingHeapProfiler::AddStack(
AllocationProfile* profile, const std::map<int, Script*>& scripts,
const std::vector<FunctionInfo*>& stack) {
v8::AllocationProfile::Node* node = profile->GetRootNode();
// We need to process the stack in reverse order as the top of the stack is
// the first element in the list.
for (auto it = stack.rbegin(); it != stack.rend(); ++it) {
FunctionInfo* function_info = *it;
node = FindOrAddChildNode(profile, scripts, node, function_info);
}
return node;
}
v8::AllocationProfile* SamplingHeapProfiler::GetAllocationProfile() { v8::AllocationProfile* SamplingHeapProfiler::GetAllocationProfile() {
// To resolve positions to line/column numbers, we will need to look up // To resolve positions to line/column numbers, we will need to look up
// scripts. Build a map to allow fast mapping from script id to script. // scripts. Build a map to allow fast mapping from script id to script.
...@@ -227,7 +239,15 @@ v8::AllocationProfile* SamplingHeapProfiler::GetAllocationProfile() { ...@@ -227,7 +239,15 @@ v8::AllocationProfile* SamplingHeapProfiler::GetAllocationProfile() {
auto profile = new v8::internal::AllocationProfile(); auto profile = new v8::internal::AllocationProfile();
TranslateAllocationNode(profile, &profile_root_, scripts); // Create the root node.
FunctionInfo function_info("(root)");
AllocateNode(profile, scripts, &function_info);
for (SampledAllocation* allocation : samples_) {
v8::AllocationProfile::Node* node =
AddStack(profile, scripts, allocation->get_stack());
node->allocations.push_back({allocation->get_size(), 1});
}
return profile; return profile;
} }
......
...@@ -48,50 +48,50 @@ class SamplingHeapProfiler { ...@@ -48,50 +48,50 @@ class SamplingHeapProfiler {
StringsStorage* names() const { return names_; } StringsStorage* names() const { return names_; }
class AllocationNode; class FunctionInfo {
struct Sample {
public: public:
Sample(size_t size_, AllocationNode* owner_, Local<Value> local_, FunctionInfo(SharedFunctionInfo* shared, StringsStorage* names);
SamplingHeapProfiler* profiler_) explicit FunctionInfo(const char* name)
: size(size_), : name_(name),
owner(owner_), script_name_(""),
global(Global<Value>( script_id_(v8::UnboundScript::kNoScriptId),
reinterpret_cast<v8::Isolate*>(profiler_->isolate_), local_)), start_position_(0) {}
profiler(profiler_) {}
~Sample() { global.Reset(); } const char* get_name() const { return name_; }
const size_t size; const char* get_script_name() const { return script_name_; }
AllocationNode* const owner; int get_script_id() const { return script_id_; }
Global<Value> global; int get_start_position() const { return start_position_; }
SamplingHeapProfiler* const profiler;
private: private:
DISALLOW_COPY_AND_ASSIGN(Sample); const char* const name_;
const char* script_name_;
int script_id_;
const int start_position_;
}; };
class AllocationNode { class SampledAllocation {
public: public:
AllocationNode(const char* const name, int script_id, SampledAllocation(SamplingHeapProfiler* sampling_heap_profiler,
const int start_position) Isolate* isolate, Local<Value> local, size_t size,
: script_id_(script_id), int max_frames);
script_position_(start_position), ~SampledAllocation() {
name_(name) {} for (auto info : stack_) {
~AllocationNode() { delete info;
for (auto child : children_) {
delete child;
} }
global_.Reset(); // drop the reference.
} }
size_t get_size() const { return size_; }
const std::vector<FunctionInfo*>& get_stack() const { return stack_; }
private: private:
std::map<size_t, unsigned int> allocations_; static void OnWeakCallback(const WeakCallbackInfo<SampledAllocation>& data);
std::vector<AllocationNode*> children_;
const int script_id_;
const int script_position_;
const char* const name_;
friend class SamplingHeapProfiler; SamplingHeapProfiler* const sampling_heap_profiler_;
Global<Value> global_;
std::vector<FunctionInfo*> stack_;
const size_t size_;
DISALLOW_COPY_AND_ASSIGN(AllocationNode); DISALLOW_COPY_AND_ASSIGN(SampledAllocation);
}; };
private: private:
...@@ -99,29 +99,23 @@ class SamplingHeapProfiler { ...@@ -99,29 +99,23 @@ class SamplingHeapProfiler {
void SampleObject(Address soon_object, size_t size); void SampleObject(Address soon_object, size_t size);
static void OnWeakCallback(const WeakCallbackInfo<Sample>& data);
// Methods that construct v8::AllocationProfile. // Methods that construct v8::AllocationProfile.
v8::AllocationProfile::Node* AddStack(
// Translates the provided AllocationNode *node* returning an equivalent AllocationProfile* profile, const std::map<int, Script*>& scripts,
// AllocationProfile::Node. The newly created AllocationProfile::Node is added const std::vector<FunctionInfo*>& stack);
// to the provided AllocationProfile *profile*. Line numbers, column numbers, v8::AllocationProfile::Node* FindOrAddChildNode(
// and script names are resolved using *scripts* which maps all currently AllocationProfile* profile, const std::map<int, Script*>& scripts,
// loaded scripts keyed by their script id. v8::AllocationProfile::Node* parent, FunctionInfo* function_info);
v8::AllocationProfile::Node* TranslateAllocationNode( v8::AllocationProfile::Node* AllocateNode(
AllocationProfile* profile, SamplingHeapProfiler::AllocationNode* node, AllocationProfile* profile, const std::map<int, Script*>& scripts,
const std::map<int, Script*>& scripts); FunctionInfo* function_info);
AllocationNode* AddStack();
AllocationNode* FindOrAddChildNode(AllocationNode* parent, const char* name,
int script_id, int start_position);
Isolate* const isolate_; Isolate* const isolate_;
Heap* const heap_; Heap* const heap_;
base::SmartPointer<SamplingAllocationObserver> new_space_observer_; base::SmartPointer<SamplingAllocationObserver> new_space_observer_;
base::SmartPointer<SamplingAllocationObserver> other_spaces_observer_; base::SmartPointer<SamplingAllocationObserver> other_spaces_observer_;
StringsStorage* const names_; StringsStorage* const names_;
AllocationNode profile_root_; std::set<SampledAllocation*> samples_;
std::set<Sample*> samples_;
const int stack_depth_; const int stack_depth_;
friend class SamplingAllocationObserver; friend class SamplingAllocationObserver;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment