Change in dart/sdk[master]: Add `Object.hash` and `Object.hashAll` static helper methods.

219 views
Skip to first unread message

Lasse R.H. Nielsen (Gerrit)

unread,
Sep 6, 2018, 5:40:15 AM9/6/18
to rev...@dartlang.org, Leaf Petersen, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

There is currently an error in DDC that prevents this from building the SDK. I'll file issues.

View Change

    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: master
    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
    Gerrit-Change-Number: 73360
    Gerrit-PatchSet: 2
    Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
    Gerrit-CC: Nate Bosch <nbo...@google.com>
    Gerrit-CC: Zach Anderson <z...@google.com>
    Gerrit-Comment-Date: Thu, 06 Sep 2018 09:40:13 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Lasse R.H. Nielsen (Gerrit)

    unread,
    Sep 6, 2018, 5:40:16 AM9/6/18
    to Leaf Petersen, rev...@dartlang.org, Nate Bosch

    Lasse R.H. Nielsen would like Leaf Petersen to review this change.

    View Change

    Add `Object.hash` and `Object.hashAll` static helper methods.

    Bug: http://dartbug.com/11617
    Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
    ---
    M CHANGELOG.md
    M sdk/lib/core/object.dart
    M sdk/lib/internal/internal.dart
    D sdk/lib/math/jenkins_smi_hash.dart
    M sdk/lib/math/math.dart
    M sdk/lib/math/math_sources.gni
    M sdk/lib/math/point.dart
    M sdk/lib/math/rectangle.dart
    A tests/corelib_2/object_hash_test.dart
    9 files changed, 231 insertions(+), 45 deletions(-)

    diff --git a/CHANGELOG.md b/CHANGELOG.md
    index 76ca9f1..f4e99da 100644
    --- a/CHANGELOG.md
    +++ b/CHANGELOG.md
    @@ -19,6 +19,7 @@
    * Added missing methods to `UnmodifiableMapMixin`. Some maps intended to
    be unmodifiable incorrectly allowed new methods added in Dart 2 to
    succeed.
    +* Add `hash` and `hashAll` static helper functions to `Object`.

    ## 2.1.0-dev.3.0

    diff --git a/sdk/lib/core/object.dart b/sdk/lib/core/object.dart
    index 505efdf..dde7351 100644
    --- a/sdk/lib/core/object.dart
    +++ b/sdk/lib/core/object.dart
    @@ -112,4 +112,125 @@
    * A representation of the runtime type of the object.
    */
    external Type get runtimeType;
    +
    + /**
    + * Creates a combined hash code for a number of objects.
    + *
    + * The hash code is computed for all arguments that are actually
    + * supplied, even if they are `null`, by numerically combining the
    + * [Object.hashCode] of each argument.
    + *
    + * The hashing algorithm is based on the [Jenkins hash function](https://en.wikipedia.org/wiki/Jenkins_hash_function)
    + *
    + * Example:
    + * ```dart
    + * class SomeObject {
    + * final Object a, b, c;
    + * SomeObject(this.a, this.b, this.c);
    + * bool operator=(Object other) =>
    + * other is SomeObject && a == other.a && b == other.b && c == other.c;
    + * int get hashCode => Object.hash(a, b, c);
    + * }
    + * ```
    + *
    + * The computed value must be consistent when the function is called
    + * with the same arguments multiple times
    + * during the execution of a single program.
    + *
    + * The hash value generated by this function is *not* guranteed to be stable
    + * over different runs of the same program.
    + * The exact algorithm used may differ between different platforms,
    + * or between different versions of the platform libraries,
    + * and it may depend on values that change per program run
    + *
    + * The [hashAll] function gives the same result as this function when
    + * called with a collection containing the actual arguments to this function.
    + */
    + static int hash(Object object1, Object object2,
    + [Object object3 = sentinelValue,
    + Object object4 = sentinelValue,
    + Object object5 = sentinelValue,
    + Object object6 = sentinelValue,
    + Object object7 = sentinelValue,
    + Object object8 = sentinelValue,
    + Object object9 = sentinelValue,
    + Object object10 = sentinelValue]) {
    + int hash = 0;
    + hash = JenkinsSmiHash.combine(hash, object1.hashCode);
    + hash = JenkinsSmiHash.combine(hash, object2.hashCode);
    + if (!identical(sentinelValue, object3)) {
    + hash = JenkinsSmiHash.combine(hash, object3.hashCode);
    + if (!identical(sentinelValue, object4)) {
    + hash = JenkinsSmiHash.combine(hash, object4.hashCode);
    + if (!identical(sentinelValue, object5)) {
    + hash = JenkinsSmiHash.combine(hash, object5.hashCode);
    + if (!identical(sentinelValue, object6)) {
    + hash = JenkinsSmiHash.combine(hash, object6.hashCode);
    + if (!identical(sentinelValue, object7)) {
    + hash = JenkinsSmiHash.combine(hash, object7.hashCode);
    + if (!identical(sentinelValue, object8)) {
    + hash = JenkinsSmiHash.combine(hash, object8.hashCode);
    + if (!identical(sentinelValue, object9)) {
    + hash = JenkinsSmiHash.combine(hash, object9.hashCode);
    + if (!identical(sentinelValue, object10)) {
    + hash = JenkinsSmiHash.combine(hash, object10.hashCode);
    + }
    + }
    + }
    + }
    + }
    + }
    + }
    + }
    + return JenkinsSmiHash.finish(hash);
    + }
    +
    + /**
    + * Creates a combined hash code for a collection of objects.
    + *
    + * The hash code is computed for elements in [objects],
    + * even if they are `null`, by numerically combining the
    + * [Object.hashCode] of each element.
    + *
    + * The hashing algorithm is based on the [Jenkins hash function](https://en.wikipedia.org/wiki/Jenkins_hash_function)
    + *
    + * The result of `hashAll([o])` is not `o.hashCode`.
    + *
    + * Example:
    + * ```dart
    + * class SomeObject {
    + * final List<String> path;
    + * SomeObject(this.path);
    + * bool operator=(Object other) {
    + * if (other is SomeObject) {
    + * if (path.length != other.path.length) return false;
    + * for (int i = 0; i < path.length; i++) {
    + * if (path[i] != other.path[i]) return false;
    + * }
    + * return true;
    + * }
    + * return false;
    + * }
    + *
    + * int get hashCode => Object.hashAll(path);
    + * }
    + * ```
    + *
    + * The computed value must be consistent when the function is called
    + * with the same arguments multiple times
    + * during the execution of a single program.
    + *
    + * The hash value generated by this function is *not* guranteed to be stable
    + * over different runs of the same program.
    + * The exact algorithm used may differ between different platforms,
    + * or between different versions of the platform libraries,
    + * and it may depend on values that change per program run
    + */
    + static int hashAll(Iterable<Object> objects) {
    + int hash = 0;
    + for (var object in objects) {
    + hash = JenkinsSmiHash.combine(hash, object.hashCode);
    + }
    + return JenkinsSmiHash.finish(hash);
    + }
    }
    diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
    index 7ffc482..5297ae4 100644
    --- a/sdk/lib/internal/internal.dart
    +++ b/sdk/lib/internal/internal.dart
    @@ -112,6 +112,54 @@
    return digit1 * 16 + digit2 - (digit2 & 256);
    }

    +/**
    + * This is the [Jenkins hash function][1] but using masking to keep
    + * values in SMI range.
    + *
    + * [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
    + *
    + * Use:
    + * Hash each value with the hash of the previous value, then get the final
    + * hash by calling finish.
    + * ```
    + * var hash = 0;
    + * for (var value in values) {
    + * hash = JenkinsSmiHash.combine(hash, value.hashCode);
    + * }
    + * hash = JenkinsSmiHash.finish(hash);
    + * ```
    + *
    + * TODO(lrn): Consider specializing this code per platform,
    + * so the VM can use its 64-bit integers directly.
    + */
    +class JenkinsSmiHash {
    + static int combine(int hash, int value) {
    + hash = 0x1fffffff & (hash + value);
    + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
    + return hash ^ (hash >> 6);
    + }
    +
    + static int finish(int hash) {
    + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
    + hash = hash ^ (hash >> 11);
    + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
    + }
    +
    + static int hash2(a, b) => finish(combine(combine(0, a), b));
    +
    + static int hash4(a, b, c, d) =>
    + finish(combine(combine(combine(combine(0, a), b), c), d));
    +}
    +
    +/// Sentinel values that should never be exposed outside of dart:core.
    +class SentinelValue {
    + final int id;
    + const SentinelValue(this.id);
    +}
    +
    +/// A default value to use when only one sentinel is needed.
    +const Object sentinelValue = const SentinelValue(0);
    +
    /// Given an [instance] of some generic type [T], and [extract], a first-class
    /// generic function that takes the same number of type parameters as [T],
    /// invokes the function with the same type arguments that were passed to T
    diff --git a/sdk/lib/math/jenkins_smi_hash.dart b/sdk/lib/math/jenkins_smi_hash.dart
    deleted file mode 100644
    index 1fc7dda..0000000
    --- a/sdk/lib/math/jenkins_smi_hash.dart
    +++ /dev/null
    @@ -1,41 +0,0 @@
    -// Copyright (c) 2013, 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.
    -part of dart.math;
    -
    -/**
    - * This is the [Jenkins hash function][1] but using masking to keep
    - * values in SMI range.
    - *
    - * [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
    - *
    - * Use:
    - * Hash each value with the hash of the previous value, then get the final
    - * hash by calling finish.
    - *
    - * var hash = 0;
    - * for (var value in values) {
    - * hash = JenkinsSmiHash.combine(hash, value.hashCode);
    - * }
    - * hash = JenkinsSmiHash.finish(hash);
    - */
    -class _JenkinsSmiHash {
    - // TODO(11617): This class should be optimized and standardized elsewhere.
    -
    - static int combine(int hash, int value) {
    - hash = 0x1fffffff & (hash + value);
    - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
    - return hash ^ (hash >> 6);
    - }
    -
    - static int finish(int hash) {
    - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
    - hash = hash ^ (hash >> 11);
    - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
    - }
    -
    - static int hash2(a, b) => finish(combine(combine(0, a), b));
    -
    - static int hash4(a, b, c, d) =>
    - finish(combine(combine(combine(combine(0, a), b), c), d));
    -}
    diff --git a/sdk/lib/math/math.dart b/sdk/lib/math/math.dart
    index 658c834..2b16493 100644
    --- a/sdk/lib/math/math.dart
    +++ b/sdk/lib/math/math.dart
    @@ -13,7 +13,8 @@
    */
    library dart.math;

    -part "jenkins_smi_hash.dart";
    +import "dart:_internal" show JenkinsSmiHash;
    +
    part "point.dart";
    part "random.dart";
    part "rectangle.dart";
    diff --git a/sdk/lib/math/math_sources.gni b/sdk/lib/math/math_sources.gni
    index ff8f3fa..c06aead 100644
    --- a/sdk/lib/math/math_sources.gni
    +++ b/sdk/lib/math/math_sources.gni
    @@ -6,7 +6,6 @@
    "math.dart",

    # The above file needs to be first as it lists the parts below.
    - "jenkins_smi_hash.dart",
    "point.dart",
    "random.dart",
    "rectangle.dart",
    diff --git a/sdk/lib/math/point.dart b/sdk/lib/math/point.dart
    index af62968..f645fc6 100644
    --- a/sdk/lib/math/point.dart
    +++ b/sdk/lib/math/point.dart
    @@ -28,7 +28,7 @@
    return x == other.x && y == other.y;
    }

    - int get hashCode => _JenkinsSmiHash.hash2(x.hashCode, y.hashCode);
    + int get hashCode => JenkinsSmiHash.hash2(x.hashCode, y.hashCode);

    /**
    * Add [other] to `this`, as if both points were vectors.
    diff --git a/sdk/lib/math/rectangle.dart b/sdk/lib/math/rectangle.dart
    index 563713c..169d48f 100644
    --- a/sdk/lib/math/rectangle.dart
    +++ b/sdk/lib/math/rectangle.dart
    @@ -46,7 +46,7 @@
    bottom == other.bottom;
    }

    - int get hashCode => _JenkinsSmiHash.hash4(
    + int get hashCode => JenkinsSmiHash.hash4(
    left.hashCode, top.hashCode, right.hashCode, bottom.hashCode);

    /**
    diff --git a/tests/corelib_2/object_hash_test.dart b/tests/corelib_2/object_hash_test.dart
    new file mode 100644
    index 0000000..db3e0d5
    --- /dev/null
    +++ b/tests/corelib_2/object_hash_test.dart
    @@ -0,0 +1,57 @@
    +// Copyright (c) 2018, 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 "dart:typed_data";
    +
    +import "package:expect/expect.dart";
    +
    +main() {
    + const nan = double.nan;
    + const inf = double.infinity;
    +
    + int hash1234 = Object.hash(1, 2, 3, 4);
    + Expect.type<int>(hash1234);
    + Expect.equals(hash1234, Object.hash(1, 2, 3, 4)); // Consistent.
    + Expect.equals(hash1234, Object.hashAll([1, 2, 3, 4]));
    + Expect.equals(hash1234, Object.hashAll(Uint8List.fromList([1, 2, 3, 4])));
    +
    + Expect.notEquals(hash1234, Object.hash(1, 2, 3, 4, null));
    +
    + Expect.equals(Object.hash(1, 2, 3, 4, 5, 6, 7, 8, 9),
    + Object.hashAll([1, 2, 3, 4, 5, 6, 7, 8, 9]));
    +
    + // Works for all kinds of objects;
    + int varHash = Object.hash(
    + "string", 3, nan, true, null, Type, #Symbol, const Object(), function);
    + Expect.equals(
    + varHash,
    + Object.hashAll([
    + "string",
    + 3,
    + nan,
    + true,
    + null,
    + Type,
    + #Symbol,
    + const Object(),
    + function
    + ]));
    +
    + // Object doesn't matter, just its hash code.
    + Expect.equals(hash1234,
    + Object.hash(Hashable(1), Hashable(2), Hashable(3), Hashable(4)));
    +
    + // It's potentially possible to get a conflict, but it doesn't happen here.
    + Expect.notEquals("str".hashCode, Object.hashAll(["str"]));
    +}
    +
    +// static function, used as constant value.
    +void function() {}
    +
    +class Hashable {
    + final Object o;
    + Hashable(this.o);
    + bool operator ==(Object other) => other is Hashable && o == other.o;
    + int get hashCode => o.hashCode;
    +}

    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: master
    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
    Gerrit-Change-Number: 73360
    Gerrit-PatchSet: 2
    Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
    Gerrit-CC: Nate Bosch <nbo...@google.com>
    Gerrit-CC: Zach Anderson <z...@google.com>
    Gerrit-MessageType: newchange

    Stephen Adams (Gerrit)

    unread,
    Sep 6, 2018, 7:11:04 AM9/6/18
    to Lasse R.H. Nielsen, rev...@dartlang.org, Leaf Petersen, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

    View Change

    3 comments:

    • File sdk/lib/core/object.dart:

      • Patch Set #2, Line 149: static int hash(Object object1, Object object2,

        Why insist on object2?
        I think all inputs should be optional so the boilerplate for SomeObject works for 0 or 1 field.
        This will assist producing generated code.

        Presumably this function could be replaced when spread-args are available with something like:

        static int hash(List<Object> ...objects) => hashAll(objects);

      • Patch Set #2, Line 162: hash = JenkinsSmiHash.combine(hash, object3.hashCode);

        As a practical issue this is going to generate terrible code for dart2js (and probably other platforms). In dart2js each call site will pass in all the sentinel values. Each call to get:hashCode will be polymorphic (an 'interceptor' call on dart2js because of non-object types in JavaScript like null).

        Calling hash(a, b, c) is going to be inefficient - the function is too big to inline to get any specialization to improve these problems.

        When the feature was proposed I was concerned about Object.hash being another recommend-to-avoid feature, so I tried this experiment to generate better code for dart2js: https://dart-review.googlesource.com/c/sdk/+/15360

        The key is the control of inlining to achieve
        1. No arity dispatch
        2. More precise receiver types on the get:hashCode calls to avoid polymorphic calls
        3. Use of a shared branch-free combiner (after inlining combine/finish).

        The effect is to rewrite `Object.hash(a, b, c)` to `combine3(a.hashCode, b.hashCode, c.hashCode)`.
        This does generate slightly larger code than simply calling `Object.hash(a, b, c)` but it is often much faster.

        There are a few problems with the force-inline approach (the inliner can't tell that the sentinel is not passed in as an argument, so does not do arity specialization cleanly), so I think it would be better to do the rewrite explicitly. That raises the question: should the rewrite be implemented once in Kernel for all platforms?

    • File sdk/lib/internal/internal.dart:

      • Patch Set #2, Line 133: * so the VM can use its 64-bit integers directly.

        Also there are better hash functions - now that the VM arithmetic truncates, consider murmur.
        In anticipation of this change, perhaps drop 'Jenkins' from he class name.

    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: master
    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
    Gerrit-Change-Number: 73360
    Gerrit-PatchSet: 2
    Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
    Gerrit-CC: Nate Bosch <nbo...@google.com>
    Gerrit-CC: Stephen Adams <s...@google.com>
    Gerrit-CC: Zach Anderson <z...@google.com>
    Gerrit-Comment-Date: Thu, 06 Sep 2018 11:11:02 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Lasse R.H. Nielsen (Gerrit)

    unread,
    Sep 6, 2018, 8:16:43 AM9/6/18
    to rev...@dartlang.org, Stephen Adams, Leaf Petersen, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

    View Change

    3 comments:

    • File sdk/lib/core/object.dart:

      • Patch Set #2, Line 149: static int hash(Object object1, Object object2,

        Why insist on object2? […]

        To discourage using it for one object (or none), where you can just use `object1.hashCode` directly. There is no advantage to using this function for one value, it's pure overhead.

        I'd rather assist *better* generated code, not something of the form `Object.hash(o)` or `Object.hash()`.

        With spread arguments, I'd probably still go for:
        ```
        static int hash(Object object1, Object object2, [Object... objects]);
        ```
        for the same reasons.

      • Patch Set #2, Line 162: if (sentinelValue == object4) {

        As a practical issue this is going to generate terrible code for dart2js (and probably other platfor […]

        This is definitely a function that it would be interesting to make the front end "always inline" and optimize specially (I'm not absolutely sure we can guarantee that the sentinelValue doesn't leak if a user has access to mirrors: https://api.dartlang.org/stable/2.0.0/dart-mirrors/ParameterMirror/defaultValue.html).

        The hashCode calls are going to be polymorphic whenever the code is not inlined, I don't see any good way around that, so it comes down to actually inlining.

        I have no problem with having combine2..combine10 helper functions, or having platform specific implementations (the VM can likely be more efficient since it doesn't have to restrict itself to smis) that knows how to best inline for that platform.

        For now I'm going for a default implementation, and we can definitely make the function external as soon as any platform has a better implementation.

    • File sdk/lib/internal/internal.dart:

      • Also there are better hash functions - now that the VM arithmetic truncates, consider murmur. […]

        Done

    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: master
    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
    Gerrit-Change-Number: 73360
    Gerrit-PatchSet: 3
    Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
    Gerrit-CC: Nate Bosch <nbo...@google.com>
    Gerrit-CC: Stephen Adams <s...@google.com>
    Gerrit-CC: Zach Anderson <z...@google.com>
    Gerrit-Comment-Date: Thu, 06 Sep 2018 12:16:41 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Stephen Adams <s...@google.com>
    Gerrit-MessageType: comment

    Nate Bosch (Gerrit)

    unread,
    Sep 12, 2018, 12:15:49 AM9/12/18
    to Lasse R.H. Nielsen, rev...@dartlang.org, Stephen Adams, Leaf Petersen, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

    View Change

    3 comments:

    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: master
    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
    Gerrit-Change-Number: 73360
    Gerrit-PatchSet: 3
    Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
    Gerrit-CC: Nate Bosch <nbo...@google.com>
    Gerrit-CC: Stephen Adams <s...@google.com>
    Gerrit-CC: Zach Anderson <z...@google.com>
    Gerrit-Comment-Date: Wed, 12 Sep 2018 04:15:47 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Gerrit-MessageType: comment

    Leaf Petersen (Gerrit)

    unread,
    Sep 12, 2018, 12:39:53 AM9/12/18
    to Lasse R.H. Nielsen, rev...@dartlang.org, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

    We're seriously considering adding rest args to the language, would we use them in this API if we had them? If so, should we consider

    View Change

    1 comment:

    • File sdk/lib/core/object.dart:

      • Patch Set #2, Line 149: static int hash(Object object1, Object object2,

        To discourage using it for one object (or none), where you can just use `object1.hashCode` directly. […]

        We're seriously considering adding rest args to the language, would we use them in this API if we had them? If so, should we consider holding off on landing this until we have rest args? We won't be able to change the API after the fact.

    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: master
    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
    Gerrit-Change-Number: 73360
    Gerrit-PatchSet: 3
    Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
    Gerrit-CC: Nate Bosch <nbo...@google.com>
    Gerrit-CC: Stephen Adams <s...@google.com>
    Gerrit-CC: Zach Anderson <z...@google.com>
    Gerrit-Comment-Date: Wed, 12 Sep 2018 04:39:51 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Stephen Adams <s...@google.com>
    Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-MessageType: comment

    Nate Bosch (Gerrit)

    unread,
    Sep 12, 2018, 12:47:02 AM9/12/18
    to Lasse R.H. Nielsen, rev...@dartlang.org, Leaf Petersen, Stephen Adams, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

    View Change

    1 comment:

    • File sdk/lib/core/object.dart:

      • Patch Set #2, Line 149: static int hash(Object object1, Object object2,

        We're seriously considering adding rest args to the language, would we use them in this API if we ha […]

        Would there be negative performance implications of using rest args?

    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

    Gerrit-Project: sdk
    Gerrit-Branch: master
    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
    Gerrit-Change-Number: 73360
    Gerrit-PatchSet: 3
    Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
    Gerrit-CC: Nate Bosch <nbo...@google.com>
    Gerrit-CC: Stephen Adams <s...@google.com>
    Gerrit-CC: Zach Anderson <z...@google.com>
    Gerrit-Comment-Date: Wed, 12 Sep 2018 04:47:00 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Stephen Adams <s...@google.com>
    Comment-In-Reply-To: Leaf Petersen <le...@google.com>

    Stephen Adams

    unread,
    Sep 12, 2018, 2:47:54 AM9/12/18
    to change...@dart-review.googlesource.com, Lasse R.H. Nielsen, Dart Reviews, Leaf Petersen, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson
    When the feature was originally proposed I was against it on the grounds that optional arguments (or rest-arguments) together with dynamic calls to hashCode would be too inefficient, and there is a risk of the feature becoming something that enters the folklore as yet another feature to be avoided.

    I did some experimentation which I wrote up here .
    I believe the compiler needs to understand Object.hash to generate acceptable code.

    While it is reasonable to have a reference implementation using optional arguments or rest-arguments, I think we should have a plan for optimization on all platforms and resources allocated to implement them, and defer adding the feature until he full plan is in place.

    I would prefer a rest-args reference implementation that takes zero or more arguments.

    Stephen Adams (Gerrit)

    unread,
    Sep 12, 2018, 2:48:01 AM9/12/18
    to Lasse R.H. Nielsen, rev...@dartlang.org, Leaf Petersen, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

    When the feature was originally proposed I was against it on the grounds that optional arguments (or rest-arguments) together with dynamic calls to hashCode would be too inefficient, and there is a risk of the feature becoming something that enters the folklore as yet another feature to be avoided.

    I did some experimentation which I wrote up . here

    I believe the compiler needs to understand Object.hash to generate acceptable code.

    While it is reasonable to have a reference implementation using optional arguments or rest-arguments, I think we should have a plan for optimization on all platforms and resources allocated to implement them, and defer adding the feature until he full plan is in place.

    I would prefer a rest-args reference implementation that takes zero or more arguments.

    View Change

      To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: sdk
      Gerrit-Branch: master
      Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
      Gerrit-Change-Number: 73360
      Gerrit-PatchSet: 3
      Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
      Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
      Gerrit-Reviewer: Leaf Petersen <le...@google.com>
      Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
      Gerrit-CC: Nate Bosch <nbo...@google.com>
      Gerrit-CC: Stephen Adams <s...@google.com>
      Gerrit-CC: Zach Anderson <z...@google.com>
      Gerrit-Comment-Date: Wed, 12 Sep 2018 06:47:58 +0000

      Lasse R.H. Nielsen (Gerrit)

      unread,
      Sep 12, 2018, 3:57:19 AM9/12/18
      to rev...@dartlang.org, Leaf Petersen, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

      View Change

      4 comments:

        • Would there be negative performance implications of using rest args?

        • @leafp
          We can change the current API to using rest parameters. It's a static function, so nobody can *implement* the API. We are free to modify it to be more permissive later, e.g., like the signature I wrote above.

          @nbosch
          Performance implications relative to what?
          There is a performance impact of anything, including calling functions. The only things that is completely "performance impact" free is a static function which is always inlined.

          I believe rest arguments *can* be optimized well. Whether implementations do so is obviously up to them.

          With rest arguments, an implementation is free to have a calling convention where it can read values directly off the stack and know the number of parameters. That avoids checking for the sentinel. Likewise, JavaScript can use the `arguments` object directly, which is optimized by the JS engine.
          (At least until someone reifies the list, then it obviously has to be allocated).

          So, code like:

            static int hash(Object object1, Object object2, [Object... objects]) {
          var hash = 0;
          hash = JenkinsSmiHash.combine(hash, object1.hashCode);
          hash = JenkinsSmiHash.combine(hash, object2.hashCode);
          for (int i = 0; i < objects.length; i++) {
          hash = JenkinsSmiHash.combine(hash, objects[i].hashCode);
          }
          return JenkinsSmiHash.finish(hash);
          }

          should be pretty efficient. For JavaScript, it could be compiled to:

          function hash(object1, object2) {
          var hash = 0;
          hash = JenkinsSmiHash.combine$2(hash, object1.hashCode$get());
          hash = JenkinsSmiHash.combine$2(hash, object2.hashCode$get());
          for (int i = 2; i < arguments.length; i++) {
          hash = JenkinsSmiHash.combine$2(
          hash, arguments[i].hashCode$get());
          }
          return JenkinsSmiHash.finish$1(hash);
          }

          The JS implementation will be able to recognize that i is positive and bounded by arguments.length, so arguments[i] is a safe direct-to-stack access and `arguments` never need to be reified.

          The VM should be able to do something similar.

          That code is my end-goal, and why the current `hash` function is designed the away it is.

      • File sdk/lib/core/object.dart:

        • Agree. The implementation documentation should just be on SystemHash.

        • [nit] change "must" to "will be"? This isn't a contract anyone else is expected to follow, it's some […]

          Done. And done.

      • File sdk/lib/math/math.dart:

        • Done

      To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: sdk
      Gerrit-Branch: master
      Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
      Gerrit-Change-Number: 73360
      Gerrit-PatchSet: 3
      Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
      Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
      Gerrit-Reviewer: Leaf Petersen <le...@google.com>
      Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
      Gerrit-CC: Nate Bosch <nbo...@google.com>
      Gerrit-CC: Stephen Adams <s...@google.com>
      Gerrit-CC: Zach Anderson <z...@google.com>
      Gerrit-Comment-Date: Wed, 12 Sep 2018 07:57:15 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Nate Bosch <nbo...@google.com>

      Leaf Petersen (Gerrit)

      unread,
      Sep 12, 2018, 12:40:34 PM9/12/18
      to Lasse R.H. Nielsen, rev...@dartlang.org, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

      View Change

      1 comment:

      • File sdk/lib/core/object.dart:

        • Patch Set #2, Line 149: Object object4 = sentinelValue,

          @leafp […]

          I think it's breaking to change this to rest parameters. You could be tearing it off and passing it somewhere using the current type, and when you change it to rest parameters it's no longer type compatible.

      To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: sdk
      Gerrit-Branch: master
      Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
      Gerrit-Change-Number: 73360
      Gerrit-PatchSet: 8
      Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
      Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
      Gerrit-Reviewer: Leaf Petersen <le...@google.com>
      Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
      Gerrit-CC: Nate Bosch <nbo...@google.com>
      Gerrit-CC: Ryan Macnak <rma...@google.com>
      Gerrit-CC: Stephen Adams <s...@google.com>
      Gerrit-CC: Zach Anderson <z...@google.com>
      Gerrit-Comment-Date: Wed, 12 Sep 2018 16:40:32 +0000

      Nate Bosch (Gerrit)

      unread,
      Sep 12, 2018, 1:09:20 PM9/12/18
      to Lasse R.H. Nielsen, rev...@dartlang.org, Leaf Petersen, Ryan Macnak, Stephen Adams, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

      I would prefer a rest-args reference implementation that takes zero or more arguments.

      You believe we could have a more optimal implementation in JS that way? From an API standpoint I agree with Lasse - I much prefer the first two arguments to not be optional to prevent misuse and confusion.

      View Change

      1 comment:

        • Performance implications relative to what?

          Relative to what our pickier dart2js users would accept - mainly whatever Stephen's intuition is :)

          It sounds like we should be able to be performant enough in JS either way - but if we had to choose between a feature that Google JS users would ban implemented with rest args, vs one they'd use implemented with 10 optional arguments we should choose the latter.

      To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

      Gerrit-Project: sdk
      Gerrit-Branch: master
      Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
      Gerrit-Change-Number: 73360
      Gerrit-PatchSet: 8
      Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
      Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
      Gerrit-Reviewer: Leaf Petersen <le...@google.com>
      Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
      Gerrit-CC: Nate Bosch <nbo...@google.com>
      Gerrit-CC: Ryan Macnak <rma...@google.com>
      Gerrit-CC: Stephen Adams <s...@google.com>
      Gerrit-CC: Zach Anderson <z...@google.com>
      Gerrit-Comment-Date: Wed, 12 Sep 2018 17:09:18 +0000

      Stephen Adams

      unread,
      Sep 12, 2018, 1:25:31 PM9/12/18
      to change...@dart-review.googlesource.com, Lasse R.H. Nielsen, Dart Reviews, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson
      It would take significant effort to compile to the use of 'arguments' as you suggest. I would not make a decision that depends on being able to do that.
      The Dart rest-parameter will implement some collection type, so in the general case you would need to copy arguments to an Array and tag it with a type so that it passes type checks. Reducing this to a simple use of 'arguments' would be a multi-step optimization that requires understanding indexing patterns. We probably will never get around to it, and I expect that level of cleverness would be quite fragile.

      The copying to an Array is done for you with ES6 rest parameters, but we have to figure out what we are doing for IE11 before using '...'.

      Most JavaScript implementations do not optimize 'arguments' well in this use case. Remember that arguments[0] is an alias to object1, so a JIT compiler would be justified in doing less optimization due to the confusing aliasing and resource constraints.
      Since ES6 has rest parameters, I don't expect JavaScript implementors to spend much effort on 'arguments' when they can for the same effort do a better job on rest parameters.

      I think we should allow zero or more arguments.
      Disallowing one argument encourages hash-table collisions: a wrapper over, say, a single int, should probably not have the same hashCode as the int.
      Irregularity always causes problems, for example, code that somehow calls Function.apply(Object.hash, items) will sometimes fail.


      Stephen Adams (Gerrit)

      unread,
      Sep 12, 2018, 1:25:33 PM9/12/18
      to Lasse R.H. Nielsen, rev...@dartlang.org, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

      It would take significant effort to compile to the use of 'arguments' as you suggest. I would not make a decision that depends on being able to do that.

      The Dart rest-parameter will implement some collection type, so in the general case you would need to copy arguments to an Array and tag it with a type so that it passes type checks. Reducing this to a simple use of 'arguments' would be a multi-step optimization that requires understanding indexing patterns. We probably will never get around to it, and I expect that level of cleverness would be quite fragile.

      The copying to an Array is done for you with ES6 rest parameters, but we have to figure out what we are doing for IE11 before using '...'.

      Most JavaScript implementations do not optimize 'arguments' well in this use case. Remember that arguments[0] is an alias to object1, so a JIT compiler would be justified in doing less optimization due to the confusing aliasing and resource constraints.

      Since ES6 has rest parameters, I don't expect JavaScript implementors to spend much effort on 'arguments' when they can for the same effort do a better job on rest parameters.

      I think we should allow zero or more arguments.

      Disallowing one argument encourages hash-table collisions: a wrapper over, say, a single int, should probably not have the same hashCode as the int.

      Irregularity always causes problems, for example, code that somehow calls Function.apply(Object.hash, items) will sometimes fail.

      View Change

        To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: sdk
        Gerrit-Branch: master
        Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
        Gerrit-Change-Number: 73360
        Gerrit-PatchSet: 8
        Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
        Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
        Gerrit-Reviewer: Leaf Petersen <le...@google.com>
        Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
        Gerrit-CC: Nate Bosch <nbo...@google.com>
        Gerrit-CC: Ryan Macnak <rma...@google.com>
        Gerrit-CC: Stephen Adams <s...@google.com>
        Gerrit-CC: Zach Anderson <z...@google.com>
        Gerrit-Comment-Date: Wed, 12 Sep 2018 17:25:31 +0000

        Lasse R.H. Nielsen (Gerrit)

        unread,
        Sep 13, 2018, 4:10:22 AM9/13/18
        to rev...@dartlang.org, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

        View Change

        1 comment:

          • > Performance implications relative to what? […]

            If an

              int Function(Object, Object, [Object..])

            is not assignable to

              int Function(Object, Object, [Object, Object, ... n ..., Object])

            then we are doing something wrong with rest arguments. The rest-argument function can clearly be used in all the same call contexts, and then some.

            The one potential break is due to something using the static type of Object.hash to infer the type of a variable, and then assign something to it.

             var myHash = Object.hash;
            if (useMockHash) {
            myHash = (Object o1, Object o2, [ ... Object o10]) => 0;
            }

            If we consider that breaking, then *any* change *anywhere* is breaking (like adding more optional parameters to a static function, which is something we currently consider as a completely safe change).


            As for performance, I actually think rest parameters will be more performant than the optional arguments with sentinels (mainly due to the sentinels and larger code size). The optional parameters are just a stepping stone to get to the rest parameter version, one I hope we will be able to move forward from soon-ish.
            I just hope they won't ban the ten-parameter function until then.

        To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: sdk
        Gerrit-Branch: master
        Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
        Gerrit-Change-Number: 73360
        Gerrit-PatchSet: 8
        Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
        Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
        Gerrit-Reviewer: Leaf Petersen <le...@google.com>
        Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
        Gerrit-CC: Nate Bosch <nbo...@google.com>
        Gerrit-CC: Ryan Macnak <rma...@google.com>
        Gerrit-CC: Stephen Adams <s...@google.com>
        Gerrit-CC: Zach Anderson <z...@google.com>
        Gerrit-Comment-Date: Thu, 13 Sep 2018 08:10:19 +0000

        Leaf Petersen (Gerrit)

        unread,
        Sep 13, 2018, 1:53:54 PM9/13/18
        to Lasse R.H. Nielsen, rev...@dartlang.org, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

        View Change

        1 comment:

          • If an

          •   int Function(Object, Object, [Object..])

            is not assignable to

              int Function(Object, Object, [Object, Object, ... n ..., Object])
          • then we are doing something wrong with rest arguments. The rest-argument function can clearly be used in all the same call contexts, and then some.

          • Bob's proposal does not follow the principle that any function which can be used in all of the same call contexts is a subtype, for good reason (e.g. the examples with optional parameters he discusses where the call signatures are compatible but the call sends arguments to unexpected parameters).

        To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: sdk
        Gerrit-Branch: master
        Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
        Gerrit-Change-Number: 73360
        Gerrit-PatchSet: 8
        Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
        Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
        Gerrit-Reviewer: Leaf Petersen <le...@google.com>
        Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
        Gerrit-CC: Nate Bosch <nbo...@google.com>
        Gerrit-CC: Ryan Macnak <rma...@google.com>
        Gerrit-CC: Stephen Adams <s...@google.com>
        Gerrit-CC: Zach Anderson <z...@google.com>
        Gerrit-Comment-Date: Thu, 13 Sep 2018 17:53:50 +0000

        Lasse R.H. Nielsen (Gerrit)

        unread,
        Sep 14, 2018, 7:28:56 AM9/14/18
        to rev...@dartlang.org, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

        View Change

        1 comment:

          • > If an […]

            I think you are correct, and I count it as a significant argument against that design.

            It believe it would accept

             static int hash(Object o1, Object o2, [Object o3, ... , Object o10, Object... rest]) { ... }

            (Then I'd probably just intrinsify the method and let the compiler optimize it however best for the platform).

        To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

        Gerrit-Project: sdk
        Gerrit-Branch: master
        Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
        Gerrit-Change-Number: 73360
        Gerrit-PatchSet: 8
        Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
        Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
        Gerrit-Reviewer: Leaf Petersen <le...@google.com>
        Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
        Gerrit-CC: Nate Bosch <nbo...@google.com>
        Gerrit-CC: Ryan Macnak <rma...@google.com>
        Gerrit-CC: Stephen Adams <s...@google.com>
        Gerrit-CC: Zach Anderson <z...@google.com>
        Gerrit-Comment-Date: Fri, 14 Sep 2018 11:28:52 +0000

        Kevin Moore (Gerrit)

        unread,
        Oct 3, 2018, 11:11:53 PM10/3/18
        to Lasse R.H. Nielsen, rev...@dartlang.org, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

        Would LOVE to see this for 2.1!

        View Change

          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

          Gerrit-Project: sdk
          Gerrit-Branch: master
          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
          Gerrit-Change-Number: 73360
          Gerrit-PatchSet: 8
          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
          Gerrit-CC: Kevin Moore <kev...@google.com>
          Gerrit-CC: Nate Bosch <nbo...@google.com>
          Gerrit-CC: Ryan Macnak <rma...@google.com>
          Gerrit-CC: Stephen Adams <s...@google.com>
          Gerrit-CC: Zach Anderson <z...@google.com>
          Gerrit-Comment-Date: Thu, 04 Oct 2018 03:11:51 +0000

          Lasse R.H. Nielsen (Gerrit)

          unread,
          Oct 4, 2018, 9:41:22 AM10/4/18
          to rev...@dartlang.org, Kevin Moore, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

          Would LOVE to see this for 2.1!

          I'm holding it back because I worry that we might not be able to generalize it with the current var-args proposal ("parameter freedom" by rnystrom).

          We might be able to get away with this by documenting that the function may change signature in the future, so it should only be called, not torn off and assigned to a function type, then we might be good.

          View Change

            To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

            Gerrit-Project: sdk
            Gerrit-Branch: master
            Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
            Gerrit-Change-Number: 73360
            Gerrit-PatchSet: 8
            Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
            Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
            Gerrit-Reviewer: Leaf Petersen <le...@google.com>
            Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
            Gerrit-CC: Kevin Moore <kev...@google.com>
            Gerrit-CC: Nate Bosch <nbo...@google.com>
            Gerrit-CC: Ryan Macnak <rma...@google.com>
            Gerrit-CC: Stephen Adams <s...@google.com>
            Gerrit-CC: Zach Anderson <z...@google.com>
            Gerrit-Comment-Date: Thu, 04 Oct 2018 13:41:19 +0000

            Kevin Moore

            unread,
            Oct 4, 2018, 11:53:23 AM10/4/18
            to change...@dart-review.googlesource.com, rev...@dartlang.org, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, Commit Bot, Keerti Parthasarathy, Zach Anderson
            We're going to have the same issue w/ print, right?

            Kevin Moore (Gerrit)

            unread,
            Oct 4, 2018, 11:53:25 AM10/4/18
            to Lasse R.H. Nielsen, rev...@dartlang.org, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

            We're going to have the same issue w/ print, right?

            View Change

              To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

              Gerrit-Project: sdk
              Gerrit-Branch: master
              Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
              Gerrit-Change-Number: 73360
              Gerrit-PatchSet: 8
              Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
              Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
              Gerrit-Reviewer: Leaf Petersen <le...@google.com>
              Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
              Gerrit-CC: Kevin Moore <kev...@google.com>
              Gerrit-CC: Nate Bosch <nbo...@google.com>
              Gerrit-CC: Ryan Macnak <rma...@google.com>
              Gerrit-CC: Stephen Adams <s...@google.com>
              Gerrit-CC: Zach Anderson <z...@google.com>
              Gerrit-Comment-Date: Thu, 04 Oct 2018 15:53:23 +0000

              Lasse R.H. Nielsen (Gerrit)

              unread,
              Oct 5, 2018, 3:23:20 AM10/5/18
              to rev...@dartlang.org, Kevin Moore, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

              Patch Set 8:

              We're going to have the same issue w/ print, right?

              We haven't actually changed print, but if we do before deciding on parameter freedom, then yes.

              View Change

                To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                Gerrit-Project: sdk
                Gerrit-Branch: master
                Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                Gerrit-Change-Number: 73360
                Gerrit-PatchSet: 8
                Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                Gerrit-CC: Kevin Moore <kev...@google.com>
                Gerrit-CC: Nate Bosch <nbo...@google.com>
                Gerrit-CC: Ryan Macnak <rma...@google.com>
                Gerrit-CC: Stephen Adams <s...@google.com>
                Gerrit-CC: Zach Anderson <z...@google.com>
                Gerrit-Comment-Date: Fri, 05 Oct 2018 07:23:18 +0000

                Kevin Moore (Gerrit)

                unread,
                Nov 9, 2018, 1:33:36 PM11/9/18
                to Lasse R.H. Nielsen, rev...@dartlang.org, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                Let's not forget about this for 2.2!

                View Change

                  To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                  Gerrit-Project: sdk
                  Gerrit-Branch: master
                  Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                  Gerrit-Change-Number: 73360
                  Gerrit-PatchSet: 8
                  Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                  Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                  Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                  Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                  Gerrit-CC: Kevin Moore <kev...@google.com>
                  Gerrit-CC: Nate Bosch <nbo...@google.com>
                  Gerrit-CC: Ryan Macnak <rma...@google.com>
                  Gerrit-CC: Stephen Adams <s...@google.com>
                  Gerrit-CC: Zach Anderson <z...@google.com>
                  Gerrit-Comment-Date: Fri, 09 Nov 2018 18:33:35 +0000

                  Nate Bosch (Gerrit)

                  unread,
                  Jun 3, 2019, 7:25:05 PM6/3/19
                  to Lasse R.H. Nielsen, rev...@dartlang.org, Kevin Moore, Leaf Petersen, Ryan Macnak, Stephen Adams, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                  Can we revisit this? I'd rather not see it sit in limbo waiting on a decision about a language feature we aren't actively pursuing...

                  View Change

                    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                    Gerrit-Project: sdk
                    Gerrit-Branch: master
                    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                    Gerrit-Change-Number: 73360
                    Gerrit-PatchSet: 9
                    Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                    Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                    Gerrit-CC: Kevin Moore <kev...@google.com>
                    Gerrit-CC: Nate Bosch <nbo...@google.com>
                    Gerrit-CC: Ryan Macnak <rma...@google.com>
                    Gerrit-CC: Stephen Adams <s...@google.com>
                    Gerrit-CC: Zach Anderson <z...@google.com>
                    Gerrit-Comment-Date: Mon, 03 Jun 2019 23:25:00 +0000

                    Kevin Moore

                    unread,
                    Jun 4, 2019, 12:17:49 AM6/4/19
                    to change...@dart-review.googlesource.com, Lasse R.H. Nielsen, rev...@dartlang.org, Leaf Petersen, Ryan Macnak, Stephen Adams, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson
                    Ditto! Would love to have this.

                    (Don't forget @Since)

                    Kevin Moore (Gerrit)

                    unread,
                    Jun 4, 2019, 12:17:53 AM6/4/19
                    to Lasse R.H. Nielsen, rev...@dartlang.org, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                    Ditto! Would love to have this.

                    (Don't forget @Since)

                    View Change

                      To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                      Gerrit-Project: sdk
                      Gerrit-Branch: master
                      Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                      Gerrit-Change-Number: 73360
                      Gerrit-PatchSet: 9
                      Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                      Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                      Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                      Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                      Gerrit-CC: Kevin Moore <kev...@google.com>
                      Gerrit-CC: Nate Bosch <nbo...@google.com>
                      Gerrit-CC: Ryan Macnak <rma...@google.com>
                      Gerrit-CC: Stephen Adams <s...@google.com>
                      Gerrit-CC: Zach Anderson <z...@google.com>
                      Gerrit-Comment-Date: Tue, 04 Jun 2019 04:17:49 +0000

                      Nate Bosch (Gerrit)

                      unread,
                      Feb 11, 2020, 2:55:29 PM2/11/20
                      to Lasse R.H. Nielsen, rev...@dartlang.org, Kevin Moore, Leaf Petersen, Ryan Macnak, Stephen Adams, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                      If we feel stuck shipping something in the SDK, should we ship a canonical team owned `package:hash` or maybe use `package:math`?

                      I keep seeing hash codes get reimplemented over and over.

                      View Change

                        To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                        Gerrit-Project: sdk
                        Gerrit-Branch: master
                        Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                        Gerrit-Change-Number: 73360
                        Gerrit-PatchSet: 9
                        Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                        Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                        Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                        Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                        Gerrit-CC: Kevin Moore <kev...@google.com>
                        Gerrit-CC: Nate Bosch <nbo...@google.com>
                        Gerrit-CC: Ryan Macnak <rma...@google.com>
                        Gerrit-CC: Stephen Adams <s...@google.com>
                        Gerrit-CC: Zach Anderson <z...@google.com>
                        Gerrit-Comment-Date: Tue, 11 Feb 2020 19:55:25 +0000

                        Dan Field (Gerrit)

                        unread,
                        Mar 15, 2020, 10:37:18 AM3/15/20
                        to Lasse R.H. Nielsen, rev...@dartlang.org, Kevin Moore, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                        Patch Set 9:

                        If we feel stuck shipping something in the SDK, should we ship a canonical team owned `package:hash` or maybe use `package:math`?

                        I keep seeing hash codes get reimplemented over and over.

                        This is already implemented in dart:ui - part of the idea of putting it in the SDK is so we can get rid of it there. Having it in a package won't help things.

                        I second moving forward on this.

                        View Change

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 9
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Stephen Adams <s...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Comment-Date: Sun, 15 Mar 2020 14:37:14 +0000

                          Todd Volkert (Gerrit)

                          unread,
                          Aug 17, 2020, 1:45:04 AM8/17/20
                          to Lasse R.H. Nielsen, rev...@dartlang.org, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • Patchset:

                            • Patch Set #9:

                              I'd like to move forward with this. What's the path forward here?

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 9
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Stephen Adams <s...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Comment-Date: Mon, 17 Aug 2020 05:45:01 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Gerrit-MessageType: comment

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Aug 21, 2020, 10:45:28 AM8/21/20
                          to rev...@dartlang.org, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • Patchset:

                            • Patch Set #9:

                              I'd like to move forward with this. […]

                              The block was concerns about the "10 optional parameters" API being forward compatible with a potential varargs feature.

                              That hasn't changed, but there is no currently active varargs proposal.
                              I'm still fine with landing this.

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 11
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Stephen Adams <s...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Comment-Date: Fri, 21 Aug 2020 14:45:24 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Todd Volkert <tvol...@google.com>
                          Gerrit-MessageType: comment

                          Stephen Adams (Gerrit)

                          unread,
                          Aug 24, 2020, 10:26:58 PM8/24/20
                          to Lasse R.H. Nielsen, rev...@dartlang.org, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          3 comments:

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 12
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Stephen Adams <s...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Comment-Date: Tue, 25 Aug 2020 02:26:53 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Gerrit-MessageType: comment

                          Stephen Adams (Gerrit)

                          unread,
                          Aug 24, 2020, 11:15:55 PM8/24/20
                          to Lasse R.H. Nielsen, rev...@dartlang.org, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 12
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Stephen Adams <s...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Comment-Date: Tue, 25 Aug 2020 03:15:50 +0000

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Aug 25, 2020, 11:08:29 AM8/25/20
                          to rev...@dartlang.org, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          2 comments:

                            • True, we have `?` now :)

                            • This is incapable of distinguishing [1,1] from [2,2]. […]

                              Using `+` would probably be better than `^`. That's what Java does for set equality, but sets have the advantage that the same element doesn't occur more than once. At least it only drops the lowest bit, not all o them, for `[x, x]`. Still not great.

                              Sorting is also an option, but quite a lot more expensive when you need to allocate space for all the hash values before sorting. We should be able to do the computation without allocations. (On the other hand, we can probably reuse a Uint32List buffer and only grow it when necessary - probably by doubling since we are working on an iterator).

                              The Scala approach is to collect three order-independent results, using ^, + and * of the hash codes, then do a three-element hash combination of those three, and the element count, at the end.
                              For us that would be:

                               int n = 0;
                              int x = 0;
                              int a = 0;
                              int m = 1;
                              for (var object in objects) {
                              var h = object.hashCode;
                              x ^= h;
                              a += h;
                              if (h != 0) m *= h;
                              n++;
                              }
                              return SystemHash.hash4(x, a, m, n);

                              That's probably reasonably efficient. Including the count ensures that `[0, 0]` and `[0, 0, 0]` won't have the same hash (but then, I'd probably use `smear` on the object hashCode anyway.)

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 16
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Stephen Adams <s...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Comment-Date: Tue, 25 Aug 2020 15:08:24 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Stephen Adams <s...@google.com>
                          Gerrit-MessageType: comment

                          Stephen Adams (Gerrit)

                          unread,
                          Aug 25, 2020, 8:25:14 PM8/25/20
                          to Lasse R.H. Nielsen, rev...@dartlang.org, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          3 comments:

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 17
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Stephen Adams <s...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Comment-Date: Wed, 26 Aug 2020 00:25:09 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Gerrit-MessageType: comment

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Aug 26, 2020, 8:01:16 AM8/26/20
                          to rev...@dartlang.org, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Stephen Adams, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          3 comments:

                            • It's technically correct. I did write it first in 2018, and it was publicly available through this CL.
                              I don't know what our policy is for updating copyright dates when changing a file, but we usually don't.

                            • Patch Set #16, Line 1: // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file

                              Is there a corelib/ version of this test to match the corelib_2/ version?

                            • Working on that (just want to make the test complete first, and be sure it's correct, before I start copying it).

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 18
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Stephen Adams <s...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Comment-Date: Wed, 26 Aug 2020 12:01:12 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Sep 30, 2020, 1:00:06 PM9/30/20
                          to dart-dc-te...@google.com, rev...@dartlang.org, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 23
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Wed, 30 Sep 2020 16:59:59 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Gerrit-MessageType: comment

                          Kevin Moore (Gerrit)

                          unread,
                          Sep 30, 2020, 1:08:28 PM9/30/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Stephen Adams, Todd Volkert, Dan Field, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          2 comments:

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 23
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Wed, 30 Sep 2020 17:08:23 +0000

                          Dan Field (Gerrit)

                          unread,
                          Sep 30, 2020, 2:29:34 PM9/30/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Stephen Adams, Todd Volkert, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 23
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Wed, 30 Sep 2020 18:29:29 +0000

                          Leaf Petersen (Gerrit)

                          unread,
                          Sep 30, 2020, 8:25:19 PM9/30/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          7 comments:

                          • File sdk/lib/core/object.dart:

                            • Patch Set #23, Line 148: static int hash(Object? object1, Object? object2,

                              I wonder if just hashing all ten unconditionally might not be faster?

                            • Patch Set #23, Line 271: hash = SystemHash.combine(hash, object.hashCode);

                              I think `0.hashCode` is `0`, right? So this will return 0 for any length list of zeros? Fixing the underlying hash is probably the right thing to do here, but if not consider at least incorporating the length?

                            • Patch Set #23, Line 282: * in an order independet way.

                              independent

                            • Patch Set #23, Line 301: * The hash value generated by this function is *not* guranteed to be stable

                              guaranteed

                            • Patch Set #23, Line 311: const int mask = 0x3FFFFFFF;

                              Why const?

                          • File sdk/lib/internal/internal.dart:

                            • Patch Set #23, Line 158: static int hash2(int v1, int v2) {

                              If I've worked through these correctly, I think that hash(0, 0) == hash(0, 0, 0) == hash(0, 0, 0, 0, 0) etc, which doesn't seem ideal. Is there a reason we use this particular hash? Looking it up briefly on the internet, it seems to be state of the art from... 1997? :)

                            • Patch Set #23, Line 265: /// However, for the unordered hash based on xor, we need to improve

                              I don't understand this comment. The unordered hash doesn't use xor that I can see (other than in the course of SystemHash.hash2).

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 23
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Thu, 01 Oct 2020 00:25:14 +0000

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Oct 1, 2020, 5:47:25 AM10/1/20
                          to dart-dc-te...@google.com, rev...@dartlang.org, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          6 comments:

                          • File sdk/lib/core/object.dart:

                            • Patch Set #23, Line 148: static int hash(Object? object1, Object? object2,

                              I wonder if just hashing all ten unconditionally might not be faster?

                            • Not if the `hash` function is inlined. The implementation is optimized for dart2js inlining.
                              Also, `Object.hash(1, 2)` would then not give the same result as `Object.hashAll([1, 2])`, which is a goal.

                            • Here and below: identical will produce smaller code. See https://github. […]

                              Is that true for both VM and dart2js?

                            • I think `0. […]

                              ACK. Another option is to not start with `0`. If the seed is non-zero, then the number of combinations will matter, even if each object hash is zero.

                              I'd prefer to use a *random* seed, set once per execution. Then we avoid people expecting the same hash code between different executions. (But they'd probably also be different between isolates, not sure how great that is).

                            • It's used only once, so it could have been inlined. It's given a name just to avoid "magical constants". I tend to mark magical constants as const.

                          • File sdk/lib/internal/internal.dart:

                            • If I've worked through these correctly, I think that hash(0, 0) == hash(0, 0, 0) == hash(0, 0, 0, 0, […]

                              The problem with hash code algorithms is that it *might* be a breaking change to change the. You never know what people use them for

                              We can consider changing to a different algorithm, but we should be very careful that people won't break when the hash code of strings change, even if it's only because the iteration order of `HashSet<String>` changes.
                              So, for now, this is the algorithm we use, and this CL needs to keep that. For existing code, this should only be a refactoring.

                              For the `Object.hash` functions, we can do something different because they have no existing users. We then *can't* tell people that `Object.hashAll(string.codeUnits) == string.hash`, which would otherwise be true - and yes, `("\x00"*n).hashCode` *is* zero. That's actually a good thing.

                            • I don't understand this comment. […]

                              ACK. It used to, now it uses `+` instead.

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 23
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Dan Field <dnf...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Thu, 01 Oct 2020 09:47:19 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Dan Field <dnf...@google.com>
                          Comment-In-Reply-To: Leaf Petersen <le...@google.com>
                          Gerrit-MessageType: comment

                          Dan Field (Gerrit)

                          unread,
                          Oct 1, 2020, 11:44:31 AM10/1/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Stephen Adams, Todd Volkert, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • File sdk/lib/core/object.dart:

                            • Patch Set #23, Line 157: if (sentinelValue == object3) {

                              Is that true for both VM and dart2js?

                              A quick test locally with dart2js suggests that it produces the same length output, but I'm not quite as familiar with dart2js. For VM, it's definitely true, and Flutter applications use these methods a lot.

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 23
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Thu, 01 Oct 2020 15:44:27 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>
                          Comment-In-Reply-To: Dan Field <dnf...@google.com>
                          Gerrit-MessageType: comment

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Oct 2, 2020, 6:55:45 AM10/2/20
                          to dart-dc-te...@google.com, rev...@dartlang.org, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          2 comments:

                          • File sdk/lib/core/object.dart:

                            • Patch Set #12, Line 148: static int hash(Object? object1, Object? object2,

                              Why not have these all optional? […]

                              This point of the function is to *combine* multiple hashes. Using it for a single value is pointless overhead.
                              If we allow zero or one value, we should still make sure to give the same result as `hashAll` with zero or one arguments.

                              It's true that changing behavior between one and two elements can be annoying, or between one and zero, but it gives better code if you actually change.

                          • File sdk/lib/core/object.dart:

                            • A quick test locally with dart2js suggests that it produces the same length output, but I'm not quit […]

                              I ask because I started out using `identical`, but changed it in patch set 3 after comments from Stephen. I don't remember *why* I changed it, and can't find any comments about that in particular, so maybe it was just because it didn't seem important.

                              Also, why is the VM not just as efficient at `const SentinelValue(0) == x` and `identical(const SentinelValue(0), x)` when it knows statically that `SentinelValue` doesn't override `operator ==`? That seems like a low-hanging optimization fruit.

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 23
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Dan Field <dnf...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Fri, 02 Oct 2020 10:55:40 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Dan Field <dnf...@google.com>
                          Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Oct 2, 2020, 3:10:47 PM10/2/20
                          to Stephen Adams, Leaf Petersen, dart-dc-te...@google.com, rev...@dartlang.org, commi...@chromium.org, Kevin Moore, Keerti Parthasarathy, Ryan Macnak, Dan Field, Todd Volkert, Nate Bosch, Zach Anderson

                          Lasse R.H. Nielsen uploaded patch set #24 to this change.

                          View Change

                          Add `Object.hash` and `Object.hashAll` static helper methods.

                          Fixes #11617.

                          Bug: http://dartbug.com/11617
                          Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          ---
                          M CHANGELOG.md
                          M pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
                          M sdk/lib/core/object.dart
                          M sdk/lib/internal/internal.dart
                          D sdk/lib/math/jenkins_smi_hash.dart
                          M sdk/lib/math/math.dart
                          M sdk/lib/math/math_sources.gni
                          M sdk/lib/math/point.dart
                          M sdk/lib/math/rectangle.dart
                          A tests/corelib/object_hash_test.dart
                          A tests/corelib_2/object_hash_test.dart
                          M tests/lib/mirrors/class_declarations_test.dart
                          M tests/lib_2/mirrors/class_declarations_test.dart
                          13 files changed, 850 insertions(+), 283 deletions(-)

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 24
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Dan Field <dnf...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-MessageType: newpatchset

                          Dan Field (Gerrit)

                          unread,
                          Oct 2, 2020, 4:52:47 PM10/2/20
                          to dart-dc-te...@google.com, rev...@dartlang.org, Alexander Markov, Lasse R.H. Nielsen, Stephen Adams, Leaf Petersen

                          Lasse R.H. Nielsen has uploaded this change for review.

                          View Change

                          Add `Object.hash` and `Object.hashAll` static helper methods.

                          Fixes #11617.

                          Bug: http://dartbug.com/11617
                          Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          ---
                          M CHANGELOG.md
                          M pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
                          M sdk/lib/core/object.dart
                          M sdk/lib/internal/internal.dart
                          D sdk/lib/math/jenkins_smi_hash.dart
                          M sdk/lib/math/math.dart
                          M sdk/lib/math/math_sources.gni
                          M sdk/lib/math/point.dart
                          M sdk/lib/math/rectangle.dart
                          A tests/corelib/object_hash_test.dart
                          A tests/corelib_2/object_hash_test.dart
                          M tests/lib/mirrors/class_declarations_test.dart
                          M tests/lib_2/mirrors/class_declarations_test.dart
                          13 files changed, 850 insertions(+), 283 deletions(-)

                          diff --git a/CHANGELOG.md b/CHANGELOG.md
                          index 7ecc7c3..835b6b5 100644
                          --- a/CHANGELOG.md
                          +++ b/CHANGELOG.md
                          @@ -2,6 +2,12 @@

                          ### Core libraries

                          +#### `dart:core`
                          +
                          +* Adds static methods `hash`, `hashAll` and `hashAllUnordered` to the
                          + `Object` class. These can be used to combine the hash codes of
                          + multiple objects in a consistent way.
                          +
                          ### Dart VM

                          ### Dart2JS
                          diff --git a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
                          index b77ed3f..6995196 100644
                          --- a/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
                          +++ b/pkg/dev_compiler/tool/dartdevc_nnbd_sdk_error_golden.txt
                          @@ -1,11 +1,11 @@
                          ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|3725|5|94|Const constructors can't throw exceptions.
                          -ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|7913|5|97|Const constructors can't throw exceptions.
                          +ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|8117|5|97|Const constructors can't throw exceptions.
                          ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|939|5|95|Const constructors can't throw exceptions.
                          ERROR|COMPILE_TIME_ERROR|CONST_CONSTRUCTOR_THROWS_EXCEPTION|lib/core/core.dart|972|5|94|Const constructors can't throw exceptions.
                          ERROR|COMPILE_TIME_ERROR|INVALID_ASSIGNMENT|lib/_internal/js_dev_runtime/private/interceptors.dart|1348|18|27|A value of type 'double' can't be assigned to a variable of type 'int'.
                          ERROR|COMPILE_TIME_ERROR|RETURN_OF_INVALID_TYPE|lib/_internal/js_dev_runtime/private/interceptors.dart|1215|14|38|A value of type 'double' can't be returned from method '%' because it has a return type of 'JSNumber'.
                          ERROR|COMPILE_TIME_ERROR|RETURN_OF_INVALID_TYPE|lib/_internal/js_dev_runtime/private/interceptors.dart|1217|14|38|A value of type 'double' can't be returned from method '%' because it has a return type of 'JSNumber'.
                          ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|3723|3|5|Only redirecting factory constructors can be declared to be 'const'.
                          -ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|7911|3|5|Only redirecting factory constructors can be declared to be 'const'.
                          +ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|8115|3|5|Only redirecting factory constructors can be declared to be 'const'.
                          ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|937|3|5|Only redirecting factory constructors can be declared to be 'const'.
                          ERROR|SYNTACTIC_ERROR|CONST_FACTORY|lib/core/core.dart|970|3|5|Only redirecting factory constructors can be declared to be 'const'.
                          diff --git a/sdk/lib/core/object.dart b/sdk/lib/core/object.dart
                          index 0f7d97b..bc2ce25 100644
                          --- a/sdk/lib/core/object.dart
                          +++ b/sdk/lib/core/object.dart
                          @@ -112,4 +112,208 @@
                          * A representation of the runtime type of the object.
                          */
                          external Type get runtimeType;
                          +
                          + /**
                          + * Creates a combined hash code for a number of objects.
                          + *
                          + * The hash code is computed for all arguments that are actually
                          + * supplied, even if they are `null`, by numerically combining the
                          + * [Object.hashCode] of each argument.
                          + *
                          + * Example:
                          + * ```dart
                          + * class SomeObject {
                          + * final Object a, b, c;
                          + * SomeObject(this.a, this.b, this.c);
                          + * bool operator=(Object other) =>
                          + * other is SomeObject && a == other.a && b == other.b && c == other.c;
                          + * int get hashCode => Object.hash(a, b, c);
                          + * }
                          + * ```
                          + *
                          + * The computed value must be consistent when the function is called
                          + * with the same arguments multiple times
                          + * during the execution of a single program.
                          + *
                          + * The hash value generated by this function is *not* guranteed to be stable
                          + * over different runs of the same program.
                          + * The exact algorithm used may differ between different platforms,
                          + * or between different versions of the platform libraries,
                          + * and it may depend on values that change per program run
                          + *
                          + * The [hashAll] function gives the same result as this function when
                          + * called with a collection containing the actual arguments to this function.
                          + */
                          + @Since("2.11")
                          + static int hash(Object? object1, Object? object2,
                          + [Object? object3 = sentinelValue,
                          + Object? object4 = sentinelValue,
                          + Object? object5 = sentinelValue,
                          + Object? object6 = sentinelValue,
                          + Object? object7 = sentinelValue,
                          + Object? object8 = sentinelValue,
                          + Object? object9 = sentinelValue,
                          + Object? object10 = sentinelValue]) {
                          + if (sentinelValue == object3) {
                          + return SystemHash.hash2(object1.hashCode, object2.hashCode);
                          + }
                          + if (sentinelValue == object4) {
                          + return SystemHash.hash3(
                          + object1.hashCode, object2.hashCode, object3.hashCode);
                          + }
                          + if (sentinelValue == object5) {
                          + return SystemHash.hash4(object1.hashCode, object2.hashCode,
                          + object3.hashCode, object4.hashCode);
                          + }
                          + if (sentinelValue == object6) {
                          + return SystemHash.hash5(object1.hashCode, object2.hashCode,
                          + object3.hashCode, object4.hashCode, object5.hashCode);
                          + }
                          + if (sentinelValue == object7) {
                          + return SystemHash.hash6(
                          + object1.hashCode,
                          + object2.hashCode,
                          + object3.hashCode,
                          + object4.hashCode,
                          + object5.hashCode,
                          + object6.hashCode);
                          + }
                          + if (sentinelValue == object8) {
                          + return SystemHash.hash7(
                          + object1.hashCode,
                          + object2.hashCode,
                          + object3.hashCode,
                          + object4.hashCode,
                          + object5.hashCode,
                          + object6.hashCode,
                          + object7.hashCode);
                          + }
                          + if (sentinelValue == object9) {
                          + return SystemHash.hash8(
                          + object1.hashCode,
                          + object2.hashCode,
                          + object3.hashCode,
                          + object4.hashCode,
                          + object5.hashCode,
                          + object6.hashCode,
                          + object7.hashCode,
                          + object8.hashCode);
                          + }
                          + if (sentinelValue == object10) {
                          + return SystemHash.hash9(
                          + object1.hashCode,
                          + object2.hashCode,
                          + object3.hashCode,
                          + object4.hashCode,
                          + object5.hashCode,
                          + object6.hashCode,
                          + object7.hashCode,
                          + object8.hashCode,
                          + object9.hashCode);
                          + }
                          + return SystemHash.hash10(
                          + object1.hashCode,
                          + object2.hashCode,
                          + object3.hashCode,
                          + object4.hashCode,
                          + object5.hashCode,
                          + object6.hashCode,
                          + object7.hashCode,
                          + object8.hashCode,
                          + object9.hashCode,
                          + object10.hashCode);
                          + }
                          +
                          + /**
                          + * Creates a combined hash code for a sequence of objects.
                          + *
                          + * The hash code is computed for elements in [objects],
                          + * even if they are `null`,
                          + * by numerically combining the [Object.hashCode] of each element
                          + * in iteration order.
                          + *
                          + * The result of `hashAll([o])` is not `o.hashCode`.
                          + *
                          + * Example:
                          + * ```dart
                          + * class SomeObject {
                          + * final List<String> path;
                          + * SomeObject(this.path);
                          + * bool operator=(Object other) {
                          + * if (other is SomeObject) {
                          + * if (path.length != other.path.length) return false;
                          + * for (int i = 0; i < path.length; i++) {
                          + * if (path[i] != other.path[i]) return false;
                          + * }
                          + * return true;
                          + * }
                          + * return false;
                          + * }
                          + *
                          + * int get hashCode => Object.hashAll(path);
                          + * }
                          + * ```
                          + *
                          + * The computed value will be be consistent when the function is called
                          + * again with objects that have the same hash codes in the same order
                          + * during an execution of a single program.
                          + *
                          + * The hash value generated by this function is *not* guranteed to be stable
                          + * over different runs of the same program.
                          + * The exact algorithm used may differ between different platforms,
                          + * or between different versions of the platform libraries,
                          + * and it may depend on values that change per program run
                          + */
                          + @Since("2.11")
                          + static int hashAll(Iterable<Object?> objects) {
                          + int hash = 0;
                          + for (var object in objects) {
                          + hash = SystemHash.combine(hash, object.hashCode);
                          + }
                          + return SystemHash.finish(hash);
                          + }
                          +
                          + /**
                          + * Creates a combined hash code for a collection of objects.
                          + *
                          + * The hash code is computed for elements in [objects],
                          + * even if they are `null`,
                          + * by numerically combining the [Object.hashCode] of each element
                          + * in an order independet way.
                          + *
                          + * The result of `unorderedHashAll({o})` is not `o.hashCode`.
                          + *
                          + * Example:
                          + * ```dart
                          + * bool setEquals<T>(Set<T> set1, Set<T> set2) {
                          + * var hashCode1 = Object.unorderedHashAll(set1);
                          + * var hashCode2 = Object.unorderedHashAll(set2);
                          + * if (hashCode1 != hashCode2) return false;
                          + * // Compare elements ...
                          + * }
                          + * ```
                          + *
                          + * The computed value will be be consistent when the function is called
                          + * again with objects that have the same hash codes
                          + * during an execution of a single program,
                          + * even if the objects are not necessarily in the same order,
                          + *
                          + * The hash value generated by this function is *not* guranteed to be stable
                          + * over different runs of the same program.
                          + * The exact algorithm used may differ between different platforms,
                          + * or between different versions of the platform libraries,
                          + * and it may depend on values that change per program run
                          + */
                          + @Since("2.11")
                          + static int hashAllUnordered(Iterable<Object?> objects) {
                          + int sum = 0;
                          + int count = 0;
                          + const int mask = 0x3FFFFFFF;
                          + for (var object in objects) {
                          + int objectHash = SystemHash.smear(object.hashCode);
                          + sum = (sum + objectHash) & mask;
                          + count += 1;
                          + }
                          + return SystemHash.hash2(sum, count);
                          + }
                          }
                          diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
                          index f86652e..2a66bd6 100644
                          --- a/sdk/lib/internal/internal.dart
                          +++ b/sdk/lib/internal/internal.dart
                          @@ -119,6 +119,177 @@
                          return digit1 * 16 + digit2 - (digit2 & 256);
                          }

                          +/**
                          + * A default hash function used by the platform in various places.
                          + *
                          + * This is currently the [Jenkins hash function][1] but using masking to keep
                          + * values in SMI range.
                          + *
                          + * [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
                          + *
                          + * Use:
                          + * Hash each value with the hash of the previous value, then get the final
                          + * hash by calling finish.
                          + * ```
                          + * var hash = 0;
                          + * for (var value in values) {
                          + * hash = SystemHash.combine(hash, value.hashCode);
                          + * }
                          + * hash = SystemHash.finish(hash);
                          + * ```
                          + *
                          + * TODO(lrn): Consider specializing this code per platform,
                          + * so the VM can use its 64-bit integers directly.
                          + */
                          +@Since("2.11")
                          +class SystemHash {
                          + static int combine(int hash, int value) {
                          + hash = 0x1fffffff & (hash + value);
                          + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
                          + return hash ^ (hash >> 6);
                          + }
                          +
                          + static int finish(int hash) {
                          + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
                          + hash = hash ^ (hash >> 11);
                          + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
                          + }
                          +
                          + static int hash2(int v1, int v2) {
                          + int hash = 0;
                          + hash = combine(hash, v1);
                          + hash = combine(hash, v2);
                          + return finish(hash);
                          + }
                          +
                          + static int hash3(int v1, int v2, int v3) {
                          + int hash = 0;
                          + hash = combine(hash, v1);
                          + hash = combine(hash, v2);
                          + hash = combine(hash, v3);
                          + return finish(hash);
                          + }
                          +
                          + static int hash4(int v1, int v2, int v3, int v4) {
                          + int hash = 0;
                          + hash = combine(hash, v1);
                          + hash = combine(hash, v2);
                          + hash = combine(hash, v3);
                          + hash = combine(hash, v4);
                          + return finish(hash);
                          + }
                          +
                          + static int hash5(int v1, int v2, int v3, int v4, int v5) {
                          + int hash = 0;
                          + hash = combine(hash, v1);
                          + hash = combine(hash, v2);
                          + hash = combine(hash, v3);
                          + hash = combine(hash, v4);
                          + hash = combine(hash, v5);
                          + return finish(hash);
                          + }
                          +
                          + static int hash6(int v1, int v2, int v3, int v4, int v5, int v6) {
                          + int hash = 0;
                          + hash = combine(hash, v1);
                          + hash = combine(hash, v2);
                          + hash = combine(hash, v3);
                          + hash = combine(hash, v4);
                          + hash = combine(hash, v5);
                          + hash = combine(hash, v6);
                          + return finish(hash);
                          + }
                          +
                          + static int hash7(int v1, int v2, int v3, int v4, int v5, int v6, int v7) {
                          + int hash = 0;
                          + hash = combine(hash, v1);
                          + hash = combine(hash, v2);
                          + hash = combine(hash, v3);
                          + hash = combine(hash, v4);
                          + hash = combine(hash, v5);
                          + hash = combine(hash, v6);
                          + hash = combine(hash, v7);
                          + return finish(hash);
                          + }
                          +
                          + static int hash8(
                          + int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) {
                          + int hash = 0;
                          + hash = combine(hash, v1);
                          + hash = combine(hash, v2);
                          + hash = combine(hash, v3);
                          + hash = combine(hash, v4);
                          + hash = combine(hash, v5);
                          + hash = combine(hash, v6);
                          + hash = combine(hash, v7);
                          + hash = combine(hash, v8);
                          + return finish(hash);
                          + }
                          +
                          + static int hash9(
                          + int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9) {
                          + int hash = 0;
                          + hash = combine(hash, v1);
                          + hash = combine(hash, v2);
                          + hash = combine(hash, v3);
                          + hash = combine(hash, v4);
                          + hash = combine(hash, v5);
                          + hash = combine(hash, v6);
                          + hash = combine(hash, v7);
                          + hash = combine(hash, v8);
                          + hash = combine(hash, v9);
                          + return finish(hash);
                          + }
                          +
                          + static int hash10(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
                          + int v8, int v9, int v10) {
                          + int hash = 0;
                          + hash = combine(hash, v1);
                          + hash = combine(hash, v2);
                          + hash = combine(hash, v3);
                          + hash = combine(hash, v4);
                          + hash = combine(hash, v5);
                          + hash = combine(hash, v6);
                          + hash = combine(hash, v7);
                          + hash = combine(hash, v8);
                          + hash = combine(hash, v9);
                          + hash = combine(hash, v10);
                          + return finish(hash);
                          + }
                          +
                          + /// Bit shuffling operation to improve hash codes.
                          + ///
                          + /// Dart integers have very simple hash codes (their value),
                          + /// which is acceptable for the hash above because it smears the bits
                          + /// as part of the combination.
                          + /// However, for the unordered hash based on xor, we need to improve
                          + /// the hash code of, e.g., integers, so a set containing the integers
                          + /// from zero to 2^n won't always have a zero hashcode.
                          + ///
                          + /// Assumes the input hash code is an unsigned 32-bit integer.
                          + /// Found by Christopher Wellons [https://github.com/skeeto/hash-prospector].
                          + static int smear(int x) {
                          + // TODO: Use >>> instead of >> when available.
                          + x ^= x >> 16;
                          + x = (x * 0x7feb352d) & 0xFFFFFFFF;
                          + x ^= x >> 15;
                          + x = (x * 0x846ca68b) & 0xFFFFFFFF;
                          + x ^= x >> 16;
                          + return x;
                          + }
                          +}
                          +
                          +/// Sentinel values that should never be exposed outside of platform libraries.
                          +@Since("2.11")
                          +class SentinelValue {
                          + final int id;
                          + const SentinelValue(this.id);
                          +}
                          +
                          +/// A default value to use when only one sentinel is needed.
                          +@Since("2.11")
                          +const Object sentinelValue = const SentinelValue(0);
                          +
                          /// Given an [instance] of some generic type [T], and [extract], a first-class
                          /// generic function that takes the same number of type parameters as [T],
                          /// invokes the function with the same type arguments that were passed to T
                          diff --git a/sdk/lib/math/jenkins_smi_hash.dart b/sdk/lib/math/jenkins_smi_hash.dart
                          deleted file mode 100644
                          index deca56c..0000000
                          --- a/sdk/lib/math/jenkins_smi_hash.dart
                          +++ /dev/null
                          @@ -1,40 +0,0 @@
                          -// Copyright (c) 2013, 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.
                          -
                          -part of dart.math;
                          -
                          -/// This is the [Jenkins hash function][1] but using masking to keep
                          -/// values in SMI range.
                          -///
                          -/// [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
                          -///
                          -/// Use:
                          -/// Hash each value with the hash of the previous value, then get the final
                          -/// hash by calling finish.
                          -///
                          -/// var hash = 0;
                          -/// for (var value in values) {
                          -/// hash = JenkinsSmiHash.combine(hash, value.hashCode);
                          -/// }
                          -/// hash = JenkinsSmiHash.finish(hash);
                          -class _JenkinsSmiHash {
                          - // TODO(11617): This class should be optimized and standardized elsewhere.
                          -
                          - static int combine(int hash, int value) {
                          - hash = 0x1fffffff & (hash + value);
                          - hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
                          - return hash ^ (hash >> 6);
                          - }
                          -
                          - static int finish(int hash) {
                          - hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
                          - hash = hash ^ (hash >> 11);
                          - return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
                          - }
                          -
                          - static int hash2(int a, int b) => finish(combine(combine(0, a), b));
                          -
                          - static int hash4(int a, int b, int c, int d) =>
                          - finish(combine(combine(combine(combine(0, a), b), c), d));
                          -}
                          diff --git a/sdk/lib/math/math.dart b/sdk/lib/math/math.dart
                          index b335669..8f847b1 100644
                          --- a/sdk/lib/math/math.dart
                          +++ b/sdk/lib/math/math.dart
                          @@ -11,7 +11,8 @@
                          /// {@category Core}
                          library dart.math;

                          -part "jenkins_smi_hash.dart";
                          +import "dart:_internal" show SystemHash;
                          +
                          part "point.dart";
                          part "random.dart";
                          part "rectangle.dart";
                          diff --git a/sdk/lib/math/math_sources.gni b/sdk/lib/math/math_sources.gni
                          index ff8f3fa..c06aead 100644
                          --- a/sdk/lib/math/math_sources.gni
                          +++ b/sdk/lib/math/math_sources.gni
                          @@ -6,7 +6,6 @@
                          "math.dart",

                          # The above file needs to be first as it lists the parts below.
                          - "jenkins_smi_hash.dart",
                          "point.dart",
                          "random.dart",
                          "rectangle.dart",
                          diff --git a/sdk/lib/math/point.dart b/sdk/lib/math/point.dart
                          index 4b0fed5..f092fc8 100644
                          --- a/sdk/lib/math/point.dart
                          +++ b/sdk/lib/math/point.dart
                          @@ -23,7 +23,7 @@
                          bool operator ==(Object other) =>
                          other is Point && x == other.x && y == other.y;

                          - int get hashCode => _JenkinsSmiHash.hash2(x.hashCode, y.hashCode);
                          + int get hashCode => SystemHash.hash2(x.hashCode, y.hashCode);

                          /// Add [other] to `this`, as if both points were vectors.
                          ///
                          diff --git a/sdk/lib/math/rectangle.dart b/sdk/lib/math/rectangle.dart
                          index 2ee86c9..e80d790 100644
                          --- a/sdk/lib/math/rectangle.dart
                          +++ b/sdk/lib/math/rectangle.dart
                          @@ -48,7 +48,7 @@
                          right == other.right &&
                          bottom == other.bottom;

                          - int get hashCode => _JenkinsSmiHash.hash4(
                          + int get hashCode => SystemHash.hash4(
                          left.hashCode, top.hashCode, right.hashCode, bottom.hashCode);

                          /// Computes the intersection of `this` and [other].
                          diff --git a/tests/corelib/object_hash_test.dart b/tests/corelib/object_hash_test.dart
                          new file mode 100644
                          index 0000000..704d1f3
                          --- /dev/null
                          +++ b/tests/corelib/object_hash_test.dart
                          @@ -0,0 +1,119 @@
                          +// Copyright (c) 2018, 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 "dart:typed_data";
                          +
                          +import "package:expect/expect.dart";
                          +
                          +main() {
                          + const nan = double.nan;
                          + const inf = double.infinity;
                          +
                          + int hash1234 = Object.hash(1, 2, 3, 4);
                          + Expect.type<int>(hash1234);
                          + Expect.equals(hash1234, Object.hash(1, 2, 3, 4)); // Consistent.
                          + Expect.equals(hash1234, Object.hashAll([1, 2, 3, 4]));
                          + Expect.equals(hash1234, Object.hashAll(Uint8List.fromList([1, 2, 3, 4])));
                          +
                          + Expect.notEquals(hash1234, Object.hash(1, 2, 3, 4, null));
                          +
                          + Expect.equals(Object.hash(1, 2, 3, 4, 5, 6, 7, 8, 9),
                          + Object.hashAll([1, 2, 3, 4, 5, 6, 7, 8, 9]));
                          +
                          + // Works for all kinds of objects;
                          + int varHash = Object.hash(
                          + "string", 3, nan, true, null, Type, #Symbol, const Object(), function);
                          + Expect.equals(
                          + varHash,
                          + Object.hashAll([
                          + "string",
                          + 3,
                          + nan,
                          + true,
                          + null,
                          + Type,
                          + #Symbol,
                          + const Object(),
                          + function
                          + ]));
                          +
                          + // Object doesn't matter, just its hash code.
                          + Expect.equals(hash1234,
                          + Object.hash(Hashable(1), Hashable(2), Hashable(3), Hashable(4)));
                          +
                          + // It's potentially possible to get a conflict, but it doesn't happen here.
                          + Expect.notEquals("str".hashCode, Object.hashAll(["str"]));
                          +
                          + var hash12345 = Object.hashAllUnordered([1, 2, 3, 4, 5]);
                          + for (var p in permutations([1, 2, 3, 4, 5])) {
                          + Expect.equals(hash12345, Object.hashAllUnordered(p));
                          + }
                          + Expect.notEquals(
                          + Object.hashAllUnordered(["a", "a"]), Object.hashAllUnordered(["a"]));
                          +
                          + Expect.notEquals(Object.hashAllUnordered(["a", "a"]),
                          + Object.hashAllUnordered(["a", "a", "a", "a"]));
                          +
                          + Expect.notEquals(Object.hashAllUnordered(["a", "b"]),
                          + Object.hashAllUnordered(["a", "a", "a", "b"]));
                          +
                          + /// Unordered hashing works for all kinds of objects.
                          + var unorderHash = Object.hashAllUnordered([
                          + "string",
                          + 3,
                          + nan,
                          + true,
                          + null,
                          + Type,
                          + #Symbol,
                          + const Object(),
                          + function,
                          + ]);
                          +
                          + var unorderHash2 = Object.hashAllUnordered([
                          + true,
                          + const Object(),
                          + 3,
                          + function,
                          + Type,
                          + "string",
                          + null,
                          + nan,
                          + #Symbol,
                          + ]);
                          + Expect.equals(unorderHash, unorderHash2);
                          +}
                          +
                          +/// Lazily emits all permutations of [values].
                          +///
                          +/// Modifes [values] rather than create a new list.
                          +/// The [values] list is guaranteed to end up in its original state
                          +/// after all permutations have been read.
                          +Iterable<List<T>> permutations<T>(List<T> values) {
                          + Iterable<List<T>> recPermute(int end) sync* {
                          + if (end == 1) {
                          + yield values;
                          + return;
                          + }
                          + for (var i = 0; i < end; i++) {
                          + yield* recPermute(end - 1);
                          + // Rotate values[i:].
                          + var tmp = values.first;
                          + for (var k = 1; k < end; k++) values[k - 1] = values[k];
                          + values[end - 1] = tmp;
                          + }
                          + }
                          +
                          + return recPermute(values.length);
                          +}
                          +
                          +// static function, used as constant value.
                          +void function() {}
                          +
                          +class Hashable {
                          + final Object o;
                          + Hashable(this.o);
                          + bool operator ==(Object other) => other is Hashable && o == other.o;
                          + int get hashCode => o.hashCode;
                          +}
                          diff --git a/tests/corelib_2/object_hash_test.dart b/tests/corelib_2/object_hash_test.dart
                          new file mode 100644
                          index 0000000..704d1f3
                          --- /dev/null
                          +++ b/tests/corelib_2/object_hash_test.dart
                          @@ -0,0 +1,119 @@
                          +// Copyright (c) 2018, 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 "dart:typed_data";
                          +
                          +import "package:expect/expect.dart";
                          +
                          +main() {
                          + const nan = double.nan;
                          + const inf = double.infinity;
                          +
                          + int hash1234 = Object.hash(1, 2, 3, 4);
                          + Expect.type<int>(hash1234);
                          + Expect.equals(hash1234, Object.hash(1, 2, 3, 4)); // Consistent.
                          + Expect.equals(hash1234, Object.hashAll([1, 2, 3, 4]));
                          + Expect.equals(hash1234, Object.hashAll(Uint8List.fromList([1, 2, 3, 4])));
                          +
                          + Expect.notEquals(hash1234, Object.hash(1, 2, 3, 4, null));
                          +
                          + Expect.equals(Object.hash(1, 2, 3, 4, 5, 6, 7, 8, 9),
                          + Object.hashAll([1, 2, 3, 4, 5, 6, 7, 8, 9]));
                          +
                          + // Works for all kinds of objects;
                          + int varHash = Object.hash(
                          + "string", 3, nan, true, null, Type, #Symbol, const Object(), function);
                          + Expect.equals(
                          + varHash,
                          + Object.hashAll([
                          + "string",
                          + 3,
                          + nan,
                          + true,
                          + null,
                          + Type,
                          + #Symbol,
                          + const Object(),
                          + function
                          + ]));
                          +
                          + // Object doesn't matter, just its hash code.
                          + Expect.equals(hash1234,
                          + Object.hash(Hashable(1), Hashable(2), Hashable(3), Hashable(4)));
                          +
                          + // It's potentially possible to get a conflict, but it doesn't happen here.
                          + Expect.notEquals("str".hashCode, Object.hashAll(["str"]));
                          +
                          + var hash12345 = Object.hashAllUnordered([1, 2, 3, 4, 5]);
                          + for (var p in permutations([1, 2, 3, 4, 5])) {
                          + Expect.equals(hash12345, Object.hashAllUnordered(p));
                          + }
                          + Expect.notEquals(
                          + Object.hashAllUnordered(["a", "a"]), Object.hashAllUnordered(["a"]));
                          +
                          + Expect.notEquals(Object.hashAllUnordered(["a", "a"]),
                          + Object.hashAllUnordered(["a", "a", "a", "a"]));
                          +
                          + Expect.notEquals(Object.hashAllUnordered(["a", "b"]),
                          + Object.hashAllUnordered(["a", "a", "a", "b"]));
                          +
                          + /// Unordered hashing works for all kinds of objects.
                          + var unorderHash = Object.hashAllUnordered([
                          + "string",
                          + 3,
                          + nan,
                          + true,
                          + null,
                          + Type,
                          + #Symbol,
                          + const Object(),
                          + function,
                          + ]);
                          +
                          + var unorderHash2 = Object.hashAllUnordered([
                          + true,
                          + const Object(),
                          + 3,
                          + function,
                          + Type,
                          + "string",
                          + null,
                          + nan,
                          + #Symbol,
                          + ]);
                          + Expect.equals(unorderHash, unorderHash2);
                          +}
                          +
                          +/// Lazily emits all permutations of [values].
                          +///
                          +/// Modifes [values] rather than create a new list.
                          +/// The [values] list is guaranteed to end up in its original state
                          +/// after all permutations have been read.
                          +Iterable<List<T>> permutations<T>(List<T> values) {
                          + Iterable<List<T>> recPermute(int end) sync* {
                          + if (end == 1) {
                          + yield values;
                          + return;
                          + }
                          + for (var i = 0; i < end; i++) {
                          + yield* recPermute(end - 1);
                          + // Rotate values[i:].
                          + var tmp = values.first;
                          + for (var k = 1; k < end; k++) values[k - 1] = values[k];
                          + values[end - 1] = tmp;
                          + }
                          + }
                          +
                          + return recPermute(values.length);
                          +}
                          +
                          +// static function, used as constant value.
                          +void function() {}
                          +
                          +class Hashable {
                          + final Object o;
                          + Hashable(this.o);
                          + bool operator ==(Object other) => other is Hashable && o == other.o;
                          + int get hashCode => o.hashCode;
                          +}
                          diff --git a/tests/lib/mirrors/class_declarations_test.dart b/tests/lib/mirrors/class_declarations_test.dart
                          index 83f8964..2cbf8de 100644
                          --- a/tests/lib/mirrors/class_declarations_test.dart
                          +++ b/tests/lib/mirrors/class_declarations_test.dart
                          @@ -10,11 +10,18 @@
                          import 'stringify.dart';
                          import 'declarations_model.dart' as declarations_model;

                          -Set<DeclarationMirror> inheritedDeclarations(ClassMirror? cm) {
                          +/// Collects all declarations of [cm] and its super-classes except `Object`.
                          +///
                          +/// Includes static declarations of super-classes.
                          +///
                          +/// The `Object` class is omitted because this test should be stable against
                          +/// changes to the platform libraries, as long as the declaration model code
                          +/// doesn't change.
                          +Set<DeclarationMirror> transitiveDeclarations(ClassMirror cm) {
                          var decls = new Set<DeclarationMirror>();
                          - while (cm != null) {
                          + while (cm != reflectClass(Object)) {
                          decls.addAll(cm.declarations.values);
                          - cm = cm.superclass;
                          + cm = cm.superclass!;
                          }
                          return decls;
                          }
                          @@ -163,14 +170,12 @@
                          'Method(s(*) in s(Mixin))',
                          'Method(s(+) in s(Class))',
                          'Method(s(-) in s(Superclass))',
                          - 'Method(s(==) in s(Object))',
                          'TypeVariable(s(C) in s(Class),'
                          ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          'Method(s(Class.generativeConstructor) in s(Class), constructor)',
                          'Method(s(Class.normalFactory) in s(Class), static, constructor)',
                          'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
                          'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
                          - 'Method(s(Object) in s(Object), constructor)',
                          'TypeVariable(s(S) in s(Superclass),'
                          ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          'Method(s(Superclass.inheritedGenerativeConstructor)'
                          @@ -182,7 +187,6 @@
                          'Method(s(Superclass.inheritedRedirectingFactory)'
                          ' in s(Superclass), static, constructor)',
                          'Method(s(abstractMethod) in s(Class), abstract)',
                          - 'Method(s(hashCode) in s(Object), getter)',
                          'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
                          'Method(s(inheritedInstanceMethod) in s(Superclass))',
                          'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
                          @@ -199,8 +203,6 @@
                          'Method(s(mixinInstanceMethod) in s(Mixin))',
                          'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
                          'Variable(s(mixinInstanceVariable) in s(Mixin))',
                          - 'Method(s(noSuchMethod) in s(Object))',
                          - 'Method(s(runtimeType) in s(Object), getter)',
                          'Method(s(staticGetter) in s(Class), static, getter)',
                          'Method(s(staticMethod) in s(Class), static)',
                          'Method(s(staticSetter=) in s(Class), static, setter)',
                          @@ -213,12 +215,11 @@
                          ' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
                          ' in s(test.declarations_model.Superclass'
                          ' with test.declarations_model.Mixin), constructor)',
                          - 'Method(s(toString) in s(Object))',
                          'Variable(s(mixinStaticVariable) in s(Mixin), static)',
                          'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
                          'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
                          'Method(s(mixinStaticMethod) in s(Mixin), static)'
                          - ], inheritedDeclarations(cm).where((dm) => !dm.isPrivate).map(stringify),
                          + ], transitiveDeclarations(cm).where((dm) => !dm.isPrivate).map(stringify),
                          'transitive public');
                          // The public members of Object should be the same in all implementations, so
                          // we don't exclude Object here.
                          @@ -256,113 +257,106 @@
                          'Variable(s(staticVariable) in s(Class), static)'
                          ], cm.declarations.values.map(stringify), 'declarations');

                          - Expect.setEquals(
                          - [
                          - 'Method(s(*) in s(Mixin))',
                          - 'Method(s(+) in s(Class))',
                          - 'Method(s(-) in s(Superclass))',
                          - 'TypeVariable(s(C) in s(Class),'
                          - ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          - 'Method(s(Class._generativeConstructor) in s(Class), private, constructor)',
                          - 'Method(s(Class._normalFactory) in s(Class), private, static, constructor)',
                          - 'Method(s(Class._redirectingConstructor)'
                          - ' in s(Class), private, constructor)',
                          - 'Method(s(Class._redirectingFactory)'
                          - ' in s(Class), private, static, constructor)',
                          - 'Method(s(Class.generativeConstructor) in s(Class), constructor)',
                          - 'Method(s(Class.normalFactory) in s(Class), static, constructor)',
                          - 'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
                          - 'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
                          - 'TypeVariable(s(S) in s(Superclass),'
                          - ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          - 'Method(s(Superclass._inheritedGenerativeConstructor)'
                          - ' in s(Superclass), private, constructor)',
                          - 'Method(s(Superclass._inheritedNormalFactory)'
                          - ' in s(Superclass), private, static, constructor)',
                          - 'Method(s(Superclass._inheritedRedirectingConstructor)'
                          - ' in s(Superclass), private, constructor)',
                          - 'Method(s(Superclass._inheritedRedirectingFactory)'
                          - ' in s(Superclass), private, static, constructor)',
                          - 'Method(s(Superclass.inheritedGenerativeConstructor)'
                          - ' in s(Superclass), constructor)',
                          - 'Method(s(Superclass.inheritedNormalFactory)'
                          - ' in s(Superclass), static, constructor)',
                          - 'Method(s(Superclass.inheritedRedirectingConstructor)'
                          - ' in s(Superclass), constructor)',
                          - 'Method(s(Superclass.inheritedRedirectingFactory)'
                          - ' in s(Superclass), static, constructor)',
                          - 'Method(s(_inheritedInstanceGetter) in s(Superclass), private, getter)',
                          - 'Method(s(_inheritedInstanceMethod) in s(Superclass), private)',
                          - 'Method(s(_inheritedInstanceSetter=) in s(Superclass), private, setter)',
                          - 'Variable(s(_inheritedInstanceVariable) in s(Superclass), private)',
                          - 'Method(s(_inheritedStaticGetter)'
                          - ' in s(Superclass), private, static, getter)',
                          - 'Method(s(_inheritedStaticMethod) in s(Superclass), private, static)',
                          - 'Method(s(_inheritedStaticSetter=)'
                          - ' in s(Superclass), private, static, setter)',
                          - 'Variable(s(_inheritedStaticVariable) in s(Superclass), private, static)',
                          - 'Method(s(_instanceGetter) in s(Class), private, getter)',
                          - 'Method(s(_instanceMethod) in s(Class), private)',
                          - 'Method(s(_instanceSetter=) in s(Class), private, setter)',
                          - 'Variable(s(_instanceVariable) in s(Class), private)',
                          - 'Method(s(_mixinInstanceGetter) in s(Mixin), private, getter)',
                          - 'Method(s(_mixinInstanceMethod) in s(Mixin), private)',
                          - 'Method(s(_mixinInstanceSetter=) in s(Mixin), private, setter)',
                          - 'Variable(s(_mixinInstanceVariable) in s(Mixin), private)',
                          - 'Method(s(_staticGetter) in s(Class), private, static, getter)',
                          - 'Method(s(_staticMethod) in s(Class), private, static)',
                          - 'Method(s(_staticSetter=) in s(Class), private, static, setter)',
                          - 'Variable(s(_staticVariable) in s(Class), private, static)',
                          - 'Method(s(abstractMethod) in s(Class), abstract)',
                          - 'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
                          - 'Method(s(inheritedInstanceMethod) in s(Superclass))',
                          - 'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
                          - 'Variable(s(inheritedInstanceVariable) in s(Superclass))',
                          - 'Method(s(inheritedStaticGetter) in s(Superclass), static, getter)',
                          - 'Method(s(inheritedStaticMethod) in s(Superclass), static)',
                          - 'Method(s(inheritedStaticSetter=) in s(Superclass), static, setter)',
                          - 'Variable(s(inheritedStaticVariable) in s(Superclass), static)',
                          - 'Method(s(instanceGetter) in s(Class), getter)',
                          - 'Method(s(instanceMethod) in s(Class))',
                          - 'Method(s(instanceSetter=) in s(Class), setter)',
                          - 'Variable(s(instanceVariable) in s(Class))',
                          - 'Method(s(mixinInstanceGetter) in s(Mixin), getter)',
                          - 'Method(s(mixinInstanceMethod) in s(Mixin))',
                          - 'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
                          - 'Variable(s(mixinInstanceVariable) in s(Mixin))',
                          - 'Method(s(staticGetter) in s(Class), static, getter)',
                          - 'Method(s(staticMethod) in s(Class), static)',
                          - 'Method(s(staticSetter=) in s(Class), static, setter)',
                          - 'Variable(s(staticVariable) in s(Class), static)',
                          - 'Method(s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin._inheritedGenerativeConstructor)'
                          - ' in s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin), private, constructor)',
                          - 'Method(s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin._inheritedRedirectingConstructor)'
                          - ' in s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin), private, constructor)',
                          - 'Method(s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin.inheritedGenerativeConstructor)'
                          - ' in s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin), constructor)',
                          - 'Method(s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
                          - ' in s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin), constructor)',
                          - 'Variable(s(mixinStaticVariable) in s(Mixin), static)',
                          - 'Variable(s(_mixinStaticVariable) in s(Mixin), private, static)',
                          - 'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
                          - 'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
                          - 'Method(s(mixinStaticMethod) in s(Mixin), static)',
                          - 'Method(s(_mixinStaticGetter) in s(Mixin), private, static, getter)',
                          - 'Method(s(_mixinStaticSetter=) in s(Mixin), private, static, setter)',
                          - 'Method(s(_mixinStaticMethod) in s(Mixin), private, static)'
                          - ],
                          - inheritedDeclarations(cm)
                          - .difference(reflectClass(Object).declarations.values.toSet())
                          - .map(stringify),
                          - 'transitive less Object');
                          - // The private members of Object may vary across implementations, so we
                          - // exclude the declarations of Object in this test case.
                          + Expect.setEquals([
                          + 'Method(s(*) in s(Mixin))',
                          + 'Method(s(+) in s(Class))',
                          + 'Method(s(-) in s(Superclass))',
                          + 'TypeVariable(s(C) in s(Class),'
                          + ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          + 'Method(s(Class._generativeConstructor) in s(Class), private, constructor)',
                          + 'Method(s(Class._normalFactory) in s(Class), private, static, constructor)',
                          + 'Method(s(Class._redirectingConstructor)'
                          + ' in s(Class), private, constructor)',
                          + 'Method(s(Class._redirectingFactory)'
                          + ' in s(Class), private, static, constructor)',
                          + 'Method(s(Class.generativeConstructor) in s(Class), constructor)',
                          + 'Method(s(Class.normalFactory) in s(Class), static, constructor)',
                          + 'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
                          + 'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
                          + 'TypeVariable(s(S) in s(Superclass),'
                          + ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          + 'Method(s(Superclass._inheritedGenerativeConstructor)'
                          + ' in s(Superclass), private, constructor)',
                          + 'Method(s(Superclass._inheritedNormalFactory)'
                          + ' in s(Superclass), private, static, constructor)',
                          + 'Method(s(Superclass._inheritedRedirectingConstructor)'
                          + ' in s(Superclass), private, constructor)',
                          + 'Method(s(Superclass._inheritedRedirectingFactory)'
                          + ' in s(Superclass), private, static, constructor)',
                          + 'Method(s(Superclass.inheritedGenerativeConstructor)'
                          + ' in s(Superclass), constructor)',
                          + 'Method(s(Superclass.inheritedNormalFactory)'
                          + ' in s(Superclass), static, constructor)',
                          + 'Method(s(Superclass.inheritedRedirectingConstructor)'
                          + ' in s(Superclass), constructor)',
                          + 'Method(s(Superclass.inheritedRedirectingFactory)'
                          + ' in s(Superclass), static, constructor)',
                          + 'Method(s(_inheritedInstanceGetter) in s(Superclass), private, getter)',
                          + 'Method(s(_inheritedInstanceMethod) in s(Superclass), private)',
                          + 'Method(s(_inheritedInstanceSetter=) in s(Superclass), private, setter)',
                          + 'Variable(s(_inheritedInstanceVariable) in s(Superclass), private)',
                          + 'Method(s(_inheritedStaticGetter)'
                          + ' in s(Superclass), private, static, getter)',
                          + 'Method(s(_inheritedStaticMethod) in s(Superclass), private, static)',
                          + 'Method(s(_inheritedStaticSetter=)'
                          + ' in s(Superclass), private, static, setter)',
                          + 'Variable(s(_inheritedStaticVariable) in s(Superclass), private, static)',
                          + 'Method(s(_instanceGetter) in s(Class), private, getter)',
                          + 'Method(s(_instanceMethod) in s(Class), private)',
                          + 'Method(s(_instanceSetter=) in s(Class), private, setter)',
                          + 'Variable(s(_instanceVariable) in s(Class), private)',
                          + 'Method(s(_mixinInstanceGetter) in s(Mixin), private, getter)',
                          + 'Method(s(_mixinInstanceMethod) in s(Mixin), private)',
                          + 'Method(s(_mixinInstanceSetter=) in s(Mixin), private, setter)',
                          + 'Variable(s(_mixinInstanceVariable) in s(Mixin), private)',
                          + 'Method(s(_staticGetter) in s(Class), private, static, getter)',
                          + 'Method(s(_staticMethod) in s(Class), private, static)',
                          + 'Method(s(_staticSetter=) in s(Class), private, static, setter)',
                          + 'Variable(s(_staticVariable) in s(Class), private, static)',
                          + 'Method(s(abstractMethod) in s(Class), abstract)',
                          + 'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
                          + 'Method(s(inheritedInstanceMethod) in s(Superclass))',
                          + 'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
                          + 'Variable(s(inheritedInstanceVariable) in s(Superclass))',
                          + 'Method(s(inheritedStaticGetter) in s(Superclass), static, getter)',
                          + 'Method(s(inheritedStaticMethod) in s(Superclass), static)',
                          + 'Method(s(inheritedStaticSetter=) in s(Superclass), static, setter)',
                          + 'Variable(s(inheritedStaticVariable) in s(Superclass), static)',
                          + 'Method(s(instanceGetter) in s(Class), getter)',
                          + 'Method(s(instanceMethod) in s(Class))',
                          + 'Method(s(instanceSetter=) in s(Class), setter)',
                          + 'Variable(s(instanceVariable) in s(Class))',
                          + 'Method(s(mixinInstanceGetter) in s(Mixin), getter)',
                          + 'Method(s(mixinInstanceMethod) in s(Mixin))',
                          + 'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
                          + 'Variable(s(mixinInstanceVariable) in s(Mixin))',
                          + 'Method(s(staticGetter) in s(Class), static, getter)',
                          + 'Method(s(staticMethod) in s(Class), static)',
                          + 'Method(s(staticSetter=) in s(Class), static, setter)',
                          + 'Variable(s(staticVariable) in s(Class), static)',
                          + 'Method(s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin._inheritedGenerativeConstructor)'
                          + ' in s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin), private, constructor)',
                          + 'Method(s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin._inheritedRedirectingConstructor)'
                          + ' in s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin), private, constructor)',
                          + 'Method(s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin.inheritedGenerativeConstructor)'
                          + ' in s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin), constructor)',
                          + 'Method(s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
                          + ' in s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin), constructor)',
                          + 'Variable(s(mixinStaticVariable) in s(Mixin), static)',
                          + 'Variable(s(_mixinStaticVariable) in s(Mixin), private, static)',
                          + 'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
                          + 'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
                          + 'Method(s(mixinStaticMethod) in s(Mixin), static)',
                          + 'Method(s(_mixinStaticGetter) in s(Mixin), private, static, getter)',
                          + 'Method(s(_mixinStaticSetter=) in s(Mixin), private, static, setter)',
                          + 'Method(s(_mixinStaticMethod) in s(Mixin), private, static)'
                          + ], transitiveDeclarations(cm).map(stringify), 'transitive all');
                          }
                          diff --git a/tests/lib_2/mirrors/class_declarations_test.dart b/tests/lib_2/mirrors/class_declarations_test.dart
                          index f0a121c..72619da 100644
                          --- a/tests/lib_2/mirrors/class_declarations_test.dart
                          +++ b/tests/lib_2/mirrors/class_declarations_test.dart
                          @@ -10,9 +10,16 @@
                          import 'stringify.dart';
                          import 'declarations_model.dart' as declarations_model;

                          -Set<DeclarationMirror> inheritedDeclarations(ClassMirror cm) {
                          +/// Collects all declarations of [cm] and its super-classes except `Object`.
                          +///
                          +/// Includes static declarations of super-classes.
                          +///
                          +/// The `Object` class is omitted because this test should be stable against
                          +/// changes to the platform libraries, as long as the declaration model code
                          +/// doesn't change.
                          +Set<DeclarationMirror> transitiveDeclarations(ClassMirror cm) {
                          var decls = new Set<DeclarationMirror>();
                          - while (cm != null) {
                          + while (cm != reflectClass(Object)) {
                          decls.addAll(cm.declarations.values);
                          cm = cm.superclass;
                          }
                          @@ -163,14 +170,12 @@
                          'Method(s(*) in s(Mixin))',
                          'Method(s(+) in s(Class))',
                          'Method(s(-) in s(Superclass))',
                          - 'Method(s(==) in s(Object))',
                          'TypeVariable(s(C) in s(Class),'
                          ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          'Method(s(Class.generativeConstructor) in s(Class), constructor)',
                          'Method(s(Class.normalFactory) in s(Class), static, constructor)',
                          'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
                          'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
                          - 'Method(s(Object) in s(Object), constructor)',
                          'TypeVariable(s(S) in s(Superclass),'
                          ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          'Method(s(Superclass.inheritedGenerativeConstructor)'
                          @@ -182,7 +187,6 @@
                          'Method(s(Superclass.inheritedRedirectingFactory)'
                          ' in s(Superclass), static, constructor)',
                          'Method(s(abstractMethod) in s(Class), abstract)',
                          - 'Method(s(hashCode) in s(Object), getter)',
                          'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
                          'Method(s(inheritedInstanceMethod) in s(Superclass))',
                          'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
                          @@ -199,8 +203,6 @@
                          'Method(s(mixinInstanceMethod) in s(Mixin))',
                          'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
                          'Variable(s(mixinInstanceVariable) in s(Mixin))',
                          - 'Method(s(noSuchMethod) in s(Object))',
                          - 'Method(s(runtimeType) in s(Object), getter)',
                          'Method(s(staticGetter) in s(Class), static, getter)',
                          'Method(s(staticMethod) in s(Class), static)',
                          'Method(s(staticSetter=) in s(Class), static, setter)',
                          @@ -213,12 +215,11 @@
                          ' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
                          ' in s(test.declarations_model.Superclass'
                          ' with test.declarations_model.Mixin), constructor)',
                          - 'Method(s(toString) in s(Object))',
                          'Variable(s(mixinStaticVariable) in s(Mixin), static)',
                          'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
                          'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
                          'Method(s(mixinStaticMethod) in s(Mixin), static)'
                          - ], inheritedDeclarations(cm).where((dm) => !dm.isPrivate).map(stringify),
                          + ], transitiveDeclarations(cm).where((dm) => !dm.isPrivate).map(stringify),
                          'transitive public');
                          // The public members of Object should be the same in all implementations, so
                          // we don't exclude Object here.
                          @@ -256,113 +257,106 @@
                          'Variable(s(staticVariable) in s(Class), static)'
                          ], cm.declarations.values.map(stringify), 'declarations');

                          - Expect.setEquals(
                          - [
                          - 'Method(s(*) in s(Mixin))',
                          - 'Method(s(+) in s(Class))',
                          - 'Method(s(-) in s(Superclass))',
                          - 'TypeVariable(s(C) in s(Class),'
                          - ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          - 'Method(s(Class._generativeConstructor) in s(Class), private, constructor)',
                          - 'Method(s(Class._normalFactory) in s(Class), private, static, constructor)',
                          - 'Method(s(Class._redirectingConstructor)'
                          - ' in s(Class), private, constructor)',
                          - 'Method(s(Class._redirectingFactory)'
                          - ' in s(Class), private, static, constructor)',
                          - 'Method(s(Class.generativeConstructor) in s(Class), constructor)',
                          - 'Method(s(Class.normalFactory) in s(Class), static, constructor)',
                          - 'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
                          - 'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
                          - 'TypeVariable(s(S) in s(Superclass),'
                          - ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          - 'Method(s(Superclass._inheritedGenerativeConstructor)'
                          - ' in s(Superclass), private, constructor)',
                          - 'Method(s(Superclass._inheritedNormalFactory)'
                          - ' in s(Superclass), private, static, constructor)',
                          - 'Method(s(Superclass._inheritedRedirectingConstructor)'
                          - ' in s(Superclass), private, constructor)',
                          - 'Method(s(Superclass._inheritedRedirectingFactory)'
                          - ' in s(Superclass), private, static, constructor)',
                          - 'Method(s(Superclass.inheritedGenerativeConstructor)'
                          - ' in s(Superclass), constructor)',
                          - 'Method(s(Superclass.inheritedNormalFactory)'
                          - ' in s(Superclass), static, constructor)',
                          - 'Method(s(Superclass.inheritedRedirectingConstructor)'
                          - ' in s(Superclass), constructor)',
                          - 'Method(s(Superclass.inheritedRedirectingFactory)'
                          - ' in s(Superclass), static, constructor)',
                          - 'Method(s(_inheritedInstanceGetter) in s(Superclass), private, getter)',
                          - 'Method(s(_inheritedInstanceMethod) in s(Superclass), private)',
                          - 'Method(s(_inheritedInstanceSetter=) in s(Superclass), private, setter)',
                          - 'Variable(s(_inheritedInstanceVariable) in s(Superclass), private)',
                          - 'Method(s(_inheritedStaticGetter)'
                          - ' in s(Superclass), private, static, getter)',
                          - 'Method(s(_inheritedStaticMethod) in s(Superclass), private, static)',
                          - 'Method(s(_inheritedStaticSetter=)'
                          - ' in s(Superclass), private, static, setter)',
                          - 'Variable(s(_inheritedStaticVariable) in s(Superclass), private, static)',
                          - 'Method(s(_instanceGetter) in s(Class), private, getter)',
                          - 'Method(s(_instanceMethod) in s(Class), private)',
                          - 'Method(s(_instanceSetter=) in s(Class), private, setter)',
                          - 'Variable(s(_instanceVariable) in s(Class), private)',
                          - 'Method(s(_mixinInstanceGetter) in s(Mixin), private, getter)',
                          - 'Method(s(_mixinInstanceMethod) in s(Mixin), private)',
                          - 'Method(s(_mixinInstanceSetter=) in s(Mixin), private, setter)',
                          - 'Variable(s(_mixinInstanceVariable) in s(Mixin), private)',
                          - 'Method(s(_staticGetter) in s(Class), private, static, getter)',
                          - 'Method(s(_staticMethod) in s(Class), private, static)',
                          - 'Method(s(_staticSetter=) in s(Class), private, static, setter)',
                          - 'Variable(s(_staticVariable) in s(Class), private, static)',
                          - 'Method(s(abstractMethod) in s(Class), abstract)',
                          - 'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
                          - 'Method(s(inheritedInstanceMethod) in s(Superclass))',
                          - 'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
                          - 'Variable(s(inheritedInstanceVariable) in s(Superclass))',
                          - 'Method(s(inheritedStaticGetter) in s(Superclass), static, getter)',
                          - 'Method(s(inheritedStaticMethod) in s(Superclass), static)',
                          - 'Method(s(inheritedStaticSetter=) in s(Superclass), static, setter)',
                          - 'Variable(s(inheritedStaticVariable) in s(Superclass), static)',
                          - 'Method(s(instanceGetter) in s(Class), getter)',
                          - 'Method(s(instanceMethod) in s(Class))',
                          - 'Method(s(instanceSetter=) in s(Class), setter)',
                          - 'Variable(s(instanceVariable) in s(Class))',
                          - 'Method(s(mixinInstanceGetter) in s(Mixin), getter)',
                          - 'Method(s(mixinInstanceMethod) in s(Mixin))',
                          - 'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
                          - 'Variable(s(mixinInstanceVariable) in s(Mixin))',
                          - 'Method(s(staticGetter) in s(Class), static, getter)',
                          - 'Method(s(staticMethod) in s(Class), static)',
                          - 'Method(s(staticSetter=) in s(Class), static, setter)',
                          - 'Variable(s(staticVariable) in s(Class), static)',
                          - 'Method(s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin._inheritedGenerativeConstructor)'
                          - ' in s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin), private, constructor)',
                          - 'Method(s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin._inheritedRedirectingConstructor)'
                          - ' in s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin), private, constructor)',
                          - 'Method(s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin.inheritedGenerativeConstructor)'
                          - ' in s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin), constructor)',
                          - 'Method(s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
                          - ' in s(test.declarations_model.Superclass'
                          - ' with test.declarations_model.Mixin), constructor)',
                          - 'Variable(s(mixinStaticVariable) in s(Mixin), static)',
                          - 'Variable(s(_mixinStaticVariable) in s(Mixin), private, static)',
                          - 'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
                          - 'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
                          - 'Method(s(mixinStaticMethod) in s(Mixin), static)',
                          - 'Method(s(_mixinStaticGetter) in s(Mixin), private, static, getter)',
                          - 'Method(s(_mixinStaticSetter=) in s(Mixin), private, static, setter)',
                          - 'Method(s(_mixinStaticMethod) in s(Mixin), private, static)'
                          - ],
                          - inheritedDeclarations(cm)
                          - .difference(reflectClass(Object).declarations.values.toSet())
                          - .map(stringify),
                          - 'transitive less Object');
                          - // The private members of Object may vary across implementations, so we
                          - // exclude the declarations of Object in this test case.
                          + Expect.setEquals([
                          + 'Method(s(*) in s(Mixin))',
                          + 'Method(s(+) in s(Class))',
                          + 'Method(s(-) in s(Superclass))',
                          + 'TypeVariable(s(C) in s(Class),'
                          + ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          + 'Method(s(Class._generativeConstructor) in s(Class), private, constructor)',
                          + 'Method(s(Class._normalFactory) in s(Class), private, static, constructor)',
                          + 'Method(s(Class._redirectingConstructor)'
                          + ' in s(Class), private, constructor)',
                          + 'Method(s(Class._redirectingFactory)'
                          + ' in s(Class), private, static, constructor)',
                          + 'Method(s(Class.generativeConstructor) in s(Class), constructor)',
                          + 'Method(s(Class.normalFactory) in s(Class), static, constructor)',
                          + 'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
                          + 'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
                          + 'TypeVariable(s(S) in s(Superclass),'
                          + ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          + 'Method(s(Superclass._inheritedGenerativeConstructor)'
                          + ' in s(Superclass), private, constructor)',
                          + 'Method(s(Superclass._inheritedNormalFactory)'
                          + ' in s(Superclass), private, static, constructor)',
                          + 'Method(s(Superclass._inheritedRedirectingConstructor)'
                          + ' in s(Superclass), private, constructor)',
                          + 'Method(s(Superclass._inheritedRedirectingFactory)'
                          + ' in s(Superclass), private, static, constructor)',
                          + 'Method(s(Superclass.inheritedGenerativeConstructor)'
                          + ' in s(Superclass), constructor)',
                          + 'Method(s(Superclass.inheritedNormalFactory)'
                          + ' in s(Superclass), static, constructor)',
                          + 'Method(s(Superclass.inheritedRedirectingConstructor)'
                          + ' in s(Superclass), constructor)',
                          + 'Method(s(Superclass.inheritedRedirectingFactory)'
                          + ' in s(Superclass), static, constructor)',
                          + 'Method(s(_inheritedInstanceGetter) in s(Superclass), private, getter)',
                          + 'Method(s(_inheritedInstanceMethod) in s(Superclass), private)',
                          + 'Method(s(_inheritedInstanceSetter=) in s(Superclass), private, setter)',
                          + 'Variable(s(_inheritedInstanceVariable) in s(Superclass), private)',
                          + 'Method(s(_inheritedStaticGetter)'
                          + ' in s(Superclass), private, static, getter)',
                          + 'Method(s(_inheritedStaticMethod) in s(Superclass), private, static)',
                          + 'Method(s(_inheritedStaticSetter=)'
                          + ' in s(Superclass), private, static, setter)',
                          + 'Variable(s(_inheritedStaticVariable) in s(Superclass), private, static)',
                          + 'Method(s(_instanceGetter) in s(Class), private, getter)',
                          + 'Method(s(_instanceMethod) in s(Class), private)',
                          + 'Method(s(_instanceSetter=) in s(Class), private, setter)',
                          + 'Variable(s(_instanceVariable) in s(Class), private)',
                          + 'Method(s(_mixinInstanceGetter) in s(Mixin), private, getter)',
                          + 'Method(s(_mixinInstanceMethod) in s(Mixin), private)',
                          + 'Method(s(_mixinInstanceSetter=) in s(Mixin), private, setter)',
                          + 'Variable(s(_mixinInstanceVariable) in s(Mixin), private)',
                          + 'Method(s(_staticGetter) in s(Class), private, static, getter)',
                          + 'Method(s(_staticMethod) in s(Class), private, static)',
                          + 'Method(s(_staticSetter=) in s(Class), private, static, setter)',
                          + 'Variable(s(_staticVariable) in s(Class), private, static)',
                          + 'Method(s(abstractMethod) in s(Class), abstract)',
                          + 'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
                          + 'Method(s(inheritedInstanceMethod) in s(Superclass))',
                          + 'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
                          + 'Variable(s(inheritedInstanceVariable) in s(Superclass))',
                          + 'Method(s(inheritedStaticGetter) in s(Superclass), static, getter)',
                          + 'Method(s(inheritedStaticMethod) in s(Superclass), static)',
                          + 'Method(s(inheritedStaticSetter=) in s(Superclass), static, setter)',
                          + 'Variable(s(inheritedStaticVariable) in s(Superclass), static)',
                          + 'Method(s(instanceGetter) in s(Class), getter)',
                          + 'Method(s(instanceMethod) in s(Class))',
                          + 'Method(s(instanceSetter=) in s(Class), setter)',
                          + 'Variable(s(instanceVariable) in s(Class))',
                          + 'Method(s(mixinInstanceGetter) in s(Mixin), getter)',
                          + 'Method(s(mixinInstanceMethod) in s(Mixin))',
                          + 'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
                          + 'Variable(s(mixinInstanceVariable) in s(Mixin))',
                          + 'Method(s(staticGetter) in s(Class), static, getter)',
                          + 'Method(s(staticMethod) in s(Class), static)',
                          + 'Method(s(staticSetter=) in s(Class), static, setter)',
                          + 'Variable(s(staticVariable) in s(Class), static)',
                          + 'Method(s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin._inheritedGenerativeConstructor)'
                          + ' in s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin), private, constructor)',
                          + 'Method(s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin._inheritedRedirectingConstructor)'
                          + ' in s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin), private, constructor)',
                          + 'Method(s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin.inheritedGenerativeConstructor)'
                          + ' in s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin), constructor)',
                          + 'Method(s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
                          + ' in s(test.declarations_model.Superclass'
                          + ' with test.declarations_model.Mixin), constructor)',
                          + 'Variable(s(mixinStaticVariable) in s(Mixin), static)',
                          + 'Variable(s(_mixinStaticVariable) in s(Mixin), private, static)',
                          + 'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
                          + 'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
                          + 'Method(s(mixinStaticMethod) in s(Mixin), static)',
                          + 'Method(s(_mixinStaticGetter) in s(Mixin), private, static, getter)',
                          + 'Method(s(_mixinStaticSetter=) in s(Mixin), private, static, setter)',
                          + 'Method(s(_mixinStaticMethod) in s(Mixin), private, static)'
                          + ], transitiveDeclarations(cm).map(stringify), 'transitive all');
                          }

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 24
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-MessageType: newchange

                          Dan Field (Gerrit)

                          unread,
                          Oct 2, 2020, 4:52:52 PM10/2/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Alexander Markov, Stephen Adams, Todd Volkert, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • File sdk/lib/core/object.dart:

                            • I ask because I started out using `identical`, but changed it in patch set 3 after comments from Ste […]

                              I'm having trouble finding that comment :) I'm not sure why the VM doesn't optimize for this, perhaps Alex Markov would know.

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 24
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Fri, 02 Oct 2020 20:52:44 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>

                          Alexander Markov (Gerrit)

                          unread,
                          Oct 2, 2020, 5:52:05 PM10/2/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Alexander Markov, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • File sdk/lib/core/object.dart:

                            • I'm having trouble finding that comment :) I'm not sure why the VM doesn't optimize for this, perhap […]

                              VM can optimize 'sentinelValue == object3' but not 'object3 == sentinelValue' (as in https://github.com/flutter/engine/pull/19615), because in the latter case call to operator== is polymorphic if class of object3 varies. If VM can prove that operator== call will always dispatch to Object.==, then it is inlined and generated similarly to identical.

                              On a small example

                                if (obj == sentinel) {
                              print(1);
                              }
                              if (sentinel == obj) {
                              print(2);
                              }
                              if (identical(sentinel, obj)) {
                              print(3);
                              }


                              AOT produces the following flow graph for each of these conditions ('v2' is obj, 'v3' is sentinel):

                                6:     v22 <- LoadClassId(v2)
                              8: PushArgument(v2)
                              10: PushArgument(v3)
                              11: ParallelMove rcx <- rcx
                              12: v4 <- DispatchTableCall( cid=v22 Object.==<0>, v2, v3) T{bool?}
                              13: ParallelMove rax <- rax
                              14: Branch if StrictCompare:16(===, v4 T{bool}, v6) goto (3, 4)

                              --------

                               30:     Branch if StrictCompare:10(===, v3, v2 T{Object}) T{bool} goto (6, 7)

                              --------

                               46:     Branch if StrictCompare:52(===, v3, v2) goto (9, 10)

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 24
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Dan Field <dnf...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Fri, 02 Oct 2020 21:52:00 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Dan Field <dnf...@google.com>
                          Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-MessageType: comment

                          Dan Field (Gerrit)

                          unread,
                          Oct 2, 2020, 6:04:04 PM10/2/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Alexander Markov, Stephen Adams, Todd Volkert, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • File sdk/lib/core/object.dart:

                            • VM can optimize 'sentinelValue == object3' but not 'object3 == sentinelValue' (as in https://github. […]

                              Why can't the VM just say that `==` is commutative and pick whichever version will result in smaller/optimal code?

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 24
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Alexander Markov <alexm...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Fri, 02 Oct 2020 22:03:58 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Alexander Markov <alexm...@google.com>

                          Alexander Markov (Gerrit)

                          unread,
                          Oct 2, 2020, 6:21:30 PM10/2/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Alexander Markov, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • File sdk/lib/core/object.dart:

                            • Why can't the VM just say that `==` is commutative and pick whichever version will result in smaller […]

                              That would violate Dart language semantics. Operator== is not guaranteed to be commutative, and 'a == b' is just a syntactic sugar for 'a.operator==(b)' call (with additional checks for null).

                              Here is the relevant paragraph from the Dart language specification:

                              Evaluation of an equality expression ee of the form e1 == e2 proceeds as
                              follows:
                              • The expression e1 is evaluated to an object o1.
                              • The expression e2 is evaluated to an object o2.
                              • If either o1 or o2 is the null object (16.4), then ee evaluates to true if both
                              o1 and o2 are the null object and to false otherwise. Otherwise,
                              • evaluation of ee is equivalent to the method invocation o1.==(o2).

                              Here is an example of Dart program which changes behavior if arguments of operator== are swapped:

                              class A {
                              operator==(Object other) => true;
                              }
                              class B {
                              operator==(Object other) => false;
                              }
                              main() {
                              print(A() == B());
                              print(B() == A());
                              }

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 24
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Dan Field <dnf...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Fri, 02 Oct 2020 22:21:24 +0000

                          Ian Hickson (Gerrit)

                          unread,
                          Oct 2, 2020, 6:28:11 PM10/2/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Alexander Markov, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 24
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Dan Field <dnf...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Fri, 02 Oct 2020 22:28:06 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Gerrit-MessageType: comment

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Oct 5, 2020, 9:25:04 AM10/5/20
                          to dart-dc-te...@google.com, rev...@dartlang.org, Ian Hickson, Alexander Markov, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • File sdk/lib/core/object.dart:

                            • Patch Set #23, Line 157: if (sentinelValue == object3) {

                              That would violate Dart language semantics. […]

                              This code uses `_sentinelValue == object3` (quite deliberately), so it should be fine?

                              The comments might have been offline, and I don't remember the details. It's quite likely that we discussed a complete rewrite, and ended up with `_sentinelValue == object3` and no reason to improve on that (because it is just as good as identical). So, not a deliberate choice to not use `identical`, just no reason to go for it when we already had the current code. (But that's guessing).

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 24
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Alexander Markov <alexm...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Dan Field <dnf...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Mon, 05 Oct 2020 13:24:57 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No

                          Dan Field (Gerrit)

                          unread,
                          Oct 5, 2020, 11:03:32 AM10/5/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Ian Hickson, Alexander Markov, Stephen Adams, Todd Volkert, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • File sdk/lib/core/object.dart:

                            • This code uses `_sentinelValue == object3` (quite deliberately), so it should be fine? […]

                              SGTM

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 25
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Alexander Markov <alexm...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Mon, 05 Oct 2020 15:03:27 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Alexander Markov <alexm...@google.com>

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Oct 5, 2020, 11:34:26 AM10/5/20
                          to dart-dc-te...@google.com, rev...@dartlang.org, Ian Hickson, Alexander Markov, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • Patchset:

                            • Patch Set #25:

                              Leaf, Stephen, any comments? (Or rubberstamps, I'm not picky 😊)

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 25
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Alexander Markov <alexm...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Mon, 05 Oct 2020 15:34:20 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Gerrit-MessageType: comment

                          Leaf Petersen (Gerrit)

                          unread,
                          Oct 6, 2020, 12:47:52 AM10/6/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Ian Hickson, Alexander Markov, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          3 comments:

                          • File sdk/lib/core/object.dart:

                            • Patch Set #23, Line 148: static int hash(Object? object1, Object? object2,

                              Not if the `hash` function is inlined. The implementation is optimized for dart2js inlining. […]

                              Can you say more about what you mean by this? I just tried out a program with three calls to hash, and dart2js didn't inline any of them. This seems like a fairly large function for dart2js to inline speculatively.

                              On the second issue, this feels like it runs into the problem that I commented on separately - I don't think that `hashAll([]) == hashAll([0]) == hashAll([0, 0]) == hashAll([0, 0, 0])` is a good thing. Resolving that seems like it will break the property you want here anyway, so maybe look to achieve it differently?

                          • File sdk/lib/core/object.dart:

                          • File sdk/lib/internal/internal.dart:

                            • Patch Set #23, Line 158: static int hash2(int v1, int v2) {

                              The problem with hash code algorithms is that it *might* be a breaking change to change the. […]

                              This isn't just a re-factoring though, right? It's exposing new API, and thereby causing exactly the problem you're describing above: sure it's a bad hash implementation, but we can't change it because it will be breaking. This is our one chance to get a good hash function in there without it being a breaking change, so why not take it? For String and Rectangle, just hand inline the hash for them - it's non-breaking, not a lot of code, and it will probably be much faster anyway, which is important for strings. Then we can have whatever hash we want for Object.hash et al.

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 25
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Alexander Markov <alexm...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Tue, 06 Oct 2020 04:47:48 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Oct 6, 2020, 6:09:07 AM10/6/20
                          to dart-dc-te...@google.com, rev...@dartlang.org, Ian Hickson, Alexander Markov, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          2 comments:

                          • File sdk/lib/core/object.dart:

                            • Can you say more about what you mean by this? I just tried out a program with three calls to hash, […]

                              I'll have to defer to Stephen on that. Stephen?

                          • File sdk/lib/internal/internal.dart:

                            • This isn't just a re-factoring though, right? It's exposing new API, and thereby causing exactly th […]

                              It's both. It's combining the four internal versions of Jenkins into one implementation, *and* exposing a new public hash code.

                              We could split this into two CLs, and then not necessarily use the same function for the public hash functions.

                              It would leave the external world still not able to reproduce `String.hashCode`, but they've survived this far without being able to do that, so not necessarily a problem.


                              Anyone have suggestions on a better hash code combination algorithm which can be implemented efficiently in JavaScript as well?

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 25
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Alexander Markov <alexm...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Tue, 06 Oct 2020 10:09:02 +0000

                          Sigmund Cherem (Gerrit)

                          unread,
                          Oct 6, 2020, 12:19:11 PM10/6/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Ian Hickson, Alexander Markov, Stephen Adams, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          View Change

                          1 comment:

                          • File sdk/lib/core/object.dart:

                            • I'll have to defer to Stephen on that. […]

                              DBC - FYI Stephen is OOO until next week.

                              I don't have the full context of the CL, but regarding inlining: currently we cannot inline this function as it is. Basically any function with more than one `return` is not inlinable at this time.

                              We'd love to make inlining decisions where the parameters could be used to eliminate some branches entirely (and in this case allow inlining), but we don't have that capability at this time.

                              I'd have to defer to Stephen to say whether that's something we can gain in the near future. We could also special case this function directly in the compiler, which sounded like what he was hinting in Patchset #3?

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 25
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Sigmund Cherem <sig...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Alexander Markov <alexm...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Stephen Adams <s...@google.com>
                          Gerrit-Comment-Date: Tue, 06 Oct 2020 16:19:07 +0000

                          Stephen Adams (Gerrit)

                          unread,
                          Oct 28, 2020, 2:49:17 PM10/28/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          Attention is currently required from: Lasse R.H. Nielsen, Leaf Petersen, Sigmund Cherem.

                          View Change

                          2 comments:

                            • DBC - FYI Stephen is OOO until next week. […]

                              My plan is to special-case this in the 'compiler'.

                              As mentioned in my comments on patchsets #2 and #3, there are two problems that need to be solved to make Object.hash deliver on performance. (1) the arity dispatch in Object.hash needs to be removed and (2) the calls to objectN.hashCode need to be specialized on some dart2js-specific instance method dispatch criteria (i.e. 'interceptors').

                              dart2js won't inline the function. It also can't tell that the sentinel is never passed in, so if the function was inlined, the if-then-else chain cannot necessarily be simplified ahead of the first sentinel. AOT probably has similar limitations.

                              To solve the dispatch problem I would rewrite `Object.hash` to call e.g. `Object._hash3(object1, object2, object3)`:

                              ```
                              int _hash3(Object? object1, Object? object2, Object? object3) {
                              return SystemHash.hash3(object1.hashCode, object2.hashCode, object3.hashCode);
                              }
                              ```

                              The 'compiler' could then lower `Object.hash(a, b, c)` to `Object._hash3(a, b, c)`. This solves the problem with the compilers not being willing to inline a huge function and being unable to tell that the sentinels are never passed in. Perhaps this could be a common Kernel transform.

                              You could add the `_hashN` methods now or later.

                              To solve (2) I would consider inlining `_hashN` (easy to do), or specialize `_hashN` on the tuple of dispatch criteria (harder to do).

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 25
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Sigmund Cherem <sig...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                          Gerrit-Comment-Date: Wed, 28 Oct 2020 18:49:11 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>
                          Comment-In-Reply-To: Leaf Petersen <le...@google.com>
                          Comment-In-Reply-To: Sigmund Cherem <sig...@google.com>
                          Gerrit-MessageType: comment

                          Stephen Adams (Gerrit)

                          unread,
                          Oct 28, 2020, 6:38:42 PM10/28/20
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          Attention is currently required from: Lasse R.H. Nielsen, Leaf Petersen, Sigmund Cherem.

                          Patch set 25:Code-Review +1

                          View Change

                          1 comment:

                          • Patchset:

                            • Patch Set #25:

                              The flutter function that this could replace accepts up to 20 arguments: https://api.flutter.dev/flutter/dart-ui/hashValues.html
                              We should aim to support deprecating the flutter version.
                              `Object.hash` should also accept 20 arguments to allow a simple replacement.

                              The issue with `Object.hashAll([]) = Object.hashAll([0,0,0])` can be solved by either starting with a non-zero hashcode (e.g. `int hash = 1;`) or adding in a constant with the new element in `combine` (biasing the value make some other input have this property, but making -1 have this property by adding in +1 is less likely to cause trouble). This is a detail of SystemHash.

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 25
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Sigmund Cherem <sig...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                          Gerrit-Comment-Date: Wed, 28 Oct 2020 22:38:36 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: Yes
                          Gerrit-MessageType: comment

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Oct 29, 2020, 5:11:43 AM10/29/20
                          to dart-dc-te...@google.com, rev...@dartlang.org, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          Attention is currently required from: Leaf Petersen, Sigmund Cherem.

                          View Change

                          1 comment:

                          • Patchset:

                            • Patch Set #25:

                              Would you be planning on releasing this with the "Small and useful features collection" https://gith […]

                              No, I'll just release it when it's done. It's a library feature, not a language feature.

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 25
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Sigmund Cherem <sig...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                          Gerrit-Comment-Date: Thu, 29 Oct 2020 09:11:38 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Jun 22, 2021, 10:39:36 AM6/22/21
                          to dart-dc-te...@google.com, rev...@dartlang.org, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Nate Bosch, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          Attention is currently required from: Leaf Petersen, Sigmund Cherem.

                          View Change

                          3 comments:

                          • Patchset:

                          • File sdk/lib/core/object.dart:

                            • Done

                          • File sdk/lib/internal/internal.dart:

                            • It's both. […]

                              I've looked into other hash combination algorithms, and if they are better, they are generally *byte* based, which we cannot assume here.

                              I think we should go with what we have here.

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 27
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Nate Bosch <nbo...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Sigmund Cherem <sig...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                          Gerrit-Comment-Date: Tue, 22 Jun 2021 14:39:29 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>
                          Comment-In-Reply-To: Leaf Petersen <le...@google.com>
                          Gerrit-MessageType: comment

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Jun 22, 2021, 10:39:56 AM6/22/21
                          to Nate Bosch, dart-dc-te...@google.com, rev...@dartlang.org, Stephen Adams, Leaf Petersen

                          Attention is currently required from: Leaf Petersen, Sigmund Cherem, Nate Bosch.

                          Lasse R.H. Nielsen would like Nate Bosch to review this change.

                          View Change

                          Add `Object.hash` and `Object.hashAll` static helper methods.

                          Fixes #11617.

                          Bug: http://dartbug.com/11617
                          Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          ---
                          M CHANGELOG.md
                          M sdk/lib/core/object.dart
                          M sdk/lib/internal/internal.dart

                          A tests/corelib/object_hash_test.dart
                          A tests/corelib_2/object_hash_test.dart
                          M tests/lib/mirrors/class_declarations_test.dart
                          M tests/lib_2/mirrors/class_declarations_test.dart
                          7 files changed, 687 insertions(+), 241 deletions(-)

                          diff --git a/CHANGELOG.md b/CHANGELOG.md
                          index 4b4cef9..6ce8761 100644
                          --- a/CHANGELOG.md
                          +++ b/CHANGELOG.md
                          @@ -22,6 +22,10 @@
                          daylight saving changes that are not precisely one hour.
                          (No change on the Web which uses the JavaScript `Date` object.)


                          +* Adds static methods `hash`, `hashAll` and `hashAllUnordered` to the
                          + `Object` class. These can be used to combine the hash codes of
                          + multiple objects in a consistent way.
                          +
                           #### `dart:ffi`

                          * Adds the `DynamicLibrary.providesSymbol` function to check whether a symbol
                          @@ -98,7 +102,7 @@
                          underscore.
                          - fix false negative in `prefer_final_parameters` where first parameter
                          is final.
                          -- improve `directives_ordering` sorting of directives with dot paths and
                          +- improve `directives_ordering` sorting of directives with dot paths and
                          dot-separated package names.
                          - (internal) migrate to `SecurityLintCode` instead of deprecated
                          `SecurityLintCodeWithUniqueName`.
                          diff --git a/sdk/lib/core/object.dart b/sdk/lib/core/object.dart
                          index 32b52bf..8088d82 100644
                          --- a/sdk/lib/core/object.dart
                          +++ b/sdk/lib/core/object.dart
                          @@ -146,4 +146,208 @@

                          /// A representation of the runtime type of the object.

                          external Type get runtimeType;
                          +
                          + /**
                          + * Creates a combined hash code for a number of objects.
                          + *
                          + * The hash code is computed for all arguments that are actually
                          + * supplied, even if they are `null`, by numerically combining the
                          + * [Object.hashCode] of each argument.
                          + *
                          + * Example:
                          + * ```dart
                          + * class SomeObject {
                          + * final Object a, b, c;
                          + * SomeObject(this.a, this.b, this.c);
                          + * bool operator=(Object other) =>
                          + * other is SomeObject && a == other.a && b == other.b && c == other.c;
                          + * int get hashCode => Object.hash(a, b, c);
                          + * }
                          + * ```
                          + *
                          + * The computed value must be consistent when the function is called
                          + * with the same arguments multiple times
                          + * during the execution of a single program.
                          + *
                          +   * The hash value generated by this function is *not* guaranteed to be stable

                          + * over different runs of the same program.
                          + * The exact algorithm used may differ between different platforms,
                          + * or between different versions of the platform libraries,
                          + * and it may depend on values that change per program run
                          + *
                          + * The [hashAll] function gives the same result as this function when
                          + * called with a collection containing the actual arguments to this function.
                          + */
                          +  @Since("2.14")
                          +  @Since("2.14")

                          + static int hashAll(Iterable<Object?> objects) {
                          + int hash = 0;
                          + for (var object in objects) {
                          + hash = SystemHash.combine(hash, object.hashCode);
                          + }
                          + return SystemHash.finish(hash);
                          + }
                          +
                          + /**
                          + * Creates a combined hash code for a collection of objects.
                          + *
                          + * The hash code is computed for elements in [objects],
                          + * even if they are `null`,
                          + * by numerically combining the [Object.hashCode] of each element
                          +   * in an order independent way.

                          + *
                          + * The result of `unorderedHashAll({o})` is not `o.hashCode`.
                          + *
                          + * Example:
                          + * ```dart
                          + * bool setEquals<T>(Set<T> set1, Set<T> set2) {
                          + * var hashCode1 = Object.unorderedHashAll(set1);
                          + * var hashCode2 = Object.unorderedHashAll(set2);
                          + * if (hashCode1 != hashCode2) return false;
                          + * // Compare elements ...
                          + * }
                          + * ```
                          + *
                          + * The computed value will be be consistent when the function is called
                          + * again with objects that have the same hash codes
                          + * during an execution of a single program,
                          + * even if the objects are not necessarily in the same order,
                          + *
                          +   * The hash value generated by this function is *not* guranteed to be stable
                          + * over different runs of the same program.
                          + * The exact algorithm used may differ between different platforms,
                          + * or between different versions of the platform libraries,
                          + * and it may depend on values that change per program run
                          + */
                          +  @Since("2.14")

                          + static int hashAllUnordered(Iterable<Object?> objects) {
                          + int sum = 0;
                          + int count = 0;
                          + const int mask = 0x3FFFFFFF;
                          + for (var object in objects) {
                          + int objectHash = SystemHash.smear(object.hashCode);
                          + sum = (sum + objectHash) & mask;
                          + count += 1;
                          + }
                          + return SystemHash.hash2(sum, count);
                          + }
                          }
                          diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
                          index 858f1f5..e713630 100644
                          --- a/sdk/lib/internal/internal.dart
                          +++ b/sdk/lib/internal/internal.dart
                          @@ -148,7 +148,7 @@
                          ///
                          /// [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
                          ///
                          -/// Usage:
                          +/// Use:
                          /// Hash each value with the hash of the previous value, then get the final
                          /// hash by calling finish.
                          /// ```
                          @@ -158,8 +158,9 @@
                          /// }
                          /// hash = SystemHash.finish(hash);
                          /// ```
                          -// TODO(lrn): Consider specializing this code per platform,
                          -// so the VM can use its 64-bit integers directly.
                          +///
                          +/// TODO(lrn): Consider specializing this code per platform,
                          +/// so the VM can use its 64-bit integers directly.
                          @Since("2.11")
                          class SystemHash {

                          static int combine(int hash, int value) {
                          @@ -298,6 +299,17 @@

                          }
                          }

                          +/// Sentinel values that should never be exposed outside of platform libraries.
                          +@Since("2.14")

                          +class SentinelValue {
                          + final int id;
                          + const SentinelValue(this.id);
                          +}
                          +
                          +/// A default value to use when only one sentinel is needed.
                          +@Since("2.14")

                          +const Object sentinelValue = const SentinelValue(0);
                          +
                          /// Given an [instance] of some generic type [T], and [extract], a first-class
                          /// generic function that takes the same number of type parameters as [T],
                          /// invokes the function with the same type arguments that were passed to T
                          index fc43a76..29c1595 100644
                          --- a/tests/lib_2/mirrors/class_declarations_test.dart
                          +++ b/tests/lib_2/mirrors/class_declarations_test.dart
                          @@ -12,9 +12,16 @@

                          import 'stringify.dart';
                          import 'declarations_model.dart' as declarations_model;

                          -Set<DeclarationMirror> inheritedDeclarations(ClassMirror cm) {
                          +/// Collects all declarations of [cm] and its super-classes except `Object`.
                          +///
                          +/// Includes static declarations of super-classes.
                          +///
                          +/// The `Object` class is omitted because this test should be stable against
                          +/// changes to the platform libraries, as long as the declaration model code
                          +/// doesn't change.
                          +Set<DeclarationMirror> transitiveDeclarations(ClassMirror cm) {
                          var decls = new Set<DeclarationMirror>();
                          - while (cm != null) {
                          + while (cm != reflectClass(Object)) {
                          decls.addAll(cm.declarations.values);
                          cm = cm.superclass;
                          }
                          @@ -165,14 +172,12 @@

                          'Method(s(*) in s(Mixin))',
                          'Method(s(+) in s(Class))',
                          'Method(s(-) in s(Superclass))',
                          - 'Method(s(==) in s(Object))',
                          'TypeVariable(s(C) in s(Class),'
                          ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          'Method(s(Class.generativeConstructor) in s(Class), constructor)',
                          'Method(s(Class.normalFactory) in s(Class), static, constructor)',
                          'Method(s(Class.redirectingConstructor) in s(Class), constructor)',
                          'Method(s(Class.redirectingFactory) in s(Class), static, constructor)',
                          - 'Method(s(Object) in s(Object), constructor)',
                          'TypeVariable(s(S) in s(Superclass),'
                          ' upperBound = Class(s(Object) in s(dart.core), top-level))',
                          'Method(s(Superclass.inheritedGenerativeConstructor)'
                          @@ -184,7 +189,6 @@

                          'Method(s(Superclass.inheritedRedirectingFactory)'
                          ' in s(Superclass), static, constructor)',
                          'Method(s(abstractMethod) in s(Class), abstract)',
                          - 'Method(s(hashCode) in s(Object), getter)',
                          'Method(s(inheritedInstanceGetter) in s(Superclass), getter)',
                          'Method(s(inheritedInstanceMethod) in s(Superclass))',
                          'Method(s(inheritedInstanceSetter=) in s(Superclass), setter)',
                          @@ -201,8 +205,6 @@

                          'Method(s(mixinInstanceMethod) in s(Mixin))',
                          'Method(s(mixinInstanceSetter=) in s(Mixin), setter)',
                          'Variable(s(mixinInstanceVariable) in s(Mixin))',
                          - 'Method(s(noSuchMethod) in s(Object))',
                          - 'Method(s(runtimeType) in s(Object), getter)',
                          'Method(s(staticGetter) in s(Class), static, getter)',
                          'Method(s(staticMethod) in s(Class), static)',
                          'Method(s(staticSetter=) in s(Class), static, setter)',
                          @@ -215,12 +217,11 @@

                          ' with test.declarations_model.Mixin.inheritedRedirectingConstructor)'
                          ' in s(test.declarations_model.Superclass'
                          ' with test.declarations_model.Mixin), constructor)',
                          - 'Method(s(toString) in s(Object))',
                          'Variable(s(mixinStaticVariable) in s(Mixin), static)',
                          'Method(s(mixinStaticGetter) in s(Mixin), static, getter)',
                          'Method(s(mixinStaticSetter=) in s(Mixin), static, setter)',
                          'Method(s(mixinStaticMethod) in s(Mixin), static)'
                          - ], inheritedDeclarations(cm).where((dm) => !dm.isPrivate).map(stringify),
                          + ], transitiveDeclarations(cm).where((dm) => !dm.isPrivate).map(stringify),
                          'transitive public');
                          // The public members of Object should be the same in all implementations, so
                          // we don't exclude Object here.
                          @@ -258,113 +259,106 @@

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 27
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Sigmund Cherem <sig...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                          Gerrit-Attention: Nate Bosch <nbo...@google.com>
                          Gerrit-MessageType: newchange

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Jun 22, 2021, 10:44:11 AM6/22/21
                          to dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          Attention is currently required from: Kevin Moore, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                          View Change

                          1 comment:

                          • Commit Message:

                            • Change to […]

                              The "Fixed #11617" above does that too.

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 27
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Sigmund Cherem <sig...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Kevin Moore <kev...@google.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                          Gerrit-Attention: Nate Bosch <nbo...@google.com>
                          Gerrit-Comment-Date: Tue, 22 Jun 2021 14:44:04 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: No
                          Comment-In-Reply-To: Kevin Moore <kev...@google.com>
                          Gerrit-MessageType: comment

                          Lasse R.H. Nielsen (Gerrit)

                          unread,
                          Jun 22, 2021, 10:56:38 AM6/22/21
                          to dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          Attention is currently required from: Kevin Moore, Ian Hickson, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                          Patch set 27:Commit-Queue +1

                          View Change

                          14 comments:

                          • File sdk/lib/core/object.dart:

                            • Patch Set #2, Line 149: static int hash(Object object1, Object object2,

                              I think you are correct, and I count it as a significant argument against that design. […]

                              Done

                            • Patch Set #2, Line 162: hash = JenkinsSmiHash.combine(hash, object3.hashCode);

                              This is definitely a function that it would be interesting to make the front end "always inline" and […]

                              Done

                          • File sdk/lib/core/object.dart:

                          • File sdk/lib/core/object.dart:

                            • Patch Set #12, Line 148: static int hash(Object? object1, Object? object2,

                              This point of the function is to *combine* multiple hashes. […]

                              Done

                          • File sdk/lib/core/object.dart:

                          • File sdk/lib/core/object.dart:

                            • Done

                          • File sdk/lib/internal/internal.dart:

                            • I've looked into other hash combination algorithms, and if they are better, they are generally *byte […]

                              Done

                            • Patch Set #23, Line 265: /// However, for the unordered hash based on xor, we need to improve

                            • ACK. It used to, now it uses `+` instead.

                            • Done

                          • File tests/corelib_2/object_hash_test.dart:

                            • Patch Set #16, Line 1: 2018

                              It's technically correct. […]

                              Done

                            • Patch Set #16, Line 1: // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file

                              Working on that (just want to make the test complete first, and be sure it's correct, before I start […]

                              Done

                          To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                          Gerrit-Project: sdk
                          Gerrit-Branch: master
                          Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                          Gerrit-Change-Number: 73360
                          Gerrit-PatchSet: 27
                          Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                          Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                          Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                          Gerrit-Reviewer: Stephen Adams <s...@google.com>
                          Gerrit-CC: Alexander Markov <alexm...@google.com>
                          Gerrit-CC: Dan Field <dnf...@google.com>
                          Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                          Gerrit-CC: Kevin Moore <kev...@google.com>
                          Gerrit-CC: Ryan Macnak <rma...@google.com>
                          Gerrit-CC: Sigmund Cherem <sig...@google.com>
                          Gerrit-CC: Todd Volkert <tvol...@google.com>
                          Gerrit-CC: Zach Anderson <z...@google.com>
                          Gerrit-Attention: Kevin Moore <kev...@google.com>
                          Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                          Gerrit-Attention: Leaf Petersen <le...@google.com>
                          Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                          Gerrit-Attention: Nate Bosch <nbo...@google.com>
                          Gerrit-Comment-Date: Tue, 22 Jun 2021 14:56:30 +0000
                          Gerrit-HasComments: Yes
                          Gerrit-Has-Labels: Yes
                          Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>
                          Comment-In-Reply-To: Stephen Adams <s...@google.com>
                          Comment-In-Reply-To: Leaf Petersen <le...@google.com>
                          Comment-In-Reply-To: Ian Hickson <ian.h...@gmail.com>
                          Comment-In-Reply-To: Sigmund Cherem <sig...@google.com>
                          Comment-In-Reply-To: Nate Bosch <nbo...@google.com>
                          Gerrit-MessageType: comment

                          Dart CI (Gerrit)

                          unread,
                          Jun 22, 2021, 11:31:32 AM6/22/21
                          to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                          Attention is currently required from: Kevin Moore, Ian Hickson, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                          go/dart-cbuild result: FAILURE (NO REGRESSIONS DETECTED)

                          Details: https://goto.google.com/dart-cbuild/find/31a1343158bce34110b93692ccae0475e9302bf6

                          View Change

                            To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                            Gerrit-Project: sdk
                            Gerrit-Branch: master
                            Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                            Gerrit-Change-Number: 73360
                            Gerrit-PatchSet: 29
                            Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                            Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                            Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                            Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                            Gerrit-Reviewer: Stephen Adams <s...@google.com>
                            Gerrit-CC: Alexander Markov <alexm...@google.com>
                            Gerrit-CC: Dan Field <dnf...@google.com>
                            Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                            Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                            Gerrit-CC: Kevin Moore <kev...@google.com>
                            Gerrit-CC: Ryan Macnak <rma...@google.com>
                            Gerrit-CC: Sigmund Cherem <sig...@google.com>
                            Gerrit-CC: Todd Volkert <tvol...@google.com>
                            Gerrit-CC: Zach Anderson <z...@google.com>
                            Gerrit-Attention: Kevin Moore <kev...@google.com>
                            Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                            Gerrit-Attention: Leaf Petersen <le...@google.com>
                            Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                            Gerrit-Attention: Nate Bosch <nbo...@google.com>
                            Gerrit-Comment-Date: Tue, 22 Jun 2021 15:31:28 +0000
                            Gerrit-HasComments: No
                            Gerrit-Has-Labels: No
                            Gerrit-MessageType: comment

                            Dart CI (Gerrit)

                            unread,
                            Jun 22, 2021, 11:31:52 AM6/22/21
                            to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                            Attention is currently required from: Kevin Moore, Ian Hickson, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                            go/dart-cbuild result: FAILURE (NO REGRESSIONS DETECTED)

                            Details: https://goto.google.com/dart-cbuild/find/e8381698b39c427d4044be1cbbb3c0c35cf8ec25

                            Gerrit-Comment-Date: Tue, 22 Jun 2021 15:31:48 +0000

                            Stephen Adams (Gerrit)

                            unread,
                            Jun 22, 2021, 1:53:22 PM6/22/21
                            to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Dart CI, Nate Bosch, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                            Attention is currently required from: Kevin Moore, Lasse R.H. Nielsen, Ian Hickson, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                            Patch set 29:Code-Review +1

                            View Change

                            1 comment:

                            To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                            Gerrit-Project: sdk
                            Gerrit-Branch: master
                            Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                            Gerrit-Change-Number: 73360
                            Gerrit-PatchSet: 29
                            Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                            Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                            Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                            Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                            Gerrit-Reviewer: Stephen Adams <s...@google.com>
                            Gerrit-CC: Alexander Markov <alexm...@google.com>
                            Gerrit-CC: Dan Field <dnf...@google.com>
                            Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                            Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                            Gerrit-CC: Kevin Moore <kev...@google.com>
                            Gerrit-CC: Ryan Macnak <rma...@google.com>
                            Gerrit-CC: Sigmund Cherem <sig...@google.com>
                            Gerrit-CC: Todd Volkert <tvol...@google.com>
                            Gerrit-CC: Zach Anderson <z...@google.com>
                            Gerrit-Attention: Kevin Moore <kev...@google.com>
                            Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                            Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                            Gerrit-Attention: Leaf Petersen <le...@google.com>
                            Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                            Gerrit-Attention: Nate Bosch <nbo...@google.com>
                            Gerrit-Comment-Date: Tue, 22 Jun 2021 17:53:16 +0000
                            Gerrit-HasComments: Yes
                            Gerrit-Has-Labels: Yes
                            Gerrit-MessageType: comment

                            Dan Field (Gerrit)

                            unread,
                            Jun 22, 2021, 1:56:02 PM6/22/21
                            to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Dart CI, Nate Bosch, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                            Attention is currently required from: Kevin Moore, Lasse R.H. Nielsen, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                            View Change

                            1 comment:

                            • File sdk/lib/core/object.dart:

                              • There are several libraries that have needed to implement their own hash combining, e.g. […]

                                +1 on this.

                                We're really hoping that this becomes a drop in replacement for hashValues/hashList.

                            To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                            Gerrit-Project: sdk
                            Gerrit-Branch: master
                            Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                            Gerrit-Change-Number: 73360
                            Gerrit-PatchSet: 29
                            Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                            Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                            Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                            Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                            Gerrit-Reviewer: Stephen Adams <s...@google.com>
                            Gerrit-CC: Alexander Markov <alexm...@google.com>
                            Gerrit-CC: Dan Field <dnf...@google.com>
                            Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                            Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                            Gerrit-CC: Kevin Moore <kev...@google.com>
                            Gerrit-CC: Ryan Macnak <rma...@google.com>
                            Gerrit-CC: Sigmund Cherem <sig...@google.com>
                            Gerrit-CC: Todd Volkert <tvol...@google.com>
                            Gerrit-CC: Zach Anderson <z...@google.com>
                            Gerrit-Attention: Kevin Moore <kev...@google.com>
                            Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                            Gerrit-Attention: Stephen Adams <s...@google.com>
                            Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                            Gerrit-Attention: Leaf Petersen <le...@google.com>
                            Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                            Gerrit-Attention: Nate Bosch <nbo...@google.com>
                            Gerrit-Comment-Date: Tue, 22 Jun 2021 17:55:57 +0000
                            Gerrit-HasComments: Yes
                            Gerrit-Has-Labels: No

                            Nate Bosch (Gerrit)

                            unread,
                            Jun 22, 2021, 3:11:32 PM6/22/21
                            to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Dart CI, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                            Attention is currently required from: Kevin Moore, Lasse R.H. Nielsen, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem.

                            Patch set 29:Code-Review +1

                            View Change

                            1 comment:

                            • File sdk/lib/core/object.dart:

                              • Patch Set #23, Line 271: hash = SystemHash.combine(hash, object.hashCode);

                                ACK. Another option is to not start with `0`. […]

                                +1 for starting with non-zero.

                            Gerrit-Comment-Date: Tue, 22 Jun 2021 19:11:28 +0000
                            Gerrit-HasComments: Yes
                            Gerrit-Has-Labels: Yes
                            Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>

                            Lasse R.H. Nielsen (Gerrit)

                            unread,
                            Jun 23, 2021, 7:14:40 AM6/23/21
                            to dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Dart CI, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                            Attention is currently required from: Kevin Moore, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                            View Change

                            1 comment:

                            • File sdk/lib/core/object.dart:

                              • +1 for starting with non-zero.

                                How'd you feel about rolling a new seed per execution (a random 32-bit integer created in a platform dependent way)?

                                It would mean that hash codes differ *between isolates*, which would worry me. (Unless we somehow share the seed, but that's a bigger task.)
                                Or we can use today's date. 😊

                            To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                            Gerrit-Project: sdk
                            Gerrit-Branch: master
                            Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                            Gerrit-Change-Number: 73360
                            Gerrit-PatchSet: 29
                            Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                            Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                            Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                            Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                            Gerrit-Reviewer: Stephen Adams <s...@google.com>
                            Gerrit-CC: Alexander Markov <alexm...@google.com>
                            Gerrit-CC: Dan Field <dnf...@google.com>
                            Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                            Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                            Gerrit-CC: Kevin Moore <kev...@google.com>
                            Gerrit-CC: Ryan Macnak <rma...@google.com>
                            Gerrit-CC: Sigmund Cherem <sig...@google.com>
                            Gerrit-CC: Todd Volkert <tvol...@google.com>
                            Gerrit-CC: Zach Anderson <z...@google.com>
                            Gerrit-Attention: Kevin Moore <kev...@google.com>
                            Gerrit-Attention: Stephen Adams <s...@google.com>
                            Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                            Gerrit-Attention: Leaf Petersen <le...@google.com>
                            Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                            Gerrit-Attention: Nate Bosch <nbo...@google.com>
                            Gerrit-Comment-Date: Wed, 23 Jun 2021 11:14:33 +0000
                            Gerrit-HasComments: Yes
                            Gerrit-Has-Labels: No
                            Comment-In-Reply-To: Lasse R.H. Nielsen <l...@google.com>
                            Comment-In-Reply-To: Leaf Petersen <le...@google.com>

                            Dart CI (Gerrit)

                            unread,
                            Jun 23, 2021, 11:12:01 AM6/23/21
                            to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                            Attention is currently required from: Kevin Moore, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                            go/dart-cbuild result: SUCCESS

                            Details: https://goto.google.com/dart-cbuild/find/e8c3909f22baf112e1f9da5ba785a22bb561305d

                            View Change

                              To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                              Gerrit-Project: sdk
                              Gerrit-Branch: master
                              Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                              Gerrit-Change-Number: 73360
                              Gerrit-PatchSet: 30
                              Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                              Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                              Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                              Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                              Gerrit-Reviewer: Stephen Adams <s...@google.com>
                              Gerrit-CC: Alexander Markov <alexm...@google.com>
                              Gerrit-CC: Dan Field <dnf...@google.com>
                              Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                              Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                              Gerrit-CC: Kevin Moore <kev...@google.com>
                              Gerrit-CC: Ryan Macnak <rma...@google.com>
                              Gerrit-CC: Sigmund Cherem <sig...@google.com>
                              Gerrit-CC: Todd Volkert <tvol...@google.com>
                              Gerrit-CC: Zach Anderson <z...@google.com>
                              Gerrit-Attention: Kevin Moore <kev...@google.com>
                              Gerrit-Attention: Stephen Adams <s...@google.com>
                              Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                              Gerrit-Attention: Leaf Petersen <le...@google.com>
                              Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                              Gerrit-Attention: Nate Bosch <nbo...@google.com>
                              Gerrit-Comment-Date: Wed, 23 Jun 2021 15:11:55 +0000

                              Lasse R.H. Nielsen (Gerrit)

                              unread,
                              Jun 23, 2021, 11:14:05 AM6/23/21
                              to dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Dart CI, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                              Attention is currently required from: Kevin Moore, Dan Field, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                              View Change

                              1 comment:

                              • File sdk/lib/core/object.dart:

                              To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                              Gerrit-Project: sdk
                              Gerrit-Branch: master
                              Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                              Gerrit-Change-Number: 73360
                              Gerrit-PatchSet: 30
                              Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                              Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                              Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                              Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                              Gerrit-Reviewer: Stephen Adams <s...@google.com>
                              Gerrit-CC: Alexander Markov <alexm...@google.com>
                              Gerrit-CC: Dan Field <dnf...@google.com>
                              Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                              Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                              Gerrit-CC: Kevin Moore <kev...@google.com>
                              Gerrit-CC: Ryan Macnak <rma...@google.com>
                              Gerrit-CC: Sigmund Cherem <sig...@google.com>
                              Gerrit-CC: Todd Volkert <tvol...@google.com>
                              Gerrit-CC: Zach Anderson <z...@google.com>
                              Gerrit-Attention: Kevin Moore <kev...@google.com>
                              Gerrit-Attention: Dan Field <dnf...@google.com>
                              Gerrit-Attention: Stephen Adams <s...@google.com>
                              Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                              Gerrit-Attention: Leaf Petersen <le...@google.com>
                              Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                              Gerrit-Attention: Nate Bosch <nbo...@google.com>
                              Gerrit-Comment-Date: Wed, 23 Jun 2021 15:13:56 +0000
                              Gerrit-HasComments: Yes
                              Gerrit-Has-Labels: No
                              Comment-In-Reply-To: Dan Field <dnf...@google.com>

                              Nate Bosch (Gerrit)

                              unread,
                              Jun 23, 2021, 12:45:03 PM6/23/21
                              to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Dart CI, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                              Attention is currently required from: Kevin Moore, Lasse R.H. Nielsen, Dan Field, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem.

                              Patch set 31:Code-Review +1

                              View Change

                              1 comment:

                              • File sdk/lib/core/object.dart:

                                • Patch Set #23, Line 271: hash = SystemHash.combine(hash, object.hashCode);

                                  How'd you feel about rolling a new seed per execution (a random 32-bit integer created in a platform […]

                                  I don't have strong feelings on changing hash codes per execution. I could certainly be convinced that it's a good idea - I don't particularly want to support consistent hash codes across isolates as a feature.

                              To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                              Gerrit-Project: sdk
                              Gerrit-Branch: master
                              Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                              Gerrit-Change-Number: 73360
                              Gerrit-PatchSet: 31
                              Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                              Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                              Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                              Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                              Gerrit-Reviewer: Stephen Adams <s...@google.com>
                              Gerrit-CC: Alexander Markov <alexm...@google.com>
                              Gerrit-CC: Dan Field <dnf...@google.com>
                              Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                              Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                              Gerrit-CC: Kevin Moore <kev...@google.com>
                              Gerrit-CC: Ryan Macnak <rma...@google.com>
                              Gerrit-CC: Sigmund Cherem <sig...@google.com>
                              Gerrit-CC: Todd Volkert <tvol...@google.com>
                              Gerrit-CC: Zach Anderson <z...@google.com>
                              Gerrit-Attention: Kevin Moore <kev...@google.com>
                              Gerrit-Attention: Lasse R.H. Nielsen <l...@google.com>
                              Gerrit-Attention: Dan Field <dnf...@google.com>
                              Gerrit-Attention: Stephen Adams <s...@google.com>
                              Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                              Gerrit-Attention: Leaf Petersen <le...@google.com>
                              Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                              Gerrit-Comment-Date: Wed, 23 Jun 2021 16:44:59 +0000
                              Gerrit-HasComments: Yes
                              Gerrit-Has-Labels: Yes

                              Stephen Adams (Gerrit)

                              unread,
                              Jun 23, 2021, 6:21:43 PM6/23/21
                              to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Dart CI, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                              Attention is currently required from: Kevin Moore, Lasse R.H. Nielsen, Dan Field, Ian Hickson, Leaf Petersen, Sigmund Cherem.

                              Patch set 31:Code-Review +1

                              View Change

                              1 comment:

                              Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                              Gerrit-Attention: Leaf Petersen <le...@google.com>
                              Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                              Gerrit-Comment-Date: Wed, 23 Jun 2021 22:21:39 +0000
                              Gerrit-HasComments: Yes
                              Gerrit-Has-Labels: Yes
                              Gerrit-MessageType: comment

                              Dart CI (Gerrit)

                              unread,
                              Jun 23, 2021, 6:41:59 PM6/23/21
                              to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                              Attention is currently required from: Kevin Moore, Lasse R.H. Nielsen, Dan Field, Ian Hickson, Leaf Petersen, Sigmund Cherem.

                              go/dart-cbuild result: SUCCESS

                              Details: https://goto.google.com/dart-cbuild/find/9befa7fac4827ee3e90348f56d7d8b2f4f7625af

                              View Change

                              Gerrit-Comment-Date: Wed, 23 Jun 2021 22:41:55 +0000

                              Lasse R.H. Nielsen (Gerrit)

                              unread,
                              Jun 24, 2021, 5:32:39 AM6/24/21
                              to dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Dart CI, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                              Attention is currently required from: Kevin Moore, Dan Field, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem.

                              View Change

                              1 comment:

                              • File sdk/lib/_internal/js_runtime/lib/js_helper.dart:

                                • This seems to be a bug fix for an issue independent of Object.hash […]

                                  Excellent, I'll just revert that fix.

                              To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                              Gerrit-Project: sdk
                              Gerrit-Branch: master
                              Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                              Gerrit-Change-Number: 73360
                              Gerrit-PatchSet: 31
                              Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                              Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                              Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                              Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                              Gerrit-Reviewer: Stephen Adams <s...@google.com>
                              Gerrit-CC: Alexander Markov <alexm...@google.com>
                              Gerrit-CC: Dan Field <dnf...@google.com>
                              Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                              Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                              Gerrit-CC: Kevin Moore <kev...@google.com>
                              Gerrit-CC: Ryan Macnak <rma...@google.com>
                              Gerrit-CC: Sigmund Cherem <sig...@google.com>
                              Gerrit-CC: Todd Volkert <tvol...@google.com>
                              Gerrit-CC: Zach Anderson <z...@google.com>
                              Gerrit-Attention: Kevin Moore <kev...@google.com>
                              Gerrit-Attention: Dan Field <dnf...@google.com>
                              Gerrit-Attention: Stephen Adams <s...@google.com>
                              Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                              Gerrit-Attention: Leaf Petersen <le...@google.com>
                              Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                              Gerrit-Comment-Date: Thu, 24 Jun 2021 09:32:34 +0000
                              Gerrit-HasComments: Yes
                              Gerrit-Has-Labels: No

                              Dart CI (Gerrit)

                              unread,
                              Jun 24, 2021, 9:36:56 AM6/24/21
                              to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                              Attention is currently required from: Kevin Moore, Dan Field, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem.

                              go/dart-cbuild result: SUCCESS

                              Details: https://goto.google.com/dart-cbuild/find/e1f98b91fc2d841a888afd0e5487ef366c674a44

                              View Change

                                To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                                Gerrit-Project: sdk
                                Gerrit-Branch: master
                                Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                                Gerrit-Change-Number: 73360
                                Gerrit-PatchSet: 32
                                Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                                Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                                Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                                Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                                Gerrit-Reviewer: Stephen Adams <s...@google.com>
                                Gerrit-CC: Alexander Markov <alexm...@google.com>
                                Gerrit-CC: Dan Field <dnf...@google.com>
                                Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                                Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                                Gerrit-CC: Kevin Moore <kev...@google.com>
                                Gerrit-CC: Ryan Macnak <rma...@google.com>
                                Gerrit-CC: Sigmund Cherem <sig...@google.com>
                                Gerrit-CC: Todd Volkert <tvol...@google.com>
                                Gerrit-CC: Zach Anderson <z...@google.com>
                                Gerrit-Attention: Kevin Moore <kev...@google.com>
                                Gerrit-Attention: Dan Field <dnf...@google.com>
                                Gerrit-Attention: Stephen Adams <s...@google.com>
                                Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                                Gerrit-Attention: Leaf Petersen <le...@google.com>
                                Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                                Gerrit-Comment-Date: Thu, 24 Jun 2021 13:36:51 +0000

                                Lasse R.H. Nielsen (Gerrit)

                                unread,
                                Jun 25, 2021, 6:17:57 AM6/25/21
                                to dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Dart CI, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                                Attention is currently required from: Kevin Moore, Dan Field, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem.

                                Patch set 33:Commit-Queue +2

                                View Change

                                  To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                                  Gerrit-Project: sdk
                                  Gerrit-Branch: master
                                  Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                                  Gerrit-Change-Number: 73360
                                  Gerrit-PatchSet: 33
                                  Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                                  Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                                  Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                                  Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                                  Gerrit-Reviewer: Stephen Adams <s...@google.com>
                                  Gerrit-CC: Alexander Markov <alexm...@google.com>
                                  Gerrit-CC: Dan Field <dnf...@google.com>
                                  Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                                  Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                                  Gerrit-CC: Kevin Moore <kev...@google.com>
                                  Gerrit-CC: Ryan Macnak <rma...@google.com>
                                  Gerrit-CC: Sigmund Cherem <sig...@google.com>
                                  Gerrit-CC: Todd Volkert <tvol...@google.com>
                                  Gerrit-CC: Zach Anderson <z...@google.com>
                                  Gerrit-Attention: Kevin Moore <kev...@google.com>
                                  Gerrit-Attention: Dan Field <dnf...@google.com>
                                  Gerrit-Attention: Stephen Adams <s...@google.com>
                                  Gerrit-Attention: Ian Hickson <ian.h...@gmail.com>
                                  Gerrit-Attention: Leaf Petersen <le...@google.com>
                                  Gerrit-Attention: Sigmund Cherem <sig...@google.com>
                                  Gerrit-Comment-Date: Fri, 25 Jun 2021 10:17:52 +0000
                                  Gerrit-HasComments: No
                                  Gerrit-Has-Labels: Yes
                                  Gerrit-MessageType: comment

                                  Lasse R.H. Nielsen (Gerrit)

                                  unread,
                                  Jun 25, 2021, 6:18:00 AM6/25/21
                                  to dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Dart CI, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                                  Attention is currently required from: Kevin Moore, Dan Field, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                                  View Change

                                  1 comment:

                                  • File sdk/lib/core/object.dart:

                                    • I don't have strong feelings on changing hash codes per execution. […]

                                      Let's start out doing that then, and see if anyone complains about cross-isolate discrepancies.

                                  Gerrit-Attention: Nate Bosch <nbo...@google.com>
                                  Gerrit-Comment-Date: Fri, 25 Jun 2021 10:17:55 +0000
                                  Gerrit-HasComments: Yes
                                  Gerrit-Has-Labels: No

                                  Dart CI (Gerrit)

                                  unread,
                                  Jun 25, 2021, 6:29:29 AM6/25/21
                                  to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, commi...@chromium.org, Keerti Parthasarathy, Zach Anderson

                                  Attention is currently required from: Kevin Moore, Dan Field, Stephen Adams, Ian Hickson, Leaf Petersen, Sigmund Cherem, Nate Bosch.

                                  go/dart-cbuild result: SUCCESS

                                  Details: https://goto.google.com/dart-cbuild/find/18fbb5dff5cab80b315e9794c7ccc2ac6f46d994

                                  View Change

                                  Gerrit-Comment-Date: Fri, 25 Jun 2021 10:29:24 +0000

                                  commit-bot@chromium.org (Gerrit)

                                  unread,
                                  Jun 25, 2021, 7:40:45 AM6/25/21
                                  to Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Dart CI, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Keerti Parthasarathy, Zach Anderson

                                  commi...@chromium.org submitted this change.

                                  View Change

                                  Approvals: Stephen Adams: Looks good to me, approved Nate Bosch: Looks good to me, approved Lasse R.H. Nielsen: Commit
                                  Add `Object.hash` and `Object.hashAll` static helper methods.

                                  Fixes #11617.

                                  Bug: http://dartbug.com/11617
                                  Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                                  Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/73360
                                  Commit-Queue: Lasse R.H. Nielsen <l...@google.com>
                                  Reviewed-by: Nate Bosch <nbo...@google.com>
                                  Reviewed-by: Stephen Adams <s...@google.com>

                                  ---
                                  M CHANGELOG.md
                                  M sdk/lib/core/object.dart
                                  M sdk/lib/internal/internal.dart
                                  A tests/corelib/object_hash_test.dart
                                  A tests/corelib_2/object_hash_test.dart
                                  M tests/lib/mirrors/class_declarations_test.dart
                                  M tests/lib_2/mirrors/class_declarations_test.dart
                                  7 files changed, 1,274 insertions(+), 261 deletions(-)

                                  diff --git a/CHANGELOG.md b/CHANGELOG.md
                                  index 5119c30..f32243e 100644
                                  --- a/CHANGELOG.md
                                  +++ b/CHANGELOG.md
                                  @@ -27,6 +27,10 @@

                                  daylight saving changes that are not precisely one hour.
                                  (No change on the Web which uses the JavaScript `Date` object.)

                                  +* Adds static methods `hash`, `hashAll` and `hashAllUnordered` to the
                                  + `Object` class. These can be used to combine the hash codes of
                                  + multiple objects in a consistent way.
                                  +
                                  #### `dart:ffi`

                                  * Adds the `DynamicLibrary.providesSymbol` function to check whether a symbol
                                  diff --git a/sdk/lib/core/object.dart b/sdk/lib/core/object.dart
                                  index 32b52bf..8d02d06 100644
                                  --- a/sdk/lib/core/object.dart
                                  +++ b/sdk/lib/core/object.dart
                                  @@ -146,4 +146,418 @@


                                  /// A representation of the runtime type of the object.
                                  external Type get runtimeType;
                                  +
                                  +  /// Creates a combined hash code for a number of objects.
                                  + ///
                                  + /// The hash code is computed for all arguments that are actually
                                  + /// supplied, even if they are `null`, by numerically combining the
                                  + /// [Object.hashCode] of each argument.
                                  + ///
                                  + /// Example:
                                  + /// ```dart
                                  + /// class SomeObject {
                                  + /// final Object a, b, c;
                                  + /// SomeObject(this.a, this.b, this.c);
                                  + /// bool operator=(Object other) =>
                                  + /// other is SomeObject && a == other.a && b == other.b && c == other.c;
                                  + /// int get hashCode => Object.hash(a, b, c);
                                  + /// }
                                  + /// ```
                                  + ///
                                  + /// The computed value will be consistent when the function is called
                                  + /// with the same arguments multiple times
                                  + /// during the execution of a single program.
                                  + ///
                                  + /// The hash value generated by this function is *not* guaranteed to be stable
                                  + /// over different runs of the same program,
                                  + /// or between code run in different isolates of the same program.
                                  + /// The exact algorithm used may differ between different platforms,
                                  + /// or between different versions of the platform libraries,
                                  + /// and it may depend on values that change on each program execution.
                                  + ///
                                  + /// The [hashAll] function gives the same result as this function when
                                  + /// called with a collection containing the actual arguments
                                  + /// to this function in the same order.

                                  + @Since("2.14")
                                  + static int hash(Object? object1, Object? object2,
                                  + [Object? object3 = sentinelValue,
                                  + Object? object4 = sentinelValue,
                                  + Object? object5 = sentinelValue,
                                  + Object? object6 = sentinelValue,
                                  + Object? object7 = sentinelValue,
                                  + Object? object8 = sentinelValue,
                                  + Object? object9 = sentinelValue,
                                  +      Object? object10 = sentinelValue,
                                  + Object? object11 = sentinelValue,
                                  + Object? object12 = sentinelValue,
                                  + Object? object13 = sentinelValue,
                                  + Object? object14 = sentinelValue,
                                  + Object? object15 = sentinelValue,
                                  + Object? object16 = sentinelValue,
                                  + Object? object17 = sentinelValue,
                                  + Object? object18 = sentinelValue,
                                  + Object? object19 = sentinelValue,
                                  + Object? object20 = sentinelValue]) {

                                  + if (sentinelValue == object3) {
                                  +      return SystemHash.hash2(object1.hashCode, object2.hashCode, _hashSeed);

                                  + }
                                  + if (sentinelValue == object4) {
                                  + return SystemHash.hash3(
                                  +          object1.hashCode, object2.hashCode, object3.hashCode, _hashSeed);

                                  + }
                                  + if (sentinelValue == object5) {
                                  + return SystemHash.hash4(object1.hashCode, object2.hashCode,
                                  +          object3.hashCode, object4.hashCode, _hashSeed);

                                  + }
                                  + if (sentinelValue == object6) {
                                  + return SystemHash.hash5(object1.hashCode, object2.hashCode,
                                  +          object3.hashCode, object4.hashCode, object5.hashCode, _hashSeed);

                                  + }
                                  + if (sentinelValue == object7) {
                                  + return SystemHash.hash6(
                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  +          object6.hashCode,
                                  + _hashSeed);

                                  + }
                                  + if (sentinelValue == object8) {
                                  + return SystemHash.hash7(
                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  +          object7.hashCode,
                                  + _hashSeed);

                                  + }
                                  + if (sentinelValue == object9) {
                                  + return SystemHash.hash8(
                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  +          object8.hashCode,
                                  + _hashSeed);

                                  + }
                                  + if (sentinelValue == object10) {
                                  + return SystemHash.hash9(
                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  +          object9.hashCode,
                                  + _hashSeed);
                                  + }
                                  + if (sentinelValue == object11) {

                                  + return SystemHash.hash10(
                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +          object10.hashCode,
                                  + _hashSeed);
                                  + }
                                  + if (sentinelValue == object12) {
                                  + return SystemHash.hash11(

                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +          object10.hashCode,
                                  + object11.hashCode,
                                  + _hashSeed);
                                  + }
                                  + if (sentinelValue == object13) {
                                  + return SystemHash.hash12(

                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +          object10.hashCode,
                                  + object11.hashCode,
                                  + object12.hashCode,
                                  + _hashSeed);
                                  + }
                                  + if (sentinelValue == object14) {
                                  + return SystemHash.hash13(

                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +          object10.hashCode,
                                  + object11.hashCode,
                                  + object12.hashCode,
                                  + object13.hashCode,
                                  + _hashSeed);
                                  + }
                                  + if (sentinelValue == object15) {
                                  + return SystemHash.hash14(

                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +          object10.hashCode,
                                  + object11.hashCode,
                                  + object12.hashCode,
                                  + object13.hashCode,
                                  + object14.hashCode,
                                  + _hashSeed);
                                  + }
                                  + if (sentinelValue == object16) {
                                  + return SystemHash.hash15(

                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +          object10.hashCode,
                                  + object11.hashCode,
                                  + object12.hashCode,
                                  + object13.hashCode,
                                  + object14.hashCode,
                                  + object15.hashCode,
                                  + _hashSeed);
                                  + }
                                  + if (sentinelValue == object17) {
                                  + return SystemHash.hash16(

                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +          object10.hashCode,
                                  + object11.hashCode,
                                  + object12.hashCode,
                                  + object13.hashCode,
                                  + object14.hashCode,
                                  + object15.hashCode,
                                  + object16.hashCode,
                                  + _hashSeed);
                                  + }
                                  + if (sentinelValue == object18) {
                                  + return SystemHash.hash17(

                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +          object10.hashCode,
                                  + object11.hashCode,
                                  + object12.hashCode,
                                  + object13.hashCode,
                                  + object14.hashCode,
                                  + object15.hashCode,
                                  + object16.hashCode,
                                  + object17.hashCode,
                                  + _hashSeed);
                                  + }
                                  + if (sentinelValue == object19) {
                                  + return SystemHash.hash18(

                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +          object10.hashCode,
                                  + object11.hashCode,
                                  + object12.hashCode,
                                  + object13.hashCode,
                                  + object14.hashCode,
                                  + object15.hashCode,
                                  + object16.hashCode,
                                  + object17.hashCode,
                                  + object18.hashCode,
                                  + _hashSeed);
                                  + }
                                  + if (sentinelValue == object20) {
                                  + return SystemHash.hash19(

                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +          object10.hashCode,
                                  + object11.hashCode,
                                  + object12.hashCode,
                                  + object13.hashCode,
                                  + object14.hashCode,
                                  + object15.hashCode,
                                  + object16.hashCode,
                                  + object17.hashCode,
                                  + object18.hashCode,
                                  + object19.hashCode,
                                  + _hashSeed);
                                  + }
                                  + return SystemHash.hash20(

                                  + object1.hashCode,
                                  + object2.hashCode,
                                  + object3.hashCode,
                                  + object4.hashCode,
                                  + object5.hashCode,
                                  + object6.hashCode,
                                  + object7.hashCode,
                                  + object8.hashCode,
                                  + object9.hashCode,
                                  +        object10.hashCode,
                                  + object11.hashCode,
                                  + object12.hashCode,
                                  + object13.hashCode,
                                  + object14.hashCode,
                                  + object15.hashCode,
                                  + object16.hashCode,
                                  + object17.hashCode,
                                  + object18.hashCode,
                                  + object19.hashCode,
                                  + object20.hashCode,
                                  + _hashSeed);
                                  + }
                                  +
                                  + /// Creates a combined hash code for a sequence of objects.
                                  + ///
                                  + /// The hash code is computed for elements in [objects],
                                  + /// even if they are `null`,
                                  + /// by numerically combining the [Object.hashCode] of each element
                                  + /// in iteration order.
                                  + ///
                                  + /// The result of `hashAll([o])` is not `o.hashCode`.
                                  + ///
                                  + /// Example:
                                  + /// ```dart
                                  + /// class SomeObject {
                                  + /// final List<String> path;
                                  + /// SomeObject(this.path);
                                  + /// bool operator=(Object other) {
                                  + /// if (other is SomeObject) {
                                  + /// if (path.length != other.path.length) return false;
                                  + /// for (int i = 0; i < path.length; i++) {
                                  + /// if (path[i] != other.path[i]) return false;
                                  + /// }
                                  + /// return true;
                                  + /// }
                                  + /// return false;
                                  + /// }
                                  + ///
                                  + /// int get hashCode => Object.hashAll(path);
                                  + /// }
                                  + /// ```
                                  + ///
                                  + /// The computed value will be be consistent when the function is called
                                  + /// again with objects that have the same hash codes in the same order
                                  + /// during an execution of a single program.
                                  + ///
                                  + /// The hash value generated by this function is *not* guranteed to be stable
                                  + /// over different runs of the same program,
                                  + /// or between code run in different isolates of the same program.
                                  + /// The exact algorithm used may differ between different platforms,
                                  + /// or between different versions of the platform libraries,
                                  + /// and it may depend on values that change on each program execution.

                                  + @Since("2.14")
                                  + static int hashAll(Iterable<Object?> objects) {
                                  +    int hash = _hashSeed;

                                  + for (var object in objects) {
                                  + hash = SystemHash.combine(hash, object.hashCode);
                                  + }
                                  + return SystemHash.finish(hash);
                                  + }
                                  +
                                  +  /// Creates a combined hash code for a collection of objects.
                                  + ///
                                  + /// The hash code is computed for elements in [objects],
                                  + /// even if they are `null`,
                                  + /// by numerically combining the [Object.hashCode] of each element
                                  + /// in an order independent way.
                                  + ///
                                  + /// The result of `unorderedHashAll({o})` is not `o.hashCode`.
                                  + ///
                                  + /// Example:
                                  + /// ```dart
                                  + /// bool setEquals<T>(Set<T> set1, Set<T> set2) {
                                  + /// var hashCode1 = Object.unorderedHashAll(set1);
                                  + /// var hashCode2 = Object.unorderedHashAll(set2);
                                  + /// if (hashCode1 != hashCode2) return false;
                                  + /// // Compare elements ...
                                  + /// }
                                  + /// ```
                                  + ///
                                  + /// The computed value will be be consistent when the function is called
                                  + /// again with objects that have the same hash codes
                                  + /// during an execution of a single program,
                                  + /// even if the objects are not necessarily in the same order,
                                  + ///
                                  + /// The hash value generated by this function is *not* guranteed to be stable
                                  + /// over different runs of the same program.
                                  + /// The exact algorithm used may differ between different platforms,
                                  + /// or between different versions of the platform libraries,
                                  + /// and it may depend on values that change per program run

                                  + @Since("2.14")
                                  + static int hashAllUnordered(Iterable<Object?> objects) {
                                  + int sum = 0;
                                  + int count = 0;
                                  + const int mask = 0x3FFFFFFF;
                                  + for (var object in objects) {
                                  + int objectHash = SystemHash.smear(object.hashCode);
                                  + sum = (sum + objectHash) & mask;
                                  + count += 1;
                                  + }
                                  + return SystemHash.hash2(sum, count);
                                  + }
                                  }
                                  +
                                  +// A per-isolate seed for hash code computations.
                                  +final int _hashSeed = identityHashCode(Object);
                                  diff --git a/sdk/lib/internal/internal.dart b/sdk/lib/internal/internal.dart
                                  index 858f1f5..0e4c898 100644

                                  --- a/sdk/lib/internal/internal.dart
                                  +++ b/sdk/lib/internal/internal.dart
                                  @@ -148,7 +148,7 @@
                                  ///
                                  /// [1]: http://en.wikipedia.org/wiki/Jenkins_hash_function
                                  ///
                                  -/// Usage:
                                  +/// Use:
                                  /// Hash each value with the hash of the previous value, then get the final
                                  /// hash by calling finish.
                                  /// ```
                                  @@ -158,8 +158,9 @@
                                  /// }
                                  /// hash = SystemHash.finish(hash);
                                  /// ```
                                  -// TODO(lrn): Consider specializing this code per platform,
                                  -// so the VM can use its 64-bit integers directly.
                                  +///
                                  +/// TODO(lrn): Consider specializing this code per platform,
                                  +/// so the VM can use its 64-bit integers directly.
                                  @Since("2.11")
                                  class SystemHash {
                                  static int combine(int hash, int value) {
                                  @@ -174,23 +175,24 @@
                                  return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
                                  }

                                  - static int hash2(int v1, int v2) {
                                  - int hash = 0;
                                  + static int hash2(int v1, int v2, [@Since("2.14") int seed = 0]) {
                                  + int hash = seed;
                                  hash = combine(hash, v1);
                                  hash = combine(hash, v2);
                                  return finish(hash);
                                  }

                                  - static int hash3(int v1, int v2, int v3) {
                                  - int hash = 0;
                                  + static int hash3(int v1, int v2, int v3, [@Since("2.14") int seed = 0]) {
                                  + int hash = seed;
                                  hash = combine(hash, v1);
                                  hash = combine(hash, v2);
                                  hash = combine(hash, v3);
                                  return finish(hash);
                                  }

                                  - static int hash4(int v1, int v2, int v3, int v4) {
                                  - int hash = 0;
                                  + static int hash4(int v1, int v2, int v3, int v4,
                                  + [@Since("2.14") int seed = 0]) {
                                  + int hash = seed;
                                  hash = combine(hash, v1);
                                  hash = combine(hash, v2);
                                  hash = combine(hash, v3);
                                  @@ -198,8 +200,9 @@
                                  return finish(hash);
                                  }

                                  - static int hash5(int v1, int v2, int v3, int v4, int v5) {
                                  - int hash = 0;
                                  + static int hash5(int v1, int v2, int v3, int v4, int v5,
                                  + [@Since("2.14") int seed = 0]) {
                                  + int hash = seed;
                                  hash = combine(hash, v1);
                                  hash = combine(hash, v2);
                                  hash = combine(hash, v3);
                                  @@ -208,8 +211,9 @@
                                  return finish(hash);
                                  }

                                  - static int hash6(int v1, int v2, int v3, int v4, int v5, int v6) {
                                  - int hash = 0;
                                  + static int hash6(int v1, int v2, int v3, int v4, int v5, int v6,
                                  + [@Since("2.14") int seed = 0]) {
                                  + int hash = seed;
                                  hash = combine(hash, v1);
                                  hash = combine(hash, v2);
                                  hash = combine(hash, v3);
                                  @@ -219,8 +223,9 @@
                                  return finish(hash);
                                  }

                                  - static int hash7(int v1, int v2, int v3, int v4, int v5, int v6, int v7) {
                                  - int hash = 0;
                                  + static int hash7(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
                                  + [@Since("2.14") int seed = 0]) {
                                  + int hash = seed;
                                  hash = combine(hash, v1);
                                  hash = combine(hash, v2);
                                  hash = combine(hash, v3);
                                  @@ -232,8 +237,9 @@
                                  }

                                  static int hash8(
                                  - int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8) {
                                  - int hash = 0;
                                  + int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8,
                                  + [@Since("2.14") int seed = 0]) {
                                  + int hash = seed;
                                  hash = combine(hash, v1);
                                  hash = combine(hash, v2);
                                  hash = combine(hash, v3);
                                  @@ -246,8 +252,9 @@
                                  }

                                  static int hash9(
                                  - int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9) {
                                  - int hash = 0;
                                  + int v1, int v2, int v3, int v4, int v5, int v6, int v7, int v8, int v9,
                                  + [@Since("2.14") int seed = 0]) {
                                  + int hash = seed;
                                  hash = combine(hash, v1);
                                  hash = combine(hash, v2);
                                  hash = combine(hash, v3);
                                  @@ -261,8 +268,9 @@
                                  }

                                  static int hash10(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
                                  - int v8, int v9, int v10) {
                                  - int hash = 0;
                                  + int v8, int v9, int v10,
                                  + [@Since("2.14") int seed = 0]) {
                                  + int hash = seed;
                                  hash = combine(hash, v1);
                                  hash = combine(hash, v2);
                                  hash = combine(hash, v3);
                                  @@ -276,14 +284,334 @@
                                  return finish(hash);
                                  }

                                  + @Since("2.14")
                                  + static int hash11(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
                                  + int v8, int v9, int v10, int v11,
                                  + [int seed = 0]) {
                                  + int hash = seed;
                                  + hash = combine(hash, v1);
                                  + hash = combine(hash, v2);
                                  + hash = combine(hash, v3);
                                  + hash = combine(hash, v4);
                                  + hash = combine(hash, v5);
                                  + hash = combine(hash, v6);
                                  + hash = combine(hash, v7);
                                  + hash = combine(hash, v8);
                                  + hash = combine(hash, v9);
                                  + hash = combine(hash, v10);
                                  + hash = combine(hash, v11);
                                  + return finish(hash);
                                  + }
                                  +
                                  + @Since("2.14")
                                  + static int hash12(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
                                  + int v8, int v9, int v10, int v11, int v12,
                                  + [int seed = 0]) {
                                  + int hash = seed;
                                  + hash = combine(hash, v1);
                                  + hash = combine(hash, v2);
                                  + hash = combine(hash, v3);
                                  + hash = combine(hash, v4);
                                  + hash = combine(hash, v5);
                                  + hash = combine(hash, v6);
                                  + hash = combine(hash, v7);
                                  + hash = combine(hash, v8);
                                  + hash = combine(hash, v9);
                                  + hash = combine(hash, v10);
                                  + hash = combine(hash, v11);
                                  + hash = combine(hash, v12);
                                  + return finish(hash);
                                  + }
                                  +
                                  + @Since("2.14")
                                  + static int hash13(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
                                  + int v8, int v9, int v10, int v11, int v12, int v13,
                                  + [int seed = 0]) {
                                  + int hash = seed;
                                  + hash = combine(hash, v1);
                                  + hash = combine(hash, v2);
                                  + hash = combine(hash, v3);
                                  + hash = combine(hash, v4);
                                  + hash = combine(hash, v5);
                                  + hash = combine(hash, v6);
                                  + hash = combine(hash, v7);
                                  + hash = combine(hash, v8);
                                  + hash = combine(hash, v9);
                                  + hash = combine(hash, v10);
                                  + hash = combine(hash, v11);
                                  + hash = combine(hash, v12);
                                  + hash = combine(hash, v13);
                                  + return finish(hash);
                                  + }
                                  +
                                  + @Since("2.14")
                                  + static int hash14(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
                                  + int v8, int v9, int v10, int v11, int v12, int v13, int v14,
                                  + [int seed = 0]) {
                                  + int hash = seed;
                                  + hash = combine(hash, v1);
                                  + hash = combine(hash, v2);
                                  + hash = combine(hash, v3);
                                  + hash = combine(hash, v4);
                                  + hash = combine(hash, v5);
                                  + hash = combine(hash, v6);
                                  + hash = combine(hash, v7);
                                  + hash = combine(hash, v8);
                                  + hash = combine(hash, v9);
                                  + hash = combine(hash, v10);
                                  + hash = combine(hash, v11);
                                  + hash = combine(hash, v12);
                                  + hash = combine(hash, v13);
                                  + hash = combine(hash, v14);
                                  + return finish(hash);
                                  + }
                                  +
                                  + @Since("2.14")
                                  + static int hash15(int v1, int v2, int v3, int v4, int v5, int v6, int v7,
                                  + int v8, int v9, int v10, int v11, int v12, int v13, int v14, int v15,
                                  + [int seed = 0]) {
                                  + int hash = seed;
                                  + hash = combine(hash, v1);
                                  + hash = combine(hash, v2);
                                  + hash = combine(hash, v3);
                                  + hash = combine(hash, v4);
                                  + hash = combine(hash, v5);
                                  + hash = combine(hash, v6);
                                  + hash = combine(hash, v7);
                                  + hash = combine(hash, v8);
                                  + hash = combine(hash, v9);
                                  + hash = combine(hash, v10);
                                  + hash = combine(hash, v11);
                                  + hash = combine(hash, v12);
                                  + hash = combine(hash, v13);
                                  + hash = combine(hash, v14);
                                  + hash = combine(hash, v15);
                                  + return finish(hash);
                                  + }
                                  +
                                  + @Since("2.14")
                                  + static int hash16(
                                  + int v1,
                                  + int v2,
                                  + int v3,
                                  + int v4,
                                  + int v5,
                                  + int v6,
                                  + int v7,
                                  + int v8,
                                  + int v9,
                                  + int v10,
                                  + int v11,
                                  + int v12,
                                  + int v13,
                                  + int v14,
                                  + int v15,
                                  + int v16,
                                  + [int seed = 0]) {
                                  + int hash = seed;
                                  + hash = combine(hash, v1);
                                  + hash = combine(hash, v2);
                                  + hash = combine(hash, v3);
                                  + hash = combine(hash, v4);
                                  + hash = combine(hash, v5);
                                  + hash = combine(hash, v6);
                                  + hash = combine(hash, v7);
                                  + hash = combine(hash, v8);
                                  + hash = combine(hash, v9);
                                  + hash = combine(hash, v10);
                                  + hash = combine(hash, v11);
                                  + hash = combine(hash, v12);
                                  + hash = combine(hash, v13);
                                  + hash = combine(hash, v14);
                                  + hash = combine(hash, v15);
                                  + hash = combine(hash, v16);
                                  + return finish(hash);
                                  + }
                                  +
                                  + @Since("2.14")
                                  + static int hash17(
                                  + int v1,
                                  + int v2,
                                  + int v3,
                                  + int v4,
                                  + int v5,
                                  + int v6,
                                  + int v7,
                                  + int v8,
                                  + int v9,
                                  + int v10,
                                  + int v11,
                                  + int v12,
                                  + int v13,
                                  + int v14,
                                  + int v15,
                                  + int v16,
                                  + int v17,
                                  + [int seed = 0]) {
                                  + int hash = seed;
                                  + hash = combine(hash, v1);
                                  + hash = combine(hash, v2);
                                  + hash = combine(hash, v3);
                                  + hash = combine(hash, v4);
                                  + hash = combine(hash, v5);
                                  + hash = combine(hash, v6);
                                  + hash = combine(hash, v7);
                                  + hash = combine(hash, v8);
                                  + hash = combine(hash, v9);
                                  + hash = combine(hash, v10);
                                  + hash = combine(hash, v11);
                                  + hash = combine(hash, v12);
                                  + hash = combine(hash, v13);
                                  + hash = combine(hash, v14);
                                  + hash = combine(hash, v15);
                                  + hash = combine(hash, v16);
                                  + hash = combine(hash, v17);
                                  + return finish(hash);
                                  + }
                                  +
                                  + @Since("2.14")
                                  + static int hash18(
                                  + int v1,
                                  + int v2,
                                  + int v3,
                                  + int v4,
                                  + int v5,
                                  + int v6,
                                  + int v7,
                                  + int v8,
                                  + int v9,
                                  + int v10,
                                  + int v11,
                                  + int v12,
                                  + int v13,
                                  + int v14,
                                  + int v15,
                                  + int v16,
                                  + int v17,
                                  + int v18,
                                  + [int seed = 0]) {
                                  + int hash = seed;
                                  + hash = combine(hash, v1);
                                  + hash = combine(hash, v2);
                                  + hash = combine(hash, v3);
                                  + hash = combine(hash, v4);
                                  + hash = combine(hash, v5);
                                  + hash = combine(hash, v6);
                                  + hash = combine(hash, v7);
                                  + hash = combine(hash, v8);
                                  + hash = combine(hash, v9);
                                  + hash = combine(hash, v10);
                                  + hash = combine(hash, v11);
                                  + hash = combine(hash, v12);
                                  + hash = combine(hash, v13);
                                  + hash = combine(hash, v14);
                                  + hash = combine(hash, v15);
                                  + hash = combine(hash, v16);
                                  + hash = combine(hash, v17);
                                  + hash = combine(hash, v18);
                                  + return finish(hash);
                                  + }
                                  +
                                  + @Since("2.14")
                                  + static int hash19(
                                  + int v1,
                                  + int v2,
                                  + int v3,
                                  + int v4,
                                  + int v5,
                                  + int v6,
                                  + int v7,
                                  + int v8,
                                  + int v9,
                                  + int v10,
                                  + int v11,
                                  + int v12,
                                  + int v13,
                                  + int v14,
                                  + int v15,
                                  + int v16,
                                  + int v17,
                                  + int v18,
                                  + int v19,
                                  + [int seed = 0]) {
                                  + int hash = seed;
                                  + hash = combine(hash, v1);
                                  + hash = combine(hash, v2);
                                  + hash = combine(hash, v3);
                                  + hash = combine(hash, v4);
                                  + hash = combine(hash, v5);
                                  + hash = combine(hash, v6);
                                  + hash = combine(hash, v7);
                                  + hash = combine(hash, v8);
                                  + hash = combine(hash, v9);
                                  + hash = combine(hash, v10);
                                  + hash = combine(hash, v11);
                                  + hash = combine(hash, v12);
                                  + hash = combine(hash, v13);
                                  + hash = combine(hash, v14);
                                  + hash = combine(hash, v15);
                                  + hash = combine(hash, v16);
                                  + hash = combine(hash, v17);
                                  + hash = combine(hash, v18);
                                  + hash = combine(hash, v19);
                                  + return finish(hash);
                                  + }
                                  +
                                  + @Since("2.14")
                                  + static int hash20(
                                  + int v1,
                                  + int v2,
                                  + int v3,
                                  + int v4,
                                  + int v5,
                                  + int v6,
                                  + int v7,
                                  + int v8,
                                  + int v9,
                                  + int v10,
                                  + int v11,
                                  + int v12,
                                  + int v13,
                                  + int v14,
                                  + int v15,
                                  + int v16,
                                  + int v17,
                                  + int v18,
                                  + int v19,
                                  + int v20,
                                  + [int seed = 0]) {
                                  + int hash = seed;
                                  + hash = combine(hash, v1);
                                  + hash = combine(hash, v2);
                                  + hash = combine(hash, v3);
                                  + hash = combine(hash, v4);
                                  + hash = combine(hash, v5);
                                  + hash = combine(hash, v6);
                                  + hash = combine(hash, v7);
                                  + hash = combine(hash, v8);
                                  + hash = combine(hash, v9);
                                  + hash = combine(hash, v10);
                                  + hash = combine(hash, v11);
                                  + hash = combine(hash, v12);
                                  + hash = combine(hash, v13);
                                  + hash = combine(hash, v14);
                                  + hash = combine(hash, v15);
                                  + hash = combine(hash, v16);
                                  + hash = combine(hash, v17);
                                  + hash = combine(hash, v18);
                                  + hash = combine(hash, v19);
                                  + hash = combine(hash, v20);
                                  + return finish(hash);
                                  + }
                                  +
                                  /// Bit shuffling operation to improve hash codes.
                                  ///
                                  /// Dart integers have very simple hash codes (their value),
                                  /// which is acceptable for the hash above because it smears the bits
                                  /// as part of the combination.
                                  - /// However, for the unordered hash based on xor, we need to improve
                                  - /// the hash code of, e.g., integers, so a set containing the integers
                                  - /// from zero to 2^n won't always have a zero hashcode.
                                  + /// However, for the unordered hash, we need to improve
                                  + /// the hash code of, e.g., integers, to avoid collections of small integers
                                  + /// too easily having colliding hash results.
                                  ///
                                  /// Assumes the input hash code is an unsigned 32-bit integer.
                                  /// Found by Christopher Wellons [https://github.com/skeeto/hash-prospector].
                                  @@ -298,6 +626,17 @@

                                  }
                                  }

                                  +/// Sentinel values that should never be exposed outside of platform libraries.
                                  +@Since("2.14")
                                  +class SentinelValue {
                                  + final int id;
                                  + const SentinelValue(this.id);
                                  +}
                                  +
                                  +/// A default value to use when only one sentinel is needed.
                                  +@Since("2.14")
                                  +const Object sentinelValue = const SentinelValue(0);
                                  +
                                  /// Given an [instance] of some generic type [T], and [extract], a first-class
                                  /// generic function that takes the same number of type parameters as [T],
                                  /// invokes the function with the same type arguments that were passed to T
                                  diff --git a/tests/corelib/object_hash_test.dart b/tests/corelib/object_hash_test.dart
                                  new file mode 100644
                                  index 0000000..3e9e5d8
                                  --- /dev/null
                                  +++ b/tests/corelib/object_hash_test.dart
                                  @@ -0,0 +1,134 @@

                                  +// Copyright (c) 2018, 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 "dart:math";

                                  +import "dart:typed_data";
                                  +
                                  +import "package:expect/expect.dart";
                                  +
                                  +main() {
                                  + const nan = double.nan;
                                  + const inf = double.infinity;
                                  +
                                  + int hash1234 = Object.hash(1, 2, 3, 4);
                                  + Expect.type<int>(hash1234);
                                  + Expect.equals(hash1234, Object.hash(1, 2, 3, 4)); // Consistent.
                                  + Expect.equals(hash1234, Object.hashAll([1, 2, 3, 4]));
                                  + Expect.equals(hash1234, Object.hashAll(Uint8List.fromList([1, 2, 3, 4])));
                                  +
                                  + Expect.notEquals(hash1234, Object.hash(1, 2, 3, 4, null));
                                  +
                                  + Expect.equals(Object.hash(1, 2, 3, 4, 5, 6, 7, 8, 9),
                                  + Object.hashAll([1, 2, 3, 4, 5, 6, 7, 8, 9]));
                                  +
                                  +  // Check that we can call `hash` with 2-20 arguments,
                                  + // and they all agree with `hashAll`.
                                  + var random = Random();
                                  + for (var i = 2; i <= 20; i++) {
                                  + var arguments = [for (var j = 0; j < i; j++) random.nextInt(256)];
                                  + var hashAll = Object.hashAll(arguments);
                                  + var hash = Function.apply(Object.hash, arguments);
                                  + Expect.equals(
                                  + hashAll,
                                  + hash,
                                  + "hashAll and hash disagrees for $i values:\n"
                                  + "$arguments");
                                  + }
                                  index 0000000..3e9e5d8
                                  --- /dev/null
                                  +++ b/tests/corelib_2/object_hash_test.dart
                                  @@ -0,0 +1,134 @@

                                  +// Copyright (c) 2018, 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 "dart:math";

                                  +import "dart:typed_data";
                                  +
                                  +import "package:expect/expect.dart";
                                  +
                                  +main() {
                                  + const nan = double.nan;
                                  + const inf = double.infinity;
                                  +
                                  + int hash1234 = Object.hash(1, 2, 3, 4);
                                  + Expect.type<int>(hash1234);
                                  + Expect.equals(hash1234, Object.hash(1, 2, 3, 4)); // Consistent.
                                  + Expect.equals(hash1234, Object.hashAll([1, 2, 3, 4]));
                                  + Expect.equals(hash1234, Object.hashAll(Uint8List.fromList([1, 2, 3, 4])));
                                  +
                                  + Expect.notEquals(hash1234, Object.hash(1, 2, 3, 4, null));
                                  +
                                  + Expect.equals(Object.hash(1, 2, 3, 4, 5, 6, 7, 8, 9),
                                  + Object.hashAll([1, 2, 3, 4, 5, 6, 7, 8, 9]));
                                  +
                                  +  // Check that we can call `hash` with 2-20 arguments,
                                  + // and they all agree with `hashAll`.
                                  + var random = Random();
                                  + for (var i = 2; i <= 20; i++) {
                                  + var arguments = [for (var j = 0; j < i; j++) random.nextInt(256)];
                                  + var hashAll = Object.hashAll(arguments);
                                  + var hash = Function.apply(Object.hash, arguments);
                                  + Expect.equals(
                                  + hashAll,
                                  + hash,
                                  + "hashAll and hash disagrees for $i values:\n"
                                  + "$arguments");
                                  + }
                                  31 is the latest approved patch-set. The change was submitted with unreviewed changes in the following files: The name of the file: sdk/lib/_internal/js_runtime/lib/js_helper.dart Insertions: 15, Deletions: 13. ``` @@ -822:824, +822:824 @@ - // Fast shortcut for the common case. - if (JS('bool', '# instanceof Array', positionalArguments) && + // Fast path for common cases. + if (positionalArguments is JSArray && @@ -825:827, +825:826 @@ - // Let the compiler know that we did a type-test. - List arguments = (JS('JSArray', '#', positionalArguments)); + JSArray arguments = positionalArguments; @@ -879:881, +878:879 @@ - return _genericApplyFunction2( - function, positionalArguments, namedArguments); + return _generalApplyFunction(function, positionalArguments, namedArguments); @@ -883:884, +881:882 @@ - static _genericApplyFunction2(Function function, List? positionalArguments, + static _generalApplyFunction(Function function, List? positionalArguments, @@ -886:891, +884:887 @@ - bool reusesPositionalArguments = false; - if (positionalArguments != null) { - if (JS('bool', '# instanceof Array', positionalArguments)) { - arguments = JS('JSArray', '#', positionalArguments); - reusesPositionalArguments = true; + if (positionalArguments != null) { + if (positionalArguments is JSArray) { + arguments = positionalArguments; @@ -892:893, +888:889 @@ - arguments = new List.from(positionalArguments); + arguments = List.of(positionalArguments); @@ -938:940, +934:935 @@ - bool acceptsPositionalArguments = - JS('bool', '# instanceof Array', defaultValues); + bool acceptsPositionalArguments = defaultValues is JSArray; @@ -954:961, +949:958 @@ - List missingDefaults = JS('JSArray', '#.slice(#)', defaultValues, - argumentCount - requiredParameterCount); - if (reusesPositionalArguments) { - // Can't reuse arguments list if we modify it. - arguments = List.from(arguments); - } - arguments.addAll(missingDefaults); + if (argumentCount < maxArguments) { + List missingDefaults = JS('JSArray', '#.slice(#)', defaultValues, + argumentCount - requiredParameterCount); + if (identical(arguments, positionalArguments)) { + // Defensive copy to avoid modifying passed-in List. + arguments = List.of(arguments); + } + arguments.addAll(missingDefaults); + } @@ -971:975, +968:974 @@ - List keys = JS('JSArray', r'Object.keys(#)', defaultValues); - if (reusesPositionalArguments) { - arguments = List.from(arguments); - } + if (identical(arguments, positionalArguments)) { + // Defensive copy to avoid modifying passed-in List. + arguments = List.of(arguments); + } + + List keys = JS('JSArray', r'Object.keys(#)', defaultValues); @@ +997:998 @@ + // Named argument with name not accected by function. @@ +2353:2359 @@ + /// Base class for closures with no arguments. + abstract class Closure0Args extends Closure {} + + /// Base class for closures with two positional arguments. + abstract class Closure2Args extends Closure {} + ``` The name of the file: sdk/lib/core/object.dart Insertions: 9, Deletions: 6. ``` @@ -166:167, +166:167 @@ - /// The computed value must be consistent when the function is called + /// The computed value will be consistent when the function is called @@ -171:172, +171:173 @@ - /// over different runs of the same program. + /// over different runs of the same program, + /// or between code run in different isolates of the same program. @@ -174:175, +175:176 @@ - /// and it may depend on values that change per program run + /// and it may depend on values that change on each program execution. @@ -177:178, +178:180 @@ - /// called with a collection containing the actual arguments to this function. + /// called with a collection containing the actual arguments + /// to this function in the same order. @@ -502:503, +504:506 @@ - /// over different runs of the same program. + /// over different runs of the same program, + /// or between code run in different isolates of the same program. @@ -505:506, +508:509 @@ - /// and it may depend on values that change per program run + /// and it may depend on values that change on each program execution. ```

                                  To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                                  Gerrit-Project: sdk
                                  Gerrit-Branch: master
                                  Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                                  Gerrit-Change-Number: 73360
                                  Gerrit-PatchSet: 34
                                  Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                                  Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                                  Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                                  Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                                  Gerrit-Reviewer: Stephen Adams <s...@google.com>
                                  Gerrit-CC: Alexander Markov <alexm...@google.com>
                                  Gerrit-CC: Dan Field <dnf...@google.com>
                                  Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                                  Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                                  Gerrit-CC: Kevin Moore <kev...@google.com>
                                  Gerrit-CC: Ryan Macnak <rma...@google.com>
                                  Gerrit-CC: Sigmund Cherem <sig...@google.com>
                                  Gerrit-CC: Todd Volkert <tvol...@google.com>
                                  Gerrit-CC: Zach Anderson <z...@google.com>
                                  Gerrit-MessageType: merged

                                  Dart CI (Gerrit)

                                  unread,
                                  Jun 25, 2021, 8:08:11 AM6/25/21
                                  to commi...@chromium.org, Lasse R.H. Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Keerti Parthasarathy, Zach Anderson

                                  go/dart-cbuild result: SUCCESS

                                  Details: https://goto.google.com/dart-cbuild/find/83376bf1ee81607a182f8558b242f1c9f4883246

                                  View Change

                                    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                                    Gerrit-Project: sdk
                                    Gerrit-Branch: master
                                    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                                    Gerrit-Change-Number: 73360
                                    Gerrit-PatchSet: 34
                                    Gerrit-Owner: Lasse R.H. Nielsen <l...@google.com>
                                    Gerrit-Reviewer: Lasse R.H. Nielsen <l...@google.com>
                                    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                                    Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                                    Gerrit-Reviewer: Stephen Adams <s...@google.com>
                                    Gerrit-CC: Alexander Markov <alexm...@google.com>
                                    Gerrit-CC: Dan Field <dnf...@google.com>
                                    Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                                    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                                    Gerrit-CC: Kevin Moore <kev...@google.com>
                                    Gerrit-CC: Ryan Macnak <rma...@google.com>
                                    Gerrit-CC: Sigmund Cherem <sig...@google.com>
                                    Gerrit-CC: Todd Volkert <tvol...@google.com>
                                    Gerrit-CC: Zach Anderson <z...@google.com>
                                    Gerrit-Comment-Date: Fri, 25 Jun 2021 12:08:06 +0000

                                    Stephen Adams (Gerrit)

                                    unread,
                                    Jan 9, 2023, 8:53:07 PM1/9/23
                                    to Commit Bot, Lasse Nielsen, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Dart CI, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Keerti Parthasarathy, Zach Anderson

                                    Attention is currently required from: Lasse Nielsen.

                                    View Change

                                    1 comment:

                                    • File sdk/lib/core/object.dart:

                                      • Patch Set #34, Line 563: final int _hashSeed = identityHashCode(Object);

                                        Was the intention here to use the `.hashCode` of the `Type` object for the type `Object`?

                                        I would have expected `Object()` to just use the identity hash code of an instance of `Object`.

                                    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                                    Gerrit-Project: sdk
                                    Gerrit-Branch: master
                                    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                                    Gerrit-Change-Number: 73360
                                    Gerrit-PatchSet: 34
                                    Gerrit-Owner: Lasse Nielsen <l...@google.com>
                                    Gerrit-Reviewer: Commit Bot <commi...@chromium.org>
                                    Gerrit-Reviewer: Lasse Nielsen <l...@google.com>
                                    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                                    Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                                    Gerrit-Reviewer: Stephen Adams <s...@google.com>
                                    Gerrit-CC: Alexander Markov <alexm...@google.com>
                                    Gerrit-CC: Dan Field <dnf...@google.com>
                                    Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                                    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                                    Gerrit-CC: Kevin Moore <kev...@google.com>
                                    Gerrit-CC: Ryan Macnak <rma...@google.com>
                                    Gerrit-CC: Sigmund Cherem <sig...@google.com>
                                    Gerrit-CC: Todd Volkert <tvol...@google.com>
                                    Gerrit-CC: Zach Anderson <z...@google.com>
                                    Gerrit-Attention: Lasse Nielsen <l...@google.com>
                                    Gerrit-Comment-Date: Tue, 10 Jan 2023 01:53:01 +0000
                                    Gerrit-HasComments: Yes
                                    Gerrit-Has-Labels: No
                                    Gerrit-MessageType: comment

                                    Lasse Nielsen (Gerrit)

                                    unread,
                                    Jan 10, 2023, 5:15:37 AM1/10/23
                                    to Commit Bot, dart-dc-te...@google.com, rev...@dartlang.org, Nate Bosch, Dart CI, Stephen Adams, Sigmund Cherem, Ian Hickson, Alexander Markov, Todd Volkert, Dan Field, Kevin Moore, Leaf Petersen, Ryan Macnak, Keerti Parthasarathy, Zach Anderson

                                    View Change

                                    1 comment:

                                    • File sdk/lib/core/object.dart:

                                      • Was the intention here to use the `.hashCode` of the `Type` object for the type `Object`? […]

                                        The intent was to get a new seed for every run. Anything else is secondary.
                                        A `Type` object is also an object.

                                        Looking at it again, any object which doesn't specialized the identity-hash should work (so numbers are out).
                                        Using a constant will likely make it have the same value for isolates in the same isolate group.
                                        Using a `new Object()` would be more likely to give a different hash seed per isolate.
                                        I can't decide whether we want that or not. It probably doesn't matter, but since the goal is to not promise stability, using `new Object()` would be a better fit for that goal.

                                        I'm fine with changing this to practically anything that changes between runs of the same program. Using `Object()` instead of a constant is probably the choice with the most variance.

                                        Could also just do `Random().nextInt(0x3FFFFFFF)`, if we can assume actual randomness from that.

                                    To view, visit change 73360. To unsubscribe, or for help writing mail filters, visit settings.

                                    Gerrit-Project: sdk
                                    Gerrit-Branch: master
                                    Gerrit-Change-Id: Id06fb5b3914bee24713427edbd3b9b7e86f86449
                                    Gerrit-Change-Number: 73360
                                    Gerrit-PatchSet: 34
                                    Gerrit-Owner: Lasse Nielsen <l...@google.com>
                                    Gerrit-Reviewer: Commit Bot <commi...@chromium.org>
                                    Gerrit-Reviewer: Lasse Nielsen <l...@google.com>
                                    Gerrit-Reviewer: Leaf Petersen <le...@google.com>
                                    Gerrit-Reviewer: Nate Bosch <nbo...@google.com>
                                    Gerrit-Reviewer: Stephen Adams <s...@google.com>
                                    Gerrit-CC: Alexander Markov <alexm...@google.com>
                                    Gerrit-CC: Dan Field <dnf...@google.com>
                                    Gerrit-CC: Ian Hickson <ian.h...@gmail.com>
                                    Gerrit-CC: Keerti Parthasarathy <kee...@google.com>
                                    Gerrit-CC: Kevin Moore <kev...@google.com>
                                    Gerrit-CC: Ryan Macnak <rma...@google.com>
                                    Gerrit-CC: Sigmund Cherem <sig...@google.com>
                                    Gerrit-CC: Todd Volkert <tvol...@google.com>
                                    Gerrit-CC: Zach Anderson <z...@google.com>
                                    Gerrit-Comment-Date: Tue, 10 Jan 2023 10:15:28 +0000
                                    Gerrit-HasComments: Yes
                                    Gerrit-Has-Labels: No
                                    Reply all
                                    Reply to author
                                    Forward
                                    0 new messages