diff options
author | Alexey Frunze <Alexey.Frunze@imgtec.com> | 2016-08-20 01:55:47 -0700 |
---|---|---|
committer | Alexey Frunze <Alexey.Frunze@imgtec.com> | 2016-08-24 17:27:35 -0700 |
commit | 2923db7314da613d50c9e6e44f38bb8d3e1c49f0 (patch) | |
tree | 063590a45f9f384872b8fa14f9f0bd2f014f0d66 /compiler/optimizing/code_generator_mips.cc | |
parent | 897b8f5da90b38b030826273f4c9bd8fbc32759e (diff) |
MIPS32: Refactor implicit null checks in array/field get/set.
Rationale: on MIPS32 64-bit loads and stores may be performed
as pairs of 32-bit loads/stores. Implicit null checks must be
associated with the first 32-bit load/store in a pair and not
the last. This change ensures proper association of said checks
(a few were done after the last 32-bit load/store in a pair)
and lays ground for further improvements in array/field get/set.
Test: booted MIPS32 in QEMU
Test: test-art-host-gtest
Test: test-art-target-run-test-optimizing in QEMU
Change-Id: I3674947c00bb17930790a7a47c9b7aadc0c030b8
Diffstat (limited to 'compiler/optimizing/code_generator_mips.cc')
-rw-r--r-- | compiler/optimizing/code_generator_mips.cc | 108 |
1 files changed, 45 insertions, 63 deletions
diff --git a/compiler/optimizing/code_generator_mips.cc b/compiler/optimizing/code_generator_mips.cc index a7fbc84340..8a2f90d541 100644 --- a/compiler/optimizing/code_generator_mips.cc +++ b/compiler/optimizing/code_generator_mips.cc @@ -1833,11 +1833,19 @@ void LocationsBuilderMIPS::VisitArrayGet(HArrayGet* instruction) { } } +auto InstructionCodeGeneratorMIPS::GetImplicitNullChecker(HInstruction* instruction) { + auto null_checker = [this, instruction]() { + this->codegen_->MaybeRecordImplicitNullCheck(instruction); + }; + return null_checker; +} + void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { LocationSummary* locations = instruction->GetLocations(); Register obj = locations->InAt(0).AsRegister<Register>(); Location index = locations->InAt(1); uint32_t data_offset = CodeGenerator::GetArrayDataOffset(instruction); + auto null_checker = GetImplicitNullChecker(instruction); Primitive::Type type = instruction->GetType(); switch (type) { @@ -1846,10 +1854,10 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset; - __ LoadFromOffset(kLoadUnsignedByte, out, obj, offset); + __ LoadFromOffset(kLoadUnsignedByte, out, obj, offset, null_checker); } else { __ Addu(TMP, obj, index.AsRegister<Register>()); - __ LoadFromOffset(kLoadUnsignedByte, out, TMP, data_offset); + __ LoadFromOffset(kLoadUnsignedByte, out, TMP, data_offset, null_checker); } break; } @@ -1859,10 +1867,10 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset; - __ LoadFromOffset(kLoadSignedByte, out, obj, offset); + __ LoadFromOffset(kLoadSignedByte, out, obj, offset, null_checker); } else { __ Addu(TMP, obj, index.AsRegister<Register>()); - __ LoadFromOffset(kLoadSignedByte, out, TMP, data_offset); + __ LoadFromOffset(kLoadSignedByte, out, TMP, data_offset, null_checker); } break; } @@ -1872,11 +1880,11 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset; - __ LoadFromOffset(kLoadSignedHalfword, out, obj, offset); + __ LoadFromOffset(kLoadSignedHalfword, out, obj, offset, null_checker); } else { __ Sll(TMP, index.AsRegister<Register>(), TIMES_2); __ Addu(TMP, obj, TMP); - __ LoadFromOffset(kLoadSignedHalfword, out, TMP, data_offset); + __ LoadFromOffset(kLoadSignedHalfword, out, TMP, data_offset, null_checker); } break; } @@ -1886,11 +1894,11 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset; - __ LoadFromOffset(kLoadUnsignedHalfword, out, obj, offset); + __ LoadFromOffset(kLoadUnsignedHalfword, out, obj, offset, null_checker); } else { __ Sll(TMP, index.AsRegister<Register>(), TIMES_2); __ Addu(TMP, obj, TMP); - __ LoadFromOffset(kLoadUnsignedHalfword, out, TMP, data_offset); + __ LoadFromOffset(kLoadUnsignedHalfword, out, TMP, data_offset, null_checker); } break; } @@ -1902,11 +1910,11 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset; - __ LoadFromOffset(kLoadWord, out, obj, offset); + __ LoadFromOffset(kLoadWord, out, obj, offset, null_checker); } else { __ Sll(TMP, index.AsRegister<Register>(), TIMES_4); __ Addu(TMP, obj, TMP); - __ LoadFromOffset(kLoadWord, out, TMP, data_offset); + __ LoadFromOffset(kLoadWord, out, TMP, data_offset, null_checker); } break; } @@ -1916,11 +1924,11 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset; - __ LoadFromOffset(kLoadDoubleword, out, obj, offset); + __ LoadFromOffset(kLoadDoubleword, out, obj, offset, null_checker); } else { __ Sll(TMP, index.AsRegister<Register>(), TIMES_8); __ Addu(TMP, obj, TMP); - __ LoadFromOffset(kLoadDoubleword, out, TMP, data_offset); + __ LoadFromOffset(kLoadDoubleword, out, TMP, data_offset, null_checker); } break; } @@ -1930,11 +1938,11 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset; - __ LoadSFromOffset(out, obj, offset); + __ LoadSFromOffset(out, obj, offset, null_checker); } else { __ Sll(TMP, index.AsRegister<Register>(), TIMES_4); __ Addu(TMP, obj, TMP); - __ LoadSFromOffset(out, TMP, data_offset); + __ LoadSFromOffset(out, TMP, data_offset, null_checker); } break; } @@ -1944,11 +1952,11 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset; - __ LoadDFromOffset(out, obj, offset); + __ LoadDFromOffset(out, obj, offset, null_checker); } else { __ Sll(TMP, index.AsRegister<Register>(), TIMES_8); __ Addu(TMP, obj, TMP); - __ LoadDFromOffset(out, TMP, data_offset); + __ LoadDFromOffset(out, TMP, data_offset, null_checker); } break; } @@ -1957,7 +1965,6 @@ void InstructionCodeGeneratorMIPS::VisitArrayGet(HArrayGet* instruction) { LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); } - codegen_->MaybeRecordImplicitNullCheck(instruction); } void LocationsBuilderMIPS::VisitArrayLength(HArrayLength* instruction) { @@ -2004,6 +2011,7 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { bool needs_runtime_call = locations->WillCall(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); + auto null_checker = GetImplicitNullChecker(instruction); switch (value_type) { case Primitive::kPrimBoolean: @@ -2013,10 +2021,10 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_1) + data_offset; - __ StoreToOffset(kStoreByte, value, obj, offset); + __ StoreToOffset(kStoreByte, value, obj, offset, null_checker); } else { __ Addu(TMP, obj, index.AsRegister<Register>()); - __ StoreToOffset(kStoreByte, value, TMP, data_offset); + __ StoreToOffset(kStoreByte, value, TMP, data_offset, null_checker); } break; } @@ -2028,11 +2036,11 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_2) + data_offset; - __ StoreToOffset(kStoreHalfword, value, obj, offset); + __ StoreToOffset(kStoreHalfword, value, obj, offset, null_checker); } else { __ Sll(TMP, index.AsRegister<Register>(), TIMES_2); __ Addu(TMP, obj, TMP); - __ StoreToOffset(kStoreHalfword, value, TMP, data_offset); + __ StoreToOffset(kStoreHalfword, value, TMP, data_offset, null_checker); } break; } @@ -2045,14 +2053,13 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset; - __ StoreToOffset(kStoreWord, value, obj, offset); + __ StoreToOffset(kStoreWord, value, obj, offset, null_checker); } else { DCHECK(index.IsRegister()) << index; __ Sll(TMP, index.AsRegister<Register>(), TIMES_4); __ Addu(TMP, obj, TMP); - __ StoreToOffset(kStoreWord, value, TMP, data_offset); + __ StoreToOffset(kStoreWord, value, TMP, data_offset, null_checker); } - codegen_->MaybeRecordImplicitNullCheck(instruction); if (needs_write_barrier) { DCHECK_EQ(value_type, Primitive::kPrimNot); codegen_->MarkGCCard(obj, value); @@ -2075,11 +2082,11 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset; - __ StoreToOffset(kStoreDoubleword, value, obj, offset); + __ StoreToOffset(kStoreDoubleword, value, obj, offset, null_checker); } else { __ Sll(TMP, index.AsRegister<Register>(), TIMES_8); __ Addu(TMP, obj, TMP); - __ StoreToOffset(kStoreDoubleword, value, TMP, data_offset); + __ StoreToOffset(kStoreDoubleword, value, TMP, data_offset, null_checker); } break; } @@ -2091,11 +2098,11 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset; - __ StoreSToOffset(value, obj, offset); + __ StoreSToOffset(value, obj, offset, null_checker); } else { __ Sll(TMP, index.AsRegister<Register>(), TIMES_4); __ Addu(TMP, obj, TMP); - __ StoreSToOffset(value, TMP, data_offset); + __ StoreSToOffset(value, TMP, data_offset, null_checker); } break; } @@ -2107,11 +2114,11 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset; - __ StoreDToOffset(value, obj, offset); + __ StoreDToOffset(value, obj, offset, null_checker); } else { __ Sll(TMP, index.AsRegister<Register>(), TIMES_8); __ Addu(TMP, obj, TMP); - __ StoreDToOffset(value, TMP, data_offset); + __ StoreDToOffset(value, TMP, data_offset, null_checker); } break; } @@ -2120,11 +2127,6 @@ void InstructionCodeGeneratorMIPS::VisitArraySet(HArraySet* instruction) { LOG(FATAL) << "Unreachable type " << instruction->GetType(); UNREACHABLE(); } - - // Ints and objects are handled in the switch. - if (value_type != Primitive::kPrimInt && value_type != Primitive::kPrimNot) { - codegen_->MaybeRecordImplicitNullCheck(instruction); - } } void LocationsBuilderMIPS::VisitBoundsCheck(HBoundsCheck* instruction) { @@ -3589,6 +3591,7 @@ void InstructionCodeGeneratorMIPS::HandleFieldGet(HInstruction* instruction, LoadOperandType load_type = kLoadUnsignedByte; bool is_volatile = field_info.IsVolatile(); uint32_t offset = field_info.GetFieldOffset().Uint32Value(); + auto null_checker = GetImplicitNullChecker(instruction); switch (type) { case Primitive::kPrimBoolean: @@ -3654,34 +3657,20 @@ void InstructionCodeGeneratorMIPS::HandleFieldGet(HInstruction* instruction, if (type == Primitive::kPrimLong) { DCHECK(locations->Out().IsRegisterPair()); dst = locations->Out().AsRegisterPairLow<Register>(); - Register dst_high = locations->Out().AsRegisterPairHigh<Register>(); - if (obj == dst) { - __ LoadFromOffset(kLoadWord, dst_high, obj, offset + kMipsWordSize); - codegen_->MaybeRecordImplicitNullCheck(instruction); - __ LoadFromOffset(kLoadWord, dst, obj, offset); - } else { - __ LoadFromOffset(kLoadWord, dst, obj, offset); - codegen_->MaybeRecordImplicitNullCheck(instruction); - __ LoadFromOffset(kLoadWord, dst_high, obj, offset + kMipsWordSize); - } } else { DCHECK(locations->Out().IsRegister()); dst = locations->Out().AsRegister<Register>(); - __ LoadFromOffset(load_type, dst, obj, offset); } + __ LoadFromOffset(load_type, dst, obj, offset, null_checker); } else { DCHECK(locations->Out().IsFpuRegister()); FRegister dst = locations->Out().AsFpuRegister<FRegister>(); if (type == Primitive::kPrimFloat) { - __ LoadSFromOffset(dst, obj, offset); + __ LoadSFromOffset(dst, obj, offset, null_checker); } else { - __ LoadDFromOffset(dst, obj, offset); + __ LoadDFromOffset(dst, obj, offset, null_checker); } } - // Longs are handled earlier. - if (type != Primitive::kPrimLong) { - codegen_->MaybeRecordImplicitNullCheck(instruction); - } } if (is_volatile) { @@ -3729,6 +3718,7 @@ void InstructionCodeGeneratorMIPS::HandleFieldSet(HInstruction* instruction, StoreOperandType store_type = kStoreByte; bool is_volatile = field_info.IsVolatile(); uint32_t offset = field_info.GetFieldOffset().Uint32Value(); + auto null_checker = GetImplicitNullChecker(instruction); switch (type) { case Primitive::kPrimBoolean: @@ -3800,28 +3790,20 @@ void InstructionCodeGeneratorMIPS::HandleFieldSet(HInstruction* instruction, if (type == Primitive::kPrimLong) { DCHECK(locations->InAt(1).IsRegisterPair()); src = locations->InAt(1).AsRegisterPairLow<Register>(); - Register src_high = locations->InAt(1).AsRegisterPairHigh<Register>(); - __ StoreToOffset(kStoreWord, src, obj, offset); - codegen_->MaybeRecordImplicitNullCheck(instruction); - __ StoreToOffset(kStoreWord, src_high, obj, offset + kMipsWordSize); } else { DCHECK(locations->InAt(1).IsRegister()); src = locations->InAt(1).AsRegister<Register>(); - __ StoreToOffset(store_type, src, obj, offset); } + __ StoreToOffset(store_type, src, obj, offset, null_checker); } else { DCHECK(locations->InAt(1).IsFpuRegister()); FRegister src = locations->InAt(1).AsFpuRegister<FRegister>(); if (type == Primitive::kPrimFloat) { - __ StoreSToOffset(src, obj, offset); + __ StoreSToOffset(src, obj, offset, null_checker); } else { - __ StoreDToOffset(src, obj, offset); + __ StoreDToOffset(src, obj, offset, null_checker); } } - // Longs are handled earlier. - if (type != Primitive::kPrimLong) { - codegen_->MaybeRecordImplicitNullCheck(instruction); - } } // TODO: memory barriers? |