From e3aebe3adb7785c29f579fd5fb024344ea92b3fd Mon Sep 17 00:00:00 2001 From: ghidravore Date: Thu, 21 May 2020 16:46:44 -0400 Subject: [PATCH] Replace uses of LongObjectHashTable with Java's HashMap --- .../merge/datatypes/DataTypeMergeManager.java | 89 ++-- .../merge/listing/AbstractFunctionMerger.java | 33 +- .../app/merge/listing/CodeUnitMerger.java | 10 +- .../merge/listing/ExternalFunctionMerger.java | 23 +- .../app/merge/listing/FunctionMerger.java | 25 +- .../app/plugin/match/MatchFunctions.java | 35 +- .../ghidra/server/remote/RMIClassServer.java | 5 +- .../vt/api/db/AssociationDatabaseManager.java | 4 +- .../store/local/CheckoutManager.java | 26 +- .../ghidra/util/datastruct/ObjectCache.java | 70 ++- .../util/datastruct/SoftCacheLongKeyMap.java | 163 ------- .../graph/attributes/ObjectAttribute.java | 13 +- .../graph/attributes/StringAttribute.java | 24 +- .../java/ghidra/util/prop/PropertySet.java | 404 ++++++++---------- .../datastruct/SoftCacheLongKeyMapTest.java | 108 ----- .../program/database/DBObjectCache.java | 68 +-- .../database/OverlaySpaceAdapterDB.java | 10 +- .../database/data/DataTypeManagerDB.java | 9 +- .../database/external/ExternalManagerDB.java | 3 +- .../database/map/NormalizedAddressSet.java | 19 +- .../register/OldProgramContextDB.java | 8 +- .../model/util/DefaultPropertyMap.java | 25 +- 22 files changed, 407 insertions(+), 767 deletions(-) delete mode 100644 Ghidra/Framework/Generic/src/main/java/ghidra/util/datastruct/SoftCacheLongKeyMap.java delete mode 100644 Ghidra/Framework/Generic/src/test/java/ghidra/util/datastruct/SoftCacheLongKeyMapTest.java diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergeManager.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergeManager.java index 25849a194e..2a5fddaa1c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergeManager.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/datatypes/DataTypeMergeManager.java @@ -33,7 +33,6 @@ import ghidra.program.model.data.*; import ghidra.program.model.data.Enum; import ghidra.program.model.listing.DataTypeChangeSet; import ghidra.util.*; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; @@ -78,13 +77,13 @@ public class DataTypeMergeManager implements MergeResolver { private DataTypeMergePanel dtMergePanel; private int totalConflictCount; private int currentConflictIndex; - private LongObjectHashtable myResolvedDts; // maps My data type key -> resolved Data type - private LongObjectHashtable latestResolvedDts; // maps Latest data type key -> resolved Data type - private LongObjectHashtable origResolvedDts; // maps Original data type key -> resolved Data type + private Map myResolvedDts; // maps My data type key -> resolved Data type + private Map latestResolvedDts; // maps Latest data type key -> resolved Data type + private Map origResolvedDts; // maps Original data type key -> resolved Data type private List fixUpList; // FixUpInfo objects that must be resolved after private HashSet fixUpIDSet; // track types with fixups // data types have been added and conflicts resolved. - private LongObjectHashtable cleanupPlaceHolderList; // placeholders that need to be removed. + private Map cleanupPlaceHolderList; // placeholders that need to be removed. private int progressIndex; // index for showing progress private int categoryChoice = ASK_USER; @@ -700,7 +699,7 @@ public class DataTypeMergeManager implements MergeResolver { * the data type existed */ private DataType updateDataTypeName(long id, DataType dt, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataType resultDt = dtms[RESULT].getDataType(id); DataType newDt = null; if (resultDt != null) { @@ -771,7 +770,7 @@ public class DataTypeMergeManager implements MergeResolver { } private DataType updateDataType(long id, DataTypeManager dtm, - LongObjectHashtable resolvedDataTypes, boolean updatePath) { + Map resolvedDataTypes, boolean updatePath) { DataType resultDt = dtms[RESULT].getDataType(id); DataType myDt = dtm.getDataType(id); @@ -816,7 +815,7 @@ public class DataTypeMergeManager implements MergeResolver { } private DataType updateDataTypeSource(long id, DataTypeManager dtm, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataType resultDt = dtms[RESULT].getDataType(id); DataType myDt = dtm.getDataType(id); SourceArchive mySourceArchive = myDt.getSourceArchive(); @@ -832,8 +831,9 @@ public class DataTypeMergeManager implements MergeResolver { else { SourceArchive resultSourceArchive = resultDt.getSourceArchive(); - if (!resultSourceArchive.getSourceArchiveID().equals( - mySourceArchive.getSourceArchiveID())) { + if (!resultSourceArchive.getSourceArchiveID() + .equals( + mySourceArchive.getSourceArchiveID())) { resultDt.setSourceArchive(mySourceArchive); } } @@ -850,7 +850,7 @@ public class DataTypeMergeManager implements MergeResolver { * @return the resulting data type in this data type manager. */ private DataType addDataType(long dataTypeID, DataType dataType, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataType existingDt = resolvedDataTypes.get(dataTypeID); if (existingDt != null) { @@ -899,7 +899,7 @@ public class DataTypeMergeManager implements MergeResolver { * @return resolved data type that corresponds to id */ private DataType getResolvedBaseType(long id, DataType dt, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataTypeManager dtm = dt.getDataTypeManager(); DataType baseDt = getBaseDataType(dt); if (baseDt == DataType.DEFAULT) { @@ -933,7 +933,7 @@ public class DataTypeMergeManager implements MergeResolver { } private DataType createPointer(long id, Pointer pointerDt, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataType innerDt = pointerDt.getDataType(); if (innerDt == DataType.DEFAULT) { return pointerDt; @@ -954,7 +954,7 @@ public class DataTypeMergeManager implements MergeResolver { } private DataType createTypeDef(long id, TypeDef originalTypeDef, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataType innerDataType = originalTypeDef.getDataType(); if (innerDataType == DataType.DEFAULT) { return originalTypeDef; @@ -985,7 +985,7 @@ public class DataTypeMergeManager implements MergeResolver { } private DataType createArray(long id, Array array, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataType dt = array.getDataType(); if (dt == DataType.DEFAULT) { return array; @@ -1006,7 +1006,7 @@ public class DataTypeMergeManager implements MergeResolver { } private DataType addComposite(long id, Composite myDt, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { long oldLastChangeTime = myDt.getLastChangeTime(); long oldLastChangeTimeInSourceArchive = myDt.getLastChangeTimeInSourceArchive(); @@ -1026,7 +1026,7 @@ public class DataTypeMergeManager implements MergeResolver { } private DataType addFunctionDef(long id, FunctionDefinition myDt, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { FunctionDefinition newDt = (FunctionDefinition) myDt.clone(dtms[RESULT]); setCategoryPath(newDt, myDt.getCategoryPath()); updateFunctionDef(id, myDt, newDt, resolvedDataTypes); @@ -1034,7 +1034,7 @@ public class DataTypeMergeManager implements MergeResolver { } private void updateHashTables(long id, DataType newDt, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { resolvedDataTypes.put(id, newDt); if (!myDtAddedList.contains(Long.valueOf(id))) { if (resolvedDataTypes == myResolvedDts) { @@ -1053,7 +1053,7 @@ public class DataTypeMergeManager implements MergeResolver { } private DataType getResolvedComponent(long compID, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataType resolvedDt = resolvedDataTypes.get(compID); if (resolvedDt != null) { // if this is a pointer, typedef, or array, check the @@ -1095,7 +1095,7 @@ public class DataTypeMergeManager implements MergeResolver { } private void updateFlexArray(long sourceDtID, Structure sourceDt, Structure destStruct, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataTypeComponent flexDtc = sourceDt.getFlexibleArrayComponent(); if (flexDtc == null) { @@ -1155,7 +1155,7 @@ public class DataTypeMergeManager implements MergeResolver { } private void updateStructure(long sourceDtID, Structure sourceDt, Structure destStruct, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { // NOTE: it is possible for the same destStruct to be updated more than once; // therefor we must cleanup any previous obsolete fixups @@ -1356,7 +1356,7 @@ public class DataTypeMergeManager implements MergeResolver { } private void updateUnion(long sourceDtID, Union sourceDt, Union destUnion, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { // NOTE: it is possible for the same destUnion to be updated more than once; // therefor we must cleanup any previous obsolete fixups @@ -1479,7 +1479,7 @@ public class DataTypeMergeManager implements MergeResolver { } private void updateComposite(long sourceDtID, Composite sourceDt, Composite destDt, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { if (sourceDt instanceof Structure) { updateStructure(sourceDtID, (Structure) sourceDt, (Structure) destDt, @@ -1493,7 +1493,7 @@ public class DataTypeMergeManager implements MergeResolver { private void updateFunctionDef(long sourceFunctionDefDtID, FunctionDefinition sourceFunctionDefDt, FunctionDefinition destDt, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { // NOTE: it is possible for the same function def to be updated more than once; // therefor we must cleanup any previous obsolete fixups @@ -1542,7 +1542,7 @@ public class DataTypeMergeManager implements MergeResolver { * has not been resolved yet */ private DataType getResolvedParam(long id, long paramDatatypeID, int index, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataType resolvedDt = getResolvedComponent(paramDatatypeID, resolvedDataTypes); if (resolvedDt == null) { if (!myDtAddedList.contains(Long.valueOf(paramDatatypeID))) { @@ -2216,7 +2216,7 @@ public class DataTypeMergeManager implements MergeResolver { * data type manager. */ private boolean equivalentDataTypeFound(long myDtID, DataType myDt) { - if (myResolvedDts.contains(myDtID)) { + if (myResolvedDts.containsKey(myDtID)) { return true; } DataType resultDt = dtms[RESULT].getDataType(myDt.getCategoryPath(), myDt.getName()); @@ -2226,8 +2226,9 @@ public class DataTypeMergeManager implements MergeResolver { UniversalID resultDtUniversalID = resultDt.getUniversalID(); UniversalID myDtUniversalID = myDt.getUniversalID(); // UniversalID can be null if data type is BuiltIn. - if (!resultSourceArchive.getSourceArchiveID().equals( - mySourceArchive.getSourceArchiveID()) || + if (!resultSourceArchive.getSourceArchiveID() + .equals( + mySourceArchive.getSourceArchiveID()) || !SystemUtilities.isEqual(resultDtUniversalID, myDtUniversalID)) { return false; } @@ -2241,7 +2242,7 @@ public class DataTypeMergeManager implements MergeResolver { private void cleanUpDataTypes() { // clean up data types - long[] keys = cleanupPlaceHolderList.getKeys(); + List keys = new ArrayList(cleanupPlaceHolderList.keySet()); for (long key : keys) { CleanUpInfo cleanUpInfo = cleanupPlaceHolderList.get(key); cleanUpInfo.cleanUp(); @@ -2566,7 +2567,7 @@ public class DataTypeMergeManager implements MergeResolver { private void addToCleanupList(FixUpInfo info) { long id = info.id; int index = info.index; - LongObjectHashtable ht = info.ht; + Map ht = info.ht; CleanUpInfo cleanUpInfo = cleanupPlaceHolderList.get(id); if (cleanUpInfo == null) { cleanUpInfo = new CleanUpInfo(id); @@ -2685,7 +2686,7 @@ public class DataTypeMergeManager implements MergeResolver { * @return */ private DataType resolve(long id, DataTypeManager dtm, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { DataType dt = getResolvedComponent(id, resolvedDataTypes); if (dt == null) { DataType otherDt = dtm.getDataType(id); @@ -2961,15 +2962,15 @@ public class DataTypeMergeManager implements MergeResolver { origDtConflictList = new ArrayList<>(dtConflictList); - myResolvedDts = new LongObjectHashtable<>(); - latestResolvedDts = new LongObjectHashtable<>(); - origResolvedDts = new LongObjectHashtable<>(); + myResolvedDts = new HashMap<>(); + latestResolvedDts = new HashMap<>(); + origResolvedDts = new HashMap<>(); fixUpList = new ArrayList<>(); fixUpIDSet = new HashSet<>(); totalConflictCount += dtConflictList.size(); - cleanupPlaceHolderList = new LongObjectHashtable<>(); + cleanupPlaceHolderList = new HashMap<>(); } /** @@ -3212,7 +3213,7 @@ public class DataTypeMergeManager implements MergeResolver { return new String[][] { DATA_TYPES_PHASE }; } - private DataTypeManager getDataTypeManager(LongObjectHashtable dataTypeMap) { + private DataTypeManager getDataTypeManager(Map dataTypeMap) { if (dataTypeMap == origResolvedDts) { return dtms[ORIGINAL]; } @@ -3238,7 +3239,7 @@ public class DataTypeMergeManager implements MergeResolver { long id; long compID; int index; - LongObjectHashtable ht; + Map ht; // bitfield info int bitOffset = -1; @@ -3255,7 +3256,7 @@ public class DataTypeMergeManager implements MergeResolver { * @param resolvedDataTypes hashtable used for resolving the data type */ FixUpInfo(long id, long compID, int index, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { this.id = id; this.compID = compID; this.index = index; @@ -3271,7 +3272,7 @@ public class DataTypeMergeManager implements MergeResolver { * @param resolvedDataTypes hashtable used for resolving the data type */ FixUpInfo(long id, long compID, DataTypeComponent sourceDtc, - LongObjectHashtable resolvedDataTypes) { + Map resolvedDataTypes) { this(id, compID, getComponentFixupIndex(sourceDtc), resolvedDataTypes); if (sourceDtc.isBitFieldComponent()) { BitFieldDataType bfDt = (BitFieldDataType) sourceDtc.getDataType(); @@ -3347,7 +3348,7 @@ public class DataTypeMergeManager implements MergeResolver { */ private class CleanUpInfo { long id; - HashMap, int[]> map; // resolvedDataTypesMap, indexArray + Map, int[]> map; // resolvedDataTypesMap, indexArray /** * Construct info needed to clean up place holder data types after base types @@ -3364,7 +3365,7 @@ public class DataTypeMergeManager implements MergeResolver { * structure; for other data types, offset is not used (specify -1) * @param resolvedDataTypes hashtable used for resolving the data type */ - public void add(int index, LongObjectHashtable resolvedDataTypes) { + public void add(int index, Map resolvedDataTypes) { if (map == null) { map = new HashMap<>(); } @@ -3383,10 +3384,10 @@ public class DataTypeMergeManager implements MergeResolver { if (map == null) { return; } - Set> keySet = map.keySet(); - Iterator> iterator = keySet.iterator(); + Set> keySet = map.keySet(); + Iterator> iterator = keySet.iterator(); while (iterator.hasNext()) { - LongObjectHashtable ht = iterator.next(); + Map ht = iterator.next(); DataType dt = ht.get(id); if (dt instanceof Composite) { int[] indexArray = map.get(ht); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/AbstractFunctionMerger.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/AbstractFunctionMerger.java index ed1e53da58..95e7afc413 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/AbstractFunctionMerger.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/AbstractFunctionMerger.java @@ -39,7 +39,6 @@ import ghidra.program.model.symbol.*; import ghidra.program.util.DiffUtility; import ghidra.program.util.ProgramMerge; import ghidra.util.*; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.datastruct.ObjectIntHashtable; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; @@ -122,9 +121,9 @@ abstract class AbstractFunctionMerger implements ListingMergeConstants { protected AddressFactory resultAddressFactory; - protected LongObjectHashtable latestResolvedDts; // maps data type ID -> resolved Data type - protected LongObjectHashtable myResolvedDts; // maps data type ID -> resolved Data type - protected LongObjectHashtable origResolvedDts; + protected Map latestResolvedDts; // maps data type ID -> resolved Data type + protected Map myResolvedDts; // maps data type ID -> resolved Data type + protected Map origResolvedDts; // mergePanel is a panel for listing merge conflicts. // listings in CENTER, conflictInfoPanel in NORTH, mergeConflicts in SOUTH. @@ -267,9 +266,10 @@ abstract class AbstractFunctionMerger implements ListingMergeConstants { // See if both changed to same value. switch (type) { case FUNC_RETURN_ADDRESS_OFFSET: - return (latestStack.getReturnAddressOffset() == myStack.getReturnAddressOffset()) - ? 0 - : type; + return (latestStack.getReturnAddressOffset() == myStack + .getReturnAddressOffset()) + ? 0 + : type; // For now, we are not allowing you to set the parameter offset or local size outright. // case FUNC_PARAMETER_OFFSET: // return (latestStack.getParameterOffset() == myStack.getParameterOffset()) ? 0 @@ -277,9 +277,10 @@ abstract class AbstractFunctionMerger implements ListingMergeConstants { // case FUNC_LOCAL_SIZE: // return (latestStack.getLocalSize() == myStack.getLocalSize()) ? 0 : type; case FUNC_STACK_PURGE_SIZE: - return (functions[LATEST].getStackPurgeSize() == functions[MY].getStackPurgeSize()) - ? 0 - : type; + return (functions[LATEST].getStackPurgeSize() == functions[MY] + .getStackPurgeSize()) + ? 0 + : type; case FUNC_NAME: return hasUnresolvedFunctionNameConflict(functions, monitor) ? type : 0; case FUNC_INLINE: @@ -292,12 +293,14 @@ abstract class AbstractFunctionMerger implements ListingMergeConstants { // return (functions[LATEST].hasCustomVariableStorage() == functions[MY].hasCustomVariableStorage()) ? 0 // : type; case FUNC_CALLING_CONVENTION: - return (functions[LATEST].getCallingConventionName().equals( - functions[MY].getCallingConventionName())) ? 0 : type; + return (functions[LATEST].getCallingConventionName() + .equals( + functions[MY].getCallingConventionName())) ? 0 : type; case FUNC_SIGNATURE_SOURCE: - return (functions[LATEST].getSignatureSource() == functions[MY].getSignatureSource()) - ? 0 - : type; + return (functions[LATEST].getSignatureSource() == functions[MY] + .getSignatureSource()) + ? 0 + : type; default: throw new IllegalArgumentException("type = " + type); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/CodeUnitMerger.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/CodeUnitMerger.java index 1a857f9a90..414f6a941c 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/CodeUnitMerger.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/CodeUnitMerger.java @@ -17,6 +17,7 @@ package ghidra.app.merge.listing; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.Map; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; @@ -35,7 +36,6 @@ import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.util.CodeUnitInsertionException; import ghidra.program.util.*; import ghidra.util.Msg; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.exception.CancelledException; import ghidra.util.exception.NotYetImplementedException; import ghidra.util.task.TaskMonitor; @@ -100,8 +100,8 @@ class CodeUnitMerger extends AbstractListingMerger { ProgramMerge mergeLatest; ProgramMerge mergeOriginal; - private LongObjectHashtable myResolvedDts; // maps data type ID -> resolved Data type - private LongObjectHashtable origResolvedDts; + private Map myResolvedDts; // maps data type ID -> resolved Data type + private Map origResolvedDts; /** * Manages code unit changes and conflicts between the latest versioned @@ -147,9 +147,9 @@ class CodeUnitMerger extends AbstractListingMerger { mergeLatest = listingMergeMgr.mergeLatest; mergeOriginal = listingMergeMgr.mergeOriginal; - myResolvedDts = (LongObjectHashtable) mergeManager.getResolveInformation( + myResolvedDts = (Map) mergeManager.getResolveInformation( MergeConstants.RESOLVED_MY_DTS); - origResolvedDts = (LongObjectHashtable) mergeManager.getResolveInformation( + origResolvedDts = (Map) mergeManager.getResolveInformation( MergeConstants.RESOLVED_ORIGINAL_DTS); mergedCodeUnits = new AddressSet(); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalFunctionMerger.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalFunctionMerger.java index 16b29573bc..b857f93066 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalFunctionMerger.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/ExternalFunctionMerger.java @@ -36,7 +36,8 @@ import ghidra.program.model.mem.MemoryAccessException; import ghidra.program.model.symbol.*; import ghidra.program.util.*; import ghidra.util.*; -import ghidra.util.datastruct.*; +import ghidra.util.datastruct.LongLongHashtable; +import ghidra.util.datastruct.ObjectIntHashtable; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; @@ -454,11 +455,11 @@ public class ExternalFunctionMerger extends AbstractFunctionMerger implements Li throws ProgramConflictException, MemoryAccessException, CancelledException { if (mergeManager != null) { - latestResolvedDts = (LongObjectHashtable) mergeManager.getResolveInformation( + latestResolvedDts = (Map) mergeManager.getResolveInformation( MergeConstants.RESOLVED_LATEST_DTS); - myResolvedDts = (LongObjectHashtable) mergeManager.getResolveInformation( + myResolvedDts = (Map) mergeManager.getResolveInformation( MergeConstants.RESOLVED_MY_DTS); - origResolvedDts = (LongObjectHashtable) mergeManager.getResolveInformation( + origResolvedDts = (Map) mergeManager.getResolveInformation( MergeConstants.RESOLVED_ORIGINAL_DTS); latestResolvedSymbols = (LongLongHashtable) mergeManager.getResolveInformation( @@ -1816,8 +1817,9 @@ public class ExternalFunctionMerger extends AbstractFunctionMerger implements Li } if (originalImportedName != null) { try { - resultExternalLocation.getSymbol().setNameAndNamespace(externalLocation.getLabel(), - resolvedNamespace, externalLocation.getSource()); + resultExternalLocation.getSymbol() + .setNameAndNamespace(externalLocation.getLabel(), + resolvedNamespace, externalLocation.getSource()); } catch (CircularDependencyException e) { throw new AssertException(e); @@ -2141,13 +2143,15 @@ public class ExternalFunctionMerger extends AbstractFunctionMerger implements Li } // If we have a function variable storage choice then a "Use For All" has already occurred. if (variableStorageChoice != ASK_USER) { - for (Pair, List> pair : variableStorageConflicts.getOverlappingVariables()) { + for (Pair, List> pair : variableStorageConflicts + .getOverlappingVariables()) { monitor.checkCanceled(); mergeVariableStorage(functions, pair, variableStorageChoice, monitor); } } else if (askUser && mergeManager != null) { - for (Pair, List> pair : variableStorageConflicts.getOverlappingVariables()) { + for (Pair, List> pair : variableStorageConflicts + .getOverlappingVariables()) { monitor.checkCanceled(); boolean useForAll = (variableStorageChoice != ASK_USER); if (useForAll) { @@ -2164,7 +2168,8 @@ public class ExternalFunctionMerger extends AbstractFunctionMerger implements Li } } else { - for (Pair, List> pair : variableStorageConflicts.getOverlappingVariables()) { + for (Pair, List> pair : variableStorageConflicts + .getOverlappingVariables()) { monitor.checkCanceled(); mergeVariableStorage(functions, pair, currentConflictOption, monitor); } diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/FunctionMerger.java b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/FunctionMerger.java index 6a0cf86765..88dcf95739 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/FunctionMerger.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/merge/listing/FunctionMerger.java @@ -37,7 +37,6 @@ import ghidra.program.model.symbol.Namespace; import ghidra.program.util.*; import ghidra.util.Msg; import ghidra.util.SystemUtilities; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; @@ -213,11 +212,11 @@ class FunctionMerger extends AbstractFunctionMerger implements ListingMerger { public void autoMerge(int progressMin, int progressMax, TaskMonitor monitor) throws ProgramConflictException, MemoryAccessException, CancelledException { - latestResolvedDts = (LongObjectHashtable) mergeManager.getResolveInformation( + latestResolvedDts = (Map) mergeManager.getResolveInformation( MergeConstants.RESOLVED_LATEST_DTS); - myResolvedDts = (LongObjectHashtable) mergeManager.getResolveInformation( + myResolvedDts = (Map) mergeManager.getResolveInformation( MergeConstants.RESOLVED_MY_DTS); - origResolvedDts = (LongObjectHashtable) mergeManager.getResolveInformation( + origResolvedDts = (Map) mergeManager.getResolveInformation( MergeConstants.RESOLVED_ORIGINAL_DTS); initializeAutoMerge("Auto-merging Functions and determining conflicts.", progressMin, @@ -999,13 +998,15 @@ class FunctionMerger extends AbstractFunctionMerger implements ListingMerger { } // If we have a function variable storage choice then a "Use For All" has already occurred. if (variableStorageChoice != ASK_USER) { - for (Pair, List> pair : variableStorageConflicts.getOverlappingVariables()) { + for (Pair, List> pair : variableStorageConflicts + .getOverlappingVariables()) { monitor.checkCanceled(); mergeVariableStorage(addr, pair, variableStorageChoice, monitor); } } else if (askUser && mergeManager != null) { - for (Pair, List> pair : variableStorageConflicts.getOverlappingVariables()) { + for (Pair, List> pair : variableStorageConflicts + .getOverlappingVariables()) { monitor.checkCanceled(); boolean useForAll = (variableStorageChoice != ASK_USER); if (useForAll) { @@ -1022,7 +1023,8 @@ class FunctionMerger extends AbstractFunctionMerger implements ListingMerger { } } else { - for (Pair, List> pair : variableStorageConflicts.getOverlappingVariables()) { + for (Pair, List> pair : variableStorageConflicts + .getOverlappingVariables()) { monitor.checkCanceled(); mergeVariableStorage(addr, pair, currentConflictOption, monitor); } @@ -1355,8 +1357,10 @@ class FunctionMerger extends AbstractFunctionMerger implements ListingMerger { protected void mergeParameters(Address entryPtAddress, int chosenConflictOption, TaskMonitor monitor) { Function resultFunction = - listingMergeManager.mergeLatest.getResultProgram().getFunctionManager().getFunctionAt( - entryPtAddress); + listingMergeManager.mergeLatest.getResultProgram() + .getFunctionManager() + .getFunctionAt( + entryPtAddress); if (resultFunction == null) { return; } @@ -1878,7 +1882,8 @@ class FunctionMerger extends AbstractFunctionMerger implements ListingMerger { if (function1.getStackPurgeSize() != function2.getStackPurgeSize()) { return false; } - if (function1.getStackFrame().getReturnAddressOffset() != function2.getStackFrame().getReturnAddressOffset()) { + if (function1.getStackFrame().getReturnAddressOffset() != function2.getStackFrame() + .getReturnAddressOffset()) { return false; } if (!function1.getCallingConventionName().equals(function2.getCallingConventionName())) { diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/match/MatchFunctions.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/match/MatchFunctions.java index 0cd72b209c..23d82e8c0d 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/match/MatchFunctions.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/match/MatchFunctions.java @@ -15,16 +15,14 @@ */ package ghidra.app.plugin.match; +import java.util.*; + import ghidra.program.model.address.Address; import ghidra.program.model.address.AddressSetView; import ghidra.program.model.listing.*; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.exception.CancelledException; import ghidra.util.task.TaskMonitor; -import java.util.ArrayList; -import java.util.List; - /** * This class does the work of matching subroutines. Every subroutine * in the current program is hashed and the start address is put into a @@ -44,12 +42,13 @@ public class MatchFunctions { boolean includeOneToOne, boolean includeNonOneToOne, FunctionHasher hasher, TaskMonitor monitor) throws CancelledException { - LongObjectHashtable functionHashes = new LongObjectHashtable(); + Map functionHashes = new HashMap<>(); List functionMatches = new ArrayList(); FunctionIterator aProgfIter = aProgram.getFunctionManager().getFunctions(setA, true); FunctionIterator bProgfIter = bProgram.getFunctionManager().getFunctions(setB, true); monitor.setIndeterminate(false); - monitor.initialize(2 * (aProgram.getFunctionManager().getFunctionCount() + bProgram.getFunctionManager().getFunctionCount())); + monitor.initialize(2 * (aProgram.getFunctionManager().getFunctionCount() + + bProgram.getFunctionManager().getFunctionCount())); monitor.setMessage("Hashing functions in " + aProgram.getName()); // Hash functions in program A @@ -73,17 +72,15 @@ public class MatchFunctions { //Find the remaining hash matches ---> unique code match left and THERE is no symbol that matches //in the other program. - long[] keys = functionHashes.getKeys(); final long progress = monitor.getProgress(); - monitor.setMaximum(progress + keys.length); + monitor.setMaximum(progress + functionHashes.size()); monitor.setProgress(progress); monitor.setMessage("Finding function matches"); - for (int i = 0; i < keys.length; i++) { + for (Match match : functionHashes.values()) { monitor.incrementProgress(1); if (monitor.isCancelled()) { break; } - Match match = functionHashes.get(keys[i]); ArrayList
aProgAddrs = match.aAddresses; ArrayList
bProgAddrs = match.bAddresses; if ((includeOneToOne && aProgAddrs.size() == 1 && bProgAddrs.size() == 1) || @@ -103,15 +100,17 @@ public class MatchFunctions { } public static List matchOneFunction(Program aProgram, Address aEntryPoint, - Program bProgram, FunctionHasher hasher, TaskMonitor monitor) throws CancelledException { + Program bProgram, FunctionHasher hasher, TaskMonitor monitor) + throws CancelledException { return matchOneFunction(aProgram, aEntryPoint, bProgram, null, hasher, monitor); } // Finds all matches in program B to the function in Program A public static List matchOneFunction(Program aProgram, Address aEntryPoint, - Program bProgram, AddressSetView bAddressSet, FunctionHasher hasher, TaskMonitor monitor) + Program bProgram, AddressSetView bAddressSet, FunctionHasher hasher, + TaskMonitor monitor) throws CancelledException { - LongObjectHashtable functionHashes = new LongObjectHashtable(); + Map functionHashes = new HashMap<>(); List functionMatches = new ArrayList(); Function aFunc = aProgram.getFunctionManager().getFunctionContaining(aEntryPoint); @@ -131,12 +130,12 @@ public class MatchFunctions { //Find the remaining hash matches ---> unique code match left and THERE is no symbol that matches //in the other program. - long[] keys = functionHashes.getKeys(); - for (int i = 0; i < keys.length; i++) { + List keys = new ArrayList<>(functionHashes.keySet()); + for (long key : keys) { if (monitor.isCancelled()) { break; } - Match match = functionHashes.get(keys[i]); + Match match = functionHashes.get(key); ArrayList
aProgAddrs = match.aAddresses; ArrayList
bProgAddrs = match.bAddresses; @@ -149,7 +148,7 @@ public class MatchFunctions { "Code Only Match"); functionMatches.add(functionMatch); } - functionHashes.remove(keys[i]); + functionHashes.remove(key); } } @@ -157,7 +156,7 @@ public class MatchFunctions { } private static void hashFunction(TaskMonitor monitor, - LongObjectHashtable functionHashes, Function function, FunctionHasher hasher, + Map functionHashes, Function function, FunctionHasher hasher, boolean isProgA) throws CancelledException { long hash = hasher.hash(function, monitor); diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/RMIClassServer.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/RMIClassServer.java index 1a5826db36..ad40542b38 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/RMIClassServer.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/RMIClassServer.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,13 +15,13 @@ */ package ghidra.server.remote; -import ghidra.util.Msg; - import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; +import ghidra.util.Msg; + /** * RMIClassServer provides a server for serializing classes to an * RMI client as needed. This implementation starts a new listener thread each diff --git a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/db/AssociationDatabaseManager.java b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/db/AssociationDatabaseManager.java index 87f8afa5ae..b4d30f525a 100644 --- a/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/db/AssociationDatabaseManager.java +++ b/Ghidra/Features/VersionTracking/src/main/java/ghidra/feature/vt/api/db/AssociationDatabaseManager.java @@ -479,7 +479,7 @@ public class AssociationDatabaseManager implements VTAssociationManager { if (status == ACCEPTED) { associationDB.setStatus(AVAILABLE); - associationCache.invalidate(associationDB.getKey()); + associationDB.setInvalid(); unblockRelatedAssociations(associationDB); for (AssociationHook hook : associationHooks) { hook.associationCleared(associationDB); @@ -545,7 +545,7 @@ public class AssociationDatabaseManager implements VTAssociationManager { case AVAILABLE: throw new AssertException("Attempted to unblock a non-blocked association!"); case BLOCKED: - associationCache.invalidate(relatedAssociation.getKey()); + relatedAssociation.setInvalid(); relatedAssociation.setStatus(computeBlockedStatus(relatedAssociation)); break; case REJECTED: diff --git a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/CheckoutManager.java b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/CheckoutManager.java index 3444220edc..d9b3349cde 100644 --- a/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/CheckoutManager.java +++ b/Ghidra/Framework/FileSystem/src/main/java/ghidra/framework/store/local/CheckoutManager.java @@ -23,7 +23,6 @@ import org.jdom.input.SAXBuilder; import org.jdom.output.XMLOutputter; import ghidra.framework.store.*; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.xml.GenericXMLOutputter; import ghidra.util.xml.XmlUtilities; @@ -40,7 +39,7 @@ class CheckoutManager { private long nextCheckoutId = 1; // checkouts maps long checkoutId to ItemCheckoutStatus objects - private LongObjectHashtable checkouts; + private Map checkouts; /** * Constructor. @@ -53,7 +52,7 @@ class CheckoutManager { CheckoutManager(LocalFolderItem item, boolean create) throws IOException { this.item = item; if (create) { - checkouts = new LongObjectHashtable(); + checkouts = new HashMap<>(); writeCheckoutsFile(); } } @@ -164,8 +163,7 @@ class CheckoutManager { */ synchronized boolean isCheckedOut(int version) throws IOException { validate(); - long[] ids = checkouts.getKeys(); - for (long id : ids) { + for (long id : checkouts.keySet()) { ItemCheckoutStatus coStatus = checkouts.get(id); if (coStatus.getCheckoutVersion() == version) { return true; @@ -199,13 +197,9 @@ class CheckoutManager { */ synchronized ItemCheckoutStatus[] getAllCheckouts() throws IOException { validate(); - long[] ids = checkouts.getKeys(); - Arrays.sort(ids); - ItemCheckoutStatus[] list = new ItemCheckoutStatus[ids.length]; - for (int i = 0; i < ids.length; i++) { - list[i] = checkouts.get(ids[i]); - } - return list; + List list = new ArrayList<>(checkouts.values()); + Collections.sort(list, (a, b) -> (int) (a.getCheckoutId() - b.getCheckoutId())); + return list.toArray(new ItemCheckoutStatus[list.size()]); } /** @@ -219,7 +213,6 @@ class CheckoutManager { checkouts = null; } if (checkouts == null) { - LongObjectHashtable oldCheckouts = checkouts; long oldNextCheckoutId = nextCheckoutId; boolean success = false; try { @@ -229,7 +222,7 @@ class CheckoutManager { finally { if (!success) { nextCheckoutId = oldNextCheckoutId; - checkouts = oldCheckouts; + checkouts = null; } } } @@ -243,7 +236,7 @@ class CheckoutManager { @SuppressWarnings("unchecked") private void readCheckoutsFile() throws IOException { - checkouts = new LongObjectHashtable(); + checkouts = new HashMap<>(); File checkoutsFile = getCheckoutsFile(); if (!checkoutsFile.exists()) { @@ -317,8 +310,7 @@ class CheckoutManager { Element root = new Element("CHECKOUT_LIST"); root.setAttribute("NEXT_ID", Long.toString(nextCheckoutId)); - long[] ids = checkouts.getKeys(); - for (long id : ids) { + for (long id : checkouts.keySet()) { ItemCheckoutStatus coStatus = checkouts.get(id); // TRANSIENT checkout data must not be persisted - the existence // of such checkouts is retained in-memory only diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/datastruct/ObjectCache.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/datastruct/ObjectCache.java index 35efddd260..0966e551a1 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/datastruct/ObjectCache.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/datastruct/ObjectCache.java @@ -15,10 +15,9 @@ */ package ghidra.util.datastruct; - import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; -import java.util.LinkedList; +import java.util.*; /** * ObjectClass provides a fixed-size long-key-based object cache. @@ -30,23 +29,23 @@ import java.util.LinkedList; * an object in the weak cache. */ public class ObjectCache { - - private LongObjectHashtable hashTable; + + private Map> hashTable; private ReferenceQueue refQueue; private LinkedList hardCache; private int hardCacheSize; - + /** * Construct a keyed-object cache of size hardCacheSize. * @param hardCacheSize hard cache size. */ public ObjectCache(int hardCacheSize) { this.hardCacheSize = hardCacheSize; - hashTable = new LongObjectHashtable<>(); + hashTable = new HashMap<>(); refQueue = new ReferenceQueue(); hardCache = new LinkedList(); } - + /** * Determine if the keyed-object exists in the cache. * @param key object key @@ -54,34 +53,35 @@ public class ObjectCache { */ public synchronized boolean contains(long key) { processQueue(); - return hashTable.contains(key); + return hashTable.containsKey(key); } - + /** * Get the object from cache which corresponds to the specified key. * @param key object key * @return cached object */ public synchronized Object get(long key) { - WeakReference ref = (WeakReference)hashTable.get(key); + WeakReference ref = hashTable.get(key); if (ref != null) { Object obj = ref.get(); if (obj == null) { hashTable.remove(key); } addToHardCache(obj); - return obj; + return obj; } return null; } - + /** * Return the hard cache size + * @return the hard cache size */ public int size() { return hardCacheSize; } - + /** * Adjust the hard cache size * @param size new hard cache size @@ -92,7 +92,7 @@ public class ObjectCache { } this.hardCacheSize = size; } - + /** * Add an object to the cache * @param key object key @@ -111,16 +111,14 @@ public class ObjectCache { */ public synchronized void clear() { processQueue(); - long[] keys = hashTable.getKeys(); - for ( long element : keys ) { - KeyedSoftReference ref = (KeyedSoftReference)hashTable.get(element); + for (KeyedSoftReference ref : hashTable.values()) { ref.clear(); } - - hashTable.removeAll(); + + hashTable.clear(); refQueue = new ReferenceQueue(); } - + /** * Remove the specified range of keyed objects from both hard and weak caches. * A cache range should be cleared when the corresponding objects have become invalid. @@ -128,21 +126,16 @@ public class ObjectCache { * @param endKey maximum object key value */ public synchronized void remove(long startKey, long endKey) { - if ((endKey>>1)-(startKey>>1) < (hashTable.size()>>1)) { - for(long i=startKey;i<=endKey;i++) { + if ((endKey >> 1) - (startKey >> 1) < (hashTable.size() >> 1)) { + for (long i = startKey; i <= endKey; i++) { remove(i); } } else { - long[] keys = hashTable.getKeys(); - for ( long element : keys ) { - if (element >= startKey && element <= endKey) { - remove(element); - } - } + hashTable.keySet().removeIf(key -> (key >= startKey && key <= endKey)); } } - + /** * Remove the specified keyed object from both hard and weak caches. * An object should be removed from the cache when it becomes invalid. @@ -150,13 +143,13 @@ public class ObjectCache { */ public synchronized void remove(long key) { processQueue(); - KeyedSoftReference ref = (KeyedSoftReference)hashTable.get(key); + KeyedSoftReference ref = hashTable.get(key); if (ref != null) { ref.clear(); hashTable.remove(key); } } - + /** * Add the specified object to the hard cache. * @param obj object @@ -167,23 +160,23 @@ public class ObjectCache { hardCache.removeFirst(); } } - + /** * Cleanup weak cache */ private void processQueue() { KeyedSoftReference ref; - while((ref = (KeyedSoftReference)refQueue.poll()) != null) { - hashTable.remove(ref.getKey()); + while ((ref = (KeyedSoftReference) refQueue.poll()) != null) { + hashTable.remove(ref.getKey()); } } - + /** * Provides a weak wrapper for a keyed-object */ private class KeyedSoftReference extends WeakReference { private long key; - + /** * Construct a keyed-object reference * @param key object key @@ -194,13 +187,14 @@ public class ObjectCache { super(obj, queue); this.key = key; } - + /** * Return object key + * @return object key */ long getKey() { return key; } } - + } diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/datastruct/SoftCacheLongKeyMap.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/datastruct/SoftCacheLongKeyMap.java deleted file mode 100644 index ea9e4e3a10..0000000000 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/datastruct/SoftCacheLongKeyMap.java +++ /dev/null @@ -1,163 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.util.datastruct; - -import java.lang.ref.ReferenceQueue; -import java.lang.ref.SoftReference; - -/** - * Soft reference cache class that caches objects for long keys. This cache will - * store at most "cacheSize" number of entries, but since it uses soft references - * for the cached values, those object may be reclaimed. - */ - -public class SoftCacheLongKeyMap { - private int cacheSize; - private ReferenceQueue refQueue; - private Entry head; - private LongObjectHashtable map; - - /** - * Construct a new SoftCacheLongKeyMap that caches at most cacheSize number of entries - * @param cacheSize the max number of entries to cache. - */ - public SoftCacheLongKeyMap(int cacheSize) { - this.cacheSize = Math.max(cacheSize, 10); - map = new LongObjectHashtable<>(); - head = new Entry(0, null); - head.nextEntry = head; - head.prevEntry = head; - refQueue = new ReferenceQueue<>(); - } - /** - * Caches the given value for the given key - * @param key the key - * @param value the cached value for the given key - * @return any previous object that is cached for the given key. - */ - public Object put(long key, Object value) { - processQueue(); - if (map.size() == cacheSize) { - remove(head.nextEntry.key); - } - Object obj = map.remove(key); - Entry entry = new Entry(key, value); - head.addBefore(entry); - map.put(key, entry); - return obj; - } - - /** - * Returns the cached value for the given key, if it exists. - * @param key the key for which to get a cached value. - * @return the object that was cached for that key, or null if none exists. - */ - public Object get(long key) { - processQueue(); - Entry entry = (Entry)map.get(key); - if (entry != null) { - entry.delete(); - head.addBefore(entry); - return entry.get(); - } - return null; - } - - /** - * Returns the number of items in the cache. Can change from one call to - * the next even if no entries were added or deleted. - */ - public int size() { - processQueue(); - return map.size(); - } - - /** - * Removes all entries from the cache - */ - public void clear() { - map.removeAll(); - refQueue = new ReferenceQueue<>(); - } - - /** - * Returns true if the cache is empty. If true, it will remain empty until a new - * entry is added. However if false, it may return true even if nothing was removed - */ - public boolean isEmpty() { - processQueue(); - return map.size() == 0; - } - /** - * Returns true if the cache currently contains the given key. Not useful since even - * if it returns true, there is no guarentee that a get will work after containsKey - * returns true. - * @param key the Key to check - */ - public boolean containsKey(long key) { - processQueue(); - return map.contains(key); - } - - /** - * Removes any cached value for the given key. - * @param key the key for which to remove cached values. - * @return the cached object that was stored for the given key, or null - */ - public Object remove(long key) { - Entry entry = (Entry)map.remove(key); - if (entry != null) { - entry.delete(); - return entry.get(); - } - return null; - } - - /** - * Returns a list of all current keys. - */ - public long[] getKeys() { - processQueue(); - return map.getKeys(); - } - private void processQueue() { - Entry entry; - while((entry = (Entry)refQueue.poll()) != null) { - remove(entry.key); - } - } - - class Entry extends SoftReference { - long key; - Entry nextEntry; - Entry prevEntry; - Entry(long key, Object value) { - super(value, refQueue); - this.key = key; - } - void addBefore(Entry entry) { - entry.nextEntry = this; - entry.prevEntry = this.prevEntry; - this.prevEntry.nextEntry = entry; - this.prevEntry = entry; - } - void delete() { - prevEntry.nextEntry = nextEntry; - nextEntry.prevEntry = prevEntry; - } - } - -} diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/graph/attributes/ObjectAttribute.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/graph/attributes/ObjectAttribute.java index 150fdb6c82..5402fc7be2 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/graph/attributes/ObjectAttribute.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/graph/attributes/ObjectAttribute.java @@ -15,8 +15,9 @@ */ package ghidra.util.graph.attributes; -import ghidra.util.datastruct.LongObjectHashtable; -import ghidra.util.exception.NoValueException; +import java.util.HashMap; +import java.util.Map; + import ghidra.util.graph.KeyIndexableSet; import ghidra.util.graph.KeyedObject; @@ -25,7 +26,7 @@ import ghidra.util.graph.KeyedObject; */ public class ObjectAttribute extends Attribute { //private Object[] values; - private LongObjectHashtable values; + private Map values; private static String attributeType = AttributeManager.OBJECT_TYPE; /** Constructor. @@ -36,7 +37,7 @@ public class ObjectAttribute extends Attribute { public ObjectAttribute(String name, KeyIndexableSet set) { super(name, set); //this.values = new Object[set.capacity()]; - values = new LongObjectHashtable(); + values = new HashMap<>(); } /** Set the value of this attribute for the specified KeyedObject. @@ -93,7 +94,7 @@ public class ObjectAttribute extends Attribute { /** Removes all assigned values of this attribute. */ @Override public void clear() { - values.removeAll(); + values.clear(); } /** Return the attribute of the specified KeyedObject as a String. @@ -101,7 +102,7 @@ public class ObjectAttribute extends Attribute { @Override public String getValueAsString(KeyedObject o) { Object v; - if (values.contains(o.key())) { + if (values.containsKey(o.key())) { v = getValue(o); if (v != null) { return v.toString(); diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/graph/attributes/StringAttribute.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/graph/attributes/StringAttribute.java index 1478f8b404..b0d418782f 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/graph/attributes/StringAttribute.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/graph/attributes/StringAttribute.java @@ -15,20 +15,17 @@ */ package ghidra.util.graph.attributes; -import ghidra.util.datastruct.LongObjectHashtable; -import ghidra.util.exception.NoValueException; +import java.util.*; + import ghidra.util.graph.KeyIndexableSet; import ghidra.util.graph.KeyedObject; -import java.util.Arrays; -import java.util.Comparator; - /** This class provides a storage mechanism for String-valued information about * the elements of a KeyIndexableSet, e.g. the vertices of a DirectedGraph. */ public class StringAttribute extends Attribute { //private String[] values; - private ghidra.util.datastruct.LongObjectHashtable values; + private Map values; private static String attributeType = AttributeManager.STRING_TYPE; /** Constructor. @@ -38,7 +35,7 @@ public class StringAttribute extends Attribute { */ public StringAttribute(String name, KeyIndexableSet set) { super(name, set); - this.values = new LongObjectHashtable(set.capacity());// String[set.capacity()]; + this.values = new HashMap<>(set.capacity());// String[set.capacity()]; } /** Set the value of this attribute for the specified KeyedObject. @@ -49,8 +46,9 @@ public class StringAttribute extends Attribute { * not a member of the owningSet. */ public boolean setValue(T o, String value) { - if (value == null) + if (value == null) { return false; + } if (owningSet().contains(o)) { //values[ owningSet().index( o ) ] = value; values.put(o.key(), value); @@ -66,7 +64,7 @@ public class StringAttribute extends Attribute { public String getValue(KeyedObject o) //throws NoValueException { //return values[ owningSet().index( o ) ]; - return (String) values.get(o.key()); + return values.get(o.key()); } // /** Debug printing. */ @@ -129,8 +127,9 @@ public class StringAttribute extends Attribute { else if ((ko1.key() - ko2.key()) > 0) { return +1; } - else + else { return 0; + } } //ko1 is ok, ko2 fails. return -1; @@ -144,8 +143,9 @@ public class StringAttribute extends Attribute { else if ((ko1.key() - ko2.key()) > 0) { return +1; } - else + else { return 0; + } } } @@ -160,7 +160,7 @@ public class StringAttribute extends Attribute { /** Removes all assigned values of this attribute. */ @Override public void clear() { - values.removeAll(); + values.clear(); } /** Return the attribute of the specified KeyedObject as a String. diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/util/prop/PropertySet.java b/Ghidra/Framework/Generic/src/main/java/ghidra/util/prop/PropertySet.java index 89f5d59267..6c1a132e65 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/util/prop/PropertySet.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/util/prop/PropertySet.java @@ -1,6 +1,5 @@ /* ### * IP: GHIDRA - * REVIEWED: YES * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,39 +15,39 @@ */ package ghidra.util.prop; +import java.io.*; +import java.util.HashMap; +import java.util.Map; + import ghidra.util.LongIterator; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.datastruct.NoSuchIndexException; import ghidra.util.exception.AssertException; import ghidra.util.exception.NoValueException; -import java.io.*; - /** * Base class for managing properties that are accessed by an index. Property * values are determined by the derived class. */ public abstract class PropertySet implements Serializable { - private final static long serialVersionUID = 1; + private final static long serialVersionUID = 1; protected static final NoValueException noValueException = new NoValueException(); - private final static int DEFAULT_NUMBER_PAGE_BITS=12; + private final static int DEFAULT_NUMBER_PAGE_BITS = 12; private final static int MIN_NUMBER_PAGE_BITS = 8; private final static int MAX_NUMBER_PAGE_BITS = 15; // must be kept less than // size of a short - private String name; - protected PropertyPageIndex propertyPageIndex; // table of pageIDs + private String name; + protected PropertyPageIndex propertyPageIndex; // table of pageIDs private int numPageBits; // number of bits from long used as page offset private long pageMask; // a mask for the offset bits, i.e. has a 1 if and only if - // the bit is part of the offset + // the bit is part of the offset protected short pageSize; // max elements in each page - protected int numProperties; - private LongObjectHashtable ht; - private Class objectClass; - + protected int numProperties; + private Map ht; + private Class objectClass; protected PropertySet(String name, Class objectClass) { - this(name, DEFAULT_NUMBER_PAGE_BITS, objectClass); + this(name, DEFAULT_NUMBER_PAGE_BITS, objectClass); } /** @@ -59,22 +58,22 @@ public abstract class PropertySet implements Serializable { * more than 15. */ protected PropertySet(String name, int numPageBits, Class objectClass) { - this.objectClass = objectClass; - ht = new LongObjectHashtable(); + this.objectClass = objectClass; + ht = new HashMap<>(); this.name = name; - if(numPageBits > MAX_NUMBER_PAGE_BITS) { + if (numPageBits > MAX_NUMBER_PAGE_BITS) { numPageBits = MAX_NUMBER_PAGE_BITS; } - else if(numPageBits < MIN_NUMBER_PAGE_BITS) { + else if (numPageBits < MIN_NUMBER_PAGE_BITS) { numPageBits = MIN_NUMBER_PAGE_BITS; } this.numPageBits = numPageBits; // compute the page mask pageMask = -1L; - pageMask = pageMask >>> (64-numPageBits); // 64 = size of long + pageMask = pageMask >>> (64 - numPageBits); // 64 = size of long - pageSize = (short)(pageMask + 1); + pageSize = (short) (pageMask + 1); propertyPageIndex = new PropertyPageIndex(); } @@ -84,15 +83,15 @@ public abstract class PropertySet implements Serializable { * @return the size (in bytes) of the data that is stored in this property * set. */ - public abstract int getDataSize(); - - /** + public abstract int getDataSize(); + + /** * Get the name for this property manager. */ public synchronized String getName() { return name; } - + /** * Returns property object class associated with this set. */ @@ -100,19 +99,19 @@ public abstract class PropertySet implements Serializable { return objectClass; } - protected PropertyPage getPage(long pageId) { - return ht.get(pageId); - } - - protected PropertyPage getOrCreatePage(long pageID) { - PropertyPage page = getPage(pageID); - if(page == null) { - page = new PropertyPage(pageSize,pageID,getDataSize(),objectClass); - ht.put(pageID,page); + protected PropertyPage getPage(long pageId) { + return ht.get(pageId); + } + + protected PropertyPage getOrCreatePage(long pageID) { + PropertyPage page = getPage(pageID); + if (page == null) { + page = new PropertyPage(pageSize, pageID, getDataSize(), objectClass); + ht.put(pageID, page); propertyPageIndex.add(pageID); } - return page; - } + return page; + } /** * Given two indices it indicates whether there is an index in @@ -123,21 +122,22 @@ public abstract class PropertySet implements Serializable { * @return boolean true if at least one index in the range * has the property, false otherwise. */ - public boolean intersects(long start,long end) { - if (hasProperty(start)) { - return true; - } - try { - long index = this.getNextPropertyIndex(start); - if (index <= end) { - return true; - } - } - catch(NoSuchIndexException e) { - return false; - } - return false; + public boolean intersects(long start, long end) { + if (hasProperty(start)) { + return true; + } + try { + long index = this.getNextPropertyIndex(start); + if (index <= end) { + return true; + } + } + catch (NoSuchIndexException e) { + return false; + } + return false; } + /** * Removes all property values within a given range. * @param start begin range @@ -147,23 +147,23 @@ public abstract class PropertySet implements Serializable { */ public synchronized boolean removeRange(long start, long end) { - boolean status=false; - // go from start to end - // get the page starting at start - // get page start index and end index - // subtract page.getSize() from numProperties - // remove the entire page - // increment start by size of page - // else - // for (i= 0) { + if (nextOffset >= 0) { return getIndex(pageID, nextOffset); } } pageID = propertyPageIndex.getNext(pageID); - if(pageID >= 0) { + if (pageID >= 0) { page = getPage(pageID); - if(page != null) { + if (page != null) { short nextOffset = page.getFirst(); - if (nextOffset < 0) { - throw new AssertException( - "Page (" + pageID + - ") exists but there is no 'first' offset"); - } + if (nextOffset < 0) { + throw new AssertException( + "Page (" + pageID + + ") exists but there is no 'first' offset"); + } return getIndex(pageID, nextOffset); } } - throw NoSuchIndexException.noSuchIndexException; + throw NoSuchIndexException.noSuchIndexException; } /** @@ -295,36 +296,37 @@ public abstract class PropertySet implements Serializable { PropertyPage page = getPage(pageID); - if(page != null) { + if (page != null) { short prevOffset = page.getPrevious(offset); - if(prevOffset >= 0) { + if (prevOffset >= 0) { return getIndex(pageID, prevOffset); } } pageID = propertyPageIndex.getPrevious(pageID); - if(pageID >= 0) { + if (pageID >= 0) { page = getPage(pageID); - if(page != null) { + if (page != null) { short prevOffset = page.getLast(); - if (prevOffset < 0) { - throw new AssertException( - "Page (" + pageID + - ") exists but there is no 'last' offset"); - } + if (prevOffset < 0) { + throw new AssertException( + "Page (" + pageID + + ") exists but there is no 'last' offset"); + } return getIndex(pageID, prevOffset); } } - throw NoSuchIndexException.noSuchIndexException; + throw NoSuchIndexException.noSuchIndexException; } + /** * Get the first index where a property value exists. * @throws NoSuchIndexException when there is no property value for any index. */ public synchronized long getFirstPropertyIndex() throws NoSuchIndexException { - if(hasProperty(0)) { + if (hasProperty(0)) { return 0; } return getNextPropertyIndex(0); @@ -337,18 +339,19 @@ public abstract class PropertySet implements Serializable { */ public synchronized long getLastPropertyIndex() throws NoSuchIndexException { // -1 should be the highest possible address - if(hasProperty(-1)) { + if (hasProperty(-1)) { return -1; } return getPreviousPropertyIndex(-1); } + /** * Get the number of properties in the set. * @return the number of properties */ - public int getSize() { - return numProperties; - } + public int getSize() { + return numProperties; + } /** * Extract the page ID from the given index. @@ -364,7 +367,7 @@ public abstract class PropertySet implements Serializable { * @param index the long representation of an address. */ protected final short getPageOffset(long index) { - return(short)(index & pageMask); + return (short) (index & pageMask); } /** @@ -372,9 +375,9 @@ public abstract class PropertySet implements Serializable { * @return the long representation of an address. */ protected final long getIndex(long pageID, short offset) { - return(pageID << numPageBits) | offset; + return (pageID << numPageBits) | offset; } - + /** * Move the range of properties to the newStart index. * @param start the beginning of the property range to move @@ -382,48 +385,50 @@ public abstract class PropertySet implements Serializable { * @param newStart the new beginning of the property range after the move */ public void moveRange(long start, long end, long newStart) { - if (newStart < start) { - long clearSize = end-start+1; - long offset = start - newStart; - if (offset < clearSize) { - clearSize = offset; - } - removeRange(newStart, newStart+clearSize-1); - LongIterator it = getPropertyIterator(start, end); - while(it.hasNext()) { - long index = it.next(); - moveIndex(index, index-offset); - } - } - else { - long clearSize = end-start+1; - long offset = newStart - start; - if (offset < clearSize) { - clearSize = offset; - } - if (newStart > end) { - removeRange(newStart, newStart+clearSize-1); - } - else { - removeRange(end+1, end+clearSize); - } + if (newStart < start) { + long clearSize = end - start + 1; + long offset = start - newStart; + if (offset < clearSize) { + clearSize = offset; + } + removeRange(newStart, newStart + clearSize - 1); + LongIterator it = getPropertyIterator(start, end); + while (it.hasNext()) { + long index = it.next(); + moveIndex(index, index - offset); + } + } + else { + long clearSize = end - start + 1; + long offset = newStart - start; + if (offset < clearSize) { + clearSize = offset; + } + if (newStart > end) { + removeRange(newStart, newStart + clearSize - 1); + } + else { + removeRange(end + 1, end + clearSize); + } - LongIterator it = getPropertyIterator(end+1); - while(it.hasPrevious()) { - long index = it.previous(); - if (index < start) { - break; - } - moveIndex(index, index+offset); - } - } - } + LongIterator it = getPropertyIterator(end + 1); + while (it.hasPrevious()) { + long index = it.previous(); + if (index < start) { + break; + } + moveIndex(index, index + offset); + } + } + } protected abstract void moveIndex(long from, long to); - protected abstract void saveProperty(ObjectOutputStream oos, long addr) - throws IOException; - protected abstract void restoreProperty(ObjectInputStream ois, long addr) - throws IOException, ClassNotFoundException; + + protected abstract void saveProperty(ObjectOutputStream oos, long addr) + throws IOException; + + protected abstract void restoreProperty(ObjectInputStream ois, long addr) + throws IOException, ClassNotFoundException; /** * Creates an iterator over all the indexes that have this property within @@ -433,10 +438,10 @@ public abstract class PropertySet implements Serializable { * @param end The end address to search * @return LongIterator Iterator over indexes that have properties. */ - public LongIterator getPropertyIterator(long start,long end) { + public LongIterator getPropertyIterator(long start, long end) { return new LongIteratorImpl(this, start, end); } - + /** * Creates an iterator over all the indexes that have this property within * the given range. @@ -451,6 +456,7 @@ public abstract class PropertySet implements Serializable { public LongIterator getPropertyIterator(long start, long end, boolean atStart) { return new LongIteratorImpl(this, start, end, atStart); } + /** * Returns an iterator over the indices having the given property * value. @@ -478,7 +484,6 @@ public abstract class PropertySet implements Serializable { return new LongIteratorImpl(this, start, before); } - /** * Saves all property values between start and end to the output stream * @param oos the output stream @@ -487,15 +492,15 @@ public abstract class PropertySet implements Serializable { * @throws IOException if an I/O error occurs on the write. */ public void saveProperties(ObjectOutputStream oos, long start, long end) - throws IOException{ + throws IOException { - oos.writeLong(start); - oos.writeLong(end); - if (hasProperty(start)) { + oos.writeLong(start); + oos.writeLong(end); + if (hasProperty(start)) { oos.writeByte(1); oos.writeLong(start); saveProperty(oos, start); - } + } try { long index = start; while ((index = getNextPropertyIndex(index)) <= end) { @@ -504,10 +509,11 @@ public abstract class PropertySet implements Serializable { saveProperty(oos, index); } } - catch(NoSuchIndexException e) {} + catch (NoSuchIndexException e) { + } oos.writeByte(0); } - + /** * Restores all the properties from the input stream. Any existing * properties will first be removed. @@ -516,56 +522,22 @@ public abstract class PropertySet implements Serializable { * @throws ClassNotFoundException if the a class cannot be determined for * the property value. */ - public void restoreProperties(ObjectInputStream ois) throws - IOException, ClassNotFoundException { - long start = ois.readLong(); - long end = ois.readLong(); - this.removeRange(start,end); - while(ois.readByte() != 0) { + public void restoreProperties(ObjectInputStream ois) + throws IOException, ClassNotFoundException { + long start = ois.readLong(); + long end = ois.readLong(); + this.removeRange(start, end); + while (ois.readByte() != 0) { long index = ois.readLong(); restoreProperty(ois, index); } } - - /** - * Saves all properties to the given output stream. - * @param out the output stream. - * @throws IOException I/O error occurs while writing output. - */ - public void saveAll(ObjectOutputStream out) throws IOException { - out.writeObject(name); - out.writeObject(propertyPageIndex); - out.writeInt(numPageBits); - out.writeLong(pageMask); - out.writeShort(pageSize); - out.writeInt(numProperties); - out.writeObject(ht); - out.writeObject(objectClass); - } /** - * Restores all properties values from the input stream. - * @param in the input stream. - * @throws IOException if I/O error occurs while reading from stream. - * @throws ClassNotFoundException if the a class cannot be determined for - * the property value. - */ - @SuppressWarnings("unchecked") // the type must match or it is a bug - public void restoreAll(ObjectInputStream in) throws IOException, ClassNotFoundException { - name = (String)in.readObject(); - propertyPageIndex = (PropertyPageIndex)in.readObject(); - numPageBits = in.readInt(); - pageMask = in.readLong(); - pageSize = in.readShort(); - numProperties = in.readInt(); - ht = (LongObjectHashtable) in.readObject(); - objectClass = (Class)in.readObject(); - } - /** - * Based upon the type of property manager that this is, the appropriate - * visit() method will be called within the PropertyVisitor. - * @param visitor object implementing the PropertyVisitor interface. - * @param addr the address of where to visit (get) the property. + * Based upon the type of property manager that this is, the appropriate + * visit() method will be called within the PropertyVisitor. + * @param visitor object implementing the PropertyVisitor interface. + * @param addr the address of where to visit (get) the property. */ public abstract void applyValue(PropertyVisitor visitor, long addr); diff --git a/Ghidra/Framework/Generic/src/test/java/ghidra/util/datastruct/SoftCacheLongKeyMapTest.java b/Ghidra/Framework/Generic/src/test/java/ghidra/util/datastruct/SoftCacheLongKeyMapTest.java deleted file mode 100644 index a81171e5c4..0000000000 --- a/Ghidra/Framework/Generic/src/test/java/ghidra/util/datastruct/SoftCacheLongKeyMapTest.java +++ /dev/null @@ -1,108 +0,0 @@ -/* ### - * IP: GHIDRA - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ghidra.util.datastruct; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; - -import org.junit.Test; - -import generic.test.AbstractGenericTest; - -public class SoftCacheLongKeyMapTest extends AbstractGenericTest { - SoftCacheLongKeyMap cache; - - /** - * - */ - public SoftCacheLongKeyMapTest() { - super(); - } - - @Test - public void testMap() { - cache = new SoftCacheLongKeyMap(20); - cache.put(0, "aaa"); - cache.put(1, "bbb"); - cache.put(2, "ccc"); - - assertEquals(3, cache.size()); - assertEquals("aaa", cache.get(0)); - assertEquals("bbb", cache.get(1)); - assertEquals("ccc", cache.get(2)); - } - - @Test - public void testlru() { - cache = new SoftCacheLongKeyMap(10); - cache.put(0, "aaa"); - cache.put(1, "bbb"); - cache.put(2, "ccc"); - cache.put(3, "ddd"); - cache.put(4, "eee"); - cache.put(5, "fff"); - cache.put(6, "ggg"); - cache.put(7, "hhh"); - cache.put(8, "iii"); - cache.put(9, "jjj"); - - assertEquals(10, cache.size()); - cache.put(10, "kkk"); - assertEquals(10, cache.size()); - assertNull(cache.get(0)); - - } - - @Test - public void testlru2() { - cache = new SoftCacheLongKeyMap(10); - cache.put(0, "aaa"); - cache.put(1, "bbb"); - cache.put(2, "ccc"); - cache.put(3, "ddd"); - cache.put(4, "eee"); - cache.put(5, "fff"); - cache.put(6, "ggg"); - cache.put(7, "hhh"); - cache.put(8, "iii"); - cache.put(9, "jjj"); - cache.get(0); - assertEquals(10, cache.size()); - cache.put(10, "kkk"); - assertEquals(10, cache.size()); - assertEquals("aaa", cache.get(0)); - assertNull(cache.get(1)); - } - - @Test - public void testRemove() { - cache = new SoftCacheLongKeyMap(10); - cache.put(0, "aaa"); - cache.put(1, "bbb"); - cache.put(2, "ccc"); - cache.put(3, "ddd"); - cache.remove(1); - cache.remove(0); - cache.remove(3); - cache.remove(2); - assertEquals(0, cache.size()); - cache.put(5, "zzz"); - assertEquals(1, cache.size()); - cache.remove(5); - assertEquals(0, cache.size()); - - } -} diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DBObjectCache.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DBObjectCache.java index b99a9190b2..50b8c914fd 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DBObjectCache.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/DBObjectCache.java @@ -21,7 +21,6 @@ package ghidra.program.database; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; import java.util.*; -import java.util.stream.Collectors; import db.Record; import ghidra.program.model.address.KeyRange; @@ -199,18 +198,21 @@ public class DBObjectCache { * @param keyRanges key ranges to delete */ private void deleteLargeKeyRanges(List keyRanges) { - map.keySet() - .stream() - .filter(key -> keyRangesContain(keyRanges, key)) - .collect(Collectors.toList()) - .forEach(key -> { - KeyedSoftReference ref = map.remove(key); - DatabaseObject obj = ref.get(); - if (obj != null) { - obj.setDeleted(); - ref.clear(); - } - }); + map.values().removeIf(ref -> checkRef(ref, keyRanges)); + } + + private boolean checkRef(KeyedSoftReference ref, List keyRanges) { + long key = ref.getKey(); + if (keyRangesContain(keyRanges, key)) { + DatabaseObject obj = ref.get(); + if (obj != null) { + obj.setDeleted(); + ref.clear(); + } + return true; + } + return false; + } /** @@ -267,27 +269,6 @@ public class DBObjectCache { return invalidateCount; } - /** - * Invalidates a range of objects in the cache. - * @param startKey the first key in the range to invalidate. - * @param endKey the last key in the range to invalidate. - */ - public synchronized void invalidate(long startKey, long endKey) { - processQueue(); - if (endKey - startKey < map.size()) { - for (long i = startKey; i <= endKey; i++) { - doInvalidate(i); - } - } - else { - map.keySet() - .stream() - .filter(key -> (key >= startKey && key <= endKey)) - .collect(Collectors.toList()) - .forEach(key -> doInvalidate(key)); - } - } - /** * Removes the object with the given key from the cache. * @param key the key of the object to remove. @@ -305,25 +286,6 @@ public class DBObjectCache { } } - /** - * Invalidates the object with given key. - * @param key the key of the object to invalidate. - */ - public synchronized void invalidate(long key) { - processQueue(); - doInvalidate(key); - } - - private void doInvalidate(long key) { - KeyedSoftReference ref = map.get(key); - if (ref != null) { - T obj = ref.get(); - if (obj != null) { - obj.setInvalid(); - } - } - } - private void addToHardCache(T obj) { hardCache.addLast(obj); if (hardCache.size() > hardCacheSize) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/OverlaySpaceAdapterDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/OverlaySpaceAdapterDB.java index 1ddb86a3b4..f547f3882a 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/OverlaySpaceAdapterDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/OverlaySpaceAdapterDB.java @@ -16,13 +16,14 @@ package ghidra.program.database; import java.io.IOException; +import java.util.HashMap; +import java.util.Map; import db.*; import ghidra.program.model.address.AddressSpace; import ghidra.program.model.address.OverlayAddressSpace; import ghidra.program.model.lang.Language; import ghidra.program.util.LanguageTranslator; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.exception.AssertException; import ghidra.util.exception.DuplicateNameException; @@ -115,7 +116,7 @@ class OverlaySpaceAdapterDB { } void updateOverlaySpaces(ProgramAddressFactory factory) throws IOException { - LongObjectHashtable map = new LongObjectHashtable<>(); + Map map = new HashMap<>(); for (AddressSpace space : factory.getAllAddressSpaces()) { if (space instanceof OverlayAddressSpace) { OverlayAddressSpace os = (OverlayAddressSpace) space; @@ -162,11 +163,10 @@ class OverlaySpaceAdapterDB { } } if (map.size() != 0) { - long[] keys = map.getKeys(); - for (int i = 0; i < keys.length; i++) { - OverlayAddressSpace space = map.remove(keys[i]); + for (OverlayAddressSpace space : map.values()) { factory.removeOverlaySpace(space.getName()); } + map.clear(); } } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java index bccbcb8563..b470c92ee4 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/data/DataTypeManagerDB.java @@ -39,7 +39,6 @@ import ghidra.program.model.lang.CompilerSpec; import ghidra.util.*; import ghidra.util.classfinder.ClassTranslator; import ghidra.util.datastruct.FixedSizeHashMap; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; @@ -3490,15 +3489,15 @@ abstract public class DataTypeManagerDB implements DataTypeManager { } class IdsToDataTypeMap { - private Map> map = new HashMap<>(); + private Map> map = new HashMap<>(); DataType getDataType(UniversalID sourceID, UniversalID dataTypeID) { if (sourceID == null || sourceID.equals(universalID)) { sourceID = LOCAL_ARCHIVE_UNIVERSAL_ID; } - LongObjectHashtable idMap = map.get(sourceID); + Map idMap = map.get(sourceID); if (idMap == null) { - idMap = new LongObjectHashtable<>(); + idMap = new HashMap<>(); map.put(sourceID, idMap); } DataType dt = idMap.get(dataTypeID.getValue()); @@ -3527,7 +3526,7 @@ abstract public class DataTypeManagerDB implements DataTypeManager { else { sourceID = sourceArchive.getSourceArchiveID(); } - LongObjectHashtable idMap = map.get(sourceID); + Map idMap = map.get(sourceID); if (idMap != null) { idMap.remove(dataTypeID.getValue()); } diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/external/ExternalManagerDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/external/ExternalManagerDB.java index 7860644b69..8ceb260d67 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/external/ExternalManagerDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/external/ExternalManagerDB.java @@ -34,7 +34,6 @@ import ghidra.program.model.symbol.*; import ghidra.program.util.LanguageTranslator; import ghidra.util.Lock; import ghidra.util.Msg; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.exception.*; import ghidra.util.task.TaskMonitor; @@ -122,7 +121,7 @@ public class ExternalManagerDB implements ManagerDB, ExternalManager { monitor.initialize(oldNameAdapter.getRecordCount()); int cnt = 0; - LongObjectHashtable nameMap = new LongObjectHashtable<>(); + Map nameMap = new HashMap<>(); RecordIterator iter = oldNameAdapter.getRecords(); while (iter.hasNext()) { diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/NormalizedAddressSet.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/NormalizedAddressSet.java index 33caf9fa52..ce557e5385 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/NormalizedAddressSet.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/map/NormalizedAddressSet.java @@ -18,7 +18,8 @@ package ghidra.program.database.map; import java.util.*; import ghidra.program.model.address.*; -import ghidra.util.datastruct.*; +import ghidra.util.datastruct.Range; +import ghidra.util.datastruct.SortedRangeList; /** * AddressSetView implementation that handles image base changes. NOTE: THIS IMPLEMENTATION @@ -33,8 +34,7 @@ public class NormalizedAddressSet implements AddressSetView { private AddressMap addrMap; - private LongObjectHashtable baseLists = - new LongObjectHashtable(); + private Map baseLists = new HashMap<>(); private ArrayList bases = new ArrayList(); private Comparator baseComparator = new Comparator() { @@ -108,7 +108,7 @@ public class NormalizedAddressSet implements AddressSetView { * Removes all addresses from this set. */ public void clear() { - baseLists = new LongObjectHashtable(); + baseLists = new HashMap<>(); bases = new ArrayList(); } @@ -251,9 +251,9 @@ public class NormalizedAddressSet implements AddressSetView { @Override public int getNumAddressRanges() { int n = 0; - long[] keys = baseLists.getKeys(); - for (int i = 0; i < keys.length; i++) { - SortedRangeList list = baseLists.get(keys[i]); + + for (long key : baseLists.keySet()) { + SortedRangeList list = baseLists.get(key); n += list.getNumRanges(); } return n; @@ -286,9 +286,8 @@ public class NormalizedAddressSet implements AddressSetView { @Override public long getNumAddresses() { long n = 0; - long[] keys = baseLists.getKeys(); - for (int i = 0; i < keys.length; i++) { - SortedRangeList list = baseLists.get(keys[i]); + for (long key : baseLists.keySet()) { + SortedRangeList list = baseLists.get(key); n += list.getNumValues(); } return n; diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/register/OldProgramContextDB.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/register/OldProgramContextDB.java index c5ca9c777f..04775f39b6 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/register/OldProgramContextDB.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/register/OldProgramContextDB.java @@ -32,9 +32,7 @@ import ghidra.program.model.listing.ProgramContext; import ghidra.program.util.RangeMapAdapter; import ghidra.program.util.RegisterValueStore; import ghidra.util.Lock; -import ghidra.util.datastruct.LongObjectHashtable; import ghidra.util.exception.CancelledException; -import ghidra.util.exception.VersionException; import ghidra.util.task.TaskMonitor; /** @@ -61,7 +59,7 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex * address ranges using the PropertyMap utilities. */ private HashMap registersMap; - private LongObjectHashtable valueMaps; + private Map valueMaps; private Register baseContextRegister; protected Map defaultRegisterValueMap; @@ -88,7 +86,7 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex defaultRegisterValueMap = new HashMap(); registersMap = new HashMap(); - valueMaps = new LongObjectHashtable(); + valueMaps = new HashMap<>(); registerSpaceSize = 0; for (Register register : registers) { @@ -350,7 +348,7 @@ public class OldProgramContextDB implements ProgramContext, DefaultProgramContex public void invalidateCache(boolean all) throws IOException { lock.acquire(); try { - valueMaps.removeAll(); + valueMaps.clear(); } finally { lock.release(); diff --git a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/util/DefaultPropertyMap.java b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/util/DefaultPropertyMap.java index a8a8a6aca3..ceeb18981b 100644 --- a/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/util/DefaultPropertyMap.java +++ b/Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/model/util/DefaultPropertyMap.java @@ -306,29 +306,11 @@ public abstract class DefaultPropertyMap implements PropertyMap { * @throws ClassNotFoundException if the class for the object being * read is not in the class path */ - public void restoreProperties(ObjectInputStream ois) throws IOException, ClassNotFoundException { + public void restoreProperties(ObjectInputStream ois) + throws IOException, ClassNotFoundException { propertyMgr.restoreProperties(ois); } - /** - * Write all properties in the map to the given output stream. - * @throws IOException if there is a problem writing to the stream - */ - public void saveAll(ObjectOutputStream out) throws IOException { - propertyMgr.saveAll(out); - } - - /** - * Restore properties read from the given input stream. - * @param in input stream - * @throws IOException if there is a problem reading from the stream - * @throws ClassNotFoundException if the class for the object being - * read is not in the class path - */ - public void restoreAll(ObjectInputStream in) throws IOException, ClassNotFoundException { - propertyMgr.restoreAll(in); - } - private class AddressPropertyIterator implements AddressIterator { private LongIterator iter; @@ -350,7 +332,8 @@ public abstract class DefaultPropertyMap implements PropertyMap { AddressPropertyIterator(Address start, Address end, boolean forward) { iter = - propertyMgr.getPropertyIterator(addrMap.getKey(start), addrMap.getKey(end), forward); + propertyMgr.getPropertyIterator(addrMap.getKey(start), addrMap.getKey(end), + forward); this.forward = forward; }