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

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

Issue 2246623002: Delete CPS IR (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 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
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 library dart2js.cps_ir.scalar_replacement;
5
6 import 'dart:collection' show Queue;
7
8 import '../common.dart';
9 import '../compiler.dart' as dart2js show Compiler;
10 import '../constants/values.dart';
11 import '../elements/elements.dart';
12 import '../types/types.dart';
13 import '../world.dart' show World;
14 import 'cps_ir_nodes.dart';
15 import 'optimizers.dart';
16
17 /**
18 * Replaces aggregates with a set of local values. Performs inlining of
19 * single-use closures to generate more replaceable aggregates.
20 */
21 class ScalarReplacer extends Pass {
22 String get passName => 'Scalar replacement';
23
24 final InternalErrorFunction _internalError;
25 final World _classWorld;
26
27 ScalarReplacer(dart2js.Compiler compiler)
28 : _internalError = compiler.reporter.internalError,
29 _classWorld = compiler.world;
30
31 @override
32 void rewrite(FunctionDefinition root) {
33 ScalarReplacementVisitor analyzer =
34 new ScalarReplacementVisitor(_internalError, _classWorld);
35 analyzer.analyze(root);
36 analyzer.process();
37 }
38 }
39
40 /**
41 * Do scalar replacement of aggregates on instances. Since scalar replacement
42 * can create new candidates, iterate until all scalar replacements are done.
43 */
44 class ScalarReplacementVisitor extends TrampolineRecursiveVisitor {
45 final InternalErrorFunction internalError;
46 final World classWorld;
47 ScalarReplacementRemovalVisitor removalVisitor;
48
49 Primitive _current = null;
50 Set<Primitive> _allocations = new Set<Primitive>();
51 Queue<Primitive> _queue = new Queue<Primitive>();
52
53 ScalarReplacementVisitor(this.internalError, this.classWorld) {
54 removalVisitor = new ScalarReplacementRemovalVisitor(this);
55 }
56
57 void analyze(FunctionDefinition root) {
58 visit(root);
59 }
60
61 void process() {
62 while (_queue.isNotEmpty) {
63 Primitive allocation = _queue.removeFirst();
64 _allocations.remove(allocation);
65 _current = allocation;
66 tryScalarReplacement(allocation);
67 }
68 }
69
70 void tryScalarReplacement(Primitive allocation) {
71 // We can do scalar replacement of an aggregate if all uses of an allocation
72 // are reads or writes.
73 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) {
74 Node use = ref.parent;
75 if (use is GetField) continue;
76 if (use is SetField && use.objectRef == ref) continue;
77 return;
78 }
79
80 Set<FieldElement> reads = new Set<FieldElement>();
81 Set<FieldElement> writes = new Set<FieldElement>();
82 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) {
83 Node use = ref.parent;
84 if (use is GetField) {
85 reads.add(use.field);
86 } else if (use is SetField) {
87 writes.add(use.field);
88 } else {
89 assert(false);
90 }
91 }
92
93 // Find the initial values of the fields. A CreateBox has no initial
94 // values. CreateInstance has initial values in the order of the fields.
95 Map<FieldElement, Primitive> fieldInitialValues =
96 <FieldElement, Primitive>{};
97 if (allocation is CreateInstance) {
98 int i = 0;
99 allocation.classElement.forEachInstanceField(
100 (ClassElement enclosingClass, FieldElement field) {
101 Primitive argument = allocation.argument(i++);
102 fieldInitialValues[field] = argument;
103 }, includeSuperAndInjectedMembers: true);
104 }
105
106 // Create [MutableVariable]s for each written field. Initialize the
107 // MutableVariable with the value from the allocator, or initialize with a
108 // `null` constant if there is not initial value.
109 Map<FieldElement, MutableVariable> cells =
110 <FieldElement, MutableVariable>{};
111 InteriorNode insertionPoint = allocation.parent; // LetPrim
112 for (FieldElement field in writes) {
113 MutableVariable variable = new MutableVariable(field);
114 variable.type = new TypeMask.nonNullEmpty();
115 cells[field] = variable;
116 Primitive initialValue = fieldInitialValues[field];
117 if (initialValue == null) {
118 assert(allocation is CreateBox);
119 initialValue = new Constant(new NullConstantValue());
120 LetPrim let = new LetPrim(initialValue);
121 let.primitive.parent = let;
122 insertionPoint = let..insertBelow(insertionPoint);
123 }
124 LetMutable let = new LetMutable(variable, initialValue);
125 let.valueRef.parent = let;
126 insertionPoint = let..insertBelow(insertionPoint);
127 }
128
129 // Replace references with MutableVariable operations or references to the
130 // field's value.
131 for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) {
132 Node use = ref.parent;
133 if (use is GetField) {
134 GetField getField = use;
135 MutableVariable variable = cells[getField.field];
136 if (variable != null) {
137 GetMutable getter = new GetMutable(variable);
138 getter.type = getField.type;
139 getter.variableRef.parent = getter;
140 getField.replaceUsesWith(getter);
141 replacePrimitive(getField, getter);
142 deletePrimitive(getField);
143 } else {
144 Primitive value = fieldInitialValues[getField.field];
145 getField.replaceUsesWith(value);
146 deleteLetPrimOf(getField);
147 }
148 } else if (use is SetField && use.objectRef == ref) {
149 SetField setField = use;
150 MutableVariable variable = cells[setField.field];
151 Primitive value = setField.value;
152 variable.type = variable.type.union(value.type, classWorld);
153 SetMutable setter = new SetMutable(variable, value);
154 setter.variableRef.parent = setter;
155 setter.valueRef.parent = setter;
156 setField.replaceUsesWith(setter);
157 replacePrimitive(setField, setter);
158 deletePrimitive(setField);
159 } else {
160 assert(false);
161 }
162 }
163
164 // Delete [allocation] since that might 'free' another scalar replacement
165 // candidate by deleting the last non-field-access.
166 deleteLetPrimOf(allocation);
167 }
168
169 /// Replaces [old] with [primitive] in [old]'s parent [LetPrim].
170 void replacePrimitive(Primitive old, Primitive primitive) {
171 LetPrim letPrim = old.parent;
172 letPrim.primitive = primitive;
173 primitive.parent = letPrim;
174 }
175
176 void deleteLetPrimOf(Primitive primitive) {
177 assert(primitive.hasNoUses);
178 LetPrim letPrim = primitive.parent;
179 letPrim.remove();
180 deletePrimitive(primitive);
181 }
182
183 void deletePrimitive(Primitive primitive) {
184 assert(primitive.hasNoUses);
185 removalVisitor.visit(primitive);
186 }
187
188 void reconsider(Definition node) {
189 if (node is CreateInstance || node is CreateBox) {
190 if (node == _current) return;
191 enqueue(node);
192 }
193 }
194
195 void enqueue(Primitive node) {
196 assert(node is CreateInstance || node is CreateBox);
197 if (_allocations.contains(node)) return;
198 _allocations.add(node);
199 _queue.add(node);
200 }
201
202 // -------------------------- Visitor overrides ------------------------------
203 void visitCreateInstance(CreateInstance node) {
204 enqueue(node);
205 }
206
207 void visitCreateBox(CreateBox node) {
208 enqueue(node);
209 }
210 }
211
212 /// Visit a just-deleted subterm and unlink all [Reference]s in it. Reconsider
213 /// allocations for scalar replacement.
214 class ScalarReplacementRemovalVisitor extends TrampolineRecursiveVisitor {
215 ScalarReplacementVisitor process;
216
217 ScalarReplacementRemovalVisitor(this.process);
218
219 processReference(Reference reference) {
220 process.reconsider(reference.definition);
221 reference.unlink();
222 }
223 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/redundant_refinement.dart ('k') | pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698