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 library compiler.src.inferrer.closure_tracer; | 5 library compiler.src.inferrer.closure_tracer; |
6 | 6 |
7 import '../common/names.dart' show Names; | 7 import '../common/names.dart' show Names; |
8 import '../elements/elements.dart'; | 8 import '../elements/elements.dart'; |
| 9 import '../elements/entities.dart'; |
9 import '../js_backend/backend.dart' show JavaScriptBackend; | 10 import '../js_backend/backend.dart' show JavaScriptBackend; |
10 import '../types/types.dart' show TypeMask; | 11 import '../types/types.dart' show TypeMask; |
11 import '../universe/selector.dart' show Selector; | 12 import '../universe/selector.dart' show Selector; |
12 import 'debug.dart' as debug; | 13 import 'debug.dart' as debug; |
13 import 'inferrer_engine.dart'; | 14 import 'inferrer_engine.dart'; |
14 import 'node_tracer.dart'; | 15 import 'node_tracer.dart'; |
15 import 'type_graph_nodes.dart'; | 16 import 'type_graph_nodes.dart'; |
16 | 17 |
17 class ClosureTracerVisitor extends TracerVisitor { | 18 class ClosureTracerVisitor extends TracerVisitor { |
18 final Iterable<MethodElement> tracedElements; | 19 final Iterable<FunctionEntity> tracedElements; |
19 final List<CallSiteTypeInformation> _callsToAnalyze = | 20 final List<CallSiteTypeInformation> _callsToAnalyze = |
20 new List<CallSiteTypeInformation>(); | 21 new List<CallSiteTypeInformation>(); |
21 | 22 |
22 ClosureTracerVisitor(this.tracedElements, ApplyableTypeInformation tracedType, | 23 ClosureTracerVisitor(this.tracedElements, ApplyableTypeInformation tracedType, |
23 InferrerEngine inferrer) | 24 InferrerEngine inferrer) |
24 : super(tracedType, inferrer); | 25 : super(tracedType, inferrer); |
25 | 26 |
26 ApplyableTypeInformation get tracedType => super.tracedType; | 27 ApplyableTypeInformation get tracedType => super.tracedType; |
27 | 28 |
28 void run() { | 29 void run() { |
29 analyze(); | 30 analyze(); |
30 if (!continueAnalyzing) return; | 31 if (!continueAnalyzing) return; |
31 _callsToAnalyze.forEach(_analyzeCall); | 32 _callsToAnalyze.forEach(_analyzeCall); |
32 for (MethodElement e in tracedElements) { | 33 for (MethodElement element in tracedElements) { |
33 e.functionSignature.forEachParameter((Element parameter) { | 34 MethodElement implementation = element.implementation; |
| 35 implementation.functionSignature.forEachParameter((Element parameter) { |
34 ElementTypeInformation info = | 36 ElementTypeInformation info = |
35 inferrer.types.getInferredTypeOfParameter(parameter); | 37 inferrer.types.getInferredTypeOfParameter(parameter); |
36 info.disableInferenceForClosures = false; | 38 info.disableInferenceForClosures = false; |
37 }); | 39 }); |
38 } | 40 } |
39 } | 41 } |
40 | 42 |
41 void _tagAsFunctionApplyTarget([String reason]) { | 43 void _tagAsFunctionApplyTarget([String reason]) { |
42 tracedType.mightBePassedToFunctionApply = true; | 44 tracedType.mightBePassedToFunctionApply = true; |
43 if (debug.VERBOSE) { | 45 if (debug.VERBOSE) { |
44 print("Closure $tracedType might be passed to apply: $reason"); | 46 print("Closure $tracedType might be passed to apply: $reason"); |
45 } | 47 } |
46 } | 48 } |
47 | 49 |
48 void _registerCallForLaterAnalysis(CallSiteTypeInformation info) { | 50 void _registerCallForLaterAnalysis(CallSiteTypeInformation info) { |
49 _callsToAnalyze.add(info); | 51 _callsToAnalyze.add(info); |
50 } | 52 } |
51 | 53 |
52 void _analyzeCall(CallSiteTypeInformation info) { | 54 void _analyzeCall(CallSiteTypeInformation info) { |
53 Selector selector = info.selector; | 55 Selector selector = info.selector; |
54 TypeMask mask = info.mask; | 56 TypeMask mask = info.mask; |
55 tracedElements.forEach((MethodElement functionElement) { | 57 tracedElements.forEach((FunctionEntity functionElement) { |
56 if (!selector.callStructure | 58 if (!selector.callStructure |
57 .signatureApplies(functionElement.parameterStructure)) { | 59 .signatureApplies(functionElement.parameterStructure)) { |
58 return; | 60 return; |
59 } | 61 } |
60 inferrer.updateParameterAssignments( | 62 inferrer.updateParameterAssignments( |
61 info, functionElement, info.arguments, selector, mask, | 63 info, functionElement, info.arguments, selector, mask, |
62 remove: false, addToQueue: false); | 64 remove: false, addToQueue: false); |
63 }); | 65 }); |
64 } | 66 } |
65 | 67 |
66 @override | 68 @override |
67 visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) { | 69 visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) { |
68 super.visitClosureCallSiteTypeInformation(info); | 70 super.visitClosureCallSiteTypeInformation(info); |
69 if (info.closure == currentUser) { | 71 if (info.closure == currentUser) { |
70 _registerCallForLaterAnalysis(info); | 72 _registerCallForLaterAnalysis(info); |
71 } else { | 73 } else { |
72 bailout('Passed to a closure'); | 74 bailout('Passed to a closure'); |
73 } | 75 } |
74 } | 76 } |
75 | 77 |
76 @override | 78 @override |
77 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { | 79 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { |
78 super.visitStaticCallSiteTypeInformation(info); | 80 super.visitStaticCallSiteTypeInformation(info); |
79 Element called = info.calledElement; | 81 MemberEntity called = info.calledElement; |
80 if (compiler.backend | 82 if (inferrer.closedWorld.commonElements.isForeign(called)) { |
81 .isForeign(inferrer.closedWorld.commonElements, called)) { | |
82 String name = called.name; | 83 String name = called.name; |
83 if (name == JavaScriptBackend.JS || name == 'DART_CLOSURE_TO_JS') { | 84 if (name == JavaScriptBackend.JS || name == 'DART_CLOSURE_TO_JS') { |
84 bailout('Used in JS ${info.call}'); | 85 bailout('Used in JS ${info.call}'); |
85 } | 86 } |
86 } | 87 } |
87 if (called.isGetter && | 88 if (called.isGetter && |
88 info.selector != null && | 89 info.selector != null && |
89 info.selector.isCall && | 90 info.selector.isCall && |
90 inferrer.types.getInferredTypeOfMember(called) == currentUser) { | 91 inferrer.types.getInferredTypeOfMember(called) == currentUser) { |
91 // This node can be a closure call as well. For example, `foo()` | 92 // This node can be a closure call as well. For example, `foo()` |
92 // where `foo` is a getter. | 93 // where `foo` is a getter. |
93 _registerCallForLaterAnalysis(info); | 94 _registerCallForLaterAnalysis(info); |
94 } | 95 } |
95 if (called is MemberElement && | 96 if (_checkIfFunctionApply(called) && |
96 _checkIfFunctionApply(called) && | |
97 info.arguments != null && | 97 info.arguments != null && |
98 info.arguments.contains(currentUser)) { | 98 info.arguments.contains(currentUser)) { |
99 _tagAsFunctionApplyTarget("static call"); | 99 _tagAsFunctionApplyTarget("static call"); |
100 } | 100 } |
101 } | 101 } |
102 | 102 |
103 bool _checkIfCurrentUser(MemberElement element) => | 103 bool _checkIfCurrentUser(MemberEntity element) => |
104 inferrer.types.getInferredTypeOfMember(element) == currentUser; | 104 inferrer.types.getInferredTypeOfMember(element) == currentUser; |
105 | 105 |
106 bool _checkIfFunctionApply(MemberElement element) { | 106 bool _checkIfFunctionApply(MemberEntity element) { |
107 return inferrer.closedWorld.commonElements.isFunctionApplyMethod(element); | 107 return inferrer.closedWorld.commonElements.isFunctionApplyMethod(element); |
108 } | 108 } |
109 | 109 |
110 @override | 110 @override |
111 visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) { | 111 visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) { |
112 super.visitDynamicCallSiteTypeInformation(info); | 112 super.visitDynamicCallSiteTypeInformation(info); |
113 if (info.selector.isCall) { | 113 if (info.selector.isCall) { |
114 if (info.arguments.contains(currentUser)) { | 114 if (info.arguments.contains(currentUser)) { |
115 if (!info.targets.every((element) => element.isFunction)) { | 115 if (!info.targets.every((element) => element.isFunction)) { |
116 bailout('Passed to a closure'); | 116 bailout('Passed to a closure'); |
(...skipping 20 matching lines...) Expand all Loading... |
137 @override | 137 @override |
138 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { | 138 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { |
139 super.visitStaticCallSiteTypeInformation(info); | 139 super.visitStaticCallSiteTypeInformation(info); |
140 if (info.calledElement == tracedElements.first && | 140 if (info.calledElement == tracedElements.first && |
141 info.selector != null && | 141 info.selector != null && |
142 info.selector.isGetter) { | 142 info.selector.isGetter) { |
143 addNewEscapeInformation(info); | 143 addNewEscapeInformation(info); |
144 } | 144 } |
145 } | 145 } |
146 } | 146 } |
OLD | NEW |