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 '../types/types.dart' show TypeMask; | 7 import '../types/types.dart' show TypeMask; |
8 import '../common/names.dart' show Names; | 8 import '../common/names.dart' show Names; |
9 import '../elements/elements.dart'; | 9 import '../elements/elements.dart'; |
10 import '../universe/selector.dart' show Selector; | 10 import '../universe/selector.dart' show Selector; |
11 import 'node_tracer.dart'; | 11 import 'node_tracer.dart'; |
12 import 'type_graph_nodes.dart'; | 12 import 'type_graph_nodes.dart'; |
13 import 'debug.dart' as debug; | 13 import 'debug.dart' as debug; |
14 | 14 |
15 | |
16 class ClosureTracerVisitor extends TracerVisitor<ApplyableTypeInformation> { | 15 class ClosureTracerVisitor extends TracerVisitor<ApplyableTypeInformation> { |
17 final Iterable<FunctionElement> tracedElements; | 16 final Iterable<FunctionElement> tracedElements; |
18 final List<CallSiteTypeInformation> _callsToAnalyze = | 17 final List<CallSiteTypeInformation> _callsToAnalyze = |
19 new List<CallSiteTypeInformation>(); | 18 new List<CallSiteTypeInformation>(); |
20 | 19 |
21 ClosureTracerVisitor(this.tracedElements, tracedType, inferrer) | 20 ClosureTracerVisitor(this.tracedElements, tracedType, inferrer) |
22 : super(tracedType, inferrer); | 21 : super(tracedType, inferrer); |
23 | 22 |
24 void run() { | 23 void run() { |
25 analyze(); | 24 analyze(); |
26 if (!continueAnalyzing) return; | 25 if (!continueAnalyzing) return; |
27 _callsToAnalyze.forEach(_analyzeCall); | 26 _callsToAnalyze.forEach(_analyzeCall); |
28 for(FunctionElement e in tracedElements) { | 27 for (FunctionElement e in tracedElements) { |
29 e.functionSignature.forEachParameter((Element parameter) { | 28 e.functionSignature.forEachParameter((Element parameter) { |
30 ElementTypeInformation info = | 29 ElementTypeInformation info = |
31 inferrer.types.getInferredTypeOf(parameter); | 30 inferrer.types.getInferredTypeOf(parameter); |
32 info.disableInferenceForClosures = false; | 31 info.disableInferenceForClosures = false; |
33 }); | 32 }); |
34 } | 33 } |
35 } | 34 } |
36 | 35 |
37 void _tagAsFunctionApplyTarget([String reason]) { | 36 void _tagAsFunctionApplyTarget([String reason]) { |
38 tracedType.mightBePassedToFunctionApply = true; | 37 tracedType.mightBePassedToFunctionApply = true; |
39 if (debug.VERBOSE) { | 38 if (debug.VERBOSE) { |
40 print("Closure $tracedType might be passed to apply: $reason"); | 39 print("Closure $tracedType might be passed to apply: $reason"); |
41 } | 40 } |
42 } | 41 } |
43 | 42 |
44 void _registerCallForLaterAnalysis(CallSiteTypeInformation info) { | 43 void _registerCallForLaterAnalysis(CallSiteTypeInformation info) { |
45 _callsToAnalyze.add(info); | 44 _callsToAnalyze.add(info); |
46 } | 45 } |
47 | 46 |
48 void _analyzeCall(CallSiteTypeInformation info) { | 47 void _analyzeCall(CallSiteTypeInformation info) { |
49 Selector selector = info.selector; | 48 Selector selector = info.selector; |
50 TypeMask mask = info.mask; | 49 TypeMask mask = info.mask; |
51 tracedElements.forEach((FunctionElement functionElement) { | 50 tracedElements.forEach((FunctionElement functionElement) { |
52 if (!selector.signatureApplies(functionElement)) return; | 51 if (!selector.signatureApplies(functionElement)) return; |
53 inferrer.updateParameterAssignments(info, functionElement, info.arguments, | 52 inferrer.updateParameterAssignments( |
54 selector, mask, remove: false, addToQueue: false); | 53 info, functionElement, info.arguments, selector, mask, |
| 54 remove: false, addToQueue: false); |
55 }); | 55 }); |
56 } | 56 } |
57 | 57 |
58 @override | 58 @override |
59 visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) { | 59 visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) { |
60 super.visitClosureCallSiteTypeInformation(info); | 60 super.visitClosureCallSiteTypeInformation(info); |
61 if (info.closure == currentUser) { | 61 if (info.closure == currentUser) { |
62 _registerCallForLaterAnalysis(info); | 62 _registerCallForLaterAnalysis(info); |
63 } else { | 63 } else { |
64 bailout('Passed to a closure'); | 64 bailout('Passed to a closure'); |
65 } | 65 } |
66 } | 66 } |
67 | 67 |
68 @override | 68 @override |
69 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { | 69 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { |
70 super.visitStaticCallSiteTypeInformation(info); | 70 super.visitStaticCallSiteTypeInformation(info); |
71 Element called = info.calledElement; | 71 Element called = info.calledElement; |
72 if (compiler.backend.isForeign(called)) { | 72 if (compiler.backend.isForeign(called)) { |
73 String name = called.name; | 73 String name = called.name; |
74 if (name == 'JS' || name == 'DART_CLOSURE_TO_JS') { | 74 if (name == 'JS' || name == 'DART_CLOSURE_TO_JS') { |
75 bailout('Used in JS ${info.call}'); | 75 bailout('Used in JS ${info.call}'); |
76 } | 76 } |
77 } | 77 } |
78 if (called.isGetter | 78 if (called.isGetter && |
79 && info.selector != null | 79 info.selector != null && |
80 && info.selector.isCall | 80 info.selector.isCall && |
81 && inferrer.types.getInferredTypeOf(called) == currentUser) { | 81 inferrer.types.getInferredTypeOf(called) == currentUser) { |
82 // This node can be a closure call as well. For example, `foo()` | 82 // This node can be a closure call as well. For example, `foo()` |
83 // where `foo` is a getter. | 83 // where `foo` is a getter. |
84 _registerCallForLaterAnalysis(info); | 84 _registerCallForLaterAnalysis(info); |
85 } | 85 } |
86 if (_checkIfFunctionApply(called) && | 86 if (_checkIfFunctionApply(called) && |
87 info.arguments != null && | 87 info.arguments != null && |
88 info.arguments.contains(currentUser)) { | 88 info.arguments.contains(currentUser)) { |
89 _tagAsFunctionApplyTarget("static call"); | 89 _tagAsFunctionApplyTarget("static call"); |
90 } | 90 } |
91 } | 91 } |
(...skipping 26 matching lines...) Expand all Loading... |
118 } | 118 } |
119 } | 119 } |
120 | 120 |
121 class StaticTearOffClosureTracerVisitor extends ClosureTracerVisitor { | 121 class StaticTearOffClosureTracerVisitor extends ClosureTracerVisitor { |
122 StaticTearOffClosureTracerVisitor(tracedElement, tracedType, inferrer) | 122 StaticTearOffClosureTracerVisitor(tracedElement, tracedType, inferrer) |
123 : super([tracedElement], tracedType, inferrer); | 123 : super([tracedElement], tracedType, inferrer); |
124 | 124 |
125 @override | 125 @override |
126 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { | 126 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { |
127 super.visitStaticCallSiteTypeInformation(info); | 127 super.visitStaticCallSiteTypeInformation(info); |
128 if (info.calledElement == tracedElements.first | 128 if (info.calledElement == tracedElements.first && |
129 && info.selector != null | 129 info.selector != null && |
130 && info.selector.isGetter) { | 130 info.selector.isGetter) { |
131 addNewEscapeInformation(info); | 131 addNewEscapeInformation(info); |
132 } | 132 } |
133 } | 133 } |
134 } | 134 } |
OLD | NEW |