| Index: pkg/compiler/lib/src/ssa/types_propagation.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
|
| index 82c5f8bda4225abe9bbf7d8652298609fc13caff..4f3e7eec8f94605553b1d5fb0e39d066f961fe10 100644
|
| --- a/pkg/compiler/lib/src/ssa/types_propagation.dart
|
| +++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
|
| @@ -314,17 +314,6 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| });
|
| }
|
|
|
| - /// Stores a set of valid target classes for the receiver of a given
|
| - /// instruction.
|
| - final _validTargetClasses = new Map<HInstruction, _ClassSet>();
|
| -
|
| - /// Filters out (i.e. returns false for) instances of `noSuchMethod` that are
|
| - /// known to not forward but throw.
|
| - bool _excludeNoSuchMethod(Element element) {
|
| - return element.name != Compiler.NO_SUCH_METHOD ||
|
| - !backend.isDefaultNoSuchMethodImplementation(element);
|
| - }
|
| -
|
| TypeMask visitInvokeDynamic(HInvokeDynamic instruction) {
|
| if (instruction.isInterceptedCall) {
|
| // We cannot do the following optimization now, because we have
|
| @@ -352,20 +341,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| // Try to specialize the receiver after this call.
|
| if (receiver.dominatedUsers(instruction).length != 1
|
| && !selector.isClosureCall) {
|
| - var targets = compiler.world.allFunctions.query(selector);
|
| - _ClassSet classes = new _ClassSet.from(targets, classWorld,
|
| - filter: _excludeNoSuchMethod);
|
| - _ClassSet previousClasses = _validTargetClasses[receiver];
|
| - TypeMask newType;
|
| - // If we have previous knowledge, we use that to compute the typemask.
|
| - // Otherwise, we have to use `targets` to also include the noSuchMethod
|
| - // handlers, which are filtered out of `classes`.
|
| - if (previousClasses != null) {
|
| - classes = previousClasses.intersect(classes);
|
| - newType = classes.computeMask();
|
| - } else {
|
| - newType = targets.computeMask(classWorld);
|
| - }
|
| + TypeMask newType = compiler.world.allFunctions.receiverType(selector);
|
| newType = newType.intersection(receiverType, classWorld);
|
| var next = instruction.next;
|
| if (next is HTypeKnown && next.checkedInput == receiver) {
|
| @@ -377,8 +353,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| next.knownType = next.instructionType = newType;
|
| addDependentInstructionsToWorkList(next);
|
| }
|
| - _validTargetClasses[next] = classes;
|
| - } else if (newType != receiverType || !classes.treatAsDynamic) {
|
| + } else if (newType != receiverType) {
|
| // Insert a refinement node after the call and update all
|
| // users dominated by the call to use that node instead of
|
| // [receiver].
|
| @@ -387,7 +362,6 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| instruction.block.addBefore(instruction.next, converted);
|
| receiver.replaceAllUsersDominatedBy(converted.next, converted);
|
| addDependentInstructionsToWorkList(converted);
|
| - _validTargetClasses[converted] = classes;
|
| }
|
| }
|
|
|
| @@ -395,69 +369,3 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| instruction, compiler);
|
| }
|
| }
|
| -
|
| -// TODO(johnniwinther): Move to world.dart for a full implementation.
|
| -class _ClassSet {
|
| - final Set<ClassElement> classes;
|
| - final ClassWorld world;
|
| -
|
| - const _ClassSet.empty(this.world) :
|
| - classes = const ImmutableEmptySet<ClassElement>();
|
| -
|
| - _ClassSet.from(FunctionSetQuery query,
|
| - this.world,
|
| - {bool filter(Element element): null}) :
|
| - classes = new Setlet<ClassElement>() {
|
| - Iterable<Element> functions = query.functions;
|
| - if (filter != null) functions = functions.where(filter);
|
| - classes.addAll(functions.expand(_toClasses));
|
| - }
|
| -
|
| - _ClassSet._internal(this.classes, this.world);
|
| -
|
| - Iterable<ClassElement> _toClasses(Element element) {
|
| - ClassElement cls = element.enclosingClass.declaration;
|
| - return [cls]..addAll(world.mixinUsesOf(cls))..map((c) => c.declaration);
|
| - }
|
| -
|
| - _ClassSet intersect(_ClassSet other) {
|
| - Setlet<ClassElement> intersected = new Setlet<ClassElement>();
|
| - Set<ClassElement> otherClasses = other.classes;
|
| -
|
| - for (ClassElement cls in classes) {
|
| - if (otherClasses.contains(cls)) {
|
| - intersected.add(cls);
|
| - } else {
|
| - for (ClassElement otherCls in otherClasses) {
|
| - if (cls.isSubclassOf(otherCls)) {
|
| - intersected.add(cls);
|
| - break; // cls is covered, no need to search further
|
| - } else if (otherCls.isSubclassOf(cls)) {
|
| - intersected.add(otherCls);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - return new _ClassSet._internal(intersected, world);
|
| - }
|
| -
|
| - /// Whether this [_ClassSet] should be memoized in the tree or can be ignored
|
| - /// as it is too close to `dynamic`.
|
| - // TODO(herhut): Find a more meaningful implementation if the need arises.
|
| - bool get treatAsDynamic => false;
|
| -
|
| - TypeMask computeMask() {
|
| - return new TypeMask.unionOf(classes.map(_toMask), world);
|
| - }
|
| -
|
| - TypeMask _toMask(ClassElement cls) {
|
| - if (world.backend.isNullImplementation(cls)) {
|
| - return const TypeMask.empty();
|
| - } else {
|
| - return new TypeMask.nonNullSubclass(cls, world);
|
| - }
|
| - }
|
| -
|
| - toString() => "ClassSet: ${classes}";
|
| -}
|
|
|