OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'dart:io' hide Link; | 5 import 'dart:io' hide Link; |
6 import 'package:async_helper/async_helper.dart'; | 6 import 'package:async_helper/async_helper.dart'; |
7 import 'package:compiler/src/closure.dart'; | 7 import 'package:compiler/src/closure.dart'; |
8 import 'package:compiler/src/common.dart'; | 8 import 'package:compiler/src/common.dart'; |
9 import 'package:compiler/src/compiler.dart'; | 9 import 'package:compiler/src/compiler.dart'; |
10 import 'package:compiler/src/diagnostics/diagnostic_listener.dart'; | 10 import 'package:compiler/src/diagnostics/diagnostic_listener.dart'; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 popLocalFunction(); | 100 popLocalFunction(); |
101 } else { | 101 } else { |
102 super.visitFunctionExpression(node); | 102 super.visitFunctionExpression(node); |
103 } | 103 } |
104 } | 104 } |
105 | 105 |
106 @override | 106 @override |
107 String computeNodeValue(ast.Node node, [AstElement element]) { | 107 String computeNodeValue(ast.Node node, [AstElement element]) { |
108 if (element != null && element.isLocal) { | 108 if (element != null && element.isLocal) { |
109 if (element.isFunction) { | 109 if (element.isFunction) { |
110 return computeEntityValue(element); | 110 return computeObjectValue(element); |
111 } else { | 111 } else { |
112 LocalElement local = element; | 112 LocalElement local = element; |
113 return computeLocalValue(local); | 113 return computeLocalValue(local); |
114 } | 114 } |
115 } | 115 } |
116 // TODO(johnniwinther,efortuna): Collect data for other nodes? | 116 // TODO(johnniwinther,efortuna): Collect data for other nodes? |
117 return null; | 117 return null; |
118 } | 118 } |
119 | 119 |
120 @override | 120 @override |
121 String computeElementValue(AstElement element) { | 121 String computeElementValue(AstElement element) { |
122 // TODO(johnniwinther,efortuna): Collect data for the member | 122 // TODO(johnniwinther,efortuna): Collect data for the member |
123 // (has thisLocal, has box, etc.). | 123 // (has thisLocal, has box, etc.). |
124 return computeEntityValue(element); | 124 return computeObjectValue(element); |
125 } | 125 } |
126 } | 126 } |
127 | 127 |
128 /// Kernel IR visitor for computing closure data. | 128 /// Kernel IR visitor for computing closure data. |
129 class ClosureIrChecker extends IrDataExtractor with ComputeValueMixin<ir.Node> { | 129 class ClosureIrChecker extends IrDataExtractor with ComputeValueMixin<ir.Node> { |
130 final MemberEntity member; | 130 final MemberEntity member; |
131 final ClosureDataLookup<ir.Node> closureDataLookup; | 131 final ClosureDataLookup<ir.Node> closureDataLookup; |
132 final KernelToLocalsMap _localsMap; | 132 final KernelToLocalsMap _localsMap; |
133 final bool verbose; | 133 final bool verbose; |
134 | 134 |
(...skipping 16 matching lines...) Expand all Loading... |
151 | 151 |
152 visitFunctionDeclaration(ir.FunctionDeclaration node) { | 152 visitFunctionDeclaration(ir.FunctionDeclaration node) { |
153 pushLocalFunction(node); | 153 pushLocalFunction(node); |
154 super.visitFunctionDeclaration(node); | 154 super.visitFunctionDeclaration(node); |
155 popLocalFunction(); | 155 popLocalFunction(); |
156 } | 156 } |
157 | 157 |
158 @override | 158 @override |
159 String computeNodeValue(ir.Node node) { | 159 String computeNodeValue(ir.Node node) { |
160 if (node is ir.VariableDeclaration) { | 160 if (node is ir.VariableDeclaration) { |
| 161 if (node.parent is ir.FunctionDeclaration) { |
| 162 return computeObjectValue(node.parent); |
| 163 } |
161 Local local = _localsMap.getLocalVariable(node); | 164 Local local = _localsMap.getLocalVariable(node); |
162 return computeLocalValue(local); | 165 return computeLocalValue(local); |
| 166 } else if (node is ir.FunctionExpression) { |
| 167 return computeObjectValue(node); |
163 } | 168 } |
164 // TODO(johnniwinther,efortuna): Collect data for other nodes? | |
165 return null; | 169 return null; |
166 } | 170 } |
167 | 171 |
168 @override | 172 @override |
169 String computeMemberValue(ir.Member node) { | 173 String computeMemberValue(ir.Member node) { |
170 // TODO(johnniwinther,efortuna): Collect data for the member | 174 return computeObjectValue(member); |
171 // (has thisLocal, has box, etc.). | |
172 return computeEntityValue(member); | |
173 } | 175 } |
174 } | 176 } |
175 | 177 |
176 abstract class ComputeValueMixin<T> { | 178 abstract class ComputeValueMixin<T> { |
177 bool get verbose; | 179 bool get verbose; |
178 ClosureDataLookup<T> get closureDataLookup; | 180 ClosureDataLookup<T> get closureDataLookup; |
179 Link<ScopeInfo> scopeInfoStack = const Link<ScopeInfo>(); | 181 Link<ScopeInfo> scopeInfoStack = const Link<ScopeInfo>(); |
180 ScopeInfo get scopeInfo => scopeInfoStack.head; | 182 ScopeInfo get scopeInfo => scopeInfoStack.head; |
181 CapturedScope capturedScope; | 183 CapturedScope capturedScope; |
182 Link<ClosureRepresentationInfo> closureRepresentationInfoStack = | 184 Link<ClosureRepresentationInfo> closureRepresentationInfoStack = |
183 const Link<ClosureRepresentationInfo>(); | 185 const Link<ClosureRepresentationInfo>(); |
184 ClosureRepresentationInfo get closureRepresentationInfo => | 186 ClosureRepresentationInfo get closureRepresentationInfo => |
185 closureRepresentationInfoStack.head; | 187 closureRepresentationInfoStack.isNotEmpty |
| 188 ? closureRepresentationInfoStack.head |
| 189 : null; |
186 | 190 |
187 void pushMember(MemberEntity member) { | 191 void pushMember(MemberEntity member) { |
188 scopeInfoStack = | 192 scopeInfoStack = |
189 scopeInfoStack.prepend(closureDataLookup.getScopeInfo(member)); | 193 scopeInfoStack.prepend(closureDataLookup.getScopeInfo(member)); |
190 capturedScope = closureDataLookup.getCapturedScope(member); | 194 capturedScope = closureDataLookup.getCapturedScope(member); |
191 closureRepresentationInfoStack = closureRepresentationInfoStack | |
192 .prepend(closureDataLookup.getClosureInfoForMemberTesting(member)); | |
193 dump(member); | 195 dump(member); |
194 } | 196 } |
195 | 197 |
196 void popMember() { | 198 void popMember() { |
197 scopeInfoStack = scopeInfoStack.tail; | 199 scopeInfoStack = scopeInfoStack.tail; |
198 closureRepresentationInfoStack = closureRepresentationInfoStack.tail; | |
199 } | 200 } |
200 | 201 |
201 void pushLocalFunction(T node) { | 202 void pushLocalFunction(T node) { |
202 closureRepresentationInfoStack = closureRepresentationInfoStack | 203 closureRepresentationInfoStack = closureRepresentationInfoStack |
203 .prepend(closureDataLookup.getClosureInfoForTesting(node)); | 204 .prepend(closureDataLookup.getClosureInfo(node)); |
204 dump(node); | 205 dump(node); |
205 } | 206 } |
206 | 207 |
207 void popLocalFunction() { | 208 void popLocalFunction() { |
208 closureRepresentationInfoStack = closureRepresentationInfoStack.tail; | 209 closureRepresentationInfoStack = closureRepresentationInfoStack.tail; |
209 } | 210 } |
210 | 211 |
211 void dump(Object object) { | 212 void dump(Object object) { |
212 if (!verbose) return; | 213 if (!verbose) return; |
213 | 214 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 features.add('field'); | 259 features.add('field'); |
259 } | 260 } |
260 if (closureRepresentationInfo.isVariableBoxed(local)) { | 261 if (closureRepresentationInfo.isVariableBoxed(local)) { |
261 features.add('variable-boxed'); | 262 features.add('variable-boxed'); |
262 } | 263 } |
263 } | 264 } |
264 // TODO(johnniwinther,efortuna): Add more info? | 265 // TODO(johnniwinther,efortuna): Add more info? |
265 return (features.toList()..sort()).join(','); | 266 return (features.toList()..sort()).join(','); |
266 } | 267 } |
267 | 268 |
268 String computeEntityValue(Entity entity) { | 269 String computeObjectValue(Object object) { |
269 Map<String, String> features = <String, String>{}; | 270 Map<String, String> features = <String, String>{}; |
270 | 271 |
271 void addLocals(String name, forEach(f(Local local, _))) { | 272 void addLocals(String name, forEach(f(Local local, _))) { |
272 List<String> names = <String>[]; | 273 List<String> names = <String>[]; |
273 forEach((Local local, _) { | 274 forEach((Local local, _) { |
274 if (local is BoxLocal) { | 275 if (local is BoxLocal) { |
275 names.add('box'); | 276 names.add('box'); |
276 } else { | 277 } else { |
277 names.add(local.name); | 278 names.add(local.name); |
278 } | 279 } |
279 }); | 280 }); |
280 String value = names.isEmpty ? null : '[${(names..sort()).join(',')}]'; | 281 String value = names.isEmpty ? null : '[${(names..sort()).join(',')}]'; |
281 if (features.containsKey(name)) { | 282 if (features.containsKey(name)) { |
282 Expect.equals( | 283 Expect.equals( |
283 features[name], value, "Inconsistent values for $name on $entity."); | 284 features[name], value, "Inconsistent values for $name on $object."); |
284 } | 285 } |
285 features[name] = value; | 286 features[name] = value; |
286 } | 287 } |
287 | 288 |
288 if (scopeInfo.thisLocal != null) { | 289 if (object is MemberEntity) { |
289 features['hasThis'] = ''; | 290 if (scopeInfo.thisLocal != null) { |
290 } | 291 features['hasThis'] = ''; |
291 addLocals('boxed', scopeInfo.forEachBoxedVariable); | 292 } |
| 293 addLocals('boxed', scopeInfo.forEachBoxedVariable); |
292 | 294 |
293 if (entity is MemberEntity) { | |
294 if (capturedScope.requiresContextBox) { | 295 if (capturedScope.requiresContextBox) { |
295 features['requiresBox'] = ''; | 296 features['requiresBox'] = ''; |
296 } | 297 } |
297 addLocals('boxed', capturedScope.forEachBoxedVariable); | 298 addLocals('boxed', capturedScope.forEachBoxedVariable); |
298 } | 299 } |
299 | 300 |
300 if (closureRepresentationInfo != null) { | 301 if (closureRepresentationInfo != null) { |
301 addLocals('boxed', closureRepresentationInfo.forEachBoxedVariable); | 302 addLocals('boxed', closureRepresentationInfo.forEachBoxedVariable); |
302 addLocals('captured', closureRepresentationInfo.forEachCapturedVariable); | 303 addLocals('captured', closureRepresentationInfo.forEachCapturedVariable); |
303 addLocals('free', closureRepresentationInfo.forEachFreeVariable); | 304 addLocals('free', closureRepresentationInfo.forEachFreeVariable); |
(...skipping 11 matching lines...) Expand all Loading... |
315 if (value != '') { | 316 if (value != '') { |
316 sb.write('='); | 317 sb.write('='); |
317 sb.write(value); | 318 sb.write(value); |
318 } | 319 } |
319 needsComma = true; | 320 needsComma = true; |
320 } | 321 } |
321 } | 322 } |
322 return sb.toString(); | 323 return sb.toString(); |
323 } | 324 } |
324 } | 325 } |
OLD | NEW |