Files
sdk/tests/web/wasm/closure_hash_code_test.dart
T
Ömer Sinan Ağacan 2da70a8d9e [dart2wasm] Improve closure hash codes
Currently hash code for a closure is the hash code of it's runtime type.

This causes a lot hash collisions in some apps and cause performance
issues.

With this patch we now use captured objects in closures when calculating
hash codes.

The hash codes are now:

- For tear-offs:

    mix(receiver hash, closure runtime type hash)

- For instantiations:

    mix(instantiated closure hash,
        hashes of captured types)

  Note that an instantiation can be of a tear-off, in which case
  "instantiated closure hash" will calculate the tear-off hash as above.

- For others (function literals, static functions), the hash is the
  identity hash.

Fixes #54912.

CoreLibraryReviewExempt: Mark private corelib function as entry-point in Wasm
Change-Id: I6a123fdc690237f543bb8bf832f0f8119d013a55
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/353162
Reviewed-by: Martin Kustermann <kustermann@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
2024-02-21 14:44:20 +00:00

67 lines
2.3 KiB
Dart

// Copyright (c) 2024, 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 'package:expect/expect.dart';
// Check closure (tear-off, instantiation, static) equality, hash code, and
// identities.
//
// In principle principle unequal objects can have the same hash code, but it's
// very unlikely in this test. So we also check that if two closures are not
// equal then they should have different hash codes.
void staticFunction() {}
void genericStaticFunction<T>(T t) {}
class C {
void memberFunction() {}
void genericMemberFunction<T>(T t) {}
}
void main() {
var functionExpression = () {};
var genericFunctionExpression = <T>(T t) {};
check(functionExpression, functionExpression, equal: true, isIdentical: true);
check(genericFunctionExpression, genericFunctionExpression,
equal: true, isIdentical: true);
check(genericFunctionExpression<int>, genericFunctionExpression<int>,
equal: true, isIdentical: false);
check(() {}, () {}, equal: false, isIdentical: false);
check(staticFunction, staticFunction, equal: true, isIdentical: true);
check(genericStaticFunction, genericStaticFunction,
equal: true, isIdentical: true);
check(genericStaticFunction<int>, genericStaticFunction<int>,
equal: true, isIdentical: true);
final o1 = C();
check(o1.memberFunction, o1.memberFunction, equal: true, isIdentical: false);
check(o1.genericMemberFunction, o1.genericMemberFunction,
equal: true, isIdentical: false);
check(o1.genericMemberFunction<int>, o1.genericMemberFunction<int>,
equal: true, isIdentical: false);
final o2 = C();
check(o1.memberFunction, o2.memberFunction, equal: false, isIdentical: false);
check(o1.genericMemberFunction, o2.genericMemberFunction,
equal: false, isIdentical: false);
check(o1.genericMemberFunction<int>, o2.genericMemberFunction<int>,
equal: false, isIdentical: false);
}
void check(Object? o1, Object? o2,
{required bool equal, required bool isIdentical}) {
(equal ? Expect.equals : Expect.notEquals)(o1, o2);
(equal ? Expect.equals : Expect.notEquals)(o1.hashCode, o2.hashCode);
(isIdentical ? Expect.isTrue : Expect.isFalse)(identical(o1, o2));
}