Skip to main content
summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorNathan Ridge2017-10-10 06:08:01 +0000
committerNathan Ridge2017-10-16 17:53:43 +0000
commit48d5342815f83539aa5d7d5fc354d61cfedf31b3 (patch)
treeeb661af4bab22c51e6a80ed02693fce589f4d4ad /core
parent5f076989117039b247a0bf7d77f5e29f63b27e82 (diff)
downloadorg.eclipse.cdt-48d5342815f83539aa5d7d5fc354d61cfedf31b3.tar.gz
org.eclipse.cdt-48d5342815f83539aa5d7d5fc354d61cfedf31b3.tar.xz
org.eclipse.cdt-48d5342815f83539aa5d7d5fc354d61cfedf31b3.zip
Bug 519121 - Avoid building excessively long type strings in ASTTypeUtil
A type can appear as a constituent of another type multiple times. For example, in 'A<T, T>', 'T' appears as a constituent twice. When building a type string for 'A<T, T>', this means the type string of 'T' will appear in the type string of 'A<T, T>' twice. If such a duplication occurs at every level of a deeply nested type structure, the length of the type string can become exponential in the nesting depth. To avoid this, an optimization is added where, past a length threshold, type strings refer to constituent types "by reference" rather than by containing the contents of the constituent type's type string. Change-Id: Iaea268449a11b598f113a49fc61e9993bb6451da
Diffstat (limited to 'core')
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java49
1 files changed, 48 insertions, 1 deletions
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 006b6955adc..6872042128c 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
@@ -76,6 +76,11 @@ public class ASTTypeUtil {
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
private static final String SPACE = " "; //$NON-NLS-1$
private static final int DEAULT_ITYPE_SIZE = 2;
+
+ // A threshold above which type strings are appended to other type strings
+ // "by reference" rather than by copying their contents. This avoids the
+ // sizes of type strings from getting out of control for certain code patterns.
+ private static final int TYPE_STRING_LENGTH_THRESHOLD = 100000;
private static final ThreadLocal<Set<IBinding>> fSourceFileOnlyCheckInProgress=
new ThreadLocal<Set<IBinding>>() {
@@ -559,6 +564,28 @@ public class ASTTypeUtil {
}
return null;
}
+
+ /**
+ * Append a string to the builder "by reference".
+ *
+ * Instead of copying the bytes of the string into the builder, it copies
+ * the string's "address", as returned by System.identityHashCode().
+ *
+ * To preserve correct semantics, the string that's passed in must
+ * be interned, to ensure that we get the same "address" if and only if
+ * we would have gotten the same contents. (However, we do not call
+ * intern() ourselves, as some of our callers already know they have
+ * an interned strings, and calling it again would be wasteful.)
+ *
+ * The motivation is to avoid strings built by ASTTypeUtil from becoming
+ * excessively long by having the contents of a long string appended
+ * repeatedly to them.
+ */
+ private static void appendStringReference(String str, StringBuilder result) {
+ result.append("{String@"); //$NON-NLS-1$
+ result.append(System.identityHashCode(str));
+ result.append("}"); //$NON-NLS-1$
+ }
/**
* Appends the the result of {@link #getType(IType, boolean)} to the given buffer.
@@ -570,6 +597,13 @@ public class ASTTypeUtil {
if (cache != null) {
String cachedResult = cache.get(type);
if (cachedResult != null) {
+ // If the cached result is very long, append it "by reference".
+ // Note that all strings longer than TYPE_STRING_LENGTH_THRESHOLD
+ // stored in the cache are interned, so we are meeting that
+ // requirement of appendStringReference().
+ if (cachedResult.length() > TYPE_STRING_LENGTH_THRESHOLD) {
+ appendStringReference(cachedResult, result);
+ }
result.append(cachedResult);
return;
}
@@ -704,7 +738,20 @@ public class ASTTypeUtil {
if (cache != null) {
// Store result in the cache.
- cache.put(originalType, result.substring(startOffset));
+ String toCache = result.substring(startOffset);
+ // If the string to be cached is too long, we want to append it "by reference" instead.
+ if (toCache.length() > TYPE_STRING_LENGTH_THRESHOLD) {
+ // Remove the contents of the string from the buffer.
+ result.setLength(startOffset);
+
+ // Intern the string. This is required for calling appendStringReference(),
+ // to ensure that we get a unique String object for unique contents.
+ toCache = toCache.intern();
+
+ // Re-append the string by reference.
+ appendStringReference(toCache, result);
+ }
+ cache.put(originalType, toCache);
}
}

Back to the top