| Index: sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
|
| ===================================================================
|
| --- sdk/lib/_internal/compiler/implementation/ssa/nodes.dart (revision 17124)
|
| +++ sdk/lib/_internal/compiler/implementation/ssa/nodes.dart (working copy)
|
| @@ -1320,8 +1320,14 @@
|
| }
|
|
|
| class HInvokeDynamicMethod extends HInvokeDynamic {
|
| - HInvokeDynamicMethod(Selector selector, List<HInstruction> inputs)
|
| - : super(selector, null, inputs);
|
| + final InvokeDynamicSpecializer specializer;
|
| + HInvokeDynamicMethod(Selector selector,
|
| + List<HInstruction> inputs,
|
| + [bool isIntercepted = false])
|
| + : super(selector, null, inputs),
|
| + specializer = isIntercepted
|
| + ? InvokeDynamicSpecializer.lookupSpecializer(selector)
|
| + : const InvokeDynamicSpecializer();
|
| String toString() => 'invoke dynamic method: $selector';
|
| accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
|
|
|
| @@ -1335,58 +1341,11 @@
|
| HType computeDesiredTypeForInput(HInstruction input,
|
| HTypeMap types,
|
| Compiler compiler) {
|
| - // TODO(ngeoffray): Move this logic into a different class that
|
| - // will know what type it wants for a given selector.
|
| - if (!isInterceptorCall) return HType.UNKNOWN;
|
| -
|
| - if (selector.kind == SelectorKind.INDEX) {
|
| - HInstruction index = inputs[2];
|
| - if (input == inputs[1] &&
|
| - (index.isTypeUnknown(types) || index.isNumber(types))) {
|
| - return selector.name == const SourceString('[]')
|
| - ? HType.INDEXABLE_PRIMITIVE
|
| - : HType.MUTABLE_ARRAY;
|
| - }
|
| - // The index should be an int when the receiver is a string or array.
|
| - // However it turns out that inserting an integer check in the optimized
|
| - // version is cheaper than having another bailout case. This is true,
|
| - // because the integer check will simply throw if it fails.
|
| - return HType.UNKNOWN;
|
| - } else if (selector.kind == SelectorKind.OPERATOR) {
|
| - HType propagatedType = types[this];
|
| - if (selector.name == const SourceString('unary-') && input == inputs[1]) {
|
| - // If the outgoing type should be a number (integer, double or both) we
|
| - // want the outgoing type to be the input too.
|
| - // If we don't know the outgoing type we try to make it a number.
|
| - if (propagatedType.isNumber()) return propagatedType;
|
| - if (propagatedType.isUnknown()) return HType.NUMBER;
|
| - } else if (selector.name == const SourceString('~')
|
| - && input == inputs[1]) {
|
| - if (propagatedType.isUnknown() || propagatedType.isNumber()) {
|
| - return HType.INTEGER;
|
| - }
|
| - }
|
| - return HType.UNKNOWN;
|
| - }
|
| - return HType.UNKNOWN;
|
| + return specializer.computeDesiredTypeForInput(this, input, types, compiler);
|
| }
|
|
|
| HType computeTypeFromInputTypes(HTypeMap types, Compiler compiler) {
|
| - // TODO(ngeoffray): Move this logic into a different class that
|
| - // will know what type it has for a given selector.
|
| - if (!isInterceptorCall) return HType.UNKNOWN;
|
| -
|
| - if (selector.kind == SelectorKind.OPERATOR) {
|
| - if (selector.name == const SourceString('unary-')) {
|
| - HType operandType = types[inputs[1]];
|
| - if (operandType.isNumber()) return operandType;
|
| - } else if (selector.name == const SourceString('~')) {
|
| - // All bitwise operations on primitive types either produce an
|
| - // integer or throw an error.
|
| - if (inputs[1].isPrimitive(types)) return HType.INTEGER;
|
| - }
|
| - }
|
| - return HType.UNKNOWN;
|
| + return specializer.computeTypeFromInputTypes(this, types, compiler);
|
| }
|
| }
|
|
|
|
|