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

Side by Side Diff: tests/compiler/dart2js/closure/closure_test.dart

Issue 2995353002: Test the CapturedScope for local functions (Closed)
Patch Set: Created 3 years, 4 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
OLDNEW
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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 ClosureAstComputer(DiagnosticReporter reporter, Map<Id, ActualData> actualMap, 88 ClosureAstComputer(DiagnosticReporter reporter, Map<Id, ActualData> actualMap,
89 ResolvedAst resolvedAst, this.closureDataLookup, 89 ResolvedAst resolvedAst, this.closureDataLookup,
90 {this.verbose: false}) 90 {this.verbose: false})
91 : super(reporter, actualMap, resolvedAst) { 91 : super(reporter, actualMap, resolvedAst) {
92 pushMember(resolvedAst.element as MemberElement); 92 pushMember(resolvedAst.element as MemberElement);
93 } 93 }
94 94
95 visitFunctionExpression(ast.FunctionExpression node) { 95 visitFunctionExpression(ast.FunctionExpression node) {
96 Entity localFunction = resolvedAst.elements.getFunctionDefinition(node); 96 Entity localFunction = resolvedAst.elements.getFunctionDefinition(node);
97 if (localFunction is LocalFunctionElement) { 97 if (localFunction is LocalFunctionElement) {
98 pushMember(localFunction.callMethod);
98 pushLocalFunction(node); 99 pushLocalFunction(node);
99 super.visitFunctionExpression(node); 100 super.visitFunctionExpression(node);
100 popLocalFunction(); 101 popLocalFunction();
102 popMember();
101 } else { 103 } else {
102 super.visitFunctionExpression(node); 104 super.visitFunctionExpression(node);
103 } 105 }
104 } 106 }
105 107
106 @override 108 @override
107 String computeNodeValue(ast.Node node, [AstElement element]) { 109 String computeNodeValue(ast.Node node, [AstElement element]) {
108 if (element != null && element.isLocal) { 110 if (element != null && element.isLocal) {
109 if (element.isFunction) { 111 if (element.isFunction) {
110 return computeObjectValue(element); 112 LocalFunctionElement localFunction = element;
113 return computeObjectValue(localFunction.callMethod);
111 } else { 114 } else {
112 LocalElement local = element; 115 LocalElement local = element;
113 return computeLocalValue(local); 116 return computeLocalValue(local);
114 } 117 }
115 } 118 }
116 // TODO(johnniwinther,efortuna): Collect data for other nodes? 119 // TODO(johnniwinther,efortuna): Collect data for other nodes?
117 return null; 120 return null;
118 } 121 }
119 122
120 @override 123 @override
121 String computeElementValue(AstElement element) { 124 String computeElementValue(covariant MemberElement element) {
122 // TODO(johnniwinther,efortuna): Collect data for the member 125 // TODO(johnniwinther,efortuna): Collect data for the member
123 // (has thisLocal, has box, etc.). 126 // (has thisLocal, has box, etc.).
124 return computeObjectValue(element); 127 return computeObjectValue(element);
125 } 128 }
126 } 129 }
127 130
128 /// Kernel IR visitor for computing closure data. 131 /// Kernel IR visitor for computing closure data.
129 class ClosureIrChecker extends IrDataExtractor with ComputeValueMixin<ir.Node> { 132 class ClosureIrChecker extends IrDataExtractor with ComputeValueMixin<ir.Node> {
130 final MemberEntity member; 133 final MemberEntity member;
131 final ClosureDataLookup<ir.Node> closureDataLookup; 134 final ClosureDataLookup<ir.Node> closureDataLookup;
132 final KernelToLocalsMap _localsMap; 135 final KernelToLocalsMap _localsMap;
133 final bool verbose; 136 final bool verbose;
134 137
135 ClosureIrChecker( 138 ClosureIrChecker(
136 Map<Id, ActualData> actualMap, 139 Map<Id, ActualData> actualMap,
137 KernelToElementMapForBuilding elementMap, 140 KernelToElementMapForBuilding elementMap,
138 this.member, 141 this.member,
139 this._localsMap, 142 this._localsMap,
140 this.closureDataLookup, 143 this.closureDataLookup,
141 {this.verbose: false}) 144 {this.verbose: false})
142 : super(actualMap) { 145 : super(actualMap) {
143 pushMember(member); 146 pushMember(member);
144 } 147 }
145 148
146 visitFunctionExpression(ir.FunctionExpression node) { 149 visitFunctionExpression(ir.FunctionExpression node) {
150 ClosureRepresentationInfo info = closureDataLookup.getClosureInfo(node);
151 pushMember(info.callMethod);
147 pushLocalFunction(node); 152 pushLocalFunction(node);
148 super.visitFunctionExpression(node); 153 super.visitFunctionExpression(node);
149 popLocalFunction(); 154 popLocalFunction();
155 popMember();
150 } 156 }
151 157
152 visitFunctionDeclaration(ir.FunctionDeclaration node) { 158 visitFunctionDeclaration(ir.FunctionDeclaration node) {
159 ClosureRepresentationInfo info = closureDataLookup.getClosureInfo(node);
160 pushMember(info.callMethod);
153 pushLocalFunction(node); 161 pushLocalFunction(node);
154 super.visitFunctionDeclaration(node); 162 super.visitFunctionDeclaration(node);
155 popLocalFunction(); 163 popLocalFunction();
164 popMember();
156 } 165 }
157 166
158 @override 167 @override
159 String computeNodeValue(ir.Node node) { 168 String computeNodeValue(ir.Node node) {
160 if (node is ir.VariableDeclaration) { 169 if (node is ir.VariableDeclaration) {
161 if (node.parent is ir.FunctionDeclaration) { 170 if (node.parent is ir.FunctionDeclaration) {
162 return computeObjectValue(node.parent); 171 ClosureRepresentationInfo info =
172 closureDataLookup.getClosureInfo(node.parent);
173 return computeObjectValue(info.callMethod);
163 } 174 }
164 Local local = _localsMap.getLocalVariable(node); 175 Local local = _localsMap.getLocalVariable(node);
165 return computeLocalValue(local); 176 return computeLocalValue(local);
166 } else if (node is ir.FunctionExpression) { 177 } else if (node is ir.FunctionExpression) {
167 return computeObjectValue(node); 178 ClosureRepresentationInfo info = closureDataLookup.getClosureInfo(node);
179 return computeObjectValue(info.callMethod);
168 } 180 }
169 return null; 181 return null;
170 } 182 }
171 183
172 @override 184 @override
173 String computeMemberValue(ir.Member node) { 185 String computeMemberValue(ir.Member node) {
174 return computeObjectValue(member); 186 return computeObjectValue(member);
175 } 187 }
176 } 188 }
177 189
178 abstract class ComputeValueMixin<T> { 190 abstract class ComputeValueMixin<T> {
179 bool get verbose; 191 bool get verbose;
192 Map<BoxLocal, String> boxNames = <BoxLocal, String>{};
180 ClosureDataLookup<T> get closureDataLookup; 193 ClosureDataLookup<T> get closureDataLookup;
181 Link<ScopeInfo> scopeInfoStack = const Link<ScopeInfo>(); 194 Link<ScopeInfo> scopeInfoStack = const Link<ScopeInfo>();
182 ScopeInfo get scopeInfo => scopeInfoStack.head; 195 ScopeInfo get scopeInfo => scopeInfoStack.head;
183 CapturedScope capturedScope; 196 CapturedScope get capturedScope => capturedScopeStack.head;
197 Link<CapturedScope> capturedScopeStack = const Link<CapturedScope>();
184 Link<ClosureRepresentationInfo> closureRepresentationInfoStack = 198 Link<ClosureRepresentationInfo> closureRepresentationInfoStack =
185 const Link<ClosureRepresentationInfo>(); 199 const Link<ClosureRepresentationInfo>();
186 ClosureRepresentationInfo get closureRepresentationInfo => 200 ClosureRepresentationInfo get closureRepresentationInfo =>
187 closureRepresentationInfoStack.isNotEmpty 201 closureRepresentationInfoStack.isNotEmpty
188 ? closureRepresentationInfoStack.head 202 ? closureRepresentationInfoStack.head
189 : null; 203 : null;
190 204
191 void pushMember(MemberEntity member) { 205 void pushMember(MemberEntity member) {
192 scopeInfoStack = 206 scopeInfoStack =
193 scopeInfoStack.prepend(closureDataLookup.getScopeInfo(member)); 207 scopeInfoStack.prepend(closureDataLookup.getScopeInfo(member));
194 capturedScope = closureDataLookup.getCapturedScope(member); 208 capturedScopeStack =
209 capturedScopeStack.prepend(closureDataLookup.getCapturedScope(member));
210 if (capturedScope.hasBox) {
211 boxNames[capturedScope.box] = 'box${boxNames.length}';
212 }
195 dump(member); 213 dump(member);
196 } 214 }
197 215
198 void popMember() { 216 void popMember() {
199 scopeInfoStack = scopeInfoStack.tail; 217 scopeInfoStack = scopeInfoStack.tail;
218 capturedScopeStack = capturedScopeStack.tail;
200 } 219 }
201 220
202 void pushLocalFunction(T node) { 221 void pushLocalFunction(T node) {
203 closureRepresentationInfoStack = closureRepresentationInfoStack 222 closureRepresentationInfoStack = closureRepresentationInfoStack
204 .prepend(closureDataLookup.getClosureInfo(node)); 223 .prepend(closureDataLookup.getClosureInfo(node));
205 dump(node); 224 dump(node);
206 } 225 }
207 226
208 void popLocalFunction() { 227 void popLocalFunction() {
209 closureRepresentationInfoStack = closureRepresentationInfoStack.tail; 228 closureRepresentationInfoStack = closureRepresentationInfoStack.tail;
(...skipping 23 matching lines...) Expand all
233 if (scopeInfo.localIsUsedInTryOrSync(local)) { 252 if (scopeInfo.localIsUsedInTryOrSync(local)) {
234 features.add('inTry'); 253 features.add('inTry');
235 // TODO(johnniwinther,efortuna): Should this be enabled and checked? 254 // TODO(johnniwinther,efortuna): Should this be enabled and checked?
236 //Expect.isTrue(capturedScope.localIsUsedInTryOrSync(local)); 255 //Expect.isTrue(capturedScope.localIsUsedInTryOrSync(local));
237 } else { 256 } else {
238 //Expect.isFalse(capturedScope.localIsUsedInTryOrSync(local)); 257 //Expect.isFalse(capturedScope.localIsUsedInTryOrSync(local));
239 } 258 }
240 if (capturedScope.isBoxed(local)) { 259 if (capturedScope.isBoxed(local)) {
241 features.add('boxed'); 260 features.add('boxed');
242 } 261 }
243 if (capturedScope.context == local) { 262 if (capturedScope.box == local) {
244 features.add('local'); 263 // TODO(johnniwinther): This can't happen!
Emily Fortuna 2017/08/22 23:47:37 but this is happening? if not... throw?
Johnni Winther 2017/08/23 07:47:18 I'm still in the process of making this accurate.
264 features.add('box');
245 } 265 }
246 if (capturedScope is CapturedLoopScope) { 266 if (capturedScope is CapturedLoopScope) {
247 CapturedLoopScope loopScope = capturedScope; 267 CapturedLoopScope loopScope = capturedScope;
248 if (loopScope.boxedLoopVariables.contains(local)) { 268 if (loopScope.boxedLoopVariables.contains(local)) {
249 features.add('loop'); 269 features.add('loop');
250 } 270 }
251 } 271 }
252 if (closureRepresentationInfo != null) { 272 if (closureRepresentationInfo != null) {
253 if (closureRepresentationInfo.createdFieldEntities.contains(local)) { 273 if (closureRepresentationInfo.createdFieldEntities.contains(local)) {
254 features.add('field'); 274 features.add('field');
255 } 275 }
256 if (closureRepresentationInfo.isVariableBoxed(local)) {
257 features.add('variable-boxed');
258 }
259 } 276 }
260 // TODO(johnniwinther,efortuna): Add more info? 277 // TODO(johnniwinther,efortuna): Add more info?
261 return (features.toList()..sort()).join(','); 278 return (features.toList()..sort()).join(',');
262 } 279 }
263 280
264 String computeObjectValue(Object object) { 281 String computeObjectValue(MemberEntity member) {
265 Map<String, String> features = <String, String>{}; 282 Map<String, String> features = <String, String>{};
266 283
267 void addLocals(String name, forEach(f(Local local, _))) { 284 void addLocals(String name, forEach(f(Local local, _))) {
268 List<String> names = <String>[]; 285 List<String> names = <String>[];
269 forEach((Local local, _) { 286 forEach((Local local, _) {
270 if (local is BoxLocal) { 287 if (local is BoxLocal) {
271 names.add('box'); 288 names.add(boxNames[local]);
272 } else { 289 } else {
273 names.add(local.name); 290 names.add(local.name);
274 } 291 }
275 }); 292 });
276 String value = names.isEmpty ? null : '[${(names..sort()).join(',')}]'; 293 String value = names.isEmpty ? null : '[${(names..sort()).join(',')}]';
277 if (features.containsKey(name)) { 294 if (features.containsKey(name)) {
278 Expect.equals( 295 Expect.equals(
279 features[name], value, "Inconsistent values for $name on $object."); 296 features[name], value, "Inconsistent values for $name on $member.");
280 } 297 }
281 features[name] = value; 298 features[name] = value;
282 } 299 }
283 300
284 if (object is MemberEntity) { 301 if (scopeInfo.thisLocal != null) {
285 if (scopeInfo.thisLocal != null) { 302 features['hasThis'] = '';
286 features['hasThis'] = '';
287 }
288
289 if (capturedScope.requiresContextBox) {
290 features['requiresBox'] = '';
291 }
292 addLocals('boxed', capturedScope.forEachBoxedVariable);
293 } 303 }
304 if (capturedScope.hasBox) {
305 //print('------------- $object from $capturedScope');
Emily Fortuna 2017/08/22 23:47:37 remove commented out line?
306 features['box'] = boxNames[capturedScope.box];
307 }
308 addLocals('boxed', capturedScope.forEachBoxedVariable);
294 309
295 if (closureRepresentationInfo != null) { 310 if (closureRepresentationInfo != null) {
296 addLocals('boxed', closureRepresentationInfo.forEachBoxedVariable);
297 addLocals('captured', closureRepresentationInfo.forEachCapturedVariable);
298 addLocals('free', closureRepresentationInfo.forEachFreeVariable); 311 addLocals('free', closureRepresentationInfo.forEachFreeVariable);
299 } 312 }
300 313
301 StringBuffer sb = new StringBuffer(); 314 StringBuffer sb = new StringBuffer();
302 bool needsComma = false; 315 bool needsComma = false;
303 for (String name in features.keys.toList()..sort()) { 316 for (String name in features.keys.toList()..sort()) {
304 String value = features[name]; 317 String value = features[name];
305 if (value != null) { 318 if (value != null) {
306 if (needsComma) { 319 if (needsComma) {
307 sb.write(','); 320 sb.write(',');
308 } 321 }
309 sb.write(name); 322 sb.write(name);
310 if (value != '') { 323 if (value != '') {
311 sb.write('='); 324 sb.write('=');
312 sb.write(value); 325 sb.write(value);
313 } 326 }
314 needsComma = true; 327 needsComma = true;
315 } 328 }
316 } 329 }
317 return sb.toString(); 330 return sb.toString();
318 } 331 }
319 } 332 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698