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

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
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 if (ic_data.NumberOfChecks() == 0) {
240 // No type feedback collected
241 return;
242 }
243 if (!HasOneTarget(ic_data)) {
244 // TODO(srdjan): Implement when not all targets are the sa,e.
245 return;
246 }
247 Function& target = Function::Handle();
248 Class& cls = Class::Handle();
249 ic_data.GetOneClassCheckAt(0, &cls, &target);
250 if (target.kind() != RawFunction::kImplicitSetter) {
251 // Not an implicit setter.
252 // TODO(srdjan): Inline special setters.
253 return;
254 }
255 // Inline implicit instance setter.
256 const Field& field = Field::Handle(GetField(cls, comp->field_name()));
257 ASSERT(!field.IsNull());
258 StoreInstanceFieldComp* store = new StoreInstanceFieldComp(
259 field,
260 comp->InputAt(0),
261 comp->InputAt(1),
262 comp,
263 ExtractClassIds(ic_data));
264 // Replace 'comp' with 'store'.
265 store->set_instr(comp->instr());
266 comp->instr()->replace_computation(store);
267 }
268
269
140 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) { 270 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) {
141 if ((comp->ic_data() != NULL) && (!comp->ic_data()->IsNull())) { 271 if (comp->HasICData()) {
142 Token::Kind op_kind = Token::GetBinaryOp(comp->function_name()); 272 const String& function_name = comp->function_name();
273 Token::Kind op_kind = Token::GetBinaryOp(function_name);
143 if (op_kind != Token::kILLEGAL) { 274 if (op_kind != Token::kILLEGAL) {
144 TryReplaceWithBinaryOp(comp, op_kind); 275 TryReplaceWithBinaryOp(comp, op_kind);
145 return; 276 return;
146 } 277 }
147 op_kind = Token::GetUnaryOp(comp->function_name()); 278 op_kind = Token::GetUnaryOp(function_name);
148 if (op_kind != Token::kILLEGAL) { 279 if (op_kind != Token::kILLEGAL) {
149 TryReplaceWithUnaryOp(comp, op_kind); 280 TryReplaceWithUnaryOp(comp, op_kind);
150 return; 281 return;
151 } 282 }
283 if (Field::IsGetterName(function_name)) {
284 TryInlineInstanceGetter(comp);
285 return;
286 }
287 }
288 }
289
290
291 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) {
292 // TODO(srdjan): Add assigneable check node if --enable_type_checks.
293 if (comp->HasICData() && !FLAG_enable_type_checks) {
294 TryInlineInstanceSetter(comp);
152 } 295 }
153 } 296 }
154 297
155 298
156 void FlowGraphOptimizer::VisitDo(DoInstr* instr) { 299 void FlowGraphOptimizer::VisitDo(DoInstr* instr) {
157 instr->computation()->Accept(this); 300 instr->computation()->Accept(this);
158 } 301 }
159 302
160 303
161 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { 304 void FlowGraphOptimizer::VisitBind(BindInstr* instr) {
162 instr->computation()->Accept(this); 305 instr->computation()->Accept(this);
163 } 306 }
164 307
165 308
166 } // namespace dart 309 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698