1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-23 08:55:25 +02:00

Indexing performance improvements.

This commit is contained in:
Markus Schorn 2008-04-18 15:27:01 +00:00
parent b87cd95a0f
commit 9b984524cc
8 changed files with 175 additions and 177 deletions

View file

@ -11,6 +11,8 @@
package org.eclipse.cdt.internal.pdom.tests;
import java.util.Arrays;
import java.util.Comparator;
import java.util.regex.Pattern;
import junit.framework.Test;
@ -51,6 +53,7 @@ public class PDOMSearchTest extends PDOMTestBase {
return suite(PDOMSearchTest.class);
}
@Override
protected void setUp() throws Exception {
if (pdom == null) {
ICProject project = createProject("searchTests", true);
@ -59,6 +62,7 @@ public class PDOMSearchTest extends PDOMTestBase {
pdom.acquireReadLock();
}
@Override
protected void tearDown() throws Exception {
pdom.releaseReadLock();
}
@ -175,9 +179,13 @@ public class PDOMSearchTest extends PDOMTestBase {
assertEquals("Class2", getBindingQualifiedName(pdom.getLinkageImpls()[0].adaptBinding(cls1)));
methods = cls1.getDeclaredMethods();
assertEquals(3, methods.length);
Arrays.sort(methods, new Comparator<IBinding>() {
public int compare(IBinding o1, IBinding o2) {
return o1.getName().compareTo(o2.getName());
}});
assertEquals("Class2", methods[0].getName());
assertEquals("~Class2", methods[1].getName());
assertEquals("foo", methods[2].getName());
assertEquals("~Class2", methods[2].getName());
assertEquals("foo", methods[1].getName());
/** result #2 * */
ICPPMethod meth2 = (ICPPMethod) class2s[1];

View file

@ -62,17 +62,18 @@ public class PDOMNodeLinkedList {
ListItem item = firstItem;
do {
PDOMNode node;
int record= item.getItem();
final int record= item.getItem();
if(record==0) {
if(!allowsNull) {
throw new NullPointerException();
}
node= null;
} else {
node= linkage.getNode(item.getItem());
node= linkage.getNode(record);
}
if (visitor.visit(node) && node!=null)
if (visitor.visit(node) && node != null) {
node.accept(visitor);
}
visitor.leave(node);
item = item.getNext();
} while (!item.equals(firstItem));

View file

@ -15,7 +15,6 @@ import java.util.List;
import org.eclipse.cdt.core.dom.IPDOMNode;
import org.eclipse.cdt.core.dom.IPDOMVisitor;
import org.eclipse.cdt.core.dom.ast.ICompositeType;
import org.eclipse.cdt.internal.core.pdom.db.IBTreeVisitor;
import org.eclipse.cdt.internal.core.pdom.db.IString;
import org.eclipse.core.runtime.CoreException;
@ -33,7 +32,6 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor {
private final boolean caseSensitive;
private IProgressMonitor monitor= null;
private int monitorCheckCounter= 0;
private boolean visitAnonymousClassTypes= false;
private List<PDOMNamedNode> nodes = new ArrayList<PDOMNamedNode>();
@ -62,11 +60,7 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor {
public void setMonitor(IProgressMonitor pm) {
monitor= pm;
}
public void setVisitAnonymousClassTypes(boolean val) {
visitAnonymousClassTypes= val;
}
final public int compare(int record) throws CoreException {
if (monitor != null)
checkCancelled();
@ -133,14 +127,6 @@ public class NamedNodeCollector implements IBTreeVisitor, IPDOMVisitor {
if (compare(pb.getDBName()) == 0) {
addNode(pb);
}
else if (visitAnonymousClassTypes) {
if (pb instanceof ICompositeType) {
char[] nchars= pb.getNameCharArray();
if (nchars.length > 0 && nchars[0] == '{') {
return true; // visit children
}
}
}
}
return false; // don't visit children
}

View file

@ -14,6 +14,8 @@
package org.eclipse.cdt.internal.core.pdom.dom;
import java.util.Arrays;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.cdt.internal.core.pdom.db.Database;
import org.eclipse.cdt.internal.core.pdom.db.IString;
@ -66,13 +68,16 @@ public abstract class PDOMNamedNode extends PDOMNode {
}
public char[] getNameCharArray() throws CoreException {
if (fName == null) {
fName= getDBName().getChars();
}
return fName;
if (fName != null)
return fName;
return fName= getDBName().getChars();
}
public boolean hasName(char[] name) throws CoreException {
if (fName != null)
return Arrays.equals(fName, name);
return getDBName().equals(name);
}

View file

@ -38,6 +38,8 @@ public abstract class PDOMNode implements IPDOMNode {
protected final PDOM pdom;
protected final int record;
private int cachedParentRecord;
protected PDOMNode(PDOM pdom, int record) {
this.pdom = pdom;
this.record = record;
@ -53,7 +55,8 @@ public abstract class PDOMNode implements IPDOMNode {
db.putInt(record + TYPE, getNodeType());
// parent
db.putInt(record + PARENT, parent != null ? parent.getRecord() : 0);
cachedParentRecord= parent != null ? parent.getRecord() : 0;
db.putInt(record + PARENT, cachedParentRecord);
}
protected abstract int getRecordSize();
@ -106,7 +109,10 @@ public abstract class PDOMNode implements IPDOMNode {
}
public int getParentNodeRec() throws CoreException {
return pdom.getDB().getInt(record + PARENT);
if (cachedParentRecord != 0) {
return cachedParentRecord;
}
return cachedParentRecord= pdom.getDB().getInt(record + PARENT);
}
public PDOMNode getParentNode() throws CoreException {

View file

@ -35,6 +35,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateScope;
import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.core.index.IndexFilter;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.ObjectMap;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
@ -146,9 +147,10 @@ class PDOMCPPClassTemplate extends PDOMCPPClassType
@Override
protected void bindingsOfScopeAccept(IPDOMVisitor visitor) throws CoreException {
// don't visit parameters and instances
super.accept(visitor);
// this is actually wrong, the undeclared bindings should be filtered out. However, that causes
// some of the test cases to fail. --> need to look into this.
protected IndexFilter getFilterForBindingsOfScope() {
return IndexFilter.ALL;
}
private class PDOMCPPTemplateScope implements ICPPTemplateScope, IIndexScope {

View file

@ -56,6 +56,7 @@ import org.eclipse.cdt.internal.core.pdom.db.PDOMNodeLinkedList;
import org.eclipse.cdt.internal.core.pdom.dom.BindingCollector;
import org.eclipse.cdt.internal.core.pdom.dom.IPDOMMemberOwner;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMASTAdapter;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMLinkage;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMName;
import org.eclipse.cdt.internal.core.pdom.dom.PDOMNode;
@ -141,6 +142,31 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
setFirstBase(base);
}
public void removeBase(PDOMName pdomName) throws CoreException {
pdom.removeCachedResult(record+CACHE_BASES);
PDOMCPPBase base= getFirstBase();
PDOMCPPBase predecessor= null;
int nameRec= pdomName.getRecord();
while (base != null) {
PDOMName name = base.getBaseClassSpecifierName();
if (name != null && name.getRecord() == nameRec) {
break;
}
predecessor= base;
base= base.getNextBase();
}
if (base != null) {
if (predecessor != null) {
predecessor.setNextBase(base.getNextBase());
}
else {
setFirstBase(base.getNextBase());
}
base.delete();
}
}
public boolean isSameType(IType type) {
if (type instanceof ITypedef) {
return type.isSameType(this);
@ -188,17 +214,10 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
}
}
@Override
public void accept(IPDOMVisitor visitor) throws CoreException {
super.accept(visitor);
PDOMNodeLinkedList list = new PDOMNodeLinkedList(pdom, record + MEMBERLIST, getLinkageImpl());
list.accept(visitor);
}
public ICPPMethod[] getDeclaredMethods() throws DOMException {
try {
PDOMClassUtil.MethodCollector methods = new PDOMClassUtil.MethodCollector(false);
cachedBindingsAccept(methods);
acceptForNestedBindingsViaCache(methods);
return methods.getMethods();
} catch (CoreException e) {
return new ICPPMethod[0];
@ -219,7 +238,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
public ICPPMethod[] getImplicitMethods() {
try {
PDOMClassUtil.MethodCollector methods = new PDOMClassUtil.MethodCollector(true, false);
accept(methods);
acceptForNestedBindingsViaCache(methods);
return methods.getMethods();
} catch (CoreException e) {
return new ICPPMethod[0];
@ -277,7 +296,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
public ICPPField[] getDeclaredFields() throws DOMException {
try {
PDOMClassUtil.FieldCollector visitor = new PDOMClassUtil.FieldCollector();
cachedBindingsAccept(visitor);
acceptForNestedBindingsViaCache(visitor);
return visitor.getFields();
} catch (CoreException e) {
CCorePlugin.log(e);
@ -302,7 +321,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
public ICPPClassType[] getNestedClasses() throws DOMException {
try {
NestedClassCollector visitor = new NestedClassCollector();
cachedBindingsAccept(visitor);
acceptForNestedBindingsViaCache(visitor);
return visitor.getNestedClasses();
} catch (CoreException e) {
CCorePlugin.log(e);
@ -310,28 +329,33 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
}
}
private void cachedBindingsAccept(IPDOMVisitor visitor) throws CoreException {
CharArrayMap<Object> map= getBindingMap();
for (Object obj : map.values()) {
if (obj instanceof List) {
for (Object binding : (List<?>)obj) {
if (binding instanceof IPDOMNode) {
final IPDOMNode node = (IPDOMNode) binding;
if (visitor.visit(node))
return;
visitor.leave(node);
}
}
}
else if (obj instanceof Object[]) {
Object[] array= (Object[]) obj;
for (Object binding : array) {
if (binding instanceof IPDOMNode) {
final IPDOMNode node = (IPDOMNode) binding;
if (visitor.visit(node))
return;
visitor.leave(node);
@Override
public void accept(IPDOMVisitor visitor) throws CoreException {
super.accept(visitor);
acceptForNestedBindingsViaCache(visitor);
}
/**
* Called to populate the cache for the bindings in the class scope.
*/
private void acceptForNestedBindings(IPDOMVisitor visitor) throws CoreException {
super.accept(visitor);
PDOMNodeLinkedList list = new PDOMNodeLinkedList(pdom, record + MEMBERLIST, getLinkageImpl());
list.accept(visitor);
}
/**
* Visit bindings via the cache.
*/
private void acceptForNestedBindingsViaCache(IPDOMVisitor visitor) throws CoreException {
CharArrayMap<List<PDOMBinding>> map= getBindingMap();
for (List<PDOMBinding> list : map.values()) {
for (PDOMBinding node : list) {
if (node.getParentNodeRec() == record) {
if (visitor.visit(node)) {
node.accept(visitor);
}
visitor.leave(node);
}
}
}
@ -371,7 +395,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
public ICPPConstructor[] getConstructors() throws DOMException {
PDOMClassUtil.ConstructorCollector visitor= new PDOMClassUtil.ConstructorCollector();
try {
cachedBindingsAccept(visitor);
acceptForNestedBindingsViaCache(visitor);
} catch (CoreException e) {
CCorePlugin.log(e);
}
@ -395,7 +419,7 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
return this;
}
final IBinding[] candidates = getBindingsViaCache(nameChars);
final IBinding[] candidates = getBindingsViaCache(nameChars, getFilterForBindingsOfScope());
return CPPSemantics.resolveAmbiguities(name, candidates);
} catch (CoreException e) {
CCorePlugin.log(e);
@ -409,73 +433,71 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
try {
final char[] nameChars = name.toCharArray();
if (!prefixLookup) {
return getBindingsViaCache(nameChars);
return getBindingsViaCache(nameChars, getFilterForBindingsOfScope());
}
BindingCollector visitor = new BindingCollector(getLinkageImpl(), nameChars, IndexFilter.ALL_DECLARED_OR_IMPLICIT, prefixLookup, !prefixLookup);
BindingCollector visitor = new BindingCollector(getLinkageImpl(), nameChars, getFilterForBindingsOfScope(), prefixLookup, !prefixLookup);
if (getDBName().comparePrefix(nameChars, false) == 0) {
// 9.2 ... The class-name is also inserted into the scope of
// the class itself
visitor.visit(this);
}
visitor.setVisitAnonymousClassTypes(true);
bindingsOfScopeAccept(visitor);
acceptForNestedBindingsViaCache(visitor);
result= visitor.getBindings();
} catch (CoreException e) {
CCorePlugin.log(e);
}
return result;
}
protected IndexFilter getFilterForBindingsOfScope() {
return IndexFilter.ALL_DECLARED_OR_IMPLICIT;
}
/**
* Return whether or not the nested binding should go into the cache.
* @throws CoreException
* @since 5.0
*/
protected boolean isBindingOfScope(IBinding member) throws CoreException {
return IndexFilter.ALL_DECLARED_OR_IMPLICIT.acceptBinding(member);
}
IBinding[] getBindingsViaCache(final char[] name) throws CoreException {
CharArrayMap<Object> map = getBindingMap();
Object result= map.get(name);
if (result instanceof IBinding[])
return (IBinding[]) result;
if (result instanceof List) {
final List<?> list = (List<?>) result;
final IBinding[] bresult= list.toArray(new IBinding[list.size()]);
map.put(name, bresult);
return bresult;
private IBinding[] getBindingsViaCache(final char[] name, IndexFilter filter) throws CoreException {
CharArrayMap<List<PDOMBinding>> map = getBindingMap();
List<PDOMBinding> cached= map.get(name);
if (cached == null)
return IBinding.EMPTY_BINDING_ARRAY;
int i= 0;
IBinding[] result= new IBinding[cached.size()];
for (IBinding binding : cached) {
if (filter.acceptBinding(binding)) {
result[i++]= binding;
}
}
return IBinding.EMPTY_BINDING_ARRAY;
if (i == result.length)
return result;
final IBinding[] bresult= new IBinding[i];
System.arraycopy(result, 0, bresult, 0, i);
return bresult;
}
private CharArrayMap<Object> getBindingMap() throws CoreException {
final Integer key= record;
private CharArrayMap<List<PDOMBinding>> getBindingMap() throws CoreException {
final Integer key= record + CACHE_MEMBERS;
@SuppressWarnings("unchecked")
Reference<CharArrayMap<Object>> cached= (Reference<CharArrayMap<Object>>) pdom.getCachedResult(key);
CharArrayMap<Object> map= cached == null ? null : cached.get();
Reference<CharArrayMap<List<PDOMBinding>>> cached= (Reference<CharArrayMap<List<PDOMBinding>>>) pdom.getCachedResult(key);
CharArrayMap<List<PDOMBinding>> map= cached == null ? null : cached.get();
if (map == null) {
// there is no cache, build it:
final CharArrayMap<Object> result= new CharArrayMap<Object>();
final CharArrayMap<List<PDOMBinding>> result= new CharArrayMap<List<PDOMBinding>>();
IPDOMVisitor visitor= new IPDOMVisitor() {
public boolean visit(IPDOMNode node) throws CoreException {
if (node instanceof IBinding) {
final IBinding binding= (IBinding) node;
if (node instanceof PDOMBinding) {
final PDOMBinding binding= (PDOMBinding) node;
final char[] nchars = binding.getNameCharArray();
if (nchars.length > 0 && isBindingOfScope(binding)) {
@SuppressWarnings("unchecked")
List<IBinding> list= (List<IBinding>) result.get(nchars);
if (list == null) {
list= new ArrayList<IBinding>();
result.put(nchars, list);
}
list.add(binding);
if (binding instanceof ICompositeType && nchars[0] == '{') {
return true; // visit children
}
List<PDOMBinding> list= result.get(nchars);
if (list == null) {
list= new ArrayList<PDOMBinding>();
result.put(nchars, list);
}
list.add(binding);
if (binding instanceof ICompositeType && nchars.length > 0 && nchars[0] == '{') {
return true; // visit children
}
}
return false;
@ -484,17 +506,13 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
};
visitor.visit(this);
bindingsOfScopeAccept(visitor);
acceptForNestedBindings(visitor);
map= result;
pdom.putCachedResult(key, new SoftReference<CharArrayMap<?>>(map));
}
return map;
}
protected void bindingsOfScopeAccept(IPDOMVisitor visitor) throws CoreException {
this.accept(visitor);
}
public IBinding[] find(String name) throws DOMException {
return CPPSemantics.findBindings( this, name, false );
}
@ -510,31 +528,6 @@ class PDOMCPPClassType extends PDOMCPPBinding implements ICPPClassType,
public boolean mayHaveChildren() {
return true;
}
public void removeBase(PDOMName pdomName) throws CoreException {
pdom.removeCachedResult(record+CACHE_BASES);
PDOMCPPBase base= getFirstBase();
PDOMCPPBase predecessor= null;
int nameRec= pdomName.getRecord();
while (base != null) {
PDOMName name = base.getBaseClassSpecifierName();
if (name != null && name.getRecord() == nameRec) {
break;
}
predecessor= base;
base= base.getNextBase();
}
if (base != null) {
if (predecessor != null) {
predecessor.setNextBase(base.getNextBase());
}
else {
setFirstBase(base.getNextBase());
}
base.delete();
}
}
public IIndexBinding getScopeBinding() {
return this;

View file

@ -159,8 +159,8 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
public void run() {
try {
IType[] args = binding.getArguments();
for (int i = 0; i < args.length; i++) {
partial.addArgument(args[i]);
for (IType arg : args) {
partial.addArgument(arg);
}
} catch (CoreException e) {
CCorePlugin.log(e);
@ -235,10 +235,13 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
public PDOMBinding addBinding(IBinding binding, IASTName fromName) throws CoreException {
// assign names to anonymous types.
binding= PDOMASTAdapter.getAdapterForAnonymousASTBinding(binding);
if (binding == null) {
if (binding == null)
return null;
}
final PDOMNode parent= getAdaptedParent(binding, true);
if (parent == null)
return null;
PDOMBinding pdomBinding = adaptBinding(binding);
if (pdomBinding != null) {
if (shouldUpdate(pdomBinding, fromName)) {
@ -246,27 +249,17 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
}
} else {
try {
PDOMNode parent = getAdaptedParent(binding, true);
if (parent == null)
return null;
if (binding instanceof ICPPSpecialization) {
IBinding specialized= ((ICPPSpecialization)binding).getSpecializedBinding();
PDOMBinding pdomSpecialized= adaptBinding(specialized);
if (pdomSpecialized == null) {
addBinding(specialized, null);
}
addBinding(specialized, null);
}
pdomBinding = adaptBinding(binding);
if (pdomBinding == null) {
pdomBinding = addBinding(parent, binding);
if ((pdomBinding instanceof PDOMCPPClassInstance || pdomBinding instanceof PDOMCPPDeferredClassInstance) && binding instanceof ICPPClassType) {
// Add instantiated constructors to the index (bug 201174).
addConstructors(pdomBinding, (ICPPClassType) binding);
if(SemanticUtil.ENABLE_224364) {
addConversionOperators(pdomBinding, (ICPPClassType) binding);
}
pdomBinding = addBinding(parent, binding);
if ((pdomBinding instanceof PDOMCPPClassInstance || pdomBinding instanceof PDOMCPPDeferredClassInstance) && binding instanceof ICPPClassType) {
// Add instantiated constructors to the index (bug 201174).
addConstructors(pdomBinding, (ICPPClassType) binding);
if(SemanticUtil.ENABLE_224364) {
addConversionOperators(pdomBinding, (ICPPClassType) binding);
}
}
} catch (DOMException e) {
@ -473,8 +466,7 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
IScope scope = binding.getCompositeScope();
if (scope instanceof ICPPClassScope) {
ICPPMethod[] implicit= ((ICPPClassScope) scope).getImplicitMethods();
for (int i = 0; i < implicit.length; i++) {
ICPPMethod method = implicit[i];
for (ICPPMethod method : implicit) {
PDOMBinding pdomBinding= adaptBinding(method);
if (pdomBinding == null) {
addBinding(type, method);
@ -634,11 +626,16 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
if (ib.isFileLocal()) {
return null;
}
if (scope == null && binding instanceof ICPPInternalUnknownClassType) {
return adaptBinding(((PDOMBinding) binding).getParentBinding());
}
// in an index the null scope represents global scope.
if (scope == null) {
if (binding instanceof ICPPInternalUnknownClassType) {
if (binding instanceof PDOMBinding)
return addaptOrAddBinding(addParent, ((PDOMBinding) binding).getParentBinding());
// what if we have a composite binding??
return null;
}
// in an index the null scope represents global scope.
return this;
}
}
@ -653,9 +650,9 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
if (scope instanceof IIndexScope) {
if (scope instanceof CompositeScope) { // we special case for performance
return adaptBinding(((CompositeScope)scope).getRawScopeBinding());
return addaptOrAddBinding(addParent, ((CompositeScope)scope).getRawScopeBinding());
} else {
return adaptBinding(((IIndexScope) scope).getScopeBinding());
return addaptOrAddBinding(addParent, ((IIndexScope) scope).getScopeBinding());
}
}
@ -694,22 +691,22 @@ class PDOMCPPLinkage extends PDOMLinkage implements IIndexCPPBindingConstants {
}
}
}
if (scopeBinding != null && scopeBinding != binding) {
PDOMBinding scopePDOMBinding = null;
if (addParent) {
scopePDOMBinding = addBinding(scopeBinding, null);
} else {
scopePDOMBinding = adaptBinding(scopeBinding);
}
if (scopePDOMBinding != null)
return scopePDOMBinding;
}
if (scopeBinding != null && scopeBinding != binding)
return addaptOrAddBinding(addParent, scopeBinding);
} catch (DOMException e) {
throw new CoreException(Util.createStatus(e));
}
return null;
}
private PDOMBinding addaptOrAddBinding(boolean add, IBinding binding) throws CoreException {
if (add)
return addBinding(binding, null);
return adaptBinding(binding);
}
@Override
public PDOMNode addType(PDOMNode parent, IType type) throws CoreException {
if (type instanceof IProblemBinding) {