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

Side by Side Diff: pkg/fletchc/lib/src/closure_environment.dart

Issue 1659163007: Rename fletch -> dartino (Closed) Base URL: https://github.com/dartino/sdk.git@master
Patch Set: address comments Created 4 years, 10 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/fletchc/lib/src/class_debug_info.dart ('k') | pkg/fletchc/lib/src/codegen_visitor.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE.md file.
4
5 library fletchc.closure_environment;
6
7 import 'package:compiler/src/resolution/semantic_visitor.dart';
8
9 import 'package:compiler/src/resolution/operators.dart' show
10 AssignmentOperator,
11 BinaryOperator,
12 IncDecOperator,
13 UnaryOperator;
14
15 import 'package:compiler/src/elements/elements.dart';
16 import 'package:compiler/src/resolution/tree_elements.dart';
17 import 'package:compiler/src/resolution/send_resolver.dart';
18 import 'package:compiler/src/tree/tree.dart';
19 import 'package:compiler/src/universe/selector.dart';
20 import 'package:compiler/src/universe/call_structure.dart';
21 import 'package:compiler/src/diagnostics/spannable.dart' show
22 Spannable,
23 SpannableAssertionFailure;
24 import 'package:compiler/src/dart_types.dart';
25
26 enum CaptureMode {
27 /**
28 * If a local is marked [ByValue], the local is read in closures.
29 */
30 ByValue,
31
32 /**
33 * If a local is marked [ByReference], a write to the local can be observed
34 * from a closure.
35 *
36 * In this case, the local must be boxed.
37 */
38 ByReference,
39 }
40
41 /**
42 * The computed infomation about a closures usage of locals and 'this'.
43 */
44 class ClosureInfo {
45 bool isThisFree = false;
46 Set<LocalElement> free = new Set<LocalElement>();
47
48 void markUsed(LocalElement element) {
49 free.add(element);
50 }
51 }
52
53 class ClosureEnvironment {
54 /**
55 * A map of locals that are captured, and how.
56 */
57 final Map<LocalElement, CaptureMode> captured = <LocalElement, CaptureMode>{};
58
59 /**
60 * A map of all nested closures of [function], and what locals they capture.
61 */
62 final Map<FunctionElement, ClosureInfo> closures =
63 <FunctionElement, ClosureInfo>{};
64
65 bool shouldBeBoxed(element) => captured[element] == CaptureMode.ByReference;
66 }
67
68 class ClosureVisitor
69 extends SemanticVisitor
70 with TraversalSendMixin,
71 SemanticSendResolvedMixin,
72 BaseImplementationOfLocalsMixin,
73 VariableBulkMixin,
74 ParameterBulkMixin,
75 FunctionBulkMixin,
76 ConstructorBulkMixin,
77 InitializerBulkMixin
78 implements SemanticSendVisitor, SemanticDeclarationVisitor {
79 final ClosureEnvironment closureEnvironment = new ClosureEnvironment();
80
81 /**
82 * A set of all locals that are assigned in [function] excluding nested
83 * closures. This is the inverse of implicit final locals.
84 */
85 final Set<LocalElement> locallyAssigned = new Set<LocalElement>();
86
87 final MemberElement element;
88
89 ExecutableElement currentElement;
90
91 bool inInitializers = false;
92
93 ClosureVisitor(this.element, TreeElements elements)
94 : super(elements);
95
96 SemanticSendVisitor get sendVisitor => this;
97 SemanticDeclarationVisitor get declVisitor => this;
98
99 ClosureEnvironment compute() {
100 assert(element.memberContext == element);
101 assert(currentElement == null);
102 currentElement = element;
103 if (element.node != null) element.resolvedAst.node.accept(this);
104 assert(currentElement == element);
105 return closureEnvironment;
106 }
107
108 void visitNode(Node node) {
109 node.visitChildren(this);
110 }
111
112 void visitVariableDefinitions(VariableDefinitions node) {
113 for (Node definition in node.definitions) {
114 VariableElement element = elements[definition];
115 Expression initializer = element.initializer;
116 if (initializer != null) initializer.accept(this);
117 }
118 }
119
120 void visitFunctionExpression(FunctionExpression node) {
121 ExecutableElement oldElement = currentElement;
122 currentElement = elements.getFunctionDefinition(node);
123 if (currentElement != element) {
124 ClosureInfo info = new ClosureInfo();
125 closureEnvironment.closures[currentElement] = info;
126 }
127 if (currentElement.isConstructor) {
128 inInitializers = true;
129 visitInitializers(node, null);
130 inInitializers = false;
131 }
132 node.body.accept(this);
133 currentElement = oldElement;
134 }
135
136 void visitFieldInitializer(
137 SendSet node,
138 FieldElement field,
139 Node initializer,
140 _) {
141 initializer.accept(this);
142 }
143
144 void visitSuperConstructorInvoke(
145 Send node,
146 ConstructorElement superConstructor,
147 InterfaceType type,
148 NodeList arguments,
149 CallStructure callStructure,
150 _) {
151 arguments.accept(this);
152 }
153
154 void visitThisConstructorInvoke(
155 Send node,
156 ConstructorElement thisConstructor,
157 NodeList arguments,
158 CallStructure callStructure,
159 _) {
160 arguments.accept(this);
161 }
162
163 void markUsed(LocalElement element, CaptureMode use) {
164 if (currentElement == element.executableContext) {
165 // If a local is assigned in the declaring context, and it is captured
166 // at this point, mark it as used by reference (we assign to the value
167 // after it's captured).
168 if (use == CaptureMode.ByReference) {
169 if (closureEnvironment.captured.containsKey(element)) {
170 closureEnvironment.captured[element] = use;
171 } else {
172 locallyAssigned.add(element);
173 }
174 }
175 } else {
176 if (locallyAssigned.contains(element)) use = CaptureMode.ByReference;
177 // If the element is used by reference, upgrade it unconditionally.
178 if (use == CaptureMode.ByReference) {
179 closureEnvironment.captured[element] = use;
180 } else {
181 // If it's used by value, only add it to `captured` if it's not
182 // there already - if it's in there it can be by reference.
183 closureEnvironment.captured.putIfAbsent(element, () => use);
184 }
185 ExecutableElement current = currentElement;
186 // Mark all closures from the current to the one where `element` is
187 // defined, as used in that closure. That makes sure we capture it in
188 // all intermidiate closures, thus making it available in the current.
189 while (current != element.executableContext) {
190 ClosureInfo info = closureEnvironment.closures[current];
191 info.markUsed(element);
192 current = (current as Local).executableContext;
193 }
194 }
195 }
196
197 void markThisUsed() {
198 assert(!inInitializers);
199 ExecutableElement current = currentElement;
200 while (current != element) {
201 ClosureInfo info = closureEnvironment.closures[current];
202 info.isThisFree = true;
203 current = (current as Local).executableContext;
204 }
205 }
206
207 void handleLocalGet(Send node, LocalElement element, _) {
208 markUsed(element, CaptureMode.ByValue);
209 }
210
211 void handleLocalSet(
212 SendSet node,
213 LocalElement element,
214 Node rhs,
215 _) {
216 markUsed(element, CaptureMode.ByReference);
217 rhs.accept(this);
218 }
219
220 void handleLocalInvoke(
221 Send node,
222 LocalElement element,
223 NodeList arguments,
224 CallStructure callStructure,
225 _) {
226 markUsed(element, CaptureMode.ByValue);
227 arguments.accept(this);
228 }
229
230 void visitThisPropertySet(Send node, Name name, Node rhs, _) {
231 markThisUsed();
232 super.visitThisPropertySet(node, name, rhs, null);
233 }
234
235 void visitLocalVariablePrefix(
236 SendSet node,
237 LocalVariableElement element,
238 IncDecOperator operator,
239 _) {
240 markUsed(element, CaptureMode.ByReference);
241 }
242
243 void visitLocalVariablePostfix(
244 SendSet node,
245 LocalVariableElement element,
246 IncDecOperator operator,
247 _) {
248 markUsed(element, CaptureMode.ByReference);
249 }
250
251 void visitThisPropertyInvoke(
252 Send node,
253 NodeList arguments,
254 Selector selector,
255 _) {
256 markThisUsed();
257 arguments.accept(this);
258 }
259
260 void visitThisPropertyGet(
261 Send node,
262 Name name,
263 _) {
264 markThisUsed();
265 }
266
267 void visitThisGet(Node node, _) {
268 markThisUsed();
269 }
270
271 void visitIs(Send node, Node expression, DartType type, _) {
272 // TODO(ajohnsen): Type is used ByValue.
273 expression.accept(this);
274 }
275
276 void visitIsNot(Send node, Node expression, DartType type, _) {
277 // TODO(ajohnsen): Type is used ByValue.
278 expression.accept(this);
279 }
280
281 void visitAs(Send node, Node expression, DartType type, _) {
282 // TODO(ajohnsen): Type is used ByValue.
283 expression.accept(this);
284 }
285
286 void visitAssert(Assert node) {
287 // TODO(ajohnsen): Only visit in checked mode.
288 node.condition.accept(this);
289 node.message?.accept(this);
290 }
291
292 void visitLocalVariableCompound(
293 Send node,
294 LocalVariableElement variable,
295 AssignmentOperator operator,
296 Node rhs,
297 _) {
298 markUsed(variable, CaptureMode.ByReference);
299 super.visitLocalVariableCompound(node, variable, operator, rhs, null);
300 }
301
302 void internalError(Spannable spannable, String message) {
303 throw new SpannableAssertionFailure(spannable, message);
304 }
305
306 void apply(Node node, [_]) {
307 node.accept(this);
308 }
309
310 void visitThisInvoke(
311 Send node,
312 NodeList arguments,
313 CallStructure callStructure,
314 _) {
315 markThisUsed();
316 super.visitThisInvoke(node, arguments, callStructure, null);
317 }
318
319 void visitSuperFieldGet(
320 Send node,
321 FieldElement field,
322 _) {
323 markThisUsed();
324 super.visitSuperFieldGet(node, field, null);
325 }
326
327 void visitSuperFieldSet(
328 SendSet node,
329 FieldElement field,
330 Node rhs,
331 _) {
332 markThisUsed();
333 super.visitSuperFieldSet(node, field, rhs, null);
334 }
335
336 void visitSuperFieldInvoke(
337 Send node,
338 FieldElement field,
339 NodeList arguments,
340 CallStructure callStructure,
341 _) {
342 markThisUsed();
343 super.visitSuperFieldInvoke(node, field, arguments, callStructure, null);
344 }
345
346 void visitSuperMethodGet(
347 Send node,
348 MethodElement method,
349 _) {
350 markThisUsed();
351 super.visitSuperMethodGet(node, method, null);
352 }
353
354 void visitSuperGetterGet(
355 Send node,
356 FunctionElement getter,
357 _) {
358 markThisUsed();
359 super.visitSuperGetterGet(node, getter, null);
360 }
361
362 void visitSuperSetterSet(
363 SendSet node,
364 FunctionElement setter,
365 Node rhs,
366 _) {
367 markThisUsed();
368 super.visitSuperSetterSet(node, setter, rhs, null);
369 }
370
371 void visitSuperGetterInvoke(
372 Send node,
373 FunctionElement getter,
374 NodeList arguments,
375 CallStructure callStructure,
376 _) {
377 markThisUsed();
378 super.visitSuperGetterInvoke(node, getter, arguments, callStructure, null);
379 }
380
381 void visitTypeVariableTypeLiteralGet(
382 Send node,
383 TypeVariableElement element,
384 _) {
385 // TODO(ajohnsen): Visit 'this' for type literal support, except for
386 // closures in initializers.
387 super.visitTypeVariableTypeLiteralGet(node, element, null);
388 }
389
390 void visitTypeVariableTypeLiteralInvoke(
391 Send node,
392 TypeVariableElement element,
393 NodeList arguments,
394 CallStructure callStructure,
395 _) {
396 // TODO(ajohnsen): Visit 'this' for type literal support, except for
397 // closures in initializers.
398 super.visitTypeVariableTypeLiteralInvoke(
399 node, element, arguments, callStructure, null);
400 }
401
402 void visitSuperBinary(
403 Send node,
404 FunctionElement function,
405 BinaryOperator operator,
406 Node argument,
407 _) {
408 markThisUsed();
409 super.visitSuperBinary(node, function, operator, argument, null);
410 }
411
412 void visitSuperIndex(
413 Send node,
414 FunctionElement function,
415 Node index,
416 _) {
417 markThisUsed();
418 super.visitSuperIndex(node, function, index, null);
419 }
420
421 void visitSuperIndexPostfix(
422 SendSet node,
423 FunctionElement getter,
424 FunctionElement setter,
425 Node index,
426 IncDecOperator operator,
427 _) {
428 markThisUsed();
429 super.visitSuperIndexPostfix(node, getter, setter, index, operator, null);
430 }
431
432 void visitSuperNotEquals(
433 Send node,
434 FunctionElement function,
435 Node argument,
436 _) {
437 markThisUsed();
438 super.visitSuperNotEquals(node, function, argument, null);
439 }
440
441 void visitSuperEquals(
442 Send node,
443 FunctionElement function,
444 Node argument,
445 _) {
446 markThisUsed();
447 super.visitSuperEquals(node, function, argument, null);
448 }
449
450 void visitSuperUnary(
451 Send node,
452 UnaryOperator operator,
453 FunctionElement function,
454 _) {
455 markThisUsed();
456 super.visitSuperUnary(node, operator, function, null);
457 }
458
459 void visitSuperIndexSet(
460 Send node,
461 FunctionElement function,
462 Node index,
463 Node rhs,
464 _) {
465 markThisUsed();
466 super.visitSuperIndexSet(node, function, index, rhs, null);
467 }
468
469 void visitThisPropertyCompound(
470 Send node,
471 Name name,
472 AssignmentOperator operator,
473 Node rhs,
474 _) {
475 markThisUsed();
476 super.visitThisPropertyCompound(
477 node, name, operator, rhs, null);
478 }
479
480 void visitParameterCompound(
481 Send node,
482 ParameterElement parameter,
483 AssignmentOperator operator,
484 Node rhs,
485 _) {
486 markUsed(parameter, CaptureMode.ByReference);
487 super.visitParameterCompound(node, parameter, operator, rhs, null);
488 }
489
490 void visitSuperFieldCompound(
491 Send node,
492 FieldElement field,
493 AssignmentOperator operator,
494 Node rhs,
495 _) {
496 markThisUsed();
497 super.visitSuperFieldCompound(node, field, operator, rhs, null);
498 }
499
500 void visitSuperGetterSetterCompound(
501 Send node,
502 FunctionElement getter,
503 FunctionElement setter,
504 AssignmentOperator operator,
505 Node rhs,
506 _) {
507 markThisUsed();
508 super.visitSuperGetterSetterCompound(
509 node, getter, setter, operator, rhs, null);
510 }
511
512 void visitSuperMethodSetterCompound(
513 Send node,
514 FunctionElement method,
515 FunctionElement setter,
516 AssignmentOperator operator,
517 Node rhs,
518 _) {
519 markThisUsed();
520 super.visitSuperMethodSetterCompound(
521 node, method, setter, operator, rhs, null);
522 }
523
524 void visitSuperFieldSetterCompound(
525 Send node,
526 FieldElement field,
527 FunctionElement setter,
528 AssignmentOperator operator,
529 Node rhs,
530 _) {
531 markThisUsed();
532 super.visitSuperFieldSetterCompound(
533 node, field, setter, operator, rhs, null);
534 }
535
536 void visitSuperGetterFieldCompound(
537 Send node,
538 FunctionElement getter,
539 FieldElement field,
540 AssignmentOperator operator,
541 Node rhs,
542 _) {
543 markThisUsed();
544 super.visitSuperGetterFieldCompound(
545 node, getter, field, operator, rhs, null);
546 }
547
548 void visitSuperCompoundIndexSet(
549 Send node,
550 FunctionElement getter,
551 FunctionElement setter,
552 Node index,
553 AssignmentOperator operator,
554 Node rhs,
555 _) {
556 markThisUsed();
557 super.visitSuperCompoundIndexSet(
558 node, getter, setter, index, operator, rhs, null);
559 }
560
561 void visitParameterPrefix(
562 Send node,
563 ParameterElement parameter,
564 IncDecOperator operator,
565 _) {
566 markUsed(parameter, CaptureMode.ByReference);
567 super.visitParameterPrefix(node, parameter, operator, null);
568 }
569
570 void visitThisPropertyPrefix(
571 Send node,
572 Name name,
573 IncDecOperator operator,
574 _) {
575 markThisUsed();
576 super.visitThisPropertyPrefix(
577 node, name, operator, null);
578 }
579
580 void visitSuperFieldPrefix(
581 Send node,
582 FieldElement field,
583 IncDecOperator operator,
584 _) {
585 markThisUsed();
586 super.visitSuperFieldPrefix(node, field, operator, null);
587 }
588
589 void visitSuperFieldFieldPrefix(
590 Send node,
591 FieldElement readField,
592 FieldElement writtenField,
593 IncDecOperator operator,
594 _) {
595 markThisUsed();
596 super.visitSuperFieldFieldPrefix(
597 node, readField, writtenField, operator, null);
598 }
599
600 void visitSuperFieldSetterPrefix(
601 Send node,
602 FieldElement field,
603 FunctionElement setter,
604 IncDecOperator operator,
605 _) {
606 markThisUsed();
607 super.visitSuperFieldSetterPrefix(node, field, setter, operator, null);
608 }
609
610 void visitSuperGetterSetterPrefix(
611 Send node,
612 FunctionElement getter,
613 FunctionElement setter,
614 IncDecOperator operator,
615 _) {
616 markThisUsed();
617 super.visitSuperGetterSetterPrefix(node, getter, setter, operator, null);
618 }
619
620 void visitSuperGetterFieldPrefix(
621 Send node,
622 FunctionElement getter,
623 FieldElement field,
624 IncDecOperator operator,
625 _) {
626 markThisUsed();
627 super.visitSuperGetterFieldPrefix(node, getter, field, operator, null);
628 }
629
630 void visitSuperMethodSetterPrefix(
631 Send node,
632 FunctionElement method,
633 FunctionElement setter,
634 IncDecOperator operator,
635 _) {
636 markThisUsed();
637 super.visitSuperMethodSetterPrefix(node, method, setter, operator, null);
638 }
639
640 void visitTypeVariableTypeLiteralPrefix(
641 Send node,
642 TypeVariableElement element,
643 IncDecOperator operator,
644 _) {
645 markThisUsed();
646 super.visitTypeVariableTypeLiteralPrefix(node, element, operator, null);
647 }
648
649 void visitParameterPostfix(
650 Send node,
651 ParameterElement parameter,
652 IncDecOperator operator,
653 _) {
654 markUsed(parameter, CaptureMode.ByReference);
655 super.visitParameterPostfix(node, parameter, operator, null);
656 }
657
658 void visitThisPropertyPostfix(
659 Send node,
660 Name name,
661 IncDecOperator operator,
662 _) {
663 markThisUsed();
664 super.visitThisPropertyPostfix(
665 node, name, operator, null);
666 }
667
668 void visitSuperFieldPostfix(
669 Send node,
670 FieldElement field,
671 IncDecOperator operator,
672 _) {
673 markThisUsed();
674 super.visitSuperFieldPostfix(node, field, operator, null);
675 }
676
677 void visitSuperFieldFieldPostfix(
678 Send node,
679 FieldElement readField,
680 FieldElement writtenField,
681 IncDecOperator operator,
682 _) {
683 markThisUsed();
684 super.visitSuperFieldFieldPostfix(
685 node, readField, writtenField, operator, null);
686 }
687
688 void visitSuperFieldSetterPostfix(
689 Send node,
690 FieldElement field,
691 FunctionElement setter,
692 IncDecOperator operator,
693 _) {
694 markThisUsed();
695 super.visitSuperFieldSetterPostfix(node, field, setter, operator, null);
696 }
697
698 void visitSuperGetterSetterPostfix(
699 Send node,
700 FunctionElement getter,
701 FunctionElement setter,
702 IncDecOperator operator,
703 _) {
704 markThisUsed();
705 super.visitSuperGetterSetterPostfix(node, getter, setter, operator, null);
706 }
707
708 void visitSuperGetterFieldPostfix(
709 Send node,
710 FunctionElement getter,
711 FieldElement field,
712 IncDecOperator operator,
713 _) {
714 markThisUsed();
715 super.visitSuperGetterFieldPostfix(node, getter, field, operator, null);
716 }
717
718 void visitSuperMethodSetterPostfix(
719 Send node,
720 FunctionElement method,
721 FunctionElement setter,
722 IncDecOperator operator,
723 _) {
724 markThisUsed();
725 super.visitSuperMethodSetterPostfix(node, method, setter, operator, null);
726 }
727
728 void visitTypeVariableTypeLiteralPostfix(
729 Send node,
730 TypeVariableElement element,
731 IncDecOperator operator,
732 _) {
733 markThisUsed();
734 super.visitTypeVariableTypeLiteralPostfix(node, element, operator, null);
735 }
736
737 void visitSuperIndexPrefix(
738 Send node,
739 FunctionElement indexFunction,
740 FunctionElement indexSetFunction,
741 Node index,
742 IncDecOperator operator,
743 _) {
744 markThisUsed();
745 super.visitSuperIndexPrefix(
746 node, indexFunction, indexSetFunction, index, operator, null);
747 }
748
749 @override
750 void visitTypeAnnotation(TypeAnnotation node) {
751 // This is to avoid the inherited implementation that visits children and
752 // throws when encountering anything unresolved.
753 }
754
755 void handleImmutableLocalSet(
756 SendSet node,
757 LocalElement element,
758 Node rhs,
759 _) {
760 apply(rhs);
761 }
762
763 void bulkHandleNode(Node node, String message, _) {
764 }
765
766 void applyInitializers(FunctionExpression initializers, _) {
767 }
768
769 void applyParameters(NodeList parameters, _) {
770 }
771 }
OLDNEW
« no previous file with comments | « pkg/fletchc/lib/src/class_debug_info.dart ('k') | pkg/fletchc/lib/src/codegen_visitor.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698