summaryrefslogtreecommitdiffstats
path: root/compiler/optimizing/code_generator_arm.cc
diff options
context:
space:
mode:
authorNicolas Geoffray <ngeoffray@google.com>2014-11-12 18:08:09 +0000
committerNicolas Geoffray <ngeoffray@google.com>2014-11-14 13:45:02 +0000
commitaf07bc121121d7bd7e8329c55dfe24782207b561 (patch)
tree51e93225aa77c3949a63104f8d48e4b6f6fb2b5b /compiler/optimizing/code_generator_arm.cc
parentd0d805bad888857fe974142cbf3292b9747daae3 (diff)
downloadart-af07bc121121d7bd7e8329c55dfe24782207b561.tar.gz
art-af07bc121121d7bd7e8329c55dfe24782207b561.tar.bz2
art-af07bc121121d7bd7e8329c55dfe24782207b561.zip
Minor object store optimizations.
- Avoid emitting write barrier when the value is null. - Do not do a typecheck on an arraystore when storing something that was loaded from the same array. Change-Id: I902492928692e4553b5af0fc99cce3c2186c442a
Diffstat (limited to 'compiler/optimizing/code_generator_arm.cc')
-rw-r--r--compiler/optimizing/code_generator_arm.cc67
1 files changed, 45 insertions, 22 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 6f5a3cbc15..9745edaf2a 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1918,11 +1918,12 @@ void InstructionCodeGeneratorARM::VisitPhi(HPhi* instruction) {
void LocationsBuilderARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
- bool is_object_type = instruction->GetFieldType() == Primitive::kPrimNot;
+ bool needs_write_barrier =
+ CodeGenerator::StoreNeedsWriteBarrier(instruction->GetFieldType(), instruction->GetValue());
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
// Temporary registers for the write barrier.
- if (is_object_type) {
+ if (needs_write_barrier) {
locations->AddTemp(Location::RequiresRegister());
locations->AddTemp(Location::RequiresRegister());
}
@@ -1953,7 +1954,7 @@ void InstructionCodeGeneratorARM::VisitInstanceFieldSet(HInstanceFieldSet* instr
case Primitive::kPrimNot: {
Register value = locations->InAt(1).As<Register>();
__ StoreToOffset(kStoreWord, value, obj, offset);
- if (field_type == Primitive::kPrimNot) {
+ if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->GetValue())) {
Register temp = locations->GetTemp(0).As<Register>();
Register card = locations->GetTemp(1).As<Register>();
codegen_->MarkGCCard(temp, card, obj, value);
@@ -2186,10 +2187,14 @@ void InstructionCodeGeneratorARM::VisitArrayGet(HArrayGet* instruction) {
void LocationsBuilderARM::VisitArraySet(HArraySet* instruction) {
Primitive::Type value_type = instruction->GetComponentType();
- bool is_object = value_type == Primitive::kPrimNot;
+
+ bool needs_write_barrier =
+ CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
+ bool needs_runtime_call = instruction->NeedsTypeCheck();
+
LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(
- instruction, is_object ? LocationSummary::kCall : LocationSummary::kNoCall);
- if (is_object) {
+ instruction, needs_runtime_call ? LocationSummary::kCall : LocationSummary::kNoCall);
+ if (needs_runtime_call) {
InvokeRuntimeCallingConvention calling_convention;
locations->SetInAt(0, Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
locations->SetInAt(1, Location::RegisterLocation(calling_convention.GetRegisterAt(1)));
@@ -2198,6 +2203,12 @@ void LocationsBuilderARM::VisitArraySet(HArraySet* instruction) {
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RegisterOrConstant(instruction->InputAt(1)));
locations->SetInAt(2, Location::RequiresRegister());
+
+ if (needs_write_barrier) {
+ // Temporary registers for the write barrier.
+ locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresRegister());
+ }
}
}
@@ -2206,6 +2217,9 @@ void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) {
Register obj = locations->InAt(0).As<Register>();
Location index = locations->InAt(1);
Primitive::Type value_type = instruction->GetComponentType();
+ bool needs_runtime_call = locations->WillCall();
+ bool needs_write_barrier =
+ CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue());
switch (value_type) {
case Primitive::kPrimBoolean:
@@ -2236,24 +2250,32 @@ void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) {
break;
}
- case Primitive::kPrimInt: {
- uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
- Register value = locations->InAt(2).As<Register>();
- if (index.IsConstant()) {
- size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
- __ StoreToOffset(kStoreWord, value, obj, offset);
+ case Primitive::kPrimInt:
+ case Primitive::kPrimNot: {
+ if (!needs_runtime_call) {
+ uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
+ Register value = locations->InAt(2).As<Register>();
+ if (index.IsConstant()) {
+ size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
+ __ StoreToOffset(kStoreWord, value, obj, offset);
+ } else {
+ DCHECK(index.IsRegister()) << index;
+ __ add(IP, obj, ShifterOperand(index.As<Register>(), LSL, TIMES_4));
+ __ StoreToOffset(kStoreWord, value, IP, data_offset);
+ }
+ if (needs_write_barrier) {
+ DCHECK_EQ(value_type, Primitive::kPrimNot);
+ Register temp = locations->GetTemp(0).As<Register>();
+ Register card = locations->GetTemp(1).As<Register>();
+ codegen_->MarkGCCard(temp, card, obj, value);
+ }
} else {
- __ add(IP, obj, ShifterOperand(index.As<Register>(), LSL, TIMES_4));
- __ StoreToOffset(kStoreWord, value, IP, data_offset);
+ DCHECK_EQ(value_type, Primitive::kPrimNot);
+ codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pAputObject), instruction, instruction->GetDexPc());
}
break;
}
- case Primitive::kPrimNot: {
- codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pAputObject), instruction, instruction->GetDexPc());
- break;
- }
-
case Primitive::kPrimLong: {
uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
Location value = locations->InAt(2);
@@ -2602,11 +2624,12 @@ void InstructionCodeGeneratorARM::VisitStaticFieldGet(HStaticFieldGet* instructi
void LocationsBuilderARM::VisitStaticFieldSet(HStaticFieldSet* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
- bool is_object_type = instruction->GetFieldType() == Primitive::kPrimNot;
+ bool needs_write_barrier =
+ CodeGenerator::StoreNeedsWriteBarrier(instruction->GetFieldType(), instruction->GetValue());
locations->SetInAt(0, Location::RequiresRegister());
locations->SetInAt(1, Location::RequiresRegister());
// Temporary registers for the write barrier.
- if (is_object_type) {
+ if (needs_write_barrier) {
locations->AddTemp(Location::RequiresRegister());
locations->AddTemp(Location::RequiresRegister());
}
@@ -2637,7 +2660,7 @@ void InstructionCodeGeneratorARM::VisitStaticFieldSet(HStaticFieldSet* instructi
case Primitive::kPrimNot: {
Register value = locations->InAt(1).As<Register>();
__ StoreToOffset(kStoreWord, value, cls, offset);
- if (field_type == Primitive::kPrimNot) {
+ if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->GetValue())) {
Register temp = locations->GetTemp(0).As<Register>();
Register card = locations->GetTemp(1).As<Register>();
codegen_->MarkGCCard(temp, card, cls, value);