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 |