summaryrefslogtreecommitdiff
path: root/compiler/optimizing/code_generator_arm.cc
diff options
context:
space:
mode:
authorCalin Juravle <calin@google.com>2015-01-12 18:45:46 +0000
committerCalin Juravle <calin@google.com>2015-01-21 14:26:35 +0000
commit77520bca97ec44e3758510cebd0f20e3bb4584ea (patch)
tree2e3be6fdc182e5cf5ae390019457af5e9c1ed242 /compiler/optimizing/code_generator_arm.cc
parent4d2c611bf17ff309abfa152e56c0b98a21ec8787 (diff)
Record implicit null checks at the actual invoke time.
ImplicitNullChecks are recorded only for instructions directly (see NB below) preceeded by NullChecks in the graph. This way we avoid recording redundant safepoints and minimize the code size increase. NB: ParallalelMoves might be inserted by the register allocator between the NullChecks and their uses. These modify the environment and the correct action would be to reverse their modification. This will be addressed in a follow-up CL. Change-Id: Ie50006e5a4bd22932dcf11348f5a655d253cd898
Diffstat (limited to 'compiler/optimizing/code_generator_arm.cc')
-rw-r--r--compiler/optimizing/code_generator_arm.cc68
1 files changed, 46 insertions, 22 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 07c84bcc01..980de040fa 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1226,6 +1226,7 @@ void InstructionCodeGeneratorARM::VisitInvokeVirtual(HInvokeVirtual* invoke) {
} else {
__ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
}
+ codegen_->MaybeRecordImplicitNullCheck(invoke);
// temp = temp->GetMethodAt(method_offset);
uint32_t entry_point = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
kArmWordSize).Int32Value();
@@ -1264,6 +1265,7 @@ void InstructionCodeGeneratorARM::VisitInvokeInterface(HInvokeInterface* invoke)
} else {
__ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
}
+ codegen_->MaybeRecordImplicitNullCheck(invoke);
// temp = temp->GetImtEntryAt(method_offset);
uint32_t entry_point = mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset(
kArmWordSize).Int32Value();
@@ -2579,7 +2581,8 @@ void InstructionCodeGeneratorARM::GenerateWideAtomicStore(Register addr,
Register value_lo,
Register value_hi,
Register temp1,
- Register temp2) {
+ Register temp2,
+ HInstruction* instruction) {
Label fail;
if (offset != 0) {
__ LoadImmediate(temp1, offset);
@@ -2590,6 +2593,7 @@ void InstructionCodeGeneratorARM::GenerateWideAtomicStore(Register addr,
// We need a load followed by store. (The address used in a STREX instruction must
// be the same as the address in the most recently executed LDREX instruction.)
__ ldrexd(temp1, temp2, addr);
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
__ strexd(temp1, value_lo, value_hi, addr);
__ cmp(temp1, ShifterOperand(0));
__ b(&fail, NE);
@@ -2664,13 +2668,7 @@ void InstructionCodeGeneratorARM::HandleFieldSet(HInstruction* instruction,
case Primitive::kPrimInt:
case Primitive::kPrimNot: {
- Register value_reg = value.AsRegister<Register>();
- __ StoreToOffset(kStoreWord, value_reg, base, offset);
- if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
- Register temp = locations->GetTemp(0).AsRegister<Register>();
- Register card = locations->GetTemp(1).AsRegister<Register>();
- codegen_->MarkGCCard(temp, card, base, value_reg);
- }
+ __ StoreToOffset(kStoreWord, value.AsRegister<Register>(), base, offset);
break;
}
@@ -2680,9 +2678,11 @@ void InstructionCodeGeneratorARM::HandleFieldSet(HInstruction* instruction,
value.AsRegisterPairLow<Register>(),
value.AsRegisterPairHigh<Register>(),
locations->GetTemp(0).AsRegister<Register>(),
- locations->GetTemp(1).AsRegister<Register>());
+ locations->GetTemp(1).AsRegister<Register>(),
+ instruction);
} else {
__ StoreToOffset(kStoreWordPair, value.AsRegisterPairLow<Register>(), base, offset);
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
}
break;
}
@@ -2704,9 +2704,11 @@ void InstructionCodeGeneratorARM::HandleFieldSet(HInstruction* instruction,
value_reg_lo,
value_reg_hi,
locations->GetTemp(2).AsRegister<Register>(),
- locations->GetTemp(3).AsRegister<Register>());
+ locations->GetTemp(3).AsRegister<Register>(),
+ instruction);
} else {
__ StoreDToOffset(value_reg, base, offset);
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
}
break;
}
@@ -2716,6 +2718,17 @@ void InstructionCodeGeneratorARM::HandleFieldSet(HInstruction* instruction,
UNREACHABLE();
}
+ // Longs and doubles are handled in the switch.
+ if (field_type != Primitive::kPrimLong && field_type != Primitive::kPrimDouble) {
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
+ }
+
+ if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) {
+ Register temp = locations->GetTemp(0).AsRegister<Register>();
+ Register card = locations->GetTemp(1).AsRegister<Register>();
+ codegen_->MarkGCCard(temp, card, base, value.AsRegister<Register>());
+ }
+
if (is_volatile) {
GenerateMemoryBarrier(MemBarrierKind::kAnyAny);
}
@@ -2804,9 +2817,11 @@ void InstructionCodeGeneratorARM::HandleFieldGet(HInstruction* instruction,
Register lo = locations->GetTemp(0).AsRegister<Register>();
Register hi = locations->GetTemp(1).AsRegister<Register>();
GenerateWideAtomicLoad(base, offset, lo, hi);
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
__ vmovdrr(out_reg, lo, hi);
} else {
__ LoadDFromOffset(out_reg, base, offset);
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
}
break;
}
@@ -2816,6 +2831,11 @@ void InstructionCodeGeneratorARM::HandleFieldGet(HInstruction* instruction,
UNREACHABLE();
}
+ // Doubles are handled in the switch.
+ if (field_type != Primitive::kPrimDouble) {
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
+ }
+
if (is_volatile) {
GenerateMemoryBarrier(MemBarrierKind::kLoadAny);
}
@@ -2856,17 +2876,18 @@ void InstructionCodeGeneratorARM::VisitStaticFieldSet(HStaticFieldSet* instructi
void LocationsBuilderARM::VisitNullCheck(HNullCheck* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
- Location loc = codegen_->GetCompilerOptions().GetImplicitNullChecks()
- ? Location::RequiresRegister()
- : Location::RegisterOrConstant(instruction->InputAt(0));
- locations->SetInAt(0, loc);
+ locations->SetInAt(0, Location::RequiresRegister());
if (instruction->HasUses()) {
locations->SetOut(Location::SameAsFirstInput());
}
}
void InstructionCodeGeneratorARM::GenerateImplicitNullCheck(HNullCheck* instruction) {
+ if (codegen_->CanMoveNullCheckToUser(instruction)) {
+ return;
+ }
Location obj = instruction->GetLocations()->InAt(0);
+
__ LoadFromOffset(kLoadWord, IP, obj.AsRegister<Register>(), 0);
codegen_->RecordPcInfo(instruction, instruction->GetDexPc());
}
@@ -2878,14 +2899,8 @@ void InstructionCodeGeneratorARM::GenerateExplicitNullCheck(HNullCheck* instruct
LocationSummary* locations = instruction->GetLocations();
Location obj = locations->InAt(0);
- if (obj.IsRegister()) {
- __ cmp(obj.AsRegister<Register>(), ShifterOperand(0));
- __ b(slow_path->GetEntryLabel(), EQ);
- } else {
- DCHECK(obj.IsConstant()) << obj;
- DCHECK_EQ(obj.GetConstant()->AsIntConstant()->GetValue(), 0);
- __ b(slow_path->GetEntryLabel());
- }
+ __ cmp(obj.AsRegister<Register>(), ShifterOperand(0));
+ __ b(slow_path->GetEntryLabel(), EQ);
}
void InstructionCodeGeneratorARM::VisitNullCheck(HNullCheck* instruction) {
@@ -3028,6 +3043,7 @@ void InstructionCodeGeneratorARM::VisitArrayGet(HArrayGet* instruction) {
LOG(FATAL) << "Unreachable type " << instruction->GetType();
UNREACHABLE();
}
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
}
void LocationsBuilderARM::VisitArraySet(HArraySet* instruction) {
@@ -3111,6 +3127,7 @@ void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) {
__ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_4));
__ StoreToOffset(kStoreWord, value, IP, data_offset);
}
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
if (needs_write_barrier) {
DCHECK_EQ(value_type, Primitive::kPrimNot);
Register temp = locations->GetTemp(0).AsRegister<Register>();
@@ -3165,6 +3182,7 @@ void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) {
__ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_8));
__ StoreDToOffset(FromLowSToD(value.AsFpuRegisterPairLow<SRegister>()), IP, data_offset);
}
+
break;
}
@@ -3172,6 +3190,11 @@ void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) {
LOG(FATAL) << "Unreachable type " << value_type;
UNREACHABLE();
}
+
+ // Ints and objects are handled in the switch.
+ if (value_type != Primitive::kPrimInt && value_type != Primitive::kPrimNot) {
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
+ }
}
void LocationsBuilderARM::VisitArrayLength(HArrayLength* instruction) {
@@ -3187,6 +3210,7 @@ void InstructionCodeGeneratorARM::VisitArrayLength(HArrayLength* instruction) {
Register obj = locations->InAt(0).AsRegister<Register>();
Register out = locations->Out().AsRegister<Register>();
__ LoadFromOffset(kLoadWord, out, obj, offset);
+ codegen_->MaybeRecordImplicitNullCheck(instruction);
}
void LocationsBuilderARM::VisitBoundsCheck(HBoundsCheck* instruction) {