Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(195)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/inferrer/closure_tracer.dart

Issue 223403003: Use closure tracer to identify closures that are not passed to Function.apply (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: fixed issue with failing test Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 { 7 class ClosureTracerVisitor extends TracerVisitor<ApplyableTypeInformation> {
8 final FunctionElement tracedElement; 8 final Iterable<FunctionElement> tracedElements;
9 9
10 ClosureTracerVisitor(this.tracedElement, tracedType, inferrer) 10 ClosureTracerVisitor(this.tracedElements, tracedType, inferrer)
11 : super(tracedType, inferrer); 11 : super(tracedType, inferrer);
12 12
13 void run() { 13 void run() {
14 tracedElement.functionSignature.forEachParameter((Element parameter) { 14 for (FunctionElement e in tracedElements) {
15 ElementTypeInformation info = inferrer.types.getInferredTypeOf(parameter); 15 e.functionSignature.forEachParameter((Element parameter) {
16 info.abandonInferencing = false; 16 ElementTypeInformation info =
17 }); 17 inferrer.types.getInferredTypeOf(parameter);
18 info.abandonInferencing = info.abandonInferencing &&
19 !info.mightResume;
20 });
21 }
18 analyze(); 22 analyze();
19 tracedElement.functionSignature.forEachParameter((Element parameter) { 23 for(FunctionElement e in tracedElements) {
20 ElementTypeInformation info = inferrer.types.getInferredTypeOf(parameter); 24 e.functionSignature.forEachParameter((Element parameter) {
21 if (continueAnalyzing) { 25 ElementTypeInformation info =
22 info.disableHandleSpecialCases = true; 26 inferrer.types.getInferredTypeOf(parameter);
23 } else { 27 if (continueAnalyzing) {
24 info.giveUp(inferrer); 28 info.disableHandleSpecialCases = true;
25 } 29 } else {
26 }); 30 info.giveUp(inferrer);
31 }
32 });
33 }
27 } 34 }
28 35
29 visitMapTypeInformation(MapTypeInformation info) { 36 void tagAsFunctionApplyTarget([String reason]) {
30 bailout('Stored in a map'); 37 tracedType.mightBePassedToFunctionApply = true;
38 if (_VERBOSE) {
39 print("Closure $tracedType might be passed to apply: $reason");
40 }
31 } 41 }
32 42
33 void analyzeCall(CallSiteTypeInformation info) { 43 void analyzeCall(CallSiteTypeInformation info) {
34 Selector selector = info.selector; 44 Selector selector = info.selector;
35 if (!selector.signatureApplies(tracedElement, compiler)) return; 45 tracedElements.forEach((FunctionElement functionElement) {
36 inferrer.updateParameterAssignments( 46 if (!selector.signatureApplies(functionElement, compiler)) return;
37 info, tracedElement, info.arguments, selector, remove: false, 47 inferrer.updateParameterAssignments(info, functionElement, info.arguments,
38 addToQueue: false); 48 selector, remove: false, addToQueue: false);
49 });
39 } 50 }
40 51
41 visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) { 52 visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
42 super.visitClosureCallSiteTypeInformation(info); 53 super.visitClosureCallSiteTypeInformation(info);
43 if (info.closure == currentUser) { 54 if (info.closure == currentUser) {
44 analyzeCall(info); 55 analyzeCall(info);
45 } else { 56 } else {
46 bailout('Passed to a closure'); 57 bailout('Passed to a closure');
47 } 58 }
48 } 59 }
49 60
50 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { 61 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
51 super.visitStaticCallSiteTypeInformation(info); 62 super.visitStaticCallSiteTypeInformation(info);
52 Element called = info.calledElement; 63 Element called = info.calledElement;
53 if (called.isForeign(compiler)) { 64 if (called.isForeign(compiler)) {
54 String name = called.name; 65 String name = called.name;
55 if (name == 'JS' || name == 'DART_CLOSURE_TO_JS') { 66 if (name == 'JS' || name == 'DART_CLOSURE_TO_JS') {
56 bailout('Used in JS ${info.call}'); 67 bailout('Used in JS ${info.call}');
57 } 68 }
58 } 69 }
59 if (called.isGetter() 70 if (called.isGetter()
60 && info.selector != null 71 && info.selector != null
61 && info.selector.isCall() 72 && info.selector.isCall()
62 && inferrer.types.getInferredTypeOf(called) == currentUser) { 73 && inferrer.types.getInferredTypeOf(called) == currentUser) {
63 // 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()`
64 // where `foo` is a getter. 75 // where `foo` is a getter.
65 analyzeCall(info); 76 analyzeCall(info);
66 } 77 }
78 if (checkIfFunctionApply(called) &&
79 info.arguments != null &&
80 info.arguments.contains(currentUser)) {
81 tagAsFunctionApplyTarget("static call");
82 }
67 } 83 }
68 84
69 bool checkIfCurrentUser(element) { 85 bool checkIfCurrentUser(element) {
70 return inferrer.types.getInferredTypeOf(element) == currentUser; 86 return inferrer.types.getInferredTypeOf(element) == currentUser;
71 } 87 }
72 88
89 bool checkIfFunctionApply(element) {
90 return compiler.functionApplyMethod == element;
91 }
92
73 visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) { 93 visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
74 super.visitDynamicCallSiteTypeInformation(info); 94 super.visitDynamicCallSiteTypeInformation(info);
75 if (info.selector.isCall()) { 95 if (info.selector.isCall()) {
76 if (info.arguments.contains(currentUser) 96 if (info.arguments.contains(currentUser)) {
77 && !info.targets.every((element) => element.isFunction())) { 97 if (!info.targets.every((element) => element.isFunction())) {
78 bailout('Passed to a closure'); 98 bailout('Passed to a closure');
99 }
100 if (info.targets.any(checkIfFunctionApply)) {
101 tagAsFunctionApplyTarget("dynamic call");
102 }
79 } else if (info.targets.any((element) => checkIfCurrentUser(element))) { 103 } else if (info.targets.any((element) => checkIfCurrentUser(element))) {
80 analyzeCall(info); 104 analyzeCall(info);
81 } 105 }
82 } 106 }
83 } 107 }
84 } 108 }
85 109
86 class StaticTearOffClosureTracerVisitor extends ClosureTracerVisitor { 110 class StaticTearOffClosureTracerVisitor extends ClosureTracerVisitor {
87 StaticTearOffClosureTracerVisitor(tracedElement, tracedType, inferrer) 111 StaticTearOffClosureTracerVisitor(tracedElement, tracedType, inferrer)
88 : super(tracedElement, tracedType, inferrer); 112 : super([tracedElement], tracedType, inferrer);
89 113
90 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { 114 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
91 super.visitStaticCallSiteTypeInformation(info); 115 super.visitStaticCallSiteTypeInformation(info);
92 if (info.calledElement == tracedElement 116 if (info.calledElement == tracedElements.first
93 && info.selector != null 117 && info.selector != null
94 && info.selector.isGetter()) { 118 && info.selector.isGetter()) {
95 addNewEscapeInformation(info); 119 addNewEscapeInformation(info);
96 } 120 }
97 } 121 }
98 } 122 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698