[dart2wasm] Cache hash codes in JSStringImpl

Change-Id: I41980461f9e6a4818458aa17471bd868b70ad354
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/362781
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
diff --git a/pkg/dart2wasm/lib/intrinsics.dart b/pkg/dart2wasm/lib/intrinsics.dart
index 41a79fa..0035b434 100644
--- a/pkg/dart2wasm/lib/intrinsics.dart
+++ b/pkg/dart2wasm/lib/intrinsics.dart
@@ -732,14 +732,14 @@
     // dart:_object_helper static functions.
     if (node.target.enclosingLibrary.name == 'dart._object_helper') {
       switch (name) {
-        case "getHash":
+        case "getIdentityHashField":
           Expression arg = node.arguments.positional[0];
           w.ValueType objectType = translator.objectInfo.nonNullableType;
           codeGen.wrap(arg, objectType);
           b.struct_get(translator.objectInfo.struct, FieldIndex.identityHash);
           b.i64_extend_i32_u();
           return w.NumType.i64;
-        case "setHash":
+        case "setIdentityHashField":
           Expression arg = node.arguments.positional[0];
           Expression hash = node.arguments.positional[1];
           w.ValueType objectType = translator.objectInfo.nonNullableType;
diff --git a/sdk/lib/_internal/wasm/lib/js_string.dart b/sdk/lib/_internal/wasm/lib/js_string.dart
index dcb2eeb..b8f2571 100644
--- a/sdk/lib/_internal/wasm/lib/js_string.dart
+++ b/sdk/lib/_internal/wasm/lib/js_string.dart
@@ -606,10 +606,17 @@
     }
   }
 
-  /// This must be kept in sync with `StringBase.hashCode` in string_patch.dart.
-  /// TODO(joshualitt): Find some way to cache the hash code.
   @override
   int get hashCode {
+    int hash = getIdentityHashField(this);
+    if (hash != 0) return hash;
+    hash = _computeHashCode();
+    setIdentityHashField(this, hash);
+    return hash;
+  }
+
+  /// This must be kept in sync with `StringBase.hashCode` in string_patch.dart.
+  int _computeHashCode() {
     int hash = 0;
     final length = this.length;
     for (int i = 0; i < length; i++) {
diff --git a/sdk/lib/_internal/wasm/lib/js_types.dart b/sdk/lib/_internal/wasm/lib/js_types.dart
index be66655..1730dbc 100644
--- a/sdk/lib/_internal/wasm/lib/js_types.dart
+++ b/sdk/lib/_internal/wasm/lib/js_types.dart
@@ -16,6 +16,7 @@
 import 'dart:_error_utils';
 import 'dart:_internal';
 import 'dart:_js_helper' as js;
+import 'dart:_object_helper';
 import 'dart:_string_helper';
 import 'dart:_wasm';
 import 'dart:collection';
diff --git a/sdk/lib/_internal/wasm/lib/object_helper.dart b/sdk/lib/_internal/wasm/lib/object_helper.dart
index 13410eb..0378acc 100644
--- a/sdk/lib/_internal/wasm/lib/object_helper.dart
+++ b/sdk/lib/_internal/wasm/lib/object_helper.dart
@@ -5,5 +5,5 @@
 library dart._object_helper;
 
 // Access hidden identity hash code field.
-external int getHash(Object obj);
-external void setHash(Object obj, int hash);
+external int getIdentityHashField(Object obj);
+external void setIdentityHashField(Object obj, int hash);
diff --git a/sdk/lib/_internal/wasm/lib/object_patch.dart b/sdk/lib/_internal/wasm/lib/object_patch.dart
index 1deb40d..afce211 100644
--- a/sdk/lib/_internal/wasm/lib/object_patch.dart
+++ b/sdk/lib/_internal/wasm/lib/object_patch.dart
@@ -13,14 +13,14 @@
   static final _hashCodeRnd = new Random();
 
   static int _objectHashCode(Object obj) {
-    var result = getHash(obj);
+    var result = getIdentityHashField(obj);
     if (result == 0) {
       // We want the hash to be a Smi value greater than 0.
       do {
         result = _hashCodeRnd.nextInt(0x40000000);
       } while (result == 0);
 
-      setHash(obj, result);
+      setIdentityHashField(obj, result);
       return result;
     }
     return result;
diff --git a/sdk/lib/_internal/wasm/lib/string.dart b/sdk/lib/_internal/wasm/lib/string.dart
index 8f69f78..a5b61afb 100644
--- a/sdk/lib/_internal/wasm/lib/string.dart
+++ b/sdk/lib/_internal/wasm/lib/string.dart
@@ -96,10 +96,10 @@
   static const int _maxUnsignedSmiBits = 63;
 
   int get hashCode {
-    int hash = getHash(this);
+    int hash = getIdentityHashField(this);
     if (hash != 0) return hash;
     hash = _computeHashCode();
-    setHash(this, hash);
+    setIdentityHashField(this, hash);
     return hash;
   }