Version 2.18.0-88.0.dev

Merge commit '438c1ed2ba5966fee2e5e44f13956154358492f9' into 'dev'
diff --git a/DEPS b/DEPS
index 3c7752c..4d99350 100644
--- a/DEPS
+++ b/DEPS
@@ -699,6 +699,12 @@
     'action': ['python3', 'sdk/tools/generate_package_config.py'],
   },
   {
+    # Generate the sdk/version file.
+    'name': 'Generate sdk/version',
+    'pattern': '.',
+    'action': ['python3', 'sdk/tools/generate_sdk_version_file.py'],
+  },
+  {
     # Pull Debian sysroot for i386 Linux
     'name': 'sysroot_i386',
     'pattern': '.',
diff --git a/runtime/tests/vm/dart/regress_48948_test.dart b/runtime/tests/vm/dart/regress_48948_test.dart
new file mode 100644
index 0000000..2a334b3
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_48948_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/48948.
+
+import 'package:expect/expect.dart';
+
+class Foo {
+  const Foo(this.x, this.y);
+
+  final int x;
+  final int y;
+
+  static int hashCodeCounter = 0;
+
+  @override
+  int get hashCode {
+    hashCodeCounter++;
+    return x.hashCode ^ y.hashCode;
+  }
+}
+
+void main() {
+  final Map<Foo, int> someMap = {};
+  final Set<Foo> someSet = {};
+  Expect.equals(0, Foo.hashCodeCounter);
+
+  someMap[Foo(1, 100)] = 2;
+  Expect.equals(1, Foo.hashCodeCounter);
+
+  someSet.add(Foo(1, 100));
+  Expect.equals(2, Foo.hashCodeCounter);
+}
diff --git a/runtime/tests/vm/dart_2/regress_48948_test.dart b/runtime/tests/vm/dart_2/regress_48948_test.dart
new file mode 100644
index 0000000..0e71942
--- /dev/null
+++ b/runtime/tests/vm/dart_2/regress_48948_test.dart
@@ -0,0 +1,36 @@
+// Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Regression test for https://github.com/dart-lang/sdk/issues/48948.
+
+// @dart = 2.9
+
+import 'package:expect/expect.dart';
+
+class Foo {
+  const Foo(this.x, this.y);
+
+  final int x;
+  final int y;
+
+  static int hashCodeCounter = 0;
+
+  @override
+  int get hashCode {
+    hashCodeCounter++;
+    return x.hashCode ^ y.hashCode;
+  }
+}
+
+void main() {
+  final Map<Foo, int> someMap = {};
+  final Set<Foo> someSet = {};
+  Expect.equals(0, Foo.hashCodeCounter);
+
+  someMap[Foo(1, 100)] = 2;
+  Expect.equals(1, Foo.hashCodeCounter);
+
+  someSet.add(Foo(1, 100));
+  Expect.equals(2, Foo.hashCodeCounter);
+}
diff --git a/sdk/.gitignore b/sdk/.gitignore
new file mode 100644
index 0000000..edd4204
--- /dev/null
+++ b/sdk/.gitignore
@@ -0,0 +1,2 @@
+# Generated version file for the unpatched SDK
+version
diff --git a/sdk/lib/_internal/vm/lib/compact_hash.dart b/sdk/lib/_internal/vm/lib/compact_hash.dart
index 003be2c..5dc42fd 100644
--- a/sdk/lib/_internal/vm/lib/compact_hash.dart
+++ b/sdk/lib/_internal/vm/lib/compact_hash.dart
@@ -345,7 +345,6 @@
 
     for (int j = 0; j < _usedData; j += 2) {
       final key = _data[j];
-      final value = _data[j + 1];
 
       final fullHash = _hashCode(key);
       final hashPattern = _HashBase._hashPattern(fullHash, hashMask, size);
@@ -452,10 +451,10 @@
     }
   }
 
-  void _insert(K key, V value, int hashPattern, int i) {
+  void _insert(K key, V value, int fullHash, int hashPattern, int i) {
     if (_usedData == _data.length) {
       _rehash();
-      this[key] = value;
+      _set(key, value, fullHash);
     } else {
       assert(1 <= hashPattern && hashPattern < (1 << 32));
       final int index = _usedData >> 1;
@@ -496,8 +495,12 @@
   }
 
   void operator []=(K key, V value) {
-    final int size = _index.length;
     final int fullHash = _hashCode(key);
+    _set(key, value, fullHash);
+  }
+
+  void _set(K key, V value, int fullHash) {
+    final int size = _index.length;
     final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
     final int d =
         _findValueOrInsertPoint(key, fullHash, hashPattern, size, _index);
@@ -505,7 +508,7 @@
       _data[d] = value;
     } else {
       final int i = -d;
-      _insert(key, value, hashPattern, i);
+      _insert(key, value, fullHash, hashPattern, i);
     }
   }
 
@@ -526,7 +529,7 @@
       this[key] = value;
     } else {
       final int i = -d;
-      _insert(key, value, hashPattern, i);
+      _insert(key, value, fullHash, hashPattern, i);
     }
     return value;
   }
@@ -835,10 +838,14 @@
   }
 
   bool add(E key) {
+    final int fullHash = _hashCode(key);
+    return _add(key, fullHash);
+  }
+
+  bool _add(E key, int fullHash) {
     final int size = _index.length;
     final int sizeMask = size - 1;
     final int maxEntries = size >> 1;
-    final int fullHash = _hashCode(key);
     final int hashPattern = _HashBase._hashPattern(fullHash, _hashMask, size);
     int i = _HashBase._firstProbe(fullHash, sizeMask);
     int firstDeleted = -1;
@@ -859,7 +866,7 @@
     }
     if (_usedData == _data.length) {
       _rehash();
-      add(key);
+      _add(key, fullHash);
     } else {
       final int insertionPoint = (firstDeleted >= 0) ? firstDeleted : i;
       assert(1 <= hashPattern && hashPattern < (1 << 32));
diff --git a/tools/VERSION b/tools/VERSION
index 7b8f920..9aaaf90 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
 MAJOR 2
 MINOR 18
 PATCH 0
-PRERELEASE 87
+PRERELEASE 88
 PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/generate_sdk_version_file.py b/tools/generate_sdk_version_file.py
new file mode 100755
index 0000000..85354a6
--- /dev/null
+++ b/tools/generate_sdk_version_file.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+# Copyright (c) 2022, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+import os
+import utils
+import sys
+
+SDK_VERSION_FILE = os.path.join(utils.DART_DIR, 'sdk', 'version')
+
+
+def Main():
+    version = utils.ReadVersionFile()
+    with open(SDK_VERSION_FILE, 'w') as versionFile:
+        versionFile.write(f'{version.major}.{version.minor}.0\n')
+    return 0
+
+
+if __name__ == '__main__':
+    sys.exit(Main())