Makes GWT checks configurable.

See http://goo.gl/ep43pa for details.

Also introduces more specialized iterator implementation
for ArrayList for better optimizations.

Setting the check level to MINIMAL increase performance significantly
in most benchmarks. MINIMAL check level includes removal of type
checking so some of these improvements were already availabe via
-XdisableCastChecking. So following chart only summarizes
the "additional" speed ups with the check level MINIMAL:

                                   Chrome    Firefox     IE 11
ArrayListObjectGetBenchmark	    +7.18%   +36.74%     +83.96%
ArrayListObjectIterationBenchmark  +36.85%    +6.76%    +472.2%
ArrayListObjectSetBenchmark	    +9.83%   +87.89%     +37.05%
HashMapObjectIterationBenchmark	    +9.44%   -16.83%     +43.01%
HashMapObjectPutBenchmark	    +4.28%   +20.87%     +34.14%
HashMapStringIterationBenchmark	   +18.49%   +10.17%     +43.67%
HashMapStringPutBenchmark	    +5.50%   +36.25%     +40.74%



Change-Id: Id8045e3bfa21740d9096aa319aace6b36896f1b6
Review-Link: https://gwt-review.googlesource.com/#/c/10933/
diff --git a/dev/core/super/javaemul/internal/InternalPreconditions.java b/dev/core/super/javaemul/internal/InternalPreconditions.java
index 5792137..550b753 100644
--- a/dev/core/super/javaemul/internal/InternalPreconditions.java
+++ b/dev/core/super/javaemul/internal/InternalPreconditions.java
@@ -20,13 +20,27 @@
 /**
  * A utility class that provides utility functions to do precondition checks inside GWT-SDK.
  */
