Index: lldb/include/lldb/Utility/RangeMap.h =================================================================== --- lldb/include/lldb/Utility/RangeMap.h +++ lldb/include/lldb/Utility/RangeMap.h @@ -592,13 +592,17 @@ 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 Entry; typedef llvm::SmallVector Collection; - RangeDataVector(Compare compare = Compare()) : m_compare(compare) {} + RangeDataVector(Compare compare = Compare()) : m_compare(compare), upper_bound_computed(false) {} ~RangeDataVector() = default; - void Append(const Entry &entry) { m_entries.push_back(entry); } + void Append(const Entry &entry) { m_entries.push_back(entry); upper_bound_computed = false; } void Sort() { if (m_entries.size() > 1) @@ -627,11 +631,28 @@ }); } + // We can treat the vector as a flattened BST, augmenting it with upper bounds (max of + // range endpoints) for every index allows us to query for intersections in O(log n) time. + void ComputeUpperBounds() { + ComputeUpperBounds(0, m_entries.size() - 1); + upper_bound_computed = true; + } + + B ComputeUpperBounds(int lo, int hi) { + if (lo > hi) return B(); + + int mid = (lo + hi) / 2; + auto entry = m_entries[mid]; + + entry.upper_bound = std::max(entry.base + entry.size, std::max(ComputeUpperBounds(lo, mid - 1), + ComputeUpperBounds(mid + 1, hi))); + + return entry.upper_bound; + } + #ifdef ASSERT_RANGEMAP_ARE_SORTED bool IsSorted() const { typename Collection::const_iterator pos, end, prev; - // First we determine if we can combine any of the Entry objects so we - // don't end up allocating and making a new collection for no reason for (pos = m_entries.begin(), end = m_entries.end(), prev = end; pos != end; prev = pos++) { if (prev != end && *pos < *prev) @@ -677,7 +698,7 @@ } } - void Clear() { m_entries.clear(); } + void Clear() { m_entries.clear(); upper_bound_computed = false; } bool IsEmpty() const { return m_entries.empty(); } @@ -708,22 +729,41 @@ } uint32_t FindEntryIndexesThatContain(B addr, - std::vector &indexes) const { + 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 (!upper_bound_computed) + ComputeUpperBounds(); + + FindEntryIndexesThatContain(addr, 0, m_entries.size(), indexes); + return indexes.size(); } + void FindEntryIndexesThatContain(B addr, int lo, int hi, + std::vector &indexes) { + if (lo > hi) return; + int 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 + FindEntryIndexesThatContain(addr, lo, mid - 1, 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); + + FindEntryIndexesThatContain(addr, mid + 1, hi, indexes); + } + Entry *FindEntryThatContains(B addr) { return const_cast( static_cast(this)->FindEntryThatContains( @@ -806,6 +846,7 @@ protected: Collection m_entries; Compare m_compare; + bool upper_bound_computed; }; // A simple range with data class where you get to define the type of