Revision: 6858 Author: [email protected] Date: Wed Nov 11 17:18:27 2009 Log: trunk c6854-c6857 were merged into this branch Make AnnotationProxyFactory store an unmofiable minimal map. FindJsniRefVisitor can no longer beSloppy(). Removes OptionCompilationStateRetained in favor of a new GC strategy. Sandboxes AbstractCompiler so that the backreference can be detached from internal JDT types. svn merge --ignore-ancestry -r6853:6857 \ https://google-web-toolkit.googlecode.com/svn/trunk .
http://code.google.com/p/google-web-toolkit/source/detail?r=6858 Deleted: /releases/2.0/dev/core/src/com/google/gwt/dev/util/arg/OptionCompilationStateRetained.java /releases/2.0/dev/core/src/com/google/gwt/dev/util/log/ThreadLocalTreeLoggerProxy.java Modified: /releases/2.0/branch-info.txt /releases/2.0/dev/core/src/com/google/gwt/dev/Precompile.java /releases/2.0/dev/core/src/com/google/gwt/dev/javac/AnnotationProxyFactory.java /releases/2.0/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/AbstractCompiler.java /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/FindJsniRefVisitor.java /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/RebindPermutationOracle.java /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/WebModeCompilerFrontEnd.java /releases/2.0/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java /releases/2.0/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java /releases/2.0/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java /releases/2.0/user/src/com/google/gwt/junit/JUnitShell.java ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/util/arg/OptionCompilationStateRetained.java Mon Nov 2 12:44:54 2009 +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2009 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.arg; - -/** - * Option for retaining {...@link com.google.gwt.dev.javac.CompilationState} during - * a compile. Does not correspond to any command line option. This is used by - * hosted mode when doing a web mode compile to preserve the compilation state. - */ -public interface OptionCompilationStateRetained { - boolean isCompilationStateRetained(); - - void setCompilationStateRetained(boolean retained); -} ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/util/log/ThreadLocalTreeLoggerProxy.java Tue Apr 1 16:48:44 2008 +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2007 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.log; - -import com.google.gwt.core.ext.TreeLogger; - -/** - * An internal implementation support class that creates a - * {...@link com.google.gwt.server.internal.TreeLogger} that wraps another - * TreeLogger to allow for the underlying logger to be redirected per thread. It - * can be useful for situations where it is not practical to pass in a logger as - * a parameter, such as when interfacing with third-party classes. - */ -public final class ThreadLocalTreeLoggerProxy extends TreeLogger { - - private static final ThreadLocal<TreeLogger> perThreadLogger = new ThreadLocal<TreeLogger>(); - - public ThreadLocalTreeLoggerProxy() { - this(null); - } - - public ThreadLocalTreeLoggerProxy(TreeLogger logger) { - push(logger); - } - - /** - * Delegates the branch to the thread-local logger if one is present. - * Otherwise, the log entry is discarded and <code>this</code> is returned. - */ - @Override - public TreeLogger branch(Type type, String msg, Throwable caught, - HelpInfo helpInfo) { - TreeLogger logger = perThreadLogger.get(); - if (logger != null) { - return logger.branch(type, msg, caught, helpInfo); - } else { - return this; - } - } - - /** - * Delegates the check to the thread-local logger if one is present. - * - * @return relays the return value of the wrapped logger if one exists, or - * returns <code>false</code> otherwise - */ - public boolean isLoggable(Type type) { - TreeLogger logger = perThreadLogger.get(); - if (logger != null) { - return logger.isLoggable(type); - } else { - return false; - } - } - - /** - * Delegates the log to the thread-local logger if one is present. Otherwise, - * the log entry is discarded. - */ - @Override - public void log(Type type, String msg, Throwable caught, HelpInfo helpInfo) { - TreeLogger logger = perThreadLogger.get(); - if (logger != null) { - logger.log(type, msg, caught, helpInfo); - } - } - - public void pop(TreeLogger oldLogger) { - perThreadLogger.set(oldLogger); - } - - /** - * Sets the logger to which calls are redirected for the current thread. - */ - public TreeLogger push(TreeLogger logger) { - TreeLogger old = perThreadLogger.get(); - perThreadLogger.set(logger); - return old; - } -} ======================================= --- /releases/2.0/branch-info.txt Wed Nov 11 15:54:59 2009 +++ /releases/2.0/branch-info.txt Wed Nov 11 17:18:27 2009 @@ -575,3 +575,11 @@ Fixes some Scheduler bugs and adds a test case. svn merge --ignore-ancestry -c6851 https://google-web-toolkit.googlecode.com/svn/trunk/ . +trunk c6854-c6857 were merged into this branch + Make AnnotationProxyFactory store an unmofiable minimal map. + FindJsniRefVisitor can no longer beSloppy(). + Removes OptionCompilationStateRetained in favor of a new GC strategy. + Sandboxes AbstractCompiler so that the backreference can be detached from internal JDT types. + svn merge --ignore-ancestry -r6853:6857 \ + https://google-web-toolkit.googlecode.com/svn/trunk . + ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/Precompile.java Wed Nov 11 11:04:31 2009 +++ /releases/2.0/dev/core/src/com/google/gwt/dev/Precompile.java Wed Nov 11 17:18:27 2009 @@ -172,10 +172,6 @@ public boolean isClassMetadataDisabled() { return jjsOptions.isClassMetadataDisabled(); } - - public boolean isCompilationStateRetained() { - return jjsOptions.isCompilationStateRetained(); - } public boolean isDraftCompile() { return jjsOptions.isDraftCompile(); @@ -220,10 +216,6 @@ public void setClassMetadataDisabled(boolean disabled) { jjsOptions.setClassMetadataDisabled(disabled); } - - public void setCompilationStateRetained(boolean retained) { - jjsOptions.setCompilationStateRetained(retained); - } public void setDisableUpdateCheck(boolean disabled) { disableUpdateCheck = disabled; @@ -277,8 +269,8 @@ private static class DistillerRebindPermutationOracle implements RebindPermutationOracle { - private final CompilationState compilationState; - private final StandardGeneratorContext generatorContext; + private CompilationState compilationState; + private StandardGeneratorContext generatorContext; private final Permutation[] permutations; private final StaticPropertyOracle[] propertyOracles; private final RebindOracle[] rebindOracles; @@ -305,6 +297,12 @@ permutations[i] = new Permutation(i, propertyOracles[i]); } } + + public void clear() { + generatorContext.clear(); + compilationState = null; + generatorContext = null; + } public String[] getAllPossibleRebindAnswers(TreeLogger logger, String requestTypeName) throws UnableToCompleteException { @@ -455,6 +453,8 @@ module, compilationState, generatorArtifacts, new PropertyPermutations(module.getProperties()), genDir, generatorResourcesDir); + // Allow GC later. + compilationState = null; if (dumpSignatureFile != null) { // Dump early to avoid generated types. SignatureDumper.dumpSignatures(logger, @@ -516,6 +516,8 @@ DistillerRebindPermutationOracle rpo = new DistillerRebindPermutationOracle( module, compilationState, generatedArtifacts, allPermutations, genDir, generatorResourcesDir); + // Allow GC later. + compilationState = null; PerfLogger.start("Precompile"); UnifiedAst unifiedAst = getCompiler(module).precompile(logger, module, rpo, declEntryPts, null, jjsOptions, @@ -556,7 +558,6 @@ } public boolean run(TreeLogger logger) throws UnableToCompleteException { - boolean originalCompilationStateRetained = options.isCompilationStateRetained(); // Avoid early optimizations since permutation compiles will run separately. options.setOptimizePrecompile(false); @@ -612,18 +613,6 @@ int numPermsToPrecompile = Math.min(potentialPermutations - potentialFirstPerm, permutationsPerIteration); - if (potentialFirstPerm + numPermsToPrecompile < potentialPermutations) { - /* - * On all iterations but the last, force retainCompilationState to - * be true. Otherwise, state will be discarded that is needed on - * later iterations. - */ - options.setCompilationStateRetained(true); - } else { - // On the last iteration, use whatever the original setting was - options.setCompilationStateRetained(originalCompilationStateRetained); - } - // Select only the range of property permutations that we want PropertyPermutations localPermutations = new PropertyPermutations( allPermutations, potentialFirstPerm, numPermsToPrecompile); ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/javac/AnnotationProxyFactory.java Mon May 18 11:47:32 2009 +++ /releases/2.0/dev/core/src/com/google/gwt/dev/javac/AnnotationProxyFactory.java Wed Nov 11 17:18:27 2009 @@ -15,6 +15,8 @@ */ package com.google.gwt.dev.javac; +import com.google.gwt.dev.util.collect.Maps; + import java.lang.annotation.Annotation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; @@ -88,7 +90,7 @@ public AnnotationProxyInvocationHandler( Map<String, Object> identifierToValue, Class<? extends Annotation> annotationClass) { - this.identifierToValue = identifierToValue; + this.identifierToValue = Maps.normalizeUnmodifiable(identifierToValue); this.annotationClass = annotationClass; } ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java Wed Nov 11 11:04:31 2009 +++ /releases/2.0/dev/core/src/com/google/gwt/dev/javac/StandardGeneratorContext.java Wed Nov 11 17:18:27 2009 @@ -208,7 +208,7 @@ private final Set<GeneratedUnit> committedGeneratedCups = new HashSet<GeneratedUnit>(); - private final CompilationState compilationState; + private CompilationState compilationState; private Class<? extends Generator> currentGenerator; @@ -246,6 +246,14 @@ diskCache = new DiskCache(); } } + + /** + * Frees memory used up by compilation state. + */ + public void clear() { + compilationState = null; + generators.clear(); + } /** * Commits a pending generated type. ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/AbstractCompiler.java Wed Nov 11 11:04:31 2009 +++ /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/AbstractCompiler.java Wed Nov 11 17:18:27 2009 @@ -26,7 +26,6 @@ import com.google.gwt.dev.util.Empty; import com.google.gwt.dev.util.PerfLogger; import com.google.gwt.dev.util.Util; -import com.google.gwt.dev.util.log.ThreadLocalTreeLoggerProxy; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.compiler.IProblem; @@ -71,6 +70,7 @@ this.unit = unit; } + @SuppressWarnings("deprecation") public char[] getContents() { return unit.getSource().toCharArray(); } @@ -87,10 +87,6 @@ String packageName = Shared.getPackageName(unit.getTypeName()); return CharOperation.splitOn('.', packageName.toCharArray()); } - - public CompilationUnit getUnit() { - return unit; - } @Override public String toString() { @@ -99,306 +95,375 @@ } /** - * Adapted to hook the processing of compilation unit declarations so as to be - * able to add additional compilation units based on the results of - * previously-compiled ones. Examples of cases where this is useful include - * classes referenced only from JSNI and <code>GWT.create</code>. + * Shields {...@link AbstractCompiler} so it can be garbage collected at the end + * of a compile. */ - private class CompilerImpl extends Compiler { - - private Set<CompilationUnitDeclaration> cuds; - private long jdtProcessNanos; - - public CompilerImpl(INameEnvironment environment, - IErrorHandlingPolicy policy, CompilerOptions compilerOptions, - ICompilerRequestor requestor, IProblemFactory problemFactory) { - super(environment, policy, compilerOptions, requestor, problemFactory); - } - - @Override - public void compile(ICompilationUnit[] sourceUnits) { - jdtProcessNanos = 0; - super.compile(sourceUnits); - PerfLogger.log("AbstractCompiler.compile, time spent in JDT process callback: " - + (jdtProcessNanos / 1000000) + "ms"); - cuds = null; - } - - @Override - public void process(CompilationUnitDeclaration unit, int index) { - - long processBeginNanos = System.nanoTime(); - - // The following block of code is a copy of super.process(cud, index), - // with the modification that cud.generateCode is conditionally called - // based on doGenerateBytes - { - this.lookupEnvironment.unitBeingCompleted = unit; - long parseStart = System.currentTimeMillis(); - - this.parser.getMethodBodies(unit); - - long resolveStart = System.currentTimeMillis(); - this.stats.parseTime += resolveStart - parseStart; - - // fault in fields & methods - if (unit.scope != null) { - unit.scope.faultInTypes(); - } - - // verify inherited methods - if (unit.scope != null) { - unit.scope.verifyMethods(lookupEnvironment.methodVerifier()); - } - - // type checking - unit.resolve(); - - long analyzeStart = System.currentTimeMillis(); - this.stats.resolveTime += analyzeStart - resolveStart; - - // flow analysis - unit.analyseCode(); - - long generateStart = System.currentTimeMillis(); - this.stats.analyzeTime += generateStart - analyzeStart; - - // code generation - // code generation - if (doGenerateBytes) { - unit.generateCode(); - } - - // reference info - if (options.produceReferenceInfo && unit.scope != null) { - unit.scope.storeDependencyInfo(); - } - - // finalize problems (suppressWarnings) - unit.finalizeProblems(); - - this.stats.generateTime += System.currentTimeMillis() - generateStart; - - // refresh the total number of units known at this stage - unit.compilationResult.totalUnitsKnown = totalUnits; - - this.lookupEnvironment.unitBeingCompleted = null; - } - - ICompilationUnit cu = unit.compilationResult.compilationUnit; - String loc = String.valueOf(cu.getFileName()); - TreeLogger logger = threadLogger.branch(TreeLogger.SPAM, - "Scanning for additional dependencies: " + loc, null); - - // Examine the cud for magic types. - // - String[] typeNames = doFindAdditionalTypesUsingJsni(logger, unit); - addAdditionalTypes(logger, typeNames); - - typeNames = doFindAdditionalTypesUsingRebinds(logger, unit); - addAdditionalTypes(logger, typeNames); - - typeNames = doFindAdditionalTypesUsingArtificialRescues(logger, unit); - addAdditionalTypes(logger, typeNames); - - doCompilationUnitDeclarationValidation(unit, logger); - - // Optionally remember this cud. - // - if (cuds != null) { - cuds.add(unit); + private static class Sandbox { + + /** + * Adapted to hook the processing of compilation unit declarations so as to + * be able to add additional compilation units based on the results of + * previously-compiled ones. Examples of cases where this is useful include + * classes referenced only from JSNI and <code>GWT.create</code>. + */ + private class CompilerImpl extends Compiler { + + private Set<CompilationUnitDeclaration> cuds; + private long jdtProcessNanos; + + public CompilerImpl(INameEnvironment environment, + IErrorHandlingPolicy policy, CompilerOptions compilerOptions, + ICompilerRequestor requestor, IProblemFactory problemFactory) { + super(environment, policy, compilerOptions, requestor, problemFactory); + } + + @Override + public void compile(ICompilationUnit[] sourceUnits) { + jdtProcessNanos = 0; + super.compile(sourceUnits); + PerfLogger.log("AbstractCompiler.compile, time spent in JDT process callback: " + + (jdtProcessNanos / 1000000) + "ms"); + cuds = null; + } + + @Override + public void process(CompilationUnitDeclaration unit, int index) { + + long processBeginNanos = System.nanoTime(); + + // The following block of code is a copy of super.process(cud, index), + // with the modification that cud.generateCode is conditionally called + // based on doGenerateBytes + { + this.lookupEnvironment.unitBeingCompleted = unit; + long parseStart = System.currentTimeMillis(); + + this.parser.getMethodBodies(unit); + + long resolveStart = System.currentTimeMillis(); + this.stats.parseTime += resolveStart - parseStart; + + // fault in fields & methods + if (unit.scope != null) { + unit.scope.faultInTypes(); + } + + // verify inherited methods + if (unit.scope != null) { + unit.scope.verifyMethods(lookupEnvironment.methodVerifier()); + } + + // type checking + unit.resolve(); + + long analyzeStart = System.currentTimeMillis(); + this.stats.resolveTime += analyzeStart - resolveStart; + + // flow analysis + unit.analyseCode(); + + long generateStart = System.currentTimeMillis(); + this.stats.analyzeTime += generateStart - analyzeStart; + + // code generation + // code generation + if (doGenerateBytes) { + unit.generateCode(); + } + + // reference info + if (options.produceReferenceInfo && unit.scope != null) { + unit.scope.storeDependencyInfo(); + } + + // finalize problems (suppressWarnings) + unit.finalizeProblems(); + + this.stats.generateTime += System.currentTimeMillis() - generateStart; + + // refresh the total number of units known at this stage + unit.compilationResult.totalUnitsKnown = totalUnits; + + this.lookupEnvironment.unitBeingCompleted = null; + } + + ICompilationUnit cu = unit.compilationResult.compilationUnit; + String loc = String.valueOf(cu.getFileName()); + TreeLogger branch = logger.branch(TreeLogger.SPAM, + "Scanning for additional dependencies: " + loc, null); + + // Examine the cud for magic types. + // + String[] typeNames = outer.doFindAdditionalTypesUsingJsni(branch, unit); + addAdditionalTypes(branch, typeNames); + + typeNames = outer.doFindAdditionalTypesUsingRebinds(branch, unit); + addAdditionalTypes(branch, typeNames); + + typeNames = outer.doFindAdditionalTypesUsingArtificialRescues(branch, + unit); + addAdditionalTypes(branch, typeNames); + + // Optionally remember this cud. + // + if (cuds != null) { + cuds.add(unit); + } + + jdtProcessNanos += System.nanoTime() - processBeginNanos; } - jdtProcessNanos += System.nanoTime() - processBeginNanos; - } - - /** - * Helper method for process() that receives the types found by magic. This - * causes the compiler to find the additional type, possibly winding its - * back to ask for the compilation unit from the source oracle. - */ - private void addAdditionalTypes(TreeLogger logger, String[] typeNames) { - for (int i = 0; i < typeNames.length; i++) { - String typeName = typeNames[i]; - final String msg = "Need additional type '" + typeName + "'"; - logger.log(TreeLogger.SPAM, msg, null); - - resolvePossiblyNestedType(typeName); - } - } - - private void compile(ICompilationUnit[] units, - Set<CompilationUnitDeclaration> cuds) { - this.cuds = cuds; - compile(units); + /** + * Helper method for process() that receives the types found by magic. + * This causes the compiler to find the additional type, possibly winding + * its back to ask for the compilation unit from the source oracle. + */ + private void addAdditionalTypes(TreeLogger logger, String[] typeNames) { + for (int i = 0; i < typeNames.length; i++) { + String typeName = typeNames[i]; + final String msg = "Need additional type '" + typeName + "'"; + logger.log(TreeLogger.SPAM, msg, null); + + resolvePossiblyNestedType(typeName); + } + } + + private void compile(ICompilationUnit[] units, + Set<CompilationUnitDeclaration> cuds) { + this.cuds = cuds; + compile(units); + } + + private ReferenceBinding resolvePossiblyNestedType(String typeName) { + return JdtCompiler.resolveType(lookupEnvironment, typeName); + } } - private ReferenceBinding resolvePossiblyNestedType(String typeName) { - return JdtCompiler.resolveType(lookupEnvironment, typeName); - } - } - - private class ICompilerRequestorImpl implements ICompilerRequestor { - - public ICompilerRequestorImpl() { - } - - public void acceptResult(CompilationResult result) { - // Handle compilation errors. - // - IProblem[] errors = result.getErrors(); - - if (errors != null && errors.length > 0) { - // Dump it to disk. - // - String fn = String.valueOf(result.compilationUnit.getFileName()); - String msg = "Errors in '" + fn + "'"; - TreeLogger branch = getLogger().branch(TreeLogger.ERROR, msg, null); - - for (int i = 0; i < errors.length; i++) { - IProblem error = errors[i]; - - // Strip the initial code from each error. - // - msg = error.toString(); - msg = msg.substring(msg.indexOf(' ')); - - // Append 'Line #: msg' to the error message. - // - StringBuffer msgBuf = new StringBuffer(); - int line = error.getSourceLineNumber(); - if (line > 0) { - msgBuf.append("Line "); - msgBuf.append(line); - msgBuf.append(": "); - } - msgBuf.append(msg); - - HelpInfo helpInfo = null; - if (error instanceof GWTProblem) { - GWTProblem gwtProblem = (GWTProblem) error; - helpInfo = gwtProblem.getHelpInfo(); - } - branch.log(TreeLogger.ERROR, msgBuf.toString(), null, helpInfo); + private class ICompilerRequestorImpl implements ICompilerRequestor { + + public ICompilerRequestorImpl() { + } + + public void acceptResult(CompilationResult result) { + // Handle compilation errors. + // + IProblem[] errors = result.getErrors(); + + if (errors != null && errors.length > 0) { + // Dump it to disk. + // + String fn = String.valueOf(result.compilationUnit.getFileName()); + String msg = "Errors in '" + fn + "'"; + TreeLogger branch = logger.branch(TreeLogger.ERROR, msg, null); + + for (int i = 0; i < errors.length; i++) { + IProblem error = errors[i]; + + // Strip the initial code from each error. + // + msg = error.toString(); + msg = msg.substring(msg.indexOf(' ')); + + // Append 'Line #: msg' to the error message. + // + StringBuffer msgBuf = new StringBuffer(); + int line = error.getSourceLineNumber(); + if (line > 0) { + msgBuf.append("Line "); + msgBuf.append(line); + msgBuf.append(": "); + } + msgBuf.append(msg); + + HelpInfo helpInfo = null; + if (error instanceof GWTProblem) { + GWTProblem gwtProblem = (GWTProblem) error; + helpInfo = gwtProblem.getHelpInfo(); + } + branch.log(TreeLogger.ERROR, msgBuf.toString(), null, helpInfo); + } } } - - // Let the subclass do something with this if it wants to. - // - doAcceptResult(result); - } - } - - private class INameEnvironmentImpl implements INameEnvironment { - - public INameEnvironmentImpl() { - } - - public void cleanup() { - // intentionally blank - } - - public NameEnvironmentAnswer findType(char[] type, char[][] pkg) { - return findType(CharOperation.arrayConcat(pkg, type)); - } - - public NameEnvironmentAnswer findType(char[][] compoundTypeName) { - String qname = CharOperation.toString(compoundTypeName); - TreeLogger logger = threadLogger.branch(TreeLogger.SPAM, - "Compiler is asking about '" + qname + "'", null); - - if (isPackage(qname)) { - logger.log(TreeLogger.SPAM, "Found to be a package", null); - return null; - } - - // Didn't find it in the cache, so let's compile from source. - // Strip off the inner types, if any - // - String className = qname; - int pos = qname.indexOf('$'); - if (pos >= 0) { - qname = qname.substring(0, pos); - } - CompilationUnit unit = findCompilationUnit(qname); - if (unit != null) { - logger.log(TreeLogger.SPAM, "Found type in compilation unit: " - + unit.getDisplayLocation()); - ICompilationUnit icu = new CompilationUnitAdapter(unit); - return new NameEnvironmentAnswer(icu, null); - } else { - ClassLoader classLoader = getClassLoader(); - URL resourceURL = classLoader.getResource(className.replace('.', '/') - + ".class"); - if (resourceURL != null) { - /* - * We know that there is a .class file that matches the name that we - * are looking for. However, at least on OSX, this lookup is case - * insensitive so we need to use Class.forName to effectively verify - * the case. - */ - if (isBinaryType(classLoader, className)) { - byte[] classBytes = Util.readURLAsBytes(resourceURL); - ClassFileReader cfr; - try { - cfr = new ClassFileReader(classBytes, null); - return new NameEnvironmentAnswer(cfr, null); - } catch (ClassFormatException e) { - // Ignored. + } + + private class INameEnvironmentImpl implements INameEnvironment { + + public INameEnvironmentImpl() { + } + + public void cleanup() { + // intentionally blank + } + + public NameEnvironmentAnswer findType(char[] type, char[][] pkg) { + return findType(CharOperation.arrayConcat(pkg, type)); + } + + public NameEnvironmentAnswer findType(char[][] compoundTypeName) { + String qname = CharOperation.toString(compoundTypeName); + TreeLogger branch = logger.branch(TreeLogger.SPAM, + "Compiler is asking about '" + qname + "'", null); + + if (isPackage(qname)) { + branch.log(TreeLogger.SPAM, "Found to be a package", null); + return null; + } + + // Didn't find it in the cache, so let's compile from source. + // Strip off the inner types, if any + // + String className = qname; + int pos = qname.indexOf('$'); + if (pos >= 0) { + qname = qname.substring(0, pos); + } + CompilationUnit unit = findCompilationUnit(qname); + if (unit != null) { + branch.log(TreeLogger.SPAM, "Found type in compilation unit: " + + unit.getDisplayLocation()); + ICompilationUnit icu = new CompilationUnitAdapter(unit); + return new NameEnvironmentAnswer(icu, null); + } else { + ClassLoader classLoader = getClassLoader(); + URL resourceURL = classLoader.getResource(className.replace('.', '/') + + ".class"); + if (resourceURL != null) { + /* + * We know that there is a .class file that matches the name that we + * are looking for. However, at least on OSX, this lookup is case + * insensitive so we need to use Class.forName to effectively verify + * the case. + */ + if (isBinaryType(classLoader, className)) { + byte[] classBytes = Util.readURLAsBytes(resourceURL); + ClassFileReader cfr; + try { + cfr = new ClassFileReader(classBytes, null); + return new NameEnvironmentAnswer(cfr, null); + } catch (ClassFormatException e) { + // Ignored. + } } } - } - - logger.log(TreeLogger.SPAM, "Not a known type", null); - return null; - } - } - - public boolean isPackage(char[][] parentPkg, char[] pkg) { - // In special cases where class bytes are asserted from the outside, - // a package can exist that the host doesn't know about. We have to - // do a special check for these cases. - // - final char[] pathChars = CharOperation.concatWith(parentPkg, pkg, '.'); - String packageName = String.valueOf(pathChars); - if (knownPackages.contains(packageName)) { - return true; - } else if (isPackage(packageName) - || isPackage(getClassLoader(), packageName)) { - // Grow our own list to spare calls into the host. + + branch.log(TreeLogger.SPAM, "Not a known type", null); + return null; + } + } + + public boolean isPackage(char[][] parentPkg, char[] pkg) { + // In special cases where class bytes are asserted from the outside, + // a package can exist that the host doesn't know about. We have to + // do a special check for these cases. // - rememberPackage(packageName); - return true; - } else { + final char[] pathChars = CharOperation.concatWith(parentPkg, pkg, '.'); + String packageName = String.valueOf(pathChars); + if (isPackage(packageName)) { + return true; + } else if (isPackage(getClassLoader(), packageName)) { + // Grow our own list to spare calls into the host. + // + rememberPackage(packageName); + return true; + } else { + return false; + } + } + + private ClassLoader getClassLoader() { + return Thread.currentThread().getContextClassLoader(); + } + + private boolean isBinaryType(ClassLoader classLoader, String typeName) { + try { + Class.forName(typeName, false, classLoader); + return true; + } catch (ClassNotFoundException e) { + // Ignored. + } catch (LinkageError e) { + // Ignored. + } + + // Assume that it is not a binary type. return false; } - } - - private ClassLoader getClassLoader() { - return Thread.currentThread().getContextClassLoader(); + + private boolean isPackage(ClassLoader classLoader, String packageName) { + String packageAsPath = packageName.replace('.', '/'); + return classLoader.getResource(packageAsPath) != null; + } + + private boolean isPackage(String packageName) { + return knownPackages.contains(packageName); + } } - private boolean isBinaryType(ClassLoader classLoader, String typeName) { - try { - Class.forName(typeName, false, classLoader); - return true; - } catch (ClassNotFoundException e) { - // Ignored. - } catch (LinkageError e) { - // Ignored. - } - - // Assume that it is not a binary type. - return false; + final CompilerImpl compiler; + final boolean doGenerateBytes; + final Set<String> knownPackages = new HashSet<String>(); + TreeLogger logger = null; + AbstractCompiler outer; + + Sandbox(AbstractCompiler outer, boolean doGenerateBytes) { + this.outer = outer; + this.doGenerateBytes = doGenerateBytes; + rememberPackage(""); + + INameEnvironment env = new INameEnvironmentImpl(); + IErrorHandlingPolicy pol = DefaultErrorHandlingPolicies.proceedWithAllProblems(); + IProblemFactory probFact = new DefaultProblemFactory(Locale.getDefault()); + ICompilerRequestor req = new ICompilerRequestorImpl(); + CompilerOptions options = getCompilerOptions(); + + // This is only needed by TypeOracleBuilder to parse metadata. + options.docCommentSupport = false; + + compiler = new CompilerImpl(env, pol, options, req, probFact); + + // Initialize the packages list. + for (CompilationUnit unit : outer.compilationState.getCompilationUnits()) { + String packageName = Shared.getPackageName(unit.getTypeName()); + rememberPackage(packageName); + } + } + + public void clear() { + outer = null; + logger = null; } - private boolean isPackage(ClassLoader classLoader, String packageName) { - String packageAsPath = packageName.replace('.', '/'); - return classLoader.getResource(packageAsPath) != null; + private CompilationUnit findCompilationUnit(String qname) { + // Build the initial set of compilation units. + Map<String, CompilationUnit> unitMap = outer.compilationState.getCompilationUnitMap(); + CompilationUnit unit = unitMap.get(qname); + while (unit == null) { + int pos = qname.lastIndexOf('.'); + if (pos < 0) { + return null; + } + qname = qname.substring(0, pos); + unit = unitMap.get(qname); + } + return unit; } - private boolean isPackage(String packageName) { - return packages.contains(packageName); + /** + * Causes the compilation service itself to recognize the specified package + * name (and all its parent packages), avoiding a call back into the host. + * This is useful as an optimization, but more importantly, it is useful to + * compile against bytecode that was pre-compiled to which we don't have the + * source. This ability is crucial bridging the gap between user-level and + * "dev" code in hosted mode for classes such as JavaScriptHost and + * ShellJavaScriptHost. + */ + private void rememberPackage(String packageName) { + int i = packageName.lastIndexOf('.'); + if (i != -1) { + // Ensure the parent package is also created. + // + rememberPackage(packageName.substring(0, i)); + } + knownPackages.add(packageName); } } @@ -435,73 +500,34 @@ return options; } - protected final CompilationState compilationState; - - protected final ThreadLocalTreeLoggerProxy threadLogger = new ThreadLocalTreeLoggerProxy(); - - private final CompilerImpl compiler; - - private final boolean doGenerateBytes; - - private final Set<String> knownPackages = new HashSet<String>(); - - private final Set<String> packages = new HashSet<String>(); + private Sandbox sandbox; + protected CompilationState compilationState; protected AbstractCompiler(CompilationState compilationState, boolean doGenerateBytes) { this.compilationState = compilationState; - this.doGenerateBytes = doGenerateBytes; - rememberPackage(""); - - INameEnvironment env = new INameEnvironmentImpl(); - IErrorHandlingPolicy pol = DefaultErrorHandlingPolicies.proceedWithAllProblems(); - IProblemFactory probFact = new DefaultProblemFactory(Locale.getDefault()); - ICompilerRequestor req = new ICompilerRequestorImpl(); - CompilerOptions options = getCompilerOptions(); - - // This is only needed by TypeOracleBuilder to parse metadata. - options.docCommentSupport = false; - - compiler = new CompilerImpl(env, pol, options, req, probFact); + this.sandbox = new Sandbox(this, doGenerateBytes); } protected final CompilationUnitDeclaration[] compile(TreeLogger logger, ICompilationUnit[] units) { - // Initialize the packages list. - for (CompilationUnit unit : compilationState.getCompilationUnits()) { - String packageName = Shared.getPackageName(unit.getTypeName()); - addPackages(packageName); - } // Any additional compilation units that are found to be needed will be // pulled in while procssing compilation units. See CompilerImpl.process(). // - TreeLogger oldLogger = threadLogger.push(logger); + sandbox.logger = logger; try { Set<CompilationUnitDeclaration> cuds = new TreeSet<CompilationUnitDeclaration>( CUD_COMPARATOR); - compiler.compile(units, cuds); + sandbox.compiler.compile(units, cuds); int size = cuds.size(); CompilationUnitDeclaration[] cudArray = new CompilationUnitDeclaration[size]; return cuds.toArray(cudArray); } finally { - threadLogger.pop(oldLogger); + sandbox.clear(); + sandbox = null; } } - - @SuppressWarnings("unused") - // overrider may use unused parameter - protected void doAcceptResult(CompilationResult result) { - // Do nothing by default. - // - } - - @SuppressWarnings("unused") - // overrider may use unused parameter - protected void doCompilationUnitDeclarationValidation( - CompilationUnitDeclaration cud, TreeLogger logger) { - // Do nothing by default. - } @SuppressWarnings("unused") // overrider may use unused parameter @@ -524,61 +550,7 @@ return Empty.STRINGS; } - protected CompilationUnit findCompilationUnit(String qname) { - // Build the initial set of compilation units. - Map<String, CompilationUnit> unitMap = compilationState.getCompilationUnitMap(); - CompilationUnit unit = unitMap.get(qname); - while (unit == null) { - int pos = qname.lastIndexOf('.'); - if (pos < 0) { - return null; - } - qname = qname.substring(0, pos); - unit = unitMap.get(qname); - } - return unit; - } - - protected TreeLogger getLogger() { - return threadLogger; - } - - /** - * Causes the compilation service itself to recognize the specified package - * name (and all its parent packages), avoiding a call back into the host. - * This is useful as an optimization, but more importantly, it is useful to - * compile against bytecode that was pre-compiled to which we don't have the - * source. This ability is crucial bridging the gap between user-level and - * "dev" code in hosted mode for classes such as JavaScriptHost and - * ShellJavaScriptHost. - */ - protected void rememberPackage(String packageName) { - int i = packageName.lastIndexOf('.'); - if (i != -1) { - // Ensure the parent package is also created. - // - rememberPackage(packageName.substring(0, i)); - } - knownPackages.add(packageName); - } - - protected ReferenceBinding resolvePossiblyNestedType(String typeName) { - return compiler.resolvePossiblyNestedType(typeName); - } - - private void addPackages(String packageName) { - if (packages.contains(packageName)) { - return; - } - while (true) { - packages.add(String.valueOf(packageName)); - int pos = packageName.lastIndexOf('.'); - if (pos > 0) { - packageName = packageName.substring(0, pos); - } else { - packages.add(""); - break; - } - } + protected final ReferenceBinding resolvePossiblyNestedType(String typeName) { + return sandbox.compiler.resolvePossiblyNestedType(typeName); } } ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/FindJsniRefVisitor.java Tue Jul 28 21:10:00 2009 +++ /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/FindJsniRefVisitor.java Wed Nov 11 17:18:27 2009 @@ -26,10 +26,6 @@ import com.google.gwt.dev.js.ast.JsProgram; import com.google.gwt.dev.js.ast.JsStatement; import com.google.gwt.dev.js.ast.JsVisitor; -import com.google.gwt.dev.js.rhino.Context; -import com.google.gwt.dev.js.rhino.ErrorReporter; -import com.google.gwt.dev.js.rhino.EvaluatorException; -import com.google.gwt.dev.js.rhino.TokenStream; import org.eclipse.jdt.internal.compiler.ASTVisitor; import org.eclipse.jdt.internal.compiler.ast.Argument; @@ -37,7 +33,6 @@ import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import java.io.IOException; -import java.io.Reader; import java.io.StringReader; import java.util.Collections; import java.util.LinkedHashSet; @@ -51,32 +46,7 @@ * quickly but it will return a superset of the actual JSNI references. */ public class FindJsniRefVisitor extends ASTVisitor { - /** - * A Rhino error reporter that discards any errors it sees. - */ - private static ErrorReporter NullErrorReporter = new ErrorReporter() { - public void error(String message, String sourceName, int line, - String lineSource, int lineOffset) { - // ignore it - } - - public EvaluatorException runtimeError(String message, String sourceName, - int line, String lineSource, int lineOffset) { - throw new InternalCompilerException("Rhino run-time error: " + message); - } - - public void warning(String message, String sourceName, int line, - String lineSource, int lineOffset) { - // ignore it - } - }; - private final Set<String> jsniRefs = new LinkedHashSet<String>(); - private boolean sloppy = false; - - public void beSloppy() { - sloppy = true; - } public Set<String> getJsniRefs() { return Collections.unmodifiableSet(jsniRefs); @@ -97,12 +67,7 @@ return false; } - if (sloppy) { - findJsniRefsSloppily(jsniCode); - } else { - findJsniRefsAccurately(methodDeclaration, jsniCode); - } - + findJsniRefsAccurately(methodDeclaration, jsniCode); return false; } @@ -143,33 +108,6 @@ // ignore, we only care about finding valid references } } - - private void findJsniRefsSloppily(String jsniCode) { - StringReader reader = new StringReader(jsniCode); - int idx = 0; - while (true) { - idx = jsniCode.indexOf('@', idx); - if (idx < 0) { - break; - } - try { - reader.reset(); - // Ignore return value, since we know the index is valid. - reader.skip(idx); - } catch (IOException e) { - throw new InternalCompilerException(e.getMessage(), e); - } - String jsniRefString = readJsIdentifier(reader); - if (jsniRefString == null) { - // badly formatted identifier; skip to the next @ sign - idx++; - } else { - assert (jsniRefString.charAt(0) == '@'); - jsniRefs.add(jsniRefString.substring(1)); - idx += jsniRefString.length(); - } - } - } private String getJSNICode(MethodDeclaration methodDeclaration) { char[] source = methodDeclaration.compilationResult().getCompilationUnit().getContents(); @@ -187,25 +125,5 @@ jsniCode = jsniCode.substring(startPos, endPos); return jsniCode; } - - /** - * Read a JavaScript identifier using Rhino. If the parse fails, returns null. - */ - private String readJsIdentifier(Reader reader) - throws InternalCompilerException { - try { - Context.enter().setErrorReporter(NullErrorReporter); - TokenStream tokStr = new TokenStream(reader, "(memory)", 0); - if (tokStr.getToken() == TokenStream.NAME) { - return tokStr.getString(); - } else { - return null; - } - } catch (IOException e) { - throw new InternalCompilerException(e.getMessage(), e); - } finally { - Context.exit(); - } - } } ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/RebindPermutationOracle.java Wed Nov 11 11:04:31 2009 +++ /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/RebindPermutationOracle.java Wed Nov 11 17:18:27 2009 @@ -26,6 +26,13 @@ */ public interface RebindPermutationOracle { + /** + * Called when the compiler is done with this oracle, so memory can be freed + * up. After calling this method, the only legal method to call is + * {...@link #getAllPossibleRebindAnswers}. + */ + void clear(); + /** * Always answers with at least one name. */ ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/WebModeCompilerFrontEnd.java Wed Nov 11 11:04:31 2009 +++ /releases/2.0/dev/core/src/com/google/gwt/dev/jdt/WebModeCompilerFrontEnd.java Wed Nov 11 17:18:27 2009 @@ -63,15 +63,6 @@ this.fragmentLoaderCreator = new FragmentLoaderCreator( rebindPermOracle.getGeneratorContext()); } - - @Override - protected void doCompilationUnitDeclarationValidation( - CompilationUnitDeclaration cud, TreeLogger logger) { - /* - * Anything that makes it here was already checked by AstCompiler while - * building TypeOracle; no need to rerun checks. - */ - } @Override protected String[] doFindAdditionalTypesUsingArtificialRescues( ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java Tue Aug 4 09:54:58 2009 +++ /releases/2.0/dev/core/src/com/google/gwt/dev/jjs/JJSOptions.java Wed Nov 11 17:18:27 2009 @@ -16,7 +16,6 @@ package com.google.gwt.dev.jjs; import com.google.gwt.dev.util.arg.OptionAggressivelyOptimize; -import com.google.gwt.dev.util.arg.OptionCompilationStateRetained; import com.google.gwt.dev.util.arg.OptionDisableCastChecking; import com.google.gwt.dev.util.arg.OptionDisableClassMetadata; import com.google.gwt.dev.util.arg.OptionDraftCompile; @@ -24,8 +23,8 @@ import com.google.gwt.dev.util.arg.OptionOptimizePrecompile; import com.google.gwt.dev.util.arg.OptionRunAsyncEnabled; import com.google.gwt.dev.util.arg.OptionScriptStyle; -import com.google.gwt.dev.util.arg.OptionSoycEnabled; import com.google.gwt.dev.util.arg.OptionSoycDetailed; +import com.google.gwt.dev.util.arg.OptionSoycEnabled; /** * Controls options for the {...@link JavaToJavaScriptCompiler}. @@ -33,5 +32,5 @@ public interface JJSOptions extends OptionAggressivelyOptimize, OptionDisableClassMetadata, OptionDisableCastChecking, OptionDraftCompile, OptionEnableAssertions, OptionRunAsyncEnabled, OptionScriptStyle, - OptionSoycEnabled, OptionSoycDetailed, OptionCompilationStateRetained, OptionOptimizePrecompile { -} + OptionSoycEnabled, OptionSoycDetailed, OptionOptimizePrecompile { +} ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java Tue Aug 4 09:54:58 2009 +++ /releases/2.0/dev/core/src/com/google/gwt/dev/jjs/JJSOptionsImpl.java Wed Nov 11 17:18:27 2009 @@ -23,7 +23,6 @@ public class JJSOptionsImpl implements JJSOptions, Serializable { private boolean aggressivelyOptimize = true; - private boolean compilationStateRetained = false; private boolean disableCastChecking = false; private boolean disableClassMetadata = false; private boolean draftCompile = false; @@ -45,7 +44,6 @@ setAggressivelyOptimize(other.isAggressivelyOptimize()); setCastCheckingDisabled(other.isCastCheckingDisabled()); setClassMetadataDisabled(other.isClassMetadataDisabled()); - setCompilationStateRetained(other.isCompilationStateRetained()); setDraftCompile(other.isDraftCompile()); setEnableAssertions(other.isEnableAssertions()); setOutput(other.getOutput()); @@ -69,10 +67,6 @@ public boolean isClassMetadataDisabled() { return disableClassMetadata; } - - public boolean isCompilationStateRetained() { - return compilationStateRetained; - } public boolean isDraftCompile() { return draftCompile; @@ -109,10 +103,6 @@ public void setClassMetadataDisabled(boolean disabled) { disableClassMetadata = disabled; } - - public void setCompilationStateRetained(boolean retained) { - compilationStateRetained = retained; - } public void setDraftCompile(boolean draft) { this.draftCompile = draft; ======================================= --- /releases/2.0/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java Wed Nov 11 11:04:31 2009 +++ /releases/2.0/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java Wed Nov 11 17:18:27 2009 @@ -421,9 +421,7 @@ logger, allRootTypes.toArray(new String[allRootTypes.size()]), rpo); // Free up memory. - if (!options.isCompilationStateRetained()) { - module.clear(); - } + rpo.clear(); try { // HACK: Make i18n free its internal static state. Class<?> clazz = Class.forName( @@ -432,6 +430,7 @@ clazz.getDeclaredMethod("clear").invoke(null); } catch (Throwable e) { } + Memory.maybeDumpMemory("GoldenCudsBuilt"); // Check for compilation problems. We don't log here because any problems // found here will have already been logged by AbstractCompiler. ======================================= --- /releases/2.0/user/src/com/google/gwt/junit/JUnitShell.java Wed Nov 11 11:04:31 2009 +++ /releases/2.0/user/src/com/google/gwt/junit/JUnitShell.java Wed Nov 11 17:18:27 2009 @@ -918,7 +918,6 @@ } } LegacyCompilerOptions newOptions = new GWTCompilerOptionsImpl(options); - newOptions.setCompilationStateRetained(true); if (!new GWTCompiler(newOptions).run(getTopLogger(), module)) { throw new UnableToCompleteException(); } --~--~---------~--~----~------------~-------~--~----~ http://groups.google.com/group/Google-Web-Toolkit-Contributors -~----------~----~----~----~------~----~------~--~---
