[dart2wasm] Fix instantiation closure equality

The test fails in VM, which is reported as #51660.

Change-Id: Icb0f5493f282aa017980478a038b48dd09c5030c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/286933
Reviewed-by: Aske Simon Christensen <askesc@google.com>
Commit-Queue: Ömer Ağacan <omersa@google.com>
This commit is contained in:
Ömer Sinan Ağacan 2023-03-08 15:42:26 +00:00 committed by Commit Queue
parent 11929b6f68
commit 979e8dc932
2 changed files with 48 additions and 18 deletions

View file

@ -1545,15 +1545,18 @@ class Intrinsifier {
// if (f1.vtable == f2.vtable) {
// if (f1 and f2 are instantiations) {
// if (f1.context.inner.vtable == f2.context.inner.vtable) {
// if (identical(f1.context.inner.context,
// f2.context.inner.context)) {
// return typesEqual(f1.context, f2.context);
// if (typesEqual(f1.context, f2.context)) {
// f1 = f1.context.inner;
// f2 = f2.context.inner;
// if (identical(f1, f2)) return true;
// goto outerClosureContext;
// }
// }
// return false;
// }
// if (v1.context is #Top && v2.context is #Top) {
// return identical(v1.context, v2.context);
// outerClosureContext:
// if (f1.context is #Top && f2.context is #Top) {
// return identical(f1.context, f2.context);
// }
// }
// return false;
@ -1600,12 +1603,15 @@ class Intrinsifier {
final instantiationContextBase = w.RefType(
translator.closureLayouter.instantiationContextBaseStruct,
nullable: false);
final instantiationBlock =
final instantiationCheckPassedBlock = b.block();
final notInstantiationBlock =
b.block([], [w.RefType.struct(nullable: false)]);
b.local_get(fun1);
b.struct_get(closureBaseStruct, FieldIndex.closureContext);
b.br_on_cast_fail(instantiationContextBase, instantiationBlock);
b.br_on_cast_fail(instantiationContextBase, notInstantiationBlock);
// Closures are instantiations. Compare inner function vtables to check
// that instantiations are for the same generic function.
@ -1633,15 +1639,7 @@ class Intrinsifier {
b.ref_eq();
b.if_(); // fun1.context.inner.vtable == fun2.context.inner.vtable
// Closures are instantiations of the same function, compare inner
// contexts and types
getInstantiationContextInner(fun1);
b.struct_get(closureBaseStruct, FieldIndex.closureContext);
getInstantiationContextInner(fun2);
b.struct_get(closureBaseStruct, FieldIndex.closureContext);
b.ref_eq();
b.if_(); // fun1.context.inner.context == fun2.context.inner.context
// Inner contexts are equal, compare types
// Closures are instantiations of the same function, compare types
b.local_get(fun1);
b.struct_get(closureBaseStruct, FieldIndex.closureContext);
b.ref_cast(instantiationContextBase);
@ -1656,14 +1654,27 @@ class Intrinsifier {
FieldIndex.vtableInstantiationTypeComparisonFunction);
b.call_ref(translator
.closureLayouter.instantiationClosureTypeComparisonFunctionType);
b.if_();
getInstantiationContextInner(fun1);
b.local_tee(fun1);
getInstantiationContextInner(fun2);
b.local_tee(fun2);
b.ref_eq();
b.if_();
b.i32_const(1); // true
b.return_();
b.end();
b.br(instantiationCheckPassedBlock);
b.end();
b.i32_const(0); // false
b.return_();
b.end(); // fun1.context.inner.context == fun2.context.inner.context
b.end(); // fun1.context.inner.vtable == fun2.context.inner.vtable
// Contexts or inner vtables are not equal
b.i32_const(0); // false
b.return_();
b.end(); // instantiationBlock
b.end(); // notInstantiationBlock
b.drop();
b.end(); // instantiationCheckPassedBlock
// Compare context references. If context of a function has the top type
// then the function is an instance tear-off. Otherwise it's a closure.

View file

@ -0,0 +1,19 @@
// Copyright (c) 2023, 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";
void main() {
int x = 0;
List<void Function<D>()> f = [];
for (int i = 0; i < 2; i++) {
f.add(<E>() {
x++;
});
}
// We may allocate a new function in each iteration, or move the function to
// the outside of the loop. In any case, equality of the instantiations
// should agree with the equality of the instantiated functions.
Expect.equals(f[0] == f[1], f[0]<int> == f[1]<int>);
}