Index: runtime/vm/flow_graph_optimizer.cc |
=================================================================== |
--- runtime/vm/flow_graph_optimizer.cc (revision 31159) |
+++ runtime/vm/flow_graph_optimizer.cc (working copy) |
@@ -41,6 +41,8 @@ |
"Print live sets for load optimization pass."); |
DEFINE_FLAG(bool, enable_simd_inline, true, |
"Enable inlining of SIMD related method calls."); |
+DEFINE_FLAG(int, getter_setter_ratio, 10, |
+ "Ratio of getter/setter usage used for double field unboxing heuristics"); |
DECLARE_FLAG(bool, eliminate_type_checks); |
DECLARE_FLAG(bool, enable_type_checks); |
DECLARE_FLAG(bool, trace_type_check_elimination); |
@@ -3531,6 +3533,37 @@ |
} |
+void FlowGraphOptimizer::VisitStoreInstanceField( |
+ StoreInstanceFieldInstr* instr) { |
+ if (instr->IsUnboxedStore()) { |
+ ASSERT(instr->is_initialization_); |
+ // Determine if this field should be unboxed based on the usage of getter |
+ // and setter functions: The heuristic requires that the setter has a |
+ // usage count of at least 1/kGetterSetterRatio of the getter usage count. |
+ // This is to avoid unboxing fields where the setter is never or rarely |
+ // executed. |
+ const Field& field = Field::ZoneHandle(instr->field().raw()); |
+ const String& field_name = String::Handle(field.name()); |
+ class Class& owner = Class::Handle(field.owner()); |
+ const Function& getter = |
+ Function::Handle(owner.LookupGetterFunction(field_name)); |
+ const Function& setter = |
+ Function::Handle(owner.LookupSetterFunction(field_name)); |
+ bool result = !getter.IsNull() |
+ && !setter.IsNull() |
+ && (setter.usage_counter() > 0) |
+ && (FLAG_getter_setter_ratio * setter.usage_counter() > |
+ getter.usage_counter()); |
+ if (!result) { |
+ field.set_is_unboxing_candidate(false); |
+ field.DeoptimizeDependentCode(); |
+ } else { |
+ FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
+ } |
+ } |
+} |
+ |
+ |
bool FlowGraphOptimizer::TryInlineInstanceSetter(InstanceCallInstr* instr, |
const ICData& unary_ic_data) { |
ASSERT((unary_ic_data.NumberOfChecks() > 0) && |
@@ -3561,7 +3594,7 @@ |
// Inline implicit instance setter. |
const String& field_name = |
String::Handle(Field::NameFromSetter(instr->function_name())); |
- const Field& field = Field::Handle(GetField(class_id, field_name)); |
+ const Field& field = Field::ZoneHandle(GetField(class_id, field_name)); |
ASSERT(!field.IsNull()); |
if (InstanceCallNeedsClassCheck(instr)) { |
@@ -3592,6 +3625,11 @@ |
new Value(instr->ArgumentAt(0)), |
new Value(instr->ArgumentAt(1)), |
needs_store_barrier); |
+ |
+ if (store->IsUnboxedStore()) { |
+ FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
+ } |
+ |
// Discard the environment from the original instruction because the store |
// can't deoptimize. |
instr->RemoveEnvironment(); |