| Index: sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
|
| ===================================================================
|
| --- sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart (revision 30666)
|
| +++ sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart (working copy)
|
| @@ -507,12 +507,6 @@
|
| }
|
| }
|
|
|
| - bool hasOnePositionalArgumentWithType(TypeMask type) {
|
| - return arguments.named.isEmpty
|
| - && arguments.positional.length == 1
|
| - && arguments.positional[0].type == type;
|
| - }
|
| -
|
| /**
|
| * We optimize certain operations on the [int] class because we know
|
| * more about their return type than the actual Dart code. For
|
| @@ -521,33 +515,56 @@
|
| */
|
| TypeInformation handleIntrisifiedSelector(Selector selector,
|
| TypeGraphInferrerEngine inferrer) {
|
| - if (!inferrer.compiler.backend.intImplementation.isResolved) return null;
|
| - TypeMask intType = inferrer.compiler.typesTask.intType;
|
| - TypeMask nullableIntType = intType.nullable();
|
| + Compiler compiler = inferrer.compiler;
|
| + if (!compiler.backend.intImplementation.isResolved) return null;
|
| TypeMask emptyType = const TypeMask.nonNullEmpty();
|
| - if (selector.mask != intType && selector.mask != nullableIntType) {
|
| + if (selector.mask == null) return null;
|
| + if (!selector.mask.containsOnlyInt(compiler)) {
|
| return null;
|
| }
|
| if (!selector.isCall() && !selector.isOperator()) return null;
|
| if (!arguments.named.isEmpty) return null;
|
| if (arguments.positional.length > 1) return null;
|
|
|
| + ClassElement uint31Implementation = compiler.backend.uint31Implementation;
|
| + bool isInt(info) => info.type.containsOnlyInt(compiler);
|
| + bool isEmpty(info) => info.type == emptyType;
|
| + bool isUInt31(info) {
|
| + return info.type.satisfies(uint31Implementation, compiler);
|
| + }
|
| +
|
| String name = selector.name;
|
| + // We are optimizing for the cases that are not expressed in the
|
| + // Dart code, for example:
|
| + // int + int -> int
|
| + // uint31 | uint31 -> uint31
|
| if (name == '*' || name == '+' || name == '%' || name == 'remainder') {
|
| - if (hasOnePositionalArgumentWithType(intType)
|
| - || hasOnePositionalArgumentWithType(nullableIntType)) {
|
| + if (arguments.hasOnePositionalArgumentThatMatches(isInt)) {
|
| return inferrer.types.intType;
|
| - } else if (hasOnePositionalArgumentWithType(emptyType)) {
|
| + } else if (arguments.hasOnePositionalArgumentThatMatches(isEmpty)) {
|
| return inferrer.types.nonNullEmptyType;
|
| } else {
|
| return null;
|
| }
|
| + } else if (name == '|' || name == '^') {
|
| + if (isUInt31(receiver)
|
| + && arguments.hasOnePositionalArgumentThatMatches(isUInt31)) {
|
| + return inferrer.types.uint31Type;
|
| + }
|
| + } else if (name == '>>') {
|
| + if (isUInt31(receiver)) {
|
| + return inferrer.types.uint31Type;
|
| + }
|
| + } else if (name == '&') {
|
| + if (isUInt31(receiver)
|
| + || arguments.hasOnePositionalArgumentThatMatches(isUInt31)) {
|
| + return inferrer.types.uint31Type;
|
| + }
|
| } else if (name == '-') {
|
| if (arguments.hasNoArguments()) return inferrer.types.intType;
|
| - if (hasOnePositionalArgumentWithType(intType)
|
| - || hasOnePositionalArgumentWithType(nullableIntType)) {
|
| + if (arguments.hasOnePositionalArgumentThatMatches(isInt)) {
|
| return inferrer.types.intType;
|
| - } else if (hasOnePositionalArgumentWithType(emptyType)) {
|
| + } else if (arguments.hasOnePositionalArgumentThatMatches(isEmpty)) {
|
| return inferrer.types.nonNullEmptyType;
|
| }
|
| return null;
|
|
|