trunk@7259,7284,7285,7310,7340 were merged into this branch
  Restores logging for recursive unit invalidation.
  Removes some external inconsistency dangers from our collections.
  Fixes failure of TypeOracleMediator to resolve primitive arrays.
  ExpressionAnalyzer fix for clinit field refs.
  Fixes JSORestrictions crash in bad units.
  svn merge -c7259 --ignore-ancestry https://google-web-toolkit.googlecode.com/svn/trunk
  svn merge -c7284 --ignore-ancestry https://google-web-toolkit.googlecode.com/svn/trunk
  svn merge -c7285 --ignore-ancestry https://google-web-toolkit.googlecode.com/svn/trunk
  svn merge -c7310 --ignore-ancestry https://google-web-toolkit.googlecode.com/svn/trunk
  svn merge -c7340 --ignore-ancestry https://google-web-toolkit.googlecode.com/svn/trunk



git-svn-id: https://google-web-toolkit.googlecode.com/svn/releases/2.0@7502 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/branch-info.txt b/branch-info.txt
index e82fa43..834b89e 100644
--- a/branch-info.txt
+++ b/branch-info.txt
@@ -1438,3 +1438,15 @@
   Merge piece missing from r7378.
   svn merge --ignore-ancestry -c 7382 \
       http://google-web-toolkit.googlecode.com/svn/trunk .
+
+trunk@7259,7284,7285,7310,7340 were merged into this branch
+  Restores logging for recursive unit invalidation.
+  Removes some external inconsistency dangers from our collections.
+  Fixes failure of TypeOracleMediator to resolve primitive arrays.
+  ExpressionAnalyzer fix for clinit field refs.
+  Fixes JSORestrictions crash in bad units.
+  svn merge -c7259 --ignore-ancestry https://google-web-toolkit.googlecode.com/svn/trunk
+  svn merge -c7284 --ignore-ancestry https://google-web-toolkit.googlecode.com/svn/trunk
+  svn merge -c7285 --ignore-ancestry https://google-web-toolkit.googlecode.com/svn/trunk
+  svn merge -c7310 --ignore-ancestry https://google-web-toolkit.googlecode.com/svn/trunk
+  svn merge -c7340 --ignore-ancestry https://google-web-toolkit.googlecode.com/svn/trunk
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 214dbee..eb4f340 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationStateBuilder.java
@@ -186,11 +186,11 @@
     return instance;
   }
 
-  private static void invalidateUnitsWithInvalidRefs(
+  private static void invalidateUnitsWithInvalidRefs(TreeLogger logger,
       Map<String, CompilationUnit> resultUnits, Set<ContentId> set) {
     Set<CompilationUnit> validResultUnits = new HashSet<CompilationUnit>(
         resultUnits.values());
-    CompilationUnitInvalidator.retainValidUnits(validResultUnits, set);
+    CompilationUnitInvalidator.retainValidUnits(logger, validResultUnits, set);
     for (Entry<String, CompilationUnit> entry : resultUnits.entrySet()) {
       CompilationUnit unit = entry.getValue();
       if (unit.isCompiled() && !validResultUnits.contains(unit)) {
@@ -261,7 +261,8 @@
     }
 
     // Winnow the reusable set of units down to those still valid.
-    CompilationUnitInvalidator.retainValidUnits(resultUnits.values());
+    CompilationUnitInvalidator.retainValidUnits(TreeLogger.NULL,
+        resultUnits.values());
 
     // Compile everything else.
     CompileMoreLater compileMoreLater = new CompileMoreLater();
@@ -280,7 +281,7 @@
     compileMoreLater.compile(logger, builders, resultUnits);
 
     // Invalidate units with invalid refs.
-    invalidateUnitsWithInvalidRefs(resultUnits,
+    invalidateUnitsWithInvalidRefs(logger, resultUnits,
         Collections.<ContentId> emptySet());
     return new CompilationState(logger, resultUnits.values(), compileMoreLater);
   }
@@ -307,8 +308,8 @@
     }
 
     // Winnow the reusable set of units down to those still valid.
-    CompilationUnitInvalidator.retainValidUnits(resultUnits.values(),
-        compileMoreLater.getValidDependencies());
+    CompilationUnitInvalidator.retainValidUnits(TreeLogger.NULL,
+        resultUnits.values(), compileMoreLater.getValidDependencies());
     for (CompilationUnit validUnit : resultUnits.values()) {
       compileMoreLater.addValidUnit(validUnit);
       // Report any existing errors as if the unit were recompiled.
@@ -324,7 +325,7 @@
     }
 
     compileMoreLater.compile(logger, builders, resultUnits);
-    invalidateUnitsWithInvalidRefs(resultUnits,
+    invalidateUnitsWithInvalidRefs(logger, resultUnits,
         compileMoreLater.getValidDependencies());
     return resultUnits.values();
   }
diff --git a/dev/core/src/com/google/gwt/dev/javac/CompilationUnitInvalidator.java b/dev/core/src/com/google/gwt/dev/javac/CompilationUnitInvalidator.java
index a317d3b..1ec0d4f 100644
--- a/dev/core/src/com/google/gwt/dev/javac/CompilationUnitInvalidator.java
+++ b/dev/core/src/com/google/gwt/dev/javac/CompilationUnitInvalidator.java
@@ -55,12 +55,15 @@
     }
   }
 
