diff options
Diffstat (limited to 'compiler/optimizing/code_generator_arm.cc')
-rw-r--r-- | compiler/optimizing/code_generator_arm.cc | 72 |
1 files changed, 62 insertions, 10 deletions
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 39c316fa31..e3683ef0dd 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -332,8 +332,6 @@ class DeoptimizationSlowPathARM : public SlowPathCodeARM { }; #undef __ - -#undef __ #define __ down_cast<ArmAssembler*>(GetAssembler())-> inline Condition ARMCondition(IfCondition cond) { @@ -1383,6 +1381,7 @@ void InstructionCodeGeneratorARM::VisitInvokeVirtual(HInvokeVirtual* invoke) { DCHECK(receiver.IsRegister()); __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset); codegen_->MaybeRecordImplicitNullCheck(invoke); + __ MaybeUnpoisonHeapReference(temp); // temp = temp->GetMethodAt(method_offset); uint32_t entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset( kArmWordSize).Int32Value(); @@ -1422,6 +1421,7 @@ void InstructionCodeGeneratorARM::VisitInvokeInterface(HInvokeInterface* invoke) __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset); } codegen_->MaybeRecordImplicitNullCheck(invoke); + __ MaybeUnpoisonHeapReference(temp); // temp = temp->GetImtEntryAt(method_offset); uint32_t entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset( kArmWordSize).Int32Value(); @@ -2778,6 +2778,8 @@ void LocationsBuilderARM::VisitNewInstance(HNewInstance* instruction) { void InstructionCodeGeneratorARM::VisitNewInstance(HNewInstance* instruction) { InvokeRuntimeCallingConvention calling_convention; __ LoadImmediate(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex()); + // Note: if heap poisoning is enabled, the entry point takes cares + // of poisoning the reference. codegen_->InvokeRuntime(GetThreadOffset<kArmWordSize>(instruction->GetEntrypoint()).Int32Value(), instruction, instruction->GetDexPc(), @@ -2797,6 +2799,8 @@ void LocationsBuilderARM::VisitNewArray(HNewArray* instruction) { void InstructionCodeGeneratorARM::VisitNewArray(HNewArray* instruction) { InvokeRuntimeCallingConvention calling_convention; __ LoadImmediate(calling_convention.GetRegisterAt(0), instruction->GetTypeIndex()); + // Note: if heap poisoning is enabled, the entry point takes cares + // of poisoning the reference. codegen_->InvokeRuntime(GetThreadOffset<kArmWordSize>(instruction->GetEntrypoint()).Int32Value(), instruction, instruction->GetDexPc(), @@ -3030,10 +3034,12 @@ void LocationsBuilderARM::HandleFieldSet(HInstruction* instruction, const FieldI bool generate_volatile = field_info.IsVolatile() && is_wide && !codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd(); + bool needs_write_barrier = + CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1)); // Temporary registers for the write barrier. // TODO: consider renaming StoreNeedsWriteBarrier to StoreNeedsGCMark. - if (CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1))) { - locations->AddTemp(Location::RequiresRegister()); + if (needs_write_barrier) { + locations->AddTemp(Location::RequiresRegister()); // Possibly used for reference poisoning too. locations->AddTemp(Location::RequiresRegister()); } else if (generate_volatile) { // Arm encoding have some additional constraints for ldrexd/strexd: @@ -3066,6 +3072,8 @@ void InstructionCodeGeneratorARM::HandleFieldSet(HInstruction* instruction, bool atomic_ldrd_strd = codegen_->GetInstructionSetFeatures().HasAtomicLdrdAndStrd(); Primitive::Type field_type = field_info.GetFieldType(); uint32_t offset = field_info.GetFieldOffset().Uint32Value(); + bool needs_write_barrier = + CodeGenerator::StoreNeedsWriteBarrier(field_type, instruction->InputAt(1)); if (is_volatile) { GenerateMemoryBarrier(MemBarrierKind::kAnyStore); @@ -3086,7 +3094,18 @@ void InstructionCodeGeneratorARM::HandleFieldSet(HInstruction* instruction, case Primitive::kPrimInt: case Primitive::kPrimNot: { - __ StoreToOffset(kStoreWord, value.AsRegister<Register>(), base, offset); + if (kPoisonHeapReferences && needs_write_barrier) { + // Note that in the case where `value` is a null reference, + // we do not enter this block, as a null reference does not + // need poisoning. + DCHECK_EQ(field_type, Primitive::kPrimNot); + Register temp = locations->GetTemp(0).AsRegister<Register>(); + __ Mov(temp, value.AsRegister<Register>()); + __ PoisonHeapReference(temp); + __ StoreToOffset(kStoreWord, temp, base, offset); + } else { + __ StoreToOffset(kStoreWord, value.AsRegister<Register>(), base, offset); + } break; } @@ -3265,6 +3284,10 @@ void InstructionCodeGeneratorARM::HandleFieldGet(HInstruction* instruction, if (is_volatile) { GenerateMemoryBarrier(MemBarrierKind::kLoadAny); } + + if (field_type == Primitive::kPrimNot) { + __ MaybeUnpoisonHeapReference(out.AsRegister<Register>()); + } } void LocationsBuilderARM::VisitInstanceFieldSet(HInstanceFieldSet* instruction) { @@ -3352,8 +3375,9 @@ void InstructionCodeGeneratorARM::VisitArrayGet(HArrayGet* instruction) { LocationSummary* locations = instruction->GetLocations(); Register obj = locations->InAt(0).AsRegister<Register>(); Location index = locations->InAt(1); + Primitive::Type type = instruction->GetType(); - switch (instruction->GetType()) { + switch (type) { case Primitive::kPrimBoolean: { uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value(); Register out = locations->Out().AsRegister<Register>(); @@ -3470,10 +3494,15 @@ void InstructionCodeGeneratorARM::VisitArrayGet(HArrayGet* instruction) { } case Primitive::kPrimVoid: - LOG(FATAL) << "Unreachable type " << instruction->GetType(); + LOG(FATAL) << "Unreachable type " << type; UNREACHABLE(); } codegen_->MaybeRecordImplicitNullCheck(instruction); + + if (type == Primitive::kPrimNot) { + Register out = locations->Out().AsRegister<Register>(); + __ MaybeUnpoisonHeapReference(out); + } } void LocationsBuilderARM::VisitArraySet(HArraySet* instruction) { @@ -3501,7 +3530,7 @@ void LocationsBuilderARM::VisitArraySet(HArraySet* instruction) { if (needs_write_barrier) { // Temporary registers for the write barrier. - locations->AddTemp(Location::RequiresRegister()); + locations->AddTemp(Location::RequiresRegister()); // Possibly used for ref. poisoning too. locations->AddTemp(Location::RequiresRegister()); } } @@ -3552,14 +3581,25 @@ void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) { if (!needs_runtime_call) { uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value(); Register value = locations->InAt(2).AsRegister<Register>(); + Register source = value; + if (kPoisonHeapReferences && needs_write_barrier) { + // Note that in the case where `value` is a null reference, + // we do not enter this block, as a null reference does not + // need poisoning. + DCHECK_EQ(value_type, Primitive::kPrimNot); + Register temp = locations->GetTemp(0).AsRegister<Register>(); + __ Mov(temp, value); + __ PoisonHeapReference(temp); + source = temp; + } if (index.IsConstant()) { size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset; - __ StoreToOffset(kStoreWord, value, obj, offset); + __ StoreToOffset(kStoreWord, source, obj, offset); } else { DCHECK(index.IsRegister()) << index; __ add(IP, obj, ShifterOperand(index.AsRegister<Register>(), LSL, TIMES_4)); - __ StoreToOffset(kStoreWord, value, IP, data_offset); + __ StoreToOffset(kStoreWord, source, IP, data_offset); } codegen_->MaybeRecordImplicitNullCheck(instruction); if (needs_write_barrier) { @@ -3570,6 +3610,8 @@ void InstructionCodeGeneratorARM::VisitArraySet(HArraySet* instruction) { } } else { DCHECK_EQ(value_type, Primitive::kPrimNot); + // Note: if heap poisoning is enabled, pAputObject takes cares + // of poisoning the reference. codegen_->InvokeRuntime(QUICK_ENTRY_POINT(pAputObject), instruction, instruction->GetDexPc(), @@ -3994,6 +4036,7 @@ void InstructionCodeGeneratorARM::VisitLoadClass(HLoadClass* cls) { current_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value()); __ LoadFromOffset(kLoadWord, out, out, CodeGenerator::GetCacheOffset(cls->GetTypeIndex())); + __ MaybeUnpoisonHeapReference(out); SlowPathCodeARM* slow_path = new (GetGraph()->GetArena()) LoadClassSlowPathARM( cls, cls, cls->GetDexPc(), cls->MustGenerateClinitCheck()); @@ -4053,7 +4096,9 @@ void InstructionCodeGeneratorARM::VisitLoadString(HLoadString* load) { __ LoadFromOffset( kLoadWord, out, current_method, ArtMethod::DeclaringClassOffset().Int32Value()); __ LoadFromOffset(kLoadWord, out, out, mirror::Class::DexCacheStringsOffset().Int32Value()); + __ MaybeUnpoisonHeapReference(out); __ LoadFromOffset(kLoadWord, out, out, CodeGenerator::GetCacheOffset(load->GetStringIndex())); + __ MaybeUnpoisonHeapReference(out); __ CompareAndBranchIfZero(out, slow_path->GetEntryLabel()); __ Bind(slow_path->GetExitLabel()); } @@ -4111,6 +4156,7 @@ void InstructionCodeGeneratorARM::VisitInstanceOf(HInstanceOf* instruction) { } // Compare the class of `obj` with `cls`. __ LoadFromOffset(kLoadWord, out, obj, class_offset); + __ MaybeUnpoisonHeapReference(out); __ cmp(out, ShifterOperand(cls)); if (instruction->IsClassFinal()) { // Classes must be equal for the instanceof to succeed. @@ -4164,7 +4210,10 @@ void InstructionCodeGeneratorARM::VisitCheckCast(HCheckCast* instruction) { } // Compare the class of `obj` with `cls`. __ LoadFromOffset(kLoadWord, temp, obj, class_offset); + __ MaybeUnpoisonHeapReference(temp); __ cmp(temp, ShifterOperand(cls)); + // The checkcast succeeds if the classes are equal (fast path). + // Otherwise, we need to go into the slow path to check the types. __ b(slow_path->GetEntryLabel(), NE); __ Bind(slow_path->GetExitLabel()); } @@ -4316,5 +4365,8 @@ void InstructionCodeGeneratorARM::VisitBoundType(HBoundType* instruction) { LOG(FATAL) << "Unreachable"; } +#undef __ +#undef QUICK_ENTRY_POINT + } // namespace arm } // namespace art |