| Index: pkg/compiler/lib/src/ssa/builder.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/builder.dart b/pkg/compiler/lib/src/ssa/builder.dart
|
| index fc906e54b72041bc7853c3a43711ad8d5e8f1c8a..fb7b0792020f66244d7417a1f4fd6991fdcbb99b 100644
|
| --- a/pkg/compiler/lib/src/ssa/builder.dart
|
| +++ b/pkg/compiler/lib/src/ssa/builder.dart
|
| @@ -1297,6 +1297,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| */
|
| bool tryInlineMethod(Element element,
|
| Selector selector,
|
| + TypeMask mask,
|
| List<HInstruction> providedArguments,
|
| ast.Node currentNode,
|
| {InterfaceType instanceType}) {
|
| @@ -1328,8 +1329,11 @@ class SsaBuilder extends NewResolvedVisitor {
|
| Elements.isStaticOrTopLevel(element) ||
|
| element.isGenerativeConstructorBody,
|
| message: "Missing selector for inlining of $element."));
|
| - if (selector != null && !selector.applies(function, compiler.world)) {
|
| - return false;
|
| + if (selector != null) {
|
| + if (!selector.applies(function, compiler.world)) return false;
|
| + if (mask != null && !mask.canHit(function, selector, compiler.world)) {
|
| + return false;
|
| + }
|
| }
|
|
|
| // Don't inline operator== methods if the parameter can be null.
|
| @@ -1448,9 +1452,9 @@ class SsaBuilder extends NewResolvedVisitor {
|
| // Add an explicit null check on the receiver before doing the
|
| // inlining. We use [element] to get the same name in the
|
| // NoSuchMethodError message as if we had called it.
|
| - if (element.isInstanceMember
|
| - && !element.isGenerativeConstructorBody
|
| - && (selector.mask == null || selector.mask.isNullable)) {
|
| + if (element.isInstanceMember &&
|
| + !element.isGenerativeConstructorBody &&
|
| + (mask == null || mask.isNullable)) {
|
| addWithPosition(
|
| new HFieldGet(null, providedArguments[0], backend.dynamicType,
|
| isAssignable: false),
|
| @@ -2297,7 +2301,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| }
|
|
|
| if (!isNativeUpgradeFactory && // TODO(13836): Fix inlining.
|
| - tryInlineMethod(body, null, bodyCallInputs, function)) {
|
| + tryInlineMethod(body, null, null, bodyCallInputs, function)) {
|
| pop();
|
| } else {
|
| HInvokeConstructorBody invoke = new HInvokeConstructorBody(
|
| @@ -2451,6 +2455,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| pushInvokeDynamic(
|
| null,
|
| new Selector.call(name, backend.jsHelperLibrary, 1),
|
| + null,
|
| arguments);
|
|
|
| return new HTypeConversion(type, kind, original.instructionType, pop());
|
| @@ -3191,7 +3196,11 @@ class SsaBuilder extends NewResolvedVisitor {
|
| }
|
| }
|
|
|
| - pushInvokeDynamic(node, elements.getSelector(node), [operand]);
|
| + pushInvokeDynamic(
|
| + node,
|
| + elements.getSelector(node),
|
| + elements.getTypeMask(node),
|
| + [operand]);
|
| }
|
|
|
| @override
|
| @@ -3223,6 +3232,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| visitAndPop(left),
|
| visitAndPop(right),
|
| elements.getSelector(node),
|
| + elements.getTypeMask(node),
|
| node,
|
| location: node.selector);
|
| }
|
| @@ -3232,9 +3242,10 @@ class SsaBuilder extends NewResolvedVisitor {
|
| void visitBinarySend(HInstruction left,
|
| HInstruction right,
|
| Selector selector,
|
| + TypeMask mask,
|
| ast.Send send,
|
| {ast.Node location}) {
|
| - pushInvokeDynamic(send, selector, [left, right], location: location);
|
| + pushInvokeDynamic(send, selector, mask, [left, right], location: location);
|
| }
|
|
|
| HInstruction generateInstanceSendReceiver(ast.Send send) {
|
| @@ -3256,12 +3267,14 @@ class SsaBuilder extends NewResolvedVisitor {
|
| * Returns a set of interceptor classes that contain the given
|
| * [selector].
|
| */
|
| - void generateInstanceGetterWithCompiledReceiver(ast.Send send,
|
| - Selector selector,
|
| - HInstruction receiver) {
|
| + void generateInstanceGetterWithCompiledReceiver(
|
| + ast.Send send,
|
| + Selector selector,
|
| + TypeMask mask,
|
| + HInstruction receiver) {
|
| assert(Elements.isInstanceSend(send, elements));
|
| assert(selector.isGetter);
|
| - pushInvokeDynamic(send, selector, [receiver]);
|
| + pushInvokeDynamic(send, selector, mask, [receiver]);
|
| }
|
|
|
| /// Inserts a call to checkDeferredIsLoaded for [prefixElement].
|
| @@ -3379,7 +3392,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| void generateDynamicGet(ast.Send node) {
|
| HInstruction receiver = generateInstanceSendReceiver(node);
|
| generateInstanceGetterWithCompiledReceiver(
|
| - node, elements.getSelector(node), receiver);
|
| + node, elements.getSelector(node), elements.getTypeMask(node), receiver);
|
| }
|
|
|
| /// Generate a closurization of the static or top level [function].
|
| @@ -3426,8 +3439,13 @@ class SsaBuilder extends NewResolvedVisitor {
|
| pushCheckNull(expression);
|
| },
|
| () => stack.add(expression),
|
| - () => generateInstanceGetterWithCompiledReceiver(
|
| - node, elements.getSelector(node), expression));
|
| + () {
|
| + generateInstanceGetterWithCompiledReceiver(
|
| + node,
|
| + elements.getSelector(node),
|
| + elements.getTypeMask(node),
|
| + expression);
|
| + });
|
| }
|
|
|
| /// Pushes a boolean checking [expression] against null.
|
| @@ -3511,18 +3529,22 @@ class SsaBuilder extends NewResolvedVisitor {
|
| HInstruction receiver,
|
| HInstruction value,
|
| {Selector selector,
|
| + TypeMask mask,
|
| ast.Node location}) {
|
| assert(send == null || Elements.isInstanceSend(send, elements));
|
| if (selector == null) {
|
| assert(send != null);
|
| selector = elements.getSelector(send);
|
| + if (mask == null) {
|
| + mask = elements.getTypeMask(send);
|
| + }
|
| }
|
| if (location == null) {
|
| assert(send != null);
|
| location = send;
|
| }
|
| assert(selector.isSetter);
|
| - pushInvokeDynamic(location, selector, [receiver, value]);
|
| + pushInvokeDynamic(location, selector, mask, [receiver, value]);
|
| pop();
|
| stack.add(value);
|
| }
|
| @@ -3657,7 +3679,9 @@ class SsaBuilder extends NewResolvedVisitor {
|
| if (type.isFunctionType) {
|
| List arguments = [buildFunctionType(type), expression];
|
| pushInvokeDynamic(
|
| - node, new Selector.call('_isTest', backend.jsHelperLibrary, 1),
|
| + node,
|
| + new Selector.call('_isTest', backend.jsHelperLibrary, 1),
|
| + null,
|
| arguments);
|
| return new HIs.compound(type, expression, pop(), backend.boolType);
|
| } else if (type.isTypeVariable) {
|
| @@ -3779,12 +3803,13 @@ class SsaBuilder extends NewResolvedVisitor {
|
|
|
| void _generateDynamicSend(ast.Send node, HInstruction receiver) {
|
| Selector selector = elements.getSelector(node);
|
| + TypeMask mask = elements.getTypeMask(node);
|
|
|
| List<HInstruction> inputs = <HInstruction>[];
|
| inputs.add(receiver);
|
| addDynamicSendArgumentsToList(node, inputs);
|
|
|
| - pushInvokeDynamic(node, selector, inputs);
|
| + pushInvokeDynamic(node, selector, mask, inputs);
|
| if (selector.isSetter || selector.isIndexSet) {
|
| pop();
|
| stack.add(inputs.last);
|
| @@ -4148,8 +4173,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| // If the isolate library is not used, we just invoke the
|
| // closure.
|
| visit(link.tail.head);
|
| - Selector selector = new Selector.callClosure(0);
|
| - push(new HInvokeClosure(selector,
|
| + push(new HInvokeClosure(new Selector.callClosure(0),
|
| <HInstruction>[pop()],
|
| backend.dynamicType));
|
| } else {
|
| @@ -4291,7 +4315,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| // class is _not_ the default implementation from [Object], in
|
| // case the [noSuchMethod] implementation calls
|
| // [JSInvocationMirror._invokeOn].
|
| - registry.registerSelectorUse(selector.asUntyped);
|
| + registry.registerSelectorUse(selector);
|
| }
|
| String publicName = name;
|
| if (selector.isSetter) publicName += '=';
|
| @@ -5307,9 +5331,11 @@ class SsaBuilder extends NewResolvedVisitor {
|
| Selector selector = elements.getSelector(node);
|
| List<HInstruction> inputs = <HInstruction>[target];
|
| addDynamicSendArgumentsToList(node, inputs);
|
| - Selector closureSelector = new Selector.callClosureFrom(selector);
|
| pushWithPosition(
|
| - new HInvokeClosure(closureSelector, inputs, backend.dynamicType), node);
|
| + new HInvokeClosure(
|
| + new Selector.callClosureFrom(selector),
|
| + inputs, backend.dynamicType),
|
| + node);
|
| }
|
|
|
| visitGetterSend(ast.Send node) {
|
| @@ -5438,6 +5464,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
|
|
| void pushInvokeDynamic(ast.Node node,
|
| Selector selector,
|
| + TypeMask mask,
|
| List<HInstruction> arguments,
|
| {ast.Node location}) {
|
| if (location == null) location = node;
|
| @@ -5478,13 +5505,13 @@ class SsaBuilder extends NewResolvedVisitor {
|
| return false;
|
| }
|
|
|
| - Element element = compiler.world.locateSingleElement(selector);
|
| - if (element != null
|
| - && !element.isField
|
| - && !(element.isGetter && selector.isCall)
|
| - && !(element.isFunction && selector.isGetter)
|
| - && !isOptimizableOperation(selector, element)) {
|
| - if (tryInlineMethod(element, selector, arguments, node)) {
|
| + Element element = compiler.world.locateSingleElement(selector, mask);
|
| + if (element != null &&
|
| + !element.isField &&
|
| + !(element.isGetter && selector.isCall) &&
|
| + !(element.isFunction && selector.isGetter) &&
|
| + !isOptimizableOperation(selector, element)) {
|
| + if (tryInlineMethod(element, selector, mask, arguments, node)) {
|
| return;
|
| }
|
| }
|
| @@ -5496,18 +5523,19 @@ class SsaBuilder extends NewResolvedVisitor {
|
| inputs.add(invokeInterceptor(receiver));
|
| }
|
| inputs.addAll(arguments);
|
| - TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler);
|
| + TypeMask type =
|
| + TypeMaskFactory.inferredTypeForSelector(selector, mask, compiler);
|
| if (selector.isGetter) {
|
| pushWithPosition(
|
| - new HInvokeDynamicGetter(selector, null, inputs, type),
|
| + new HInvokeDynamicGetter(selector, mask, null, inputs, type),
|
| location);
|
| } else if (selector.isSetter) {
|
| pushWithPosition(
|
| - new HInvokeDynamicSetter(selector, null, inputs, type),
|
| + new HInvokeDynamicSetter(selector, mask, null, inputs, type),
|
| location);
|
| } else {
|
| pushWithPosition(
|
| - new HInvokeDynamicMethod(selector, inputs, type, isIntercepted),
|
| + new HInvokeDynamicMethod(selector, mask, inputs, type, isIntercepted),
|
| location);
|
| }
|
| }
|
| @@ -5517,7 +5545,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| List<HInstruction> arguments,
|
| {TypeMask typeMask,
|
| InterfaceType instanceType}) {
|
| - if (tryInlineMethod(element, null, arguments, location,
|
| + if (tryInlineMethod(element, null, null, arguments, location,
|
| instanceType: instanceType)) {
|
| return;
|
| }
|
| @@ -5572,7 +5600,8 @@ class SsaBuilder extends NewResolvedVisitor {
|
| inputs,
|
| type,
|
| isSetter: selector.isSetter || selector.isIndexSet);
|
| - instruction.sideEffects = compiler.world.getSideEffectsOfSelector(selector);
|
| + instruction.sideEffects =
|
| + compiler.world.getSideEffectsOfSelector(selector, null);
|
| return instruction;
|
| }
|
|
|
| @@ -5589,6 +5618,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| }
|
| visitBinarySend(receiver, rhs,
|
| elements.getOperatorSelectorInComplexSendSet(node),
|
| + elements.getOperatorTypeMaskInComplexSendSet(node),
|
| node,
|
| location: node.assignmentOperator);
|
| }
|
| @@ -5686,6 +5716,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| pushInvokeDynamic(
|
| node,
|
| elements.getGetterSelectorInComplexSendSet(node),
|
| + elements.getGetterTypeMaskInComplexSendSet(node),
|
| [receiver, index]);
|
| HInstruction getterInstruction = pop();
|
| if (node.isIfNullAssignment) {
|
| @@ -5700,7 +5731,10 @@ class SsaBuilder extends NewResolvedVisitor {
|
| visit(arguments.head);
|
| HInstruction value = pop();
|
| pushInvokeDynamic(
|
| - node, elements.getSelector(node), [receiver, index, value]);
|
| + node,
|
| + elements.getSelector(node),
|
| + elements.getTypeMask(node),
|
| + [receiver, index, value]);
|
| pop();
|
| stack.add(value);
|
| });
|
| @@ -5708,7 +5742,10 @@ class SsaBuilder extends NewResolvedVisitor {
|
| handleComplexOperatorSend(node, getterInstruction, arguments);
|
| HInstruction value = pop();
|
| pushInvokeDynamic(
|
| - node, elements.getSelector(node), [receiver, index, value]);
|
| + node,
|
| + elements.getSelector(node),
|
| + elements.getTypeMask(node),
|
| + [receiver, index, value]);
|
| pop();
|
| if (node.isPostfix) {
|
| stack.add(getterInstruction);
|
| @@ -5995,7 +6032,10 @@ class SsaBuilder extends NewResolvedVisitor {
|
| void generateAssignment(HInstruction receiver) {
|
| // desugars `e.x op= e2` to `e.x = e.x op e2`
|
| generateInstanceGetterWithCompiledReceiver(
|
| - node, elements.getGetterSelectorInComplexSendSet(node), receiver);
|
| + node,
|
| + elements.getGetterSelectorInComplexSendSet(node),
|
| + elements.getGetterTypeMaskInComplexSendSet(node),
|
| + receiver);
|
| HInstruction getterInstruction = pop();
|
| if (node.isIfNullAssignment) {
|
| SsaBranchBuilder brancher = new SsaBranchBuilder(this, node);
|
| @@ -6446,7 +6486,8 @@ class SsaBuilder extends NewResolvedVisitor {
|
|
|
| HInstruction buildCondition() {
|
| Selector selector = elements.getMoveNextSelector(node);
|
| - pushInvokeDynamic(node, selector, [streamIterator]);
|
| + TypeMask mask = elements.getMoveNextTypeMask(node);
|
| + pushInvokeDynamic(node, selector, mask, [streamIterator]);
|
| HInstruction future = pop();
|
| push(new HAwait(future, new TypeMask.subclass(compiler.objectClass,
|
| compiler.world)));
|
| @@ -6454,11 +6495,13 @@ class SsaBuilder extends NewResolvedVisitor {
|
| }
|
| void buildBody() {
|
| Selector call = elements.getCurrentSelector(node);
|
| - pushInvokeDynamic(node, call, [streamIterator]);
|
| + TypeMask callMask = elements.getCurrentTypeMask(node);
|
| + pushInvokeDynamic(node, call, callMask, [streamIterator]);
|
|
|
| ast.Node identifier = node.declaredIdentifier;
|
| Element variable = elements.getForInVariable(node);
|
| Selector selector = elements.getSelector(identifier);
|
| + TypeMask mask = elements.getTypeMask(identifier);
|
|
|
| HInstruction value = pop();
|
| if (identifier.asSend() != null
|
| @@ -6470,6 +6513,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| receiver,
|
| value,
|
| selector: selector,
|
| + mask: mask,
|
| location: identifier);
|
| } else {
|
| generateNonInstanceSetter(
|
| @@ -6489,7 +6533,9 @@ class SsaBuilder extends NewResolvedVisitor {
|
| buildUpdate,
|
| buildBody);
|
| }, () {
|
| - pushInvokeDynamic(node, new Selector.call("cancel", null, 0),
|
| + pushInvokeDynamic(node,
|
| + new Selector.call("cancel", null, 0),
|
| + null,
|
| [streamIterator]);
|
| push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass,
|
| compiler.world)));
|
| @@ -6509,7 +6555,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| // case.
|
|
|
| Selector selector = elements.getIteratorSelector(node);
|
| - TypeMask mask = selector.mask;
|
| + TypeMask mask = elements.getIteratorTypeMask(node);
|
|
|
| ClassWorld classWorld = compiler.world;
|
| if (mask != null && mask.satisfies(backend.jsIndexableClass, classWorld)) {
|
| @@ -6531,21 +6577,24 @@ class SsaBuilder extends NewResolvedVisitor {
|
|
|
| void buildInitializer() {
|
| Selector selector = elements.getIteratorSelector(node);
|
| + TypeMask mask = elements.getIteratorTypeMask(node);
|
| visit(node.expression);
|
| HInstruction receiver = pop();
|
| - pushInvokeDynamic(node, selector, [receiver]);
|
| + pushInvokeDynamic(node, selector, mask, [receiver]);
|
| iterator = pop();
|
| }
|
|
|
| HInstruction buildCondition() {
|
| Selector selector = elements.getMoveNextSelector(node);
|
| - pushInvokeDynamic(node, selector, [iterator]);
|
| + TypeMask mask = elements.getMoveNextTypeMask(node);
|
| + pushInvokeDynamic(node, selector, mask, [iterator]);
|
| return popBoolified();
|
| }
|
|
|
| void buildBody() {
|
| Selector call = elements.getCurrentSelector(node);
|
| - pushInvokeDynamic(node, call, [iterator]);
|
| + TypeMask mask = elements.getCurrentTypeMask(node);
|
| + pushInvokeDynamic(node, call, mask, [iterator]);
|
| buildAssignLoopVariable(node, pop());
|
| visit(node.body);
|
| }
|
| @@ -6557,6 +6606,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| ast.Node identifier = node.declaredIdentifier;
|
| Element variable = elements.getForInVariable(node);
|
| Selector selector = elements.getSelector(identifier);
|
| + TypeMask mask = elements.getTypeMask(identifier);
|
|
|
| if (identifier.asSend() != null &&
|
| Elements.isInstanceSend(identifier, elements)) {
|
| @@ -6567,6 +6617,7 @@ class SsaBuilder extends NewResolvedVisitor {
|
| receiver,
|
| value,
|
| selector: selector,
|
| + mask: mask,
|
| location: identifier);
|
| } else {
|
| generateNonInstanceSetter(null, variable, value, location: identifier);
|
| @@ -6646,9 +6697,8 @@ class SsaBuilder extends NewResolvedVisitor {
|
| // example, `get current` includes null.
|
| // TODO(sra): The element type of a container type mask might be better.
|
| Selector selector = new Selector.index();
|
| - Selector refined = new TypedSelector(arrayType, selector, compiler.world);
|
| - TypeMask type =
|
| - TypeMaskFactory.inferredTypeForSelector(refined, compiler);
|
| + TypeMask type = TypeMaskFactory.inferredTypeForSelector(
|
| + selector, arrayType, compiler);
|
|
|
| HInstruction index = localsHandler.readLocal(indexVariable);
|
| HInstruction value = new HIndex(array, index, null, type);
|
| @@ -7565,12 +7615,12 @@ class StringBuilderVisitor extends ast.Visitor {
|
|
|
| // If the `toString` method is guaranteed to return a string we can call it
|
| // directly.
|
| - Selector selector =
|
| - new TypedSelector(expression.instructionType,
|
| - new Selector.call('toString', null, 0), compiler.world);
|
| - TypeMask type = TypeMaskFactory.inferredTypeForSelector(selector, compiler);
|
| + Selector selector = new Selector.call('toString', null, 0);
|
| + TypeMask type = TypeMaskFactory.inferredTypeForSelector(
|
| + selector, expression.instructionType, compiler);
|
| if (type.containsOnlyString(compiler.world)) {
|
| - builder.pushInvokeDynamic(node, selector, <HInstruction>[expression]);
|
| + builder.pushInvokeDynamic(
|
| + node, selector, expression.instructionType, <HInstruction>[expression]);
|
| append(builder.pop());
|
| return;
|
| }
|
|
|