[vm/aot] Partition table selector IDs based on hierarchy connectedness.

Compared to assigning selector IDs purely by name, this improves the
packing of selector rows, reducing the in-memory size of the dispatch
table by typically around 20% (75k memory usage reduction for Flutter
Gallery on ARM64).

It also improved tree shaking of methods called (or rather, not called)
via dispatch table calls, reducing the total snapshot sizes of Flutter
benchmarks by up to 2.1% (Flutter Gallery: ARM 1.8%, ARM64 2.1%).

Fixes https://github.com/dart-lang/sdk/issues/40660
Fixes https://github.com/dart-lang/sdk/issues/41647

Change-Id: Ia9ecfb0818b301bcbad631c377f3910b0a5956de
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/152323
Commit-Queue: Aske Simon Christensen <askesc@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Aske Simon Christensen 2020-06-30 14:03:37 +00:00 committed by commit-bot@chromium.org
parent 34dbe66e7d
commit 0549295eb4
16 changed files with 424 additions and 86 deletions

View file

@ -4,6 +4,7 @@
import 'package:kernel/ast.dart';
import 'utils.dart' show assertx, UnionFind;
import '../../metadata/procedure_attributes.dart';
import '../../metadata/table_selector.dart';
@ -13,51 +14,102 @@ import '../../metadata/table_selector.dart';
class TableSelectorAssigner {
final TableSelectorMetadata metadata = TableSelectorMetadata();
final Map<Name, int> _methodSelectorId = {};
final Map<Name, int> _getterSelectorId = {};
final Map<Name, int> _setterSelectorId = {};
final Map<Class, Map<Name, int>> _getterMemberIds = {};
final Map<Class, Map<Name, int>> _methodOrSetterMemberIds = {};
int _selectorIdForMap(Map<Name, int> map, Member member) {
return map.putIfAbsent(member.name, () => metadata.addSelector());
final UnionFind _unionFind = UnionFind();
List<int> _selectorIdForMemberId;
TableSelectorAssigner(Component component) {
for (Library library in component.libraries) {
for (Class cls in library.classes) {
_memberIdsForClass(cls, getter: false);
_memberIdsForClass(cls, getter: true);
}
}
_selectorIdForMemberId = List(_unionFind.size);
}
Map<Name, int> _memberIdsForClass(Class cls, {bool getter}) {
if (cls == null) return {};
final cache = getter ? _getterMemberIds : _methodOrSetterMemberIds;
// Already computed for this class?
Map<Name, int> memberIds = cache[cls];
if (memberIds != null) return memberIds;
// Merge maps from supertypes.
memberIds = Map.from(_memberIdsForClass(cls.superclass, getter: getter));
for (Supertype impl in cls.implementedTypes) {
_memberIdsForClass(impl.classNode, getter: getter).forEach((name, id) {
final int firstId = memberIds[name];
if (firstId == null) {
memberIds[name] = id;
} else if (firstId != id) {
_unionFind.union(firstId, id);
}
});
}
// Add declared instance members.
for (Member member in cls.members) {
if (member.isInstanceMember) {
bool addToMap;
if (member is Procedure) {
switch (member.kind) {
case ProcedureKind.Method:
addToMap = true;
break;
case ProcedureKind.Operator:
case ProcedureKind.Setter:
addToMap = !getter;
break;
case ProcedureKind.Getter:
addToMap = getter;
break;
default:
throw "Unexpected procedure kind '${member.kind}'";
}
} else if (member is Field) {
addToMap = true;
} else {
throw "Unexpected member kind '${member.runtimeType}'";
}
if (addToMap && !memberIds.containsKey(member.name)) {
memberIds[member.name] = _unionFind.add();
}
}
}
return cache[cls] = memberIds;
}
int _selectorIdForMap(Map<Class, Map<Name, int>> map, Member member) {
int memberId = map[member.enclosingClass][member.name];
if (memberId == null) {
assertx(member is Procedure &&
((identical(map, _getterMemberIds) &&
(member.kind == ProcedureKind.Operator ||
member.kind == ProcedureKind.Setter)) ||
identical(map, _methodOrSetterMemberIds) &&
member.kind == ProcedureKind.Getter));
return ProcedureAttributesMetadata.kInvalidSelectorId;
}
memberId = _unionFind.find(memberId);
int selectorId = _selectorIdForMemberId[memberId];
if (selectorId == null) {
_selectorIdForMemberId[memberId] = selectorId = metadata.addSelector();
}
return selectorId;
}
int methodOrSetterSelectorId(Member member) {
if (member is Procedure) {
switch (member.kind) {
case ProcedureKind.Method:
case ProcedureKind.Operator:
return _selectorIdForMap(_methodSelectorId, member);
case ProcedureKind.Setter:
return _selectorIdForMap(_setterSelectorId, member);
case ProcedureKind.Getter:
return ProcedureAttributesMetadata.kInvalidSelectorId;
default:
throw "Unexpected procedure kind '${member.kind}'";
}
}
if (member is Field) {
return _selectorIdForMap(_setterSelectorId, member);
}
throw "Unexpected member kind '${member.runtimeType}'";
return _selectorIdForMap(_methodOrSetterMemberIds, member);
}
int getterSelectorId(Member member) {
if (member is Procedure) {
switch (member.kind) {
case ProcedureKind.Getter:
case ProcedureKind.Method:
return _selectorIdForMap(_getterSelectorId, member);
case ProcedureKind.Operator:
case ProcedureKind.Setter:
return ProcedureAttributesMetadata.kInvalidSelectorId;
default:
throw "Unexpected procedure kind '${member.kind}'";
}
}
if (member is Field) {
return _selectorIdForMap(_getterSelectorId, member);
}
throw "Unexpected member kind '${member.runtimeType}'";
return _selectorIdForMap(_getterMemberIds, member);
}
void registerMethodOrSetterCall(Member member, bool calledOnNull) {

View file

@ -163,7 +163,7 @@ class AnnotateKernel extends RecursiveVisitor<Null> {
_procedureAttributesMetadata =
new ProcedureAttributesMetadataRepository(),
_tableSelectorMetadata = new TableSelectorMetadataRepository(),
_tableSelectorAssigner = new TableSelectorAssigner(),
_tableSelectorAssigner = new TableSelectorAssigner(component),
_unboxingInfoMetadata = new UnboxingInfoMetadataRepository(),
_intClass = _typeFlowAnalysis.environment.coreTypes.intClass {
component.addMetadataRepository(_inferredTypeMetadata);

View file

@ -261,6 +261,48 @@ int findOverlap(List list, List sublist) {
return list.length;
}
/// A Union-Find data structure over integers.
class UnionFind {
// Negative weight if root, parent index otherwise.
final List<int> _elements;
UnionFind([int initialSize = 0])
: _elements = List<int>.filled(initialSize, -1, growable: true);
/// Add a new singleton set.
int add() {
int id = _elements.length;
_elements.add(-1);
return id;
}
/// Find the canonical element for the set containing the given element.
/// Two elements belonging to the same set have the same canonical element.
int find(int id) {
return _elements[id] < 0 ? id : _elements[id] = find(_elements[id]);
}
/// Merge the sets containing the given elements.
void union(int id1, int id2) {
id1 = find(id1);
id2 = find(id2);
if (id1 == id2) return;
final int w1 = _elements[id1];
final int w2 = _elements[id2];
assertx(w1 < 0 && w2 < 0);
if (w1 < w2) {
_elements[id1] += w2;
_elements[id2] = id1;
} else {
_elements[id2] += w1;
_elements[id1] = id2;
}
}
/// Total number of elements in the sets.
int get size => _elements.length;
}
const nullabilitySuffix = {
Nullability.legacy: '*',
Nullability.nullable: '?',

View file

@ -52,13 +52,13 @@ class DeepCaller2 extends core::Object {
synthetic constructor •() → self::DeepCaller2*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method barL1([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method barL1([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(dd);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method barL2([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method barL2([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(dd);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method barL3([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method barL3([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(dd);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method barL4([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method barL4([@vm.inferred-type.metadata=#lib::D] self::D* dd) → dynamic
return [@vm.direct-call.metadata=#lib::D.field2] [@vm.inferred-type.metadata=!] dd.{self::D::field2};
}
[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;

View file

@ -32,11 +32,11 @@ class B extends core::Object {
synthetic constructor •() → self::B*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → dynamic
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method foo() → dynamic
return new self::T1::•();
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method bar() → dynamic
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method bar() → dynamic
return new self::T2::•();
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method bazz() → dynamic
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method bazz() → dynamic
return new self::T3::•();
}
[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;

View file

@ -36,13 +36,13 @@ class DeepCaller2 extends core::Object {
synthetic constructor •() → self::DeepCaller2*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method barL1([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] method barL1([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2.barL2] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL2}(aa);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method barL2([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:15,getterSelectorId:16] method barL2([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2.barL3] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL3}(aa);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9,getterSelectorId:10] method barL3([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:17,getterSelectorId:18] method barL3([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2.barL4] [@vm.inferred-type.metadata=! (skip check)] this.{self::DeepCaller2::barL4}(aa);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method barL4([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:19,getterSelectorId:20] method barL4([@vm.inferred-type.metadata=#lib::A?] self::A* aa) → dynamic
return [@vm.direct-call.metadata=#lib::A.field2??] [@vm.inferred-type.metadata=!] aa.{self::A::field2};
}
[@vm.inferred-type.metadata=dart.core::Null? (value: null)]static field core::Function* unknown;

View file

@ -104,7 +104,7 @@ class H extends core::Object {
synthetic constructor •() → self::H*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo({[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic left = #C1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic right = #C1}) → dynamic
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8,getterSelectorId:9] method foo({[@vm.inferred-type.metadata=dart.core::_Smi (value: 1)] dynamic left = #C1, [@vm.inferred-type.metadata=dart.core::_Smi (value: 2)] dynamic right = #C1}) → dynamic
return new self::T6::•();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] method noSuchMethod(core::Invocation* invocation) → dynamic {
return new self::T7::•();

View file

@ -55,20 +55,20 @@ class FooKeep extends pro::GeneratedMessage {
@#C10
static method create() → self::FooKeep*
return new self::FooKeep::_();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] @#C12
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] @#C12
get barKeep() → self::BarKeep*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep*>(0);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5] @#C12
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] @#C12
set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(1, v);
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6] @#C14
get mapKeep() → core::Map<core::String*, self::BarKeep*>*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] @#C16
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C16
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8] @#C16
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C16
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
}
@ -95,10 +95,10 @@ class BarKeep extends pro::GeneratedMessage {
@#C10
static method create() → self::BarKeep*
return new self::BarKeep::_();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] @#C12
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] @#C12
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8] @#C12
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] @#C12
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
}

View file

@ -92,7 +92,7 @@ class BarKeep extends pro::GeneratedMessage {
@#C11
static method create() → self::BarKeep*
return new self::BarKeep::_();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] @#C13
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:12] @#C13
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
}

View file

@ -101,11 +101,11 @@ class BarKeep extends pro::GeneratedMessage {
@#C11
static method create() → self::BarKeep*
return new self::BarKeep::_();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6] @#C13
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9] @#C13
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:9] @#C25
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10] @#C25
set bDrop([@vm.inferred-type.metadata=dart.core::_Smi (value: 4)] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(1, v);
}
@ -157,7 +157,7 @@ class ZopDrop extends pro::GeneratedMessage {
@#C11
static method create() → self::ZopDrop*
return new self::ZopDrop::_();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:10] @#C13
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11] @#C13
set aDrop([@vm.inferred-type.metadata=dart.core::_Smi (value: 3)] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
}

View file

@ -59,20 +59,20 @@ class FooKeep extends pro::GeneratedMessage {
@#C10
static method create() → self::FooKeep*
return new self::FooKeep::_();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:4] @#C12
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] @#C12
get barKeep() → self::BarKeep*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getN] [@vm.inferred-type.metadata=foo.pb.dart::BarKeep? (skip check)] this.{pro::GeneratedMessage::$_getN}<self::BarKeep*>(0);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5] @#C12
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] @#C12
set barKeep([@vm.inferred-type.metadata=foo.pb.dart::BarKeep] self::BarKeep* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.setField] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::setField}(1, v);
}
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:6] @#C14
get mapKeep() → core::Map<core::String*, self::BarKeep*>*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getMap] [@vm.inferred-type.metadata=! (skip check)] this.{pro::GeneratedMessage::$_getMap}<core::String*, self::BarKeep*>(2);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] @#C16
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C16
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(4);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8] @#C16
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] @#C16
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi (value: 43)] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(4, v);
}
@ -99,10 +99,10 @@ class BarKeep extends pro::GeneratedMessage {
@#C10
static method create() → self::BarKeep*
return new self::BarKeep::_();
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:7] @#C12
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] @#C12
get aKeep() → core::int*
return [@vm.direct-call.metadata=protobuf::GeneratedMessage.$_getIZ] [@vm.inferred-type.metadata=int (skip check)] this.{pro::GeneratedMessage::$_getIZ}(0);
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:8] @#C12
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] @#C12
set aKeep([@vm.inferred-type.metadata=dart.core::_Smi] core::int* v) → void {
[@vm.direct-call.metadata=protobuf::GeneratedMessage.$_setSignedInt32] [@vm.inferred-type.metadata=!? (skip check)] this.{pro::GeneratedMessage::$_setSignedInt32}(0, v);
}

View file

@ -38,27 +38,27 @@ class T2 extends core::Object {
}
}
class A2 extends core::Object {
[@vm.inferred-type.metadata=#lib::T2?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] field dynamic foo = null;
[@vm.inferred-type.metadata=#lib::T2?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:13,getterSelectorId:14] field dynamic foo = null;
synthetic constructor •() → self::A2*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=#lib::T2?] dynamic a6 = #C1]) → void {
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:11,getterSelectorId:12] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=#lib::T2?] dynamic a6 = #C1]) → void {
[@vm.direct-call.metadata=#lib::A2.foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A2::foo} = a6;
}
}
abstract class B2Base extends core::Object {
[@vm.inferred-type.metadata=#lib::A2] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:12,getterSelectorId:13] field dynamic _aa = new self::A2::•();
[@vm.inferred-type.metadata=#lib::A2] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:16,getterSelectorId:17] field dynamic _aa = new self::A2::•();
synthetic constructor •() → self::B2Base*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:11] get aa2() → dynamic
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,getterSelectorId:15] get aa2() → dynamic
return [@vm.direct-call.metadata=#lib::B2Base._aa] [@vm.inferred-type.metadata=#lib::A2] this.{self::B2Base::_aa};
}
class B2 extends self::B2Base {
synthetic constructor •() → self::B2*
: super self::B2Base::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:14,getterSelectorId:15] method doSuperCall() → void {
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:18,getterSelectorId:19] method doSuperCall() → void {
[@vm.call-site-attributes.metadata=receiverType:dynamic] [@vm.direct-call.metadata=#lib::A2.call] [@vm.inferred-type.metadata=!? (receiver not int)] [@vm.inferred-type.metadata=#lib::A2] super.{self::B2Base::aa2}.call(1, 2, 3, 4, 5, new self::T2::•());
}
}
@ -66,21 +66,21 @@ class T3 extends core::Object {
synthetic constructor •() → self::T3*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:16,getterSelectorId:17] method doTest3() → void {
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:20,getterSelectorId:21] method doTest3() → void {
self::ok = true;
}
}
class A3 extends core::Object {
[@vm.inferred-type.metadata=#lib::T3?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] field dynamic foo = null;
[@vm.inferred-type.metadata=#lib::T3?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:24,getterSelectorId:25] field dynamic foo = null;
synthetic constructor •() → self::A3*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=#lib::T3?] dynamic a7 = #C1]) → void {
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:22,getterSelectorId:23] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=#lib::T3?] dynamic a7 = #C1]) → void {
[@vm.direct-call.metadata=#lib::A3.foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A3::foo} = a7;
}
}
class B3 extends core::Object {
[@vm.inferred-type.metadata=#lib::A3] [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:18,getterSelectorId:19] field self::A3* aa3 = new self::A3::•();
[@vm.inferred-type.metadata=#lib::A3] [@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:26,getterSelectorId:27] field self::A3* aa3 = new self::A3::•();
synthetic constructor •() → self::B3*
: super core::Object::•()
;
@ -89,25 +89,25 @@ class T4 extends core::Object {
synthetic constructor •() → self::T4*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:20,getterSelectorId:21] method doTest4() → void {
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:28,getterSelectorId:29] method doTest4() → void {
self::ok = true;
}
}
class A4 extends core::Object {
[@vm.inferred-type.metadata=#lib::T4?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] field dynamic foo = null;
[@vm.inferred-type.metadata=#lib::T4?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:32,getterSelectorId:33] field dynamic foo = null;
synthetic constructor •() → self::A4*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a7 = #C1, [@vm.inferred-type.metadata=#lib::T4?] dynamic a8 = #C1]) → void {
[@vm.procedure-attributes.metadata=getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:30,getterSelectorId:31] method call([dynamic a1 = #C1, dynamic a2 = #C1, dynamic a3 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a4 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a5 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a6 = #C1, [@vm.inferred-type.metadata=dart.core::_Smi?] dynamic a7 = #C1, [@vm.inferred-type.metadata=#lib::T4?] dynamic a8 = #C1]) → void {
[@vm.direct-call.metadata=#lib::A4.foo] [@vm.inferred-type.metadata=!? (skip check)] this.{self::A4::foo} = a8;
}
}
class B4 extends core::Object {
[@vm.inferred-type.metadata=#lib::A4] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:12,getterSelectorId:13] field dynamic _aa = new self::A4::•();
[@vm.inferred-type.metadata=#lib::A4] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:35,getterSelectorId:36] field dynamic _aa = new self::A4::•();
synthetic constructor •() → self::B4*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,getterSelectorId:22] get aa4() → dynamic
[@vm.procedure-attributes.metadata=hasThisUses:false,hasTearOffUses:false,getterSelectorId:34] get aa4() → dynamic
return [@vm.direct-call.metadata=#lib::B4._aa] [@vm.inferred-type.metadata=#lib::A4] this.{self::B4::_aa};
}
[@vm.inferred-type.metadata=dart.core::bool?]static field core::bool* ok;

View file

@ -0,0 +1,92 @@
// Copyright (c) 2020, 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.
// Validate the partitioning of methods for selector ID assignment.
// Two members should get the same selector ID(s) iff they have the same name
// and are defined in classes with the same number.
class X {}
class A1 {
void foo() {
print("A1");
}
}
class B1 extends A1 {}
class C1 extends B1 {
void foo() {
print("C1");
}
}
class A2 {
void foo() {
print("A2");
}
}
class B2 extends A2 implements X {
void foo() {
print("B2");
}
}
abstract class A3 {
void foo();
}
class B3 extends A3 implements X {
void foo() {
print("B3");
}
}
class C3 implements A3 {
void foo() {
print("C3");
}
}
class A4 {
void foo() {
print("A4");
}
}
class B4 {
void foo() {
print("B4");
}
}
class C4 {
void foo() {
print("C4");
}
}
class D4 extends A4 implements B4 {
void foo() {
print("D4");
}
}
class E4 extends C4 implements B4 {}
main() {
List<A1> x1 = [A1(), B1(), C1()];
for (A1 o in x1) o.foo();
List<A2> x2 = [A2(), B2()];
for (A2 o in x2) o.foo();
List<A3> x3 = [B3(), C3()];
for (A3 o in x3) o.foo();
List<A4> x4 = [A4(), D4()];
for (A4 o in x4) o.foo();
List<B4> y4 = [B4(), D4(), E4()];
for (B4 o in y4) o.foo();
List<C4> z4 = [C4(), E4()];
for (C4 o in z4) o.foo();
}

View file

@ -0,0 +1,152 @@
library #lib;
import self as self;
import "dart:core" as core;
abstract class X extends core::Object {
}
class A1 extends core::Object {
synthetic constructor •() → self::A1*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → void {
core::print("A1");
}
}
class B1 extends self::A1 {
synthetic constructor •() → self::B1*
: super self::A1::•()
;
}
class C1 extends self::B1 {
synthetic constructor •() → self::C1*
: super self::B1::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → void {
core::print("C1");
}
}
class A2 extends core::Object {
synthetic constructor •() → self::A2*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method foo() → void {
core::print("A2");
}
}
class B2 extends self::A2 implements self::X {
synthetic constructor •() → self::B2*
: super self::A2::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method foo() → void {
core::print("B2");
}
}
abstract class A3 extends core::Object {
synthetic constructor •() → self::A3*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] abstract method foo() → void;
}
class B3 extends self::A3 implements self::X {
synthetic constructor •() → self::B3*
: super self::A3::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method foo() → void {
core::print("B3");
}
}
class C3 extends core::Object implements self::A3 {
synthetic constructor •() → self::C3*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method foo() → void {
core::print("C3");
}
}
class A4 extends core::Object {
synthetic constructor •() → self::A4*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method foo() → void {
core::print("A4");
}
}
class B4 extends core::Object {
synthetic constructor •() → self::B4*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method foo() → void {
core::print("B4");
}
}
class C4 extends core::Object {
synthetic constructor •() → self::C4*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method foo() → void {
core::print("C4");
}
}
class D4 extends self::A4 implements self::B4 {
synthetic constructor •() → self::D4*
: super self::A4::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method foo() → void {
core::print("D4");
}
}
class E4 extends self::C4 implements self::B4 {
synthetic constructor •() → self::E4*
: super self::C4::•()
;
}
static method main() → dynamic {
core::List<self::A1*>* x1 = <self::A1*>[new self::A1::•(), new self::B1::•(), new self::C1::•()];
{
core::Iterator<self::A1*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A1*>] x1.{core::Iterable::iterator};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
self::A1* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current};
o.{self::A1::foo}();
}
}
core::List<self::A2*>* x2 = <self::A2*>[new self::A2::•(), new self::B2::•()];
{
core::Iterator<self::A2*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A2*>] x2.{core::Iterable::iterator};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
self::A2* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current};
o.{self::A2::foo}();
}
}
core::List<self::A3*>* x3 = <self::A3*>[new self::B3::•(), new self::C3::•()];
{
core::Iterator<self::A3*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A3*>] x3.{core::Iterable::iterator};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
self::A3* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current};
o.{self::A3::foo}();
}
}
core::List<self::A4*>* x4 = <self::A4*>[new self::A4::•(), new self::D4::•()];
{
core::Iterator<self::A4*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::A4*>] x4.{core::Iterable::iterator};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
self::A4* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current};
o.{self::A4::foo}();
}
}
core::List<self::B4*>* y4 = <self::B4*>[new self::B4::•(), new self::D4::•(), new self::E4::•()];
{
core::Iterator<self::B4*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::B4*>] y4.{core::Iterable::iterator};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
self::B4* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current};
o.{self::B4::foo}();
}
}
core::List<self::C4*>* z4 = <self::C4*>[new self::C4::•(), new self::E4::•()];
{
core::Iterator<self::C4*>* :sync-for-iterator = [@vm.direct-call.metadata=dart.core::_GrowableList.iterator] [@vm.inferred-type.metadata=dart._internal::ListIterator<#lib::C4*>] z4.{core::Iterable::iterator};
for (; [@vm.direct-call.metadata=dart._internal::ListIterator.moveNext] [@vm.inferred-type.metadata=dart.core::bool (skip check)] :sync-for-iterator.{core::Iterator::moveNext}(); ) {
self::C4* o = [@vm.direct-call.metadata=dart._internal::ListIterator.current] :sync-for-iterator.{core::Iterator::current};
[@vm.direct-call.metadata=#lib::C4.foo??] [@vm.inferred-type.metadata=!? (skip check)] o.{self::C4::foo}();
}
}
}

View file

@ -20,16 +20,16 @@ abstract class Base extends core::Object {
synthetic constructor •() → self::Base*
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method foo() → core::int*
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasNonThisUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method foo() → core::int*
return _in::unsafeCast<core::int*>([@vm.direct-call.metadata=dart.core::_IntegerImplementation.+] [@vm.inferred-type.metadata=int (skip check)] 3.{core::num::+}(_in::unsafeCast<core::num>([@vm.direct-call.metadata=#lib::B.foo] [@vm.inferred-type.metadata=int? (receiver not int)] [@vm.inferred-type.metadata=#lib::B] self::knownResult().foo())));
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] method doCall(dynamic x) → core::int*
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method doCall(dynamic x) → core::int*
return [@vm.call-site-attributes.metadata=receiverType:dynamic] x.call() as{TypeError,ForDynamic} core::int*;
}
class TearOffSuperMethod extends self::Base {
synthetic constructor •() → self::TearOffSuperMethod*
: super self::Base::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:5,getterSelectorId:6] method bar() → core::int*
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:7,getterSelectorId:8] method bar() → core::int*
return [@vm.direct-call.metadata=#lib::Base.doCall] [@vm.inferred-type.metadata=int? (skip check)] this.{self::Base::doCall}(super.{self::Base::foo});
}
[@vm.inferred-type.metadata=#lib::B?]static field self::A* aa = new self::B::•();

View file

@ -12,11 +12,11 @@ class A extends core::Object {
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3] set /*isNullableByDefault*/ x(core::int value) → void;
}
class B extends core::Object {
[@vm.inferred-type.metadata=dart.core::_Smi?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3,getterSelectorId:4] late final [setter] field core::int x;
[@vm.inferred-type.metadata=dart.core::_Smi?] [@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasNonThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:6,getterSelectorId:7] late final [setter] field core::int x;
synthetic constructor •() → self::B
: super core::Object::•()
;
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:1,getterSelectorId:2] method use() → dynamic {
[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:4,getterSelectorId:5] method use() → dynamic {
[@vm.direct-call.metadata=#lib::B.x] [@vm.inferred-type.metadata=!? (skip check)] this.{self::B::x} = 3;
}
}