Cleanups/optimizations for ImageFunctionsView.

- Get rid of the functions array as we no longer really needed it except
to sift duplicates. The latter function is now done simply by keeping a
set of already seen function addresses, and skipping entries which fall
in said category.

- Use NotifyNodesCleared()/NotifyTableModelReset() as appropriate.

- Remove now-unused sorting functions.

Combined, these changes significantly reduce the overhead of switching
the active image, which was produced observable lag when either choosing
another image in the Images list, or when stepping into/out of a
function resulted in an image change.
This commit is contained in:
Rene Gollent 2013-05-15 09:48:19 -04:00
parent 6132f7b96d
commit f3bf3eb0d4

View File

@ -8,8 +8,8 @@
#include <stdio.h>
#include <algorithm>
#include <new>
#include <set>
#include <AutoDeleter.h>
@ -170,8 +170,6 @@ public:
{
// unset old functions
if (fImageDebugInfo != NULL) {
NotifyNodesRemoved(TreeTablePath(), 0,
fChildPathComponents.CountItems());
for (int32 i = 0; i < fChildPathComponents.CountItems(); i++)
fChildPathComponents.ItemAt(i)->ReleaseReference();
@ -182,48 +180,34 @@ public:
fImageDebugInfo = imageDebugInfo;
// set new functions
if (fImageDebugInfo == NULL || fImageDebugInfo->CountFunctions() == 0)
if (fImageDebugInfo == NULL || fImageDebugInfo->CountFunctions()
== 0) {
NotifyNodesCleared();
return;
// create an array with the functions
int32 functionCount = fImageDebugInfo->CountFunctions();
FunctionInstance** functions
= new(std::nothrow) FunctionInstance*[functionCount];
if (functions == NULL)
return;
ArrayDeleter<FunctionInstance*> functionsDeleter(functions);
for (int32 i = 0; i < functionCount; i++)
functions[i] = fImageDebugInfo->FunctionAt(i);
// sort them
std::sort(functions, functions + functionCount, &_FunctionLess);
// eliminate duplicate function instances
if (functionCount > 0) {
Function* previousFunction = functions[0]->GetFunction();
int32 removed = 0;
for (int32 i = 1; i < functionCount; i++) {
if (functions[i]->GetFunction() == previousFunction) {
removed++;
} else {
functions[i - removed] = functions[i];
previousFunction = functions[i]->GetFunction();
}
}
functionCount -= removed;
// The array might now be too large, but we can live with that.
}
std::set<target_addr_t> functionAddresses;
SourcePathComponentNode* sourcelessNode = new(std::nothrow)
SourcePathComponentNode(NULL, "<no source file>", NULL, NULL);
BReference<SourcePathComponentNode> sourceNodeRef(
sourcelessNode, true);
int32 functionCount = fImageDebugInfo->CountFunctions();
for (int32 i = 0; i < functionCount; i++) {
if (!_BuildFunctionSourcePath(functions[i], sourcelessNode))
FunctionInstance* instance = fImageDebugInfo->FunctionAt(i);
target_addr_t address = instance->Address();
if (functionAddresses.find(address) != functionAddresses.end())
continue;
else {
try {
functionAddresses.insert(address);
} catch (...) {
return;
}
}
if (!_BuildFunctionSourcePath(instance, sourcelessNode))
return;
}
@ -235,8 +219,7 @@ public:
}
}
NotifyNodesAdded(TreeTablePath(), 0,
fChildPathComponents.CountItems());
NotifyTableModelReset();
}
virtual int32 CountColumns() const
@ -437,38 +420,6 @@ private:
return true;
}
static int _CompareSourceFileNames(LocatableFile* a, LocatableFile* b)
{
if (a == b)
return 0;
if (a == NULL)
return 1;
if (b == NULL)
return -1;
BString pathA;
a->GetPath(pathA);
BString pathB;
b->GetPath(pathB);
return pathA.Compare(pathB);
}
static bool _FunctionLess(const FunctionInstance* a,
const FunctionInstance* b)
{
// compare source file name first
int compared = _CompareSourceFileNames(a->SourceFile(),
b->SourceFile());
if (compared != 0)
return compared < 0;
// source file names are equal -- compare the function names
return strcasecmp(a->PrettyName(), b->PrettyName()) < 0;
}
private:
typedef BObjectList<SourcePathComponentNode> ChildPathComponentList;