Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 3488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3499 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || | 3499 ASSERT((cid == kOneByteStringCid) || (cid == kTwoByteStringCid) || |
| 3500 (cid == kExternalOneByteStringCid) || | 3500 (cid == kExternalOneByteStringCid) || |
| 3501 (cid == kGrowableObjectArrayCid) || | 3501 (cid == kGrowableObjectArrayCid) || |
| 3502 (cid == kImmutableArrayCid) || (cid == kArrayCid)); | 3502 (cid == kImmutableArrayCid) || (cid == kArrayCid)); |
| 3503 ConstantInstr* cid_instr = new ConstantInstr(Smi::Handle(Smi::New(cid))); | 3503 ConstantInstr* cid_instr = new ConstantInstr(Smi::Handle(Smi::New(cid))); |
| 3504 ReplaceCall(call, cid_instr); | 3504 ReplaceCall(call, cid_instr); |
| 3505 } | 3505 } |
| 3506 } | 3506 } |
| 3507 | 3507 |
| 3508 | 3508 |
| 3509 void FlowGraphOptimizer::VisitStoreInstanceField( | |
| 3510 StoreInstanceFieldInstr* instr) { | |
| 3511 if (instr->IsUnboxedStore()) { | |
| 3512 ASSERT(instr->initialization_); | |
| 3513 // Determine if this field should be unboxed based on the usage of getter | |
| 3514 // and setter functions. | |
| 3515 const Field& field = Field::ZoneHandle(instr->field().raw()); | |
| 3516 const String& field_name = String::Handle(field.name()); | |
| 3517 class Class& owner = Class::Handle(field.owner()); | |
| 3518 const Function& getter = | |
| 3519 Function::Handle(owner.LookupGetterFunction(field_name)); | |
| 3520 const Function& setter = | |
| 3521 Function::Handle(owner.LookupSetterFunction(field_name)); | |
|
srdjan
2013/12/13 22:12:06
Below is an important heuristic, add brief comment
Florian Schneider
2013/12/16 13:08:09
Done.
| |
| 3522 bool result = !getter.IsNull() | |
| 3523 && !setter.IsNull() | |
| 3524 && setter.usage_counter() > 0 | |
|
srdjan
2013/12/13 18:13:17
Add parentheses here and below.
Florian Schneider
2013/12/16 13:08:09
Done.
| |
| 3525 && 10 * setter.usage_counter() > getter.usage_counter(); | |
|
srdjan
2013/12/13 22:12:06
put 10 into a flag to experiment with ?
Florian Schneider
2013/12/16 13:08:09
Done.
| |
| 3526 if (!result) { | |
| 3527 field.set_is_unboxing_candidate(false); | |
| 3528 field.DeoptimizeDependentCode(); | |
| 3529 } else { | |
| 3530 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | |
| 3531 } | |
| 3532 } | |
| 3533 } | |
| 3534 | |
| 3535 | |
| 3509 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, | 3536 bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, |
| 3510 const ICData& unary_ic_data) { | 3537 const ICData& unary_ic_data) { |
| 3511 ASSERT((unary_ic_data.NumberOfChecks() > 0) && | 3538 ASSERT((unary_ic_data.NumberOfChecks() > 0) && |
| 3512 (unary_ic_data.num_args_tested() == 1)); | 3539 (unary_ic_data.num_args_tested() == 1)); |
| 3513 if (FLAG_enable_type_checks) { | 3540 if (FLAG_enable_type_checks) { |
| 3514 // Checked mode setters are inlined like normal methods by conventional | 3541 // Checked mode setters are inlined like normal methods by conventional |
| 3515 // inlining. | 3542 // inlining. |
| 3516 return false; | 3543 return false; |
| 3517 } | 3544 } |
| 3518 | 3545 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 3529 Function& target = Function::Handle(); | 3556 Function& target = Function::Handle(); |
| 3530 intptr_t class_id; | 3557 intptr_t class_id; |
| 3531 unary_ic_data.GetOneClassCheckAt(0, &class_id, &target); | 3558 unary_ic_data.GetOneClassCheckAt(0, &class_id, &target); |
| 3532 if (target.kind() != RawFunction::kImplicitSetter) { | 3559 if (target.kind() != RawFunction::kImplicitSetter) { |
| 3533 // Non-implicit setter are inlined like normal method calls. | 3560 // Non-implicit setter are inlined like normal method calls. |
| 3534 return false; | 3561 return false; |
| 3535 } | 3562 } |
| 3536 // Inline implicit instance setter. | 3563 // Inline implicit instance setter. |
| 3537 const String& field_name = | 3564 const String& field_name = |
| 3538 String::Handle(Field::NameFromSetter(instr->function_name())); | 3565 String::Handle(Field::NameFromSetter(instr->function_name())); |
| 3539 const Field& field = Field::Handle(GetField(class_id, field_name)); | 3566 const Field& field = Field::ZoneHandle(GetField(class_id, field_name)); |
| 3540 ASSERT(!field.IsNull()); | 3567 ASSERT(!field.IsNull()); |
| 3541 | 3568 |
| 3542 if (InstanceCallNeedsClassCheck(instr)) { | 3569 if (InstanceCallNeedsClassCheck(instr)) { |
| 3543 AddReceiverCheck(instr); | 3570 AddReceiverCheck(instr); |
| 3544 } | 3571 } |
| 3545 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; | 3572 StoreBarrierType needs_store_barrier = kEmitStoreBarrier; |
| 3546 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { | 3573 if (ArgIsAlways(kSmiCid, *instr->ic_data(), 1)) { |
| 3547 InsertBefore(instr, | 3574 InsertBefore(instr, |
| 3548 new CheckSmiInstr(new Value(instr->ArgumentAt(1)), | 3575 new CheckSmiInstr(new Value(instr->ArgumentAt(1)), |
| 3549 instr->deopt_id()), | 3576 instr->deopt_id()), |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 3560 instr->env(), | 3587 instr->env(), |
| 3561 Definition::kEffect); | 3588 Definition::kEffect); |
| 3562 } | 3589 } |
| 3563 | 3590 |
| 3564 // Field guard was detached. | 3591 // Field guard was detached. |
| 3565 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( | 3592 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 3566 field, | 3593 field, |
| 3567 new Value(instr->ArgumentAt(0)), | 3594 new Value(instr->ArgumentAt(0)), |
| 3568 new Value(instr->ArgumentAt(1)), | 3595 new Value(instr->ArgumentAt(1)), |
| 3569 needs_store_barrier); | 3596 needs_store_barrier); |
| 3597 | |
| 3598 if (store->IsUnboxedStore()) { | |
| 3599 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | |
| 3600 } | |
| 3601 | |
| 3570 // Discard the environment from the original instruction because the store | 3602 // Discard the environment from the original instruction because the store |
| 3571 // can't deoptimize. | 3603 // can't deoptimize. |
| 3572 instr->RemoveEnvironment(); | 3604 instr->RemoveEnvironment(); |
| 3573 ReplaceCall(instr, store); | 3605 ReplaceCall(instr, store); |
| 3574 return true; | 3606 return true; |
| 3575 } | 3607 } |
| 3576 | 3608 |
| 3577 | 3609 |
| 3578 // Range analysis for smi values. | 3610 // Range analysis for smi values. |
| 3579 class RangeAnalysis : public ValueObject { | 3611 class RangeAnalysis : public ValueObject { |
| (...skipping 4467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8047 } | 8079 } |
| 8048 | 8080 |
| 8049 // Insert materializations at environment uses. | 8081 // Insert materializations at environment uses. |
| 8050 for (intptr_t i = 0; i < exits.length(); i++) { | 8082 for (intptr_t i = 0; i < exits.length(); i++) { |
| 8051 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 8083 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 8052 } | 8084 } |
| 8053 } | 8085 } |
| 8054 | 8086 |
| 8055 | 8087 |
| 8056 } // namespace dart | 8088 } // namespace dart |
| OLD | NEW |