[dart2js] Add member applies to sets and builder.

Will be used during call hierarchy analysis in combination with explicit call graph construction.

Currently typemasks do not support the `difference` operation and so we cannot fully narrow the type cones based on the call hierarchy. An implementation is included here of the applies-to set with subtraction of overrides.

Change-Id: I3f6c113787a4d26e9751added482791365c12832
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/259560
Reviewed-by: Mayank Patke <fishythefish@google.com>
Commit-Queue: Nate Biggs <natebiggs@google.com>
This commit is contained in:
Nate Biggs 2022-09-16 02:54:10 +00:00 committed by Commit Bot
parent 4e9cd784ab
commit 433c9eb4ee
4 changed files with 60 additions and 0 deletions

View file

@ -0,0 +1,54 @@
// Copyright (c) 2022, 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:compiler/src/common/names.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/inferrer/abstract_value_domain.dart';
import 'package:compiler/src/world_interfaces.dart';
import 'package:compiler/src/universe/selector.dart';
class MemberAppliesTo {
final MemberEntity member;
AbstractValue mask;
MemberAppliesTo(this.member, this.mask);
@override
String toString() => 'MemberAppliesTo($member:$mask)';
}
class MemberAppliesToBuilder {
final JClosedWorld _closedWorld;
final Map<Selector, Iterable<MemberAppliesTo>> _memberSetsBySelector = {};
final Map<Selector, List<MemberEntity>> _membersBySelector = {};
MemberAppliesToBuilder(this._closedWorld) {
for (final member in _closedWorld.liveInstanceMembers) {
if (member.isFunction || member.isGetter || member.isSetter) {
(_membersBySelector[Selector.fromElement(member)] ??= []).add(member);
}
}
}
Iterable<MemberAppliesTo> _buildSets(Selector selector) {
final List<MemberAppliesTo> memberSets = [];
final members = _membersBySelector.remove(selector);
if (members == null) {
return selector == Selectors.noSuchMethod_
? const []
: forSelector(Selectors.noSuchMethod_);
}
for (final member in members) {
// TODO(fishythefish): Use type cone mask here.
final mask = _closedWorld.abstractValueDomain
.createNonNullSubclass(member.enclosingClass!);
final memberSet = MemberAppliesTo(member, mask);
memberSets.add(memberSet);
}
return memberSets;
}
Iterable<MemberAppliesTo> forSelector(Selector selector) =>
_memberSetsBySelector[selector] ??= _buildSets(selector);
}

View file

@ -65,6 +65,7 @@ class JsClosedWorld implements JClosedWorld {
// TODO(johnniwinther): Can this be derived from [ClassSet]s?
final Set<ClassEntity> implementedClasses;
@override
final Set<MemberEntity> liveInstanceMembers;
/// Members that are written either directly or through a setter selector.

View file

@ -69,6 +69,9 @@ abstract class JClosedWorld implements interfaces.JClosedWorld {
Iterable<MemberEntity> get processedMembers;
@override
Iterable<MemberEntity> get liveInstanceMembers;
/// Returns the set of interfaces passed as type arguments to the internal
/// `extractTypeArguments` function.
Set<ClassEntity> get extractTypeArgumentsInterfacesNewRti;

View file

@ -29,6 +29,8 @@ abstract class JClosedWorld implements World {
AnnotationsData get annotationsData;
Iterable<MemberEntity> get liveInstanceMembers;
bool isUsedAsMixin(ClassEntity cls);
bool includesClosureCall(Selector selector, AbstractValue? receiver);