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

Side by Side Diff: pkg/compiler/lib/src/closure.dart

Issue 831133004: Use closure conversion in new dart2js backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Removed redundant null-check Created 5 years, 11 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 closureToClassMapper; 5 library closureToClassMapper;
6 6
7 import "elements/elements.dart"; 7 import "elements/elements.dart";
8 import "dart2jslib.dart"; 8 import "dart2jslib.dart";
9 import "dart_types.dart"; 9 import "dart_types.dart";
10 import "js_backend/js_backend.dart" show JavaScriptBackend; 10 import "js_backend/js_backend.dart" show JavaScriptBackend;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 } 97 }
98 98
99 /// Common interface for [BoxFieldElement] and [ClosureFieldElement] as 99 /// Common interface for [BoxFieldElement] and [ClosureFieldElement] as
100 /// non-elements. 100 /// non-elements.
101 abstract class CapturedVariable {} 101 abstract class CapturedVariable {}
102 102
103 // TODO(ahe): These classes continuously cause problems. We need to 103 // TODO(ahe): These classes continuously cause problems. We need to
104 // find a more general solution. 104 // find a more general solution.
105 class ClosureFieldElement extends ElementX 105 class ClosureFieldElement extends ElementX
106 implements VariableElement, CapturedVariable { 106 implements VariableElement, CapturedVariable {
107 /// The source variable this element refers to. 107 /// The [BoxLocal] or [LocalElement] being accessed through the field.
108 final Local local; 108 final Local local;
109 109
110 ClosureFieldElement(String name, 110 ClosureFieldElement(String name,
111 this.local, 111 this.local,
112 ClosureClassElement enclosing) 112 ClosureClassElement enclosing)
113 : super(name, ElementKind.FIELD, enclosing); 113 : super(name, ElementKind.FIELD, enclosing);
114 114
115 /// Use [closureClass] instead. 115 /// Use [closureClass] instead.
116 @deprecated 116 @deprecated
117 get enclosingElement => super.enclosingElement; 117 get enclosingElement => super.enclosingElement;
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
294 ResolvedAst get resolvedAst { 294 ResolvedAst get resolvedAst {
295 return new ResolvedAst(this, node, treeElements); 295 return new ResolvedAst(this, node, treeElements);
296 } 296 }
297 297
298 Element get analyzableElement => closureClass.methodElement.analyzableElement; 298 Element get analyzableElement => closureClass.methodElement.analyzableElement;
299 } 299 }
300 300
301 // The box-element for a scope, and the captured variables that need to be 301 // The box-element for a scope, and the captured variables that need to be
302 // stored in the box. 302 // stored in the box.
303 class ClosureScope { 303 class ClosureScope {
304 BoxLocal boxElement; 304 final BoxLocal boxElement;
305 Map<VariableElement, BoxFieldElement> _capturedVariableMapping; 305 final Map<Local, BoxFieldElement> capturedVariables;
306 306
307 // If the scope is attached to a [For] contains the variables that are 307 // If the scope is attached to a [For] contains the variables that are
308 // declared in the initializer of the [For] and that need to be boxed. 308 // declared in the initializer of the [For] and that need to be boxed.
309 // Otherwise contains the empty List. 309 // Otherwise contains the empty List.
310 List<VariableElement> boxedLoopVariables = const <VariableElement>[]; 310 List<VariableElement> boxedLoopVariables = const <VariableElement>[];
311 311
312 ClosureScope(this.boxElement, this._capturedVariableMapping); 312 ClosureScope(this.boxElement, this.capturedVariables);
313 313
314 bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty; 314 bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty;
315 315
316 bool isCapturedVariable(VariableElement variable) { 316 bool isCapturedVariable(VariableElement variable) {
317 return _capturedVariableMapping.containsKey(variable); 317 return capturedVariables.containsKey(variable);
318 } 318 }
319 319
320 void forEachCapturedVariable(f(LocalVariableElement variable, 320 void forEachCapturedVariable(f(LocalVariableElement variable,
321 BoxFieldElement boxField)) { 321 BoxFieldElement boxField)) {
322 _capturedVariableMapping.forEach(f); 322 capturedVariables.forEach(f);
323 } 323 }
324 } 324 }
325 325
326 class ClosureClassMap { 326 class ClosureClassMap {
327 // The closure's element before any translation. Will be null for methods. 327 // The closure's element before any translation. Will be null for methods.
328 final LocalFunctionElement closureElement; 328 final LocalFunctionElement closureElement;
329 // The closureClassElement will be null for methods that are not local 329 // The closureClassElement will be null for methods that are not local
330 // closures. 330 // closures.
331 final ClosureClassElement closureClassElement; 331 final ClosureClassElement closureClassElement;
332 // The callElement will be null for methods that are not local closures. 332 // The callElement will be null for methods that are not local closures.
333 final FunctionElement callElement; 333 final FunctionElement callElement;
334 // The [thisElement] makes handling 'this' easier by treating it like any 334 // The [thisElement] makes handling 'this' easier by treating it like any
335 // other argument. It is only set for instance-members. 335 // other argument. It is only set for instance-members.
336 final ThisLocal thisLocal; 336 final ThisLocal thisLocal;
337 337
338 // Maps free locals, arguments and function elements to their captured 338 // Maps free locals, arguments, function elements, and box locals to
339 // copies. 339 // their locations.
340 final Map<Local, CapturedVariable> _freeVariableMapping = 340 final Map<Local, CapturedVariable> freeVariableMap =
341 new Map<Local, CapturedVariable>(); 341 new Map<Local, CapturedVariable>();
342 342
343 // Maps closure-fields to their captured elements. This is somehow the inverse 343 // Maps [Loop] and [FunctionExpression] nodes to their
344 // mapping of [freeVariableMapping], but whereas [freeVariableMapping] does
345 // not deal with boxes, here we map instance-fields (which might represent
346 // boxes) to their boxElement.
347 final Map<ClosureFieldElement, Local> _closureFieldMapping =
348 new Map<ClosureFieldElement, Local>();
349
350 // Maps scopes ([Loop] and [FunctionExpression] nodes) to their
351 // [ClosureScope] which contains their box and the 344 // [ClosureScope] which contains their box and the
352 // captured variables that are stored in the box. 345 // captured variables that are stored in the box.
353 // This map will be empty if the method/closure of this [ClosureData] does not 346 // This map will be empty if the method/closure of this [ClosureData] does not
354 // contain any nested closure. 347 // contain any nested closure.
355 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); 348 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>();
356 349
357 final Set<Local> usedVariablesInTry = new Set<Local>(); 350 final Set<Local> usedVariablesInTry = new Set<Local>();
358 351
359 ClosureClassMap(this.closureElement, 352 ClosureClassMap(this.closureElement,
360 this.closureClassElement, 353 this.closureClassElement,
361 this.callElement, 354 this.callElement,
362 this.thisLocal); 355 this.thisLocal);
363 356
364 void addFreeVariable(Local element) { 357 void addFreeVariable(Local element) {
365 assert(_freeVariableMapping[element] == null); 358 assert(freeVariableMap[element] == null);
366 _freeVariableMapping[element] = null; 359 freeVariableMap[element] = null;
367 } 360 }
368 361
369 Iterable<Local> get freeVariables => _freeVariableMapping.keys; 362 Iterable<Local> get freeVariables => freeVariableMap.keys;
370 363
371 bool isFreeVariable(Local element) { 364 bool isFreeVariable(Local element) {
372 return _freeVariableMapping.containsKey(element); 365 return freeVariableMap.containsKey(element);
373 } 366 }
374 367
375 CapturedVariable getFreeVariableElement(Local element) {
376 return _freeVariableMapping[element];
377 }
378
379 /// Sets the free [variable] to be captured by the [boxField].
380 void setFreeVariableBoxField(Local variable,
381 BoxFieldElement boxField) {
382 _freeVariableMapping[variable] = boxField;
383 }
384
385 /// Sets the free [variable] to be captured by the [closureField].
386 void setFreeVariableClosureField(Local variable,
387 ClosureFieldElement closureField) {
388 _freeVariableMapping[variable] = closureField;
389 }
390
391
392 void forEachFreeVariable(f(Local variable, 368 void forEachFreeVariable(f(Local variable,
393 CapturedVariable field)) { 369 CapturedVariable field)) {
394 _freeVariableMapping.forEach(f); 370 freeVariableMap.forEach(f);
395 } 371 }
396 372
397 Local getLocalVariableForClosureField(ClosureFieldElement field) { 373 Local getLocalVariableForClosureField(ClosureFieldElement field) {
398 return _closureFieldMapping[field]; 374 return field.local;
399 }
400
401 void setLocalVariableForClosureField(ClosureFieldElement field,
402 Local variable) {
403 _closureFieldMapping[field] = variable;
404 } 375 }
405 376
406 bool get isClosure => closureElement != null; 377 bool get isClosure => closureElement != null;
407 378
408 bool capturingScopesBox(Local variable) { 379 bool capturingScopesBox(Local variable) {
409 return capturingScopes.values.any((scope) { 380 return capturingScopes.values.any((scope) {
410 return scope.boxedLoopVariables.contains(variable); 381 return scope.boxedLoopVariables.contains(variable);
411 }); 382 });
412 } 383 }
413 384
414 bool isVariableBoxed(Local variable) { 385 bool isVariableBoxed(Local variable) {
415 CapturedVariable copy = _freeVariableMapping[variable]; 386 CapturedVariable copy = freeVariableMap[variable];
416 if (copy is BoxFieldElement) { 387 if (copy is BoxFieldElement) {
417 return true; 388 return true;
418 } 389 }
419 return capturingScopesBox(variable); 390 return capturingScopesBox(variable);
420 } 391 }
421 392
422 void forEachCapturedVariable(void f(Local variable, 393 void forEachCapturedVariable(void f(Local variable,
423 CapturedVariable field)) { 394 CapturedVariable field)) {
424 _freeVariableMapping.forEach((variable, copy) { 395 freeVariableMap.forEach((variable, copy) {
425 if (variable is BoxLocal) return; 396 if (variable is BoxLocal) return;
426 f(variable, copy); 397 f(variable, copy);
427 }); 398 });
428 capturingScopes.values.forEach((ClosureScope scope) { 399 capturingScopes.values.forEach((ClosureScope scope) {
429 scope.forEachCapturedVariable(f); 400 scope.forEachCapturedVariable(f);
430 }); 401 });
431 } 402 }
432 403
433 void forEachBoxedVariable(void f(LocalVariableElement local, 404 void forEachBoxedVariable(void f(LocalVariableElement local,
434 BoxFieldElement field)) { 405 BoxFieldElement field)) {
435 _freeVariableMapping.forEach((variable, copy) { 406 freeVariableMap.forEach((variable, copy) {
436 if (!isVariableBoxed(variable)) return; 407 if (!isVariableBoxed(variable)) return;
437 f(variable, copy); 408 f(variable, copy);
438 }); 409 });
439 capturingScopes.values.forEach((ClosureScope scope) { 410 capturingScopes.values.forEach((ClosureScope scope) {
440 scope.forEachCapturedVariable(f); 411 scope.forEachCapturedVariable(f);
441 }); 412 });
442 } 413 }
443 414
444 void removeMyselfFrom(Universe universe) { 415 void removeMyselfFrom(Universe universe) {
445 _freeVariableMapping.values.forEach((e) { 416 freeVariableMap.values.forEach((e) {
446 universe.closurizedMembers.remove(e); 417 universe.closurizedMembers.remove(e);
447 universe.fieldSetters.remove(e); 418 universe.fieldSetters.remove(e);
448 universe.fieldGetters.remove(e); 419 universe.fieldGetters.remove(e);
449 }); 420 });
450 } 421 }
451 } 422 }
452 423
453 class ClosureTranslator extends Visitor { 424 class ClosureTranslator extends Visitor {
454 final Compiler compiler; 425 final Compiler compiler;
455 final TreeElements elements; 426 final TreeElements elements;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 // The captured variables that need to be stored in a field of the closure 508 // The captured variables that need to be stored in a field of the closure
538 // class. 509 // class.
539 Set<Local> fieldCaptures = new Set<Local>(); 510 Set<Local> fieldCaptures = new Set<Local>();
540 Set<BoxLocal> boxes = new Set<BoxLocal>(); 511 Set<BoxLocal> boxes = new Set<BoxLocal>();
541 ClosureClassMap data = closureMappingCache[closure]; 512 ClosureClassMap data = closureMappingCache[closure];
542 // We get a copy of the keys and iterate over it, to avoid modifications 513 // We get a copy of the keys and iterate over it, to avoid modifications
543 // to the map while iterating over it. 514 // to the map while iterating over it.
544 Iterable<Local> freeVariables = data.freeVariables.toList(); 515 Iterable<Local> freeVariables = data.freeVariables.toList();
545 freeVariables.forEach((Local fromElement) { 516 freeVariables.forEach((Local fromElement) {
546 assert(data.isFreeVariable(fromElement)); 517 assert(data.isFreeVariable(fromElement));
547 assert(data.getFreeVariableElement(fromElement) == null); 518 assert(data.freeVariableMap[fromElement] == null);
548 assert(isCapturedVariable(fromElement)); 519 assert(isCapturedVariable(fromElement));
549 BoxFieldElement boxFieldElement = 520 BoxFieldElement boxFieldElement =
550 getCapturedVariableBoxField(fromElement); 521 getCapturedVariableBoxField(fromElement);
551 if (boxFieldElement == null) { 522 if (boxFieldElement == null) {
552 assert(fromElement is! BoxLocal); 523 assert(fromElement is! BoxLocal);
553 // The variable has not been boxed. 524 // The variable has not been boxed.
554 fieldCaptures.add(fromElement); 525 fieldCaptures.add(fromElement);
555 } else { 526 } else {
556 // A boxed element. 527 // A boxed element.
557 data.setFreeVariableBoxField(fromElement, boxFieldElement); 528 data.freeVariableMap[fromElement] = boxFieldElement;
558 boxes.add(boxFieldElement.box); 529 boxes.add(boxFieldElement.box);
559 } 530 }
560 }); 531 });
561 ClosureClassElement closureClass = data.closureClassElement; 532 ClosureClassElement closureClass = data.closureClassElement;
562 assert(closureClass != null || 533 assert(closureClass != null ||
563 (fieldCaptures.isEmpty && boxes.isEmpty)); 534 (fieldCaptures.isEmpty && boxes.isEmpty));
564 535
565 void addClosureField(Local local, String name) { 536 void addClosureField(Local local, String name) {
566 ClosureFieldElement closureField = 537 ClosureFieldElement closureField =
567 new ClosureFieldElement(name, local, closureClass); 538 new ClosureFieldElement(name, local, closureClass);
568 closureClass.addField(closureField, compiler); 539 closureClass.addField(closureField, compiler);
569 data.setLocalVariableForClosureField(closureField, local); 540 data.freeVariableMap[local] = closureField;
570 data.setFreeVariableClosureField(local, closureField);
571 } 541 }
572 542
573 // Add the box elements first so we get the same ordering. 543 // Add the box elements first so we get the same ordering.
574 // TODO(sra): What is the canonical order of multiple boxes? 544 // TODO(sra): What is the canonical order of multiple boxes?
575 for (BoxLocal capturedElement in boxes) { 545 for (BoxLocal capturedElement in boxes) {
576 addClosureField(capturedElement, capturedElement.name); 546 addClosureField(capturedElement, capturedElement.name);
577 } 547 }
578 548
579 /// Comparator for locals. Position boxes before elements. 549 /// Comparator for locals. Position boxes before elements.
580 int compareLocals(a, b) { 550 int compareLocals(a, b) {
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 992
1023 String get name => typeVariable.name; 993 String get name => typeVariable.name;
1024 994
1025 int get hashCode => typeVariable.hashCode; 995 int get hashCode => typeVariable.hashCode;
1026 996
1027 bool operator ==(other) { 997 bool operator ==(other) {
1028 if (other is! TypeVariableLocal) return false; 998 if (other is! TypeVariableLocal) return false;
1029 return typeVariable == other.typeVariable; 999 return typeVariable == other.typeVariable;
1030 } 1000 }
1031 } 1001 }
OLDNEW
« no previous file with comments | « pkg/analyzer2dart/lib/src/cps_generator.dart ('k') | pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698