Chromium Code Reviews| 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 0ef26591b908ce4d5ecb0c34336f8993d993030a..0224c9a01ce45949aa1cf1d568375c8057a142c9 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( |
| @@ -2450,6 +2454,7 @@ class SsaBuilder extends NewResolvedVisitor { |
| pushInvokeDynamic( |
| null, |
| new Selector.call(name, backend.jsHelperLibrary, 1), |
| + null, |
| arguments); |
| return new HTypeConversion(type, kind, original.instructionType, pop()); |
| @@ -3192,7 +3197,11 @@ class SsaBuilder extends NewResolvedVisitor { |
| } |
| } |
| - pushInvokeDynamic(node, elements.getSelector(node), [operand]); |
| + pushInvokeDynamic( |
| + node, |
| + elements.getSelector(node), |
| + elements.getTypeMask(node), |
| + [operand]); |
| } |
| @override |
| @@ -3224,6 +3233,7 @@ class SsaBuilder extends NewResolvedVisitor { |
| visitAndPop(left), |
| visitAndPop(right), |
| elements.getSelector(node), |
| + elements.getTypeMask(node), |
| node, |
| location: node.selector); |
| } |
| @@ -3233,9 +3243,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) { |
| @@ -3257,12 +3268,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]. |
| @@ -3380,7 +3393,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]. |
| @@ -3427,8 +3440,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. |
| @@ -3512,6 +3530,7 @@ class SsaBuilder extends NewResolvedVisitor { |
| HInstruction pushReceiver(), |
| HInstruction pushValue(), |
| {Selector selector, |
| + TypeMask mask, |
| ast.Node location}) { |
| if (send.isConditional) { |
| SsaBranchBuilder brancher = new SsaBranchBuilder(this, send); |
| @@ -3531,11 +3550,11 @@ class SsaBuilder extends NewResolvedVisitor { |
| () => stack.add(receiver), |
| () => generateInstanceSetterWithCompiledReceiver( |
| send, receiver, pushValue(), |
| - selector: selector, location: location)); |
| + selector: selector, mask: mask, location: location)); |
| } else { |
| generateInstanceSetterWithCompiledReceiver( |
| send, pushReceiver(), pushValue(), |
| - selector: selector, location: location); |
| + selector: selector, mask: mask, location: location); |
| } |
| } |
| @@ -3543,18 +3562,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); |
| } |
| @@ -3689,7 +3712,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) { |
| @@ -3811,12 +3836,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); |
| @@ -4180,8 +4206,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 { |
| @@ -4323,7 +4348,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 += '='; |
| @@ -5339,9 +5364,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) { |
| @@ -5470,6 +5497,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; |
| @@ -5510,15 +5538,21 @@ 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 (selector.name == 'double') { |
| + //debugPrint('Try to inline $node call to $element'); |
| + } |
| + if (tryInlineMethod(element, selector, mask, arguments, node)) { |
| return; |
| } |
| + if (selector.name == 'double') { |
|
karlklose
2015/06/17 12:43:11
Remove debug code.
Johnni Winther
2015/06/17 13:03:52
Done.
|
| + //debugPrint('Failed to inline $node'); |
| + } |
| } |
| HInstruction receiver = arguments[0]; |
| @@ -5528,18 +5562,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); |
| } |
| } |
| @@ -5549,7 +5584,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; |
| } |
| @@ -5604,7 +5639,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; |
| } |
| @@ -5621,6 +5657,7 @@ class SsaBuilder extends NewResolvedVisitor { |
| } |
| visitBinarySend(receiver, rhs, |
| elements.getOperatorSelectorInComplexSendSet(node), |
| + elements.getOperatorTypeMaskInComplexSendSet(node), |
| node, |
| location: node.assignmentOperator); |
| } |
| @@ -5715,6 +5752,7 @@ class SsaBuilder extends NewResolvedVisitor { |
| pushInvokeDynamic( |
| node, |
| elements.getGetterSelectorInComplexSendSet(node), |
| + elements.getGetterTypeMaskInComplexSendSet(node), |
| [receiver, index]); |
| HInstruction getterInstruction = pop(); |
| if (node.isIfNullAssignment) { |
| @@ -5729,7 +5767,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); |
| }); |
| @@ -5737,7 +5778,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); |
| @@ -5781,7 +5825,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); |
| @@ -6209,7 +6256,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))); |
| @@ -6217,11 +6265,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 |
| @@ -6233,6 +6283,7 @@ class SsaBuilder extends NewResolvedVisitor { |
| receiver, |
| value, |
| selector: selector, |
| + mask: mask, |
| location: identifier); |
| } else { |
| generateNonInstanceSetter( |
| @@ -6252,7 +6303,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))); |
| @@ -6272,7 +6325,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)) { |
| @@ -6294,21 +6347,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); |
| } |
| @@ -6320,6 +6376,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)) { |
| @@ -6330,6 +6387,7 @@ class SsaBuilder extends NewResolvedVisitor { |
| receiver, |
| value, |
| selector: selector, |
| + mask: mask, |
| location: identifier); |
| } else { |
| generateNonInstanceSetter(null, variable, value, location: identifier); |
| @@ -6409,9 +6467,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); |
| @@ -7328,12 +7385,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; |
| } |