GT-3226 - Symbol Table - Performance improvements - review fixes:

convert SymbolRowObject to Symbol
This commit is contained in:
dragonmacher 2019-10-24 14:19:19 -04:00
parent fc67c6aaeb
commit 9e320c6401
33 changed files with 638 additions and 624 deletions

View file

@ -217,7 +217,8 @@ public class CodeSymbol extends SymbolDB {
*/
@Override
public boolean isValidParent(Namespace parent) {
return SymbolType.LABEL.isValidParent(symbolMgr.getProgram(), parent, address, isExternal());
return SymbolType.LABEL.isValidParent(symbolMgr.getProgram(), parent, address,
isExternal());
// if (isExternal() != parent.isExternal()) {
// return false;
@ -241,15 +242,12 @@ public class CodeSymbol extends SymbolDB {
// return true;
}
/**
* @see ghidra.program.model.symbol.Symbol#getName()
*/
@Override
public String getName() {
protected String doGetName() {
if (getSource() == SourceType.DEFAULT && isExternal()) {
return ExternalManagerDB.getDefaultExternalName(this);
}
return super.getName();
return super.doGetName();
}
@Override

View file

@ -33,7 +33,6 @@ import ghidra.util.Msg;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.task.TaskMonitor;
import ghidra.util.task.TaskMonitorAdapter;
/**
* Symbol class for functions.
@ -237,11 +236,8 @@ public class FunctionSymbol extends SymbolDB {
isExternal());
}
/**
* @see ghidra.program.model.symbol.Symbol#getName()
*/
@Override
public String getName() {
protected String doGetName() {
if (getSource() == SourceType.DEFAULT) {
if (isExternal()) {
return ExternalManagerDB.getDefaultExternalName(this);
@ -251,17 +247,17 @@ public class FunctionSymbol extends SymbolDB {
Symbol thunkedSymbol = getThunkedSymbol();
if (thunkedSymbol instanceof FunctionSymbol) {
FunctionSymbol thunkedFuncSym = (FunctionSymbol) thunkedSymbol;
String name = thunkedFuncSym.getName();
String thunkName = thunkedFuncSym.getName();
if (thunkedFuncSym.getSource() == SourceType.DEFAULT &&
thunkedFuncSym.getThunkedSymbol() == null) {
// if thunking a default non-thunk function
name = "thunk_" + name;
thunkName = "thunk_" + thunkName;
}
return name;
return thunkName;
}
return SymbolUtilities.getDefaultFunctionName(address);
}
return super.getName();
return super.doGetName();
}
// @Override
@ -363,7 +359,7 @@ public class FunctionSymbol extends SymbolDB {
checkIsValid();
Reference[] refs = super.getReferences(monitor);
if (monitor == null) {
monitor = TaskMonitorAdapter.DUMMY_MONITOR;
monitor = TaskMonitor.DUMMY;
}
if (monitor.isCancelled()) {
return refs;

View file

@ -54,7 +54,7 @@ public class GlobalVariableSymbolDB extends VariableSymbolDB {
}
@Override
public String getName() {
protected String doGetName() {
if (!checkIsValid()) {
// TODO: SCR
return "[Invalid VariableSymbol - Deleted!]";
@ -63,7 +63,7 @@ public class GlobalVariableSymbolDB extends VariableSymbolDB {
if (storage == null) {
return Function.DEFAULT_LOCAL_PREFIX + "_!BAD!";
}
return super.getName();
return super.doGetName();
}
}

View file

@ -30,11 +30,13 @@ import ghidra.program.model.listing.CircularDependencyException;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.*;
import ghidra.program.util.ChangeManager;
import ghidra.program.util.ProgramLocation;
import ghidra.util.Lock;
import ghidra.util.SystemUtilities;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.InvalidInputException;
import ghidra.util.task.*;
import ghidra.util.task.TaskMonitor;
import ghidra.util.task.UnknownProgressWrappingTaskMonitor;
/**
* Base class for symbols
@ -43,10 +45,25 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
private Record record;
private boolean isDeleting = false;
protected String name;
protected Address address;
protected SymbolManager symbolMgr;
protected Lock lock;
/**
* Creates a Symbol that is just a placeholder for use when trying to find symbols by using
* {@link Symbol#getID()}. This is useful for locating symbols in Java collections when
* a symbol has been deleted and the only remaining information is that symbol's ID.
*
* @param manager the manager for the new symbol
* @param address the address of the symbol
* @param id the id of the symbol
* @return the fake symbol
*/
static SymbolDB createSymbolPlaceholder(SymbolManager manager, Address address, long id) {
return new PlaceholderSymbolDB(manager, address, id);
}
SymbolDB(SymbolManager symbolMgr, DBObjectCache<SymbolDB> cache, Address address,
Record record) {
super(cache, record.getKey());
@ -65,6 +82,11 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
@Override
public String toString() {
// prefer cached name for speed; it may be stale; call getName() for current value
String temp = name;
if (temp != null) {
return temp;
}
return getName();
}
@ -75,6 +97,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
@Override
protected boolean refresh(Record rec) {
name = null;
if (record != null) {
if (rec == null) {
rec = symbolMgr.getSymbolRecord(key);
@ -145,17 +168,29 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
lock.acquire();
try {
checkIsValid();
if (record != null) {
return record.getString(SymbolDatabaseAdapter.SYMBOL_NAME_COL);
if (name == null) {
name = doGetName();
}
return SymbolUtilities.getDynamicName(symbolMgr.getProgram(), address);
return name;
}
finally {
lock.release();
}
}
/**
* The code for creating the name content for this symbol. This code will be called
* with the symbol's lock.
*
* @return the name
*/
protected String doGetName() {
if (record != null) {
return record.getString(SymbolDatabaseAdapter.SYMBOL_NAME_COL);
}
return SymbolUtilities.getDynamicName(symbolMgr.getProgram(), address);
}
@Override
public Program getProgram() {
return symbolMgr.getProgram();
@ -238,7 +273,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
try {
checkIsValid();
if (monitor == null) {
monitor = TaskMonitorAdapter.DUMMY_MONITOR;
monitor = TaskMonitor.DUMMY;
}
if (monitor.getMaximum() == 0) {
@ -275,7 +310,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
@Override
public Reference[] getReferences() {
return getReferences(TaskMonitorAdapter.DUMMY_MONITOR);
return getReferences(TaskMonitor.DUMMY);
}
@Override
@ -470,7 +505,11 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
/**
* Allow symbol implementations to validate the source when setting the name of
* this symbol.
* this symbol
*
* @param newName the new name
* @param source the source type
* @return the validated source type
*/
protected SourceType validateNameSource(String newName, SourceType source) {
return source;
@ -482,6 +521,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
lock.acquire();
try {
name = null;
checkDeleted();
checkEditOK();
@ -535,6 +575,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
record.setLongValue(SymbolDatabaseAdapter.SYMBOL_PARENT_COL, newNamespace.getID());
record.setString(SymbolDatabaseAdapter.SYMBOL_NAME_COL, newName);
name = newName;
updateSymbolSource(record, source);
updateRecord();
@ -613,10 +654,16 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
if (obj == this) {
return true;
}
Symbol s = (Symbol) obj;
if (getID() == s.getID()) {
return true;
}
if (!getName().equals(s.getName())) {
return false;
}
if (!getAddress().equals(s.getAddress())) {
return false;
}
@ -776,6 +823,7 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
/**
* gets the generic symbol data 2 data.
* @return the symbol data
*/
public int getSymbolData2() {
lock.acquire();
@ -852,10 +900,64 @@ public abstract class SymbolDB extends DatabaseObject implements Symbol {
/**
* Change the record and key associated with this symbol
* @param the record.
* @param record the record
*/
void setRecord(Record record) {
this.record = record;
keyChanged(record.getKey());
}
private static class PlaceholderSymbolDB extends SymbolDB {
PlaceholderSymbolDB(SymbolManager symbolMgr, Address address, long key) {
super(symbolMgr, null, address, key);
}
@Override
public boolean equals(Object obj) {
if ((obj == null) || (!(obj instanceof Symbol))) {
return false;
}
if (obj == this) {
return true;
}
// this class is only ever equal if the id matches
Symbol s = (Symbol) obj;
if (getID() == s.getID()) {
return true;
}
return false;
}
@Override
public SymbolType getSymbolType() {
throw new IllegalArgumentException();
}
@Override
public ProgramLocation getProgramLocation() {
throw new IllegalArgumentException();
}
@Override
public boolean isExternal() {
throw new IllegalArgumentException();
}
@Override
public Object getObject() {
throw new IllegalArgumentException();
}
@Override
public boolean isPrimary() {
throw new IllegalArgumentException();
}
@Override
public boolean isValidParent(Namespace parent) {
throw new IllegalArgumentException();
}
}
}

View file

@ -2274,6 +2274,11 @@ public class SymbolManager implements SymbolTable, ManagerDB {
return new NamespaceDB(s, namespaceMgr);
}
@Override
public Symbol createSymbolPlaceholder(Address address, long id) {
return SymbolDB.createSymbolPlaceholder(this, address, id);
}
/**
* Creates a symbol, specifying all information for the record. This method is not on the
* public interface and is only intended for program API internal use. The user of this
@ -2675,5 +2680,4 @@ class SymbolMatcher implements Predicate<Symbol> {
SymbolType type = s.getSymbolType();
return type == type1;
}
}

View file

@ -203,7 +203,7 @@ public class VariableSymbolDB extends SymbolDB {
}
@Override
public String getName() {
protected String doGetName() {
if (!checkIsValid()) {
// TODO: SCR
return "[Invalid VariableSymbol - Deleted!]";
@ -213,7 +213,7 @@ public class VariableSymbolDB extends SymbolDB {
if (getSource() == SourceType.DEFAULT) {
return getParamName();
}
String storedName = super.getName();
String storedName = super.doGetName();
if (SymbolUtilities.isDefaultParameterName(storedName)) {
return getParamName();
}
@ -232,7 +232,7 @@ public class VariableSymbolDB extends SymbolDB {
// TODO: we use to check for a default name and regenerate new default name but we should
// not need to do this if source remains at default
return super.getName();
return super.doGetName();
}
@Override

View file

@ -543,4 +543,15 @@ public interface SymbolTable {
public Namespace createNameSpace(Namespace parent, String name, SourceType source)
throws DuplicateNameException, InvalidInputException;
/**
* Creates a Symbol that is just a placeholder for use when trying to find symbols by using
* {@link Symbol#getID()}. This is useful for locating symbols in Java collections when
* a symbol has been deleted and the only remaining information is that symbol's ID.
*
* @param address the address of the symbol
* @param id the id of the symbol
* @return the fake symbol
*/
public Symbol createSymbolPlaceholder(Address address, long id);
}

View file

@ -897,7 +897,11 @@ public class SymbolUtilities {
if (symbol.isExternal()) {
return "External Function";
}
Function func = (Function) symbol.getObject();
if (func == null) {
return null; // symbol deleted
}
if (func.isThunk()) {
return "Thunk Function";
}