- System.identityHashCode() now returns stable values for Strings.
- Moved Impl into its own package, made public.

Review by: bruce (voice)

git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@2318 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/core/client/GWT.java b/user/src/com/google/gwt/core/client/GWT.java
index dc8e0f4..b4652d7 100644
--- a/user/src/com/google/gwt/core/client/GWT.java
+++ b/user/src/com/google/gwt/core/client/GWT.java
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.core.client;
 
+import com.google.gwt.core.client.impl.Impl;
+
 /**
  * Supports core functionality that in some cases requires direct support from
  * the compiler and runtime systems such as runtime type information and
diff --git a/user/src/com/google/gwt/core/client/Impl.java b/user/src/com/google/gwt/core/client/Impl.java
deleted file mode 100644
index 8cb8903..0000000
--- a/user/src/com/google/gwt/core/client/Impl.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2008 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.core.client;
-
-final class Impl {
-
-  private static int sNextHashId = 0;
-
-  protected static int getNextHashId() {
-    return ++sNextHashId;
-  }
-
-  static native int getHashCode(Object o) /*-{
-    return o.$H || (o.$H = @com.google.gwt.core.client.Impl::getNextHashId()());
-  }-*/;
-
-  static native String getHostPageBaseURL() /*-{
-    var s = $doc.location.href;
-
-    // Pull off any hash.
-    var i = s.indexOf('#');
-    if (i != -1)
-      s = s.substring(0, i);
-
-    // Pull off any query string.
-    i = s.indexOf('?');
-    if (i != -1)
-      s = s.substring(0, i);
-
-    // Rip off everything after the last slash.
-    i = s.lastIndexOf('/');
-    if (i != -1)
-      s = s.substring(0, i);
-      
-    // Ensure a final slash if non-empty.
-    return s.length > 0 ? s + "/" : "";
-  }-*/;
-
-  static native String getModuleBaseURL() /*-{
-    return $moduleBase;
-  }-*/;
-
-  static native String getModuleName() /*-{
-    return $moduleName;
-  }-*/;
-}
diff --git a/user/src/com/google/gwt/core/client/JavaScriptObject.java b/user/src/com/google/gwt/core/client/JavaScriptObject.java
index 274d2da..2fd1f7f 100644
--- a/user/src/com/google/gwt/core/client/JavaScriptObject.java
+++ b/user/src/com/google/gwt/core/client/JavaScriptObject.java
@@ -15,6 +15,8 @@
  */
 package com.google.gwt.core.client;
 
+import com.google.gwt.core.client.impl.Impl;
+
 /**
  * An opaque handle to a native JavaScript object. A
  * <code>JavaScriptObject</code> cannot be created directly.
diff --git a/user/src/com/google/gwt/core/client/impl/Impl.java b/user/src/com/google/gwt/core/client/impl/Impl.java
new file mode 100644
index 0000000..ab05a2f
--- /dev/null
+++ b/user/src/com/google/gwt/core/client/impl/Impl.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2008 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.core.client.impl;
+
+/**
+ * Private implementation class for GWT core. This API is should not be
+ * considered public or stable.
+ */
+public final class Impl {
+
+  private static int sNextHashId = 0;
+
+  /**
+   * Gets an identity-based hash code on the passed-in Object by adding an
+   * expando. This method should not be used with <code>null</code> or any
+   * String. The former will crash and the later will produce unstable results
+   * when called repeatedly with a String primitive.
+   */
+  public static native int getHashCode(Object o) /*-{
+    return o.$H || (o.$H = @com.google.gwt.core.client.impl.Impl::getNextHashId()());
+  }-*/;
+
+  public static native String getHostPageBaseURL() /*-{
+    var s = $doc.location.href;
+
+    // Pull off any hash.
+    var i = s.indexOf('#');
+    if (i != -1)
+      s = s.substring(0, i);
+
+    // Pull off any query string.
+    i = s.indexOf('?');
+    if (i != -1)
+      s = s.substring(0, i);
+
+    // Rip off everything after the last slash.
+    i = s.lastIndexOf('/');
+    if (i != -1)
+      s = s.substring(0, i);
+      
+    // Ensure a final slash if non-empty.
+    return s.length > 0 ? s + "/" : "";
+  }-*/;
+
+  public static native String getModuleBaseURL() /*-{
+    return $moduleBase;
+  }-*/;
+
+  public static native String getModuleName() /*-{
+    return $moduleName;
+  }-*/;
+
+  /**
+   * Called from JSNI.
+   */
+  @SuppressWarnings("unused")
+  private static int getNextHashId() {
+    return ++sNextHashId;
+  }
+}
diff --git a/user/super/com/google/gwt/emul/java/lang/Object.java b/user/super/com/google/gwt/emul/java/lang/Object.java
index 13bbca5..c9d12dc 100644
--- a/user/super/com/google/gwt/emul/java/lang/Object.java
+++ b/user/super/com/google/gwt/emul/java/lang/Object.java
@@ -15,6 +15,8 @@
  */
 package java.lang;
 
+import com.google.gwt.core.client.impl.Impl;
+
 /**
  * The superclass of all other types. The GWT emulation library supports a
  * limited subset of methods on <code>Object</code> due to browser
@@ -41,7 +43,7 @@
   }
 
   /*
-   * Magic; unlike the real JDT, we don't spec this method as final.  The
+   * Magic; unlike the real JRE, we don't spec this method as final. The
    * compiler will generate a polymorphic override on every other class which
    * will return the correct class object.
    */
@@ -49,16 +51,16 @@
     return Object.class;
   }
 
-  public native int hashCode() /*-{
-    return @com.google.gwt.core.client.Impl::getHashCode(Ljava/lang/Object;)(this);
-  }-*/;
+  public int hashCode() {
+    return Impl.getHashCode(this);
+  }
 
   public String toString() {
     return getClass().getName() + '@' + Integer.toHexString(hashCode());
   }
 
   /**
-   * Never called.
+   * Never called; here for compatibility.
    * 
    * @skip
    */
diff --git a/user/super/com/google/gwt/emul/java/lang/System.java b/user/super/com/google/gwt/emul/java/lang/System.java
index 9a2c21c..a6d22e1 100644
--- a/user/super/com/google/gwt/emul/java/lang/System.java
+++ b/user/super/com/google/gwt/emul/java/lang/System.java
@@ -15,6 +15,8 @@
  */
 package java.lang;
 
+import com.google.gwt.core.client.impl.Impl;
+
 import java.io.PrintStream;
 
 /**
@@ -97,9 +99,10 @@
   public static void gc() {
   };
 
-  public static native int identityHashCode(Object o) /*-{
-    return (o == null) ? 0 : @com.google.gwt.core.client.Impl::getHashCode(Ljava/lang/Object;)(o);
-  }-*/;
+  public static int identityHashCode(Object o) {
+    return (o == null) ? 0 : (!(o instanceof String)) ? Impl.getHashCode(o)
+        : String.HashCache.getHashCode((String) o);
+  }
 
   public static native void setErr(PrintStream err) /*-{
     @java.lang.System::err = err;