-  public static void retainValidUnits(Collection<CompilationUnit> units) {
-    retainValidUnits(units, Collections.<ContentId> emptySet());
+  public static void retainValidUnits(TreeLogger logger,
+      Collection<CompilationUnit> units) {
+    retainValidUnits(logger, units, Collections.<ContentId> emptySet());
   }
 
-  public static void retainValidUnits(Collection<CompilationUnit> units,
-      Set<ContentId> knownValidRefs) {
+  public static void retainValidUnits(TreeLogger logger,
+      Collection<CompilationUnit> units, Set<ContentId> knownValidRefs) {
+    logger = logger.branch(TreeLogger.TRACE, "Removing invalidated units");
+
     // Assume all units are valid at first.
     Set<CompilationUnit> currentlyValidUnits = new HashSet<CompilationUnit>();
     Set<ContentId> currentlyValidRefs = new HashSet<ContentId>(knownValidRefs);
@@ -74,14 +77,19 @@
     boolean changed;
     do {
       changed = false;
-      iterating : for (Iterator<CompilationUnit> it = currentlyValidUnits.iterator(); it.hasNext();) {
+      for (Iterator<CompilationUnit> it = currentlyValidUnits.iterator(); it.hasNext();) {
         CompilationUnit unitToCheck = it.next();
+        TreeLogger branch = null;
         for (ContentId ref : unitToCheck.getDependencies()) {
           if (!currentlyValidRefs.contains(ref)) {
-            it.remove();
-            currentlyValidRefs.remove(unitToCheck.getContentId());
-            changed = true;
-            continue iterating;
+            if (branch == null) {
+              branch = logger.branch(TreeLogger.DEBUG, "Compilation unit '"
+                  + unitToCheck + "' is removed due to invalid reference(s):");
+              it.remove();
+              currentlyValidRefs.remove(unitToCheck.getContentId());
+              changed = true;
+            }
+            branch.log(TreeLogger.DEBUG, ref.get());
           }
         }
       }
diff --git a/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java b/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java
index 1e9cb0f..20cb178 100644
--- a/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java
+++ b/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java
@@ -85,8 +85,19 @@
 
     @Override
     public void endVisit(AllocationExpression exp, BlockScope scope) {
+      // In rare cases we might not be able to resolve the expression.
+      if (exp.type == null) {
+        return;
+      }
+      TypeBinding resolvedType = exp.resolvedType;
+      if (resolvedType == null) {
+        if (scope == null) {
+          return;
+        }
+        resolvedType = exp.type.resolveType(scope);
+      }
       // Anywhere an allocation occurs is wrong.
-      if (exp.type != null && isJsoSubclass(exp.type.resolveType(scope))) {
+      if (isJsoSubclass(resolvedType)) {
         errorOn(exp, ERR_NEW_JSO);
       }
     }
diff --git a/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java b/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
index e2b0352..ebd5e8d 100644
--- a/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
+++ b/dev/core/src/com/google/gwt/dev/javac/TypeOracleMediator.java
@@ -597,6 +597,10 @@
             + value.getClass().getCanonicalName());
         return null;
       }
+      if (componentType.isPrimitive()) {
+        // primitive arrays are already resolved
+        return value;
+      }
       // resolve each element in the array
       int n = Array.getLength(value);
       Object newArray = Array.newInstance(componentType, n);
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/ExpressionAnalyzer.java b/dev/core/src/com/google/gwt/dev/jjs/impl/ExpressionAnalyzer.java
index d8c9904..18005f0 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/ExpressionAnalyzer.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/ExpressionAnalyzer.java
@@ -130,6 +130,10 @@
       accessesFieldNonFinal = true;
     }
 
+    if (x.hasClinit()) {
+      recordMethodCall();
+    }
+
     JExpression instance = x.getInstance();
     if (instance == null) {
       return;
@@ -159,15 +163,7 @@
 
   @Override
   public void endVisit(JMethodCall x, Context ctx) {
-    /*
-     * We can't assume anything about method calls right now, except that it
-     * can't assign to one of our locals or one of our parameters. It's possible
-     * that it could read from a field, assign to a field or throw an exception
-     * that we can't see.
-     */
-    assignmentToField = true;
-    accessesField = true;
-    canThrowException = true;
+    recordMethodCall();
   }
 
   @Override
@@ -297,4 +293,19 @@
       assignmentToLocal = true;
     }
   }
+
+  /**
+   * We can't assume anything about method calls right now, except that it can't
+   * access any of our locals or parameters.
+   * 
+   * TODO: what about accessing arrays? Should be treated like field refs I
+   * guess.
+   */
+  private void recordMethodCall() {
+    assignmentToField = true;
+    accessesField = true;
+    accessesFieldNonFinal = true;
+    canThrowException = true;
+    createsObject = true;
+  }
 }
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/TypeOracleAnnotationSupportTest.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/TypeOracleAnnotationSupportTest.java
index 6a2f27d..5784e4d 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/TypeOracleAnnotationSupportTest.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/TypeOracleAnnotationSupportTest.java
@@ -251,5 +251,11 @@
 
     short s = annotation.s();
     assertTrue(s > 0);
+    
+    int[] ia = annotation.ia();
+    assertEquals(3, ia.length);
+    for (int it = 0; it < 3; ++it) {
+      assertEquals(it, ia[it]);
+    }
   }
 }
