| 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 2198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2209 const String& field_name = | 2209 const String& field_name = |
| 2210 String::Handle(Field::NameFromGetter(call->function_name())); | 2210 String::Handle(Field::NameFromGetter(call->function_name())); |
| 2211 const Field& field = Field::ZoneHandle(GetField(class_ids[0], field_name)); | 2211 const Field& field = Field::ZoneHandle(GetField(class_ids[0], field_name)); |
| 2212 ASSERT(!field.IsNull()); | 2212 ASSERT(!field.IsNull()); |
| 2213 | 2213 |
| 2214 if (InstanceCallNeedsClassCheck(call)) { | 2214 if (InstanceCallNeedsClassCheck(call)) { |
| 2215 AddReceiverCheck(call); | 2215 AddReceiverCheck(call); |
| 2216 } | 2216 } |
| 2217 LoadFieldInstr* load = new LoadFieldInstr( | 2217 LoadFieldInstr* load = new LoadFieldInstr( |
| 2218 new Value(call->ArgumentAt(0)), | 2218 new Value(call->ArgumentAt(0)), |
| 2219 field.Offset(), | 2219 &field, |
| 2220 AbstractType::ZoneHandle(field.type()), | 2220 AbstractType::ZoneHandle(field.type()), |
| 2221 field.is_final()); | 2221 field.is_final()); |
| 2222 load->set_field(&field); | |
| 2223 if (field.guarded_cid() != kIllegalCid) { | 2222 if (field.guarded_cid() != kIllegalCid) { |
| 2224 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { | 2223 if (!field.is_nullable() || (field.guarded_cid() == kNullCid)) { |
| 2225 load->set_result_cid(field.guarded_cid()); | 2224 load->set_result_cid(field.guarded_cid()); |
| 2226 } | 2225 } |
| 2227 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); | 2226 FlowGraph::AddToGuardedFields(flow_graph_->guarded_fields(), &field); |
| 2228 } | 2227 } |
| 2229 | 2228 |
| 2230 // Discard the environment from the original instruction because the load | 2229 // Discard the environment from the original instruction because the load |
| 2231 // can't deoptimize. | 2230 // can't deoptimize. |
| 2232 call->RemoveEnvironment(); | 2231 call->RemoveEnvironment(); |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2685 ic_data.GetCheckAt(0, &class_ids, &target); | 2684 ic_data.GetCheckAt(0, &class_ids, &target); |
| 2686 MethodRecognizer::Kind recognized_kind = | 2685 MethodRecognizer::Kind recognized_kind = |
| 2687 MethodRecognizer::RecognizeKind(target); | 2686 MethodRecognizer::RecognizeKind(target); |
| 2688 | 2687 |
| 2689 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && | 2688 if ((recognized_kind == MethodRecognizer::kGrowableArraySetData) && |
| 2690 (ic_data.NumberOfChecks() == 1) && | 2689 (ic_data.NumberOfChecks() == 1) && |
| 2691 (class_ids[0] == kGrowableObjectArrayCid)) { | 2690 (class_ids[0] == kGrowableObjectArrayCid)) { |
| 2692 // This is an internal method, no need to check argument types. | 2691 // This is an internal method, no need to check argument types. |
| 2693 Definition* array = call->ArgumentAt(0); | 2692 Definition* array = call->ArgumentAt(0); |
| 2694 Definition* value = call->ArgumentAt(1); | 2693 Definition* value = call->ArgumentAt(1); |
| 2695 StoreVMFieldInstr* store = new StoreVMFieldInstr( | 2694 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 2695 GrowableObjectArray::data_offset(), |
| 2696 new Value(array), | 2696 new Value(array), |
| 2697 GrowableObjectArray::data_offset(), | |
| 2698 new Value(value), | 2697 new Value(value), |
| 2699 Type::ZoneHandle()); | 2698 kEmitStoreBarrier); |
| 2700 ReplaceCall(call, store); | 2699 ReplaceCall(call, store); |
| 2701 return true; | 2700 return true; |
| 2702 } | 2701 } |
| 2703 | 2702 |
| 2704 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && | 2703 if ((recognized_kind == MethodRecognizer::kGrowableArraySetLength) && |
| 2705 (ic_data.NumberOfChecks() == 1) && | 2704 (ic_data.NumberOfChecks() == 1) && |
| 2706 (class_ids[0] == kGrowableObjectArrayCid)) { | 2705 (class_ids[0] == kGrowableObjectArrayCid)) { |
| 2707 // This is an internal method, no need to check argument types nor | 2706 // This is an internal method, no need to check argument types nor |
| 2708 // range. | 2707 // range. |
| 2709 Definition* array = call->ArgumentAt(0); | 2708 Definition* array = call->ArgumentAt(0); |
| 2710 Definition* value = call->ArgumentAt(1); | 2709 Definition* value = call->ArgumentAt(1); |
| 2711 StoreVMFieldInstr* store = new StoreVMFieldInstr( | 2710 StoreInstanceFieldInstr* store = new StoreInstanceFieldInstr( |
| 2711 GrowableObjectArray::length_offset(), |
| 2712 new Value(array), | 2712 new Value(array), |
| 2713 GrowableObjectArray::length_offset(), | |
| 2714 new Value(value), | 2713 new Value(value), |
| 2715 Type::ZoneHandle()); | 2714 kEmitStoreBarrier); |
| 2716 ReplaceCall(call, store); | 2715 ReplaceCall(call, store); |
| 2717 return true; | 2716 return true; |
| 2718 } | 2717 } |
| 2719 | 2718 |
| 2720 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || | 2719 if (((recognized_kind == MethodRecognizer::kStringBaseCodeUnitAt) || |
| 2721 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && | 2720 (recognized_kind == MethodRecognizer::kStringBaseCharAt)) && |
| 2722 (ic_data.NumberOfChecks() == 1) && | 2721 (ic_data.NumberOfChecks() == 1) && |
| 2723 ((class_ids[0] == kOneByteStringCid) || | 2722 ((class_ids[0] == kOneByteStringCid) || |
| 2724 (class_ids[0] == kTwoByteStringCid))) { | 2723 (class_ids[0] == kTwoByteStringCid))) { |
| 2725 return TryReplaceInstanceCallWithInline(call); | 2724 return TryReplaceInstanceCallWithInline(call); |
| (...skipping 2230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4956 field_ = load_field->field(); | 4955 field_ = load_field->field(); |
| 4957 } else { | 4956 } else { |
| 4958 kind_ = kVMField; | 4957 kind_ = kVMField; |
| 4959 offset_in_bytes_ = load_field->offset_in_bytes(); | 4958 offset_in_bytes_ = load_field->offset_in_bytes(); |
| 4960 } | 4959 } |
| 4961 *is_load = true; | 4960 *is_load = true; |
| 4962 break; | 4961 break; |
| 4963 } | 4962 } |
| 4964 | 4963 |
| 4965 case Instruction::kStoreInstanceField: { | 4964 case Instruction::kStoreInstanceField: { |
| 4966 StoreInstanceFieldInstr* store_instance_field = | 4965 StoreInstanceFieldInstr* store = |
| 4967 instr->AsStoreInstanceField(); | 4966 instr->AsStoreInstanceField(); |
| 4968 kind_ = kField; | 4967 representation_ = store->RequiredInputRepresentation( |
| 4969 representation_ = store_instance_field-> | 4968 StoreInstanceFieldInstr::kValuePos); |
| 4970 RequiredInputRepresentation(StoreInstanceFieldInstr::kValuePos); | 4969 instance_ = OriginalDefinition(store->instance()->definition()); |
| 4971 instance_ = | 4970 if (!store->field().IsNull()) { |
| 4972 OriginalDefinition(store_instance_field->instance()->definition()); | 4971 kind_ = kField; |
| 4973 field_ = &store_instance_field->field(); | 4972 field_ = &store->field(); |
| 4974 break; | 4973 } else { |
| 4975 } | 4974 kind_ = kVMField; |
| 4976 | 4975 offset_in_bytes_ = store->offset_in_bytes(); |
| 4977 case Instruction::kStoreVMField: { | 4976 } |
| 4978 StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField(); | |
| 4979 kind_ = kVMField; | |
| 4980 representation_ = store_vm_field-> | |
| 4981 RequiredInputRepresentation(StoreVMFieldInstr::kValuePos); | |
| 4982 instance_ = OriginalDefinition(store_vm_field->dest()->definition()); | |
| 4983 offset_in_bytes_ = store_vm_field->offset_in_bytes(); | |
| 4984 break; | 4977 break; |
| 4985 } | 4978 } |
| 4986 | 4979 |
| 4987 case Instruction::kLoadStaticField: | 4980 case Instruction::kLoadStaticField: |
| 4988 kind_ = kField; | 4981 kind_ = kField; |
| 4989 representation_ = instr->AsLoadStaticField()->representation(); | 4982 representation_ = instr->AsLoadStaticField()->representation(); |
| 4990 field_ = &instr->AsLoadStaticField()->StaticField(); | 4983 field_ = &instr->AsLoadStaticField()->StaticField(); |
| 4991 *is_load = true; | 4984 *is_load = true; |
| 4992 break; | 4985 break; |
| 4993 | 4986 |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5258 return Alias::ConstantIndex(GetIndexId(Smi::Cast(index).Value())); | 5251 return Alias::ConstantIndex(GetIndexId(Smi::Cast(index).Value())); |
| 5259 } | 5252 } |
| 5260 } | 5253 } |
| 5261 return Alias::Indexes(); | 5254 return Alias::Indexes(); |
| 5262 } | 5255 } |
| 5263 | 5256 |
| 5264 StoreInstanceFieldInstr* store_instance_field = | 5257 StoreInstanceFieldInstr* store_instance_field = |
| 5265 instr->AsStoreInstanceField(); | 5258 instr->AsStoreInstanceField(); |
| 5266 if (store_instance_field != NULL) { | 5259 if (store_instance_field != NULL) { |
| 5267 Definition* instance = store_instance_field->instance()->definition(); | 5260 Definition* instance = store_instance_field->instance()->definition(); |
| 5268 return Alias::Field(GetInstanceFieldId(instance, | 5261 if (!store_instance_field->field().IsNull()) { |
| 5269 store_instance_field->field())); | 5262 return Alias::Field(GetInstanceFieldId(instance, |
| 5270 } | 5263 store_instance_field->field())); |
| 5271 | 5264 } |
| 5272 StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField(); | 5265 return Alias::VMField(store_instance_field->offset_in_bytes()); |
| 5273 if (store_vm_field != NULL) { | |
| 5274 return Alias::VMField(store_vm_field->offset_in_bytes()); | |
| 5275 } | 5266 } |
| 5276 | 5267 |
| 5277 if (instr->IsStoreContext()) { | 5268 if (instr->IsStoreContext()) { |
| 5278 return Alias::CurrentContext(); | 5269 return Alias::CurrentContext(); |
| 5279 } | 5270 } |
| 5280 | 5271 |
| 5281 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); | 5272 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); |
| 5282 if (store_static_field != NULL) { | 5273 if (store_static_field != NULL) { |
| 5283 return Alias::Field(GetStaticFieldId(store_static_field->field())); | 5274 return Alias::Field(GetStaticFieldId(store_static_field->field())); |
| 5284 } | 5275 } |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5368 // this value is stored in a field, escapes to another function or | 5359 // this value is stored in a field, escapes to another function or |
| 5369 // participates in a phi. | 5360 // participates in a phi. |
| 5370 static bool CanBeAliased(AllocateObjectInstr* alloc) { | 5361 static bool CanBeAliased(AllocateObjectInstr* alloc) { |
| 5371 if (alloc->identity() == AllocateObjectInstr::kUnknown) { | 5362 if (alloc->identity() == AllocateObjectInstr::kUnknown) { |
| 5372 bool escapes = false; | 5363 bool escapes = false; |
| 5373 for (Value* use = alloc->input_use_list(); | 5364 for (Value* use = alloc->input_use_list(); |
| 5374 use != NULL; | 5365 use != NULL; |
| 5375 use = use->next_use()) { | 5366 use = use->next_use()) { |
| 5376 Instruction* instr = use->instruction(); | 5367 Instruction* instr = use->instruction(); |
| 5377 if (instr->IsPushArgument() || | 5368 if (instr->IsPushArgument() || |
| 5378 (instr->IsStoreVMField() | |
| 5379 && (use->use_index() != StoreVMFieldInstr::kObjectPos)) || | |
| 5380 (instr->IsStoreInstanceField() | 5369 (instr->IsStoreInstanceField() |
| 5381 && (use->use_index() != StoreInstanceFieldInstr::kInstancePos)) || | 5370 && (use->use_index() != StoreInstanceFieldInstr::kInstancePos)) || |
| 5382 instr->IsStoreStaticField() || | 5371 instr->IsStoreStaticField() || |
| 5383 instr->IsPhi() || | 5372 instr->IsPhi() || |
| 5384 instr->IsAssertAssignable() || | 5373 instr->IsAssertAssignable() || |
| 5385 instr->IsRedefinition()) { | 5374 instr->IsRedefinition()) { |
| 5386 escapes = true; | 5375 escapes = true; |
| 5387 break; | 5376 break; |
| 5388 } | 5377 } |
| 5389 } | 5378 } |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5570 static Definition* GetStoredValue(Instruction* instr) { | 5559 static Definition* GetStoredValue(Instruction* instr) { |
| 5571 if (instr->IsStoreIndexed()) { | 5560 if (instr->IsStoreIndexed()) { |
| 5572 return instr->AsStoreIndexed()->value()->definition(); | 5561 return instr->AsStoreIndexed()->value()->definition(); |
| 5573 } | 5562 } |
| 5574 | 5563 |
| 5575 StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField(); | 5564 StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField(); |
| 5576 if (store_instance_field != NULL) { | 5565 if (store_instance_field != NULL) { |
| 5577 return store_instance_field->value()->definition(); | 5566 return store_instance_field->value()->definition(); |
| 5578 } | 5567 } |
| 5579 | 5568 |
| 5580 StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField(); | |
| 5581 if (store_vm_field != NULL) { | |
| 5582 return store_vm_field->value()->definition(); | |
| 5583 } | |
| 5584 | |
| 5585 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); | 5569 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); |
| 5586 if (store_static_field != NULL) { | 5570 if (store_static_field != NULL) { |
| 5587 return store_static_field->value()->definition(); | 5571 return store_static_field->value()->definition(); |
| 5588 } | 5572 } |
| 5589 | 5573 |
| 5590 if (instr->IsStoreContext()) { | 5574 if (instr->IsStoreContext()) { |
| 5591 return instr->InputAt(0)->definition(); | 5575 return instr->InputAt(0)->definition(); |
| 5592 } | 5576 } |
| 5593 | 5577 |
| 5594 UNREACHABLE(); // Should only be called for supported store instructions. | 5578 UNREACHABLE(); // Should only be called for supported store instructions. |
| (...skipping 1725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7320 SetValue(instr, Smi::ZoneHandle( | 7304 SetValue(instr, Smi::ZoneHandle( |
| 7321 Smi::New(Array::Cast(constant->value()).Length()))); | 7305 Smi::New(Array::Cast(constant->value()).Length()))); |
| 7322 return; | 7306 return; |
| 7323 } | 7307 } |
| 7324 } | 7308 } |
| 7325 } | 7309 } |
| 7326 SetValue(instr, non_constant_); | 7310 SetValue(instr, non_constant_); |
| 7327 } | 7311 } |
| 7328 | 7312 |
| 7329 | 7313 |
| 7330 void ConstantPropagator::VisitStoreVMField(StoreVMFieldInstr* instr) { | |
| 7331 SetValue(instr, instr->value()->definition()->constant_value()); | |
| 7332 } | |
| 7333 | |
| 7334 | |
| 7335 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { | 7314 void ConstantPropagator::VisitInstantiateType(InstantiateTypeInstr* instr) { |
| 7336 const Object& object = | 7315 const Object& object = |
| 7337 instr->instantiator()->definition()->constant_value(); | 7316 instr->instantiator()->definition()->constant_value(); |
| 7338 if (IsNonConstant(object)) { | 7317 if (IsNonConstant(object)) { |
| 7339 SetValue(instr, non_constant_); | 7318 SetValue(instr, non_constant_); |
| 7340 return; | 7319 return; |
| 7341 } | 7320 } |
| 7342 if (IsConstant(object)) { | 7321 if (IsConstant(object)) { |
| 7343 if (instr->type().IsTypeParameter()) { | 7322 if (instr->type().IsTypeParameter()) { |
| 7344 if (object.IsNull()) { | 7323 if (object.IsNull()) { |
| (...skipping 635 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7980 // Replace constant-valued instructions without observable side | 7959 // Replace constant-valued instructions without observable side |
| 7981 // effects. Do this for smis only to avoid having to copy other | 7960 // effects. Do this for smis only to avoid having to copy other |
| 7982 // objects into the heap's old generation. | 7961 // objects into the heap's old generation. |
| 7983 if ((defn != NULL) && | 7962 if ((defn != NULL) && |
| 7984 IsConstant(defn->constant_value()) && | 7963 IsConstant(defn->constant_value()) && |
| 7985 (defn->constant_value().IsSmi() || defn->constant_value().IsOld()) && | 7964 (defn->constant_value().IsSmi() || defn->constant_value().IsOld()) && |
| 7986 !defn->IsConstant() && | 7965 !defn->IsConstant() && |
| 7987 !defn->IsPushArgument() && | 7966 !defn->IsPushArgument() && |
| 7988 !defn->IsStoreIndexed() && | 7967 !defn->IsStoreIndexed() && |
| 7989 !defn->IsStoreInstanceField() && | 7968 !defn->IsStoreInstanceField() && |
| 7990 !defn->IsStoreStaticField() && | 7969 !defn->IsStoreStaticField()) { |
| 7991 !defn->IsStoreVMField()) { | |
| 7992 if (FLAG_trace_constant_propagation) { | 7970 if (FLAG_trace_constant_propagation) { |
| 7993 OS::Print("Constant v%" Pd " = %s\n", | 7971 OS::Print("Constant v%" Pd " = %s\n", |
| 7994 defn->ssa_temp_index(), | 7972 defn->ssa_temp_index(), |
| 7995 defn->constant_value().ToCString()); | 7973 defn->constant_value().ToCString()); |
| 7996 } | 7974 } |
| 7997 ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); | 7975 ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); |
| 7998 defn->ReplaceUsesWith(constant); | 7976 defn->ReplaceUsesWith(constant); |
| 7999 i.RemoveCurrentFromGraph(); | 7977 i.RemoveCurrentFromGraph(); |
| 8000 } | 7978 } |
| 8001 } | 7979 } |
| (...skipping 569 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8571 AllocateObjectInstr* alloc, | 8549 AllocateObjectInstr* alloc, |
| 8572 const Class& cls, | 8550 const Class& cls, |
| 8573 const ZoneGrowableArray<const Field*>& fields) { | 8551 const ZoneGrowableArray<const Field*>& fields) { |
| 8574 ZoneGrowableArray<Value*>* values = | 8552 ZoneGrowableArray<Value*>* values = |
| 8575 new ZoneGrowableArray<Value*>(fields.length()); | 8553 new ZoneGrowableArray<Value*>(fields.length()); |
| 8576 | 8554 |
| 8577 // Insert load instruction for every field. | 8555 // Insert load instruction for every field. |
| 8578 for (intptr_t i = 0; i < fields.length(); i++) { | 8556 for (intptr_t i = 0; i < fields.length(); i++) { |
| 8579 const Field* field = fields[i]; | 8557 const Field* field = fields[i]; |
| 8580 LoadFieldInstr* load = new LoadFieldInstr(new Value(alloc), | 8558 LoadFieldInstr* load = new LoadFieldInstr(new Value(alloc), |
| 8581 field->Offset(), | 8559 field, |
| 8582 AbstractType::ZoneHandle()); | 8560 AbstractType::ZoneHandle()); |
| 8583 load->set_field(field); | |
| 8584 flow_graph_->InsertBefore( | 8561 flow_graph_->InsertBefore( |
| 8585 exit, load, NULL, Definition::kValue); | 8562 exit, load, NULL, Definition::kValue); |
| 8586 values->Add(new Value(load)); | 8563 values->Add(new Value(load)); |
| 8587 } | 8564 } |
| 8588 | 8565 |
| 8589 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, fields, values); | 8566 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, fields, values); |
| 8590 flow_graph_->InsertBefore(exit, mat, NULL, Definition::kValue); | 8567 flow_graph_->InsertBefore(exit, mat, NULL, Definition::kValue); |
| 8591 | 8568 |
| 8592 // Replace all mentions of this allocation with a newly inserted | 8569 // Replace all mentions of this allocation with a newly inserted |
| 8593 // MaterializeObject instruction. | 8570 // MaterializeObject instruction. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8645 } | 8622 } |
| 8646 | 8623 |
| 8647 // Insert materializations at environment uses. | 8624 // Insert materializations at environment uses. |
| 8648 for (intptr_t i = 0; i < exits.length(); i++) { | 8625 for (intptr_t i = 0; i < exits.length(); i++) { |
| 8649 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 8626 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 8650 } | 8627 } |
| 8651 } | 8628 } |
| 8652 | 8629 |
| 8653 | 8630 |
| 8654 } // namespace dart | 8631 } // namespace dart |
| OLD | NEW |