From cd662e1910495a86ef0567ea424832923b338a88 Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Mon, 28 Feb 2005 22:17:27 +0000 Subject: [PATCH] Performance and memory fixes for resolving bindings --- .../core/dom/ast/cpp/ICPPNamespaceScope.java | 3 + .../cdt/core/parser/util/ArrayUtil.java | 19 +++++ .../core/dom/parser/cpp/CPPNamespace.java | 5 ++ .../dom/parser/cpp/CPPNamespaceScope.java | 80 ++++++++++++++----- .../core/dom/parser/cpp/CPPSemantics.java | 79 ++++++++++++------ .../core/dom/parser/cpp/CPPVisitor.java | 4 +- .../eclipse/cdt/core/parser/ParserUtil.java | 3 + 7 files changed, 144 insertions(+), 49 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespaceScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespaceScope.java index 31a3430d01d..1375212dde3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespaceScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNamespaceScope.java @@ -13,9 +13,12 @@ */ package org.eclipse.cdt.core.dom.ast.cpp; +import org.eclipse.cdt.core.dom.ast.IASTName; + /** * @author aniefer */ public interface ICPPNamespaceScope extends ICPPScope { + boolean isFullyResolved( IASTName name ); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java index 589e9ad8fc7..d9db697c17b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/parser/util/ArrayUtil.java @@ -59,6 +59,25 @@ public class ArrayUtil { return array; } + static public int [] setInt( int[] array, int idx, int val ){ + if( array == null ){ + array = new int [ DEFAULT_LENGTH > idx + 1 ? DEFAULT_LENGTH : idx + 1]; + array[idx] = val; + return array; + } + + if( array.length <= idx ){ + int newLen = array.length * 2; + while( newLen <= idx ) newLen *=2; + int [] temp = new int [newLen]; + System.arraycopy( array, 0, temp, 0, array.length ); + + array = temp; + } + array[idx] = val; + return array; + } + static public Object [] append( Object[] array, Object obj ){ return append( Object.class, array, obj ); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespace.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespace.java index 640087fc315..47d0e82616f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespace.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespace.java @@ -23,6 +23,7 @@ import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IASTVisitor.BaseVisitorAction; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLinkageSpecification; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamespaceDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisitor; @@ -84,6 +85,8 @@ public class CPPNamespace implements ICPPNamespace, ICPPBinding { } public int processDeclaration( IASTDeclaration declaration ){ + if( declaration instanceof ICPPASTLinkageSpecification ) + return PROCESS_CONTINUE; return PROCESS_SKIP; } } @@ -94,6 +97,8 @@ public class CPPNamespace implements ICPPNamespace, ICPPBinding { IASTNode node = nsDef.getParent(); ICPPASTVisitor visitor = (ICPPASTVisitor) node.getTranslationUnit().getVisitor(); + while( node instanceof ICPPASTLinkageSpecification ) + node = node.getParent(); if( node instanceof IASTTranslationUnit ) visitor.visitTranslationUnit( collector ); else if( node instanceof ICPPASTNamespaceDefinition ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceScope.java index bd934b49da1..2c083dd5a37 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNamespaceScope.java @@ -13,21 +13,43 @@ */ package org.eclipse.cdt.internal.core.dom.parser.cpp; -import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.CharArrayObjectMap; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPSemantics.LookupData; /** * @author aniefer */ public class CPPNamespaceScope extends CPPScope implements ICPPNamespaceScope{ - private CharArrayObjectMap bindings = CharArrayObjectMap.EMPTY_MAP; - private boolean checkForAdditionalBindings = true; + private static class ScopeMap extends CharArrayObjectMap { + private boolean[] resolvedTable; + public ScopeMap( int initialSize ) { + super( initialSize ); + resolvedTable = new boolean[capacity()]; + } + protected void resize(int size) { + boolean[] oldResolvedTable = resolvedTable; + resolvedTable = new boolean[size]; + System.arraycopy(oldResolvedTable, 0, resolvedTable, 0, oldResolvedTable.length); + super.resize(size); + } + public boolean isFullyResolved( char [] name ){ + int i = lookup(name, 0, name.length); + if( i >= 0 ) + return resolvedTable[i]; + return false; + } + public void setFullyResolved( char [] name ){ + int i = lookup(name, 0, name.length); + if( i >= 0 ) + resolvedTable[i] = true; + } + } + private ScopeMap bindings = null; + //private boolean checkForAdditionalBindings = true; public CPPNamespaceScope( IASTNode physicalNode ) { super( physicalNode ); @@ -36,8 +58,8 @@ public class CPPNamespaceScope extends CPPScope implements ICPPNamespaceScope{ * @see org.eclipse.cdt.core.dom.ast.cpp.ICPPScope#addBinding(org.eclipse.cdt.core.dom.ast.IBinding) */ public void addBinding(IBinding binding) { - if( bindings == CharArrayObjectMap.EMPTY_MAP ) - bindings = new CharArrayObjectMap(1); + if( bindings == null ) + bindings = new ScopeMap(1); char [] c = binding.getNameCharArray(); Object o = bindings.get( c ); if( o != null ){ @@ -48,22 +70,22 @@ public class CPPNamespaceScope extends CPPScope implements ICPPNamespaceScope{ } } else { bindings.put( c, binding ); - if( checkForAdditionalBindings ){ - //need to ensure we have all bindings that correspond to this char[] - checkForAdditionalBindings = false; - LookupData data = new LookupData( c ); - try { - data.foundItems = CPPSemantics.lookupInScope( data, this, null, null ); - } catch ( DOMException e ) { - } - if( data.foundItems != null ){ - IASTName [] ns = (IASTName[]) data.foundItems; - for( int i = 0; i < ns.length && ns[i] != null; i++ ){ - ns[i].resolveBinding(); - } - } - checkForAdditionalBindings = true; - } +// if( checkForAdditionalBindings ){ +// //need to ensure we have all bindings that correspond to this char[] +// checkForAdditionalBindings = false; +// LookupData data = new LookupData( c ); +// try { +// data.foundItems = CPPSemantics.lookupInScope( data, this, null, null ); +// } catch ( DOMException e ) { +// } +// if( data.foundItems != null ){ +// IASTName [] ns = (IASTName[]) data.foundItems; +// for( int i = 0; i < ns.length && ns[i] != null; i++ ){ +// ns[i].resolveBinding(); +// } +// } +// checkForAdditionalBindings = true; +// } } } @@ -72,6 +94,9 @@ public class CPPNamespaceScope extends CPPScope implements ICPPNamespaceScope{ */ public IBinding getBinding( IASTName name ) { char [] c = name.toCharArray(); + if( bindings == null ) + return null; + Object obj = bindings.get( c ); if( obj != null ){ if( obj instanceof IBinding[] ){ @@ -88,4 +113,15 @@ public class CPPNamespaceScope extends CPPScope implements ICPPNamespaceScope{ // TODO Auto-generated method stub return null; } + + public void setFullyResolved( IASTName name ){ + if( bindings != null ) + bindings.setFullyResolved( name.toCharArray() ); + } + + public boolean isFullyResolved( IASTName name ){ + if( bindings != null ) + return bindings.isFullyResolved( name.toCharArray() ); + return false; + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java index 3cee71a9fce..b8a1e84cbd2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java @@ -647,8 +647,10 @@ public class CPPSemantics { ArrayWrapper directives = null; if( !data.usingDirectivesOnly ){ IBinding binding = data.prefixLookup ? null : scope.getBinding( data.astName ); - if( binding == null || !( CPPSemantics.declaredBefore( binding, data.astName ) || - (scope instanceof ICPPClassScope && data.checkWholeClassScope())) ) + if( binding == null || + (scope instanceof ICPPNamespaceScope && !((ICPPNamespaceScope) scope).isFullyResolved( data.astName ) ) || + !( CPPSemantics.declaredBefore( binding, data.astName ) || + (scope instanceof ICPPClassScope && data.checkWholeClassScope()) ) ) { directives = new ArrayWrapper(); mergeResults( data, lookupInScope( data, scope, blockItem, directives ), true ); @@ -900,11 +902,19 @@ public class CPPSemantics { int idx = -1; boolean checkWholeClassScope = ( scope instanceof ICPPClassScope ) && data.checkWholeClassScope(); IASTNode item = ( nodes != null ? (nodes.length > 0 ? nodes[++idx] : null ) : parent ); - + IASTNode [][] nodeStack = null; + int [] nodeIdxStack = null; + int nodeStackPos = -1; while( item != null ) { if( item instanceof ICPPASTLinkageSpecification ){ - nodes = (IASTNode[]) ArrayUtil.replace( IASTDeclaration.class, nodes, idx, ((ICPPASTLinkageSpecification)item).getDeclarations() ); - item = nodes[idx]; + IASTDeclaration [] decls = ((ICPPASTLinkageSpecification)item).getDeclarations(); + if( decls != null && decls.length > 0 ){ + nodeStack = (IASTNode[][]) ArrayUtil.append( IASTNode[].class, nodeStack, nodes ); + nodeIdxStack = ArrayUtil.setInt( nodeIdxStack, ++nodeStackPos, idx ); + nodes = ((ICPPASTLinkageSpecification)item).getDeclarations(); + idx = 0; + item = nodes[idx]; + } } if( !checkWholeClassScope && blockItem != null && ((ASTNode)item).getOffset() > ((ASTNode) blockItem).getOffset() ) break; @@ -930,26 +940,37 @@ public class CPPSemantics { item = nodes[idx]; } else { item = null; - - if( namespaceIdx > -1 ) { - //check all definitions of this namespace - while( namespaceIdx > -1 && namespaceDefs.length > ++namespaceIdx ){ - nodes = ((ICPPASTNamespaceDefinition)namespaceDefs[namespaceIdx].getParent()).getDeclarations(); - if( nodes.length > 0 ){ + nullItem: while( item == null ){ + if( namespaceIdx > -1 ) { + //check all definitions of this namespace + while( namespaceIdx > -1 && namespaceDefs.length > ++namespaceIdx ){ + nodes = ((ICPPASTNamespaceDefinition)namespaceDefs[namespaceIdx].getParent()).getDeclarations(); + if( nodes.length > 0 ){ + idx = 0; + item = nodes[0]; + break; + } + } + } else if( parent instanceof IASTCompoundStatement && nodes instanceof IASTParameterDeclaration [] ){ + //function body, we were looking at parameters, now check the body itself + IASTCompoundStatement compound = (IASTCompoundStatement) parent; + nodes = compound.getStatements(); + if( nodes.length > 0 ){ idx = 0; item = nodes[0]; break; - } + } } - } else if( parent instanceof IASTCompoundStatement && nodes instanceof IASTParameterDeclaration [] ){ - //function body, we were looking at parameters, now check the body itself - IASTCompoundStatement compound = (IASTCompoundStatement) parent; - nodes = compound.getStatements(); - if( nodes.length > 0 ){ - idx = 0; - item = nodes[0]; - break; - } + if( item == null && nodeStackPos >= 0 ){ + nodes = nodeStack[nodeStackPos]; + nodeStack[nodeStackPos] = null; + idx = nodeIdxStack[nodeStackPos--]; + if( ++idx >= nodes.length ) + continue; + + item = nodes[idx]; + } + break; } } } @@ -991,9 +1012,9 @@ public class CPPSemantics { IASTDeclaration declaration = null; if( node instanceof IASTDeclaration ) declaration = (IASTDeclaration) node; - if( node instanceof IASTDeclarationStatement ) + else if( node instanceof IASTDeclarationStatement ) declaration = ((IASTDeclarationStatement)node).getDeclaration(); - else if( node instanceof IASTForStatement ) + else if( node instanceof IASTForStatement && checkAux ) declaration = ((IASTForStatement)node).getInitDeclaration(); else if( node instanceof IASTParameterDeclaration && !data.typesOnly() ){ IASTParameterDeclaration parameterDeclaration = (IASTParameterDeclaration) node; @@ -1010,7 +1031,7 @@ public class CPPSemantics { if( declaration instanceof IASTSimpleDeclaration ){ IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration; - if( !data.typesOnly() ) { + if( !data.typesOnly() || simpleDeclaration.getDeclSpecifier().getStorageClass() == IASTDeclSpecifier.sc_typedef ) { IASTDeclarator [] declarators = simpleDeclaration.getDeclarators(); for( int i = 0; i < declarators.length; i++ ){ IASTDeclarator declarator = declarators[i]; @@ -1195,9 +1216,15 @@ public class CPPSemantics { Object [] items = (Object[]) data.foundItems; for( int i = 0; i < items.length && items[i] != null; i++ ){ Object o = items[i]; - if( o instanceof IASTName ) + if( o instanceof IASTName ){ temp = ((IASTName) o).resolveBinding(); - else if( o instanceof IBinding ){ + if( temp == null ) + continue; + IScope scope = temp.getScope(); + if( scope instanceof CPPNamespaceScope ){ + ((CPPNamespaceScope)scope).setFullyResolved( (IASTName) o ); + } + } else if( o instanceof IBinding ){ temp = (IBinding) o; if( !( temp instanceof ICPPMember ) && !declaredBefore( temp, name ) ) continue; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java index 97413da7d6c..13fd2ea634e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPVisitor.java @@ -312,7 +312,7 @@ public class CPPVisitor implements ICPPASTVisitor { if( elabType.getKind() != IASTElaboratedTypeSpecifier.k_enum ) binding = new CPPClassType( elabType.getName() ); scope.addBinding( binding ); - } else { + } else if( binding instanceof ICPPClassType ){ ((CPPClassType)binding).addDeclaration( elabType ); } } catch ( DOMException e ) { @@ -643,6 +643,8 @@ public class CPPVisitor implements ICPPASTVisitor { return parent; } else if( parent instanceof IASTExpression ){ IASTNode p = parent.getParent(); + if( p instanceof IASTForStatement ) + return parent; if( p instanceof IASTStatement ) return p; } else if ( parent instanceof IASTStatement || parent instanceof IASTTranslationUnit ) { diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserUtil.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserUtil.java index e02a570ac39..3c38880ec01 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserUtil.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/parser/ParserUtil.java @@ -86,6 +86,9 @@ public class ParserUtil catch( IOException e ) { } + catch( IllegalStateException e ) + { + } return InternalParserUtil.createFileReader(finalPath); }