OLD | NEW |
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 |
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 if (Token::IsUnaryToken(op_kind) && TryReplaceWithUnaryOp(comp, op_kind)) { | 364 if (Token::IsUnaryToken(op_kind) && TryReplaceWithUnaryOp(comp, op_kind)) { |
365 return; | 365 return; |
366 } | 366 } |
367 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(comp)) { | 367 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(comp)) { |
368 return; | 368 return; |
369 } | 369 } |
370 if (TryInlineInstanceMethod(comp)) { | 370 if (TryInlineInstanceMethod(comp)) { |
371 return; | 371 return; |
372 } | 372 } |
373 const intptr_t kMaxChecks = 4; | 373 const intptr_t kMaxChecks = 4; |
374 if (comp->ic_data()->num_args_tested() <= kMaxChecks) { | 374 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { |
375 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); | 375 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); |
376 ICData& unary_checks = | 376 ICData& unary_checks = |
377 ICData::Handle(ToUnaryClassChecks(*comp->ic_data())); | 377 ICData::ZoneHandle(ToUnaryClassChecks(*comp->ic_data())); |
378 call->set_ic_data(&unary_checks); | 378 call->set_ic_data(&unary_checks); |
379 comp->ReplaceWith(call); | 379 comp->ReplaceWith(call); |
380 } | 380 } |
| 381 } else { |
| 382 // Mark it for deopt. |
| 383 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); |
| 384 call->set_ic_data(&ICData::ZoneHandle()); |
| 385 comp->ReplaceWith(call); |
381 } | 386 } |
382 } | 387 } |
383 | 388 |
384 | 389 |
385 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp) { | 390 void FlowGraphOptimizer::VisitStaticCall(StaticCallComp* comp) { |
386 MethodRecognizer::Kind recognized_kind = | 391 MethodRecognizer::Kind recognized_kind = |
387 MethodRecognizer::RecognizeKind(comp->function()); | 392 MethodRecognizer::RecognizeKind(comp->function()); |
388 if (recognized_kind == MethodRecognizer::kMathSqrt) { | 393 if (recognized_kind == MethodRecognizer::kMathSqrt) { |
389 comp->set_recognized(MethodRecognizer::kMathSqrt); | 394 comp->set_recognized(MethodRecognizer::kMathSqrt); |
390 } | 395 } |
391 } | 396 } |
392 | 397 |
393 | 398 |
394 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) { | 399 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceSetterComp* comp) { |
395 ASSERT(comp->HasICData()); | 400 ASSERT(comp->HasICData()); |
396 const ICData& ic_data = *comp->ic_data(); | 401 const ICData& ic_data = *comp->ic_data(); |
397 if (ic_data.NumberOfChecks() == 0) { | 402 if (ic_data.NumberOfChecks() == 0) { |
398 // No type feedback collected. | 403 // No type feedback collected. |
399 return false; | 404 return false; |
400 } | 405 } |
401 if (!HasOneTarget(ic_data)) { | 406 if (!HasOneTarget(ic_data)) { |
402 // TODO(srdjan): Implement when not all targets are the sa,e. | 407 // TODO(srdjan): Implement when not all targets are the same. |
403 return false; | 408 return false; |
404 } | 409 } |
405 Function& target = Function::Handle(); | 410 Function& target = Function::Handle(); |
406 intptr_t class_id; | 411 intptr_t class_id; |
407 ic_data.GetOneClassCheckAt(0, &class_id, &target); | 412 ic_data.GetOneClassCheckAt(0, &class_id, &target); |
408 if (target.kind() != RawFunction::kImplicitSetter) { | 413 if (target.kind() != RawFunction::kImplicitSetter) { |
409 // Not an implicit setter. | 414 // Not an implicit setter. |
410 // TODO(srdjan): Inline special setters. | 415 // TODO(srdjan): Inline special setters. |
411 return false; | 416 return false; |
412 } | 417 } |
413 // Inline implicit instance setter. | 418 // Inline implicit instance setter. |
414 const Field& field = Field::Handle(GetField(class_id, comp->field_name())); | 419 const Field& field = Field::Handle(GetField(class_id, comp->field_name())); |
415 ASSERT(!field.IsNull()); | 420 ASSERT(!field.IsNull()); |
416 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( | 421 StoreInstanceFieldComp* store = new StoreInstanceFieldComp( |
417 field, | 422 field, |
418 comp->InputAt(0), | 423 comp->InputAt(0), |
419 comp->InputAt(1), | 424 comp->InputAt(1), |
420 comp); | 425 comp); |
421 store->set_ic_data(comp->ic_data()); | 426 store->set_ic_data(comp->ic_data()); |
422 comp->ReplaceWith(store); | 427 comp->ReplaceWith(store); |
423 return true; | 428 return true; |
424 } | 429 } |
425 | 430 |
426 | 431 |
427 | 432 |
428 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) { | 433 void FlowGraphOptimizer::VisitInstanceSetter(InstanceSetterComp* comp) { |
429 // TODO(srdjan): Add assigneable check node if --enable_type_checks. | 434 // TODO(srdjan): Add assignable check node if --enable_type_checks. |
430 if (comp->HasICData() && !FLAG_enable_type_checks) { | 435 if (comp->HasICData() && !FLAG_enable_type_checks) { |
431 TryInlineInstanceSetter(comp); | 436 if (TryInlineInstanceSetter(comp)) { |
| 437 return; |
| 438 } |
432 } | 439 } |
| 440 // TODO(srdjan): Polymorphic dispatch to setters or deoptimize. |
433 } | 441 } |
434 | 442 |
435 | 443 |
436 enum IndexedAccessType { | 444 enum IndexedAccessType { |
437 kIndexedLoad, | 445 kIndexedLoad, |
438 kIndexedStore | 446 kIndexedStore |
439 }; | 447 }; |
440 | 448 |
441 | 449 |
442 static intptr_t ReceiverClassId(Computation* comp) { | 450 static intptr_t ReceiverClassId(Computation* comp) { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
535 TryFuseComparisonWithBranch(comp); | 543 TryFuseComparisonWithBranch(comp); |
536 } | 544 } |
537 | 545 |
538 | 546 |
539 void FlowGraphOptimizer::VisitStrictCompareComp(StrictCompareComp* comp) { | 547 void FlowGraphOptimizer::VisitStrictCompareComp(StrictCompareComp* comp) { |
540 TryFuseComparisonWithBranch(comp); | 548 TryFuseComparisonWithBranch(comp); |
541 } | 549 } |
542 | 550 |
543 | 551 |
544 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp) { | 552 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp) { |
545 const intptr_t kMaxChecks = 4; | 553 if (comp->HasICData()) { |
546 if (comp->HasICData() && (comp->ic_data()->num_args_tested() <= kMaxChecks)) { | 554 // Replace binary checks with unary ones since EmitNative expects it. |
547 // Replace binary checks with unary ones. | |
548 ICData& unary_checks = | 555 ICData& unary_checks = |
549 ICData::Handle(ToUnaryClassChecks(*comp->ic_data())); | 556 ICData::Handle(ToUnaryClassChecks(*comp->ic_data())); |
550 comp->set_ic_data(&unary_checks); | 557 comp->set_ic_data(&unary_checks); |
551 } | 558 } |
552 | 559 |
553 TryFuseComparisonWithBranch(comp); | 560 TryFuseComparisonWithBranch(comp); |
554 } | 561 } |
555 | 562 |
556 | 563 |
557 void FlowGraphOptimizer::VisitDo(DoInstr* instr) { | 564 void FlowGraphOptimizer::VisitDo(DoInstr* instr) { |
558 instr->computation()->Accept(this); | 565 instr->computation()->Accept(this); |
559 } | 566 } |
560 | 567 |
561 | 568 |
562 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { | 569 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { |
563 instr->computation()->Accept(this); | 570 instr->computation()->Accept(this); |
564 } | 571 } |
565 | 572 |
566 | 573 |
567 } // namespace dart | 574 } // namespace dart |
OLD | NEW |