diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingModelAdapter.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingModelAdapter.java index 9bf2155da5..1e6d6180e2 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingModelAdapter.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ListingModelAdapter.java @@ -53,16 +53,13 @@ public class ListingModelAdapter implements LayoutModel, ListingModelListener { removeUnviewableAddressRanges(); model.addListener(this); - updateMgr = new SwingUpdateManager(500, 5000, new Runnable() { - @Override - public void run() { - if (!model.isClosed()) { - resetIndexMap(); - for (LayoutModelListener listener : listeners) { - listener.dataChanged(BigInteger.ZERO, addressToIndexMap.getIndexCount()); - } - preferredViewSize = null; + updateMgr = new SwingUpdateManager(500, 5000, () -> { + if (!model.isClosed()) { + resetIndexMap(); + for (LayoutModelListener listener : listeners) { + listener.dataChanged(BigInteger.ZERO, addressToIndexMap.getIndexCount()); } + preferredViewSize = null; } }); } @@ -217,7 +214,6 @@ public class ListingModelAdapter implements LayoutModel, ListingModelListener { if (floc != null) { return floc; } - return getFieldLocation(location.getAddress(), location, true); } @@ -237,7 +233,7 @@ public class ListingModelAdapter implements LayoutModel, ListingModelListener { BigInteger index = addressToIndexMap.getIndex(address); Layout layout = getLayout(index); if (layout == null) { - index = getLayoutForArrayElement(address); + index = getLayoutWithinCodeUnit(address); layout = getLayout(index); } @@ -272,11 +268,12 @@ public class ListingModelAdapter implements LayoutModel, ListingModelListener { return null; } - private BigInteger getLayoutForArrayElement(Address address) { + private BigInteger getLayoutWithinCodeUnit(Address address) { CodeUnit cu = model.getProgram().getListing().getCodeUnitContaining(address); if (cu == null) { return null; } + Address min = cu.getMinAddress(); while (address.compareTo(min) > 0) { address = address.subtract(1); diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ProgramBigListingModel.java b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ProgramBigListingModel.java index 4ac0decc9a..a58089b092 100644 --- a/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ProgramBigListingModel.java +++ b/Ghidra/Features/Base/src/main/java/ghidra/app/util/viewer/listingpanel/ProgramBigListingModel.java @@ -53,7 +53,7 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener private List listeners = new ArrayList<>(); // Use a cache so that simple arrowing to-and-fro with the keyboard will respond quickly - private LRUMap layoutCache = new LRUMap<>(10); + private LayoutCache layoutCache = new LayoutCache(); public ProgramBigListingModel(Program program, FormatManager formatMgr) { this.program = program; @@ -124,15 +124,15 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener @Override public Layout getLayout(Address addr, boolean isGapAddress) { - Layout layout = layoutCache.get(addr); + Layout layout = layoutCache.get(addr, isGapAddress); if (layout == null) { layout = doGetLayout(addr, isGapAddress); - layoutCache.put(addr, layout); + layoutCache.put(addr, layout, isGapAddress); } return layout; } - public Layout doGetLayout(Address addr, boolean isGapAddress) { + private Layout doGetLayout(Address addr, boolean isGapAddress) { List list = new ArrayList<>(); FieldFormatModel format; CodeUnit cu = listing.getCodeUnitAt(addr); @@ -581,4 +581,31 @@ public class ProgramBigListingModel implements ListingModel, FormatModelListener } return addressSet; } + + private class LayoutCache { + + private LRUMap cache = new LRUMap<>(10); + private LRUMap gapCache = new LRUMap<>(10); + + void clear() { + cache.clear(); + gapCache.clear(); + } + + Layout get(Address addr, boolean isGapAddress) { + if (isGapAddress) { + return gapCache.get(addr); + } + return cache.get(addr); + } + + void put(Address addr, Layout layout, boolean isGapAddress) { + if (isGapAddress) { + gapCache.put(addr, layout); + } + else { + cache.put(addr, layout); + } + } + } }