Re-roll r870801. *** Original Change Description *** Reduce DevMode memory footprint by using a WeakInterner for potentially duplicated strings Review at http://gwt-code-reviews.appspot.com/870801 git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8850 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/build.xml b/dev/build.xml index 85feef9..74d6514 100755 --- a/dev/build.xml +++ b/dev/build.xml
@@ -108,6 +108,7 @@ <include name="w3c/sac/sac-1.3.jar" /> <!-- htmlunit dependencies not already included: END --> <include name="sun/swingworker/swing-worker-1.1.jar" /> + <include name="guava/guava-r06/guava-r06-rebased.jar" /> </fileset> <fileset file="build.xml"/> </sourcefiles> @@ -170,6 +171,7 @@ <zipfileset src="${gwt.tools.lib}/w3c/sac/sac-1.3.jar" /> <!-- htmlunit dependencies not already included: END --> <zipfileset src="${gwt.tools.lib}/sun/swingworker/swing-worker-1.1.jar" /> + <zipfileset src="${gwt.tools.lib}/guava/guava-r06/guava-r06-rebased.jar" /> </gwt.jar> </sequential> </outofdate> @@ -207,6 +209,7 @@ <pathelement location="${gwt.tools.lib}/eclipse/jdt-3.4.2.jar" /> <pathelement location="${gwt.tools.lib}/tomcat/commons-collections-3.1.jar" /> <pathelement location="${gwt.tools.lib}/junit/junit-3.8.1.jar" /> + <pathelement location="${gwt.tools.lib}/guava/guava-r06/guava-r06-rebased.jar" /> </classpath> </gwt.javac>
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JAbstractMethod.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JAbstractMethod.java index 2e144a9..8748e74 100644 --- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JAbstractMethod.java +++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JAbstractMethod.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.core.ext.typeinfo; +import com.google.gwt.dev.util.StringInterner; import com.google.gwt.dev.util.collect.Lists; import java.lang.annotation.Annotation; @@ -55,7 +56,7 @@ JAbstractMethod(String name, Map<Class<? extends Annotation>, Annotation> declaredAnnotations, JTypeParameter[] jtypeParameters) { - this.name = name; + this.name = StringInterner.get().intern(name); annotations = new Annotations(declaredAnnotations); if (jtypeParameters != null) { @@ -239,7 +240,13 @@ for (int i = 0; i < n; ++i) { // Identity tests are ok since identity is durable within an oracle. if (params.get(i) == parameter) { - return realParameterNames == null ? "arg" + i : realParameterNames[i]; + String realParameterName; + if (realParameterNames == null) { + realParameterName = StringInterner.get().intern("arg" + i); + } else { + realParameterName = StringInterner.get().intern(realParameterNames[i]); + } + return realParameterName; } } // TODO: report error if we are asked for an unknown JParameter?
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JArrayType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JArrayType.java index 055d936..ed2afaa 100644 --- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JArrayType.java +++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JArrayType.java
@@ -15,6 +15,8 @@ */ package com.google.gwt.core.ext.typeinfo; +import com.google.gwt.dev.util.StringInterner; + import java.lang.annotation.Annotation; import java.util.Map; @@ -205,7 +207,8 @@ @Override public String getSimpleSourceName() { if (lazySimpleName == null) { - lazySimpleName = getComponentType().getSimpleSourceName() + "[]"; + lazySimpleName = StringInterner.get().intern( + getComponentType().getSimpleSourceName() + "[]"); } return lazySimpleName; }
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JField.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JField.java index ea912fb..8a3f3d6 100644 --- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JField.java +++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JField.java
@@ -15,6 +15,8 @@ */ package com.google.gwt.core.ext.typeinfo; +import com.google.gwt.dev.util.StringInterner; + import java.lang.annotation.Annotation; import java.util.Map; @@ -50,7 +52,7 @@ Map<Class<? extends Annotation>, Annotation> declaredAnnotations) { assert (enclosingType != null); this.enclosingType = enclosingType; - this.name = name; + this.name = StringInterner.get().intern(name); this.enclosingType.addField(this); annotations = new Annotations(declaredAnnotations); }
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameter.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameter.java index f7b0686..3e30132 100644 --- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameter.java +++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JParameter.java
@@ -15,6 +15,8 @@ */ package com.google.gwt.core.ext.typeinfo; +import com.google.gwt.dev.util.StringInterner; + import java.lang.annotation.Annotation; import java.util.Map; @@ -37,7 +39,7 @@ JParameter(JAbstractMethod enclosingMethod, JParameter srcParam) { this.enclosingMethod = enclosingMethod; this.type = srcParam.type; - this.name = srcParam.name; + this.name = StringInterner.get().intern(srcParam.name); this.annotations = new Annotations(srcParam.annotations); } @@ -56,7 +58,7 @@ boolean argNameIsReal) { this.enclosingMethod = enclosingMethod; this.type = type; - this.name = name; + this.name = StringInterner.get().intern(name); this.argNameIsReal = argNameIsReal; enclosingMethod.addParameter(this); @@ -123,7 +125,7 @@ // Only called by JAbstractMethod after real parameter names are fetched. void setName(String name) { - this.name = name; + this.name = StringInterner.get().intern(name); } // Called when parameter types are found to be parameterized
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java index 1d64d80..b40ab8d 100644 --- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java +++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JRealClassType.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.core.ext.typeinfo; +import com.google.gwt.dev.util.StringInterner; import com.google.gwt.dev.util.collect.IdentitySets; import com.google.gwt.dev.util.collect.Lists; @@ -75,7 +76,7 @@ String enclosingTypeName, String name, boolean isInterface) { this.oracle = oracle; this.declaringPackage = declaringPackage; - this.name = name; + this.name = StringInterner.get().intern(name); this.isInterface = isInterface; if (enclosingTypeName == null) { // Add myself to my package. @@ -244,6 +245,7 @@ } else { lazyQualifiedName = nestedName; } + lazyQualifiedName = StringInterner.get().intern(lazyQualifiedName); } return lazyQualifiedName; }
diff --git a/dev/core/src/com/google/gwt/core/ext/typeinfo/JTypeParameter.java b/dev/core/src/com/google/gwt/core/ext/typeinfo/JTypeParameter.java index 74de83a..1084c4f 100644 --- a/dev/core/src/com/google/gwt/core/ext/typeinfo/JTypeParameter.java +++ b/dev/core/src/com/google/gwt/core/ext/typeinfo/JTypeParameter.java
@@ -15,6 +15,8 @@ */ package com.google.gwt.core.ext.typeinfo; +import com.google.gwt.dev.util.StringInterner; + import java.util.ArrayList; import java.util.List; @@ -28,7 +30,7 @@ private final String typeName; public JTypeParameter(String typeName, int ordinal) { - this.typeName = typeName; + this.typeName = StringInterner.get().intern(typeName); this.ordinal = ordinal; }
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java index 2be3f89..09dfd61 100644 --- a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java +++ b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
@@ -22,6 +22,7 @@ import com.google.gwt.dev.javac.JdtCompiler.UnitProcessor; import com.google.gwt.dev.js.ast.JsProgram; import com.google.gwt.dev.resource.Resource; +import com.google.gwt.dev.util.StringInterner; import com.google.gwt.dev.util.log.speedtracer.DevModeEventType; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger; import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event; @@ -81,21 +82,25 @@ MethodArgNamesLookup methodArgs = MethodParamCollector.collect(cud); - String packageName = Shared.getPackageName(builder.getTypeName()); + StringInterner interner = StringInterner.get(); + String packageName = interner.intern( + Shared.getPackageName(builder.getTypeName())); List<String> unresolvedQualified = new ArrayList<String>(); List<String> unresolvedSimple = new ArrayList<String>(); for (char[] simpleRef : cud.compilationResult().simpleNameReferences) { - unresolvedSimple.add(canonical(String.valueOf(simpleRef))); + unresolvedSimple.add(interner.intern(String.valueOf(simpleRef))); } - for (char[][] qualifiedRef : cud.compilationResult().qualifiedReferences) { - unresolvedQualified.add(canonical(CharOperation.toString(qualifiedRef))); + for (char[][] qualifiedRef : + cud.compilationResult().qualifiedReferences) { + unresolvedQualified.add( + interner.intern(CharOperation.toString(qualifiedRef))); } for (String jsniDep : jsniDeps) { - unresolvedQualified.add(canonical(jsniDep)); + unresolvedQualified.add(interner.intern(jsniDep)); } ArrayList<String> apiRefs = compiler.collectApiRefs(cud); for (int i = 0; i < apiRefs.size(); ++i) { - apiRefs.set(i, canonical(apiRefs.get(i))); + apiRefs.set(i, interner.intern(apiRefs.get(i))); } Dependencies dependencies = new Dependencies(packageName, unresolvedQualified, unresolvedSimple, apiRefs); @@ -118,15 +123,6 @@ } newlyBuiltUnits.add(unit); } - - private String canonical(String str) { - String result = internedTypeNames.get(str); - if (result != null) { - return result; - } - internedTypeNames.put(str, str); - return str; - } } /** @@ -143,14 +139,6 @@ new UnitProcessorImpl()); /** - * Memory efficiency only. Stores canonical versions of dependency type - * names so that String instances can be shared among many units. Otherwise, - * we'd get many duplicate String objects since we have to build them from - * JDT's char arrays. - */ - private final Map<String, String> internedTypeNames = new HashMap<String, String>(); - - /** * Continuation state for JSNI checking. */ private final JSORestrictionsChecker.CheckerState jsoState = new JSORestrictionsChecker.CheckerState();
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompiledClass.java b/dev/core/src/com/google/gwt/dev/javac/CompiledClass.java index 89d4ec1..a0e0585 100644 --- a/dev/core/src/com/google/gwt/dev/javac/CompiledClass.java +++ b/dev/core/src/com/google/gwt/dev/javac/CompiledClass.java
@@ -17,6 +17,7 @@ import com.google.gwt.dev.util.DiskCache; import com.google.gwt.dev.util.Name.InternalName; +import com.google.gwt.dev.util.StringInterner; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ClassFile; @@ -64,7 +65,8 @@ CompiledClass(ClassFile classFile, CompiledClass enclosingClass) { this.enclosingClass = enclosingClass; SourceTypeBinding binding = classFile.referenceBinding; - this.internalName = CharOperation.charToString(binding.constantPoolName()); + this.internalName = StringInterner.get().intern( + CharOperation.charToString(binding.constantPoolName())); byte[] bytes = classFile.getBytes(); this.cacheToken = diskCache.writeByteArray(bytes); this.isLocal = isLocalType(binding); @@ -99,7 +101,7 @@ * Returns the qualified source name, e.g. {@code java.util.Map.Entry}. */ public String getSourceName() { - return InternalName.toSourceName(internalName); + return StringInterner.get().intern(InternalName.toSourceName(internalName)); } public CompilationUnit getUnit() {
diff --git a/dev/core/src/com/google/gwt/dev/javac/Dependencies.java b/dev/core/src/com/google/gwt/dev/javac/Dependencies.java index 6b7253f..47786a4 100644 --- a/dev/core/src/com/google/gwt/dev/javac/Dependencies.java +++ b/dev/core/src/com/google/gwt/dev/javac/Dependencies.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.dev.javac; +import com.google.gwt.dev.util.StringInterner; import com.google.gwt.dev.util.collect.HashMap; import com.google.gwt.dev.util.collect.Lists; @@ -49,7 +50,8 @@ */ Dependencies(String myPackage, List<String> unresolvedQualified, List<String> unresolvedSimple, List<String> apiRefs) { - this.myPackage = (myPackage.length() == 0) ? "" : (myPackage + '.'); + this.myPackage = StringInterner.get().intern( + (myPackage.length() == 0) ? "" : (myPackage + '.')); this.unresolvedQualified = unresolvedQualified; this.unresolvedSimple = unresolvedSimple; this.apiRefs = apiRefs;
diff --git a/dev/core/src/com/google/gwt/dev/javac/MethodArgNamesLookup.java b/dev/core/src/com/google/gwt/dev/javac/MethodArgNamesLookup.java index 0b9d667..aba7337 100644 --- a/dev/core/src/com/google/gwt/dev/javac/MethodArgNamesLookup.java +++ b/dev/core/src/com/google/gwt/dev/javac/MethodArgNamesLookup.java
@@ -17,6 +17,7 @@ import com.google.gwt.core.ext.typeinfo.JAbstractMethod; import com.google.gwt.dev.javac.asm.CollectMethodData; +import com.google.gwt.dev.util.StringInterner; import com.google.gwt.dev.util.collect.Maps; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; @@ -84,12 +85,13 @@ int n = method.arguments.length; String[] argNames = new String[n]; for (int i = 0; i < n; ++i) { - argNames[i] = String.valueOf(method.arguments[i].name); + argNames[i] = StringInterner.get().intern( + String.valueOf(method.arguments[i].name)); } StringBuilder buf = new StringBuilder(); buf.append(enclosingType).append('.').append(method.selector); buf.append(method.binding.signature()); - String key = buf.toString(); + String key = StringInterner.get().intern(buf.toString()); methodArgs.put(key, argNames); } }
diff --git a/dev/core/src/com/google/gwt/dev/javac/asm/CollectAnnotationData.java b/dev/core/src/com/google/gwt/dev/javac/asm/CollectAnnotationData.java index e4f92b5..bf4c4af 100644 --- a/dev/core/src/com/google/gwt/dev/javac/asm/CollectAnnotationData.java +++ b/dev/core/src/com/google/gwt/dev/javac/asm/CollectAnnotationData.java
@@ -17,6 +17,7 @@ import com.google.gwt.dev.asm.AnnotationVisitor; import com.google.gwt.dev.javac.asm.CollectClassData.AnnotationEnum; +import com.google.gwt.dev.util.StringInterner; import java.util.ArrayList; import java.util.HashMap; @@ -37,12 +38,12 @@ private final boolean visible; protected AnnotationData(String desc, boolean visible) { - this.desc = desc; + this.desc = StringInterner.get().intern(desc); this.visible = visible; } public void addValue(String name, Object value) { - values.put(name, value); + values.put(StringInterner.get().intern(name), value); } /**
diff --git a/dev/core/src/com/google/gwt/dev/javac/asm/CollectClassData.java b/dev/core/src/com/google/gwt/dev/javac/asm/CollectClassData.java index 602d020..733edb7 100644 --- a/dev/core/src/com/google/gwt/dev/javac/asm/CollectClassData.java +++ b/dev/core/src/com/google/gwt/dev/javac/asm/CollectClassData.java
@@ -21,6 +21,7 @@ import com.google.gwt.dev.asm.Opcodes; import com.google.gwt.dev.asm.commons.EmptyVisitor; import com.google.gwt.dev.util.Name; +import com.google.gwt.dev.util.StringInterner; import java.util.ArrayList; import java.util.List; @@ -114,8 +115,8 @@ * @param value actual value in this enum */ public AnnotationEnum(String desc, String value) { - this.desc = desc; - this.value = value; + this.desc = StringInterner.get().intern(desc); + this.value = StringInterner.get().intern(value); } /**
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java index 7e1660e..9d598b1 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JMethod.java
@@ -17,6 +17,7 @@ import com.google.gwt.dev.jjs.InternalCompilerException; import com.google.gwt.dev.jjs.SourceInfo; +import com.google.gwt.dev.util.StringInterner; import com.google.gwt.dev.util.collect.Lists; import java.io.IOException; @@ -78,7 +79,7 @@ JType returnType, boolean isAbstract, boolean isStatic, boolean isFinal, boolean isPrivate) { super(info); - this.name = name; + this.name = StringInterner.get().intern(name); this.enclosingType = enclosingType; this.returnType = returnType; this.isAbstract = isAbstract;
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java index 2faba7d..02cb31e 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JParameter.java
@@ -16,6 +16,7 @@ package com.google.gwt.dev.jjs.ast; import com.google.gwt.dev.jjs.SourceInfo; +import com.google.gwt.dev.util.StringInterner; /** * Java method parameter definition. @@ -28,8 +29,8 @@ assert (type != null); assert (enclosingMethod != null); - JParameter x = new JParameter(info, name, type, isFinal, isThis, - enclosingMethod); + JParameter x = new JParameter(info, StringInterner.get().intern(name), type, + isFinal, isThis, enclosingMethod); enclosingMethod.addParam(x); return x;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsName.java b/dev/core/src/com/google/gwt/dev/js/ast/JsName.java index 96d7e50..a087d15 100644 --- a/dev/core/src/com/google/gwt/dev/js/ast/JsName.java +++ b/dev/core/src/com/google/gwt/dev/js/ast/JsName.java
@@ -16,6 +16,7 @@ package com.google.gwt.dev.js.ast; import com.google.gwt.dev.jjs.SourceInfo; +import com.google.gwt.dev.util.StringInterner; import java.io.Serializable; @@ -40,8 +41,8 @@ */ JsName(JsScope enclosing, String ident, String shortIdent) { this.enclosing = enclosing; - this.ident = ident; - this.shortIdent = shortIdent; + this.ident = StringInterner.get().intern(ident); + this.shortIdent = StringInterner.get().intern(shortIdent); this.isObfuscatable = true; }
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java b/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java index 03c3433..e967138 100644 --- a/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java +++ b/dev/core/src/com/google/gwt/dev/js/ast/JsNameRef.java
@@ -16,6 +16,7 @@ package com.google.gwt.dev.js.ast; import com.google.gwt.dev.jjs.SourceInfo; +import com.google.gwt.dev.util.StringInterner; /** * Represents a JavaScript expression that references a name. @@ -36,7 +37,7 @@ public JsNameRef(SourceInfo sourceInfo, String ident) { super(sourceInfo); - this.ident = ident; + this.ident = StringInterner.get().intern(ident); } public String getIdent() {
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java b/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java index de9552a..b317f38 100644 --- a/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java +++ b/dev/core/src/com/google/gwt/dev/js/ast/JsScope.java
@@ -16,6 +16,7 @@ package com.google.gwt.dev.js.ast; import com.google.gwt.dev.js.JsKeywords; +import com.google.gwt.dev.util.StringInterner; import com.google.gwt.dev.util.collect.Lists; import com.google.gwt.dev.util.collect.Maps; @@ -59,7 +60,7 @@ if (JsKeywords.isKeyword(ident)) { ident = ident + "_$"; } - return ident; + return StringInterner.get().intern(ident); } private List<JsScope> children = Collections.emptyList(); @@ -72,7 +73,7 @@ */ public JsScope(JsScope parent, String description) { assert (parent != null); - this.description = description; + this.description = StringInterner.get().intern(description); this.parent = parent; parent.children = Lists.add(parent.children, this); } @@ -81,7 +82,7 @@ * Subclasses can be parentless. */ protected JsScope(String description) { - this.description = description; + this.description = StringInterner.get().intern(description); this.parent = null; } @@ -200,6 +201,8 @@ * Creates a new name in this scope. */ protected JsName doCreateName(String ident, String shortIdent) { + ident = StringInterner.get().intern(ident); + shortIdent = StringInterner.get().intern(shortIdent); JsName name = new JsName(this, ident, shortIdent); names = Maps.putOrdered(names, ident, name); return name;
diff --git a/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java b/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java index 1d2ea51..f6fd8cc 100644 --- a/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java +++ b/dev/core/src/com/google/gwt/dev/js/ast/JsStringLiteral.java
@@ -16,6 +16,7 @@ package com.google.gwt.dev.js.ast; import com.google.gwt.dev.jjs.SourceInfo; +import com.google.gwt.dev.util.StringInterner; /** * A JavaScript string literal expression. @@ -27,7 +28,7 @@ // These only get created by JsProgram so that they can be interned. JsStringLiteral(SourceInfo sourceInfo, String value) { super(sourceInfo); - this.value = value; + this.value = StringInterner.get().intern(value); } public String getValue() {
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java b/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java index 0963fc7..a1270ef 100644 --- a/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java +++ b/dev/core/src/com/google/gwt/dev/resource/impl/PathPrefixSet.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.dev.resource.impl; +import com.google.gwt.dev.util.StringInterner; import com.google.gwt.dev.util.collect.Maps; import java.util.ArrayList; @@ -42,10 +43,11 @@ private PathPrefix prefix; public TrieNode(String part) { - this.part = part; + this.part = StringInterner.get().intern(part); } public TrieNode addChild(String part) { + part = StringInterner.get().intern(part); TrieNode newChild = new TrieNode(part); assert !children.containsKey(part); children = Maps.put(children, part, newChild);
diff --git a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java index e715bf6..b746913 100644 --- a/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java +++ b/dev/core/src/com/google/gwt/dev/resource/impl/ZipFileResource.java
@@ -15,6 +15,8 @@ */ package com.google.gwt.dev.resource.impl; +import com.google.gwt.dev.util.StringInterner; + import java.io.IOException; import java.io.InputStream; import java.util.zip.ZipEntry; @@ -31,7 +33,7 @@ public ZipFileResource(ZipFileClassPathEntry classPathEntry, String path, long lastModified) { this.classPathEntry = classPathEntry; - this.path = path; + this.path = StringInterner.get().intern(path); this.lastModified = lastModified; }
diff --git a/dev/core/src/com/google/gwt/dev/shell/DispatchClassInfo.java b/dev/core/src/com/google/gwt/dev/shell/DispatchClassInfo.java index 27819b3..d4dbda9 100644 --- a/dev/core/src/com/google/gwt/dev/shell/DispatchClassInfo.java +++ b/dev/core/src/com/google/gwt/dev/shell/DispatchClassInfo.java
@@ -16,6 +16,7 @@ package com.google.gwt.dev.shell; import com.google.gwt.dev.util.JsniRef; +import com.google.gwt.dev.util.StringInterner; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -82,7 +83,8 @@ private void addMemberIfUnique(String name, List<Member> membersForName) { if (membersForName.size() == 1) { memberById.add(membersForName.get(0)); - memberIdByName.put(name, memberById.size() - 1); + memberIdByName.put( + StringInterner.get().intern(name), memberById.size() - 1); } } @@ -182,7 +184,8 @@ } sb.append(")"); - String mangledName = sb.toString(); + String mangledName = StringInterner.get().intern(sb.toString()); + return mangledName; }
diff --git a/dev/core/src/com/google/gwt/dev/util/StringInterner.java b/dev/core/src/com/google/gwt/dev/util/StringInterner.java new file mode 100644 index 0000000..e193293 --- /dev/null +++ b/dev/core/src/com/google/gwt/dev/util/StringInterner.java
@@ -0,0 +1,43 @@ +/* + * Copyright 2010 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.google.gwt.dev.util; + +import com.google.gwt.thirdparty.guava.common.collect.Interner; +import com.google.gwt.thirdparty.guava.common.collect.Interners; + +/** + * A utility class for reducing String memory waste. Note that this does not use + * the String.intern() method which would prevent GC and fill the PermGen space. + * Instead, we use a Google Collections WeakInterner. + */ +public class StringInterner { + private static final StringInterner instance = new StringInterner(); + + public static StringInterner get() { + return instance; + } + + private final Interner<String> stringPool = Interners.newWeakInterner(); + + protected StringInterner() { + } + + public String intern(String s) { + return stringPool.intern(s); + } + +}
diff --git a/eclipse/dev/.classpath b/eclipse/dev/.classpath index 4502d00..022782a 100644 --- a/eclipse/dev/.classpath +++ b/eclipse/dev/.classpath
@@ -40,5 +40,6 @@ <classpathentry kind="var" path="GWT_TOOLS/lib/htmlunit/htmlunit-r5940/htmlunit-core-js-r5940.jar" sourcepath="/GWT_TOOLS/lib/htmlunit/htmlunit-r5940/htmlunit-core-js-r5940-sources.jar"/> <classpathentry kind="var" path="GWT_TOOLS/lib/htmlunit/htmlunit-r5940/htmlunit-r5940.jar" sourcepath="/GWT_TOOLS/lib/htmlunit/htmlunit-r5940/htmlunit-r5940-sources.jar"/> <classpathentry kind="var" path="GWT_TOOLS/lib/protobuf/protobuf-2.2.0/protobuf-java-rebased-2.2.0.jar"/> + <classpathentry kind="var" path="GWT_TOOLS/lib/guava/guava-r06/guava-r06-rebased.jar"/> <classpathentry kind="output" path="bin"/> </classpath>