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

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

Issue 1415923012: Simple sharing and hoisting of final field loads (Closed) Base URL: https://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 // Copyright (c) 2015, the Dart 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 file.
4
5 library dart2js.cps_ir.share_final_fields;
6
7 import 'optimizers.dart';
8 import 'cps_ir_nodes.dart';
9 import 'loop_hierarchy.dart';
10 import 'cps_fragment.dart';
11 import '../constants/values.dart';
12 import '../elements/elements.dart';
13 import '../js_backend/backend_helpers.dart' show BackendHelpers;
14 import '../js_backend/js_backend.dart' show JavaScriptBackend;
15 import '../types/types.dart' show TypeMask;
16 import '../io/source_information.dart' show SourceInformation;
17
18 /// Removes redundant GetField operations.
19 ///
20 /// The pass performs these optimizations for field loads.
21 ///- share GetFields of final fields when one is in scope of the other.
22 ///- pull GetField operations out of loops.
23 class ShareFinalFields extends TrampolineRecursiveVisitor implements Pass {
24 String get passName => 'Share final fields';
25
26 /// The innermost loop containing a given primitive.
27 final Map<Primitive, Continuation> loopHeaderFor =
28 <Primitive, Continuation>{};
29
30 /// An interceptor currently in scope for a given primitive.
31 final Map<Primitive, Interceptor> interceptorFor = <Primitive, Interceptor>{};
asgerf 2015/10/30 09:57:46 Unused field
32
33 // field -> receiver -> GetField
34 Map<FieldElement, Map<Primitive, Primitive>> fieldValues =
35 <FieldElement, Map<Primitive, Primitive>>{};
36
37 /// Interceptors that have been hoisted out of a given loop.
38 final Map<Continuation, List<GetField>> loopHoistedGetters =
39 <Continuation, List<GetField>>{};
40
41 JavaScriptBackend backend;
42 LoopHierarchy loopHierarchy;
43 Continuation currentLoopHeader;
44
45 ShareFinalFields(this.backend);
46
47 BackendHelpers get helpers => backend.helpers;
48
49 void rewrite(FunctionDefinition node) {
50 loopHierarchy = new LoopHierarchy(node);
51 visit(node.body);
52 }
53
54 @override
55 Expression traverseContinuation(Continuation cont) {
56 Continuation oldLoopHeader = currentLoopHeader;
57 currentLoopHeader = loopHierarchy.getLoopHeader(cont);
58 for (Parameter parameter in cont.parameters) {
59 loopHeaderFor[parameter] = currentLoopHeader;
60 }
61 if (cont.isRecursive) {
62 pushAction(() {
63 // After the loop body has been processed, all values hoisted to this
64 // loop fall out of scope and should be removed from the environment.
65 List<GetField> hoisted = loopHoistedGetters[cont];
66 if (hoisted != null) {
67 for (GetField primitive in hoisted) {
68 Primitive refinedReceiver = primitive.object.definition;
69 Primitive receiver = refinedReceiver.effectiveDefinition;
70 var map = fieldValues[primitive.field];
71 assert(map[receiver] == primitive);
72 map.remove(receiver);
73 }
74 }
75 });
76 }
77 pushAction(() {
78 currentLoopHeader = oldLoopHeader;
79 });
80 return cont.body;
81 }
82
83 Continuation getCurrentOuterLoop({Continuation scope}) {
84 Continuation inner = null, outer = currentLoopHeader;
85 while (outer != scope) {
86 inner = outer;
87 outer = loopHierarchy.getEnclosingLoop(outer);
88 }
89 return inner;
90 }
91
92 @override
93 Expression traverseLetPrim(LetPrim node) {
94 loopHeaderFor[node.primitive] = currentLoopHeader;
95 Expression next = node.body;
96 if (node.primitive is! GetField) {
97 return next;
98 }
99 GetField primitive = node.primitive;
100 FieldElement field = primitive.field;
101
102 if (!shouldShareField(field)) {
103 return next;
104 }
105
106 Primitive refinedReceiver = primitive.object.definition;
107 Primitive receiver = refinedReceiver.effectiveDefinition;
108
109 // Try to reuse an existing load for the same input.
110 var map = fieldValues.putIfAbsent(field, () => <Primitive,Primitive>{});
111 Primitive existing = map[receiver];
112 if (existing != null) {
113 existing.substituteFor(primitive);
114 primitive.destroy();
115 node.remove();
116 return next;
117 }
118
119 map[receiver] = primitive;
120
121 if (primitive.objectIsNotNull) {
122 // Determine how far the GetField can be lifted. The outermost loop that
123 // contains the input binding should also contain the load.
124 // Don't move above a refinement guard since that might be unsafe.
125 // TODO(sra): We can move above a refinement guard provided the input is
126 // still safe (non-null).
127 Continuation referencedLoop =
128 lowestCommonAncestor(loopHeaderFor[refinedReceiver],
129 currentLoopHeader);
130 if (referencedLoop != currentLoopHeader) {
131 Continuation hoistTarget = getCurrentOuterLoop(scope: referencedLoop);
132 LetCont loopBinding = hoistTarget.parent;
133 node.remove();
134 node.insertAbove(loopBinding);
135 // Remove the hoisted operations from the environment after processing
136 // the loop.
137 loopHoistedGetters
138 .putIfAbsent(hoistTarget, () => <GetField>[])
139 .add(primitive);
140 return next;
141 }
142 }
143
144 pushAction(() {
145 var map = fieldValues[field];
146 assert(map[receiver] == primitive);
147 map.remove(receiver);
148 });
149 return next;
150 }
151
152 bool shouldShareField(FieldElement field) {
153 return backend.compiler.world.fieldNeverChanges(field);
154 }
155
156
157 /// Returns the the innermost loop that effectively encloses both
158 /// c1 and c2 (or `null` if there is no such loop).
159 Continuation lowestCommonAncestor(Continuation c1, Continuation c2) {
160 int d1 = getDepth(c1), d2 = getDepth(c2);
161 while (c1 != c2) {
162 if (d1 <= d2) {
163 c2 = loopHierarchy.getEnclosingLoop(c2);
164 d2 = getDepth(c2);
165 } else {
166 c1 = loopHierarchy.getEnclosingLoop(c1);
167 d1 = getDepth(c1);
168 }
169 }
170 return c1;
171 }
172
173 int getDepth(Continuation loop) {
174 if (loop == null) return -1;
175 return loopHierarchy.loopDepth[loop];
176 }
177 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/optimizers.dart ('k') | pkg/compiler/lib/src/js_backend/codegen/task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698