Chromium Code Reviews| Index: runtime/vm/profiler_service.cc |
| diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc |
| index e750b2c573ed036de4a197b2490653a12a83d956..939ecdeb0851f9f8046a68efb68730898b1f6a9e 100644 |
| --- a/runtime/vm/profiler_service.cc |
| +++ b/runtime/vm/profiler_service.cc |
| @@ -146,9 +146,11 @@ bool ProfileFunction::is_visible() const { |
| void ProfileFunction::Tick(bool exclusive, |
| intptr_t inclusive_serial, |
| - TokenPosition token_position) { |
| + TokenPosition token_position, |
| + ProcessedSample* sample) { |
| if (exclusive) { |
| exclusive_ticks_++; |
| + AccumulateAllocation(sample->native_allocation_size_bytes(), true); |
| TickSourcePosition(token_position, exclusive); |
| } |
| // Fall through and tick inclusive count too. |
| @@ -158,6 +160,7 @@ void ProfileFunction::Tick(bool exclusive, |
| } |
| inclusive_serial_ = inclusive_serial; |
| inclusive_ticks_++; |
| + AccumulateAllocation(sample->native_allocation_size_bytes(), false); |
| TickSourcePosition(token_position, false); |
| } |
| @@ -199,6 +202,42 @@ void ProfileFunction::TickSourcePosition(TokenPosition token_position, |
| } |
| +static intptr_t SumAllocations(const AllocationHashMap& map) { |
| + uintptr_t sum = 0; |
| + AllocationHashMap::Iterator iter = map.GetIterator(); |
| + AllocationKeyValueTrait::Pair* pair = iter.Next(); |
| + |
| + while (pair != NULL) { |
| + sum += pair->value * pair->key; |
| + pair = iter.Next(); |
| + } |
| + |
| + return sum; |
| +} |
| + |
| + |
| +static void AccumulateAllocationHelper(AllocationHashMap* map, |
|
Cutch
2017/03/16 20:38:16
I don't see why this code is necessary?
bkonyi
2017/03/16 20:48:40
So, currently, I'm tracking the inclusive/exclusiv
bkonyi
2017/03/21 01:53:23
Removed.
|
| + intptr_t allocation_size) { |
| + ASSERT(map != NULL); |
| + AllocationKeyValueTrait::Pair* allocation = map->Lookup(allocation_size); |
| + if (allocation == NULL) { |
| + map->Insert(AllocationKeyValueTrait::Pair(allocation_size, 1)); |
| + return; |
| + } |
| + ++allocation->value; |
| +} |
| + |
| + |
| +void ProfileFunction::AccumulateAllocation(intptr_t allocation_size, |
| + bool exclusive) { |
| + if (exclusive) { |
| + AccumulateAllocationHelper(&exclusive_native_allocations_, allocation_size); |
| + } else { |
| + AccumulateAllocationHelper(&inclusive_native_allocations_, allocation_size); |
| + } |
| +} |
| + |
| + |
| const char* ProfileFunction::KindToCString(Kind kind) { |
| switch (kind) { |
| case kDartFunction: |
| @@ -230,6 +269,12 @@ void ProfileFunction::PrintToJSONArray(JSONArray* functions) { |
| obj.AddProperty("kind", KindToCString(kind())); |
| obj.AddPropertyF("inclusiveTicks", "%" Pd "", inclusive_ticks()); |
| obj.AddPropertyF("exclusiveTicks", "%" Pd "", exclusive_ticks()); |
| + |
| + obj.AddPropertyF("inclusiveNativeAllocations", "%" Pd "", |
| + SumAllocations(inclusive_native_allocations_)); |
| + obj.AddPropertyF("exclusiveNativeAllocations", "%" Pd "", |
| + SumAllocations(exclusive_native_allocations_)); |
| + |
| if (kind() == kDartFunction) { |
| ASSERT(!function_.IsNull()); |
| obj.AddProperty("function", function_); |
| @@ -344,10 +389,14 @@ void ProfileCode::GenerateAndSetSymbolName(const char* prefix) { |
| } |
| -void ProfileCode::Tick(uword pc, bool exclusive, intptr_t serial) { |
| +void ProfileCode::Tick(uword pc, |
| + bool exclusive, |
| + intptr_t serial, |
| + ProcessedSample* sample) { |
| // If exclusive is set, tick it. |
| if (exclusive) { |
| exclusive_ticks_++; |
| + AccumulateAllocation(sample->native_allocation_size_bytes(), true); |
| TickAddress(pc, true); |
| } |
| // Fall through and tick inclusive count too. |
| @@ -355,6 +404,9 @@ void ProfileCode::Tick(uword pc, bool exclusive, intptr_t serial) { |
| // Already gave inclusive tick for this sample. |
| return; |
| } |
| + |
| + AccumulateAllocation(sample->native_allocation_size_bytes(), false); |
| + |
| inclusive_serial_ = serial; |
| inclusive_ticks_++; |
| TickAddress(pc, false); |
| @@ -392,6 +444,16 @@ void ProfileCode::TickAddress(uword pc, bool exclusive) { |
| } |
| +void ProfileCode::AccumulateAllocation(intptr_t allocation_size, |
| + bool exclusive) { |
| + if (exclusive) { |
| + AccumulateAllocationHelper(&exclusive_native_allocations_, allocation_size); |
| + } else { |
| + AccumulateAllocationHelper(&inclusive_native_allocations_, allocation_size); |
| + } |
| +} |
| + |
| + |
| void ProfileCode::PrintNativeCode(JSONObject* profile_code_obj) { |
| ASSERT(kind() == kNativeCode); |
| JSONObject obj(profile_code_obj, "code"); |
| @@ -487,6 +549,10 @@ void ProfileCode::PrintToJSONArray(JSONArray* codes) { |
| obj.AddProperty("kind", ProfileCode::KindToCString(kind())); |
| obj.AddPropertyF("inclusiveTicks", "%" Pd "", inclusive_ticks()); |
| obj.AddPropertyF("exclusiveTicks", "%" Pd "", exclusive_ticks()); |
| + obj.AddPropertyF("inclusiveNativeAllocations", "%" Pd "", |
| + SumAllocations(inclusive_native_allocations_)); |
| + obj.AddPropertyF("exclusiveNativeAllocations", "%" Pd "", |
| + SumAllocations(exclusive_native_allocations_)); |
| if (kind() == kDartCode) { |
| ASSERT(!code_.IsNull()); |
| obj.AddProperty("code", code_); |
| @@ -863,7 +929,12 @@ class ProfileCodeTable : public ZoneAllocated { |
| ProfileTrieNode::ProfileTrieNode(intptr_t table_index) |
| - : table_index_(table_index), count_(0), children_(0), frame_id_(-1) { |
| + : table_index_(table_index), |
| + count_(0), |
| + exclusive_allocations_(0), |
| + inclusive_allocations_(0), |
| + children_(0), |
| + frame_id_(-1) { |
| ASSERT(table_index_ >= 0); |
| } |
| @@ -904,6 +975,10 @@ class ProfileCodeTrieNode : public ProfileTrieNode { |
| // Write number of children. |
| intptr_t child_count = NumChildren(); |
| array->AddValue(child_count); |
| + // Write inclusive allocations. |
| + array->AddValue64(inclusive_allocations_); |
| + // Write exclusive allocations. |
| + array->AddValue64(exclusive_allocations_); |
| // Recurse. |
| for (intptr_t i = 0; i < child_count; i++) { |
| children_[i]->PrintToJSONArray(array); |
| @@ -965,6 +1040,10 @@ class ProfileFunctionTrieNode : public ProfileTrieNode { |
| array->AddValue(table_index()); |
| // Write count. |
| array->AddValue(count()); |
| + // Write inclusive allocations. |
| + array->AddValue64(inclusive_allocations_); |
| + // Write exclusive allocations. |
| + array->AddValue64(exclusive_allocations_); |
| // Write number of code objects. |
| intptr_t code_count = code_objects_.length(); |
| array->AddValue(code_count); |
| @@ -1320,10 +1399,11 @@ class ProfileBuilder : public ValueObject { |
| ASSERT(pc != 0); |
| ProfileCode* code = FindOrRegisterProfileCode(pc, timestamp); |
| ASSERT(code != NULL); |
| - code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index); |
| + code->Tick(pc, IsExecutingFrame(sample, frame_index), sample_index, |
| + sample); |
| } |
| - TickExitFrame(sample->vm_tag(), sample_index); |
| + TickExitFrame(sample->vm_tag(), sample_index, sample); |
| } |
| SanitizeMinMaxTimes(); |
| } |
| @@ -1410,15 +1490,18 @@ class ProfileBuilder : public ValueObject { |
| // Tick the root. |
| ProfileCodeTrieNode* current = root; |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
|
Cutch
2017/03/16 20:38:16
Refactor this so it follows the pattern you set el
bkonyi
2017/03/21 01:53:24
Done.
|
| + false); |
| // VM & User tags. |
| - current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
| + current = |
| + AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); |
| ResetKind(); |
| // Truncated tag. |
| if (sample->truncated()) { |
| - current = AppendTruncatedTag(current); |
| + current = AppendTruncatedTag(current, sample); |
| } |
| // Walk the sampled PCs. |
| @@ -1433,13 +1516,15 @@ class ProfileBuilder : public ValueObject { |
| GetProfileCode(sample->At(frame_index), sample->timestamp()); |
| ASSERT(profile_code->code_table_index() == index); |
| code ^= profile_code->code(); |
| - current = AppendKind(code, current); |
| + current = AppendKind(code, current, sample); |
| current = current->GetChild(index); |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
|
Cutch
2017/03/16 20:38:16
ditto
bkonyi
2017/03/21 01:53:23
Done.
|
| + (frame_index == 0)); |
| } |
| if (!sample->first_frame_executing()) { |
| - current = AppendExitFrame(sample->vm_tag(), current); |
| + current = AppendExitFrame(sample->vm_tag(), current, sample); |
| } |
| } |
| } |
| @@ -1454,14 +1539,16 @@ class ProfileBuilder : public ValueObject { |
| // Tick the root. |
| ProfileCodeTrieNode* current = root; |
| current->Tick(); |
| - |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
|
Cutch
2017/03/16 20:38:16
ditto
bkonyi
2017/03/21 01:53:23
Done.
|
| + false); |
| // VM & User tags. |
| - current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
| + current = |
| + AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); |
| ResetKind(); |
| if (!sample->first_frame_executing()) { |
| - current = AppendExitFrame(sample->vm_tag(), current); |
| + current = AppendExitFrame(sample->vm_tag(), current, sample); |
| } |
| // Walk the sampled PCs. |
| @@ -1479,12 +1566,14 @@ class ProfileBuilder : public ValueObject { |
| current = current->GetChild(index); |
| if (ShouldTickNode(sample, frame_index)) { |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
|
Cutch
2017/03/16 20:38:16
ditto
bkonyi
2017/03/21 01:53:24
Done.
|
| + (frame_index == 0)); |
| } |
| - current = AppendKind(code, current); |
| + current = AppendKind(code, current, sample); |
| } |
| // Truncated tag. |
| if (sample->truncated()) { |
| - current = AppendTruncatedTag(current); |
| + current = AppendTruncatedTag(current, sample); |
| } |
| } |
| } |
| @@ -1516,13 +1605,15 @@ class ProfileBuilder : public ValueObject { |
| // Tick the root. |
| ProfileFunctionTrieNode* current = root; |
| current->Tick(); |
| - |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
| + false); |
| // VM & User tags. |
| - current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
| + current = |
| + AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); |
| // Truncated tag. |
| if (sample->truncated()) { |
| - current = AppendTruncatedTag(current); |
| + current = AppendTruncatedTag(current, sample); |
| } |
| // Walk the sampled PCs. |
| @@ -1533,7 +1624,7 @@ class ProfileBuilder : public ValueObject { |
| } |
| if (!sample->first_frame_executing()) { |
| - current = AppendExitFrame(sample->vm_tag(), current); |
| + current = AppendExitFrame(sample->vm_tag(), current, sample); |
| } |
| sample->set_timeline_trie(current); |
| @@ -1551,14 +1642,16 @@ class ProfileBuilder : public ValueObject { |
| // Tick the root. |
| ProfileFunctionTrieNode* current = root; |
| current->Tick(); |
| - |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
| + false); |
| // VM & User tags. |
| - current = AppendTags(sample->vm_tag(), sample->user_tag(), current); |
| + current = |
| + AppendTags(sample->vm_tag(), sample->user_tag(), current, sample); |
| ResetKind(); |
| if (!sample->first_frame_executing()) { |
| - current = AppendExitFrame(sample->vm_tag(), current); |
| + current = AppendExitFrame(sample->vm_tag(), current, sample); |
| } |
| // Walk the sampled PCs. |
| @@ -1568,12 +1661,12 @@ class ProfileBuilder : public ValueObject { |
| current = ProcessFrame(current, sample_index, sample, frame_index); |
| } |
| - TickExitFrameFunction(sample->vm_tag(), sample_index); |
| + TickExitFrameFunction(sample->vm_tag(), sample_index, sample); |
| // Truncated tag. |
| if (sample->truncated()) { |
| - current = AppendTruncatedTag(current); |
| - InclusiveTickTruncatedTag(); |
| + current = AppendTruncatedTag(current, sample); |
| + InclusiveTickTruncatedTag(sample); |
| } |
| } |
| } |
| @@ -1611,16 +1704,17 @@ class ProfileBuilder : public ValueObject { |
| (inlined_functions->length() <= 1)) { |
| // No inlined functions. |
| if (inclusive_tree_) { |
| - current = AppendKind(code, current); |
| + current = AppendKind(code, current, sample); |
| } |
| current = ProcessFunction(current, sample_index, sample, frame_index, |
| function, token_position, code_index); |
| if (!inclusive_tree_) { |
| - current = AppendKind(code, current); |
| + current = AppendKind(code, current, sample); |
| } |
| return current; |
| } |
| + // TODO(bkonyi) deal with this |
|
bkonyi
2017/03/16 19:50:57
What needs to be done here again John?
Cutch
2017/03/16 20:38:16
You should figure out why the assumption that the
bkonyi
2017/03/21 01:53:24
Acknowledged.
|
| ASSERT(code.is_optimized()); |
| if (inclusive_tree_) { |
| @@ -1631,19 +1725,19 @@ class ProfileBuilder : public ValueObject { |
| TokenPosition inlined_token_position = (*inlined_token_positions)[i]; |
| const bool inliner = i == 0; |
| if (inliner) { |
| - current = AppendKind(code, current); |
| + current = AppendKind(code, current, sample); |
| } |
| current = ProcessInlinedFunction(current, sample_index, sample, |
| frame_index, inlined_function, |
| inlined_token_position, code_index); |
| if (inliner) { |
| - current = AppendKind(kInlineStart, current); |
| + current = AppendKind(kInlineStart, current, sample); |
| } |
| } |
| - current = AppendKind(kInlineFinish, current); |
| + current = AppendKind(kInlineFinish, current, sample); |
| } else { |
| // Append the inlined children. |
| - current = AppendKind(kInlineFinish, current); |
| + current = AppendKind(kInlineFinish, current, sample); |
| for (intptr_t i = inlined_functions->length() - 1; i >= 0; i--) { |
| const Function* inlined_function = (*inlined_functions)[i]; |
| ASSERT(inlined_function != NULL); |
| @@ -1651,13 +1745,13 @@ class ProfileBuilder : public ValueObject { |
| TokenPosition inlined_token_position = (*inlined_token_positions)[i]; |
| const bool inliner = i == 0; |
| if (inliner) { |
| - current = AppendKind(kInlineStart, current); |
| + current = AppendKind(kInlineStart, current, sample); |
| } |
| current = ProcessInlinedFunction(current, sample_index, sample, |
| frame_index + i, inlined_function, |
| inlined_token_position, code_index); |
| if (inliner) { |
| - current = AppendKind(code, current); |
| + current = AppendKind(code, current, sample); |
| } |
| } |
| } |
| @@ -1707,19 +1801,21 @@ class ProfileBuilder : public ValueObject { |
| sample->At(frame_index)); |
| } |
| function->Tick(IsExecutingFrame(sample, frame_index), sample_index, |
| - token_position); |
| + token_position, sample); |
| } |
| function->AddProfileCode(code_index); |
| current = current->GetChild(function->table_index()); |
| if (ShouldTickNode(sample, frame_index)) { |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
| + (frame_index == 0)); |
| } |
| current->AddCodeObjectIndex(code_index); |
| return current; |
| } |
| // Tick the truncated tag's inclusive tick count. |
| - void InclusiveTickTruncatedTag() { |
| + void InclusiveTickTruncatedTag(ProcessedSample* sample) { |
| ProfileCodeTable* tag_table = profile_->tag_code_; |
| intptr_t index = tag_table->FindCodeIndexForPC(VMTag::kTruncatedTagId); |
| ASSERT(index >= 0); |
| @@ -1728,6 +1824,10 @@ class ProfileBuilder : public ValueObject { |
| ASSERT(code != NULL); |
| ProfileFunction* function = code->function(); |
| function->IncInclusiveTicks(); |
| + |
| + code->AccumulateAllocation(sample->native_allocation_size_bytes(), false); |
| + function->AccumulateAllocation(sample->native_allocation_size_bytes(), |
| + false); |
| } |
| @@ -1736,25 +1836,32 @@ class ProfileBuilder : public ValueObject { |
| // ProfileCodeTrieNode |
| ProfileCodeTrieNode* AppendUserTag(uword user_tag, |
| - ProfileCodeTrieNode* current) { |
| + ProfileCodeTrieNode* current, |
| + ProcessedSample* sample) { |
| intptr_t user_tag_index = GetProfileCodeTagIndex(user_tag); |
| if (user_tag_index >= 0) { |
| current = current->GetChild(user_tag_index); |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
| + false); |
| } |
| return current; |
| } |
| - ProfileCodeTrieNode* AppendTruncatedTag(ProfileCodeTrieNode* current) { |
| + ProfileCodeTrieNode* AppendTruncatedTag(ProfileCodeTrieNode* current, |
| + ProcessedSample* sample) { |
| intptr_t truncated_tag_index = |
| GetProfileCodeTagIndex(VMTag::kTruncatedTagId); |
| ASSERT(truncated_tag_index >= 0); |
| current = current->GetChild(truncated_tag_index); |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), false); |
| return current; |
| } |
| - ProfileCodeTrieNode* AppendVMTag(uword vm_tag, ProfileCodeTrieNode* current) { |
| + ProfileCodeTrieNode* AppendVMTag(uword vm_tag, |
| + ProfileCodeTrieNode* current, |
| + ProcessedSample* sample) { |
| if (VMTag::IsNativeEntryTag(vm_tag)) { |
| // Insert a dummy kNativeTagId node. |
| intptr_t tag_index = GetProfileCodeTagIndex(VMTag::kNativeTagId); |
| @@ -1773,12 +1880,14 @@ class ProfileBuilder : public ValueObject { |
| // Give the tag a tick. |
| current->Tick(); |
| } |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), false); |
| return current; |
| } |
| ProfileCodeTrieNode* AppendSpecificNativeRuntimeEntryVMTag( |
| uword vm_tag, |
| - ProfileCodeTrieNode* current) { |
| + ProfileCodeTrieNode* current, |
| + ProcessedSample* sample) { |
| // Only Native and Runtime entries have a second VM tag. |
| if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) { |
| return current; |
| @@ -1787,6 +1896,7 @@ class ProfileBuilder : public ValueObject { |
| current = current->GetChild(tag_index); |
| // Give the tag a tick. |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), false); |
| return current; |
| } |
| @@ -1811,7 +1921,8 @@ class ProfileBuilder : public ValueObject { |
| } |
| ProfileCodeTrieNode* AppendKind(ProfileInfoKind kind, |
| - ProfileCodeTrieNode* current) { |
| + ProfileCodeTrieNode* current, |
| + ProcessedSample* sample) { |
| if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { |
| // Only emit if debug tags are requested. |
| return current; |
| @@ -1822,29 +1933,33 @@ class ProfileBuilder : public ValueObject { |
| ASSERT(tag_index >= 0); |
| current = current->GetChild(tag_index); |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
| + false); |
| } |
| return current; |
| } |
| ProfileCodeTrieNode* AppendKind(const Code& code, |
| - ProfileCodeTrieNode* current) { |
| + ProfileCodeTrieNode* current, |
| + ProcessedSample* sample) { |
| if (code.IsNull()) { |
| - return AppendKind(kNone, current); |
| + return AppendKind(kNone, current, sample); |
| } else if (code.is_optimized()) { |
| - return AppendKind(kOptimized, current); |
| + return AppendKind(kOptimized, current, sample); |
| } else { |
| - return AppendKind(kUnoptimized, current); |
| + return AppendKind(kUnoptimized, current, sample); |
| } |
| } |
| ProfileCodeTrieNode* AppendVMTags(uword vm_tag, |
| - ProfileCodeTrieNode* current) { |
| - current = AppendVMTag(vm_tag, current); |
| - current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); |
| + ProfileCodeTrieNode* current, |
| + ProcessedSample* sample) { |
| + current = AppendVMTag(vm_tag, current, sample); |
| + current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); |
| return current; |
| } |
| - void TickExitFrame(uword vm_tag, intptr_t serial) { |
| + void TickExitFrame(uword vm_tag, intptr_t serial, ProcessedSample* sample) { |
| if (FLAG_profile_vm) { |
| return; |
| } |
| @@ -1854,10 +1969,12 @@ class ProfileBuilder : public ValueObject { |
| ProfileCodeTable* tag_table = profile_->tag_code_; |
| ProfileCode* code = tag_table->FindCodeForPC(vm_tag); |
| ASSERT(code != NULL); |
| - code->Tick(vm_tag, true, serial); |
| + code->Tick(vm_tag, true, serial, sample); |
| } |
| - void TickExitFrameFunction(uword vm_tag, intptr_t serial) { |
| + void TickExitFrameFunction(uword vm_tag, |
| + intptr_t serial, |
| + ProcessedSample* sample) { |
| if (FLAG_profile_vm) { |
| return; |
| } |
| @@ -1869,11 +1986,12 @@ class ProfileBuilder : public ValueObject { |
| ASSERT(code != NULL); |
| ProfileFunction* function = code->function(); |
| ASSERT(function != NULL); |
| - function->Tick(true, serial, TokenPosition::kNoSource); |
| + function->Tick(true, serial, TokenPosition::kNoSource, sample); |
| } |
| ProfileCodeTrieNode* AppendExitFrame(uword vm_tag, |
| - ProfileCodeTrieNode* current) { |
| + ProfileCodeTrieNode* current, |
| + ProcessedSample* sample) { |
| if (FLAG_profile_vm) { |
| return current; |
| } |
| @@ -1883,19 +2001,22 @@ class ProfileBuilder : public ValueObject { |
| } |
| if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) { |
| - current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); |
| + current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); |
| } else { |
| intptr_t tag_index = GetProfileCodeTagIndex(vm_tag); |
| current = current->GetChild(tag_index); |
| // Give the tag a tick. |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
| + false); |
| } |
| return current; |
| } |
| ProfileCodeTrieNode* AppendTags(uword vm_tag, |
| uword user_tag, |
| - ProfileCodeTrieNode* current) { |
| + ProfileCodeTrieNode* current, |
| + ProcessedSample* sample) { |
| if (FLAG_profile_vm) { |
| // None. |
| if (tag_order() == Profile::kNoTags) { |
| @@ -1904,36 +2025,37 @@ class ProfileBuilder : public ValueObject { |
| // User first. |
| if ((tag_order() == Profile::kUserVM) || |
| (tag_order() == Profile::kUser)) { |
| - current = AppendUserTag(user_tag, current); |
| + current = AppendUserTag(user_tag, current, sample); |
| // Only user. |
| if (tag_order() == Profile::kUser) { |
| return current; |
| } |
| - return AppendVMTags(vm_tag, current); |
| + return AppendVMTags(vm_tag, current, sample); |
| } |
| // VM first. |
| ASSERT((tag_order() == Profile::kVMUser) || |
| (tag_order() == Profile::kVM)); |
| - current = AppendVMTags(vm_tag, current); |
| + current = AppendVMTags(vm_tag, current, sample); |
| // Only VM. |
| if (tag_order() == Profile::kVM) { |
| return current; |
| } |
| - return AppendUserTag(user_tag, current); |
| + return AppendUserTag(user_tag, current, sample); |
| } |
| if (tag_order() == Profile::kNoTags) { |
| return current; |
| } |
| - return AppendUserTag(user_tag, current); |
| + return AppendUserTag(user_tag, current, sample); |
| } |
| // ProfileFunctionTrieNode |
| void ResetKind() { info_kind_ = kNone; } |
| ProfileFunctionTrieNode* AppendKind(ProfileInfoKind kind, |
| - ProfileFunctionTrieNode* current) { |
| + ProfileFunctionTrieNode* current, |
| + ProcessedSample* sample) { |
| if (!TagsEnabled(ProfilerService::kCodeTransitionTagsBit)) { |
| // Only emit if debug tags are requested. |
| return current; |
| @@ -1945,43 +2067,51 @@ class ProfileBuilder : public ValueObject { |
| ASSERT(tag_index >= 0); |
| current = current->GetChild(tag_index); |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
| + false); |
| } |
| return current; |
| } |
| ProfileFunctionTrieNode* AppendKind(const Code& code, |
| - ProfileFunctionTrieNode* current) { |
| + ProfileFunctionTrieNode* current, |
| + ProcessedSample* sample) { |
| if (code.IsNull()) { |
| - return AppendKind(kNone, current); |
| + return AppendKind(kNone, current, sample); |
| } else if (code.is_optimized()) { |
| - return AppendKind(kOptimized, current); |
| + return AppendKind(kOptimized, current, sample); |
| } else { |
| - return AppendKind(kUnoptimized, current); |
| + return AppendKind(kUnoptimized, current, sample); |
| } |
| } |
| ProfileFunctionTrieNode* AppendUserTag(uword user_tag, |
| - ProfileFunctionTrieNode* current) { |
| + ProfileFunctionTrieNode* current, |
| + ProcessedSample* sample) { |
| intptr_t user_tag_index = GetProfileFunctionTagIndex(user_tag); |
| if (user_tag_index >= 0) { |
| current = current->GetChild(user_tag_index); |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
| + false); |
| } |
| return current; |
| } |
| - ProfileFunctionTrieNode* AppendTruncatedTag( |
| - ProfileFunctionTrieNode* current) { |
| + ProfileFunctionTrieNode* AppendTruncatedTag(ProfileFunctionTrieNode* current, |
| + ProcessedSample* sample) { |
| intptr_t truncated_tag_index = |
| GetProfileFunctionTagIndex(VMTag::kTruncatedTagId); |
| ASSERT(truncated_tag_index >= 0); |
| current = current->GetChild(truncated_tag_index); |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), false); |
| return current; |
| } |
| ProfileFunctionTrieNode* AppendVMTag(uword vm_tag, |
| - ProfileFunctionTrieNode* current) { |
| + ProfileFunctionTrieNode* current, |
| + ProcessedSample* sample) { |
| if (VMTag::IsNativeEntryTag(vm_tag)) { |
| // Insert a dummy kNativeTagId node. |
| intptr_t tag_index = GetProfileFunctionTagIndex(VMTag::kNativeTagId); |
| @@ -2000,12 +2130,14 @@ class ProfileBuilder : public ValueObject { |
| // Give the tag a tick. |
| current->Tick(); |
| } |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), false); |
| return current; |
| } |
| ProfileFunctionTrieNode* AppendSpecificNativeRuntimeEntryVMTag( |
| uword vm_tag, |
| - ProfileFunctionTrieNode* current) { |
| + ProfileFunctionTrieNode* current, |
| + ProcessedSample* sample) { |
| // Only Native and Runtime entries have a second VM tag. |
| if (!VMTag::IsNativeEntryTag(vm_tag) && !VMTag::IsRuntimeEntryTag(vm_tag)) { |
| return current; |
| @@ -2014,18 +2146,21 @@ class ProfileBuilder : public ValueObject { |
| current = current->GetChild(tag_index); |
| // Give the tag a tick. |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), false); |
| return current; |
| } |
| ProfileFunctionTrieNode* AppendVMTags(uword vm_tag, |
| - ProfileFunctionTrieNode* current) { |
| - current = AppendVMTag(vm_tag, current); |
| - current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); |
| + ProfileFunctionTrieNode* current, |
| + ProcessedSample* sample) { |
| + current = AppendVMTag(vm_tag, current, sample); |
| + current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); |
| return current; |
| } |
| ProfileFunctionTrieNode* AppendExitFrame(uword vm_tag, |
| - ProfileFunctionTrieNode* current) { |
| + ProfileFunctionTrieNode* current, |
| + ProcessedSample* sample) { |
| if (FLAG_profile_vm) { |
| return current; |
| } |
| @@ -2034,19 +2169,22 @@ class ProfileBuilder : public ValueObject { |
| return current; |
| } |
| if (VMTag::IsNativeEntryTag(vm_tag) || VMTag::IsRuntimeEntryTag(vm_tag)) { |
| - current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current); |
| + current = AppendSpecificNativeRuntimeEntryVMTag(vm_tag, current, sample); |
| } else { |
| intptr_t tag_index = GetProfileFunctionTagIndex(vm_tag); |
| current = current->GetChild(tag_index); |
| // Give the tag a tick. |
| current->Tick(); |
| + current->IncrementAllocation(sample->native_allocation_size_bytes(), |
| + false); |
| } |
| return current; |
| } |
| ProfileFunctionTrieNode* AppendTags(uword vm_tag, |
| uword user_tag, |
| - ProfileFunctionTrieNode* current) { |
| + ProfileFunctionTrieNode* current, |
| + ProcessedSample* sample) { |
| if (FLAG_profile_vm) { |
| // None. |
| if (tag_order() == Profile::kNoTags) { |
| @@ -2055,29 +2193,29 @@ class ProfileBuilder : public ValueObject { |
| // User first. |
| if ((tag_order() == Profile::kUserVM) || |
| (tag_order() == Profile::kUser)) { |
| - current = AppendUserTag(user_tag, current); |
| + current = AppendUserTag(user_tag, current, sample); |
| // Only user. |
| if (tag_order() == Profile::kUser) { |
| return current; |
| } |
| - return AppendVMTags(vm_tag, current); |
| + return AppendVMTags(vm_tag, current, sample); |
| } |
| // VM first. |
| ASSERT((tag_order() == Profile::kVMUser) || |
| (tag_order() == Profile::kVM)); |
| - current = AppendVMTags(vm_tag, current); |
| + current = AppendVMTags(vm_tag, current, sample); |
| // Only VM. |
| if (tag_order() == Profile::kVM) { |
| return current; |
| } |
| - return AppendUserTag(user_tag, current); |
| + return AppendUserTag(user_tag, current, sample); |
| } |
| if (tag_order() == Profile::kNoTags) { |
| return current; |
| } |
| - return AppendUserTag(user_tag, current); |
| + return AppendUserTag(user_tag, current, sample); |
| } |
| intptr_t GetProfileCodeTagIndex(uword tag) { |
| @@ -2727,15 +2865,15 @@ class ClassAllocationSampleFilter : public SampleFilter { |
| class NativeAllocationSampleFilter : public SampleFilter { |
| public: |
| - NativeAllocationSampleFilter(intptr_t thread_task_mask, |
| - int64_t time_origin_micros, |
| + NativeAllocationSampleFilter(int64_t time_origin_micros, |
| int64_t time_extent_micros) |
| : SampleFilter(ILLEGAL_PORT, |
| - thread_task_mask, |
| + SampleFilter::kNoTaskFilter, |
| time_origin_micros, |
| time_extent_micros) {} |
| bool FilterSample(Sample* sample) { |
| - return sample->is_native_allocation_sample(); |
| + return sample->is_native_allocation_sample() && |
| + !sample->NativeAllocationFreed(); |
| } |
| }; |
| @@ -2760,11 +2898,7 @@ void ProfilerService::PrintNativeAllocationJSON(JSONStream* stream, |
| int64_t time_origin_micros, |
| int64_t time_extent_micros) { |
| Thread* thread = Thread::Current(); |
| - const intptr_t thread_task_mask = Thread::kMutatorTask | |
| - Thread::kCompilerTask | |
| - Thread::kSweeperTask | Thread::kMarkerTask; |
| - NativeAllocationSampleFilter filter(thread_task_mask, time_origin_micros, |
| - time_extent_micros); |
| + NativeAllocationSampleFilter filter(time_origin_micros, time_extent_micros); |
| const bool as_timeline = false; |
| PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter, as_timeline); |
| } |