diff --git a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/PrimitivesAnnotatedClass.java b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/PrimitivesAnnotatedClass.java
index bd4b377..74e9237 100644
--- a/dev/core/test/com/google/gwt/core/ext/typeinfo/test/PrimitivesAnnotatedClass.java
+++ b/dev/core/test/com/google/gwt/core/ext/typeinfo/test/PrimitivesAnnotatedClass.java
@@ -21,7 +21,8 @@
  */
 @PrimitiveValuesAnnotation(b = PrimitivesAnnotatedClass.byteAsInt,
     c = (byte) 12, s = 'a', i = (short) 1452,
-    l = 12345, f = (byte) 15, d = 123412312L)
+    l = 12345, f = (byte) 15, d = 123412312L, ia = {
+    0, 1, 2})
 public class PrimitivesAnnotatedClass {
   static final int byteAsInt = 123;
 }
diff --git a/dev/core/test/com/google/gwt/dev/jjs/impl/ExpressionAnalyzerTest.java b/dev/core/test/com/google/gwt/dev/jjs/impl/ExpressionAnalyzerTest.java
index 47bc7b3..ee0252e 100644
--- a/dev/core/test/com/google/gwt/dev/jjs/impl/ExpressionAnalyzerTest.java
+++ b/dev/core/test/com/google/gwt/dev/jjs/impl/ExpressionAnalyzerTest.java
@@ -116,6 +116,22 @@
     analyzeExpression("int", "0").check();
   }
 
