Allow JTypeOracle information to be reused across compiles. Change-Id: I8afe419c0e41004882a0c9da7fc965fdb5dd12a9 Review-Link: https://gwt-review.googlesource.com/#/c/8418/
diff --git a/dev/BUILD b/dev/BUILD index fe265e6..44b019f 100644 --- a/dev/BUILD +++ b/dev/BUILD
@@ -186,6 +186,7 @@ "core/src/com/google/gwt/dev/CompileTaskOptionsImpl.java", "core/src/com/google/gwt/dev/GwtCreateMap.java", "core/src/com/google/gwt/dev/GwtVersion.java", + "core/src/com/google/gwt/dev/MinimalRebuildCache.java", "core/src/com/google/gwt/dev/Permutation.java", "core/src/com/google/gwt/dev/PrecompileTaskOptions.java", "core/src/com/google/gwt/dev/PrecompileTaskOptionsImpl.java",
diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/ModuleState.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/ModuleState.java index d63c706..20fda87 100644 --- a/dev/codeserver/java/com/google/gwt/dev/codeserver/ModuleState.java +++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/ModuleState.java
@@ -78,7 +78,7 @@ */ boolean recompile(Map<String, String> bindingProperties, AtomicReference<Progress> progress) { try { - current.set(recompiler.compile(bindingProperties, progress)); + current.set(recompiler.recompile(bindingProperties, progress)); return true; } catch (UnableToCompleteException e) { logger.log(TreeLogger.Type.WARN, "continuing to serve previous version");
diff --git a/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java b/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java index 4518f21..abef180 100644 --- a/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java +++ b/dev/codeserver/java/com/google/gwt/dev/codeserver/Recompiler.java
@@ -25,6 +25,7 @@ import com.google.gwt.dev.CompilerOptions; import com.google.gwt.dev.IncrementalBuilder; import com.google.gwt.dev.IncrementalBuilder.BuildResultStatus; +import com.google.gwt.dev.MinimalRebuildCache; import com.google.gwt.dev.cfg.BindingProperty; import com.google.gwt.dev.cfg.ConfigProps; import com.google.gwt.dev.cfg.ConfigurationProperty; @@ -56,6 +57,7 @@ private final TreeLogger logger; private String serverPrefix; private int compilesDone = 0; + private MinimalRebuildCache minimalRebuildCache; // after renaming private AtomicReference<String> moduleName = new AtomicReference<String>(null); @@ -77,10 +79,22 @@ compilerContext = compilerContextBuilder.build(); } - synchronized CompileDir compile(Map<String, String> bindingProperties, - AtomicReference<Progress> progress) + CompileDir recompile(Map<String, String> bindingProperties, AtomicReference<Progress> progress) throws UnableToCompleteException { + if (options.shouldCompilePerFile()) { + return compile(bindingProperties, progress, minimalRebuildCache); + } + return compile(bindingProperties, progress, new MinimalRebuildCache()); + } + synchronized CompileDir compile(Map<String, String> bindingProperties, + AtomicReference<Progress> progress) throws UnableToCompleteException { + return compile(bindingProperties, progress, new MinimalRebuildCache()); + } + + private synchronized CompileDir compile(Map<String, String> bindingProperties, + AtomicReference<Progress> progress, MinimalRebuildCache minimalRebuildCache) + throws UnableToCompleteException { if (compilesDone == 0) { System.setProperty("java.awt.headless", "true"); if (System.getProperty("gwt.speedtracerlog") == null) { @@ -112,7 +126,8 @@ success = compileIncremental(compileLogger, compileDir); } else { - success = compileMonolithic(compileLogger, bindingProperties, compileDir, progress); + success = compileMonolithic(compileLogger, bindingProperties, compileDir, progress, + minimalRebuildCache); } } finally { try { @@ -128,6 +143,9 @@ throw new UnableToCompleteException(); } + // keep the minimal rebuild cache for the next compile + this.minimalRebuildCache = minimalRebuildCache; + long elapsedTime = System.currentTimeMillis() - startTime; compileLogger.log(TreeLogger.Type.INFO, String.format("%.3fs total -- Compile completed", elapsedTime / 1000d)); @@ -208,7 +226,8 @@ } private boolean compileMonolithic(TreeLogger compileLogger, Map<String, String> bindingProperties, - CompileDir compileDir, AtomicReference<Progress> progress) throws UnableToCompleteException { + CompileDir compileDir, AtomicReference<Progress> progress, MinimalRebuildCache rebuildCache) + throws UnableToCompleteException { progress.set(new Progress.Compiling(moduleName.get(), compilesDone, 0, 2, "Loading modules")); @@ -226,7 +245,7 @@ CompilerOptions runOptions = new CompilerOptionsImpl(compileDir, newModuleName, options); compilerContext = compilerContextBuilder.options(runOptions).build(); - boolean success = new Compiler(runOptions).run(compileLogger, module); + boolean success = new Compiler(runOptions, rebuildCache).run(compileLogger, module); if (success) { publishedCompileDir = compileDir; }
diff --git a/dev/core/src/com/google/gwt/dev/Compiler.java b/dev/core/src/com/google/gwt/dev/Compiler.java index 320e8b1..8b46fe7 100644 --- a/dev/core/src/com/google/gwt/dev/Compiler.java +++ b/dev/core/src/com/google/gwt/dev/Compiler.java
@@ -123,9 +123,14 @@ private final CompilerOptionsImpl options; public Compiler(CompilerOptions compilerOptions) { + this(compilerOptions, new MinimalRebuildCache()); + } + + public Compiler(CompilerOptions compilerOptions, MinimalRebuildCache minimalRebuildCache) { this.options = new CompilerOptionsImpl(compilerOptions); this.compilerContextBuilder = new CompilerContext.Builder(); - this.compilerContext = compilerContextBuilder.options(options).build(); + this.compilerContext = compilerContextBuilder.options(options) + .minimalRebuildCache(minimalRebuildCache).build(); } public boolean run(TreeLogger logger) throws UnableToCompleteException {
diff --git a/dev/core/src/com/google/gwt/dev/CompilerContext.java b/dev/core/src/com/google/gwt/dev/CompilerContext.java index 5155d9d..410d265 100644 --- a/dev/core/src/com/google/gwt/dev/CompilerContext.java +++ b/dev/core/src/com/google/gwt/dev/CompilerContext.java
@@ -46,6 +46,7 @@ private ResourceOracle buildResourceOracle; private boolean compileMonolithic = true; + private MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); private CompilationErrorsIndex globalCompilationErrorsIndex; private CompilationErrorsIndex libraryCompilationErrorsIndex; private LibraryGroup libraryGroup = new ImmutableLibraryGroup(); @@ -63,6 +64,7 @@ CompilerContext compilerContext = new CompilerContext(); compilerContext.buildResourceOracle = buildResourceOracle; + compilerContext.minimalRebuildCache = minimalRebuildCache; compilerContext.libraryWriter = libraryWriter; compilerContext.libraryGroup = libraryGroup; compilerContext.module = module; @@ -110,6 +112,12 @@ return this; } + public Builder minimalRebuildCache(MinimalRebuildCache minimalRebuildCache) { + assert minimalRebuildCache != null; + this.minimalRebuildCache = minimalRebuildCache; + return this; + } + public Builder unitCache(UnitCache unitCache) { this.unitCache = unitCache; return this; @@ -169,6 +177,8 @@ * they should be grouped together instead of floating free here. */ private boolean compileMonolithic = true; + + private MinimalRebuildCache minimalRebuildCache = new MinimalRebuildCache(); private LibraryGroup libraryGroup = new ImmutableLibraryGroup(); private LibraryWriter libraryWriter = new NullLibraryWriter(); private CompilationErrorsIndex localCompilationErrorsIndex = new CompilationErrorsIndexImpl(); @@ -188,6 +198,10 @@ return buildResourceOracle; } + public MinimalRebuildCache getMinimalRebuildCache() { + return minimalRebuildCache; + } + /** * Returns the immutable compilation errors index that provides a combined view of compilation * errors for both the current compile as well as previously compiled libraries.
diff --git a/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java new file mode 100644 index 0000000..72a0059 --- /dev/null +++ b/dev/core/src/com/google/gwt/dev/MinimalRebuildCache.java
@@ -0,0 +1,32 @@ +/* + * Copyright 2014 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; + +import com.google.gwt.dev.jjs.ast.JTypeOracle.ImmediateTypeRelations; + +import java.io.Serializable; + +/** + * MinimalRebuildCache contains compiler information that can be persisted between compiles to + * decrease compilation time. + */ +public class MinimalRebuildCache implements Serializable { + private ImmediateTypeRelations immediateTypeRelations = new ImmediateTypeRelations(); + + public ImmediateTypeRelations getImmediateTypeRelations() { + return immediateTypeRelations; + } +}
diff --git a/dev/core/src/com/google/gwt/dev/jjs/AstConstructor.java b/dev/core/src/com/google/gwt/dev/jjs/AstConstructor.java index 744dfdf..df06c8d 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/AstConstructor.java +++ b/dev/core/src/com/google/gwt/dev/jjs/AstConstructor.java
@@ -18,6 +18,7 @@ import com.google.gwt.core.ext.TreeLogger; import com.google.gwt.core.ext.UnableToCompleteException; import com.google.gwt.dev.CompilerContext; +import com.google.gwt.dev.MinimalRebuildCache; import com.google.gwt.dev.PrecompileTaskOptions; import com.google.gwt.dev.cfg.ConfigProps; import com.google.gwt.dev.javac.CompilationState; @@ -49,7 +50,8 @@ InternalCompilerException.preload(); - CompilerContext compilerContext = new CompilerContext.Builder().options(options).build(); + CompilerContext compilerContext = new CompilerContext.Builder().options(options) + .minimalRebuildCache(new MinimalRebuildCache()).build(); RebindPermutationOracle rpo = new RebindPermutationOracle() { @Override @@ -73,7 +75,7 @@ } }; - JProgram jprogram = new JProgram(); + JProgram jprogram = new JProgram(compilerContext.getMinimalRebuildCache()); JsProgram jsProgram = new JsProgram(); UnifyAst unifyAst = new UnifyAst(logger, compilerContext, jprogram, jsProgram, rpo); unifyAst.buildEverything();
diff --git a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java index a21e4c2..e41a2b3 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java +++ b/dev/core/src/com/google/gwt/dev/jjs/JavaToJavaScriptCompiler.java
@@ -827,7 +827,7 @@ protected abstract void checkEntryPoints(String[] additionalRootTypes); - protected abstract void createJProgram(); + protected abstract void createJProgram(CompilerContext compilerContext); /** * Takes as input a CompilationState and transforms that into a unified by not yet resolved Java @@ -863,7 +863,7 @@ */ // (1) Initialize local state - createJProgram(); + createJProgram(compilerContext); // Synchronize JTypeOracle with compile optimization behavior. jprogram.typeOracle.setOptimize( options.getOptimizationLevel() > OptionOptimize.OPTIMIZE_LEVEL_DRAFT);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/LibraryJavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/LibraryJavaToJavaScriptCompiler.java index cc05df7..edec35a 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/LibraryJavaToJavaScriptCompiler.java +++ b/dev/core/src/com/google/gwt/dev/jjs/LibraryJavaToJavaScriptCompiler.java
@@ -165,8 +165,8 @@ } @Override - protected void createJProgram() { - jprogram = new JProgram(false); + protected void createJProgram(CompilerContext compilerContext) { + jprogram = new JProgram(compilerContext.getMinimalRebuildCache(), false); } @VisibleForTesting
diff --git a/dev/core/src/com/google/gwt/dev/jjs/MonolithicJavaToJavaScriptCompiler.java b/dev/core/src/com/google/gwt/dev/jjs/MonolithicJavaToJavaScriptCompiler.java index e93fa33..427181f 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/MonolithicJavaToJavaScriptCompiler.java +++ b/dev/core/src/com/google/gwt/dev/jjs/MonolithicJavaToJavaScriptCompiler.java
@@ -261,8 +261,8 @@ } @Override - protected void createJProgram() { - jprogram = new JProgram(); + protected void createJProgram(CompilerContext compilerContext) { + jprogram = new JProgram(compilerContext.getMinimalRebuildCache()); } }
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java index bdd0316..52ef015 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JProgram.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.dev.jjs.ast; +import com.google.gwt.dev.MinimalRebuildCache; import com.google.gwt.dev.jjs.Correlation.Literal; import com.google.gwt.dev.jjs.InternalCompilerException; import com.google.gwt.dev.jjs.SourceInfo; @@ -377,14 +378,14 @@ pinnedMethods.add(method); } - public JProgram() { + public JProgram(MinimalRebuildCache minimalRebuildCache) { super(SourceOrigin.UNKNOWN); - typeOracle = new JTypeOracle(this, true); + typeOracle = new JTypeOracle(this, minimalRebuildCache, true); } - public JProgram(boolean hasWholeWorldKnowledge) { + public JProgram(MinimalRebuildCache minimalRebuildCache, boolean hasWholeWorldKnowledge) { super(SourceOrigin.UNKNOWN); - typeOracle = new JTypeOracle(this, hasWholeWorldKnowledge); + typeOracle = new JTypeOracle(this, minimalRebuildCache, hasWholeWorldKnowledge); } public void addEntryMethod(JMethod entryPoint) {
diff --git a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java index fb03c8f..45d4892 100644 --- a/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java +++ b/dev/core/src/com/google/gwt/dev/jjs/ast/JTypeOracle.java
@@ -15,6 +15,7 @@ */ package com.google.gwt.dev.jjs.ast; +import com.google.gwt.dev.MinimalRebuildCache; import com.google.gwt.dev.jjs.ast.js.JMultiExpression; import com.google.gwt.dev.util.arg.JsInteropMode; import com.google.gwt.dev.util.collect.HashMap; @@ -485,14 +486,16 @@ /** * Constructs a new JTypeOracle. */ - public JTypeOracle(ArrayTypeCreator arrayTypeCreator, boolean hasWholeWorldKnowledge) { - this.immediateTypeRelations = new ImmediateTypeRelations(); + public JTypeOracle(ArrayTypeCreator arrayTypeCreator, MinimalRebuildCache minimalRebuildCache, + boolean hasWholeWorldKnowledge) { + this.immediateTypeRelations = minimalRebuildCache.getImmediateTypeRelations(); this.arrayTypeCreator = arrayTypeCreator; this.hasWholeWorldKnowledge = hasWholeWorldKnowledge; } /** - * True if the type is a JSO or interface implemented by JSO.. + * True if the type is a JSO or interface implemented by JSO or a JsType without + * prototype. */ public boolean canBeJavaScriptObject(JType type) { if (type instanceof JNonNullType) { @@ -502,8 +505,7 @@ } /** - * True if the type is a JSO or interface implemented by JSO or a JsType without - * prototype. + * True if the type is a JSO or interface implemented by JSO or a JsType without prototype. */ public boolean canCrossCastLikeJso(JType type) { JDeclaredType dtype = getNearestJsType(type, false); @@ -525,7 +527,7 @@ return true; } if (type instanceof JInterfaceType && isImplementedMap.get(type.getName()) != null) { - for (JReferenceType impl : getTypes(isImplementedMap, (JReferenceType) type)) { + for (JReferenceType impl : getTypes(isImplementedMap, type.getName())) { if (isInstantiatedType((JClassType) impl)) { return true; } @@ -692,6 +694,14 @@ return false; } + public void updateImmediateTypeRelations(Set<JDeclaredType> changedTypes, + Set<JDeclaredType> deletedTypes) { + deleteImmediateTypeRelations(deletedTypes); + deleteImmediateTypeRelations(changedTypes); + recordImmediateTypeRelations(changedTypes); + computeExtendedTypeRelations(); + } + public void computeBeforeAST(StandardTypes standardTypes, Collection<JDeclaredType> declaredTypes) { this.standardTypes = standardTypes; @@ -813,8 +823,8 @@ // Class arrays reuse their leaf type super hierarchy. JDeclaredType leafType = (JDeclaredType) arrayType.getLeafType(); for (JReferenceType leafSuperType : getSuperHierarchyTypes(leafType)) { - JArrayType superArrayType = arrayTypeCreator.getOrCreateArrayType( - leafSuperType, arrayType.getDims()); + JArrayType superArrayType = + arrayTypeCreator.getOrCreateArrayType(leafSuperType, arrayType.getDims()); superHierarchyTypes.add(superArrayType); } } @@ -823,13 +833,13 @@ Set<JReferenceType> superHierarchyTypes = Sets.newHashSet(); if (superClassMap.containsKey(type.getName())) { - superHierarchyTypes.addAll(getTypes(superClassMap, type)); + superHierarchyTypes.addAll(getTypes(superClassMap, type.getName())); } if (superInterfaceMap.containsKey(type.getName())) { - superHierarchyTypes.addAll(getTypes(superInterfaceMap, type)); + superHierarchyTypes.addAll(getTypes(superInterfaceMap, type.getName())); } if (implementsMap.containsKey(type.getName())) { - superHierarchyTypes.addAll(getTypes(implementsMap, type)); + superHierarchyTypes.addAll(getTypes(implementsMap, type.getName())); } superHierarchyTypes.add(type); @@ -896,8 +906,14 @@ if (referenceType instanceof JNullType) { return true; } + return isJavaScriptObject(referenceType.getName()); + } - String typeName = referenceType.getName(); + // Note: This method does not account for null types and only relies on static + // class inheritance and does not account for any changes due to optimizations. + // Therefore this method should be kept private since callers need to be aware + // of this semantic difference. + private boolean isJavaScriptObject(String typeName) { if (typeName.equals(JProgram.JAVASCRIPTOBJECT)) { return true; } @@ -1009,17 +1025,17 @@ } /** - * Returns true if qType is a subclass of type, directly or indirectly. + * Returns true if possibleSubType is a subclass of type, directly or indirectly. */ - public boolean isSubClass(JClassType type, JClassType qType) { - return get(subClassMap, type.getName()).contains(qType.getName()); + public boolean isSubClass(JClassType type, JClassType possibleSubType) { + return get(subClassMap, type.getName()).contains(possibleSubType.getName()); } /** - * Returns true if qType is a superclass of type, directly or indirectly. + * Returns true if possibleSuperClass is a superclass of type, directly or indirectly. */ - public boolean isSuperClass(JClassType type, JClassType qType) { - return isSuperClass(type.getName(), qType.getName()); + public boolean isSuperClass(JClassType type, JClassType possibleSuperClass) { + return isSuperClass(type.getName(), possibleSuperClass.getName()); } /** @@ -1078,7 +1094,18 @@ getOrCreate(map, key).add(value); } - private void recordImmediateTypeRelations(Collection<JDeclaredType> types) { + private void deleteImmediateTypeRelations(Set<JDeclaredType> types) { + for (JDeclaredType type : types) { + if (type instanceof JClassType) { + immediateTypeRelations.superClassesByClass.remove(type.getName()); + immediateTypeRelations.implementedIntfsByClass.remove(type.getName()); + } else if (type instanceof JInterfaceType) { + immediateTypeRelations.superIntfsByIntf.remove(type.getName()); + } + } + } + + private void recordImmediateTypeRelations(Iterable<JDeclaredType> types) { referenceTypesByName.clear(); for (JReferenceType type : types) { referenceTypesByName.put(type.getName(), type); @@ -1173,16 +1200,15 @@ dualImpls.clear(); // Create dual mappings for any jso interface with a Java implementor. for (String jsoIntfName : jsoSingleImpls.keySet()) { - JInterfaceType jsoIntf = (JInterfaceType) referenceTypesByName.get(jsoIntfName); - Set<JReferenceType> implementors = getTypes(isImplementedMap, jsoIntf); - for (JReferenceType implementor : implementors) { + Set<String> implementors = get(isImplementedMap, jsoIntfName); + for (String implementor : implementors) { if (!hasWholeWorldKnowledge || !isJavaScriptObject(implementor)) { // Assume always dualImpl for separate compilation. Due to the nature of separate // compilation, the compiler can not know if a specific interface is implemented in a // different module unless it is a monolithic whole world compile. // TODO(rluble): Jso devirtualization should be an normalization pass before optimization // JTypeOracle should be mostly unaware of JSOs. - dualImpls.add(jsoIntf.getName()); + dualImpls.add(jsoIntfName); break; } } @@ -1389,7 +1415,7 @@ */ for (JInterfaceType intf : type.getImplements()) { computeVirtualUpRefs(type, intf); - for (JReferenceType superIntf : getTypes(superInterfaceMap, intf)) { + for (JReferenceType superIntf : getTypes(superInterfaceMap, intf.getName())) { computeVirtualUpRefs(type, (JInterfaceType) superIntf); } } @@ -1464,12 +1490,12 @@ } private Set<JReferenceType> getTypes(Map<String, Set<String>> typeNamesByTypeName, - JReferenceType type) { - Set<String> typeNames = get(typeNamesByTypeName, type.getName()); + String typeName) { + Set<String> typeNames = get(typeNamesByTypeName, typeName); IdentityHashSet<JReferenceType> types = new IdentityHashSet<JReferenceType>(); - for (String typeName : typeNames) { - JReferenceType referenceType = referenceTypesByName.get(typeName); + for (String localTypeName : typeNames) { + JReferenceType referenceType = referenceTypesByName.get(localTypeName); assert referenceType != null; types.add(referenceType); }
diff --git a/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java b/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java index 7412912..9a03166 100644 --- a/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java +++ b/dev/core/test/com/google/gwt/dev/jjs/JjsTypeTest.java
@@ -16,8 +16,10 @@ package com.google.gwt.dev.jjs; +import com.google.gwt.dev.MinimalRebuildCache; import com.google.gwt.dev.jjs.ast.JArrayType; import com.google.gwt.dev.jjs.ast.JClassType; +import com.google.gwt.dev.jjs.ast.JDeclaredType; import com.google.gwt.dev.jjs.ast.JInterfaceType; import com.google.gwt.dev.jjs.ast.JNonNullType; import com.google.gwt.dev.jjs.ast.JNullType; @@ -29,8 +31,11 @@ import junit.framework.TestCase; +import org.junit.Assert; + import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -244,6 +249,28 @@ assertSuperHierarchy(arrayOfArrayOfB, arrayOfArrayOfB, arrayOfArrayOfBase, arrayOfArrayOfObject, arrayOfArrayOfIntfI, arrayOfArrayOfIntfIBase, classObject); assertSuperHierarchy(arrayOfInt, arrayOfInt, classObject); + + intfCollection = createInterface("java.util.Collection"); + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType> newHashSet(classArrayList, intfList, intfCollection, classObject), + Sets.<JDeclaredType> newHashSet(intfIterable)); + + assertSuperHierarchy(intfCollection, intfCollection); + assertSuperHierarchy(intfList, intfList, intfCollection); + assertSuperHierarchy(classArrayList, classArrayList, intfList, classObject, + intfCollection); + + classA = createClass("A", classObject, false, false); + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType> newHashSet(classA, classObject), + Sets.<JDeclaredType> newHashSet(classBase)); + assertSuperHierarchy(classA, classA, classObject); + + JClassType classASub = createClass("ASub", classA, false, false); + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType> newHashSet(classASub, classA, classObject), + Sets.<JDeclaredType> newHashSet()); + assertSuperHierarchy(classASub, classASub, classA, classObject); } public void testJavahSignatures() { @@ -272,9 +299,126 @@ assertSame(arrayOfA, program.strongerType(intfCloneable, arrayOfA)); } + public void testUpdateTypeInformation_isJavaScriptObject() { + program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), + program.getDeclaredTypes()); + + JClassType jso = createClass("SomeJSO", classJso, false, false); + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType> newHashSet(jso), + Collections.<JDeclaredType> emptySet()); + Assert.assertTrue(program.typeOracle.isJavaScriptObject(jso)); + program.typeOracle.updateImmediateTypeRelations( + Collections.<JDeclaredType> emptySet(), + Sets.<JDeclaredType> newHashSet(jso)); + Assert.assertFalse(program.typeOracle.isJavaScriptObject(jso)); + + jso = createClass("SomeJSO", classJso, false, false); + JClassType jsoChild = createClass("SomeJSOChild", jso, false, false); + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType> newHashSet(jso, jsoChild), + Collections.<JDeclaredType> emptySet()); + Assert.assertTrue(program.typeOracle.isJavaScriptObject(jsoChild)); + jsoChild = createClass("SomeJSOChild", classObject, false, false); + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType> newHashSet(jsoChild), + Collections.<JDeclaredType> emptySet()); + Assert.assertFalse(program.typeOracle.isJavaScriptObject(jsoChild)); + + jso = createClass("SomeJSO", classJso, false, false); + jsoChild = createClass("SomeJSOChild", jso, false, false); + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType> newHashSet(jsoChild), + Collections.<JDeclaredType> emptySet()); + Assert.assertTrue(program.typeOracle.isJavaScriptObject(jsoChild)); + Assert.assertTrue(program.typeOracle.isJavaScriptObject(jso)); + jso = createClass("SomeJSO", classObject, false, false); + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType> newHashSet(jso), + Collections.<JDeclaredType> emptySet()); + Assert.assertFalse(program.typeOracle.isJavaScriptObject(jsoChild)); + Assert.assertFalse(program.typeOracle.isJavaScriptObject(jso)); + } + + public void testUpdateTypeInformation_JSODualImpl() { + program.typeOracle.computeBeforeAST(StandardTypes.createFrom(program), + program.getDeclaredTypes()); + + Assert.assertFalse(program.typeOracle.isDualJsoInterface(intfJ)); + + JClassType javaIntfImplementor = createClass("JavaImplementor", classObject, false, false); + javaIntfImplementor.addImplements(intfJ); + + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType>newHashSet(javaIntfImplementor), + Collections.<JDeclaredType>emptySet()); + Assert.assertTrue(program.typeOracle.isDualJsoInterface(intfJ)); + program.typeOracle.updateImmediateTypeRelations( + Collections.<JDeclaredType>emptySet(), + Sets.<JDeclaredType>newHashSet(javaIntfImplementor)); + Assert.assertFalse(program.typeOracle.isDualJsoInterface(intfJ)); + } + + public void testUpdateTypeInformation_SubClasses() { + JClassType baseAll = createClass("IncrementalBaseAll", classObject, false, false); + JClassType sub1 = createClass("IncrementalSub1", baseAll, false, false); + JClassType sub2 = createClass("IncrementalSub2", baseAll, false, false); + JClassType sub1_2 = createClass("IncrementalSub1_2", sub1, false, false); + + Assert.assertFalse(program.typeOracle.isSubClass(baseAll, sub1)); + + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType>newHashSet(baseAll, sub1, sub2, sub1_2), + Collections.<JDeclaredType>emptySet()); + + Assert.assertTrue(program.typeOracle.isSubClass(baseAll, sub1)); + Assert.assertTrue(program.typeOracle.isSubClass(baseAll, sub2)); + Assert.assertTrue(program.typeOracle.isSubClass(baseAll, sub1_2)); + Assert.assertTrue(program.typeOracle.isSubClass(sub1, sub1_2)); + + sub1_2 = createClass("IncrementalSub1_2", baseAll, false, false); + + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType>newHashSet(baseAll, sub2, sub1_2), + Sets.<JDeclaredType>newHashSet(sub1)); + + Assert.assertFalse(program.typeOracle.isSubClass(baseAll, sub1)); + Assert.assertTrue(program.typeOracle.isSubClass(baseAll, sub2)); + Assert.assertTrue(program.typeOracle.isSubClass(baseAll, sub1_2)); + } + + public void testUpdateTypeInformation_SuperClasses() { + JClassType baseAll = createClass("IncrementalBaseAll", classObject, false, false); + JClassType sub1 = createClass("IncrementalSub1", baseAll, false, false); + JClassType sub2 = createClass("IncrementalSub2", baseAll, false, false); + JClassType sub1_2 = createClass("IncrementalSub1_2", sub1, false, false); + + Assert.assertFalse(program.typeOracle.isSuperClass(sub1, baseAll)); + + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType>newHashSet(baseAll, sub1, sub2, sub1_2), + Collections.<JDeclaredType>emptySet()); + + Assert.assertTrue(program.typeOracle.isSuperClass(sub1, baseAll)); + Assert.assertTrue(program.typeOracle.isSuperClass(sub2, baseAll)); + Assert.assertTrue(program.typeOracle.isSuperClass(sub1_2, baseAll)); + Assert.assertTrue(program.typeOracle.isSuperClass(sub1_2, sub1)); + + sub1_2 = createClass("IncrementalSub1_2", baseAll, false, false); + + program.typeOracle.updateImmediateTypeRelations( + Sets.<JDeclaredType>newHashSet(baseAll, sub2, sub1_2), + Sets.<JDeclaredType>newHashSet(sub1)); + + Assert.assertFalse(program.typeOracle.isSuperClass(sub1, baseAll)); + Assert.assertTrue(program.typeOracle.isSuperClass(sub2, baseAll)); + Assert.assertFalse(program.typeOracle.isSuperClass(sub1_2, sub1)); + Assert.assertTrue(program.typeOracle.isSuperClass(sub1_2, baseAll)); + } + @Override protected void setUp() { - createSampleProgram(); + createSampleProgram(new MinimalRebuildCache()); } private void assertSuperHierarchy(JReferenceType type, JReferenceType... superHierarchyTypes) { @@ -296,9 +440,9 @@ return x; } - private void createSampleProgram() { + private void createSampleProgram(MinimalRebuildCache minimalRebuildCache) { // Make the program itself - program = new JProgram(); + program = new JProgram(minimalRebuildCache); typeOracle = program.typeOracle; synthSource = SourceOrigin.UNKNOWN;
diff --git a/dev/core/test/com/google/gwt/dev/jjs/LibraryJavaToJavaScriptCompilerTest.java b/dev/core/test/com/google/gwt/dev/jjs/LibraryJavaToJavaScriptCompilerTest.java index ffc4797..008abf1 100644 --- a/dev/core/test/com/google/gwt/dev/jjs/LibraryJavaToJavaScriptCompilerTest.java +++ b/dev/core/test/com/google/gwt/dev/jjs/LibraryJavaToJavaScriptCompilerTest.java
@@ -22,6 +22,7 @@ import com.google.gwt.core.ext.linker.ArtifactSet; import com.google.gwt.dev.CompilerContext; import com.google.gwt.dev.CompilerOptionsImpl; +import com.google.gwt.dev.MinimalRebuildCache; import com.google.gwt.dev.PrecompileTaskOptions; import com.google.gwt.dev.cfg.BindingProperty; import com.google.gwt.dev.cfg.Condition; @@ -298,7 +299,7 @@ public void testBuildLocalRuntimeRebindRules() throws UnableToCompleteException { // Sets up environment. Set<String> allRootTypes = Sets.newHashSet(); - compiler.jprogram = new JProgram(); + compiler.jprogram = new JProgram(new MinimalRebuildCache()); Map<String, String> runtimeRebindRuleSourcesByShortName = RuntimeRebindRuleGenerator.RUNTIME_REBIND_RULE_SOURCES_BY_SHORT_NAME; Rules rules = new Rules(); @@ -372,7 +373,7 @@ ConfigurationProperty emulateStackProperty = properties.createConfiguration("emulateStack", false); emulateStackProperty.setValue("TRUE"); - compiler.jprogram = new JProgram(); + compiler.jprogram = new JProgram(new MinimalRebuildCache()); // Builds property provider classes and a property provider registrator to register them. precompiler.buildPropertyProviderRegistrator(allRootTypes,
diff --git a/dev/core/test/com/google/gwt/dev/js/JsStackEmulatorTest.java b/dev/core/test/com/google/gwt/dev/js/JsStackEmulatorTest.java index 81c0357..d6a5d1f 100644 --- a/dev/core/test/com/google/gwt/dev/js/JsStackEmulatorTest.java +++ b/dev/core/test/com/google/gwt/dev/js/JsStackEmulatorTest.java
@@ -19,6 +19,7 @@ import com.google.gwt.core.ext.linker.SymbolData; import com.google.gwt.core.ext.linker.impl.StandardSymbolData; import com.google.gwt.dev.CompilerContext; +import com.google.gwt.dev.MinimalRebuildCache; import com.google.gwt.dev.PrecompileTaskOptions; import com.google.gwt.dev.PrecompileTaskOptionsImpl; import com.google.gwt.dev.cfg.BindingProperty; @@ -227,7 +228,8 @@ PrecompileTaskOptions options = new PrecompileTaskOptionsImpl(); options.setOutput(JsOutputOption.PRETTY); options.setRunAsyncEnabled(false); - CompilerContext context = new CompilerContext.Builder().options(options).build(); + CompilerContext context = new CompilerContext.Builder().options(options) + .minimalRebuildCache(new MinimalRebuildCache()).build(); ConfigProps config = new ConfigProps(Arrays.asList(recordFileNamesProp, recordLineNumbersProp));
diff --git a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java index 4975a71..b00f008 100644 --- a/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java +++ b/user/src/com/google/gwt/validation/rebind/GwtSpecificValidatorCreator.java
@@ -27,7 +27,12 @@ import com.google.gwt.core.ext.typeinfo.JPrimitiveType; import com.google.gwt.core.ext.typeinfo.JType; import com.google.gwt.core.shared.impl.StringCase; -import com.google.gwt.dev.jjs.ast.JProgram; +import com.google.gwt.dev.jjs.ast.JBooleanLiteral; +import com.google.gwt.dev.jjs.ast.JCharLiteral; +import com.google.gwt.dev.jjs.ast.JDoubleLiteral; +import com.google.gwt.dev.jjs.ast.JFloatLiteral; +import com.google.gwt.dev.jjs.ast.JIntLiteral; +import com.google.gwt.dev.jjs.ast.JLongLiteral; import com.google.gwt.thirdparty.guava.common.base.Function; import com.google.gwt.thirdparty.guava.common.base.Functions; import com.google.gwt.thirdparty.guava.common.base.Joiner; @@ -138,7 +143,6 @@ */ public static String asLiteral(Object value) throws IllegalArgumentException { Class<?> clazz = value.getClass(); - JProgram jProgram = new JProgram(); if (clazz.isArray()) { StringBuilder sb = new StringBuilder(); @@ -160,27 +164,27 @@ } if (value instanceof Boolean) { - return jProgram.getLiteralBoolean(((Boolean) value).booleanValue()) + return JBooleanLiteral.get(((Boolean) value).booleanValue()) .toSource(); } else if (value instanceof Byte) { - return jProgram.getLiteralInt(((Byte) value).byteValue()).toSource(); + return JIntLiteral.get(((Byte) value).byteValue()).toSource(); } else if (value instanceof Character) { - return jProgram.getLiteralChar(((Character) value).charValue()) + return JCharLiteral.get(((Character) value).charValue()) .toSource(); } else if (value instanceof Class<?>) { return ((Class<?>) ((Class<?>) value)).getCanonicalName() + ".class"; } else if (value instanceof Double) { - return jProgram.getLiteralDouble(((Double) value).doubleValue()) + return JDoubleLiteral.get(((Double) value).doubleValue()) .toSource(); } else if (value instanceof Enum) { return value.getClass().getCanonicalName() + "." + ((Enum<?>) value).name(); } else if (value instanceof Float) { - return jProgram.getLiteralFloat(((Float) value).floatValue()).toSource(); + return JFloatLiteral.get(((Float) value).floatValue()).toSource(); } else if (value instanceof Integer) { - return jProgram.getLiteralInt(((Integer) value).intValue()).toSource(); + return JIntLiteral.get(((Integer) value).intValue()).toSource(); } else if (value instanceof Long) { - return jProgram.getLiteralLong(((Long) value).intValue()).toSource(); + return JLongLiteral.get(((Long) value).intValue()).toSource(); } else if (value instanceof String) { return '"' + Generator.escape((String) value) + '"'; } else {
diff --git a/user/test/com/google/gwt/dev/StrictModeTest.java b/user/test/com/google/gwt/dev/StrictModeTest.java index 9671956..b9ef065 100644 --- a/user/test/com/google/gwt/dev/StrictModeTest.java +++ b/user/test/com/google/gwt/dev/StrictModeTest.java
@@ -47,7 +47,8 @@ private CompilerContext compilerContext = new CompilerContext(); public StrictModeTest() { - compilerContext = compilerContextBuilder.build(); + compilerContext = compilerContextBuilder.minimalRebuildCache(new MinimalRebuildCache()) + .build(); } /**