Migrate all javaemul.internal to user

Change-Id: I4121c7979552043bce654f6ea418f1519e3d51c4
diff --git a/user/BUILD b/user/BUILD
index 64ca2fa..2fb8d6f 100644
--- a/user/BUILD
+++ b/user/BUILD
@@ -60,10 +60,13 @@
 java_library(
     name = "gwt-user-bare",
     srcs = glob(
-        ["src/**/*.java"],
+        [
+            "src/**/*.java",
+            "super/com/google/gwt/emul/javaemul/internal/**/*.java",
+        ],
         exclude = [
             "src/com/google/gwt/junit/**/*.java",  # see gwt-testing
-            "**/super/**",
+            "**/EmulatedCharset.java",
             "**/RunStyleSelenium.java",
         ],
     ),
@@ -343,8 +346,6 @@
             "src/com/google/gwt/user/client/impl/WindowImpl.java",
             "src/com/google/gwt/dom/client/*.java",
             "src/com/google/gwt/core/client/impl/Impl.java",
-            "src/com/google/gwt/core/client/impl/Disposable.java",
-            "src/com/google/gwt/core/client/impl/UnloadSupport.java",
             "src/com/google/gwt/core/client/impl/StackTraceCreator.java",
             "src/com/google/gwt/core/client/impl/SchedulerImpl.java",
             "src/com/google/gwt/core/client/impl/AsyncFragmentLoader.java",
@@ -359,12 +360,13 @@
             "src/com/google/gwt/i18n/client/impl/*.java",
             "src/com/google/gwt/i18n/client/*.java",
             "src/com/google/gwt/i18n/rebind/keygen/*.java",
+            "super/com/google/gwt/emul/javaemul/internal/ArrayHelper.java",
+            "super/com/google/gwt/emul/javaemul/internal/ArrayStamper.java",
             # And it's also sensible to want for serialization:
             "src/com/google/gwt/user/client/ui/SuggestOracle.java",
         ],
         exclude = [
             "**/junit/**",
-            "**/super/**",
             "**/package-info.java",
             "src/com/google/web/bindery/requestfactory/server/RequestFactoryJarExtractor.java",
         ],
@@ -641,24 +643,30 @@
 )
 
 filegroup(
-    name = "emul",
-    srcs = glob(
-        [
-            "super/com/google/gwt/emul/java/**/*.java",
-        ],
-    ),
+    name = "java_emul",
+    srcs = glob(["super/com/google/gwt/emul/java/**/*.java"]),
     visibility = ["//third_party/java_src/j2cl:__subpackages__"],
 )
 
 filegroup(
-    name = "emul_test",
+    name = "java_emul_internal",
+    srcs = glob(["super/com/google/gwt/emul/javaemul/**/*.java"]),
+    visibility = ["//third_party/java_src/j2cl:__subpackages__"],
+)
+
+filegroup(
+    name = "java_emul_test",
     srcs = glob(
         [
             "test/com/google/gwt/emultest/**/*.java",
             "test/com/google/gwt/testing/TestUtils.java",
             "test/org/apache/commons/**/*.java",
         ],
-        exclude = ["**/package-info.java"],
+        exclude = [
+            "test/**/java8/**",
+            "test/**/*Java8Suite.java",
+            "**/package-info.java",
+        ],
     ),
     visibility = ["//third_party/java_src/j2cl:__subpackages__"],
 )
diff --git a/user/build.xml b/user/build.xml
index bf50826..7769964 100755
--- a/user/build.xml
+++ b/user/build.xml
@@ -104,7 +104,8 @@
   <target name="compile" description="Compile all class files"
           unless="compile.complete">
     <mkdir dir="${javac.out}"/>
-    <gwt.javac excludes="**/super/**">
+    <gwt.javac excludes="**/EmulatedCharset.java">
+      <src path="super/com/google/gwt/emul/javaemul/internal"/>
       <classpath>
         <pathelement location="${gwt.tools.lib}/gss/2015-10-07/closure-stylesheets-library-20151007-rebased.jar"/>
         <pathelement location="${gwt.tools.lib}/gss/2015-11-04/closure-stylesheets-library-20151104-rebased.jar"/>
diff --git a/user/src/com/google/gwt/core/client/JavaScriptObject.java b/user/src/com/google/gwt/core/client/JavaScriptObject.java
index 3462bc7..abaa697 100644
--- a/user/src/com/google/gwt/core/client/JavaScriptObject.java
+++ b/user/src/com/google/gwt/core/client/JavaScriptObject.java
@@ -15,8 +15,6 @@
  */
 package com.google.gwt.core.client;
 
