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

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

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 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
« no previous file with comments | « pkg/compiler/lib/src/cache_strategy.dart ('k') | pkg/compiler/lib/src/common.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 'common.dart'; 7 import 'common.dart';
8 import 'common/names.dart' show 8 import 'common/names.dart' show Identifiers;
9 Identifiers; 9 import 'common/resolution.dart' show Parsing, Resolution;
10 import 'common/resolution.dart' show 10 import 'common/tasks.dart' show CompilerTask;
11 Parsing, 11 import 'compiler.dart' show Compiler;
12 Resolution;
13 import 'common/tasks.dart' show
14 CompilerTask;
15 import 'compiler.dart' show
16 Compiler;
17 import 'constants/expressions.dart'; 12 import 'constants/expressions.dart';
18 import 'dart_types.dart'; 13 import 'dart_types.dart';
19 import 'elements/elements.dart'; 14 import 'elements/elements.dart';
20 import 'elements/modelx.dart' show 15 import 'elements/modelx.dart'
21 BaseFunctionElementX, 16 show BaseFunctionElementX, ClassElementX, ElementX, LocalFunctionElementX;
22 ClassElementX,
23 ElementX,
24 LocalFunctionElementX;
25 import 'elements/visitor.dart' show ElementVisitor; 17 import 'elements/visitor.dart' show ElementVisitor;
26 import 'js_backend/js_backend.dart' show JavaScriptBackend; 18 import 'js_backend/js_backend.dart' show JavaScriptBackend;
27 import 'resolution/tree_elements.dart' show TreeElements; 19 import 'resolution/tree_elements.dart' show TreeElements;
28 import 'tokens/token.dart' show Token; 20 import 'tokens/token.dart' show Token;
29 import 'tree/tree.dart'; 21 import 'tree/tree.dart';
30 import 'util/util.dart'; 22 import 'util/util.dart';
31 import 'universe/universe.dart' show 23 import 'universe/universe.dart' show Universe;
32 Universe;
33 24
34 class ClosureTask extends CompilerTask { 25 class ClosureTask extends CompilerTask {
35 Map<Node, ClosureClassMap> closureMappingCache; 26 Map<Node, ClosureClassMap> closureMappingCache;
36 ClosureTask(Compiler compiler) 27 ClosureTask(Compiler compiler)
37 : closureMappingCache = new Map<Node, ClosureClassMap>(), 28 : closureMappingCache = new Map<Node, ClosureClassMap>(),
38 super(compiler); 29 super(compiler);
39 30
40 String get name => "Closure Simplifier"; 31 String get name => "Closure Simplifier";
41 32
42 ClosureClassMap computeClosureToClassMapping(Element element, 33 ClosureClassMap computeClosureToClassMapping(
43 Node node, 34 Element element, Node node, TreeElements elements) {
44 TreeElements elements) {
45 return measure(() { 35 return measure(() {
46 ClosureClassMap cached = closureMappingCache[node]; 36 ClosureClassMap cached = closureMappingCache[node];
47 if (cached != null) return cached; 37 if (cached != null) return cached;
48 38
49 ClosureTranslator translator = 39 ClosureTranslator translator =
50 new ClosureTranslator(compiler, elements, closureMappingCache); 40 new ClosureTranslator(compiler, elements, closureMappingCache);
51 41
52 // The translator will store the computed closure-mappings inside the 42 // The translator will store the computed closure-mappings inside the
53 // cache. One for given node and one for each nested closure. 43 // cache. One for given node and one for each nested closure.
54 if (node is FunctionExpression) { 44 if (node is FunctionExpression) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 /// non-elements. 90 /// non-elements.
101 abstract class CapturedVariable implements Element {} 91 abstract class CapturedVariable implements Element {}
102 92
103 // TODO(ahe): These classes continuously cause problems. We need to 93 // TODO(ahe): These classes continuously cause problems. We need to
104 // find a more general solution. 94 // find a more general solution.
105 class ClosureFieldElement extends ElementX 95 class ClosureFieldElement extends ElementX
106 implements FieldElement, CapturedVariable, PrivatelyNamedJSEntity { 96 implements FieldElement, CapturedVariable, PrivatelyNamedJSEntity {
107 /// The [BoxLocal] or [LocalElement] being accessed through the field. 97 /// The [BoxLocal] or [LocalElement] being accessed through the field.
108 final Local local; 98 final Local local;
109 99
110 ClosureFieldElement(String name, 100 ClosureFieldElement(String name, this.local, ClosureClassElement enclosing)
111 this.local,
112 ClosureClassElement enclosing)
113 : super(name, ElementKind.FIELD, enclosing); 101 : super(name, ElementKind.FIELD, enclosing);
114 102
115 /// Use [closureClass] instead. 103 /// Use [closureClass] instead.
116 @deprecated 104 @deprecated
117 get enclosingElement => super.enclosingElement; 105 get enclosingElement => super.enclosingElement;
118 106
119 ClosureClassElement get closureClass => super.enclosingElement; 107 ClosureClassElement get closureClass => super.enclosingElement;
120 108
121 MemberElement get memberContext => closureClass.methodElement.memberContext; 109 MemberElement get memberContext => closureClass.methodElement.memberContext;
122 110
123 @override 111 @override
124 Entity get declaredEntity => local; 112 Entity get declaredEntity => local;
125 @override 113 @override
126 Entity get rootOfScope => closureClass; 114 Entity get rootOfScope => closureClass;
127 115
128 bool get hasNode => false; 116 bool get hasNode => false;
129 117
130 Node get node { 118 Node get node {
131 throw new SpannableAssertionFailure(local, 119 throw new SpannableAssertionFailure(
132 'Should not access node of ClosureFieldElement.'); 120 local, 'Should not access node of ClosureFieldElement.');
133 } 121 }
134 122
135 bool get hasResolvedAst => hasTreeElements; 123 bool get hasResolvedAst => hasTreeElements;
136 124
137 ResolvedAst get resolvedAst { 125 ResolvedAst get resolvedAst {
138 return new ResolvedAst(this, null, treeElements); 126 return new ResolvedAst(this, null, treeElements);
139 } 127 }
140 128
141 Expression get initializer { 129 Expression get initializer {
142 throw new SpannableAssertionFailure(local, 130 throw new SpannableAssertionFailure(
143 'Should not access initializer of ClosureFieldElement.'); 131 local, 'Should not access initializer of ClosureFieldElement.');
144 } 132 }
145 133
146 bool get isInstanceMember => true; 134 bool get isInstanceMember => true;
147 bool get isAssignable => false; 135 bool get isAssignable => false;
148 136
149 DartType computeType(Resolution resolution) => type; 137 DartType computeType(Resolution resolution) => type;
150 138
151 DartType get type { 139 DartType get type {
152 if (local is LocalElement) { 140 if (local is LocalElement) {
153 LocalElement element = local; 141 LocalElement element = local;
(...skipping 16 matching lines...) Expand all
170 @override 158 @override
171 ConstantExpression get constant => null; 159 ConstantExpression get constant => null;
172 } 160 }
173 161
174 // TODO(ahe): These classes continuously cause problems. We need to find 162 // TODO(ahe): These classes continuously cause problems. We need to find
175 // a more general solution. 163 // a more general solution.
176 class ClosureClassElement extends ClassElementX { 164 class ClosureClassElement extends ClassElementX {
177 DartType rawType; 165 DartType rawType;
178 DartType thisType; 166 DartType thisType;
179 FunctionType callType; 167 FunctionType callType;
168
180 /// Node that corresponds to this closure, used for source position. 169 /// Node that corresponds to this closure, used for source position.
181 final FunctionExpression node; 170 final FunctionExpression node;
182 171
183 /** 172 /**
184 * The element for the declaration of the function expression. 173 * The element for the declaration of the function expression.
185 */ 174 */
186 final LocalFunctionElement methodElement; 175 final LocalFunctionElement methodElement;
187 176
188 final List<ClosureFieldElement> _closureFields = <ClosureFieldElement>[]; 177 final List<ClosureFieldElement> _closureFields = <ClosureFieldElement>[];
189 178
190 ClosureClassElement(this.node, 179 ClosureClassElement(
191 String name, 180 this.node, String name, Compiler compiler, LocalFunctionElement closure)
192 Compiler compiler,
193 LocalFunctionElement closure)
194 : this.methodElement = closure, 181 : this.methodElement = closure,
195 super(name, 182 super(
196 closure.compilationUnit, 183 name,
197 // By assigning a fresh class-id we make sure that the hashcode 184 closure.compilationUnit,
198 // is unique, but also emit closure classes after all other 185 // By assigning a fresh class-id we make sure that the hashcode
199 // classes (since the emitter sorts classes by their id). 186 // is unique, but also emit closure classes after all other
200 compiler.getNextFreeClassId(), 187 // classes (since the emitter sorts classes by their id).
201 STATE_DONE) { 188 compiler.getNextFreeClassId(),
189 STATE_DONE) {
202 JavaScriptBackend backend = compiler.backend; 190 JavaScriptBackend backend = compiler.backend;
203 ClassElement superclass = methodElement.isInstanceMember 191 ClassElement superclass = methodElement.isInstanceMember
204 ? backend.helpers.boundClosureClass 192 ? backend.helpers.boundClosureClass
205 : backend.helpers.closureClass; 193 : backend.helpers.closureClass;
206 superclass.ensureResolved(compiler.resolution); 194 superclass.ensureResolved(compiler.resolution);
207 supertype = superclass.thisType; 195 supertype = superclass.thisType;
208 interfaces = const Link<DartType>(); 196 interfaces = const Link<DartType>();
209 thisType = rawType = new InterfaceType(this); 197 thisType = rawType = new InterfaceType(this);
210 allSupertypesAndSelf = 198 allSupertypesAndSelf =
211 superclass.allSupertypesAndSelf.extendClass(thisType); 199 superclass.allSupertypesAndSelf.extendClass(thisType);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 class BoxLocal extends Local { 232 class BoxLocal extends Local {
245 final String name; 233 final String name;
246 final ExecutableElement executableContext; 234 final ExecutableElement executableContext;
247 235
248 BoxLocal(this.name, this.executableContext); 236 BoxLocal(this.name, this.executableContext);
249 } 237 }
250 238
251 // TODO(ngeoffray, ahe): These classes continuously cause problems. We need to 239 // TODO(ngeoffray, ahe): These classes continuously cause problems. We need to
252 // find a more general solution. 240 // find a more general solution.
253 class BoxFieldElement extends ElementX 241 class BoxFieldElement extends ElementX
254 implements TypedElement, CapturedVariable, FieldElement, 242 implements
243 TypedElement,
244 CapturedVariable,
245 FieldElement,
255 PrivatelyNamedJSEntity { 246 PrivatelyNamedJSEntity {
256 final BoxLocal box; 247 final BoxLocal box;
257 248
258 BoxFieldElement(String name, this.variableElement, 249 BoxFieldElement(String name, this.variableElement, BoxLocal box)
259 BoxLocal box)
260 : this.box = box, 250 : this.box = box,
261 super(name, ElementKind.FIELD, box.executableContext); 251 super(name, ElementKind.FIELD, box.executableContext);
262 252
263 DartType computeType(Resolution resolution) => type; 253 DartType computeType(Resolution resolution) => type;
264 254
265 DartType get type => variableElement.type; 255 DartType get type => variableElement.type;
266 256
267 @override 257 @override
268 Entity get declaredEntity => variableElement; 258 Entity get declaredEntity => variableElement;
269 @override 259 @override
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 String get name => 'this'; 306 String get name => 'this';
317 307
318 ClassElement get enclosingClass => executableContext.enclosingClass; 308 ClassElement get enclosingClass => executableContext.enclosingClass;
319 } 309 }
320 310
321 /// Call method of a closure class. 311 /// Call method of a closure class.
322 class SynthesizedCallMethodElementX extends BaseFunctionElementX 312 class SynthesizedCallMethodElementX extends BaseFunctionElementX
323 implements MethodElement { 313 implements MethodElement {
324 final LocalFunctionElement expression; 314 final LocalFunctionElement expression;
325 315
326 SynthesizedCallMethodElementX(String name, 316 SynthesizedCallMethodElementX(
327 LocalFunctionElementX other, 317 String name, LocalFunctionElementX other, ClosureClassElement enclosing)
328 ClosureClassElement enclosing)
329 : expression = other, 318 : expression = other,
330 super(name, other.kind, other.modifiers, enclosing) { 319 super(name, other.kind, other.modifiers, enclosing) {
331 asyncMarker = other.asyncMarker; 320 asyncMarker = other.asyncMarker;
332 functionSignature = other.functionSignature; 321 functionSignature = other.functionSignature;
333 } 322 }
334 323
335 /// Use [closureClass] instead. 324 /// Use [closureClass] instead.
336 @deprecated 325 @deprecated
337 get enclosingElement => super.enclosingElement; 326 get enclosingElement => super.enclosingElement;
338 327
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 List<VariableElement> boxedLoopVariables = const <VariableElement>[]; 360 List<VariableElement> boxedLoopVariables = const <VariableElement>[];
372 361
373 ClosureScope(this.boxElement, this.capturedVariables); 362 ClosureScope(this.boxElement, this.capturedVariables);
374 363
375 bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty; 364 bool hasBoxedLoopVariables() => !boxedLoopVariables.isEmpty;
376 365
377 bool isCapturedVariable(VariableElement variable) { 366 bool isCapturedVariable(VariableElement variable) {
378 return capturedVariables.containsKey(variable); 367 return capturedVariables.containsKey(variable);
379 } 368 }
380 369
381 void forEachCapturedVariable(f(LocalVariableElement variable, 370 void forEachCapturedVariable(
382 BoxFieldElement boxField)) { 371 f(LocalVariableElement variable, BoxFieldElement boxField)) {
383 capturedVariables.forEach(f); 372 capturedVariables.forEach(f);
384 } 373 }
385 } 374 }
386 375
387 class ClosureClassMap { 376 class ClosureClassMap {
388 // The closure's element before any translation. Will be null for methods. 377 // The closure's element before any translation. Will be null for methods.
389 final LocalFunctionElement closureElement; 378 final LocalFunctionElement closureElement;
390 // The closureClassElement will be null for methods that are not local 379 // The closureClassElement will be null for methods that are not local
391 // closures. 380 // closures.
392 final ClosureClassElement closureClassElement; 381 final ClosureClassElement closureClassElement;
(...skipping 16 matching lines...) Expand all
409 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>(); 398 final Map<Node, ClosureScope> capturingScopes = new Map<Node, ClosureScope>();
410 399
411 /// Variables that are used in a try must be treated as boxed because the 400 /// Variables that are used in a try must be treated as boxed because the
412 /// control flow can be non-linear. 401 /// control flow can be non-linear.
413 /// 402 ///
414 /// Also parameters to a `sync*` generator must be boxed, because of the way 403 /// Also parameters to a `sync*` generator must be boxed, because of the way
415 /// we rewrite sync* functions. See also comments in [useLocal]. 404 /// we rewrite sync* functions. See also comments in [useLocal].
416 /// TODO(johnniwinter): Add variables to this only if the variable is mutated. 405 /// TODO(johnniwinter): Add variables to this only if the variable is mutated.
417 final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>(); 406 final Set<Local> variablesUsedInTryOrGenerator = new Set<Local>();
418 407
419 ClosureClassMap(this.closureElement, 408 ClosureClassMap(this.closureElement, this.closureClassElement,
420 this.closureClassElement, 409 this.callElement, this.thisLocal);
421 this.callElement,
422 this.thisLocal);
423 410
424 void addFreeVariable(Local element) { 411 void addFreeVariable(Local element) {
425 assert(freeVariableMap[element] == null); 412 assert(freeVariableMap[element] == null);
426 freeVariableMap[element] = null; 413 freeVariableMap[element] = null;
427 } 414 }
428 415
429 Iterable<Local> get freeVariables => freeVariableMap.keys; 416 Iterable<Local> get freeVariables => freeVariableMap.keys;
430 417
431 bool isFreeVariable(Local element) { 418 bool isFreeVariable(Local element) {
432 return freeVariableMap.containsKey(element); 419 return freeVariableMap.containsKey(element);
433 } 420 }
434 421
435 void forEachFreeVariable(f(Local variable, 422 void forEachFreeVariable(f(Local variable, CapturedVariable field)) {
436 CapturedVariable field)) {
437 freeVariableMap.forEach(f); 423 freeVariableMap.forEach(f);
438 } 424 }
439 425
440 Local getLocalVariableForClosureField(ClosureFieldElement field) { 426 Local getLocalVariableForClosureField(ClosureFieldElement field) {
441 return field.local; 427 return field.local;
442 } 428 }
443 429
444 bool get isClosure => closureElement != null; 430 bool get isClosure => closureElement != null;
445 431
446 bool capturingScopesBox(Local variable) { 432 bool capturingScopesBox(Local variable) {
447 return capturingScopes.values.any((scope) { 433 return capturingScopes.values.any((scope) {
448 return scope.boxedLoopVariables.contains(variable); 434 return scope.boxedLoopVariables.contains(variable);
449 }); 435 });
450 } 436 }
451 437
452 bool isVariableBoxed(Local variable) { 438 bool isVariableBoxed(Local variable) {
453 CapturedVariable copy = freeVariableMap[variable]; 439 CapturedVariable copy = freeVariableMap[variable];
454 if (copy is BoxFieldElement) { 440 if (copy is BoxFieldElement) {
455 return true; 441 return true;
456 } 442 }
457 return capturingScopesBox(variable); 443 return capturingScopesBox(variable);
458 } 444 }
459 445
460 void forEachCapturedVariable(void f(Local variable, 446 void forEachCapturedVariable(void f(Local variable, CapturedVariable field)) {
461 CapturedVariable field)) {
462 freeVariableMap.forEach((variable, copy) { 447 freeVariableMap.forEach((variable, copy) {
463 if (variable is BoxLocal) return; 448 if (variable is BoxLocal) return;
464 f(variable, copy); 449 f(variable, copy);
465 }); 450 });
466 capturingScopes.values.forEach((ClosureScope scope) { 451 capturingScopes.values.forEach((ClosureScope scope) {
467 scope.forEachCapturedVariable(f); 452 scope.forEachCapturedVariable(f);
468 }); 453 });
469 } 454 }
470 455
471 void forEachBoxedVariable(void f(LocalVariableElement local, 456 void forEachBoxedVariable(
472 BoxFieldElement field)) { 457 void f(LocalVariableElement local, BoxFieldElement field)) {
473 freeVariableMap.forEach((variable, copy) { 458 freeVariableMap.forEach((variable, copy) {
474 if (!isVariableBoxed(variable)) return; 459 if (!isVariableBoxed(variable)) return;
475 f(variable, copy); 460 f(variable, copy);
476 }); 461 });
477 capturingScopes.values.forEach((ClosureScope scope) { 462 capturingScopes.values.forEach((ClosureScope scope) {
478 scope.forEachCapturedVariable(f); 463 scope.forEachCapturedVariable(f);
479 }); 464 });
480 } 465 }
481 466
482 void removeMyselfFrom(Universe universe) { 467 void removeMyselfFrom(Universe universe) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 Set<LocalVariableElement> mutatedVariables = new Set<LocalVariableElement>(); 499 Set<LocalVariableElement> mutatedVariables = new Set<LocalVariableElement>();
515 500
516 MemberElement outermostElement; 501 MemberElement outermostElement;
517 ExecutableElement executableContext; 502 ExecutableElement executableContext;
518 503
519 // The closureData of the currentFunctionElement. 504 // The closureData of the currentFunctionElement.
520 ClosureClassMap closureData; 505 ClosureClassMap closureData;
521 506
522 bool insideClosure = false; 507 bool insideClosure = false;
523 508
524 ClosureTranslator(this.compiler, 509 ClosureTranslator(this.compiler, this.elements, this.closureMappingCache);
525 this.elements,
526 this.closureMappingCache);
527 510
528 DiagnosticReporter get reporter => compiler.reporter; 511 DiagnosticReporter get reporter => compiler.reporter;
529 512
530 /// Generate a unique name for the [id]th closure field, with proposed name 513 /// Generate a unique name for the [id]th closure field, with proposed name
531 /// [name]. 514 /// [name].
532 /// 515 ///
533 /// The result is used as the name of [ClosureFieldElement]s, and must 516 /// The result is used as the name of [ClosureFieldElement]s, and must
534 /// therefore be unique to avoid breaking an invariant in the element model 517 /// therefore be unique to avoid breaking an invariant in the element model
535 /// (classes cannot declare multiple fields with the same name). 518 /// (classes cannot declare multiple fields with the same name).
536 /// 519 ///
(...skipping 24 matching lines...) Expand all
561 return _capturedVariableMapping.containsKey(element); 544 return _capturedVariableMapping.containsKey(element);
562 } 545 }
563 546
564 void addCapturedVariable(Node node, Local variable) { 547 void addCapturedVariable(Node node, Local variable) {
565 if (_capturedVariableMapping[variable] != null) { 548 if (_capturedVariableMapping[variable] != null) {
566 reporter.internalError(node, 'In closure analyzer.'); 549 reporter.internalError(node, 'In closure analyzer.');
567 } 550 }
568 _capturedVariableMapping[variable] = null; 551 _capturedVariableMapping[variable] = null;
569 } 552 }
570 553
571 void setCapturedVariableBoxField(Local variable, 554 void setCapturedVariableBoxField(Local variable, BoxFieldElement boxField) {
572 BoxFieldElement boxField) {
573 assert(isCapturedVariable(variable)); 555 assert(isCapturedVariable(variable));
574 _capturedVariableMapping[variable] = boxField; 556 _capturedVariableMapping[variable] = boxField;
575 } 557 }
576 558
577 BoxFieldElement getCapturedVariableBoxField(Local variable) { 559 BoxFieldElement getCapturedVariableBoxField(Local variable) {
578 return _capturedVariableMapping[variable]; 560 return _capturedVariableMapping[variable];
579 } 561 }
580 562
581 void translateFunction(Element element, FunctionExpression node) { 563 void translateFunction(Element element, FunctionExpression node) {
582 // For constructors the [element] and the [:elements[node]:] may differ. 564 // For constructors the [element] and the [:elements[node]:] may differ.
583 // The [:elements[node]:] always points to the generative-constructor 565 // The [:elements[node]:] always points to the generative-constructor
584 // element, whereas the [element] might be the constructor-body element. 566 // element, whereas the [element] might be the constructor-body element.
585 visit(node); // [visitFunctionExpression] will call [visitInvokable]. 567 visit(node); // [visitFunctionExpression] will call [visitInvokable].
586 // When variables need to be boxed their [_capturedVariableMapping] is 568 // When variables need to be boxed their [_capturedVariableMapping] is
587 // updated, but we delay updating the similar freeVariableMapping in the 569 // updated, but we delay updating the similar freeVariableMapping in the
588 // closure datas that capture these variables. 570 // closure datas that capture these variables.
589 // The closures don't have their fields (in the closure class) set, either. 571 // The closures don't have their fields (in the closure class) set, either.
590 updateClosures(); 572 updateClosures();
591 } 573 }
592 574
593 void translateLazyInitializer(VariableElement element, 575 void translateLazyInitializer(VariableElement element,
594 VariableDefinitions node, 576 VariableDefinitions node, Expression initializer) {
595 Expression initializer) { 577 visitInvokable(element, node, () {
596 visitInvokable(element, node, () { visit(initializer); }); 578 visit(initializer);
579 });
597 updateClosures(); 580 updateClosures();
598 } 581 }
599 582
600 // This function runs through all of the existing closures and updates their 583 // This function runs through all of the existing closures and updates their
601 // free variables to the boxed value. It also adds the field-elements to the 584 // free variables to the boxed value. It also adds the field-elements to the
602 // class representing the closure. 585 // class representing the closure.
603 void updateClosures() { 586 void updateClosures() {
604 for (Expression closure in closures) { 587 for (Expression closure in closures) {
605 // The captured variables that need to be stored in a field of the closure 588 // The captured variables that need to be stored in a field of the closure
606 // class. 589 // class.
(...skipping 13 matching lines...) Expand all
620 assert(fromElement is! BoxLocal); 603 assert(fromElement is! BoxLocal);
621 // The variable has not been boxed. 604 // The variable has not been boxed.
622 fieldCaptures.add(fromElement); 605 fieldCaptures.add(fromElement);
623 } else { 606 } else {
624 // A boxed element. 607 // A boxed element.
625 data.freeVariableMap[fromElement] = boxFieldElement; 608 data.freeVariableMap[fromElement] = boxFieldElement;
626 boxes.add(boxFieldElement.box); 609 boxes.add(boxFieldElement.box);
627 } 610 }
628 }); 611 });
629 ClosureClassElement closureClass = data.closureClassElement; 612 ClosureClassElement closureClass = data.closureClassElement;
630 assert(closureClass != null || 613 assert(closureClass != null || (fieldCaptures.isEmpty && boxes.isEmpty));
631 (fieldCaptures.isEmpty && boxes.isEmpty));
632 614
633 void addClosureField(Local local, String name) { 615 void addClosureField(Local local, String name) {
634 ClosureFieldElement closureField = 616 ClosureFieldElement closureField =
635 new ClosureFieldElement(name, local, closureClass); 617 new ClosureFieldElement(name, local, closureClass);
636 closureClass.addField(closureField, reporter); 618 closureClass.addField(closureField, reporter);
637 data.freeVariableMap[local] = closureField; 619 data.freeVariableMap[local] = closureField;
638 } 620 }
639 621
640 // Add the box elements first so we get the same ordering. 622 // Add the box elements first so we get the same ordering.
641 // TODO(sra): What is the canonical order of multiple boxes? 623 // TODO(sra): What is the canonical order of multiple boxes?
(...skipping 25 matching lines...) Expand all
667 649
668 void useLocal(Local variable) { 650 void useLocal(Local variable) {
669 // If the element is not declared in the current function and the element 651 // If the element is not declared in the current function and the element
670 // is not the closure itself we need to mark the element as free variable. 652 // is not the closure itself we need to mark the element as free variable.
671 // Note that the check on [insideClosure] is not just an 653 // Note that the check on [insideClosure] is not just an
672 // optimization: factories have type parameters as function 654 // optimization: factories have type parameters as function
673 // parameters, and type parameters are declared in the class, not 655 // parameters, and type parameters are declared in the class, not
674 // the factory. 656 // the factory.
675 bool inCurrentContext(Local variable) { 657 bool inCurrentContext(Local variable) {
676 return variable == executableContext || 658 return variable == executableContext ||
677 variable.executableContext == executableContext; 659 variable.executableContext == executableContext;
678 } 660 }
679 661
680 if (insideClosure && !inCurrentContext(variable)) { 662 if (insideClosure && !inCurrentContext(variable)) {
681 closureData.addFreeVariable(variable); 663 closureData.addFreeVariable(variable);
682 } else if (inTryStatement) { 664 } else if (inTryStatement) {
683 // Don't mark the this-element or a self-reference. This would complicate 665 // Don't mark the this-element or a self-reference. This would complicate
684 // things in the builder. 666 // things in the builder.
685 // Note that nested (named) functions are immutable. 667 // Note that nested (named) functions are immutable.
686 if (variable != closureData.thisLocal && 668 if (variable != closureData.thisLocal &&
687 variable != closureData.closureElement && 669 variable != closureData.closureElement &&
(...skipping 24 matching lines...) Expand all
712 694
713 visit(Node node) => node.accept(this); 695 visit(Node node) => node.accept(this);
714 696
715 visitNode(Node node) => node.visitChildren(this); 697 visitNode(Node node) => node.visitChildren(this);
716 698
717 visitVariableDefinitions(VariableDefinitions node) { 699 visitVariableDefinitions(VariableDefinitions node) {
718 if (node.type != null) { 700 if (node.type != null) {
719 visit(node.type); 701 visit(node.type);
720 } 702 }
721 for (Link<Node> link = node.definitions.nodes; 703 for (Link<Node> link = node.definitions.nodes;
722 !link.isEmpty; 704 !link.isEmpty;
723 link = link.tail) { 705 link = link.tail) {
724 Node definition = link.head; 706 Node definition = link.head;
725 LocalElement element = elements[definition]; 707 LocalElement element = elements[definition];
726 assert(element != null); 708 assert(element != null);
727 if (!element.isInitializingFormal) { 709 if (!element.isInitializingFormal) {
728 declareLocal(element); 710 declareLocal(element);
729 } 711 }
730 // We still need to visit the right-hand sides of the init-assignments. 712 // We still need to visit the right-hand sides of the init-assignments.
731 // For SendSets don't visit the left again. Otherwise it would be marked 713 // For SendSets don't visit the left again. Otherwise it would be marked
732 // as mutated. 714 // as mutated.
733 if (definition is Send) { 715 if (definition is Send) {
734 Send assignment = definition; 716 Send assignment = definition;
735 Node arguments = assignment.argumentsNode; 717 Node arguments = assignment.argumentsNode;
736 if (arguments != null) { 718 if (arguments != null) {
737 visit(arguments); 719 visit(arguments);
738 } 720 }
739 } else { 721 } else {
740 visit(definition); 722 visit(definition);
741 } 723 }
742 } 724 }
743 } 725 }
744 726
745 visitTypeAnnotation(TypeAnnotation node) { 727 visitTypeAnnotation(TypeAnnotation node) {
746 MemberElement member = executableContext.memberContext; 728 MemberElement member = executableContext.memberContext;
747 DartType type = elements.getType(node); 729 DartType type = elements.getType(node);
748 // TODO(karlklose,johnniwinther): if the type is null, the annotation is 730 // TODO(karlklose,johnniwinther): if the type is null, the annotation is
749 // from a parameter which has been analyzed before the method has been 731 // from a parameter which has been analyzed before the method has been
750 // resolved and the result has been thrown away. 732 // resolved and the result has been thrown away.
751 if (compiler.options.enableTypeAssertions && type != null && 733 if (compiler.options.enableTypeAssertions &&
734 type != null &&
752 type.containsTypeVariables) { 735 type.containsTypeVariables) {
753 if (insideClosure && member.isFactoryConstructor) { 736 if (insideClosure && member.isFactoryConstructor) {
754 // This is a closure in a factory constructor. Since there is no 737 // This is a closure in a factory constructor. Since there is no
755 // [:this:], we have to mark the type arguments as free variables to 738 // [:this:], we have to mark the type arguments as free variables to
756 // capture them in the closure. 739 // capture them in the closure.
757 type.forEachTypeVariable((TypeVariableType variable) { 740 type.forEachTypeVariable((TypeVariableType variable) {
758 useTypeVariableAsLocal(variable); 741 useTypeVariableAsLocal(variable);
759 }); 742 });
760 } 743 }
761 if (member.isInstanceMember && !member.isField) { 744 if (member.isInstanceMember && !member.isField) {
762 // In checked mode, using a type variable in a type annotation may lead 745 // In checked mode, using a type variable in a type annotation may lead
763 // to a runtime type check that needs to access the type argument and 746 // to a runtime type check that needs to access the type argument and
764 // therefore the closure needs a this-element, if it is not in a field 747 // therefore the closure needs a this-element, if it is not in a field
765 // initializer; field initatializers are evaluated in a context where 748 // initializer; field initatializers are evaluated in a context where
766 // the type arguments are available in locals. 749 // the type arguments are available in locals.
767 registerNeedsThis(); 750 registerNeedsThis();
768 } 751 }
769 } 752 }
770 } 753 }
771 754
772 visitIdentifier(Identifier node) { 755 visitIdentifier(Identifier node) {
773 if (node.isThis()) { 756 if (node.isThis()) {
774 registerNeedsThis(); 757 registerNeedsThis();
775 } else { 758 } else {
776 Element element = elements[node]; 759 Element element = elements[node];
777 if (element != null && element.isTypeVariable) { 760 if (element != null && element.isTypeVariable) {
778 if (outermostElement.isConstructor || 761 if (outermostElement.isConstructor || outermostElement.isField) {
779 outermostElement.isField) {
780 TypeVariableElement typeVariable = element; 762 TypeVariableElement typeVariable = element;
781 useTypeVariableAsLocal(typeVariable.type); 763 useTypeVariableAsLocal(typeVariable.type);
782 } else { 764 } else {
783 registerNeedsThis(); 765 registerNeedsThis();
784 } 766 }
785 } 767 }
786 } 768 }
787 node.visitChildren(this); 769 node.visitChildren(this);
788 } 770 }
789 771
790 visitSend(Send node) { 772 visitSend(Send node) {
791 Element element = elements[node]; 773 Element element = elements[node];
792 if (Elements.isLocal(element)) { 774 if (Elements.isLocal(element)) {
793 LocalElement localElement = element; 775 LocalElement localElement = element;
794 useLocal(localElement); 776 useLocal(localElement);
795 } else if (element != null && element.isTypeVariable) { 777 } else if (element != null && element.isTypeVariable) {
796 TypeVariableElement variable = element; 778 TypeVariableElement variable = element;
797 analyzeType(variable.type); 779 analyzeType(variable.type);
798 } else if (node.receiver == null && 780 } else if (node.receiver == null &&
799 Elements.isInstanceSend(node, elements)) { 781 Elements.isInstanceSend(node, elements)) {
800 registerNeedsThis(); 782 registerNeedsThis();
801 } else if (node.isSuperCall) { 783 } else if (node.isSuperCall) {
802 registerNeedsThis(); 784 registerNeedsThis();
803 } else if (node.isTypeTest || node.isTypeCast) { 785 } else if (node.isTypeTest || node.isTypeCast) {
804 TypeAnnotation annotation = node.typeAnnotationFromIsCheckOrCast; 786 TypeAnnotation annotation = node.typeAnnotationFromIsCheckOrCast;
805 DartType type = elements.getType(annotation); 787 DartType type = elements.getType(annotation);
806 analyzeType(type); 788 analyzeType(type);
807 } else if (node.isTypeTest) { 789 } else if (node.isTypeTest) {
808 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); 790 DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
809 analyzeType(type); 791 analyzeType(type);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 visitLiteralMap(LiteralMap node) { 823 visitLiteralMap(LiteralMap node) {
842 DartType type = elements.getType(node); 824 DartType type = elements.getType(node);
843 analyzeType(type); 825 analyzeType(type);
844 node.visitChildren(this); 826 node.visitChildren(this);
845 } 827 }
846 828
847 void analyzeTypeVariables(DartType type) { 829 void analyzeTypeVariables(DartType type) {
848 type.forEachTypeVariable((TypeVariableType typeVariable) { 830 type.forEachTypeVariable((TypeVariableType typeVariable) {
849 // Field initializers are inlined and access the type variable as 831 // Field initializers are inlined and access the type variable as
850 // normal parameters. 832 // normal parameters.
851 if (!outermostElement.isField && 833 if (!outermostElement.isField && !outermostElement.isConstructor) {
852 !outermostElement.isConstructor) {
853 registerNeedsThis(); 834 registerNeedsThis();
854 } else { 835 } else {
855 useTypeVariableAsLocal(typeVariable); 836 useTypeVariableAsLocal(typeVariable);
856 } 837 }
857 }); 838 });
858 } 839 }
859 840
860 void analyzeType(DartType type) { 841 void analyzeType(DartType type) {
861 // TODO(johnniwinther): Find out why this can be null. 842 // TODO(johnniwinther): Find out why this can be null.
862 if (type == null) return; 843 if (type == null) return;
863 if (outermostElement.isClassMember && 844 if (outermostElement.isClassMember &&
864 compiler.backend.classNeedsRti(outermostElement.enclosingClass)) { 845 compiler.backend.classNeedsRti(outermostElement.enclosingClass)) {
865 if (outermostElement.isConstructor || 846 if (outermostElement.isConstructor || outermostElement.isField) {
866 outermostElement.isField) {
867 analyzeTypeVariables(type); 847 analyzeTypeVariables(type);
868 } else if (outermostElement.isInstanceMember) { 848 } else if (outermostElement.isInstanceMember) {
869 if (type.containsTypeVariables) { 849 if (type.containsTypeVariables) {
870 registerNeedsThis(); 850 registerNeedsThis();
871 } 851 }
872 } 852 }
873 } 853 }
874 } 854 }
875 855
876 // If variables that are declared in the [node] scope are captured and need 856 // If variables that are declared in the [node] scope are captured and need
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
951 // condition or body are indeed flagged as mutated. 931 // condition or body are indeed flagged as mutated.
952 if (node.conditionStatement != null) visit(node.conditionStatement); 932 if (node.conditionStatement != null) visit(node.conditionStatement);
953 if (node.body != null) visit(node.body); 933 if (node.body != null) visit(node.body);
954 934
955 // See if we have declared loop variables that need to be boxed. 935 // See if we have declared loop variables that need to be boxed.
956 if (node.initializer == null) return; 936 if (node.initializer == null) return;
957 VariableDefinitions definitions = 937 VariableDefinitions definitions =
958 node.initializer.asVariableDefinitions(); 938 node.initializer.asVariableDefinitions();
959 if (definitions == null) return; 939 if (definitions == null) return;
960 for (Link<Node> link = definitions.definitions.nodes; 940 for (Link<Node> link = definitions.definitions.nodes;
961 !link.isEmpty; 941 !link.isEmpty;
962 link = link.tail) { 942 link = link.tail) {
963 Node definition = link.head; 943 Node definition = link.head;
964 LocalVariableElement element = elements[definition]; 944 LocalVariableElement element = elements[definition];
965 // Non-mutated variables should not be boxed. The mutatedVariables set 945 // Non-mutated variables should not be boxed. The mutatedVariables set
966 // gets cleared when 'inNewScope' returns, so check it here. 946 // gets cleared when 'inNewScope' returns, so check it here.
967 if (isCapturedVariable(element) && mutatedVariables.contains(element)) { 947 if (isCapturedVariable(element) && mutatedVariables.contains(element)) {
968 boxedLoopVariables.add(element); 948 boxedLoopVariables.add(element);
969 } 949 }
970 } 950 }
971 }); 951 });
972 ClosureScope scopeData = closureData.capturingScopes[node]; 952 ClosureScope scopeData = closureData.capturingScopes[node];
973 if (scopeData == null) return; 953 if (scopeData == null) return;
974 scopeData.boxedLoopVariables = boxedLoopVariables; 954 scopeData.boxedLoopVariables = boxedLoopVariables;
975 } 955 }
976 956
977 /** Returns a non-unique name for the given closure element. */ 957 /** Returns a non-unique name for the given closure element. */
978 String computeClosureName(Element element) { 958 String computeClosureName(Element element) {
979 Link<String> parts = const Link<String>(); 959 Link<String> parts = const Link<String>();
980 String ownName = element.name; 960 String ownName = element.name;
981 if (ownName == null || ownName == "") { 961 if (ownName == null || ownName == "") {
982 parts = parts.prepend("closure"); 962 parts = parts.prepend("closure");
983 } else { 963 } else {
984 parts = parts.prepend(ownName); 964 parts = parts.prepend(ownName);
985 } 965 }
986 for (Element enclosingElement = element.enclosingElement; 966 for (Element enclosingElement = element.enclosingElement;
987 enclosingElement != null && 967 enclosingElement != null &&
988 (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY 968 (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
989 || enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR 969 enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR ||
990 || enclosingElement.kind == ElementKind.CLASS 970 enclosingElement.kind == ElementKind.CLASS ||
991 || enclosingElement.kind == ElementKind.FUNCTION 971 enclosingElement.kind == ElementKind.FUNCTION ||
992 || enclosingElement.kind == ElementKind.GETTER 972 enclosingElement.kind == ElementKind.GETTER ||
993 || enclosingElement.kind == ElementKind.SETTER); 973 enclosingElement.kind == ElementKind.SETTER);
994 enclosingElement = enclosingElement.enclosingElement) { 974 enclosingElement = enclosingElement.enclosingElement) {
995 // TODO(johnniwinther): Simplify computed names. 975 // TODO(johnniwinther): Simplify computed names.
996 if (enclosingElement.isGenerativeConstructor || 976 if (enclosingElement.isGenerativeConstructor ||
997 enclosingElement.isGenerativeConstructorBody || 977 enclosingElement.isGenerativeConstructorBody ||
998 enclosingElement.isFactoryConstructor) { 978 enclosingElement.isFactoryConstructor) {
999 parts = parts.prepend( 979 parts = parts
1000 Elements.reconstructConstructorName(enclosingElement)); 980 .prepend(Elements.reconstructConstructorName(enclosingElement));
1001 } else { 981 } else {
1002 String surroundingName = 982 String surroundingName =
1003 Elements.operatorNameToIdentifier(enclosingElement.name); 983 Elements.operatorNameToIdentifier(enclosingElement.name);
1004 parts = parts.prepend(surroundingName); 984 parts = parts.prepend(surroundingName);
1005 } 985 }
1006 // A generative constructors's parent is the class; the class name is 986 // A generative constructors's parent is the class; the class name is
1007 // already part of the generative constructor's name. 987 // already part of the generative constructor's name.
1008 if (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR) break; 988 if (enclosingElement.kind == ElementKind.GENERATIVE_CONSTRUCTOR) break;
1009 } 989 }
1010 StringBuffer sb = new StringBuffer(); 990 StringBuffer sb = new StringBuffer();
1011 parts.printOn(sb, '_'); 991 parts.printOn(sb, '_');
1012 return sb.toString(); 992 return sb.toString();
1013 } 993 }
1014 994
1015 JavaScriptBackend get backend => compiler.backend; 995 JavaScriptBackend get backend => compiler.backend;
1016 996
1017 ClosureClassMap globalizeClosure(FunctionExpression node, 997 ClosureClassMap globalizeClosure(
1018 LocalFunctionElement element) { 998 FunctionExpression node, LocalFunctionElement element) {
1019 String closureName = computeClosureName(element); 999 String closureName = computeClosureName(element);
1020 ClosureClassElement globalizedElement = new ClosureClassElement( 1000 ClosureClassElement globalizedElement =
1021 node, closureName, compiler, element); 1001 new ClosureClassElement(node, closureName, compiler, element);
1022 // Extend [globalizedElement] as an instantiated class in the closed world. 1002 // Extend [globalizedElement] as an instantiated class in the closed world.
1023 compiler.world.registerClass( 1003 compiler.world
1024 globalizedElement, isDirectlyInstantiated: true); 1004 .registerClass(globalizedElement, isDirectlyInstantiated: true);
1025 FunctionElement callElement = 1005 FunctionElement callElement = new SynthesizedCallMethodElementX(
1026 new SynthesizedCallMethodElementX(Identifiers.call, 1006 Identifiers.call, element, globalizedElement);
1027 element,
1028 globalizedElement);
1029 backend.maybeMarkClosureAsNeededForReflection( 1007 backend.maybeMarkClosureAsNeededForReflection(
1030 globalizedElement, callElement, element); 1008 globalizedElement, callElement, element);
1031 MemberElement enclosing = element.memberContext; 1009 MemberElement enclosing = element.memberContext;
1032 enclosing.nestedClosures.add(callElement); 1010 enclosing.nestedClosures.add(callElement);
1033 globalizedElement.addMember(callElement, reporter); 1011 globalizedElement.addMember(callElement, reporter);
1034 globalizedElement.computeAllClassMembers(compiler); 1012 globalizedElement.computeAllClassMembers(compiler);
1035 // The nested function's 'this' is the same as the one for the outer 1013 // The nested function's 'this' is the same as the one for the outer
1036 // function. It could be [null] if we are inside a static method. 1014 // function. It could be [null] if we are inside a static method.
1037 ThisLocal thisElement = closureData.thisLocal; 1015 ThisLocal thisElement = closureData.thisLocal;
1038 1016
1039 return new ClosureClassMap(element, globalizedElement, 1017 return new ClosureClassMap(
1040 callElement, thisElement); 1018 element, globalizedElement, callElement, thisElement);
1041 } 1019 }
1042 1020
1043 void visitInvokable(ExecutableElement element, 1021 void visitInvokable(
1044 Node node, 1022 ExecutableElement element, Node node, void visitChildren()) {
1045 void visitChildren()) {
1046 bool oldInsideClosure = insideClosure; 1023 bool oldInsideClosure = insideClosure;
1047 Element oldFunctionElement = executableContext; 1024 Element oldFunctionElement = executableContext;
1048 ClosureClassMap oldClosureData = closureData; 1025 ClosureClassMap oldClosureData = closureData;
1049 1026
1050 insideClosure = outermostElement != null; 1027 insideClosure = outermostElement != null;
1051 LocalFunctionElement closure; 1028 LocalFunctionElement closure;
1052 executableContext = element; 1029 executableContext = element;
1053 if (insideClosure) { 1030 if (insideClosure) {
1054 closure = element; 1031 closure = element;
1055 closures.add(node); 1032 closures.add(node);
1056 closureData = globalizeClosure(node, closure); 1033 closureData = globalizeClosure(node, closure);
1057 } else { 1034 } else {
1058 outermostElement = element; 1035 outermostElement = element;
1059 ThisLocal thisElement = null; 1036 ThisLocal thisElement = null;
1060 if (element.isInstanceMember || element.isGenerativeConstructor) { 1037 if (element.isInstanceMember || element.isGenerativeConstructor) {
1061 thisElement = new ThisLocal(element); 1038 thisElement = new ThisLocal(element);
1062 } 1039 }
1063 closureData = new ClosureClassMap(null, null, null, thisElement); 1040 closureData = new ClosureClassMap(null, null, null, thisElement);
1064 } 1041 }
1065 closureMappingCache[node] = closureData; 1042 closureMappingCache[node] = closureData;
1066 1043
1067 inNewScope(node, () { 1044 inNewScope(node, () {
1068 DartType type = element.type; 1045 DartType type = element.type;
1069 // If the method needs RTI, or checked mode is set, we need to 1046 // If the method needs RTI, or checked mode is set, we need to
1070 // escape the potential type variables used in that closure. 1047 // escape the potential type variables used in that closure.
1071 if (element is FunctionElement && 1048 if (element is FunctionElement &&
1072 (compiler.backend.methodNeedsRti(element) || 1049 (compiler.backend.methodNeedsRti(element) ||
1073 compiler.options.enableTypeAssertions)) { 1050 compiler.options.enableTypeAssertions)) {
1074 analyzeTypeVariables(type); 1051 analyzeTypeVariables(type);
1075 } 1052 }
1076 1053
1077 visitChildren(); 1054 visitChildren();
1078 }); 1055 });
1079 1056
1080
1081 ClosureClassMap savedClosureData = closureData; 1057 ClosureClassMap savedClosureData = closureData;
1082 bool savedInsideClosure = insideClosure; 1058 bool savedInsideClosure = insideClosure;
1083 1059
1084 // Restore old values. 1060 // Restore old values.
1085 insideClosure = oldInsideClosure; 1061 insideClosure = oldInsideClosure;
1086 closureData = oldClosureData; 1062 closureData = oldClosureData;
1087 executableContext = oldFunctionElement; 1063 executableContext = oldFunctionElement;
1088 1064
1089 // Mark all free variables as captured and use them in the outer function. 1065 // Mark all free variables as captured and use them in the outer function.
1090 Iterable<Local> freeVariables = savedClosureData.freeVariables; 1066 Iterable<Local> freeVariables = savedClosureData.freeVariables;
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
1162 /// 1138 ///
1163 /// Move the below classes to a JS model eventually. 1139 /// Move the below classes to a JS model eventually.
1164 /// 1140 ///
1165 abstract class JSEntity implements Entity { 1141 abstract class JSEntity implements Entity {
1166 Entity get declaredEntity; 1142 Entity get declaredEntity;
1167 } 1143 }
1168 1144
1169 abstract class PrivatelyNamedJSEntity implements JSEntity { 1145 abstract class PrivatelyNamedJSEntity implements JSEntity {
1170 Entity get rootOfScope; 1146 Entity get rootOfScope;
1171 } 1147 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cache_strategy.dart ('k') | pkg/compiler/lib/src/common.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698