Index: lldb/include/lldb/Utility/RangeMap.h =================================================================== --- lldb/include/lldb/Utility/RangeMap.h +++ lldb/include/lldb/Utility/RangeMap.h @@ -592,13 +592,18 @@ struct RangeData : public Range { typedef T DataType; + B upper_bound; DataType data; - RangeData() : Range(), data() {} + RangeData() : Range(), upper_bound(), data() {} - RangeData(B base, S size) : Range(base, size), data() {} + RangeData(B base, S size) : Range(base, size), upper_bound(), data() {} - RangeData(B base, S size, DataType d) : Range(base, size), data(d) {} + RangeData(B base, S size, DataType d) + : Range(base, size), upper_bound(), data(d) {} + + RangeData(B base, S size, B ub, DataType d) + : Range(base, size), upper_bound(ub), data(d) {} }; template &indexes) const { + uint32_t FindEntryIndexesThatContain(B addr, std::vector &indexes) { #ifdef ASSERT_RANGEMAP_ARE_SORTED assert(IsSorted()); #endif - // Search the entries until the first entry that has a larger base address - // than `addr`. As m_entries is sorted by their base address, all following - // entries can't contain `addr` as their base address is already larger. - for (const auto &entry : m_entries) { - if (entry.Contains(addr)) - indexes.push_back(entry.data); - else if (entry.GetRangeBase() > addr) - break; - } + if (!m_entries.empty()) + FindEntryIndexesThatContain(addr, 0, m_entries.size(), indexes); + return indexes.size(); } @@ -806,6 +804,56 @@ protected: Collection m_entries; Compare m_compare; + +private: + // We can treat the vector as a flattened Binary Search Tree, augmenting it + // with upper bounds (max of range endpoints) for every index allows us to + // query for range containment quicker. + B ComputeUpperBounds(size_t lo, size_t hi) { + size_t mid = (lo + hi) / 2; + auto &entry = m_entries[mid]; + + entry.upper_bound = entry.base + entry.size; + + if (lo < mid) + entry.upper_bound = + std::max(entry.upper_bound, ComputeUpperBounds(lo, mid)); + + if (mid + 1 < hi) + entry.upper_bound = + std::max(entry.upper_bound, ComputeUpperBounds(mid + 1, hi)); + + return entry.upper_bound; + } + + // This is based on the augmented tree implementation found at + // https://en.wikipedia.org/wiki/Interval_tree#Augmented_tree + void FindEntryIndexesThatContain(B addr, size_t lo, size_t hi, + std::vector &indexes) { + size_t mid = (lo + hi) / 2; + auto entry = m_entries[mid]; + + // addr is greater than the rightmost point of any interval below mid + // so there are cannot be any matches. + if (addr > entry.upper_bound) + return; + + // Recursively search left subtree + if (lo < mid) + FindEntryIndexesThatContain(addr, lo, mid, indexes); + + // If addr is smaller than the start of the current interval it + // cannot contain it nor can any of its right subtree. + if (addr < entry.base) + return; + + if (entry.Contains(addr)) + indexes.push_back(entry.data); + + // Recursively search right subtree + if (mid + 1 < hi) + FindEntryIndexesThatContain(addr, mid + 1, hi, indexes); + } }; // A simple range with data class where you get to define the type of