Skip to content

Commit 59e00e6

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm,bytecode] Fix canonicalization of type arguments of recursive types
Previously, it was possible that type arguments of recursive types are shared between unrelated recursive types if they have exactly the same shape (e.g. Foo extends Base<Foo> and Bar extends Base<Bar> both have type arguments <recursive-ref#0>). Fixes ffi/structs_test in AOT+bytecode mode. Change-Id: I516bc34c3b5797d76e1bf087ac3c8f075f1b6424 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/120380 Reviewed-by: Régis Crelier <regis@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
1 parent 4f309f0 commit 59e00e6

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

pkg/vm/lib/bytecode/object_table.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,16 @@ class _TypeArgumentsHandle extends ObjectHandle {
11601160
@override
11611161
ObjectKind get kind => ObjectKind.kTypeArguments;
11621162

1163+
@override
1164+
bool get isCacheable {
1165+
for (var arg in args) {
1166+
if (!arg.isCacheable) {
1167+
return false;
1168+
}
1169+
}
1170+
return true;
1171+
}
1172+
11631173
@override
11641174
void writeContents(BufferedWriter writer) {
11651175
writer.writePackedList(args);
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:kernel/ast.dart';
6+
import 'package:kernel/core_types.dart' show CoreTypes;
7+
import 'package:kernel/testing/mock_sdk_component.dart';
8+
import 'package:test/test.dart';
9+
import 'package:expect/expect.dart';
10+
import 'package:vm/bytecode/object_table.dart';
11+
12+
main() {
13+
Library lib1;
14+
Library lib2;
15+
CoreTypes coreTypes;
16+
Supertype objectSupertype;
17+
ObjectTable objectTable;
18+
19+
Class addClass(Library lib, String name,
20+
[List<TypeParameter> typeParameters = const []]) {
21+
Class cls = new Class(
22+
name: name, supertype: objectSupertype, typeParameters: typeParameters);
23+
cls.parent = lib;
24+
lib.addClass(cls);
25+
return cls;
26+
}
27+
28+
setUp(() {
29+
// Start with mock SDK libraries.
30+
Component component = createMockSdkComponent();
31+
coreTypes = new CoreTypes(component);
32+
objectSupertype = coreTypes.objectClass.asThisSupertype;
33+
34+
// Add test libraries.
35+
lib1 = new Library(Uri.parse('org-dartlang:///test1.dart'), name: 'lib1');
36+
lib1.parent = component;
37+
component.libraries.add(lib1);
38+
39+
lib2 = new Library(Uri.parse('org-dartlang:///test2.dart'), name: 'lib2');
40+
lib2.parent = component;
41+
component.libraries.add(lib2);
42+
43+
objectTable = new ObjectTable();
44+
});
45+
46+
tearDown(() {});
47+
48+
test('libraries', () {
49+
final h1 = objectTable.getHandle(lib1);
50+
final h2 = objectTable.getHandle(lib2);
51+
Expect.notEquals(h1, h2);
52+
Expect.identical(h1, objectTable.getHandle(lib1));
53+
Expect.identical(h2, objectTable.getHandle(lib2));
54+
Expect.equals(true, h1.isCacheable);
55+
Expect.equals(true, h2.isCacheable);
56+
Expect.equals(false, h1.shouldBeIncludedIntoIndexTable); // 2 uses
57+
Expect.identical(h1, objectTable.getHandle(lib1));
58+
Expect.equals(true, h1.shouldBeIncludedIntoIndexTable); // 3 uses
59+
});
60+
61+
test('classes', () {
62+
final Class c1 = addClass(lib1, 'A');
63+
final Class c2 = addClass(lib1, 'B');
64+
final Class c3 = addClass(lib2, 'A');
65+
final h1 = objectTable.getHandle(c1);
66+
final h2 = objectTable.getHandle(c2);
67+
final h3 = objectTable.getHandle(c3);
68+
Expect.notEquals(h1, h2);
69+
Expect.notEquals(h1, h3);
70+
Expect.notEquals(h2, h3);
71+
Expect.identical(h1, objectTable.getHandle(c1));
72+
Expect.identical(h2, objectTable.getHandle(c2));
73+
Expect.identical(h3, objectTable.getHandle(c3));
74+
Expect.equals(true, h1.isCacheable);
75+
Expect.equals(true, h2.isCacheable);
76+
Expect.equals(true, h3.isCacheable);
77+
final lib1h = objectTable.getHandle(lib1);
78+
final lib2h = objectTable.getHandle(lib2);
79+
Expect.equals(true, lib1h.shouldBeIncludedIntoIndexTable); // 3 uses
80+
Expect.equals(false, lib2h.shouldBeIncludedIntoIndexTable); // 2 uses
81+
});
82+
83+
test('simple-types', () {
84+
final h1a = objectTable.getHandle(new InterfaceType(coreTypes.intClass));
85+
final h1b = objectTable.getHandle(new InterfaceType(coreTypes.intClass));
86+
final h2a = objectTable.getHandle(const DynamicType());
87+
final h2b = objectTable.getHandle(new DynamicType());
88+
Expect.identical(h1a, h1b);
89+
Expect.identical(h2a, h2b);
90+
Expect.notEquals(h1a, h2a);
91+
Expect.equals(true, h1a.isCacheable);
92+
Expect.equals(true, h2a.isCacheable);
93+
Expect.equals(false, h1a.shouldBeIncludedIntoIndexTable); // 2 uses
94+
objectTable.getHandle(new InterfaceType(
95+
coreTypes.listClass, [new InterfaceType(coreTypes.intClass)]));
96+
Expect.equals(true, h1a.shouldBeIncludedIntoIndexTable); // 3 uses
97+
});
98+
99+
test('recursive-types', () {
100+
final base = addClass(lib1, "Base", [new TypeParameter("T")]);
101+
final derived1 = addClass(lib1, "Derived");
102+
derived1.supertype = new Supertype(base, [new InterfaceType(derived1)]);
103+
final derived2 = addClass(lib2, "Derived");
104+
derived2.supertype = new Supertype(base, [new InterfaceType(derived2)]);
105+
final h1a = objectTable.getHandle(new InterfaceType(derived1));
106+
final h1b = objectTable.getHandle(new InterfaceType(derived1));
107+
final h2a = objectTable.getHandle(new InterfaceType(derived2));
108+
final h2b = objectTable.getHandle(new InterfaceType(derived2));
109+
Expect.identical(h1a, h1b);
110+
Expect.identical(h2a, h2b);
111+
Expect.notEquals(h1a, h2a);
112+
Expect.equals(true, h1a.isCacheable);
113+
Expect.equals(true, h2a.isCacheable);
114+
final typeArgs1 = (h1a as dynamic).typeArgs;
115+
final typeArgs2 = (h2a as dynamic).typeArgs;
116+
Expect.equals(false, typeArgs1.isCacheable);
117+
Expect.equals(false, typeArgs2.isCacheable);
118+
});
119+
}

0 commit comments

Comments
 (0)