-import javaemul.internal.HashCodes;
-
 /**
  * An opaque handle to a native JavaScript object. A
  * <code>JavaScriptObject</code> cannot be created directly.
@@ -148,7 +146,7 @@
    */
   @Override
   public final int hashCode() {
-    return HashCodes.getObjectIdentityHashCode(this);
+    return super.hashCode();
   }
 
   /**
diff --git a/user/super/com/google/gwt/emul/Emulation.gwt.xml b/user/super/com/google/gwt/emul/Emulation.gwt.xml
index 9555138..9b75e95 100644
--- a/user/super/com/google/gwt/emul/Emulation.gwt.xml
+++ b/user/super/com/google/gwt/emul/Emulation.gwt.xml
@@ -15,7 +15,6 @@
 <!-- A JavaScript-based emulation of the Java Runtime library.              -->
 <!-- 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"
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/ArrayHelper.java b/user/super/com/google/gwt/emul/javaemul/internal/ArrayHelper.java
new file mode 100644
index 0000000..1fc2a0e
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/ArrayHelper.java
@@ -0,0 +1,98 @@
+/*
+ * 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 javaemul.internal;
+
+/**
+ * Provides utilities to perform operations on Arrays.
+ */
+public class ArrayHelper {
+
+  public static final int ARRAY_PROCESS_BATCH_SIZE = 10000;
+
+  public static <T> T[] clone(T[] array, int fromIndex, int toIndex) {
+    Object result = unsafeClone(array, fromIndex, toIndex);
+    return ArrayStamper.stampJavaTypeInfo(result, array);
+  }
+
+  /**
+   * Unlike clone, this method returns a copy of the array that is not type marked. This is only
+   * safe for temp arrays as returned array will not do any type checks.
+   */
+  public static native Object[] unsafeClone(Object array, int fromIndex, int toIndex) /*-{
+    return array.slice(fromIndex, toIndex);
+  }-*/;
+
+  public static <T> T[] createFrom(T[] array, int length) {
+    Object result = createNativeArray(length);
+    return ArrayStamper.stampJavaTypeInfo(result, array);
+  }
+
+  private static native Object createNativeArray(int length)/*-{
+    return new Array(length);
+  }-*/;
+
+  public static native int getLength(Object array) /*-{
+    return array.length;
+  }-*/;
+
+  public static native void setLength(Object array, int length)/*-{
+    array.length = length;
+  }-*/;
+
+  public static native void removeFrom(Object array, int index, int deleteCount) /*-{
+    array.splice(index, deleteCount);
+  }-*/;
+
+  public static native void insertTo(Object array, int index, Object value) /*-{
+    array.splice(index, 0, value);
+  }-*/;
+
+  public static void insertTo(Object array, int index, Object[] values) {
+    copy(values, 0, array, index, values.length, false);
+  }
+
+  public static void copy(Object array, int srcOfs, Object dest, int destOfs, int len) {
+    copy(array, srcOfs, dest, destOfs, len, true);
+  }
+
+  private static void copy(
+      Object src, int srcOfs, Object dest, int destOfs, int len, boolean overwrite) {
+    /*
+     * Array.prototype.splice is not used directly to overcome the limits imposed to the number of
+     * function parameters by browsers.
+     */
+
+    if (src == dest) {
+      // copying to the same array, make a copy first
+      src = unsafeClone(src, srcOfs, srcOfs + len);
+      srcOfs = 0;
+    }
+    for (int batchStart = srcOfs, end = srcOfs + len; batchStart < end;) {
+      // increment in block
+      int batchEnd = Math.min(batchStart + ARRAY_PROCESS_BATCH_SIZE, end);
+      len = batchEnd - batchStart;
+      applySplice(dest, destOfs, overwrite ? len : 0, unsafeClone(src, batchStart, batchEnd));
+      batchStart = batchEnd;
+      destOfs += len;
+    }
+  }
+
+  private static native void applySplice(Object array, int index, int deleteCount,
+      Object arrayToAdd) /*-{
+    Array.prototype.splice.apply(array, [index, deleteCount].concat(arrayToAdd));
+  }-*/;
+}
+
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/ArrayStamper.java b/user/super/com/google/gwt/emul/javaemul/internal/ArrayStamper.java
new file mode 100644
index 0000000..7da1402
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/ArrayStamper.java
@@ -0,0 +1,26 @@
+/*
+ * 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 javaemul.internal;
+
+/**
+ * A utility to provide array stamping. Provided as a separate class to simplify super-source.
+ */
+class ArrayStamper {
+  public static native <T> T[] stampJavaTypeInfo(Object array, T[] referenceType) /*-{
+    return @com.google.gwt.lang.Array::stampJavaTypeInfo(
+        Ljava/lang/Object;[Ljava/lang/Object;)(array, referenceType);
+  }-*/;
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/Coercions.java b/user/super/com/google/gwt/emul/javaemul/internal/Coercions.java
new file mode 100644
index 0000000..267b98f
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/Coercions.java
@@ -0,0 +1,34 @@
+/*
+ * 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 javaemul.internal;
+
+/**
+ * Private implementation class for GWT. This API should not be
+ * considered public or stable.
+ */
+public final class Coercions {
+
+  /**
+   * Coerce js int to 32 bits.
+   * Trick related to JS and lack of integer rollover.
+   * {@see com.google.gwt.lang.Cast#narrow_int}
+   */
+  public static int ensureInt(int value) {
+    return value | 0;
+  }
+
+  private Coercions() { }
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/ConsoleLogger.java b/user/super/com/google/gwt/emul/javaemul/internal/ConsoleLogger.java
new file mode 100644
index 0000000..ebad921
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/ConsoleLogger.java
@@ -0,0 +1,74 @@
+/*
+ * 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 javaemul.internal;
+
+/**
+ * A helper to print log messages to console.
+ * <p> Note that, this is not a public API and can change/disappear in any release.
+ */
+public class ConsoleLogger {
+  public static ConsoleLogger createIfSupported() {
+    return isSupported() ? new ConsoleLogger() : null;
+  }
+
+  private static native boolean isSupported() /*-{
+    return !!window.console;
+  }-*/;
+
+  public native void log(String level, String message) /*-{
+    console[level](message);
+  }-*/;
+
+  public void log(String level, Throwable t) {
+    log(level, t, "Exception: ", true);
+  }
+
+  private void log(String level, Throwable t, String label, boolean expanded) {
+    groupStart(label + t.toString(), expanded);
+    log(level, getBackingError(t));
+    Throwable cause = t.getCause();
+    if (cause != null) {
+      log(level, cause, "Caused by: ", false);
+    }
+    for (Throwable suppressed : t.getSuppressed()) {
+      log(level, suppressed, "Suppressed: ", false);
+    }
+    groupEnd();
+  }
+
+  private native void groupStart(String msg, boolean expanded) /*-{
+    // Not all browsers support grouping:
+    var groupStart = (!expanded && console.groupCollapsed) || console.group || console.log;
+    groupStart.call(console, msg);
+  }-*/;
+
+  private native void groupEnd() /*-{
+    var groupEnd = console.groupEnd || function(){};
+    groupEnd.call(console);
+  }-*/;
+
+  private native String getBackingError(Throwable t) /*-{
+    // Converts CollectorLegacy (IE8/IE9/Safari5) function stack to something readable.
+    function stringify(fnStack) {
+      if (!fnStack || fnStack.length == 0) {
+        return "";
+      }
+      return "\t" + fnStack.join("\n\t");
+    }
+    var backingError = t.backingJsObject;
+    return backingError && (backingError.stack || stringify(t["fnStack"]));
+  }-*/;
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/DateUtil.java b/user/super/com/google/gwt/emul/javaemul/internal/DateUtil.java
new file mode 100644
index 0000000..321bf95
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/DateUtil.java
@@ -0,0 +1,36 @@
+/*
+ * 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 javaemul.internal;
+
+/**
+ * Simple Helper class to return Date.now.
+ */
+public class DateUtil {
+  /**
+   * Returns the numeric value corresponding to the current time -
+   * the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.
+   */
+  public static native double now() /*-{
+      // IE8 does not have Date.now
+      // when removing IE8 support we change this to Date.now()
+      if (Date.now) {
+          // Date.now vs Date.getTime() performance comparison:
+          // http://jsperf.com/date-now-vs-new-date/8
+          return Date.now();
+      }
+      return (new Date()).getTime();
+  }-*/;
+}
\ No newline at end of file
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/EmulatedCharset.java b/user/super/com/google/gwt/emul/javaemul/internal/EmulatedCharset.java
new file mode 100644
index 0000000..ddde0fa
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/EmulatedCharset.java
@@ -0,0 +1,201 @@
+/*
+ * 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 javaemul.internal;
+
+import java.nio.charset.Charset;
+
+/**
+ * Provides Charset implementations.
+ */
+public abstract class EmulatedCharset extends Charset {
+
+  public static final EmulatedCharset UTF_8 = new UtfCharset("UTF-8");
+
+  public static final EmulatedCharset ISO_LATIN_1 = new LatinCharset("ISO-LATIN-1");
+
+  public static final EmulatedCharset ISO_8859_1 = new LatinCharset("ISO-8859-1");
+
+  private static class LatinCharset extends EmulatedCharset {
+    public LatinCharset(String name) {
+      super(name);
+    }
+
+    @Override
+    public byte[] getBytes(String str) {
+      int n = str.length();
+      byte[] bytes = new byte[n];
+      for (int i = 0; i < n; ++i) {
+        bytes[i] = (byte) (str.charAt(i) & 255);
+      }
+      return bytes;
+    }
+
+    @Override
+    public char[] decodeString(byte[] bytes, int ofs, int len) {
+      char[] chars = new char[len];
+      for (int i = 0; i < len; ++i) {
+        chars[i] = (char) (bytes[ofs + i] & 255);
+      }
+      return chars;
+    }
+  }
+
+  private static class UtfCharset extends EmulatedCharset {
+    public UtfCharset(String name) {
+      super(name);
+    }
+
+    @Override
+    public char[] decodeString(byte[] bytes, int ofs, int len) {
+      // TODO(jat): consider using decodeURIComponent(escape(bytes)) instead
+      int charCount = 0;
+      for (int i = 0; i < len; ) {
+        ++charCount;
+        byte ch = bytes[ofs + i];
+        if ((ch & 0xC0) == 0x80) {
+          throw new IllegalArgumentException("Invalid UTF8 sequence");
+        } else if ((ch & 0x80) == 0) {
+          ++i;
+        } else if ((ch & 0xE0) == 0xC0) {
+          i += 2;
+        } else if ((ch & 0xF0) == 0xE0) {
+          i += 3;
+        } else if ((ch & 0xF8) == 0xF0) {
+          i += 4;
+        } else {
+          // no 5+ byte sequences since max codepoint is less than 2^21
+          throw new IllegalArgumentException("Invalid UTF8 sequence");
+        }
+        if (i > len) {
+          throw new IndexOutOfBoundsException("Invalid UTF8 sequence");
+        }
+      }
+      char[] chars = new char[charCount];
+      int outIdx = 0;
+      int count = 0;
+      for (int i = 0; i < len; ) {
+        int ch = bytes[ofs + i++];
+        if ((ch & 0x80) == 0) {
+          count = 1;
+          ch &= 127;
+        } else if ((ch & 0xE0) == 0xC0) {
+          count = 2;
+          ch &= 31;
+        } else if ((ch & 0xF0) == 0xE0) {
+          count = 3;
+          ch &= 15;
+        } else if ((ch & 0xF8) == 0xF0) {
+          count = 4;
+          ch &= 7;
+        } else if ((ch & 0xFC) == 0xF8) {
+          count = 5;
+          ch &= 3;
+        }
+        while (--count > 0) {
+          byte b = bytes[ofs + i++];
+          if ((b & 0xC0) != 0x80) {
+            throw new IllegalArgumentException("Invalid UTF8 sequence at "
+                + (ofs + i - 1) + ", byte=" + Integer.toHexString(b));
+          }
+          ch = (ch << 6) | (b & 63);
+        }
+        outIdx += Character.toChars(ch, chars, outIdx);
+      }
+      return chars;
+    }
+
+    @Override
+    public byte[] getBytes(String str) {
+      // TODO(jat): consider using unescape(encodeURIComponent(bytes)) instead
+      int n = str.length();
+      int byteCount = 0;
+      for (int i = 0; i < n;) {
+        int ch = str.codePointAt(i);
+        i += Character.charCount(ch);
+        if (ch < (1 << 7)) {
+          byteCount++;
+        } else if (ch < (1 << 11)) {
+          byteCount += 2;
+        } else if (ch < (1 << 16)) {
+          byteCount += 3;
+        } else if (ch < (1 << 21)) {
+          byteCount += 4;
+        } else if (ch < (1 << 26)) {
+          byteCount += 5;
+        }
+      }
+      byte[] bytes = new byte[byteCount];
+      int out = 0;
+      for (int i = 0; i < n;) {
+        int ch = str.codePointAt(i);
+        i += Character.charCount(ch);
+        out += encodeUtf8(bytes, out, ch);
+      }
+      return bytes;
+    }
+
+    /**
+     * Encode a single character in UTF8.
+     *
+     * @param bytes byte array to store character in
+     * @param ofs offset into byte array to store first byte
+     * @param codePoint character to encode
+     * @return number of bytes consumed by encoding the character
+     * @throws IllegalArgumentException if codepoint >= 2^26
+     */
+    private int encodeUtf8(byte[] bytes, int ofs, int codePoint) {
+      if (codePoint < (1 << 7)) {
+        bytes[ofs] = (byte) (codePoint & 127);
+        return 1;
+      } else if (codePoint < (1 << 11)) {
+        // 110xxxxx 10xxxxxx
+        bytes[ofs++] = (byte) (((codePoint >> 6) & 31) | 0xC0);
+        bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
+        return 2;
+      } else if (codePoint < (1 << 16)) {
+        // 1110xxxx 10xxxxxx 10xxxxxx
+        bytes[ofs++] = (byte) (((codePoint >> 12) & 15) | 0xE0);
+        bytes[ofs++] = (byte) (((codePoint >> 6) & 63) | 0x80);
+        bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
+        return 3;
+      } else if (codePoint < (1 << 21)) {
+        // 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+        bytes[ofs++] = (byte) (((codePoint >> 18) & 7) | 0xF0);
+        bytes[ofs++] = (byte) (((codePoint >> 12) & 63) | 0x80);
+        bytes[ofs++] = (byte) (((codePoint >> 6) & 63) | 0x80);
+        bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
+        return 4;
+      } else if (codePoint < (1 << 26)) {
+        // 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
+        bytes[ofs++] = (byte) (((codePoint >> 24) & 3) | 0xF8);
+        bytes[ofs++] = (byte) (((codePoint >> 18) & 63) | 0x80);
+        bytes[ofs++] = (byte) (((codePoint >> 12) & 63) | 0x80);
+        bytes[ofs++] = (byte) (((codePoint >> 6) & 63) | 0x80);
+        bytes[ofs] = (byte) ((codePoint & 63) | 0x80);
+        return 5;
+      }
+      throw new IllegalArgumentException("Character out of range: " + codePoint);
+    }
+  }
+
+  public EmulatedCharset(String name) {
+    super(name, null);
+  }
+
+  public abstract byte[] getBytes(String string);
+
+  public abstract char[] decodeString(byte[] bytes, int ofs, int len);
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/HashCodes.java b/user/super/com/google/gwt/emul/javaemul/internal/HashCodes.java
new file mode 100644
index 0000000..86c4c76
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/HashCodes.java
@@ -0,0 +1,51 @@
+/*
+ * 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 javaemul.internal;
+
+/**
+ * Contains logics for calculating hash codes in JavaScript.
+ */
+public class HashCodes {
+
+  private static int sNextHashId = 0;
+  private static final String HASH_CODE_PROPERTY = "$H";
+
+  public static int hashCodeForString(String s) {
+    return StringHashCache.getHashCode(s);
+  }
+
+  public static int getIdentityHashCode(Object o) {
+    if (o == null) {
+      return 0;
+    }
+    return o instanceof String
+        ?  hashCodeForString(JsUtils.unsafeCastToString(o)) : getObjectIdentityHashCode(o);
+  }
+
+  public static native int getObjectIdentityHashCode(Object o) /*-{
+    return o.$H || (o.$H = @HashCodes::getNextHashId()());
+  }-*/;
+
+  /**
+   * Called from JSNI. Do not change this implementation without updating:
+   * <ul>
+   * <li>{@link com.google.gwt.user.client.rpc.impl.SerializerBase}</li>
+   * </ul>
+   */
+  private static int getNextHashId() {
+    return ++sNextHashId;
+  }
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/Internal.gwt.xml b/user/super/com/google/gwt/emul/javaemul/internal/Internal.gwt.xml
new file mode 100644
index 0000000..5365991
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/Internal.gwt.xml
@@ -0,0 +1,22 @@
+<!--                                                                        -->
+<!-- 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   -->
+<!-- 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.                                         -->
+
+<!-- Internal JRE emultation helpers.                                       -->
+<!-- Do not inherit this module directly; inherit com.google.gwt.core.Core. -->
+<!--                                                                        -->
+<!-- Types from this module should never be used in any user code           -->
+<!--                                                                        -->
+<module>
+  <source path=""/>
+</module>
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/InternalPreconditions.java b/user/super/com/google/gwt/emul/javaemul/internal/InternalPreconditions.java
new file mode 100644
index 0000000..15e064b
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/InternalPreconditions.java
@@ -0,0 +1,490 @@
+/*
+ * 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 javaemul.internal;
+
+import java.util.NoSuchElementException;
+
+/**
+ * A utility class that provides utility functions to do precondition checks inside GWT-SDK.
+ */
+// Some parts adapted from Guava
+public final class InternalPreconditions {
+  private static final boolean CHECKED_MODE =
+      System.getProperty("jre.checkedMode", "ENABLED").equals("ENABLED");
+  private static final boolean TYPE_CHECK =
+      System.getProperty("jre.checks.type", "ENABLED").equals("ENABLED");
+  private static final boolean API_CHECK =
+      System.getProperty("jre.checks.api", "ENABLED").equals("ENABLED");
+  private static final boolean BOUND_CHECK =
+      System.getProperty("jre.checks.bounds", "ENABLED").equals("ENABLED");
+
+  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();
+    }
+  }
+
+  /**
+   * 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();
+    }
+  }
+
+  /**
+   * 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));
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving existence of an element.
+   */
+  public static void checkElement(boolean expression) {
+    if (API_CHECK) {
+      checkCriticalElement(expression);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalElement(expression);
+      } 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) {
+    if (!expression) {
+      throw new NoSuchElementException();
+    }
+  }
+
+  /**
+   * 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) {
+    if (API_CHECK) {
+      checkCriticalArgument(expression);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalArgument(expression);
+      } 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.
+   */
+  public static void checkCriticalArgument(boolean expression) {
+    if (!expression) {
+      throw new IllegalArgumentException();
+    }
+  }
+
+  /**
+   * 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.
+   */
+  public static void checkCriticalArgument(boolean expression, Object errorMessage) {
+    if (!expression) {
+      throw new IllegalArgumentException(String.valueOf(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) {
+    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.
+   */
+  public static void checkCriticalArgument(boolean expression, String errorMessageTemplate,
+      Object... errorMessageArgs) {
+    if (!expression) {
+      throw new IllegalArgumentException(format(errorMessageTemplate, errorMessageArgs));
+    }
+  }
+
+  /**
+   * Ensures the truth of an expression involving the state of the calling instance, but not
+   * involving any parameters to the calling method.
+   *
+   * @param expression a boolean expression
+   * @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();
+    }
+  }
+
+  /**
+   * 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 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));
+    }
+  }
+
+  /**
+   * 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();
+    }
+    return reference;
+  }
+
+  /**
+   * 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));
+    }
+  }
+
+  /**
+   * 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);
+    }
+  }
+
+  /**
+   * Ensures that {@code index} specifies a valid <i>element</i> in an array, list or string of size
+   * {@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);
+    }
+  }
+
+  /**
+   * Ensures that {@code index} specifies a valid <i>position</i> in an array, list or string of
+   * 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);
+    }
+  }
+
+  /**
+   * Ensures that {@code start} and {@code end} specify a valid <i>positions</i> in an array, list
+   * or string of size {@code size}, and are in order. A position index may range from zero to
+   * {@code size}, inclusive.
+   */
+  public static void checkPositionIndexes(int start, int end, int size) {
+    if (BOUND_CHECK) {
+      checkCriticalPositionIndexes(start, end, size);
+    } else if (CHECKED_MODE) {
+      try {
+        checkCriticalPositionIndexes(start, end, size);
+      } catch (Exception e) {
+        throw new AssertionError(e);
+      }
+    }
+  }
+
+  /**
+   * Ensures that {@code start} and {@code end} specify a valid <i>positions</i> in an array, list
+   * or string of size {@code size}, and are in order. A position index may range from zero to
+   * {@code size}, inclusive.
+   */
+  public static void checkCriticalPositionIndexes(int start, int end, int size) {
+    if (start < 0) {
+      throw new IndexOutOfBoundsException("fromIndex: " + start + " < 0");
+    }
+    if (end > size) {
+      throw new IndexOutOfBoundsException("toIndex: " + end + " > size " + size);
+    }
+    if (start > end) {
+      throw new IllegalArgumentException("fromIndex: " + start + " > toIndex: " + end);
+    }
+  }
+
+  /**
+   * Checks that bounds are correct.
+   *
+   * @throw StringIndexOutOfBoundsException if the range is not legal
+   */
+  public static void checkStringBounds(int start, int end, int size) {
+    if (start < 0) {
+      throw new StringIndexOutOfBoundsException("fromIndex: " + start + " < 0");
+    }
+    if (end > size) {
+      throw new StringIndexOutOfBoundsException("toIndex: " + end + " > size " + size);
+    }
+    if (end < start) {
+      throw new StringIndexOutOfBoundsException("fromIndex: " + start + " > toIndex: " + end);
+    }
+  }
+
+  /**
+   * Substitutes each {@code %s} in {@code template} with an argument. These are matched by
+   * position: the first {@code %s} gets {@code args[0]}, etc.  If there are more arguments than
+   * placeholders, the unmatched arguments will be appended to the end of the formatted message in
+   * square braces.
+   */
+  private static String format(String template, Object... args) {
+    template = String.valueOf(template); // null -> "null"
+
+    // start substituting the arguments into the '%s' placeholders
+    StringBuilder builder = new StringBuilder(template.length() + 16 * args.length);
+    int templateStart = 0;
+    int i = 0;
+    while (i < args.length) {
+      int placeholderStart = template.indexOf("%s", templateStart);
+      if (placeholderStart == -1) {
+        break;
+      }
+      builder.append(template.substring(templateStart, placeholderStart));
+      builder.append(args[i++]);
+      templateStart = placeholderStart + 2;
+    }
+    builder.append(template.substring(templateStart));
+
+    // if we run out of placeholders, append the extra args in square braces
+    if (i < args.length) {
+      builder.append(" [");
+      builder.append(args[i++]);
+      while (i < args.length) {
+        builder.append(", ");
+        builder.append(args[i++]);
+      }
+      builder.append(']');
+    }
+
+    return builder.toString();
+  }
+
+  // Hides the constructor for this static utility class.
+  private InternalPreconditions() { }
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
new file mode 100644
index 0000000..a1ecbde
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/JsUtils.java
@@ -0,0 +1,59 @@
+/*
+ * 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 javaemul.internal;
+
+/**
+ * Provides an interface for simple JavaScript idioms that can not be expressed in Java.
+ */
+public class JsUtils {
+
+  public static native double getInfinity() /*-{
+    return Infinity;
+  }-*/;
+
+  public static native int parseInt(String s, int radix) /*-{
+    return parseInt(s, radix);
+  }-*/;
+
+  public static native boolean isUndefined(Object value) /*-{
+    return value === undefined;
+  }-*/;
+
+  // TODO(goktug): replace this with a real cast when the compiler can optimize it.
+  public static native String unsafeCastToString(Object string) /*-{
+   return string;
+  }-*/;
+
+  public static native void setPropertySafe(Object map, String key, Object value) /*-{
+    try {
+      // This may throw exception in strict mode.
+      map[key] = value;
+    } catch(ignored) { }
+  }-*/;
+
+  public static native int getIntProperty(Object map, String key) /*-{
+    return map[key];
+  }-*/;
+
+  public static native void setIntProperty(Object map, String key, int value) /*-{
+    map[key] = value;
+  }-*/;
+
+  public static native String typeOf(Object o) /*-{
+    return typeof o;
+  }-*/;
+}
+
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/LongCompareHolder.java b/user/super/com/google/gwt/emul/javaemul/internal/LongCompareHolder.java
new file mode 100644
index 0000000..5a75c7c
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/LongCompareHolder.java
@@ -0,0 +1,27 @@
+/*
+ * 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 javaemul.internal;
+
+/**
+ * A helper class for long comparison.
+ */
+public class LongCompareHolder {
+  // TODO(dankurka): replace this with @JsFunction once its available in GWT.
+  public static native Object getLongComparator() /*-{
+    return @com.google.gwt.lang.LongLib::compare(*);
+  }-*/;
+}
+
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/StringHashCache.java b/user/super/com/google/gwt/emul/javaemul/internal/StringHashCache.java
new file mode 100644
index 0000000..d472de9
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/StringHashCache.java
@@ -0,0 +1,109 @@
+/*
+ * 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 javaemul.internal;
+
+import static javaemul.internal.Coercions.ensureInt;
+
+/**
+ * Hashcode caching for strings.
+ */
+class StringHashCache {
+  /**
+   * The "old" cache; it will be dumped when front is full.
+   */
+  private static Object back = createNativeObject();
+  /**
+   * Tracks the number of entries in front.
+   */
+  private static int count = 0;
+  /**
+   * The "new" cache; it will become back when it becomes full.
+   */
+  private static Object front = createNativeObject();
+  /**
+   * Pulled this number out of thin air.
+   */
+  private static final int MAX_CACHE = 256;
+
+  public static int getHashCode(String str) {
+    // Accesses must to be prefixed with ':' to prevent conflict with built-in
+    // JavaScript properties.
+    String key = ":" + str;
+
+    // Check the front store.
+    Object result = getProperty(front, key);
+    if (!JsUtils.isUndefined(result)) {
+      return unsafeCastToInt(result);
+    }
+    // Check the back store.
+    result = getProperty(back, key);
+    int hashCode = JsUtils.isUndefined(result) ? compute(str) : unsafeCastToInt(result);
+    // Increment can trigger the swap/flush; call after checking back but
+    // before writing to front.
+    increment();
+    JsUtils.setIntProperty(front, key, hashCode);
+
+    return hashCode;
+  }
+
+  private static int compute(String str) {
+    int hashCode = 0;
+    int n = str.length();
+    int nBatch = n - 4;
+    int i = 0;
+
+    // Process batches of 4 characters at a time and add them to the hash coercing to 32 bits
+    while (i < nBatch) {
+      hashCode = str.charAt(i + 3)
+          + 31 * (str.charAt(i + 2)
+          + 31 * (str.charAt(i + 1)
+          + 31 * (str.charAt(i)
+          + 31 * hashCode)));
+
+      hashCode = ensureInt(hashCode); // make sure we don't overflow
+      i += 4;
+    }
+
+    // Now process the leftovers
+    while (i < n) {
+      hashCode = hashCode * 31 + str.charAt(i++);
+    }
+    hashCode = ensureInt(hashCode); // make sure we don't overflow
+
+    return hashCode;
+  }
+
+  private static void increment() {
+    if (count == MAX_CACHE) {
+      back = front;
+      front = createNativeObject();
+      count = 0;
+    }
+    ++count;
+  }
+
+  private static native Object getProperty(Object map, String key) /*-{
+    return map[key];
+  }-*/;
+
+  private static native Object createNativeObject() /*-{
+    return {};
+  }-*/;
+
+  private static native int unsafeCastToInt(Object o) /*-{
+    return o;
+  }-*/;
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/CompilerHint.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/CompilerHint.java
new file mode 100644
index 0000000..b887a6e
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/CompilerHint.java
@@ -0,0 +1,26 @@
+/*
+ * 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 javaemul.internal.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark another annotation as a compiler hint.
+ */
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface CompilerHint {
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/DoNotInline.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/DoNotInline.java
new file mode 100644
index 0000000..4e7321d
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/DoNotInline.java
@@ -0,0 +1,29 @@
+/*
+ * 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 javaemul.internal.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark a given method as not inlineable.
+ * <p>
+ * Internal SDK use only, might change or disappear at any time.
+ */
+@CompilerHint
+@Target(ElementType.METHOD)
+public @interface DoNotInline {
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/ForceInline.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/ForceInline.java
new file mode 100644
index 0000000..c0561c2
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/ForceInline.java
@@ -0,0 +1,29 @@
+/*
+ * 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 javaemul.internal.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark a given method as not inlineable.
+ * <p>
+ * Internal SDK use only, might change or disappear at any time.
+ */
+@CompilerHint
+@Target(ElementType.METHOD)
+public @interface ForceInline {
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/GwtIncompatible.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/GwtIncompatible.java
new file mode 100644
index 0000000..df8326f
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/GwtIncompatible.java
@@ -0,0 +1,32 @@
+/*
+ * 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 javaemul.internal.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * A simple of a GwtIncompatible annotation for internal emulation use.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
+@Documented
+public @interface GwtIncompatible {
+  String value() default "";
+}
\ No newline at end of file
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/HasNoSideEffects.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/HasNoSideEffects.java
new file mode 100644
index 0000000..f21fcff
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/HasNoSideEffects.java
@@ -0,0 +1,29 @@
+/*
+ * 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 javaemul.internal.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark a given method as side-effect free.
+ * <p>
+ * Internal SDK use only, might change or disappear at any time.
+ */
+@CompilerHint
+@Target(ElementType.METHOD)
+public @interface HasNoSideEffects {
+}
diff --git a/user/super/com/google/gwt/emul/javaemul/internal/annotations/SpecializeMethod.java b/user/super/com/google/gwt/emul/javaemul/internal/annotations/SpecializeMethod.java
new file mode 100644
index 0000000..ddab6cd
--- /dev/null
+++ b/user/super/com/google/gwt/emul/javaemul/internal/annotations/SpecializeMethod.java
@@ -0,0 +1,49 @@
+/*
+ * 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 javaemul.internal.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to mark a given method as being specialized. If the specified
+ * parameters and return context match of a JMethodCall, then the call
+ * is retargeted at the specialized version.
+ */
+@Target(ElementType.METHOD)
+@CompilerHint
+public @interface SpecializeMethod {
+
+  /**
+   * Represents a type that matches any type, even void.
+   */
+  interface ANY { }
+
+  /**
+   * List of parameter types, matched via assignability.
+   */
+  Class<?>[] params();
+
+  /**
+   * List of return types to match, or null if you don't care.
+   */
+  Class<?> returns() default ANY.class;
+
+  /**
+   * The name of the method to target. It must have a signature matching to the {@link #params()}.
+   */
+  String target();
+}