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

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

Issue 694353007: Move dart2js from sdk/lib/_internal/compiler to pkg/compiler (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 1 month 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of type_graph_inferrer;
6
7 /**
8 * A set of selector names that [List] implements, that we know do not
9 * change the element type of the list, or let the list escape to code
10 * that might change the element type.
11 */
12 Set<String> okListSelectorsSet = new Set<String>.from(
13 const <String>[
14 // From Object.
15 '==',
16 'hashCode',
17 'toString',
18 'noSuchMethod',
19 'runtimeType',
20
21 // From Iterable.
22 'iterator',
23 'map',
24 'where',
25 'expand',
26 'contains',
27 'forEach',
28 'reduce',
29 'fold',
30 'every',
31 'join',
32 'any',
33 'toList',
34 'toSet',
35 'length',
36 'isEmpty',
37 'isNotEmpty',
38 'take',
39 'takeWhile',
40 'skip',
41 'skipWhile',
42 'first',
43 'last',
44 'single',
45 'firstWhere',
46 'lastWhere',
47 'singleWhere',
48 'elementAt',
49
50 // From List.
51 '[]',
52 'length',
53 'reversed',
54 'sort',
55 'indexOf',
56 'lastIndexOf',
57 'clear',
58 'remove',
59 'removeAt',
60 'removeLast',
61 'removeWhere',
62 'retainWhere',
63 'sublist',
64 'getRange',
65 'removeRange',
66 'asMap',
67
68 // From JSArray.
69 'checkMutable',
70 'checkGrowable',
71 ]);
72
73 Set<String> doNotChangeLengthSelectorsSet = new Set<String>.from(
74 const <String>[
75 // From Object.
76 '==',
77 'hashCode',
78 'toString',
79 'noSuchMethod',
80 'runtimeType',
81
82 // From Iterable.
83 'iterator',
84 'map',
85 'where',
86 'expand',
87 'contains',
88 'forEach',
89 'reduce',
90 'fold',
91 'every',
92 'join',
93 'any',
94 'toList',
95 'toSet',
96 'length',
97 'isEmpty',
98 'isNotEmpty',
99 'take',
100 'takeWhile',
101 'skip',
102 'skipWhile',
103 'first',
104 'last',
105 'single',
106 'firstWhere',
107 'lastWhere',
108 'singleWhere',
109 'elementAt',
110
111 // From List.
112 '[]',
113 '[]=',
114 'length',
115 'reversed',
116 'sort',
117 'indexOf',
118 'lastIndexOf',
119 'sublist',
120 'getRange',
121 'asMap',
122
123 // From JSArray.
124 'checkMutable',
125 'checkGrowable',
126 ]);
127
128
129 class ListTracerVisitor extends TracerVisitor<ListTypeInformation> {
130 // The [Set] of found assignments to the list.
131 Set<TypeInformation> assignments = new Setlet<TypeInformation>();
132 bool callsGrowableMethod = false;
133
134 ListTracerVisitor(tracedType, inferrer) : super(tracedType, inferrer);
135
136 /**
137 * Returns [true] if the analysis completed successfully, [false] if it
138 * bailed out. In the former case, [assignments] holds a list of
139 * [TypeInformation] nodes that flow into the element type of this list.
140 */
141 bool run() {
142 analyze();
143 ListTypeInformation list = tracedType;
144 if (continueAnalyzing) {
145 if (!callsGrowableMethod && list.inferredLength == null) {
146 list.inferredLength = list.originalLength;
147 }
148 list.addFlowsIntoTargets(flowsInto);
149 return true;
150 } else {
151 callsGrowableMethod = true;
152 assignments = null;
153 return false;
154 }
155 }
156
157 visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) {
158 bailout('Passed to a closure');
159 }
160
161 visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) {
162 super.visitStaticCallSiteTypeInformation(info);
163 Element called = info.calledElement;
164 if (called.isForeign(compiler.backend) && called.name == 'JS') {
165 bailout('Used in JS ${info.call}');
166 }
167 }
168
169 visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) {
170 super.visitDynamicCallSiteTypeInformation(info);
171 Selector selector = info.selector;
172 String selectorName = selector.name;
173 if (currentUser == info.receiver) {
174 if (!okListSelectorsSet.contains(selectorName)) {
175 if (selector.isCall) {
176 int positionalLength = info.arguments.positional.length;
177 if (selectorName == 'add') {
178 if (positionalLength == 1) {
179 assignments.add(info.arguments.positional[0]);
180 }
181 } else if (selectorName == 'insert') {
182 if (positionalLength == 2) {
183 assignments.add(info.arguments.positional[1]);
184 }
185 } else {
186 bailout('Used in a not-ok selector');
187 return;
188 }
189 } else if (selector.isIndexSet) {
190 assignments.add(info.arguments.positional[1]);
191 } else if (!selector.isIndex) {
192 bailout('Used in a not-ok selector');
193 return;
194 }
195 }
196 if (!doNotChangeLengthSelectorsSet.contains(selectorName)) {
197 callsGrowableMethod = true;
198 }
199 if (selectorName == 'length' && selector.isSetter) {
200 callsGrowableMethod = true;
201 assignments.add(inferrer.types.nullType);
202 }
203 } else if (selector.isCall &&
204 !info.targets.every((element) => element.isFunction)) {
205 bailout('Passed to a closure');
206 return;
207 }
208 }
209 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698