Chromium Code Reviews| 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 2330 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2782 compiler); | 2783 compiler); |
| 2783 } | 2784 } |
| 2784 | 2785 |
| 2785 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { | 2786 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { |
| 2786 for (; !link.isEmpty; link = link.tail) { | 2787 for (; !link.isEmpty; link = link.tail) { |
| 2787 visit(link.head); | 2788 visit(link.head); |
| 2788 list.add(pop()); | 2789 list.add(pop()); |
| 2789 } | 2790 } |
| 2790 } | 2791 } |
| 2791 | 2792 |
| 2793 bool isThisSend(Send send) { | |
| 2794 Node receiver = send.receiver; | |
| 2795 if (receiver == null) return true; | |
| 2796 Identifier identifier = receiver.asIdentifier(); | |
| 2797 return identifier != null && identifier.isThis(); | |
| 2798 } | |
| 2799 | |
| 2792 visitDynamicSend(Send node) { | 2800 visitDynamicSend(Send node) { |
| 2793 Selector selector = elements.getSelector(node); | 2801 Selector selector = elements.getSelector(node); |
| 2794 | 2802 |
| 2803 // TODO(kasperl): It would be much better to try to get the | |
| 2804 // guaranteed type of the receiver after we've evaluated it, but | |
| 2805 // because of the way inlining currently works that is hard to do | |
| 2806 // with re-evaluating the receiver. | |
| 2807 if (isThisSend(node)) { | |
| 2808 HType receiverType = localsHandler.getTypeOfThis(); | |
| 2809 selector = receiverType.refine(selector, compiler); | |
| 2810 } | |
| 2811 | |
| 2795 SourceString dartMethodName; | 2812 SourceString dartMethodName; |
| 2796 bool isNotEquals = false; | 2813 bool isNotEquals = false; |
| 2797 if (node.isIndex && !node.arguments.tail.isEmpty) { | 2814 if (node.isIndex && !node.arguments.tail.isEmpty) { |
| 2798 dartMethodName = Elements.constructOperatorName( | 2815 dartMethodName = Elements.constructOperatorName( |
| 2799 const SourceString('[]='), false); | 2816 const SourceString('[]='), false); |
| 2800 } else if (node.selector.asOperator() != null) { | 2817 } else if (node.selector.asOperator() != null) { |
| 2801 SourceString name = node.selector.asIdentifier().source; | 2818 SourceString name = node.selector.asIdentifier().source; |
| 2802 isNotEquals = identical(name.stringValue, '!='); | 2819 isNotEquals = identical(name.stringValue, '!='); |
| 2803 dartMethodName = Elements.constructOperatorName( | 2820 dartMethodName = Elements.constructOperatorName( |
| 2804 name, node.argumentsNode is Prefix); | 2821 name, node.argumentsNode is Prefix); |
| 2805 } else { | 2822 } else { |
| 2806 dartMethodName = node.selector.asIdentifier().source; | 2823 dartMethodName = node.selector.asIdentifier().source; |
| 2807 } | 2824 } |
| 2808 | 2825 |
| 2809 Element element = elements[node]; | 2826 Element element = compiler.world.locateSingleElement(selector); |
| 2810 bool isClosureCall = false; | 2827 bool isClosureCall = false; |
| 2811 if (element != null && compiler.world.hasNoOverridingMember(element)) { | 2828 if (element != null) { |
| 2812 if (tryInlineMethod(element, selector, node.arguments, node)) { | 2829 if (tryInlineMethod(element, selector, node.arguments, node)) { |
| 2813 if (element.isGetter()) { | 2830 if (element.isGetter()) { |
| 2814 // If the element is a getter, we are doing a closure call | 2831 // If the element is a getter, we are doing a closure call |
| 2815 // on what this getter returns. | 2832 // on what this getter returns. |
| 2816 assert(selector.isCall()); | 2833 assert(selector.isCall()); |
| 2817 isClosureCall = true; | 2834 isClosureCall = true; |
| 2818 } else { | 2835 } else { |
| 2819 return; | 2836 return; |
| 2820 } | 2837 } |
| 2821 } | 2838 } |
| (...skipping 1103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3925 void buildInitializer() { | 3942 void buildInitializer() { |
| 3926 SourceString iteratorName = const SourceString("iterator"); | 3943 SourceString iteratorName = const SourceString("iterator"); |
| 3927 Selector selector = | 3944 Selector selector = |
| 3928 new Selector.getter(iteratorName, currentElement.getLibrary()); | 3945 new Selector.getter(iteratorName, currentElement.getLibrary()); |
| 3929 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); | 3946 Set<ClassElement> interceptedClasses = getInterceptedClassesOn(selector); |
| 3930 visit(node.expression); | 3947 visit(node.expression); |
| 3931 HInstruction receiver = pop(); | 3948 HInstruction receiver = pop(); |
| 3932 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); | 3949 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); |
| 3933 if (interceptedClasses == null) { | 3950 if (interceptedClasses == null) { |
| 3934 iterator = | 3951 iterator = |
| 3935 new HInvokeDynamicGetter(selector, null, receiver, hasGetter); | 3952 new HInvokeDynamicGetter(selector, null, receiver, !hasGetter); |
|
ngeoffray
2013/02/18 08:35:34
change the constructor to have a named argument? T
| |
| 3936 } else { | 3953 } else { |
| 3937 HInterceptor interceptor = | 3954 HInterceptor interceptor = |
| 3938 invokeInterceptor(interceptedClasses, receiver, null); | 3955 invokeInterceptor(interceptedClasses, receiver, null); |
| 3939 iterator = | 3956 iterator = |
| 3940 new HInvokeDynamicGetter(selector, null, interceptor, hasGetter); | 3957 new HInvokeDynamicGetter(selector, null, interceptor, !hasGetter); |
| 3941 // Add the receiver as an argument to the getter call on the | 3958 // Add the receiver as an argument to the getter call on the |
| 3942 // interceptor. | 3959 // interceptor. |
| 3943 iterator.inputs.add(receiver); | 3960 iterator.inputs.add(receiver); |
| 3944 } | 3961 } |
| 3945 add(iterator); | 3962 add(iterator); |
| 3946 } | 3963 } |
| 3947 HInstruction buildCondition() { | 3964 HInstruction buildCondition() { |
| 3948 SourceString name = const SourceString('moveNext'); | 3965 SourceString name = const SourceString('moveNext'); |
| 3949 Selector selector = new Selector.call( | 3966 Selector selector = new Selector.call( |
| 3950 name, currentElement.getLibrary(), 0); | 3967 name, currentElement.getLibrary(), 0); |
| 3951 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); | 3968 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(selector); |
|
ngeoffray
2013/02/18 08:35:34
You can remove this hasGetter.
| |
| 3952 push(new HInvokeDynamicMethod(selector, <HInstruction>[iterator])); | 3969 push(new HInvokeDynamicMethod(selector, <HInstruction>[iterator])); |
| 3953 return popBoolified(); | 3970 return popBoolified(); |
| 3954 } | 3971 } |
| 3955 void buildBody() { | 3972 void buildBody() { |
| 3956 SourceString name = const SourceString('current'); | 3973 SourceString name = const SourceString('current'); |
| 3957 Selector call = new Selector.getter(name, currentElement.getLibrary()); | 3974 Selector call = new Selector.getter(name, currentElement.getLibrary()); |
| 3958 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call); | 3975 bool hasGetter = compiler.world.hasAnyUserDefinedGetter(call); |
| 3959 push(new HInvokeDynamicGetter(call, null, iterator, hasGetter)); | 3976 push(new HInvokeDynamicGetter(call, null, iterator, !hasGetter)); |
| 3960 | 3977 |
| 3961 Element variable; | 3978 Element variable; |
| 3962 if (node.declaredIdentifier.asSend() != null) { | 3979 if (node.declaredIdentifier.asSend() != null) { |
| 3963 variable = elements[node.declaredIdentifier]; | 3980 variable = elements[node.declaredIdentifier]; |
| 3964 } else { | 3981 } else { |
| 3965 assert(node.declaredIdentifier.asVariableDefinitions() != null); | 3982 assert(node.declaredIdentifier.asVariableDefinitions() != null); |
| 3966 VariableDefinitions variableDefinitions = node.declaredIdentifier; | 3983 VariableDefinitions variableDefinitions = node.declaredIdentifier; |
| 3967 variable = elements[variableDefinitions.definitions.nodes.head]; | 3984 variable = elements[variableDefinitions.definitions.nodes.head]; |
| 3968 } | 3985 } |
| 3969 HInstruction oldVariable = pop(); | 3986 HInstruction oldVariable = pop(); |
| (...skipping 1106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5076 new HSubGraphBlockInformation(elseBranch.graph)); | 5093 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5077 | 5094 |
| 5078 HBasicBlock conditionStartBlock = conditionBranch.block; | 5095 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5079 conditionStartBlock.setBlockFlow(info, joinBlock); | 5096 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5080 SubGraph conditionGraph = conditionBranch.graph; | 5097 SubGraph conditionGraph = conditionBranch.graph; |
| 5081 HIf branch = conditionGraph.end.last; | 5098 HIf branch = conditionGraph.end.last; |
| 5082 assert(branch is HIf); | 5099 assert(branch is HIf); |
| 5083 branch.blockInformation = conditionStartBlock.blockFlow; | 5100 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5084 } | 5101 } |
| 5085 } | 5102 } |
| OLD | NEW |