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/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 4486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4497 break; | 4497 break; |
4498 } | 4498 } |
4499 } | 4499 } |
4500 } | 4500 } |
4501 } | 4501 } |
4502 | 4502 |
4503 | 4503 |
4504 void FlowGraphOptimizer::VisitStoreInstanceField( | 4504 void FlowGraphOptimizer::VisitStoreInstanceField( |
4505 StoreInstanceFieldInstr* instr) { | 4505 StoreInstanceFieldInstr* instr) { |
4506 if (instr->IsUnboxedStore()) { | 4506 if (instr->IsUnboxedStore()) { |
4507 ASSERT(instr->is_initialization_); | 4507 ASSERT(instr->is_potential_unboxed_initialization_); |
4508 // Determine if this field should be unboxed based on the usage of getter | 4508 // Determine if this field should be unboxed based on the usage of getter |
4509 // and setter functions: The heuristic requires that the setter has a | 4509 // and setter functions: The heuristic requires that the setter has a |
4510 // usage count of at least 1/kGetterSetterRatio of the getter usage count. | 4510 // usage count of at least 1/kGetterSetterRatio of the getter usage count. |
4511 // This is to avoid unboxing fields where the setter is never or rarely | 4511 // This is to avoid unboxing fields where the setter is never or rarely |
4512 // executed. | 4512 // executed. |
4513 const Field& field = Field::ZoneHandle(I, instr->field().raw()); | 4513 const Field& field = Field::ZoneHandle(I, instr->field().raw()); |
4514 const String& field_name = String::Handle(I, field.name()); | 4514 const String& field_name = String::Handle(I, field.name()); |
4515 const Class& owner = Class::Handle(I, field.owner()); | 4515 const Class& owner = Class::Handle(I, field.owner()); |
4516 const Function& getter = | 4516 const Function& getter = |
4517 Function::Handle(I, owner.LookupGetterFunction(field_name)); | 4517 Function::Handle(I, owner.LookupGetterFunction(field_name)); |
(...skipping 24 matching lines...) Expand all Loading... |
4542 new AllocateUninitializedContextInstr(instr->token_pos(), | 4542 new AllocateUninitializedContextInstr(instr->token_pos(), |
4543 instr->num_context_variables()); | 4543 instr->num_context_variables()); |
4544 instr->ReplaceWith(replacement, current_iterator()); | 4544 instr->ReplaceWith(replacement, current_iterator()); |
4545 | 4545 |
4546 StoreInstanceFieldInstr* store = | 4546 StoreInstanceFieldInstr* store = |
4547 new(I) StoreInstanceFieldInstr(Context::parent_offset(), | 4547 new(I) StoreInstanceFieldInstr(Context::parent_offset(), |
4548 new Value(replacement), | 4548 new Value(replacement), |
4549 new Value(flow_graph_->constant_null()), | 4549 new Value(flow_graph_->constant_null()), |
4550 kNoStoreBarrier, | 4550 kNoStoreBarrier, |
4551 instr->token_pos()); | 4551 instr->token_pos()); |
4552 store->set_is_initialization(true); // Won't be eliminated by DSE. | 4552 // Storing into uninitialized memory; remember to prevent dead store |
| 4553 // elimination and ensure proper GC barrier. |
| 4554 store->set_is_object_reference_initialization(true); |
4553 flow_graph_->InsertAfter(replacement, store, NULL, FlowGraph::kEffect); | 4555 flow_graph_->InsertAfter(replacement, store, NULL, FlowGraph::kEffect); |
4554 Definition* cursor = store; | 4556 Definition* cursor = store; |
4555 for (intptr_t i = 0; i < instr->num_context_variables(); ++i) { | 4557 for (intptr_t i = 0; i < instr->num_context_variables(); ++i) { |
4556 store = | 4558 store = |
4557 new(I) StoreInstanceFieldInstr(Context::variable_offset(i), | 4559 new(I) StoreInstanceFieldInstr(Context::variable_offset(i), |
4558 new Value(replacement), | 4560 new Value(replacement), |
4559 new Value(flow_graph_->constant_null()), | 4561 new Value(flow_graph_->constant_null()), |
4560 kNoStoreBarrier, | 4562 kNoStoreBarrier, |
4561 instr->token_pos()); | 4563 instr->token_pos()); |
4562 store->set_is_initialization(true); // Won't be eliminated by DSE. | 4564 // Storing into uninitialized memory; remember to prevent dead store |
| 4565 // elimination and ensure proper GC barrier. |
| 4566 store->set_is_object_reference_initialization(true); |
4563 flow_graph_->InsertAfter(cursor, store, NULL, FlowGraph::kEffect); | 4567 flow_graph_->InsertAfter(cursor, store, NULL, FlowGraph::kEffect); |
4564 cursor = store; | 4568 cursor = store; |
4565 } | 4569 } |
4566 } | 4570 } |
4567 | 4571 |
4568 | 4572 |
4569 void FlowGraphOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { | 4573 void FlowGraphOptimizer::VisitLoadCodeUnits(LoadCodeUnitsInstr* instr) { |
4570 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. | 4574 // TODO(zerny): Use kUnboxedUint32 once it is fully supported/optimized. |
4571 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) | 4575 #if defined(TARGET_ARCH_IA32) || defined(TARGET_ARCH_ARM) |
4572 if (!instr->can_pack_into_smi()) | 4576 if (!instr->can_pack_into_smi()) |
(...skipping 2552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7125 Dump(); | 7129 Dump(); |
7126 } | 7130 } |
7127 EliminateDeadStores(); | 7131 EliminateDeadStores(); |
7128 if (FLAG_trace_load_optimization) { | 7132 if (FLAG_trace_load_optimization) { |
7129 FlowGraphPrinter::PrintGraph("After StoreOptimizer", graph_); | 7133 FlowGraphPrinter::PrintGraph("After StoreOptimizer", graph_); |
7130 } | 7134 } |
7131 } | 7135 } |
7132 | 7136 |
7133 bool CanEliminateStore(Instruction* instr) { | 7137 bool CanEliminateStore(Instruction* instr) { |
7134 switch (instr->tag()) { | 7138 switch (instr->tag()) { |
7135 case Instruction::kStoreInstanceField: | 7139 case Instruction::kStoreInstanceField: { |
7136 if (instr->AsStoreInstanceField()->is_initialization()) { | 7140 StoreInstanceFieldInstr* store_instance = instr->AsStoreInstanceField(); |
7137 // Can't eliminate stores that initialized unboxed fields. | 7141 // Can't eliminate stores that initialize fields. |
7138 return false; | 7142 return !(store_instance->is_potential_unboxed_initialization() || |
7139 } | 7143 store_instance->is_object_reference_initialization()); |
| 7144 } |
7140 case Instruction::kStoreIndexed: | 7145 case Instruction::kStoreIndexed: |
7141 case Instruction::kStoreStaticField: | 7146 case Instruction::kStoreStaticField: |
7142 return true; | 7147 return true; |
7143 default: | 7148 default: |
7144 UNREACHABLE(); | 7149 UNREACHABLE(); |
7145 return false; | 7150 return false; |
7146 } | 7151 } |
7147 } | 7152 } |
7148 | 7153 |
7149 virtual void ComputeInitialSets() { | 7154 virtual void ComputeInitialSets() { |
(...skipping 1312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8462 | 8467 |
8463 // Insert materializations at environment uses. | 8468 // Insert materializations at environment uses. |
8464 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8469 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
8465 CreateMaterializationAt( | 8470 CreateMaterializationAt( |
8466 exits_collector_.exits()[i], alloc, *slots); | 8471 exits_collector_.exits()[i], alloc, *slots); |
8467 } | 8472 } |
8468 } | 8473 } |
8469 | 8474 |
8470 | 8475 |
8471 } // namespace dart | 8476 } // namespace dart |
OLD | NEW |