Improved bulk addDatatypes performance (experimental method) and

corrected structure editor help text.
This commit is contained in:
ghidra1 2020-06-04 19:38:45 -04:00
parent 4406b8a7a8
commit bdbbca30a1
5 changed files with 41 additions and 20 deletions

View file

@ -179,14 +179,12 @@
<H3>Unaligned Structures</H3> <H3>Unaligned Structures</H3>
<BLOCKQUOTE> <BLOCKQUOTE>
<P>When a structure is unaligned, with the exception of bitfields, each component immediately <P>When a structure is unaligned, with the exception of bitfields, each component shown within
follows the one before it. In the editor immediately follows the one before it. In other words, no automatic alignment or padding occurs.
other words no automatic alignment or padding occurs. Unaligned structures can contain Unaligned structures may be used to position components with known data
Unaligned structures should be used to position components with known data types at specific offsets within a structure. Therefore, when editing an unaligned structure,
types at specific offsets within the structure. Therefore the structure editor tries to the structure editor attempts to prevent defined components from moving
prevent defined components (those other than Undefined bytes) from accidentally being moved to a different offset when performing operations like drag and drop which may consume undefined bytes. <BR>
to a different offset when performing operations like drag and drop, although undefined bytes
may be consumed. <BR>
</P> </P>
<DIV style="text-align: center; margin-top: 10px;"> <DIV style="text-align: center; margin-top: 10px;">

View file

@ -812,7 +812,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
} }
finally { finally {
if (isResolveCacheOwner) { if (isResolveCacheOwner) {
flushResolveCacheAndClearQueue(); flushResolveQueue(true);
} }
if (isEquivalenceCacheOwner) { if (isEquivalenceCacheOwner) {
clearEquivalenceCache(); clearEquivalenceCache();
@ -1142,15 +1142,26 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
lock.acquire(); lock.acquire();
boolean isEquivalenceCacheOwner = activateEquivalenceCache(); boolean isEquivalenceCacheOwner = activateEquivalenceCache();
boolean isResolveCacheOwner = activateResolveCache(); boolean isResolveCacheOwner = activateResolveCache();
// TODO: extended hold time on lock may cause the GUI to become
// unresponsive. Consider releasing lock between resolves, although
// this exposes risk of having active resolve queue/cache without lock
try { try {
monitor.setMessage("Adding datatypes...");
monitor.setMaximum(dataTypes.size());
monitor.setProgress(0);
int i = 0;
for (DataType dt : dataTypes) { for (DataType dt : dataTypes) {
monitor.checkCanceled(); monitor.checkCanceled();
resolve(dt, handler); resolve(dt, handler);
if (isResolveCacheOwner) {
flushResolveQueue(false);
}
monitor.setProgress(++i);
} }
} }
finally { finally {
if (isResolveCacheOwner) { if (isResolveCacheOwner) {
flushResolveCacheAndClearQueue(); flushResolveQueue(true);
} }
if (isEquivalenceCacheOwner) { if (isEquivalenceCacheOwner) {
clearEquivalenceCache(); clearEquivalenceCache();
@ -3764,19 +3775,17 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
/** /**
* Activate resolveCache and associated resolveQueue if not already active. If * Activate resolveCache and associated resolveQueue if not already active. If
* this method returns true caller is responsible for flushing resolveQueue and * this method returns true caller is responsible for flushing resolveQueue and
* invoking {@link #flushResolveCacheAndClearQueue(DataTypeConflictHandler)} * invoking {@link #flushResolveQueue(boolean)} when resolve complete.
* when resolve. For each completed resolve * For each completed resolve {@link #cacheResolvedDataType(DataType, DataType)}
* {@link #cacheResolvedDataType(DataType, DataType)} should be called. * should be invoked.
* *
* @return true if resolveCache and resolveQueue activated else false if * @return true if resolveCache activated else false if already active.
* previously activated.
*/ */
boolean activateResolveCache() { boolean activateResolveCache() {
if (resolveCache != null) { if (resolveCache != null) {
return false; return false;
} }
resolveCache = new IdentityHashMap<>(); resolveCache = new IdentityHashMap<>();
resolveQueue = new TreeSet<>();
return true; return true;
} }
@ -3788,10 +3797,19 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
*/ */
void queuePostResolve(DataTypeDB resolvedDt, DataType definitionDt) { void queuePostResolve(DataTypeDB resolvedDt, DataType definitionDt) {
resolvedDt.resolving = true; resolvedDt.resolving = true;
if (resolveQueue == null) {
resolveQueue = new TreeSet<>();
}
resolveQueue.add(new ResolvePair(resolvedDt, definitionDt)); resolveQueue.add(new ResolvePair(resolvedDt, definitionDt));
} }
void flushResolveCacheAndClearQueue() { void flushResolveQueue(boolean deactivateCache) {
if (resolveQueue == null) {
if (deactivateCache) {
resolveCache = null;
}
return;
}
DataTypeConflictHandler handler = getDependencyConflictHandler(); DataTypeConflictHandler handler = getDependencyConflictHandler();
while (!resolveQueue.isEmpty()) { while (!resolveQueue.isEmpty()) {
ResolvePair resolvePair = resolveQueue.pollFirst(); ResolvePair resolvePair = resolveQueue.pollFirst();
@ -3805,8 +3823,10 @@ abstract public class DataTypeManagerDB implements DataTypeManager {
resolvedDt.pointerPostResolveRequired = false; resolvedDt.pointerPostResolveRequired = false;
} }
} }
resolveCache = null;
resolveQueue = null; resolveQueue = null;
if (deactivateCache) {
resolveCache = null;
}
} }
private DataType getCachedResolve(DataType dt) { private DataType getCachedResolve(DataType dt) {

View file

@ -1168,7 +1168,7 @@ class StructureDB extends CompositeDB implements Structure {
} }
finally { finally {
if (isResolveCacheOwner) { if (isResolveCacheOwner) {
dataMgr.flushResolveCacheAndClearQueue(); dataMgr.flushResolveQueue(true);
} }
lock.release(); lock.release();
} }

View file

@ -257,7 +257,7 @@ class UnionDB extends CompositeDB implements Union {
} }
finally { finally {
if (isResolveCacheOwner) { if (isResolveCacheOwner) {
dataMgr.flushResolveCacheAndClearQueue(); dataMgr.flushResolveQueue(true);
} }
lock.release(); lock.release();
} }

View file

@ -101,6 +101,9 @@ public interface DataTypeManager {
* Sequentially adds a collection of datatypes to this data manager. * Sequentially adds a collection of datatypes to this data manager.
* This method provides the added benefit of equivalence caching * This method provides the added benefit of equivalence caching
* for improved performance. * for improved performance.
* <br>
* WARNING: This is an experimental method whoose use may cause the GUI and
* task monitor to become unresponsive due to extended hold times on the manager lock.
* @param dataTypes collection of datatypes * @param dataTypes collection of datatypes
* @param handler conflict handler * @param handler conflict handler
* @param monitor task monitor * @param monitor task monitor