diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java index 396f6b27ee7..357aeeb7f27 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java @@ -10,6 +10,7 @@ * Markus Schorn (Wind River Systems) * Sergey Prigogin (Google) * Nathan Ridge + * Karsten Thoms (itemis) - Bug#471103 *******************************************************************************/ package org.eclipse.cdt.core.dom.ast; @@ -17,6 +18,7 @@ import java.net.URI; import java.util.ArrayList; import java.util.BitSet; import java.util.List; +import java.util.WeakHashMap; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IBasicType.Kind; @@ -70,6 +72,37 @@ public class ASTTypeUtil { private static final String SPACE = " "; //$NON-NLS-1$ private static final int DEAULT_ITYPE_SIZE = 2; + private static class ResultCache { + // Keep two separate maps for normalized and unnormalized type representations. + private WeakHashMap normalizedTypes = new WeakHashMap<>(); + private WeakHashMap unnormalizedTypes = new WeakHashMap<>(); + + /** + * Returns the cached string representation for a type. Returns {@code null} + * if the value was not cached or was garbage collected. + */ + public String get(IType type, boolean normalize) { + if (normalize) { + return normalizedTypes.get(type); + } else { + return unnormalizedTypes.get(type); + } + } + + /** + * Stores a string representation of the given type name in the cache. + */ + public String put(IType type, boolean normalize, String result) { + if (normalize) { + return normalizedTypes.put(type, result); + } else { + return unnormalizedTypes.put(type, result); + } + } + } + + private static final ThreadLocal resultCache = new ThreadLocal<>(); + private ASTTypeUtil() {} /** @@ -537,6 +570,20 @@ public class ASTTypeUtil { * @since 5.3 */ public static void appendType(IType type, boolean normalize, StringBuilder result) { + // performance: check if type was appended before + ResultCache cache = resultCache.get(); + if (cache != null) { + String cachedResult = cache.get(type, normalize); + if (cachedResult != null) { + result.append(cachedResult); + return; + } + } + + // Remember type argument for caching, argument is not final and might be changed. + IType originalType = type; + // Remember the start offset of the appended string. + int startOffset = result.length(); IType[] types = new IType[DEAULT_ITYPE_SIZE]; int numTypes = 0; @@ -659,6 +706,11 @@ public class ASTTypeUtil { appendTypeString(tj, normalize, result); } } + + if (cache != null) { + // Store result in the cache. + cache.put(originalType, normalize, result.substring(startOffset)); + } } /** @@ -797,7 +849,7 @@ public class ASTTypeUtil { CCorePlugin.log(e); } } else { - IASTNode node = ASTInternal.getDefinitionOfBinding(binding); + IASTNode node = ASTInternal.getDeclaredInSourceFileOnly(binding); if (node != null) { IPath filePath = new Path(node.getTranslationUnit().getFilePath()); URI uri = UNCPathConverter.getInstance().toURI(filePath); @@ -905,9 +957,29 @@ public class ASTTypeUtil { switch (fname[i]) { case '/': case '\\': - return i + 1; + return i+1; } } return 0; } + + /** + * Marks start of processing a translation unit during indexing. + * Enables caching of string representations of types. + * + * @noreference This method is not intended to be referenced by clients. + */ + public static void startTranslationUnit() { + resultCache.set(new ResultCache()); + } + + /** + * Marks the end of processing a translation unit during indexing. + * Disables caching of string representations of types and clears the previously cached results. + * + * @noreference This method is not intended to be referenced by clients. + */ + public static void finishTranslationUnit() { + resultCache.set(null); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java index f4c9e6efba9..12bbc6b699b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/AbstractIndexerTask.java @@ -11,6 +11,7 @@ * Sergey Prigogin (Google) * Thomas Corbat (IFS) * Marc-Andre Laperle (Ericsson) + * Karsten Thoms (itemis) - Bug#471103 *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom; @@ -35,6 +36,7 @@ import java.util.regex.Pattern; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.IPDOMIndexerTask; +import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; import org.eclipse.cdt.core.dom.ast.IASTComment; import org.eclipse.cdt.core.dom.ast.IASTFileLocation; import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIncludeStatement; @@ -1083,6 +1085,7 @@ public abstract class AbstractIndexerTask extends PDOMWriter { final boolean isSource = fResolver.isSourceUnit(tu); long start= System.currentTimeMillis(); + ASTTypeUtil.startTranslationUnit(); IASTTranslationUnit ast= createAST(lang, codeReader, scanInfo, isSource, fASTOptions, ctx, pm); fStatistics.fParsingTime += System.currentTimeMillis() - start; if (ast == null) { @@ -1105,6 +1108,8 @@ public abstract class AbstractIndexerTask extends PDOMWriter { if (--fSwallowOutOfMemoryError < 0) throw e; th= e; + } finally { + ASTTypeUtil.finishTranslationUnit(); } if (th != null) { swallowError(path, th);