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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/loop_effects.dart

Issue 1426633005: dart2js cps: Better side-effect tracking in loops. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month 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
(Empty)
1 library dart2js.cps_ir.loop_effects;
2
3 import 'cps_ir_nodes.dart';
4 import 'loop_hierarchy.dart';
5 import 'type_mask_system.dart';
6 import '../universe/side_effects.dart';
7 import '../elements/elements.dart';
8 import '../world.dart';
9
10 /// Determines which the [SideEffects] that may occur during each loop in
11 /// a given function, in addition to whether the loop may change the length
12 /// of an indexable object.
13 ///
14 /// TODO(asgerf): Make length a flag on [SideEffects] for better precision and
15 /// so we don't need to special case the length in this class.
16 class LoopSideEffects extends TrampolineRecursiveVisitor {
17 LoopHierarchy loopHierarchy;
18 final World world;
19 final Map<Continuation, List<Continuation>> exitContinuations = {};
20 final Map<Continuation, SideEffects> loopSideEffects = {};
21 final Set<Continuation> loopsChangingLength = new Set<Continuation>();
22 Continuation currentLoopHeader;
23 SideEffects currentLoopSideEffects = new SideEffects.empty();
24 bool currentLoopChangesLength = false;
25
26 LoopSideEffects(FunctionDefinition node, this.world, {this.loopHierarchy}) {
27 if (loopHierarchy == null) {
28 loopHierarchy = new LoopHierarchy(node);
29 }
30 visit(node);
31 }
32
33 /// Returns the accumulated effects and dependencies on all paths from the
34 /// loop entry to any recursive invocation of the loop.
35 SideEffects getSideEffectsInLoop(Continuation loop) {
36 return loopSideEffects[loop];
37 }
38
39 /// True if the length of an indexable object may change between the loop
40 /// entry and a recursive invocation of the loop.
41 bool loopChangesLength(Continuation loop) {
42 return loopsChangingLength.contains(loop);
43 }
44
45 @override
46 Expression traverseContinuation(Continuation cont) {
47 if (cont.isRecursive) {
48 SideEffects oldEffects = currentLoopSideEffects;
49 Continuation oldLoopHeader = currentLoopHeader;
50 bool oldChangesLength = currentLoopChangesLength;
51 currentLoopHeader = cont;
52 loopSideEffects[cont] = currentLoopSideEffects = new SideEffects.empty();
53 exitContinuations[cont] = <Continuation>[];
54 pushAction(() {
55 oldEffects.add(currentLoopSideEffects);
56 if (currentLoopChangesLength) {
57 loopsChangingLength.add(cont);
58 }
59 currentLoopChangesLength = currentLoopChangesLength || oldChangesLength;
60 currentLoopHeader = oldLoopHeader;
61 currentLoopSideEffects = oldEffects;
62 exitContinuations[cont].forEach(push);
63 });
64 }
65 return cont.body;
66 }
67
68 @override
69 Expression traverseLetHandler(LetHandler node) {
70 enqueueContinuation(node.handler);
71 return node.body;
72 }
73
74 @override
75 Expression traverseLetCont(LetCont node) {
76 node.continuations.forEach(enqueueContinuation);
77 return node.body;
78 }
79
80 void enqueueContinuation(Continuation cont) {
81 Continuation loop = loopHierarchy.getEnclosingLoop(cont);
82 if (loop == currentLoopHeader) {
83 push(cont);
84 } else {
85 // Multiple loops can be exited at once.
86 // Register as an exit from the outermost loop being exited.
87 Continuation inner = currentLoopHeader;
88 Continuation outer = loopHierarchy.getEnclosingLoop(currentLoopHeader);
89 while (outer != loop) {
90 inner = outer;
91 outer = loopHierarchy.getEnclosingLoop(outer);
92 }
93 exitContinuations[inner].add(cont);
94 }
95 }
96
97 void addSideEffects(SideEffects effects) {
98 currentLoopSideEffects.add(effects);
99 if (effects.changesIndex()) {
100 currentLoopChangesLength = true;
101 }
102 }
103
104 void addAllSideEffects() {
105 currentLoopSideEffects.setAllSideEffects();
106 currentLoopSideEffects.setDependsOnSomething();
107 currentLoopChangesLength = true;
108 }
109
110 void visitInvokeMethod(InvokeMethod node) {
111 addSideEffects(world.getSideEffectsOfSelector(node.selector, node.mask));
112 }
113
114 void visitInvokeStatic(InvokeStatic node) {
115 addSideEffects(world.getSideEffectsOfElement(node.target));
116 }
117
118 void visitInvokeMethodDirectly(InvokeMethodDirectly node) {
119 FunctionElement target = node.target;
120 if (target is ConstructorBodyElement) {
121 ConstructorBodyElement body = target;
122 target = body.constructor;
123 }
124 addSideEffects(world.getSideEffectsOfElement(target));
125 }
126
127 void visitInvokeConstructor(InvokeConstructor node) {
128 addSideEffects(world.getSideEffectsOfElement(node.target));
129 }
130
131 void visitSetStatic(SetStatic node) {
132 currentLoopSideEffects.setChangesStaticProperty();
133 }
134
135 void visitGetStatic(GetStatic node) {
136 currentLoopSideEffects.setDependsOnStaticPropertyStore();
137 }
138
139 void visitGetField(GetField node) {
140 currentLoopSideEffects.setDependsOnInstancePropertyStore();
141 }
142
143 void visitSetField(SetField node) {
144 currentLoopSideEffects.setChangesInstanceProperty();
145 }
146
147 void visitGetIndex(GetIndex node) {
148 currentLoopSideEffects.setDependsOnIndexStore();
149 }
150
151 void visitSetIndex(SetIndex node) {
152 // Set the change index flag without setting the change length flag.
153 currentLoopSideEffects.setChangesIndex();
154 }
155
156 void visitForeignCode(ForeignCode node) {
157 addSideEffects(node.nativeBehavior.sideEffects);
158 }
159
160 void visitGetLazyStatic(GetLazyStatic node) {
161 // TODO(asgerf): How do we get the side effects of a lazy field initializer?
162 addAllSideEffects();
163 }
164
165 void visitAwait(Await node) {
166 addAllSideEffects();
167 }
168
169 void visitYield(Yield node) {
170 addAllSideEffects();
171 }
172
173 void visitApplyBuiltinMethod(ApplyBuiltinMethod node) {
174 currentLoopChangesLength = true; // Push and pop.
175 }
176 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698