+  public void testFieldAccessClinit() throws Exception {
+    sourceOracle.addOrReplace(new MockJavaResource("test.Foo") {
+      @Override
+      protected CharSequence getContent() {
+        StringBuffer code = new StringBuffer();
+        code.append("package test;\n");
+        code.append("public class Foo {\n");
+        code.append("  static final boolean value = trueMethod();");
+        code.append("  static boolean trueMethod() { return true; }");
+        code.append("}\n");
+        return code;
+      }
+    });
+    analyzeExpression("boolean", "Foo.value").accessesFieldNonFinal().canThrowException().createsObject().hasAssignmentToField().check();
+  }
+
   public void testFieldAccessInstance() throws Exception {
     sourceOracle.addOrReplace(new MockJavaResource("test.Foo") {
       @Override
diff --git a/user/super/com/google/gwt/emul/java/util/AbstractList.java b/user/super/com/google/gwt/emul/java/util/AbstractList.java
index e76a993..53754c7 100644
--- a/user/super/com/google/gwt/emul/java/util/AbstractList.java
+++ b/user/super/com/google/gwt/emul/java/util/AbstractList.java
@@ -206,10 +206,12 @@
 
   public boolean addAll(int index, Collection<? extends E> c) {
     Iterator<? extends E> iter = c.iterator();
+    boolean changed = false;
     while (iter.hasNext()) {
       add(index++, iter.next());
+      changed = true;
     }
-    return !c.isEmpty();
+    return changed;
   }
 
   @Override
diff --git a/user/super/com/google/gwt/emul/java/util/ArrayList.java b/user/super/com/google/gwt/emul/java/util/ArrayList.java
index 418d953..b061955 100644
--- a/user/super/com/google/gwt/emul/java/util/ArrayList.java
+++ b/user/super/com/google/gwt/emul/java/util/ArrayList.java
@@ -81,7 +81,7 @@
   public ArrayList(Collection<? extends E> c) {
     // Avoid calling overridable methods from constructors
     spliceArray(array, 0, 0, c.toArray());
-    size = c.size();
+    size = array.length;
   }
 
   public ArrayList(int initialCapacity) {
@@ -107,23 +107,27 @@
 
   @Override
   public boolean addAll(Collection<? extends E> c) {
-    if (c.isEmpty()) {
+    Object[] cArray = c.toArray();
+    int len = cArray.length;
+    if (len == 0) {
       return false;
     }
-    spliceArray(array, size, 0, c.toArray());
-    size += c.size();
+    spliceArray(array, size, 0, cArray);
+    size += len;
     return true;
   }
 
   public boolean addAll(int index, Collection<? extends E> c) {
-    if (c.isEmpty()) {
-      return false;
-    }
     if (index < 0 || index > size) {
       indexOutOfBounds(index, size);
     }
-    spliceArray(array, index, 0, c.toArray());
-    size += c.size();
+    Object[] cArray = c.toArray();
+    int len = cArray.length;
+    if (len == 0) {
+      return false;
+    }
+    spliceArray(array, index, 0, cArray);
+    size += len;
     return true;
   }
 
diff --git a/user/test/com/google/gwt/emultest/java/util/ListTestBase.java b/user/test/com/google/gwt/emultest/java/util/ListTestBase.java
index 7e2727b..06d7d3c 100644
--- a/user/test/com/google/gwt/emultest/java/util/ListTestBase.java
+++ b/user/test/com/google/gwt/emultest/java/util/ListTestBase.java
@@ -33,6 +33,17 @@
 
   private static volatile boolean NO_OPTIMIZE_FALSE = false;
   
+  public void testAddAll() {
+    assertFalse(makeEmptyList().addAll(makeEmptyList()));
+    assertTrue(makeEmptyList().addAll(makeFullList()));
+    assertFalse(makeEmptyList().addAll(0, makeEmptyList()));
+    assertTrue(makeEmptyList().addAll(0, makeFullList()));
+    assertFalse(makeFullList().addAll(makeEmptyList()));
+    assertTrue(makeFullList().addAll(makeFullList()));
+    assertFalse(makeFullList().addAll(1, makeEmptyList()));
+    assertTrue(makeFullList().addAll(1, makeFullList()));
+  }
+  
   public void testAddWatch() {
     List s = makeEmptyList();
     s.add("watch");