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

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 10540040: Inline setters, getters, various cleanups & restructuring. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 6 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 | Annotate | Revision Log
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 #include "vm/flow_graph_optimizer.h" 5 #include "vm/flow_graph_optimizer.h"
6 6
7 #include "vm/flow_graph_builder.h" 7 #include "vm/flow_graph_builder.h"
8 #include "vm/il_printer.h" 8 #include "vm/il_printer.h"
9 #include "vm/object_store.h" 9 #include "vm/object_store.h"
10 10
11 namespace dart { 11 namespace dart {
12 12
13 DECLARE_FLAG(bool, enable_type_checks);
13 DECLARE_FLAG(bool, print_flow_graph); 14 DECLARE_FLAG(bool, print_flow_graph);
14 DECLARE_FLAG(bool, trace_optimization); 15 DECLARE_FLAG(bool, trace_optimization);
15 16
16 void FlowGraphOptimizer::ApplyICData() { 17 void FlowGraphOptimizer::ApplyICData() {
17 VisitBlocks(); 18 VisitBlocks();
18 if (FLAG_print_flow_graph) { 19 if (FLAG_print_flow_graph) {
19 OS::Print("After Optimizations:\n"); 20 OS::Print("After Optimizations:\n");
20 FlowGraphPrinter printer(Function::Handle(), block_order_); 21 FlowGraphPrinter printer(Function::Handle(), block_order_);
21 printer.PrintBlocks(); 22 printer.PrintBlocks();
22 } 23 }
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 } 131 }
131 if (unary_op != NULL) { 132 if (unary_op != NULL) {
132 ASSERT(unary_op->ic_data() == NULL); 133 ASSERT(unary_op->ic_data() == NULL);
133 unary_op->set_ic_data(comp->ic_data()); 134 unary_op->set_ic_data(comp->ic_data());
134 unary_op->set_instr(comp->instr()); 135 unary_op->set_instr(comp->instr());
135 comp->instr()->replace_computation(unary_op); 136 comp->instr()->replace_computation(unary_op);
136 } 137 }
137 } 138 }
138 139
139 140
141 // Returns true if all targets are the same.
142 static bool HasOneTarget(const ICData& ic_data) {
143 ASSERT(ic_data.NumberOfChecks() > 0);
144 Function& prev_target = Function::Handle();
145 Class& cls = Class::Handle();
146 ic_data.GetOneClassCheckAt(0, &cls, &prev_target);
147 ASSERT(!prev_target.IsNull());
148 Function& target = Function::Handle();
149 for (intptr_t i = 1; i < ic_data.NumberOfChecks(); i++) {
150 ic_data.GetOneClassCheckAt(i, &cls, &target);
151 ASSERT(!target.IsNull());
152 if (prev_target.raw() != target.raw()) {
153 return false;
154 }
155 prev_target = target.raw();
156 }
157 return true;
158 }
159
160
161 // Using field class
162 static RawField* GetField(const Class& field_class, const String& field_name) {
163 Class& cls = Class::Handle(field_class.raw());
164 Field& field = Field::Handle();
165 while (!cls.IsNull()) {
166 field = cls.LookupInstanceField(field_name);
167 if (!field.IsNull()) {
168 return field.raw();
169 }
170 cls = cls.SuperClass();
171 }
172 return Field::null();
173 }
174
175
176 // Returns array of all class ids that are in ic_data. The result is
177 // normalized so that a smi class is at index 0 if it exists in the ic_data.
178 static ZoneGrowableArray<intptr_t>* ExtractClassIds(const ICData& ic_data) {
179 if (ic_data.NumberOfChecks() == 0) return NULL;
180 ZoneGrowableArray<intptr_t>* result =
181 new ZoneGrowableArray<intptr_t>(ic_data.NumberOfChecks());
182 intptr_t smi_index = -1;
183 Function& target = Function::Handle();
184 Class& cls = Class::Handle();
185 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) {
186 ic_data.GetOneClassCheckAt(i, &cls, &target);
187 result->Add(cls.id());
188 if (cls.id() == kSmi) {
189 ASSERT(smi_index < 0); // Classes entered only once in ic_data.
190 smi_index = i;
191 }
192 }
193 if (smi_index >= 0) {
194 // Smi class id must be at index 0.
195 intptr_t temp = (*result)[0];
196 (*result)[0] = (*result)[smi_index];
197 (*result)[smi_index] = temp;
198 }
199 return result;
200 }
201
202
203 // Only unique implicit instance getters can be currently handled.
204 void FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) {
205 ASSERT(comp->HasICData());
206 const ICData& ic_data = *comp->ic_data();
207 if (ic_data.NumberOfChecks() == 0) {
208 // No type feedback collected
209 return;
210 }
211 if (!HasOneTarget(ic_data)) {
212 // TODO(srdjan): Implement when not all targets are the sa,e.
213 return;
214 }
215 Function& target = Function::Handle();
216 Class& cls = Class::Handle();
217 ic_data.GetOneClassCheckAt(0, &cls, &target);
218 if (target.kind() != RawFunction::kImplicitGetter) {
219 // Not an implicit getter.
220 // TODO(srdjan): Inline special getters (e.g., array length).
221 return;
222 }
223 // Inline implicit instance getter.
224 const String& field_name =
225 String::Handle(Field::NameFromGetter(comp->function_name()));
226 const Field& field = Field::Handle(GetField(cls, field_name));
227 ASSERT(!field.IsNull());
228 LoadInstanceFieldComp* load = new LoadInstanceFieldComp(
229 field, comp->InputAt(0), comp, ExtractClassIds(ic_data));
230 // Replace 'comp' with 'load'.
231 load->set_instr(comp->instr());
232 comp->instr()->replace_computation(load);
233 }
234
235
236 void FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) {
237 ASSERT(comp->HasICData());
238 const ICData& ic_data = *comp->ic_data();
239 OS::Print("TryInlineInstanceSetter %d\n", ic_data.NumberOfChecks());
240 if (ic_data.NumberOfChecks() == 0) {
241 // No type feedback collected
242 return;
243 }
244 if (!HasOneTarget(ic_data)) {
245 // TODO(srdjan): Implement when not all targets are the sa,e.
246 return;
247 }
248 Function& target = Function::Handle();
249 Class& cls = Class::Handle();
250 ic_data.GetOneClassCheckAt(0, &cls, &target);
251 if (target.kind() != RawFunction::kImplicitSetter) {
252 // Not an implicit setter.
253 // TODO(srdjan): Inline special getters (e.g., array length).
Florian Schneider 2012/06/07 08:47:59 s/getter/setter/
srdjan 2012/06/07 18:24:50 Done.
254 return;
255 }
256 // Inline implicit instance setter.
257 const Field& field = Field::Handle(GetField(cls, comp->field_name()));
258 ASSERT(!field.IsNull());
259 StoreInstanceFieldComp* store = new StoreInstanceFieldComp(
260 field,
261 comp->InputAt(0),
262 comp->InputAt(1),
263 comp,
264 ExtractClassIds(ic_data));
265 // Replace 'comp' with 'load'.
Florian Schneider 2012/06/07 08:47:59 s/load/store/
srdjan 2012/06/07 18:24:50 Done.
266 store->set_instr(comp->instr());
267 comp->instr()->replace_computation(store);
268 }
269
270
140 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) { 271 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) {
141 if ((comp->ic_data() != NULL) && (!comp->ic_data()->IsNull())) { 272 if (comp->HasICData()) {
142 Token::Kind op_kind = Token::GetBinaryOp(comp->function_name()); 273 const String& function_name = comp->function_name();
274 Token::Kind op_kind = Token::GetBinaryOp(function_name);
143 if (op_kind != Token::kILLEGAL) { 275 if (op_kind != Token::kILLEGAL) {
144 TryReplaceWithBinaryOp(comp, op_kind); 276 TryReplaceWithBinaryOp(comp, op_kind);
145 return; 277 return;
146 } 278 }
147 op_kind = Token::GetUnaryOp(comp->function_name()); 279 op_kind = Token::GetUnaryOp(function_name);
148 if (op_kind != Token::kILLEGAL) { 280 if (op_kind != Token::kILLEGAL) {
149 TryReplaceWithUnaryOp(comp, op_kind); 281 TryReplaceWithUnaryOp(comp, op_kind);
150 return; 282 return;
151 } 283 }
284 if (Field::IsGetterName(function_name)) {
285 TryInlineInstanceGetter(comp);
286 return;
287 }
288 }
289 }
290
291
292 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) {
293 // TODO(srdjan): Add assigneable check node if --enable_type_checks.
294 if (comp->HasICData() && !FLAG_enable_type_checks) {
295 TryInlineInstanceSetter(comp);
152 } 296 }
153 } 297 }
154 298
155 299
156 void FlowGraphOptimizer::VisitDo(DoInstr* instr) { 300 void FlowGraphOptimizer::VisitDo(DoInstr* instr) {
157 instr->computation()->Accept(this); 301 instr->computation()->Accept(this);
158 } 302 }
159 303
160 304
161 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { 305 void FlowGraphOptimizer::VisitBind(BindInstr* instr) {
162 instr->computation()->Accept(this); 306 instr->computation()->Accept(this);
163 } 307 }
164 308
165 309
166 } // namespace dart 310 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698