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

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

Issue 10536096: Add code comment to ia32 disassembly as well, bug fix new ia32 compiler, remove use of TMP register… (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/intermediate_language.h » ('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, enable_type_checks);
14 DECLARE_FLAG(bool, print_flow_graph); 14 DECLARE_FLAG(bool, print_flow_graph);
15 DECLARE_FLAG(bool, trace_optimization); 15 DECLARE_FLAG(bool, trace_optimization);
16 16
17 // TODO(srdjan): Add _ByteArrayBase, get:length.
18
19 #define RECOGNIZED_LIST(V) \
20 V(ObjectArray, get:length, ObjectArrayLength) \
21 V(ImmutableArray, get:length, ImmutableArrayLength) \
22 V(GrowableObjectArray, get:length, GrowableArrayLength) \
23 V(StringBase, get:length, StringBaseLength) \
24 V(IntegerImplementation, toDouble, IntegerToDouble) \
25 V(Double, toDouble, DoubleToDouble) \
26 V(Math, sqrt, MathSqrt) \
27
28 // Class that recognizes the name and owner of a function and returns the
29 // corresponding enum. See RECOGNIZED_LIST above for list of recognizable
30 // functions.
31 class MethodRecognizer : public AllStatic {
32 public:
33 enum Kind {
34 kUnknown,
35 #define DEFINE_ENUM_LIST(class_name, function_name, enum_name) k##enum_name,
36 RECOGNIZED_LIST(DEFINE_ENUM_LIST)
37 #undef DEFINE_ENUM_LIST
38 };
39
40 static Kind RecognizeKind(const Function& function) {
41 // Only core library methods can be recognized.
42 const Library& core_lib = Library::Handle(Library::CoreLibrary());
43 const Library& core_impl_lib = Library::Handle(Library::CoreImplLibrary());
44 const Class& function_class = Class::Handle(function.owner());
45 if ((function_class.library() != core_lib.raw()) &&
46 (function_class.library() != core_impl_lib.raw())) {
47 return kUnknown;
48 }
49 const String& recognize_name = String::Handle(function.name());
50 const String& recognize_class = String::Handle(function_class.Name());
51 String& test_function_name = String::Handle();
52 String& test_class_name = String::Handle();
53 #define RECOGNIZE_FUNCTION(class_name, function_name, enum_name) \
54 test_function_name = String::NewSymbol(#function_name); \
55 test_class_name = String::NewSymbol(#class_name); \
56 if (recognize_name.Equals(test_function_name) && \
57 recognize_class.Equals(test_class_name)) { \
58 return k##enum_name; \
59 }
60 RECOGNIZED_LIST(RECOGNIZE_FUNCTION)
61 #undef RECOGNIZE_FUNCTION
62 return kUnknown;
63 }
64
65 static const char* KindToCString(Kind kind) {
66 #define KIND_TO_STRING(class_name, function_name, enum_name) \
67 if (kind == k##enum_name) return #enum_name;
68 RECOGNIZED_LIST(KIND_TO_STRING)
69 #undef KIND_TO_STRING
70 return "?";
71 }
72 };
73
74
17 void FlowGraphOptimizer::ApplyICData() { 75 void FlowGraphOptimizer::ApplyICData() {
18 VisitBlocks(); 76 VisitBlocks();
19 if (FLAG_print_flow_graph) { 77 if (FLAG_print_flow_graph) {
20 OS::Print("After Optimizations:\n"); 78 OS::Print("After Optimizations:\n");
21 FlowGraphPrinter printer(Function::Handle(), block_order_); 79 FlowGraphPrinter printer(Function::Handle(), block_order_);
22 printer.PrintBlocks(); 80 printer.PrintBlocks();
23 } 81 }
24 } 82 }
25 83
26 84
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 if (unary_op != NULL) { 224 if (unary_op != NULL) {
167 ASSERT(unary_op->ic_data() == NULL); 225 ASSERT(unary_op->ic_data() == NULL);
168 unary_op->set_ic_data(comp->ic_data()); 226 unary_op->set_ic_data(comp->ic_data());
169 unary_op->set_instr(comp->instr()); 227 unary_op->set_instr(comp->instr());
170 comp->instr()->replace_computation(unary_op); 228 comp->instr()->replace_computation(unary_op);
171 } 229 }
172 } 230 }
173 231
174 232
175 // Returns true if all targets are the same. 233 // Returns true if all targets are the same.
234 // TODO(srdjan): if targets are native use their C_function to compare.
176 static bool HasOneTarget(const ICData& ic_data) { 235 static bool HasOneTarget(const ICData& ic_data) {
177 ASSERT(ic_data.NumberOfChecks() > 0); 236 ASSERT(ic_data.NumberOfChecks() > 0);
178 Function& prev_target = Function::Handle(); 237 Function& prev_target = Function::Handle();
179 GrowableArray<const Class*> classes; 238 GrowableArray<const Class*> classes;
180 ic_data.GetCheckAt(0, &classes, &prev_target); 239 ic_data.GetCheckAt(0, &classes, &prev_target);
181 ASSERT(!prev_target.IsNull()); 240 ASSERT(!prev_target.IsNull());
182 Function& target = Function::Handle(); 241 Function& target = Function::Handle();
183 for (intptr_t i = 1; i < ic_data.NumberOfChecks(); i++) { 242 for (intptr_t i = 1; i < ic_data.NumberOfChecks(); i++) {
184 ic_data.GetCheckAt(i, &classes, &target); 243 ic_data.GetCheckAt(i, &classes, &target);
185 ASSERT(!target.IsNull()); 244 ASSERT(!target.IsNull());
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 } 291 }
233 return result; 292 return result;
234 } 293 }
235 294
236 295
237 // Only unique implicit instance getters can be currently handled. 296 // Only unique implicit instance getters can be currently handled.
238 void FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) { 297 void FlowGraphOptimizer::TryInlineInstanceGetter(InstanceCallComp* comp) {
239 ASSERT(comp->HasICData()); 298 ASSERT(comp->HasICData());
240 const ICData& ic_data = *comp->ic_data(); 299 const ICData& ic_data = *comp->ic_data();
241 if (ic_data.NumberOfChecks() == 0) { 300 if (ic_data.NumberOfChecks() == 0) {
242 // No type feedback collected 301 // No type feedback collected.
243 return;
244 }
245 if (!HasOneTarget(ic_data)) {
246 // TODO(srdjan): Implement when not all targets are the sa,e.
247 return; 302 return;
248 } 303 }
249 Function& target = Function::Handle(); 304 Function& target = Function::Handle();
250 Class& cls = Class::Handle(); 305 GrowableArray<const Class*> classes;
251 ic_data.GetOneClassCheckAt(0, &cls, &target); 306 ic_data.GetCheckAt(0, &classes, &target);
252 if (target.kind() != RawFunction::kImplicitGetter) { 307 ASSERT(classes.length() == 1);
253 // Not an implicit getter. 308
254 // TODO(srdjan): Inline special getters (e.g., array length). 309 if (target.kind() == RawFunction::kImplicitGetter) {
310 if (!HasOneTarget(ic_data)) {
311 // TODO(srdjan): Implement for mutiple targets.
312 return;
313 }
314 // Inline implicit instance getter.
315 const String& field_name =
316 String::Handle(Field::NameFromGetter(comp->function_name()));
317 const Field& field = Field::Handle(GetField(*classes[0], field_name));
318 ASSERT(!field.IsNull());
319 LoadInstanceFieldComp* load = new LoadInstanceFieldComp(
320 field, comp->InputAt(0), comp, ExtractClassIds(ic_data));
321 // Replace 'comp' with 'load'.
322 load->set_instr(comp->instr());
323 comp->instr()->replace_computation(load);
255 return; 324 return;
256 } 325 }
257 // Inline implicit instance getter. 326
258 const String& field_name = 327 // Not an implicit getter.
259 String::Handle(Field::NameFromGetter(comp->function_name())); 328 MethodRecognizer::Kind recognized_kind =
260 const Field& field = Field::Handle(GetField(cls, field_name)); 329 MethodRecognizer::RecognizeKind(target);
261 ASSERT(!field.IsNull()); 330
262 LoadInstanceFieldComp* load = new LoadInstanceFieldComp( 331 // VM objects length getter.
263 field, comp->InputAt(0), comp, ExtractClassIds(ic_data)); 332 if ((recognized_kind == MethodRecognizer::kObjectArrayLength) ||
264 // Replace 'comp' with 'load'. 333 (recognized_kind == MethodRecognizer::kImmutableArrayLength) ||
265 load->set_instr(comp->instr()); 334 (recognized_kind == MethodRecognizer::kGrowableArrayLength)) {
266 comp->instr()->replace_computation(load); 335 if (!HasOneTarget(ic_data)) {
336 // TODO(srdjan): Implement for mutiple targets.
337 return;
338 }
339 intptr_t length_offset = -1;
340 switch (recognized_kind) {
341 case MethodRecognizer::kObjectArrayLength:
342 case MethodRecognizer::kImmutableArrayLength:
343 length_offset = Array::length_offset();
344 break;
345 case MethodRecognizer::kGrowableArrayLength:
346 length_offset = GrowableObjectArray::length_offset();
347 break;
348 default:
349 UNREACHABLE();
350 }
351 LoadVMFieldComp* load = new LoadVMFieldComp(
352 comp->InputAt(0),
353 Array::length_offset(),
354 Type::ZoneHandle(Type::IntInterface()),
355 comp,
356 ExtractClassIds(ic_data));
357 load->set_instr(comp->instr());
358 comp->instr()->replace_computation(load);
359 return;
360 }
361
362 if (recognized_kind == MethodRecognizer::kStringBaseLength) {
363 ASSERT(HasOneTarget(ic_data));
364 LoadVMFieldComp* load = new LoadVMFieldComp(
365 comp->InputAt(0),
366 String::length_offset(),
367 Type::ZoneHandle(Type::IntInterface()),
368 comp,
369 ExtractClassIds(ic_data));
370 load->set_instr(comp->instr());
371 comp->instr()->replace_computation(load);
372 return;
373 }
374 }
375
376
377 // Inline only simple, frequently called core library methods.
378 void FlowGraphOptimizer::TryInlineInstanceMethod(InstanceCallComp* comp) {
379 ASSERT(comp->HasICData());
380 const ICData& ic_data = *comp->ic_data();
381 if ((ic_data.NumberOfChecks() == 0) || !HasOneTarget(ic_data)) {
382 // No type feedback collected.
383 return;
384 }
385 Function& target = Function::Handle();
386 GrowableArray<const Class*> classes;
387 ic_data.GetCheckAt(0, &classes, &target);
388 ASSERT(classes.length() == 1);
389 MethodRecognizer::Kind recognized_kind =
390 MethodRecognizer::RecognizeKind(target);
391 if (recognized_kind == MethodRecognizer::kDoubleToDouble) {
392 // TODO(srdjan): Implement.
393 }
394 if (recognized_kind == MethodRecognizer::kIntegerToDouble) {
395 // TODO(srdjan): Implement.
396 }
397 }
398
399
400 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) {
401 if (comp->HasICData()) {
402 const String& function_name = comp->function_name();
403 Token::Kind op_kind = Token::GetBinaryOp(function_name);
404 if (op_kind != Token::kILLEGAL) {
405 TryReplaceWithBinaryOp(comp, op_kind);
406 return;
407 }
408 op_kind = Token::GetUnaryOp(function_name);
409 if (op_kind != Token::kILLEGAL) {
410 TryReplaceWithUnaryOp(comp, op_kind);
411 return;
412 }
413 if (Field::IsGetterName(function_name)) {
414 TryInlineInstanceGetter(comp);
415 return;
416 }
417 TryInlineInstanceMethod(comp);
418 }
419 }
420
421
422 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp) {
423 MethodRecognizer::Kind recognized_kind =
424 MethodRecognizer::RecognizeKind(comp->function());
425 if (recognized_kind == MethodRecognizer::kMathSqrt) {
426 // TODO(srdjan): Implement this.
427 }
267 } 428 }
268 429
269 430
270 void FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) { 431 void FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) {
271 ASSERT(comp->HasICData()); 432 ASSERT(comp->HasICData());
272 const ICData& ic_data = *comp->ic_data(); 433 const ICData& ic_data = *comp->ic_data();
273 if (ic_data.NumberOfChecks() == 0) { 434 if (ic_data.NumberOfChecks() == 0) {
274 // No type feedback collected 435 // No type feedback collected.
275 return; 436 return;
276 } 437 }
277 if (!HasOneTarget(ic_data)) { 438 if (!HasOneTarget(ic_data)) {
278 // TODO(srdjan): Implement when not all targets are the sa,e. 439 // TODO(srdjan): Implement when not all targets are the sa,e.
279 return; 440 return;
280 } 441 }
281 Function& target = Function::Handle(); 442 Function& target = Function::Handle();
282 Class& cls = Class::Handle(); 443 Class& cls = Class::Handle();
283 ic_data.GetOneClassCheckAt(0, &cls, &target); 444 ic_data.GetOneClassCheckAt(0, &cls, &target);
284 if (target.kind() != RawFunction::kImplicitSetter) { 445 if (target.kind() != RawFunction::kImplicitSetter) {
285 // Not an implicit setter. 446 // Not an implicit setter.
286 // TODO(srdjan): Inline special setters. 447 // TODO(srdjan): Inline special setters.
287 return; 448 return;
288 } 449 }
289 // Inline implicit instance setter. 450 // Inline implicit instance setter.
290 const Field& field = Field::Handle(GetField(cls, comp->field_name())); 451 const Field& field = Field::Handle(GetField(cls, comp->field_name()));
291 ASSERT(!field.IsNull()); 452 ASSERT(!field.IsNull());
292 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( 453 StoreInstanceFieldComp* store = new StoreInstanceFieldComp(
293 field, 454 field,
294 comp->InputAt(0), 455 comp->InputAt(0),
295 comp->InputAt(1), 456 comp->InputAt(1),
296 comp, 457 comp,
297 ExtractClassIds(ic_data)); 458 ExtractClassIds(ic_data));
298 // Replace 'comp' with 'store'. 459 // Replace 'comp' with 'store'.
299 store->set_instr(comp->instr()); 460 store->set_instr(comp->instr());
300 comp->instr()->replace_computation(store); 461 comp->instr()->replace_computation(store);
301 } 462 }
302 463
303 464
304 void FlowGraphOptimizer::VisitInstanceCall(InstanceCallComp* comp) {
305 if (comp->HasICData()) {
306 const String& function_name = comp->function_name();
307 Token::Kind op_kind = Token::GetBinaryOp(function_name);
308 if (op_kind != Token::kILLEGAL) {
309 TryReplaceWithBinaryOp(comp, op_kind);
310 return;
311 }
312 op_kind = Token::GetUnaryOp(function_name);
313 if (op_kind != Token::kILLEGAL) {
314 TryReplaceWithUnaryOp(comp, op_kind);
315 return;
316 }
317 if (Field::IsGetterName(function_name)) {
318 TryInlineInstanceGetter(comp);
319 return;
320 }
321 }
322 }
323
324 465
325 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) { 466 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) {
326 // TODO(srdjan): Add assigneable check node if --enable_type_checks. 467 // TODO(srdjan): Add assigneable check node if --enable_type_checks.
327 if (comp->HasICData() && !FLAG_enable_type_checks) { 468 if (comp->HasICData() && !FLAG_enable_type_checks) {
328 TryInlineInstanceSetter(comp); 469 TryInlineInstanceSetter(comp);
329 } 470 }
330 } 471 }
331 472
332 473
333 void FlowGraphOptimizer::VisitLoadIndexed(LoadIndexedComp* comp) { 474 void FlowGraphOptimizer::VisitLoadIndexed(LoadIndexedComp* comp) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 instr->computation()->Accept(this); 514 instr->computation()->Accept(this);
374 } 515 }
375 516
376 517
377 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { 518 void FlowGraphOptimizer::VisitBind(BindInstr* instr) {
378 instr->computation()->Accept(this); 519 instr->computation()->Accept(this);
379 } 520 }
380 521
381 522
382 } // namespace dart 523 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_optimizer.h ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698