| 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 49373dc08e30f4fc12ad64210f3cc5f49584c33c..e5ad51361666fd50fbaef0d92041761be01c8628 100644
|
| --- a/pkg/compiler/lib/src/ssa/types_propagation.dart
|
| +++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
|
| @@ -98,7 +98,6 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| } while (!worklist.isEmpty);
|
| }
|
|
|
| -
|
| void addToWorkList(HInstruction instruction) {
|
| final int id = instruction.id;
|
|
|
| @@ -175,12 +174,12 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| // We must make sure a type conversion for receiver or argument check
|
| // does not try to do an int check, because an int check is not enough.
|
| // We only do an int check if the input is integer or null.
|
| - if (checkedType.containsOnlyNum(classWorld)
|
| - && !checkedType.containsOnlyDouble(classWorld)
|
| - && input.isIntegerOrNull(compiler)) {
|
| + if (checkedType.containsOnlyNum(classWorld) &&
|
| + !checkedType.containsOnlyDouble(classWorld) &&
|
| + input.isIntegerOrNull(compiler)) {
|
| instruction.checkedType = backend.intType;
|
| - } else if (checkedType.containsOnlyInt(classWorld)
|
| - && !input.isIntegerOrNull(compiler)) {
|
| + } else if (checkedType.containsOnlyInt(classWorld) &&
|
| + !input.isIntegerOrNull(compiler)) {
|
| instruction.checkedType = backend.numType;
|
| }
|
| }
|
| @@ -192,8 +191,8 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| // can be a literal double '8.0' that is marked as an integer (because 'is
|
| // int' will return 'true'). What we really need to do is make the
|
| // overlap between int and double values explicit in the TypeMask system.
|
| - if (inputType.containsOnlyInt(classWorld)
|
| - && checkedType.containsOnlyDouble(classWorld)) {
|
| + if (inputType.containsOnlyInt(classWorld) &&
|
| + checkedType.containsOnlyDouble(classWorld)) {
|
| if (inputType.isNullable && checkedType.isNullable) {
|
| outputType = backend.doubleType.nullable();
|
| } else {
|
| @@ -218,22 +217,19 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| return outputType;
|
| }
|
|
|
| - void convertInput(HInvokeDynamic instruction,
|
| - HInstruction input,
|
| - TypeMask type,
|
| - int kind) {
|
| + void convertInput(
|
| + HInvokeDynamic instruction, HInstruction input, TypeMask type, int kind) {
|
| Selector selector = (kind == HTypeConversion.RECEIVER_TYPE_CHECK)
|
| ? instruction.selector
|
| : null;
|
| - HTypeConversion converted = new HTypeConversion(
|
| - null, kind, type, input, selector)
|
| - ..sourceInformation = instruction.sourceInformation;
|
| + HTypeConversion converted =
|
| + new HTypeConversion(null, kind, type, input, selector)
|
| + ..sourceInformation = instruction.sourceInformation;
|
| instruction.block.addBefore(instruction, converted);
|
| input.replaceAllUsersDominatedBy(instruction, converted);
|
| }
|
|
|
| - bool isCheckEnoughForNsmOrAe(HInstruction instruction,
|
| - TypeMask type) {
|
| + bool isCheckEnoughForNsmOrAe(HInstruction instruction, TypeMask type) {
|
| // In some cases, we want the receiver to be an integer,
|
| // but that does not mean we will get a NoSuchMethodError
|
| // if it's not: the receiver could be a double.
|
| @@ -254,20 +250,20 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| HInstruction receiver = instruction.inputs[1];
|
| if (receiver.isNumber(compiler)) return false;
|
| if (receiver.isNumberOrNull(compiler)) {
|
| - convertInput(instruction,
|
| - receiver,
|
| - receiver.instructionType.nonNullable(),
|
| - HTypeConversion.RECEIVER_TYPE_CHECK);
|
| + convertInput(
|
| + instruction,
|
| + receiver,
|
| + receiver.instructionType.nonNullable(),
|
| + HTypeConversion.RECEIVER_TYPE_CHECK);
|
| return true;
|
| } else if (instruction.element == null) {
|
| - Iterable<Element> targets =
|
| - compiler.world.allFunctions.filter(
|
| - instruction.selector, instruction.mask);
|
| + Iterable<Element> targets = compiler.world.allFunctions
|
| + .filter(instruction.selector, instruction.mask);
|
| if (targets.length == 1) {
|
| Element target = targets.first;
|
| ClassElement cls = target.enclosingClass;
|
| - TypeMask type = new TypeMask.nonNullSubclass(
|
| - cls.declaration, classWorld);
|
| + TypeMask type =
|
| + new TypeMask.nonNullSubclass(cls.declaration, classWorld);
|
| // TODO(ngeoffray): We currently only optimize on primitive
|
| // types.
|
| if (!type.satisfies(backend.helpers.jsIndexableClass, classWorld) &&
|
| @@ -277,10 +273,8 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| }
|
| if (!isCheckEnoughForNsmOrAe(receiver, type)) return false;
|
| instruction.element = target;
|
| - convertInput(instruction,
|
| - receiver,
|
| - type,
|
| - HTypeConversion.RECEIVER_TYPE_CHECK);
|
| + convertInput(
|
| + instruction, receiver, type, HTypeConversion.RECEIVER_TYPE_CHECK);
|
| return true;
|
| }
|
| }
|
| @@ -306,10 +300,8 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| // variant and will do the check in their method anyway. We
|
| // still add a check because it allows to GVN these operations,
|
| // but we should find a better way.
|
| - convertInput(instruction,
|
| - right,
|
| - type,
|
| - HTypeConversion.ARGUMENT_TYPE_CHECK);
|
| + convertInput(
|
| + instruction, right, type, HTypeConversion.ARGUMENT_TYPE_CHECK);
|
| return true;
|
| }
|
| return false;
|
| @@ -339,18 +331,19 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| // We cannot do the following optimization now, because we have
|
| // to wait for the type propagation to be stable. The receiver
|
| // of [instruction] might move from number to dynamic.
|
| - pendingOptimizations.putIfAbsent(instruction, () => () {
|
| - Selector selector = instruction.selector;
|
| - if (selector.isOperator && selector.name != '==') {
|
| - if (checkReceiver(instruction)) {
|
| - addAllUsersBut(instruction, instruction.inputs[1]);
|
| - }
|
| - if (!selector.isUnaryOperator &&
|
| - checkArgument(instruction)) {
|
| - addAllUsersBut(instruction, instruction.inputs[2]);
|
| - }
|
| - }
|
| - });
|
| + pendingOptimizations.putIfAbsent(
|
| + instruction,
|
| + () => () {
|
| + Selector selector = instruction.selector;
|
| + if (selector.isOperator && selector.name != '==') {
|
| + if (checkReceiver(instruction)) {
|
| + addAllUsersBut(instruction, instruction.inputs[1]);
|
| + }
|
| + if (!selector.isUnaryOperator && checkArgument(instruction)) {
|
| + addAllUsersBut(instruction, instruction.inputs[2]);
|
| + }
|
| + }
|
| + });
|
| }
|
|
|
| HInstruction receiver = instruction.getDartReceiver(compiler);
|
| @@ -358,10 +351,10 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| instruction.mask = receiverType;
|
|
|
| // Try to specialize the receiver after this call.
|
| - if (receiver.dominatedUsers(instruction).length != 1
|
| - && !instruction.selector.isClosureCall) {
|
| - TypeMask newType = compiler.world.allFunctions.receiverType(
|
| - instruction.selector, instruction.mask);
|
| + if (receiver.dominatedUsers(instruction).length != 1 &&
|
| + !instruction.selector.isClosureCall) {
|
| + TypeMask newType = compiler.world.allFunctions
|
| + .receiverType(instruction.selector, instruction.mask);
|
| newType = newType.intersection(receiverType, classWorld);
|
| var next = instruction.next;
|
| if (next is HTypeKnown && next.checkedInput == receiver) {
|
| @@ -385,7 +378,7 @@ class SsaTypePropagator extends HBaseVisitor implements OptimizationPhase {
|
| }
|
| }
|
|
|
| - return instruction.specializer.computeTypeFromInputTypes(
|
| - instruction, compiler);
|
| + return instruction.specializer
|
| + .computeTypeFromInputTypes(instruction, compiler);
|
| }
|
| }
|
|
|