Speed up testing for multiple functions at an address on Posix

The way this was originally written blows up on large enough targets
(like...Chromium :/). This change adds a set for amortized constant
time lookup of whether a FUNC already exists at a given address.

Bug: google-breakpad:751
Change-Id: I10a322da70f769c106e1e5f5b2dc3dc3f79444fd
Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/4031580
Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Leonard Grey 2022-11-17 11:37:26 -05:00
parent 442456a68c
commit 522bd2337a
2 changed files with 15 additions and 17 deletions

View file

@ -174,27 +174,23 @@ bool Module::AddFunction(Function* function) {
} }
} }
#endif #endif
if (enable_multiple_field_) { if (enable_multiple_field_ && function_addresses_.count(function->address)) {
FunctionSet::iterator existing_function = std::find_if( FunctionSet::iterator existing_function = std::find_if(
functions_.begin(), functions_.end(), functions_.begin(), functions_.end(),
[&](Function* other) { return other->address == function->address; }); [&](Function* other) { return other->address == function->address; });
if (existing_function != functions_.end()) { assert(existing_function != functions_.end());
(*existing_function)->is_multiple = true; (*existing_function)->is_multiple = true;
// Free the duplicate that was not inserted because this Module // Free the duplicate that was not inserted because this Module
// now owns it. // now owns it.
return false; return false;
} }
std::pair<FunctionSet::iterator, bool> ret = functions_.insert(function); function_addresses_.emplace(function->address);
// We just checked!
assert(ret.second);
} else {
std::pair<FunctionSet::iterator, bool> ret = functions_.insert(function); std::pair<FunctionSet::iterator, bool> ret = functions_.insert(function);
if (!ret.second && (*ret.first != function)) { if (!ret.second && (*ret.first != function)) {
// Free the duplicate that was not inserted because this Module // Free the duplicate that was not inserted because this Module
// now owns it. // now owns it.
return false; return false;
} }
}
return true; return true;
} }

View file

@ -472,6 +472,8 @@ class Module {
// point to. // point to.
FileByNameMap files_; // This module's source files. FileByNameMap files_; // This module's source files.
FunctionSet functions_; // This module's functions. FunctionSet functions_; // This module's functions.
// Used to quickly look up whether a function exists at a particular address.
unordered_set<Address> function_addresses_;
// The module owns all the call frame info entries that have been // The module owns all the call frame info entries that have been
// added to it. // added to it.