| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 type_graph_inferrer; | 5 part of type_graph_inferrer; |
| 6 | 6 |
| 7 class ClosureTracerVisitor extends TracerVisitor<ApplyableTypeInformation> { | 7 class ClosureTracerVisitor extends TracerVisitor<ApplyableTypeInformation> { |
| 8 final Iterable<FunctionElement> tracedElements; | 8 final Iterable<FunctionElement> tracedElements; |
| 9 | 9 |
| 10 ClosureTracerVisitor(this.tracedElements, tracedType, inferrer) | 10 ClosureTracerVisitor(this.tracedElements, tracedType, inferrer) |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 | 60 |
| 61 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { | 61 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { |
| 62 super.visitStaticCallSiteTypeInformation(info); | 62 super.visitStaticCallSiteTypeInformation(info); |
| 63 Element called = info.calledElement; | 63 Element called = info.calledElement; |
| 64 if (called.isForeign(compiler)) { | 64 if (called.isForeign(compiler)) { |
| 65 String name = called.name; | 65 String name = called.name; |
| 66 if (name == 'JS' || name == 'DART_CLOSURE_TO_JS') { | 66 if (name == 'JS' || name == 'DART_CLOSURE_TO_JS') { |
| 67 bailout('Used in JS ${info.call}'); | 67 bailout('Used in JS ${info.call}'); |
| 68 } | 68 } |
| 69 } | 69 } |
| 70 if (called.isGetter() | 70 if (called.isGetter |
| 71 && info.selector != null | 71 && info.selector != null |
| 72 && info.selector.isCall() | 72 && info.selector.isCall |
| 73 && inferrer.types.getInferredTypeOf(called) == currentUser) { | 73 && inferrer.types.getInferredTypeOf(called) == currentUser) { |
| 74 // This node can be a closure call as well. For example, `foo()` | 74 // This node can be a closure call as well. For example, `foo()` |
| 75 // where `foo` is a getter. | 75 // where `foo` is a getter. |
| 76 analyzeCall(info); | 76 analyzeCall(info); |
| 77 } | 77 } |
| 78 if (checkIfFunctionApply(called) && | 78 if (checkIfFunctionApply(called) && |
| 79 info.arguments != null && | 79 info.arguments != null && |
| 80 info.arguments.contains(currentUser)) { | 80 info.arguments.contains(currentUser)) { |
| 81 tagAsFunctionApplyTarget("static call"); | 81 tagAsFunctionApplyTarget("static call"); |
| 82 } | 82 } |
| 83 } | 83 } |
| 84 | 84 |
| 85 bool checkIfCurrentUser(element) { | 85 bool checkIfCurrentUser(element) { |
| 86 return inferrer.types.getInferredTypeOf(element) == currentUser; | 86 return inferrer.types.getInferredTypeOf(element) == currentUser; |
| 87 } | 87 } |
| 88 | 88 |
| 89 bool checkIfFunctionApply(element) { | 89 bool checkIfFunctionApply(element) { |
| 90 return compiler.functionApplyMethod == element; | 90 return compiler.functionApplyMethod == element; |
| 91 } | 91 } |
| 92 | 92 |
| 93 visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) { | 93 visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) { |
| 94 super.visitDynamicCallSiteTypeInformation(info); | 94 super.visitDynamicCallSiteTypeInformation(info); |
| 95 if (info.selector.isCall()) { | 95 if (info.selector.isCall) { |
| 96 if (info.arguments.contains(currentUser)) { | 96 if (info.arguments.contains(currentUser)) { |
| 97 if (!info.targets.every((element) => element.isFunction())) { | 97 if (!info.targets.every((element) => element.isFunction)) { |
| 98 bailout('Passed to a closure'); | 98 bailout('Passed to a closure'); |
| 99 } | 99 } |
| 100 if (info.targets.any(checkIfFunctionApply)) { | 100 if (info.targets.any(checkIfFunctionApply)) { |
| 101 tagAsFunctionApplyTarget("dynamic call"); | 101 tagAsFunctionApplyTarget("dynamic call"); |
| 102 } | 102 } |
| 103 } else if (info.targets.any((element) => checkIfCurrentUser(element))) { | 103 } else if (info.targets.any((element) => checkIfCurrentUser(element))) { |
| 104 analyzeCall(info); | 104 analyzeCall(info); |
| 105 } | 105 } |
| 106 } else if (info.selector.isGetter() && | 106 } else if (info.selector.isGetter && |
| 107 info.selector.name == Compiler.CALL_OPERATOR_NAME) { | 107 info.selector.name == Compiler.CALL_OPERATOR_NAME) { |
| 108 // We are potentially tearing off ourself here | 108 // We are potentially tearing off ourself here |
| 109 addNewEscapeInformation(info); | 109 addNewEscapeInformation(info); |
| 110 } | 110 } |
| 111 } | 111 } |
| 112 } | 112 } |
| 113 | 113 |
| 114 class StaticTearOffClosureTracerVisitor extends ClosureTracerVisitor { | 114 class StaticTearOffClosureTracerVisitor extends ClosureTracerVisitor { |
| 115 StaticTearOffClosureTracerVisitor(tracedElement, tracedType, inferrer) | 115 StaticTearOffClosureTracerVisitor(tracedElement, tracedType, inferrer) |
| 116 : super([tracedElement], tracedType, inferrer); | 116 : super([tracedElement], tracedType, inferrer); |
| 117 | 117 |
| 118 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { | 118 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { |
| 119 super.visitStaticCallSiteTypeInformation(info); | 119 super.visitStaticCallSiteTypeInformation(info); |
| 120 if (info.calledElement == tracedElements.first | 120 if (info.calledElement == tracedElements.first |
| 121 && info.selector != null | 121 && info.selector != null |
| 122 && info.selector.isGetter()) { | 122 && info.selector.isGetter) { |
| 123 addNewEscapeInformation(info); | 123 addNewEscapeInformation(info); |
| 124 } | 124 } |
| 125 } | 125 } |
| 126 } | 126 } |
| OLD | NEW |