Chromium Code Reviews| Index: runtime/vm/profiler_service.cc |
| diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc |
| index f245ed5f29657d2f5ac8d176c217fdc1f26b4ba9..b89ca0a4549b0eab428e230965ab8c7aa3be26d9 100644 |
| --- a/runtime/vm/profiler_service.cc |
| +++ b/runtime/vm/profiler_service.cc |
| @@ -302,10 +302,31 @@ ProfileCode::ProfileCode(Kind kind, |
| address_ticks_(0) {} |
| -void ProfileCode::AdjustExtent(uword start, uword end) { |
| +void ProfileCode::TruncateLower(uword start) { |
| + if (start > start_) { |
| + start_ = start; |
| + } |
| + ASSERT(start_ < end_); |
| +} |
| + |
| + |
| +void ProfileCode::TruncateUpper(uword end) { |
| + if (end < end_) { |
| + end_ = end; |
| + } |
| + ASSERT(start_ < end_); |
| +} |
| + |
| + |
| +void ProfileCode::ExpandLower(uword start) { |
| if (start < start_) { |
| start_ = start; |
| } |
| + ASSERT(start_ < end_); |
| +} |
| + |
| + |
| +void ProfileCode::ExpandUpper(uword end) { |
| if (end > end_) { |
| end_ = end; |
| } |
| @@ -712,18 +733,26 @@ class ProfileCodeTable : public ZoneAllocated { |
| // Find the table index to the ProfileCode containing pc. |
| // Returns < 0 if not found. |
| intptr_t FindCodeIndexForPC(uword pc) const { |
| - intptr_t index = FindCodeIndex(pc, &CompareLowerBound); |
| - if (index == length()) { |
| - // Not present. |
| - return -1; |
| - } |
| - const ProfileCode* code = At(index); |
| - if (!code->Contains(pc)) { |
| - // Not present. |
| - return -1; |
| + intptr_t length = table_.length(); |
| + if (length == 0) { |
| + return -1; // No found. |
|
zra
2017/06/14 05:00:05
Not
rmacnak
2017/06/14 17:32:14
Done.
|
| + } |
| + intptr_t lo = 0; |
| + intptr_t hi = length - 1; |
| + while (lo <= hi) { |
| + intptr_t mid = (hi - lo + 1) / 2 + lo; |
| + ASSERT(mid >= lo); |
| + ASSERT(mid <= hi); |
| + ProfileCode* code = At(mid); |
| + if (code->Contains(pc)) { |
| + return mid; |
| + } else if (pc < code->start()) { |
| + hi = mid - 1; |
| + } else { |
| + lo = mid + 1; |
| + } |
| } |
| - // Found at index. |
| - return index; |
| + return -1; |
| } |
| ProfileCode* FindCodeForPC(uword pc) const { |
| @@ -737,101 +766,111 @@ class ProfileCodeTable : public ZoneAllocated { |
| // Insert |new_code| into the table. Returns the table index where |new_code| |
| // was inserted. Will merge with an overlapping ProfileCode if one is present. |
| intptr_t InsertCode(ProfileCode* new_code) { |
| - const uword start = new_code->start(); |
| - const uword end = new_code->end(); |
| const intptr_t length = table_.length(); |
| if (length == 0) { |
| table_.Add(new_code); |
| return length; |
| } |
| + |
| // Determine the correct place to insert or merge |new_code| into table. |
| - intptr_t lo = FindCodeIndex(start, &CompareLowerBound); |
| - intptr_t hi = FindCodeIndex(end - 1, &CompareUpperBound); |
| - // TODO(johnmccutchan): Simplify below logic. |
| - if ((lo == length) && (hi == length)) { |
| - lo = length - 1; |
| - } |
| - if (lo == length) { |
| - ProfileCode* code = At(hi); |
| - if (code->Overlaps(new_code)) { |
| - HandleOverlap(code, new_code, start, end); |
| - return hi; |
| - } |
| - table_.Add(new_code); |
| - return length; |
| - } else if (hi == length) { |
| - ProfileCode* code = At(lo); |
| - if (code->Overlaps(new_code)) { |
| - HandleOverlap(code, new_code, start, end); |
| - return lo; |
| - } |
| - table_.Add(new_code); |
| - return length; |
| - } else if (lo == hi) { |
| - ProfileCode* code = At(lo); |
| - if (code->Overlaps(new_code)) { |
| - HandleOverlap(code, new_code, start, end); |
| - return lo; |
| - } |
| - table_.InsertAt(lo, new_code); |
| + intptr_t lo = -1; |
| + intptr_t hi = -1; |
| + ProfileCode* lo_code = NULL; |
| + ProfileCode* hi_code = NULL; |
| + const uword pc = new_code->end() - 1; |
| + FindNeighbors(pc, &lo, &hi, &lo_code, &hi_code); |
| + ASSERT((lo_code != NULL) || (hi_code != NULL)); |
| + |
| + if (lo != -1) { |
| + // Has left neighbor. |
| + new_code->TruncateLower(lo_code->end()); |
| + ASSERT(!new_code->Overlaps(lo_code)); |
| + } |
| + if (hi != -1) { |
| + // Has right neighbor. |
| + new_code->TruncateUpper(hi_code->start()); |
| + ASSERT(!new_code->Overlaps(hi_code)); |
| + } |
| + |
| + if ((lo != -1) && (lo_code->kind() == ProfileCode::kNativeCode) && |
| + (new_code->kind() == ProfileCode::kNativeCode) && |
| + (lo_code->end() == new_code->start())) { |
| + // Adjacent left neighbor of the same kind: merge. |
| + // (dladdr doesn't give us symbol size so we may new PCs we didn't |
|
zra
2017/06/14 05:00:05
may see new PCs
rmacnak
2017/06/14 17:32:14
Done.
|
| + // previously know belonged to it.) |
| + lo_code->ExpandUpper(new_code->end()); |
| return lo; |
| - } else { |
| - ProfileCode* code = At(lo); |
| - if (code->Overlaps(new_code)) { |
| - HandleOverlap(code, new_code, start, end); |
| - return lo; |
| - } |
| - code = At(hi); |
| - if (code->Overlaps(new_code)) { |
| - HandleOverlap(code, new_code, start, end); |
| - return hi; |
| - } |
| - table_.InsertAt(hi, new_code); |
| + } |
| + |
| + if ((hi != -1) && (hi_code->kind() == ProfileCode::kNativeCode) && |
| + (new_code->kind() == ProfileCode::kNativeCode) && |
| + (new_code->end() == hi_code->start())) { |
| + // Adjacent right neighbor of the same kind: merge. |
| + // (dladdr doesn't give us symbol size so we may new PCs we didn't |
|
zra
2017/06/14 05:00:05
may see new PCs
rmacnak
2017/06/14 17:32:14
Done.
|
| + // previously know belonged to it.) |
| + hi_code->ExpandLower(new_code->start()); |
| return hi; |
| } |
| - UNREACHABLE(); |
| - return -1; |
| + |
| + intptr_t insert; |
| + if (lo == -1) { |
| + insert = 0; |
| + } else if (hi == -1) { |
| + insert = length; |
| + } else { |
| + insert = lo + 1; |
| + } |
| + table_.InsertAt(insert, new_code); |
| + return insert; |
| } |
| private: |
| - intptr_t FindCodeIndex(uword pc, RangeCompare comparator) const { |
| - ASSERT(comparator != NULL); |
| - intptr_t count = table_.length(); |
| - intptr_t first = 0; |
| - while (count > 0) { |
| - intptr_t it = first; |
| - intptr_t step = count / 2; |
| - it += step; |
| - const ProfileCode* code = At(it); |
| - if (comparator(pc, code->start(), code->end())) { |
| - first = ++it; |
| - count -= (step + 1); |
| - } else { |
| - count = step; |
| - } |
| + void FindNeighbors(uword pc, |
| + intptr_t* lo, |
| + intptr_t* hi, |
| + ProfileCode** lo_code, |
| + ProfileCode** hi_code) const { |
| + ASSERT(table_.length() >= 1); |
| + |
| + intptr_t length = table_.length(); |
| + |
| + if (pc < At(0)->start()) { |
| + // Lower than any existing code. |
| + *lo = -1; |
| + *lo_code = NULL; |
| + *hi = 0; |
| + *hi_code = At(*hi); |
| + return; |
| } |
| - return first; |
| - } |
| - static bool CompareUpperBound(uword pc, uword start, uword end) { |
| - return pc >= end; |
| - } |
| + if (pc >= At(length - 1)->end()) { |
| + // Higher than any existing code. |
| + *lo = length - 1; |
| + *lo_code = At(*lo); |
| + *hi = -1; |
| + *hi_code = NULL; |
| + return; |
| + } |
| - static bool CompareLowerBound(uword pc, uword start, uword end) { |
| - return end <= pc; |
| - } |
| + *lo = 0; |
| + *lo_code = At(*lo); |
| + *hi = length - 1; |
| + *hi_code = At(*hi); |
| - void HandleOverlap(ProfileCode* existing, |
| - ProfileCode* code, |
| - uword start, |
| - uword end) { |
| - // We should never see overlapping Dart code regions. |
| - ASSERT(existing->kind() != ProfileCode::kDartCode); |
| - // We should never see overlapping Tag code regions. |
| - ASSERT(existing->kind() != ProfileCode::kTagCode); |
| - // When code regions overlap, they should be of the same kind. |
| - ASSERT(existing->kind() == code->kind()); |
| - existing->AdjustExtent(start, end); |
| + while ((*hi - *lo) > 1) { |
| + intptr_t mid = (*hi - *lo + 1) / 2 + *lo; |
| + ASSERT(*lo <= mid); |
| + ASSERT(*hi >= mid); |
| + ProfileCode* code = At(mid); |
| + if (code->start() <= pc) { |
| + *lo = mid; |
| + *lo_code = code; |
| + } |
| + if (pc < code->end()) { |
| + *hi = mid; |
| + *hi_code = code; |
| + } |
| + } |
| } |
| void VerifyOrder() { |
| @@ -2239,6 +2278,24 @@ class ProfileBuilder : public ValueObject { |
| native_start &= ~1; |
| #endif |
| + if (native_start > pc) { |
| + // Bogus lookup result. |
| + if (native_name != NULL) { |
| + NativeSymbolResolver::FreeSymbolName(native_name); |
| + native_name = NULL; |
| + } |
| + native_start = pc; |
| + } |
| + if ((pc - native_start) > (32 * KB)) { |
| + // Suspect lookup result. More likely dladdr going off the rails than a |
| + // jumbo function. |
| + if (native_name != NULL) { |
| + NativeSymbolResolver::FreeSymbolName(native_name); |
| + native_name = NULL; |
| + } |
| + native_start = pc; |
| + } |
| + |
| ASSERT(pc >= native_start); |
| profile_code = new ProfileCode(ProfileCode::kNativeCode, native_start, |
| pc + 1, 0, code); |