| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 243 updateLocal(boxElement, oldBox); | 243 updateLocal(boxElement, oldBox); |
| 244 HInstruction oldValue = readLocal(boxedVariable); | 244 HInstruction oldValue = readLocal(boxedVariable); |
| 245 updateLocal(boxElement, newBox); | 245 updateLocal(boxElement, newBox); |
| 246 updateLocal(boxedVariable, oldValue); | 246 updateLocal(boxedVariable, oldValue); |
| 247 } | 247 } |
| 248 updateLocal(boxElement, newBox); | 248 updateLocal(boxElement, newBox); |
| 249 } | 249 } |
| 250 | 250 |
| 251 HType cachedTypeOfThis; | 251 HType cachedTypeOfThis; |
| 252 | 252 |
| 253 HType computeTypeOfThis() { | 253 HType getTypeOfThis() { |
| 254 Element element = closureData.thisElement; | 254 HType result = cachedTypeOfThis; |
| 255 ClassElement cls = element.enclosingElement.getEnclosingClass(); | 255 if (result == null) { |
| 256 Compiler compiler = builder.compiler; | 256 Element element = closureData.thisElement; |
| 257 DartType type = cls.computeType(compiler); | 257 ClassElement cls = element.enclosingElement.getEnclosingClass(); |
| 258 if (compiler.world.isUsedAsMixin(cls)) { | 258 Compiler compiler = builder.compiler; |
| 259 // If the enclosing class is used as a mixin, [:this:] can be | 259 DartType type = cls.computeType(compiler); |
| 260 // of the class that mixins the enclosing class. These two | 260 if (compiler.world.isUsedAsMixin(cls)) { |
| 261 // classes do not have a subclass relationship, so, for | 261 // If the enclosing class is used as a mixin, [:this:] can be |
| 262 // simplicity, we mark the type as an interface type. | 262 // of the class that mixins the enclosing class. These two |
| 263 cachedTypeOfThis = new HType.nonNullSubtype(type, compiler); | 263 // classes do not have a subclass relationship, so, for |
| 264 } else { | 264 // simplicity, we mark the type as an interface type. |
| 265 cachedTypeOfThis = new HType.nonNullSubclass(type, compiler); | 265 result = new HType.nonNullSubtype(type, compiler); |
| 266 } else { |
| 267 result = new HType.nonNullSubclass(type, compiler); |
| 268 } |
| 269 cachedTypeOfThis = result; |
| 266 } | 270 } |
| 267 return cachedTypeOfThis; | 271 return result; |
| 268 } | 272 } |
| 269 | 273 |
| 270 /** | 274 /** |
| 271 * Documentation wanted -- johnniwinther | 275 * Documentation wanted -- johnniwinther |
| 272 * | 276 * |
| 273 * Invariant: [function] must be an implementation element. | 277 * Invariant: [function] must be an implementation element. |
| 274 */ | 278 */ |
| 275 void startFunction(Element element, Expression node) { | 279 void startFunction(Element element, Expression node) { |
| 276 assert(invariant(node, element.isImplementation)); | 280 assert(invariant(node, element.isImplementation)); |
| 277 Compiler compiler = builder.compiler; | 281 Compiler compiler = builder.compiler; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 HThis thisInstruction = new HThis(closureData.thisElement); | 317 HThis thisInstruction = new HThis(closureData.thisElement); |
| 314 builder.graph.thisInstruction = thisInstruction; | 318 builder.graph.thisInstruction = thisInstruction; |
| 315 builder.graph.entry.addAtEntry(thisInstruction); | 319 builder.graph.entry.addAtEntry(thisInstruction); |
| 316 updateLocal(closureData.closureElement, thisInstruction); | 320 updateLocal(closureData.closureElement, thisInstruction); |
| 317 } else if (element.isInstanceMember() | 321 } else if (element.isInstanceMember() |
| 318 || element.isGenerativeConstructor()) { | 322 || element.isGenerativeConstructor()) { |
| 319 // Once closures have been mapped to classes their instance members might | 323 // Once closures have been mapped to classes their instance members might |
| 320 // not have any thisElement if the closure was created inside a static | 324 // not have any thisElement if the closure was created inside a static |
| 321 // context. | 325 // context. |
| 322 HThis thisInstruction = new HThis( | 326 HThis thisInstruction = new HThis( |
| 323 closureData.thisElement, computeTypeOfThis()); | 327 closureData.thisElement, getTypeOfThis()); |
| 324 builder.graph.thisInstruction = thisInstruction; | 328 builder.graph.thisInstruction = thisInstruction; |
| 325 builder.graph.entry.addAtEntry(thisInstruction); | 329 builder.graph.entry.addAtEntry(thisInstruction); |
| 326 directLocals[closureData.thisElement] = thisInstruction; | 330 directLocals[closureData.thisElement] = thisInstruction; |
| 327 } | 331 } |
| 328 | 332 |
| 329 // If this method is an intercepted method, add the extra | 333 // If this method is an intercepted method, add the extra |
| 330 // parameter to it, that is the actual receiver. | 334 // parameter to it, that is the actual receiver. |
| 331 ClassElement cls = element.getEnclosingClass(); | 335 ClassElement cls = element.getEnclosingClass(); |
| 332 if (builder.backend.isInterceptorClass(cls)) { | 336 if (builder.backend.isInterceptorClass(cls)) { |
| 333 HType type = HType.UNKNOWN; | 337 HType type = HType.UNKNOWN; |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 HLocalValue local = getLocal(element); | 432 HLocalValue local = getLocal(element); |
| 429 HInstruction variable = new HLocalGet(element, local); | 433 HInstruction variable = new HLocalGet(element, local); |
| 430 builder.add(variable); | 434 builder.add(variable); |
| 431 return variable; | 435 return variable; |
| 432 } | 436 } |
| 433 } | 437 } |
| 434 | 438 |
| 435 HInstruction readThis() { | 439 HInstruction readThis() { |
| 436 HInstruction res = readLocal(closureData.thisElement); | 440 HInstruction res = readLocal(closureData.thisElement); |
| 437 if (res.guaranteedType == null) { | 441 if (res.guaranteedType == null) { |
| 438 if (cachedTypeOfThis == null) { | 442 res.guaranteedType = getTypeOfThis(); |
| 439 computeTypeOfThis(); | |
| 440 } | |
| 441 res.guaranteedType = cachedTypeOfThis; | |
| 442 } | 443 } |
| 443 return res; | 444 return res; |
| 444 } | 445 } |
| 445 | 446 |
| 446 HLocalValue getLocal(Element element) { | 447 HLocalValue getLocal(Element element) { |
| 447 // If the element is a parameter, we already have a | 448 // If the element is a parameter, we already have a |
| 448 // HParameterValue for it. We cannot create another one because | 449 // HParameterValue for it. We cannot create another one because |
| 449 // it could then have another name than the real parameter. And | 450 // it could then have another name than the real parameter. And |
| 450 // the other one would not know it is just a copy of the real | 451 // the other one would not know it is just a copy of the real |
| 451 // parameter. | 452 // parameter. |
| (...skipping 1863 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2315 return; | 2316 return; |
| 2316 default: | 2317 default: |
| 2317 compiler.internalError("Unexpected operator $op", node: op); | 2318 compiler.internalError("Unexpected operator $op", node: op); |
| 2318 break; | 2319 break; |
| 2319 } | 2320 } |
| 2320 | 2321 |
| 2321 pushWithPosition( | 2322 pushWithPosition( |
| 2322 buildInvokeDynamic(send, selector, left, [right]), | 2323 buildInvokeDynamic(send, selector, left, [right]), |
| 2323 op); | 2324 op); |
| 2324 if (op.source.stringValue == '!=') { | 2325 if (op.source.stringValue == '!=') { |
| 2325 HBoolify bl = new HBoolify(pop()); | 2326 pushWithPosition(new HNot(popBoolified()), op); |
| 2326 add(bl); | |
| 2327 pushWithPosition(new HNot(bl), op); | |
| 2328 } | 2327 } |
| 2329 } | 2328 } |
| 2330 | 2329 |
| 2331 HInstruction generateInstanceSendReceiver(Send send) { | 2330 HInstruction generateInstanceSendReceiver(Send send) { |
| 2332 assert(Elements.isInstanceSend(send, elements)); | 2331 assert(Elements.isInstanceSend(send, elements)); |
| 2333 if (send.receiver == null) { | 2332 if (send.receiver == null) { |
| 2334 return localsHandler.readThis(); | 2333 return localsHandler.readThis(); |
| 2335 } | 2334 } |
| 2336 visit(send.receiver); | 2335 visit(send.receiver); |
| 2337 return pop(); | 2336 return pop(); |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2782 compiler); | 2781 compiler); |
| 2783 } | 2782 } |
| 2784 | 2783 |
| 2785 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { | 2784 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| 2786 for (; !link.isEmpty; link = link.tail) { | 2785 for (; !link.isEmpty; link = link.tail) { |
| 2787 visit(link.head); | 2786 visit(link.head); |
| 2788 list.add(pop()); | 2787 list.add(pop()); |
| 2789 } | 2788 } |
| 2790 } | 2789 } |
| 2791 | 2790 |
| 2792 visitDynamicSend(Send node) { | 2791 bool isThisSend(Send send) { |
| 2792 Node receiver = send.receiver; |
| 2793 if (receiver == null) return true; |
| 2794 Identifier identifier = receiver.asIdentifier(); |
| 2795 return identifier != null && identifier.isThis(); |
| 2796 } |
| 2797 |
| 2798 visitDynamicSend(Send node, {bool inline: true}) { |
| 2793 Selector selector = elements.getSelector(node); | 2799 Selector selector = elements.getSelector(node); |
| 2794 | 2800 |
| 2795 SourceString dartMethodName; | 2801 // TODO(kasperl): It would be much better to try to get the |
| 2796 bool isNotEquals = false; | 2802 // guaranteed type of the receiver after we've evaluated it, but |
| 2797 if (node.isIndex && !node.arguments.tail.isEmpty) { | 2803 // because of the way inlining currently works that is hard to do |
| 2798 dartMethodName = Elements.constructOperatorName( | 2804 // with re-evaluating the receiver. |
| 2799 const SourceString('[]='), false); | 2805 if (isThisSend(node)) { |
| 2800 } else if (node.selector.asOperator() != null) { | 2806 HType receiverType = localsHandler.getTypeOfThis(); |
| 2801 SourceString name = node.selector.asIdentifier().source; | 2807 selector = receiverType.refine(selector, compiler); |
| 2802 isNotEquals = identical(name.stringValue, '!='); | |
| 2803 dartMethodName = Elements.constructOperatorName( | |
| 2804 name, node.argumentsNode is Prefix); | |
| 2805 } else { | |
| 2806 dartMethodName = node.selector.asIdentifier().source; | |
| 2807 } | 2808 } |
| 2808 | 2809 |
| 2809 Element element = elements[node]; | 2810 Element element = compiler.world.locateSingleElement(selector); |
| 2810 bool isClosureCall = false; | 2811 bool isClosureCall = false; |
| 2811 if (element != null && compiler.world.hasNoOverridingMember(element)) { | 2812 if (inline && element != null) { |
| 2812 if (tryInlineMethod(element, selector, node.arguments, node)) { | 2813 if (tryInlineMethod(element, selector, node.arguments, node)) { |
| 2813 if (element.isGetter()) { | 2814 if (element.isGetter()) { |
| 2814 // If the element is a getter, we are doing a closure call | 2815 // If the element is a getter, we are doing a closure call |
| 2815 // on what this getter returns. | 2816 // on what this getter returns. |
| 2816 assert(selector.isCall()); | 2817 assert(selector.isCall()); |
| 2817 isClosureCall = true; | 2818 isClosureCall = true; |
| 2818 } else { | 2819 } else { |
| 2819 return; | 2820 return; |
| 2820 } | 2821 } |
| 2821 } | 2822 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2838 | 2839 |
| 2839 HInstruction invoke; | 2840 HInstruction invoke; |
| 2840 if (isClosureCall) { | 2841 if (isClosureCall) { |
| 2841 Selector closureSelector = new Selector.callClosureFrom(selector); | 2842 Selector closureSelector = new Selector.callClosureFrom(selector); |
| 2842 invoke = new HInvokeClosure(closureSelector, inputs); | 2843 invoke = new HInvokeClosure(closureSelector, inputs); |
| 2843 } else { | 2844 } else { |
| 2844 invoke = buildInvokeDynamic(node, selector, receiver, inputs); | 2845 invoke = buildInvokeDynamic(node, selector, receiver, inputs); |
| 2845 } | 2846 } |
| 2846 | 2847 |
| 2847 pushWithPosition(invoke, node); | 2848 pushWithPosition(invoke, node); |
| 2848 | |
| 2849 if (isNotEquals) { | |
| 2850 HNot not = new HNot(popBoolified()); | |
| 2851 push(not); | |
| 2852 } | |
| 2853 } | 2849 } |
| 2854 | 2850 |
| 2855 visitClosureSend(Send node) { | 2851 visitClosureSend(Send node) { |
| 2856 Selector selector = elements.getSelector(node); | 2852 Selector selector = elements.getSelector(node); |
| 2857 assert(node.receiver == null); | 2853 assert(node.receiver == null); |
| 2858 Element element = elements[node]; | 2854 Element element = elements[node]; |
| 2859 HInstruction closureTarget; | 2855 HInstruction closureTarget; |
| 2860 if (element == null) { | 2856 if (element == null) { |
| 2861 visit(node.selector); | 2857 visit(node.selector); |
| 2862 closureTarget = pop(); | 2858 closureTarget = pop(); |
| (...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3600 add(target); | 3596 add(target); |
| 3601 var inputs = <HInstruction>[target, context]; | 3597 var inputs = <HInstruction>[target, context]; |
| 3602 addDynamicSendArgumentsToList(node, inputs); | 3598 addDynamicSendArgumentsToList(node, inputs); |
| 3603 if (!identical(node.assignmentOperator.source.stringValue, '=')) { | 3599 if (!identical(node.assignmentOperator.source.stringValue, '=')) { |
| 3604 compiler.unimplemented('complex super assignment', | 3600 compiler.unimplemented('complex super assignment', |
| 3605 node: node.assignmentOperator); | 3601 node: node.assignmentOperator); |
| 3606 } | 3602 } |
| 3607 push(new HInvokeSuper(inputs, isSetter: true)); | 3603 push(new HInvokeSuper(inputs, isSetter: true)); |
| 3608 } else if (node.isIndex) { | 3604 } else if (node.isIndex) { |
| 3609 if (const SourceString("=") == op.source) { | 3605 if (const SourceString("=") == op.source) { |
| 3610 visitDynamicSend(node); | 3606 // TODO(kasperl): We temporarily disable inlining because the |
| 3607 // code here cannot deal with it yet. |
| 3608 visitDynamicSend(node, inline: false); |
| 3611 HInvokeDynamicMethod method = pop(); | 3609 HInvokeDynamicMethod method = pop(); |
| 3612 // Push the value. | 3610 // Push the value. |
| 3613 stack.add(method.inputs.last); | 3611 stack.add(method.inputs.last); |
| 3614 } else { | 3612 } else { |
| 3615 visit(node.receiver); | 3613 visit(node.receiver); |
| 3616 HInstruction receiver = pop(); | 3614 HInstruction receiver = pop(); |
| 3617 visit(node.argumentsNode); | 3615 visit(node.argumentsNode); |
| 3618 HInstruction value; | 3616 HInstruction value; |
| 3619 HInstruction index; | 3617 HInstruction index; |
| 3620 // Compound assignments are considered as being prefix. | 3618 // Compound assignments are considered as being prefix. |
| 3621 bool isCompoundAssignment = op.source.stringValue.endsWith('='); | 3619 bool isCompoundAssignment = op.source.stringValue.endsWith('='); |
| 3622 bool isPrefix = !node.isPostfix; | 3620 bool isPrefix = !node.isPostfix; |
| 3623 Element getter = elements[node.selector]; | |
| 3624 if (isCompoundAssignment) { | 3621 if (isCompoundAssignment) { |
| 3625 value = pop(); | 3622 value = pop(); |
| 3626 index = pop(); | 3623 index = pop(); |
| 3627 } else { | 3624 } else { |
| 3628 index = pop(); | 3625 index = pop(); |
| 3629 value = graph.addConstantInt(1, constantSystem); | 3626 value = graph.addConstantInt(1, constantSystem); |
| 3630 } | 3627 } |
| 3631 | 3628 |
| 3632 HInvokeDynamicMethod left = buildInvokeDynamic( | 3629 HInvokeDynamicMethod left = buildInvokeDynamic( |
| 3633 node, new Selector.index(), receiver, [index]); | 3630 node, new Selector.index(), receiver, [index]); |
| 3634 add(left); | 3631 add(left); |
| 3635 visitBinary(left, op, value, node); | 3632 visitBinary(left, op, value, node); |
| 3636 value = pop(); | 3633 value = pop(); |
| 3637 HInvokeDynamicMethod assign = buildInvokeDynamic( | 3634 HInvokeDynamicMethod assign = buildInvokeDynamic( |
| 3638 node, new Selector.indexSet(), receiver, [index, value]); | 3635 node, new Selector.indexSet(), receiver, [index, value]); |
| 3639 add(assign); | 3636 add(assign); |
| 3640 if (isPrefix) { | 3637 if (isPrefix) { |
| 3641 stack.add(value); | 3638 stack.add(value); |
| 3642 } else { | 3639 } else { |
| 3643 stack.add(left); | 3640 stack.add(left); |
| 3644 } | 3641 } |
| 3645 } | 3642 } |
| 3646 } else if (const SourceString("=") == op.source) { | 3643 } else if (const SourceString("=") == op.source) { |
| 3647 Element element = elements[node]; | |
| 3648 Link<Node> link = node.arguments; | 3644 Link<Node> link = node.arguments; |
| 3649 assert(!link.isEmpty && link.tail.isEmpty); | 3645 assert(!link.isEmpty && link.tail.isEmpty); |
| 3650 visit(link.head); | 3646 visit(link.head); |
| 3651 HInstruction value = pop(); | 3647 HInstruction value = pop(); |
| 3652 generateSetter(node, element, value); | 3648 generateSetter(node, element, value); |
| 3653 } else if (identical(op.source.stringValue, "is")) { | 3649 } else if (identical(op.source.stringValue, "is")) { |
| 3654 compiler.internalError("is-operator as SendSet", node: op); | 3650 compiler.internalError("is-operator as SendSet", node: op); |
| 3655 } else { | 3651 } else { |
| 3656 assert(const SourceString("++") == op.source || | 3652 assert(const SourceString("++") == op.source || |
| 3657 const SourceString("--") == op.source || | 3653 const SourceString("--") == op.source || |
| 3658 node.assignmentOperator.source.stringValue.endsWith("=")); | 3654 node.assignmentOperator.source.stringValue.endsWith("=")); |
| 3659 Element element = elements[node]; | |
| 3660 bool isCompoundAssignment = !node.arguments.isEmpty; | 3655 bool isCompoundAssignment = !node.arguments.isEmpty; |
| 3661 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. | 3656 bool isPrefix = !node.isPostfix; // Compound assignments are prefix. |
| 3662 | 3657 |
| 3663 // [receiver] is only used if the node is an instance send. | 3658 // [receiver] is only used if the node is an instance send. |
| 3664 HInstruction receiver = null; | 3659 HInstruction receiver = null; |
| 3665 Element selectorElement = elements[node]; | |
| 3666 if (Elements.isInstanceSend(node, elements)) { | 3660 if (Elements.isInstanceSend(node, elements)) { |
| 3667 receiver = generateInstanceSendReceiver(node); | 3661 receiver = generateInstanceSendReceiver(node); |
| 3668 generateInstanceGetterWithCompiledReceiver(node, receiver); | 3662 generateInstanceGetterWithCompiledReceiver(node, receiver); |
| 3669 } else { | 3663 } else { |
| 3670 generateGetter(node, elements[node.selector]); | 3664 generateGetter(node, elements[node.selector]); |
| 3671 } | 3665 } |
| 3672 HInstruction left = pop(); | 3666 HInstruction left = pop(); |
| 3673 HInstruction right; | 3667 HInstruction right; |
| 3674 if (isCompoundAssignment) { | 3668 if (isCompoundAssignment) { |
| 3675 visit(node.argumentsNode); | 3669 visit(node.argumentsNode); |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3925 void buildInitializer() { | 3919 void buildInitializer() { |
| 3926 SourceString iteratorName = const SourceString("iterator"); | 3920 SourceString iteratorName = const SourceString("iterator"); |
| 3927 Selector selector = | 3921 Selector selector = |
| 3928 new Selector.getter(iteratorName, currentElement.getLibrary()); | 3922 new Selector.getter(iteratorName, currentElement.getLibrary()); |
| 3929 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); | 3923 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); |
| 3930 visit(node.expression); | 3924 visit(node.expression); |
| 3931 HInstruction receiver = pop(); | 3925 HInstruction receiver = pop(); |
| 3932 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); | 3926 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); |
| 3933 if (interceptedClasses == null) { | 3927 if (interceptedClasses == null) { |
| 3934 iterator = | 3928 iterator = |
| 3935 new HInvokeDynamicGetter(selector, null, receiver, hasGetter); | 3929 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter); |
| 3936 } else { | 3930 } else { |
| 3937 HInterceptor interceptor = | 3931 HInterceptor interceptor = |
| 3938 invokeInterceptor(interceptedClasses, receiver, null); | 3932 invokeInterceptor(interceptedClasses, receiver, null); |
| 3939 iterator = | 3933 iterator = |
| 3940 new HInvokeDynamicGetter(selector, null, interceptor, hasGetter); | 3934 new HInvokeDynamicGetter(selector, null, interceptor, !hasGetter); |
| 3941 // Add the receiver as an argument to the getter call on the | 3935 // Add the receiver as an argument to the getter call on the |
| 3942 // interceptor. | 3936 // interceptor. |
| 3943 iterator.inputs.add(receiver); | 3937 iterator.inputs.add(receiver); |
| 3944 } | 3938 } |
| 3945 add(iterator); | 3939 add(iterator); |
| 3946 } | 3940 } |
| 3947 HInstruction buildCondition() { | 3941 HInstruction buildCondition() { |
| 3948 SourceString name = const SourceString('moveNext'); | 3942 SourceString name = const SourceString('moveNext'); |
| 3949 Selector selector = new Selector.call( | 3943 Selector selector = new Selector.call( |
| 3950 name, currentElement.getLibrary(), 0); | 3944 name, currentElement.getLibrary(), 0); |
| 3951 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); | |
| 3952 push(new HInvokeDynamicMethod(selector, <HInstruction>[iterator])); | 3945 push(new HInvokeDynamicMethod(selector, <HInstruction>[iterator])); |
| 3953 return popBoolified(); | 3946 return popBoolified(); |
| 3954 } | 3947 } |
| 3955 void buildBody() { | 3948 void buildBody() { |
| 3956 SourceString name = const SourceString('current'); | 3949 SourceString name = const SourceString('current'); |
| 3957 Selector call = new Selector.getter(name, currentElement.getLibrary()); | 3950 Selector call = new Selector.getter(name, currentElement.getLibrary()); |
| 3958 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call); | 3951 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call); |
| 3959 push(new HInvokeDynamicGetter(call, null, iterator, hasGetter)); | 3952 push(new HInvokeDynamicGetter(call, null, iterator, !hasGetter)); |
| 3960 | 3953 |
| 3961 Element variable; | 3954 Element variable; |
| 3962 if (node.declaredIdentifier.asSend() != null) { | 3955 if (node.declaredIdentifier.asSend() != null) { |
| 3963 variable = elements[node.declaredIdentifier]; | 3956 variable = elements[node.declaredIdentifier]; |
| 3964 } else { | 3957 } else { |
| 3965 assert(node.declaredIdentifier.asVariableDefinitions() != null); | 3958 assert(node.declaredIdentifier.asVariableDefinitions() != null); |
| 3966 VariableDefinitions variableDefinitions = node.declaredIdentifier; | 3959 VariableDefinitions variableDefinitions = node.declaredIdentifier; |
| 3967 variable = elements[variableDefinitions.definitions.nodes.head]; | 3960 variable = elements[variableDefinitions.definitions.nodes.head]; |
| 3968 } | 3961 } |
| 3969 HInstruction oldVariable = pop(); | 3962 HInstruction oldVariable = pop(); |
| (...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5076 new HSubGraphBlockInformation(elseBranch.graph)); | 5069 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5077 | 5070 |
| 5078 HBasicBlock conditionStartBlock = conditionBranch.block; | 5071 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5079 conditionStartBlock.setBlockFlow(info, joinBlock); | 5072 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5080 SubGraph conditionGraph = conditionBranch.graph; | 5073 SubGraph conditionGraph = conditionBranch.graph; |
| 5081 HIf branch = conditionGraph.end.last; | 5074 HIf branch = conditionGraph.end.last; |
| 5082 assert(branch is HIf); | 5075 assert(branch is HIf); |
| 5083 branch.blockInformation = conditionStartBlock.blockFlow; | 5076 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5084 } | 5077 } |
| 5085 } | 5078 } |
| OLD | NEW |