-public class InternalPreconditions {
-  // Some parts adapted from Guava
+// Some parts adapted from Guava
+public final class InternalPreconditions {
+  private static final boolean CHECKED_MODE = System.getProperty("superdevmode").equals("on");
+  private static final boolean JSNI_CHECK = System.getProperty("checks.jsni").equals("ENABLED");
+  private static final boolean TYPE_CHECK = System.getProperty("checks.type").equals("ENABLED");
+  private static final boolean API_CHECK = System.getProperty("checks.api").equals("ENABLED");
+  private static final boolean BOUND_CHECK = System.getProperty("checks.bounds").equals("ENABLED");
 
-  /**
-   * Ensures the truth of an expression that verifies type.
-   */
   public static void checkType(boolean expression) {
+    if (TYPE_CHECK) {
+      checkCriticalType(expression);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalType(expression);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  public static void checkCriticalType(boolean expression) {
     if (!expression) {
       throw new ClassCastException();
     }
@@ -36,6 +50,18 @@
    * Ensures the truth of an expression that verifies array type.
    */
   public static void checkArrayType(boolean expression) {
+    if (TYPE_CHECK) {
+      checkCriticalArrayType(expression);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalArrayType(expression);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  public static void checkCriticalArrayType(boolean expression) {
     if (!expression) {
       throw new ArrayStoreException();
     }
@@ -45,6 +71,18 @@
    * Ensures the truth of an expression that verifies array type.
    */
   public static void checkArrayType(boolean expression, Object errorMessage) {
+    if (TYPE_CHECK) {
+      checkCriticalArrayType(expression, errorMessage);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalArrayType(expression, errorMessage);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  public static void checkCriticalArrayType(boolean expression, Object errorMessage) {
     if (!expression) {
       throw new ArrayStoreException(String.valueOf(errorMessage));
     }
@@ -54,15 +92,14 @@
    * Ensures the truth of an expression involving existence of an element.
    */
   public static void checkElement(boolean expression) {
-    checkCriticalElement(expression);
-  }
-
-  /**
-   * Ensures the truth of an expression involving existence of an element.
-   */
-  public static void checkElement(boolean expression, Object errorMessage) {
-    if (!expression) {
-      throw new NoSuchElementException(String.valueOf(errorMessage));
+    if (API_CHECK) {
+      checkCriticalElement(expression);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalElement(expression);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
     }
   }
 
@@ -79,25 +116,45 @@
   }
 
   /**
+   * Ensures the truth of an expression involving existence of an element.
+   */
+  public static void checkElement(boolean expression, Object errorMessage) {
+    if (API_CHECK) {
+      checkCriticalElement(expression, errorMessage);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalElement(expression, errorMessage);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving existence of an element.
+   * <p>
+   * For cases where failing fast is pretty important and not failing early could cause bugs that
+   * are much harder to debug.
+   */
+  public static void checkCriticalElement(boolean expression, Object errorMessage) {
+    if (!expression) {
+      throw new NoSuchElementException(String.valueOf(errorMessage));
+    }
+  }
+
+  /**
    * Ensures the truth of an expression involving one or more parameters to the calling method.
    */
   public static void checkArgument(boolean expression) {
-    checkCriticalArgument(expression);
-  }
-
-  /**
-   * Ensures the truth of an expression involving one or more parameters to the calling method.
-   */
-  public static void checkArgument(boolean expression, Object errorMessage) {
-    checkCriticalArgument(expression, errorMessage);
-  }
-
-  /**
-   * Ensures the truth of an expression involving one or more parameters to the calling method.
-   */
-  public static void checkArgument(boolean expression, String errorMessageTemplate,
-      Object... errorMessageArgs) {
-    checkCriticalArgument(expression, errorMessageTemplate, errorMessageArgs);
+    if (API_CHECK) {
+      checkCriticalArgument(expression);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalArgument(expression);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
   }
 
   /**
@@ -114,6 +171,21 @@
 
   /**
    * Ensures the truth of an expression involving one or more parameters to the calling method.
+   */
+  public static void checkArgument(boolean expression, Object errorMessage) {
+    if (API_CHECK) {
+      checkCriticalArgument(expression, errorMessage);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalArgument(expression, errorMessage);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving one or more parameters to the calling method.
    * <p>
    * For cases where failing fast is pretty important and not failing early could cause bugs that
    * are much harder to debug.
@@ -126,6 +198,22 @@
 
   /**
    * Ensures the truth of an expression involving one or more parameters to the calling method.
+   */
+  public static void checkArgument(boolean expression, String errorMessageTemplate,
+      Object... errorMessageArgs) {
+    if (API_CHECK) {
+      checkCriticalArgument(expression, errorMessageTemplate, errorMessageArgs);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalArgument(expression, errorMessageTemplate, errorMessageArgs);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving one or more parameters to the calling method.
    * <p>
    * For cases where failing fast is pretty important and not failing early could cause bugs that
    * are much harder to debug.
@@ -145,6 +233,25 @@
    * @throws IllegalStateException if {@code expression} is false
    */
   public static void checkState(boolean expression) {
+    if (API_CHECK) {
+      checkCritcalState(expression);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCritcalState(expression);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving the state of the calling instance, but not
+   * involving any parameters to the calling method.
+   * <p>
+   * For cases where failing fast is pretty important and not failing early could cause bugs that
+   * are much harder to debug.
+   */
+  public static void checkCritcalState(boolean expression) {
     if (!expression) {
       throw new IllegalStateException();
     }
@@ -155,6 +262,22 @@
    * involving any parameters to the calling method.
    */
   public static void checkState(boolean expression, Object errorMessage) {
+    if (API_CHECK) {
+      checkCriticalState(expression, errorMessage);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalState(expression, errorMessage);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving the state of the calling instance, but not
+   * involving any parameters to the calling method.
+   */
+  public static void checkCriticalState(boolean expression, Object errorMessage) {
     if (!expression) {
       throw new IllegalStateException(String.valueOf(errorMessage));
     }
@@ -164,6 +287,20 @@
    * Ensures that an object reference passed as a parameter to the calling method is not null.
    */
   public static <T> T checkNotNull(T reference) {
+    if (API_CHECK) {
+      checkCriticalNotNull(reference);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalNotNull(reference);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+
+    return reference;
+  }
+
+  public static <T> T checkCriticalNotNull(T reference) {
     if (reference == null) {
       throw new NullPointerException();
     }
@@ -174,6 +311,18 @@
    * Ensures that an object reference passed as a parameter to the calling method is not null.
    */
   public static void checkNotNull(Object reference, Object errorMessage) {
+    if (API_CHECK) {
+      checkCriticalNotNull(reference, errorMessage);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalNotNull(reference, errorMessage);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  public static void checkCriticalNotNull(Object reference, Object errorMessage) {
     if (reference == null) {
       throw new NullPointerException(String.valueOf(errorMessage));
     }
@@ -183,6 +332,18 @@
    * Ensures that {@code size} specifies a valid array size (i.e. non-negative).
    */
   public static void checkArraySize(int size) {
+    if (API_CHECK) {
+      checkCriticalArraySize(size);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalArraySize(size);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  public static void checkCriticalArraySize(int size) {
     if (size < 0) {
       throw new NegativeArraySizeException("Negative array size: " + size);
     }
@@ -193,6 +354,18 @@
    * {@code size}. An element index may range from zero, inclusive, to {@code size}, exclusive.
    */
   public static void checkElementIndex(int index, int size) {
+    if (BOUND_CHECK) {
+      checkCriticalElementIndex(index, size);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalElementIndex(index, size);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  public static void checkCriticalElementIndex(int index, int size) {
     if (index < 0 || index >= size) {
       throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
     }
@@ -203,6 +376,18 @@
    * size {@code size}. A position index may range from zero to {@code size}, inclusive.
    */
   public static void checkPositionIndex(int index, int size) {
+    if (BOUND_CHECK) {
+      checkCriticalPositionIndex(index, size);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalPositionIndex(index, size);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  public static void checkCriticalPositionIndex(int index, int size) {
     if (index < 0 || index > size) {
       throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);
     }
@@ -214,7 +399,15 @@
    * {@code size}, inclusive.
    */
   public static void checkPositionIndexes(int start, int end, int size) {
-    checkCriticalPositionIndexes(start, end, size);
+    if (BOUND_CHECK) {
+      checkCriticalPositionIndexes(start, end, size);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalPositionIndexes(start, end, size);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
   }
 
   /**
diff --git a/user/super/com/google/gwt/emul/Emulation.gwt.xml b/user/super/com/google/gwt/emul/Emulation.gwt.xml
index 31db233..9555138 100644
--- a/user/super/com/google/gwt/emul/Emulation.gwt.xml
+++ b/user/super/com/google/gwt/emul/Emulation.gwt.xml
@@ -16,6 +16,7 @@
 <!-- Do not inherit this module directly; inherit com.google.gwt.core.Core. -->
 <module>
   <inherits name="javaemul.internal.Internal"/>
+  <inherits name="com.google.gwt.emul.Preconditions" />
 
   <extend-configuration-property name="compiler.enum.obfuscate.names.blacklist"
       value="java.math.RoundingMode" />
diff --git a/user/super/com/google/gwt/emul/Preconditions.gwt.xml b/user/super/com/google/gwt/emul/Preconditions.gwt.xml
new file mode 100644
index 0000000..5ef8a2b
--- /dev/null
+++ b/user/super/com/google/gwt/emul/Preconditions.gwt.xml
@@ -0,0 +1,121 @@
+<!--                                                                        -->
+<!-- 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   -->
+<!-- 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. License for the specific language governing permissions and   -->
+<!-- limitations under the License.                                         -->
+
+<!-- Defines support configurable preconditions -->
+<module type="fileset">
+
+  <!--
+ ┌────────┬─────────────────────────────────────────────────────┬───────────────────────────────┐
+ │Group   │Description                                          │Common Exception Types         │
+ ├────────┼─────────────────────────────────────────────────────┼───────────────────────────────┤
+ │JSNI    │Checks related to arguments and return types of      │ClassCastException             │
+ │        │JSNI methods. (Not implemented yet)                  │                               │
+ ├────────┼─────────────────────────────────────────────────────┼───────────────────────────────┤
+ │BOUNDS  │Checks related to the bound checking in collections. │IndexOutBoundsException        │
+ │        │                                                     │ArrayIndexOutOfBoundsException │
+ ├────────┼─────────────────────────────────────────────────────┼───────────────────────────────┤
+ │API     │Checks related to the correct usage of APIs.         │IllegalStateException          │
+ │        │                                                     │NoSuchElementException         │
+ │        │                                                     │NullPointerException           │
+ │        │                                                     │IllegalArgumentException       │
+ │        │                                                     │ConcurrentModificationException│
+ ├────────┼─────────────────────────────────────────────────────┼───────────────────────────────┤
+ │TYPE    │Checks related to java type system.                  │ClassCastException             │
+ │        │                                                     │ArrayStoreException            │
+ ├────────┼─────────────────────────────────────────────────────┼───────────────────────────────┤
+ │CRITICAL│Checks for cases where not failing-fast will keep    │IllegalArgumentException       │
+ │        │the object in an inconsistent state and/or degrade   │                               │
+ │        │debugging significantly. Currently disabling these   │                               │
+ │        │checks is not supported.                             │                               │
+ └────────┴─────────────────────────────────────────────────────┴───────────────────────────────┘
+  -->
+  <define-property name="checks.jsni" values="ENABLED,DISABLED" />
+  <define-property name="checks.bounds" values="ENABLED,DISABLED" />
+  <define-property name="checks.api" values="ENABLED,DISABLED" />
+  <define-property name="checks.type" values="ENABLED,DISABLED" />
+  <define-property name="checks.critical" values="ENABLED" />
+
+
+  <!--
+ ┌────────────────┬─────────┬──────────┬─────────┬─────────┬─────────┐
+ │Check level     │  JSNI   │  BOUNDS  │   API   │  TYPE   │CRITICAL │
+ ├────────────────┼─────────┼──────────┼─────────┼─────────┼─────────┤
+ │Full            │    X    │    X     │    X    │    X    │    X    │
+ ├────────────────┼─────────┼──────────┼─────────┼─────────┼─────────┤
+ │Normal (default)│         │    X     │    X    │    X    │    X    │
+ ├────────────────┼─────────┼──────────┼─────────┼─────────┼─────────┤
+ │Optimized       │         │          │         │    X    │    X    │
+ ├────────────────┼─────────┼──────────┼─────────┼─────────┼─────────┤
+ │Minimal         │         │          │         │         │    X    │
+ ├────────────────┼─────────┼──────────┼─────────┼─────────┼─────────┤
+ │None (N/A yet)  │         │          │         │         │         │
+ └────────────────┴─────────┴──────────┴─────────┴─────────┴─────────┘
+  -->
+  <define-property name="checks.checkLevel" values="FULL,NORMAL,OPTIMIZED,MINIMAL" />
+
+
+  <!-- Associate individual checks with levels -->
+
+  <set-property name="checks.jsni" value="DISABLED" />
+  <set-property name="checks.jsni" value="ENABLED">
+    <any>
+      <when-property-is name="checks.checkLevel" value="FULL" />
+    </any>
+  </set-property>
+
+  <set-property name="checks.bounds" value="DISABLED" />
+  <set-property name="checks.bounds" value="ENABLED">
+    <any>
+      <when-property-is name="checks.checkLevel" value="FULL" />
+      <when-property-is name="checks.checkLevel" value="NORMAL" />
+    </any>
+  </set-property>
+
+  <set-property name="checks.api" value="DISABLED" />
+  <set-property name="checks.api" value="ENABLED">
+    <any>
+      <when-property-is name="checks.checkLevel" value="FULL" />
+      <when-property-is name="checks.checkLevel" value="NORMAL" />
+    </any>
+  </set-property>
+
+
+  <set-property name="checks.type" value="DISABLED" />
+  <set-property name="checks.type" value="ENABLED">
+    <any>
+      <when-property-is name="checks.checkLevel" value="FULL" />
+      <when-property-is name="checks.checkLevel" value="NORMAL" />
+      <when-property-is name="checks.checkLevel" value="OPTIMIZED" />
+    </any>
+  </set-property>
+
+  <!-- CRITICAL checking cannot be disabled for now.
+  <set-property name="checks.critical" value="DISABLED" />
+  <set-property name="checks.critical" value="ENABLED">
+    <any>
+      <when-property-is name="checks.checkLevel" value="FULL" />
+      <when-property-is name="checks.checkLevel" value="NORMAL" />
+      <when-property-is name="checks.checkLevel" value="OPTIMIZED" />
+      <when-property-is name="checks.checkLevel" value="MINIMAL" />
+    </any>
+  </set-property>
+  -->
+
+  <!-- End of associations -->
+
+
+  <!-- Default checkLevel is NORMAL -->
+  <set-property name="checks.checkLevel" value="NORMAL" />
+
+</module>
diff --git a/user/super/com/google/gwt/emul/java/util/ConcurrentModificationDetector.java b/user/super/com/google/gwt/emul/java/util/ConcurrentModificationDetector.java
index 11d9ba7..7458eab 100644
--- a/user/super/com/google/gwt/emul/java/util/ConcurrentModificationDetector.java
+++ b/user/super/com/google/gwt/emul/java/util/ConcurrentModificationDetector.java
@@ -23,20 +23,31 @@
  */
 class ConcurrentModificationDetector {
 
+private static final boolean API_CHECK = System.getProperty("checks.api").equals("ENABLED");
+
   private static final String MOD_COUNT_PROPERTY = "_gwt_modCount";
 
   public static void structureChanged(Object map) {
+    if (!API_CHECK) {
+      return;
+    }
     // Ensure that modCount is initialized if it is not already.
     int modCount = JsUtils.getIntProperty(map, MOD_COUNT_PROPERTY) | 0;
     JsUtils.setIntProperty(map, MOD_COUNT_PROPERTY, modCount + 1);
   }
 
   public static void recordLastKnownStructure(Object host, Iterator<?> iterator) {
+    if (!API_CHECK) {
+      return;
+    }
     int modCount = JsUtils.getIntProperty(host, MOD_COUNT_PROPERTY);
     JsUtils.setIntProperty(iterator, MOD_COUNT_PROPERTY, modCount);
   }
 
   public static void checkStructuralChange(Object host, Iterator<?> iterator) {
+    if (!API_CHECK) {
+      return;
+    }
     if (JsUtils.getIntProperty(iterator, MOD_COUNT_PROPERTY)
         != JsUtils.getIntProperty(host, MOD_COUNT_PROPERTY)) {
       throw new ConcurrentModificationException();
diff --git a/user/test/com/google/gwt/dev/jjs/CompilerSuiteOptimized.gwt.xml b/user/test/com/google/gwt/dev/jjs/CompilerSuiteOptimized.gwt.xml
new file mode 100644
index 0000000..6e9948b
--- /dev/null
+++ b/user/test/com/google/gwt/dev/jjs/CompilerSuiteOptimized.gwt.xml
@@ -0,0 +1,25 @@
+<!--                                                                        -->
+<!-- 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   -->
+<!-- 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. License for the specific language governing permissions and   -->
+<!-- limitations under the License.                                         -->
+
+<module type="fileset">
+  <inherits name="com.google.gwt.core.Core"/>
+  <!-- Make sure junit xml processed prior to this one so stack mode will not be overwritten -->
+  <inherits name="com.google.gwt.junit.JUnit" />
+
+  <!-- stack emulation disabled so that we can check the implementation of functions -->
+  <set-property name="compiler.stackMode" value="native" />
+  <set-property name="checks.checkLevel" value="MINIMAL" />
+
+  <source path='optimized' />
+</module>
diff --git a/user/test/com/google/gwt/dev/jjs/OptimizedOnlyCompilerSuite.java b/user/test/com/google/gwt/dev/jjs/OptimizedOnlyCompilerSuite.java
index 7ea3c79..f37d6e1 100644
--- a/user/test/com/google/gwt/dev/jjs/OptimizedOnlyCompilerSuite.java
+++ b/user/test/com/google/gwt/dev/jjs/OptimizedOnlyCompilerSuite.java
@@ -15,9 +15,12 @@
  */
 package com.google.gwt.dev.jjs;
 
+import com.google.gwt.dev.jjs.optimized.ArrayListOptimizationTest;
+import com.google.gwt.dev.jjs.optimized.ArrayStoreOptimizationTest;
+import com.google.gwt.dev.jjs.optimized.CastOptimizationTest;
+import com.google.gwt.dev.jjs.optimized.SpecializationTest;
 import com.google.gwt.dev.jjs.test.HasNoSideEffectsTest;
 import com.google.gwt.dev.jjs.test.RunAsyncContentTest;
-import com.google.gwt.dev.jjs.test.SpecializationTest;
 import com.google.gwt.junit.tools.GWTTestSuite;
 
 import junit.framework.Test;
@@ -31,6 +34,9 @@
     GWTTestSuite suite = new GWTTestSuite("Test for com.google.gwt.dev.jjs");
 
     // $JUnit-BEGIN$
+    suite.addTestSuite(ArrayListOptimizationTest.class);
+    suite.addTestSuite(ArrayStoreOptimizationTest.class);
+    suite.addTestSuite(CastOptimizationTest.class);
     suite.addTestSuite(SpecializationTest.class);
     suite.addTestSuite(HasNoSideEffectsTest.class);
     // RunAsyncContentTest relies in string interning for its assertions which is now always off
diff --git a/user/test/com/google/gwt/dev/jjs/optimized/ArrayListOptimizationTest.java b/user/test/com/google/gwt/dev/jjs/optimized/ArrayListOptimizationTest.java
new file mode 100644
index 0000000..56107e9
--- /dev/null
+++ b/user/test/com/google/gwt/dev/jjs/optimized/ArrayListOptimizationTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2015 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.jjs.optimized;
+
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+
+import java.util.ArrayList;
+
+/**
+ * Tests for ArrayList checks are optimized out when checking is disabled.
+ */
+@DoNotRunWith(Platform.Devel)
+public class ArrayListOptimizationTest extends OptimizationTestBase {
+
+  private static ArrayList<String> arrayListField = new ArrayList<String>();
+
+  public static String getFromArrayList() {
+    return arrayListField.get(0);
+  }
+
+  private static native String getGeneratedFunctionDefinitionForGet() /*-{
+    return function() {
+      tmp = @ArrayListOptimizationTest::getFromArrayList()();
+    }.toString();
+  }-*/;
+
+  public void testArrayListGetChecksAreRemoved() throws Exception {
+    String functionDef = getGeneratedFunctionDefinitionForGet();
+    assertFunctionMatches(functionDef, "tmp=<obf>.<obf>[0]");
+  }
+
+  private static native String getGeneratedFunctionDefinitionForGetIgnoredReturn()/*-{
+    return function() {
+      @ArrayListOptimizationTest::getFromArrayList()();
+    }.toString();
+  }-*/;
+
+  public void testArrayListCallRemoved() throws Exception {
+    String functionDef = getGeneratedFunctionDefinitionForGetIgnoredReturn();
+    assertFunctionMatches(functionDef, "");
+  }
+
+  // The compiler will not inline unless arrayListField is a parameter.
+  public static void setArrayList(ArrayList<String> arrayListField) {
+    arrayListField.set(0, "abc");
+  }
+
+  private static native String getGeneratedFunctionDefinitionForAdd() /*-{
+    return function() {
+      @ArrayListOptimizationTest::setArrayList(*)(@ArrayListOptimizationTest::arrayListField);
+    }.toString();
+  }-*/;
+
+  public void testArrayListSetChecksAreRemoved() throws Exception {
+    String functionDef = getGeneratedFunctionDefinitionForAdd();
+    assertFunctionMatches(functionDef, "<obf>.<obf>[0]='abc'");
+  }
+
+  private static void iterateArrayList() {
+    for (String s : arrayListField) {
+      // empty
+    }
+  }
+
+  private static native String getGeneratedFunctionDefinitionForIterate() /*-{
+    return @ArrayListOptimizationTest::iterateArrayList().toString();
+  }-*/;
+  
+  // Disabled as resulting snippet is too complex for assertion
+  public void _disabled_testArrayListIterationChecksAreRemoved() throws Exception {
+    String functionDef = getGeneratedFunctionDefinitionForIterate();
+    assertFunctionMatches(
+        functionDef,
+        "function <obf>(){"
+        + "  var <obf>;"
+        + "  for(<obf> = new <obf>(<obf>);<obf>.<obf> < <obf>.<obf>.<obf>.length;){"
+        + "    <obf>.<obf>=<obf>.<obf>++;"
+        + "  }"
+        + "}");
+  }
+}
diff --git a/user/test/com/google/gwt/dev/jjs/optimized/ArrayStoreOptimizationTest.java b/user/test/com/google/gwt/dev/jjs/optimized/ArrayStoreOptimizationTest.java
new file mode 100644
index 0000000..8dbda49
--- /dev/null
+++ b/user/test/com/google/gwt/dev/jjs/optimized/ArrayStoreOptimizationTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.jjs.optimized;
+
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+
+/**
+ * Tests for ArrayStore checks are optimized out when cast checking is disabled.
+ */
+@DoNotRunWith(Platform.Devel)
+public class ArrayStoreOptimizationTest extends OptimizationTestBase {
+
+  private static class TestObject { }
+
+  private static Object[] arrayField = new TestObject[3];
+
+  public static void modifyArray() {
+    arrayField[0] = "ABC";
+  }
+
+  private static native String getGeneratedFunctionDefinition() /*-{
+    return function() {
+      @ArrayStoreOptimizationTest::modifyArray()();
+    }.toString();
+  }-*/;
+
+  public void testArrayStoreChecksAreRemoved() throws Exception {
+    String functionDef = getGeneratedFunctionDefinition();
+    assertFunctionMatches(functionDef, "<obf>[0]='ABC'");
+  }
+}
diff --git a/user/test/com/google/gwt/dev/jjs/optimized/CastOptimizationTest.java b/user/test/com/google/gwt/dev/jjs/optimized/CastOptimizationTest.java
new file mode 100644
index 0000000..4d9743d
--- /dev/null
+++ b/user/test/com/google/gwt/dev/jjs/optimized/CastOptimizationTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.jjs.optimized;
+
+import com.google.gwt.core.client.JavaScriptObject;
+import com.google.gwt.core.client.js.JsType;
+import com.google.gwt.junit.DoNotRunWith;
+import com.google.gwt.junit.Platform;
+
+import java.util.Random;
+
+/**
+ * Tests cast checks are optimized out when cast checking is disabled.
+ */
+@DoNotRunWith(Platform.Devel)
+public class CastOptimizationTest extends OptimizationTestBase {
+
+  private static class TestObject { }
+
+  @JsType(prototype = "Test")
+  private interface JsTypeTestInterface { }
+
+  private interface DualJsoTestInterface { }
+
+  private static class JsoTestObject extends JavaScriptObject implements DualJsoTestInterface {
+    protected JsoTestObject() { }
+  }
+
+  private static Object field;
+
+  @Override
+  protected void gwtSetUp() throws Exception {
+    field = createField();
+  }
+
+  private static Object createField() {
+    // Makes sure that field type is not upgradable even the compiler becomes really smart and also
+    // no types are pruned otherwise casts can be statically evaluated.
+    switch (new Random().nextInt(42)) {
+      case 0:
+        return new TestObject();
+      case 1:
+        return JavaScriptObject.createObject();
+      case 2:
+        return new DualJsoTestInterface() { };
+      case 3:
+        return "Some string";
+      default:
+        return null;
+    }
+  }
+
+  public static TestObject castOp() {
+    return ((TestObject) field);
+  }
+
+  public static JavaScriptObject castOpJso() {
+    return ((JavaScriptObject) field);
+  }
+
+  public static DualJsoTestInterface castOpDualJso() {
+    return ((DualJsoTestInterface) field);
+  }
+
+  public static JavaScriptObject castOpJsType() {
+    return ((JavaScriptObject) field);
+  }
+
+  public static String castOpString() {
+    return ((String) field);
+  }
+
+  private static native String getGeneratedFunctionDefinition() /*-{
+    return function() {
+      @CastOptimizationTest::castOp()();
+      @CastOptimizationTest::castOpJso()();
+      @CastOptimizationTest::castOpDualJso()();
+      @CastOptimizationTest::castOpJsType()();
+      @CastOptimizationTest::castOpString()();
+    }.toString();
+  }-*/;
+
+  public void testCastsAreRemoved() throws Exception {
+    String functionDef = getGeneratedFunctionDefinition();
+    assertFunctionMatches(functionDef, "");
+  }
+}
diff --git a/user/test/com/google/gwt/dev/jjs/optimized/OptimizationTestBase.java b/user/test/com/google/gwt/dev/jjs/optimized/OptimizationTestBase.java
new file mode 100644
index 0000000..5677c36
--- /dev/null
+++ b/user/test/com/google/gwt/dev/jjs/optimized/OptimizationTestBase.java
@@ -0,0 +1,54 @@
+/*
+ * 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.jjs.optimized;
+
+import com.google.gwt.junit.client.GWTTestCase;
+
+/**
+ * Base class for optimizations tests.
+ */
+public abstract class OptimizationTestBase extends GWTTestCase {
+
+  @Override
+  public String getModuleName() {
+    return "com.google.gwt.dev.jjs.CompilerSuiteOptimized";
+  }
+
+  public static void assertFunctionMatches(String functionDef, String pattern) {
+    String content = getFunctionContent(functionDef);
+    String regex = createRegex(pattern);
+    assertTrue("content: " + content, content.matches(regex));
+  }
+
+  private static String getFunctionContent(String functionDef) {
+    String stripped = functionDef.replaceAll("\\s", "");
+    String funcDeclare = "function(){";
+    assertTrue("Resulting function: " + functionDef, stripped.startsWith(funcDeclare));
+    stripped = stripped.substring(funcDeclare.length());
+    assertTrue("Resulting function: " + functionDef, stripped.endsWith("}"));
+    stripped = stripped.substring(0, stripped.length() - 1);
+    stripped = stripped.replace('"', '\''); // for HtmlUnit
+    return stripped;
+  }
+
+  private static String createRegex(String pattern) {
+    for (char toBeEscaped : ".[]+".toCharArray()) {
+      pattern = pattern.replace("" + toBeEscaped, "\\" + toBeEscaped);
+    }
+    pattern = pattern.replace("<obf>", "\\w+");
+    return pattern + ";?";
+  }
+}
diff --git a/user/test/com/google/gwt/dev/jjs/test/SpecializationTest.java b/user/test/com/google/gwt/dev/jjs/optimized/SpecializationTest.java
similarity index 95%
rename from user/test/com/google/gwt/dev/jjs/test/SpecializationTest.java
rename to user/test/com/google/gwt/dev/jjs/optimized/SpecializationTest.java
index 7237a97..664ce27 100644
--- a/user/test/com/google/gwt/dev/jjs/test/SpecializationTest.java
+++ b/user/test/com/google/gwt/dev/jjs/optimized/SpecializationTest.java
@@ -13,7 +13,7 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-package com.google.gwt.dev.jjs.test;
+package com.google.gwt.dev.jjs.optimized;
 
 import com.google.gwt.junit.DoNotRunWith;
 import com.google.gwt.junit.Platform;
@@ -57,7 +57,7 @@
 
   @Override
   public String getModuleName() {
-    return "com.google.gwt.dev.jjs.CompilerSuite";
+    return "com.google.gwt.dev.jjs.CompilerSuiteOptimized";
   }
 
   public void testSpecialization() {