| Index: sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
|
| ===================================================================
|
| --- sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart (revision 22031)
|
| +++ sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart (working copy)
|
| @@ -126,7 +126,8 @@
|
| }
|
|
|
| HType visitInvokeDynamic(HInvokeDynamic instruction) {
|
| - HType receiverType = instruction.getDartReceiver(compiler).instructionType;
|
| + HInstruction receiver = instruction.getDartReceiver(compiler);
|
| + HType receiverType = receiver.instructionType;
|
| Selector refined = receiverType.refine(instruction.selector, compiler);
|
| HType type = new HType.inferredTypeForSelector(refined, compiler);
|
| if (type.isUseful()) return type;
|
| @@ -171,18 +172,7 @@
|
| }
|
| }
|
|
|
| - void convertInput(HInstruction instruction, HInstruction input, HType type) {
|
| - HTypeConversion converted = new HTypeConversion(
|
| - null, HTypeConversion.ARGUMENT_TYPE_CHECK, type, input);
|
| - instruction.block.addBefore(instruction, converted);
|
| - Set<HInstruction> dominatedUsers = input.dominatedUsers(instruction);
|
| - for (HInstruction user in dominatedUsers) {
|
| - user.changeUse(input, converted);
|
| - addToWorkList(user);
|
| - }
|
| - }
|
| -
|
| - HType visitInvokeDynamicMethod(HInvokeDynamicMethod instruction) {
|
| + HType visitInvokeDynamic(HInvokeDynamic instruction) {
|
| // Update the pending optimizations map based on the potentially
|
| // new types of the operands. If the operand types no longer allow
|
| // us to optimize, we remove the pending optimization.
|
| @@ -194,14 +184,57 @@
|
| // This callback function is invoked after we're done
|
| // propagating types. The types shouldn't have changed.
|
| assert(left.isNumber() && !right.isNumber());
|
| - convertInput(instruction, right, HType.NUMBER);
|
| + convertInput(instruction, right, HType.NUMBER,
|
| + HTypeConversion.ARGUMENT_TYPE_CHECK);
|
| };
|
| } else {
|
| pendingOptimizations.remove(instruction);
|
| }
|
| }
|
| - return super.visitInvokeDynamicMethod(instruction);
|
| +
|
| + HInstruction receiver = instruction.getDartReceiver(compiler);
|
| + HType receiverType = receiver.instructionType;
|
| + Selector refined = receiverType.refine(instruction.selector, compiler);
|
| + TypeMask receiverMask = receiverType.computeMask(compiler);
|
| +
|
| + // Try to refine the type of the receiver with the potential
|
| + // targets this call can hit.
|
| + TypeMask refinedMaskForSelector = new TypeMask.refineWith(
|
| + receiverMask, refined, compiler);
|
| +
|
| + if (refinedMaskForSelector != receiverMask) {
|
| + HType newSelectorType =
|
| + new HType.fromMask(refinedMaskForSelector, compiler);
|
| + if (instruction.next is HTypeConversion
|
| + && instruction.next.checkedInput == receiver) {
|
| + instruction.next.instructionType = newSelectorType;
|
| + } else {
|
| + convertInput(instruction.next,
|
| + receiver,
|
| + newSelectorType,
|
| + HTypeConversion.NO_CHECK);
|
| + }
|
| + }
|
| +
|
| + HType type = new HType.inferredTypeForSelector(refined, compiler);
|
| + if (type.isUseful()) return type;
|
| + return instruction.specializer.computeTypeFromInputTypes(
|
| + instruction, compiler);
|
| }
|
| +
|
| + void convertInput(HInstruction instruction,
|
| + HInstruction input,
|
| + HType type,
|
| + int kind) {
|
| + Set<HInstruction> dominatedUsers = input.dominatedUsers(instruction);
|
| + if (dominatedUsers.isEmpty) return;
|
| + HTypeConversion converted = new HTypeConversion(null, kind, type, input);
|
| + instruction.block.addBefore(instruction, converted);
|
| + for (HInstruction user in dominatedUsers) {
|
| + user.changeUse(input, converted);
|
| + addToWorkList(user);
|
| + }
|
| + }
|
| }
|
|
|
| /**
|
|
|