From: Roland Levillain Date: Tue, 19 Jan 2016 15:07:47 +0000 (+0000) Subject: Some read barrier clean-up in Optimizing. X-Git-Tag: android-x86-7.1-r1~424^2~229^2^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=e3f43ac79e50a4693ea4d46acf5cffca64910cee;p=android-x86%2Fart.git Some read barrier clean-up in Optimizing. These changes make the read barrier compiler instrumentation code more uniform among the ARM, ARM64, x86 and x86-64 back ends. Bug: 12687968 Change-Id: I6b1c0cf2bc22ed6cd6b14754136bef4a2a036ea5 --- diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc index 2bf84042e..272579219 100644 --- a/compiler/optimizing/code_generator_arm.cc +++ b/compiler/optimizing/code_generator_arm.cc @@ -5483,7 +5483,7 @@ void InstructionCodeGeneratorARM::VisitInstanceOf(HInstanceOf* instruction) { case TypeCheckKind::kUnresolvedCheck: case TypeCheckKind::kInterfaceCheck: { // Note that we indeed only call on slow path, but we always go - // into the slow path for the unresolved & interface check + // into the slow path for the unresolved and interface check // cases. // // We cannot directly call the InstanceofNonTrivial runtime @@ -5693,8 +5693,8 @@ void InstructionCodeGeneratorARM::VisitCheckCast(HCheckCast* instruction) { case TypeCheckKind::kUnresolvedCheck: case TypeCheckKind::kInterfaceCheck: - // We always go into the type check slow path for the unresolved & - // interface check cases. + // We always go into the type check slow path for the unresolved + // and interface check cases. // // We cannot directly call the CheckCast runtime entry point // without resorting to a type checking slow path here (i.e. by @@ -5980,6 +5980,7 @@ void InstructionCodeGeneratorARM::GenerateGcRootFieldLoad(HInstruction* instruct new (GetGraph()->GetArena()) ReadBarrierMarkSlowPathARM(instruction, root, root); codegen_->AddSlowPath(slow_path); + // IP = Thread::Current()->GetIsGcMarking() __ LoadFromOffset( kLoadWord, IP, TR, Thread::IsGcMarkingOffset().Int32Value()); __ CompareAndBranchIfNonZero(IP, slow_path->GetEntryLabel()); @@ -6058,11 +6059,8 @@ void CodeGeneratorARM::GenerateReferenceLoadWithBakerReadBarrier(HInstruction* i // } // // Note: the original implementation in ReadBarrier::Barrier is - // slightly more complex as: - // - it implements the load-load fence using a data dependency on - // the high-bits of rb_state, which are expected to be all zeroes; - // - it performs additional checks that we do not do here for - // performance reasons. + // slightly more complex as it performs additional checks that we do + // not do here for performance reasons. Register ref_reg = ref.AsRegister(); Register temp_reg = temp.AsRegister(); diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h index 1183dda8c..d45ea973f 100644 --- a/compiler/optimizing/code_generator_arm.h +++ b/compiler/optimizing/code_generator_arm.h @@ -442,7 +442,7 @@ class CodeGeneratorARM : public CodeGenerator { // Fast path implementation of ReadBarrier::Barrier for a heap // reference field load when Baker's read barriers are used. void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction, - Location out, + Location ref, Register obj, uint32_t offset, Location temp, @@ -450,7 +450,7 @@ class CodeGeneratorARM : public CodeGenerator { // Fast path implementation of ReadBarrier::Barrier for a heap // reference array load when Baker's read barriers are used. void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction, - Location out, + Location ref, Register obj, uint32_t data_offset, Location index, diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index f95cb30b9..f7ccdd8b8 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -6009,7 +6009,7 @@ void InstructionCodeGeneratorX86::VisitInstanceOf(HInstanceOf* instruction) { case TypeCheckKind::kUnresolvedCheck: case TypeCheckKind::kInterfaceCheck: { // Note that we indeed only call on slow path, but we always go - // into the slow path for the unresolved & interface check + // into the slow path for the unresolved and interface check // cases. // // We cannot directly call the InstanceofNonTrivial runtime @@ -6240,8 +6240,8 @@ void InstructionCodeGeneratorX86::VisitCheckCast(HCheckCast* instruction) { case TypeCheckKind::kUnresolvedCheck: case TypeCheckKind::kInterfaceCheck: - // We always go into the type check slow path for the unresolved & - // interface check cases. + // We always go into the type check slow path for the unresolved + // and interface check cases. // // We cannot directly call the CheckCast runtime entry point // without resorting to a type checking slow path here (i.e. by @@ -6520,6 +6520,8 @@ void InstructionCodeGeneratorX86::GenerateGcRootFieldLoad(HInstruction* instruct // Plain GC root load with no read barrier. // /* GcRoot */ root = *(obj + offset) __ movl(root_reg, Address(obj, offset)); + // Note that GC roots are not affected by heap poisoning, thus we + // do not have to unpoison `root_reg` here. } } @@ -6582,7 +6584,9 @@ void CodeGeneratorX86::GenerateReferenceLoadWithBakerReadBarrier(HInstruction* i // Note: the original implementation in ReadBarrier::Barrier is // slightly more complex as: // - it implements the load-load fence using a data dependency on - // the high-bits of rb_state, which are expected to be all zeroes; + // the high-bits of rb_state, which are expected to be all zeroes + // (we use CodeGeneratorX86::GenerateMemoryBarrier instead here, + // which is a no-op thanks to the x86 memory model); // - it performs additional checks that we do not do here for // performance reasons. diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index 34f983fc0..43e9543e4 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -451,7 +451,7 @@ class CodeGeneratorX86 : public CodeGenerator { // Fast path implementation of ReadBarrier::Barrier for a heap // reference field load when Baker's read barriers are used. void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction, - Location out, + Location ref, Register obj, uint32_t offset, Location temp, @@ -459,7 +459,7 @@ class CodeGeneratorX86 : public CodeGenerator { // Fast path implementation of ReadBarrier::Barrier for a heap // reference array load when Baker's read barriers are used. void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction, - Location out, + Location ref, Register obj, uint32_t data_offset, Location index, diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 31f366038..2ce2d9150 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -4663,13 +4663,13 @@ void LocationsBuilderX86_64::VisitArraySet(HArraySet* instruction) { bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); - bool may_need_runtime_call = instruction->NeedsTypeCheck(); + bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck(); bool object_array_set_with_read_barrier = kEmitCompilerReadBarrier && (value_type == Primitive::kPrimNot); LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary( instruction, - (may_need_runtime_call || object_array_set_with_read_barrier) ? + (may_need_runtime_call_for_type_check || object_array_set_with_read_barrier) ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall); @@ -4698,7 +4698,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { Location index = locations->InAt(1); Location value = locations->InAt(2); Primitive::Type value_type = instruction->GetComponentType(); - bool may_need_runtime_call = instruction->NeedsTypeCheck(); + bool may_need_runtime_call_for_type_check = instruction->NeedsTypeCheck(); bool needs_write_barrier = CodeGenerator::StoreNeedsWriteBarrier(value_type, instruction->GetValue()); uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); @@ -4750,7 +4750,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { __ movl(address, Immediate(0)); codegen_->MaybeRecordImplicitNullCheck(instruction); DCHECK(!needs_write_barrier); - DCHECK(!may_need_runtime_call); + DCHECK(!may_need_runtime_call_for_type_check); break; } @@ -4759,7 +4759,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { NearLabel done, not_null, do_put; SlowPathCode* slow_path = nullptr; CpuRegister temp = locations->GetTemp(0).AsRegister(); - if (may_need_runtime_call) { + if (may_need_runtime_call_for_type_check) { slow_path = new (GetGraph()->GetArena()) ArraySetSlowPathX86_64(instruction); codegen_->AddSlowPath(slow_path); if (instruction->GetValueCanBeNull()) { @@ -4837,7 +4837,7 @@ void InstructionCodeGeneratorX86_64::VisitArraySet(HArraySet* instruction) { } else { __ movl(address, register_value); } - if (!may_need_runtime_call) { + if (!may_need_runtime_call_for_type_check) { codegen_->MaybeRecordImplicitNullCheck(instruction); } @@ -5626,7 +5626,7 @@ void InstructionCodeGeneratorX86_64::VisitInstanceOf(HInstanceOf* instruction) { case TypeCheckKind::kUnresolvedCheck: case TypeCheckKind::kInterfaceCheck: { // Note that we indeed only call on slow path, but we always go - // into the slow path for the unresolved & interface check + // into the slow path for the unresolved and interface check // cases. // // We cannot directly call the InstanceofNonTrivial runtime @@ -5857,8 +5857,8 @@ void InstructionCodeGeneratorX86_64::VisitCheckCast(HCheckCast* instruction) { case TypeCheckKind::kUnresolvedCheck: case TypeCheckKind::kInterfaceCheck: - // We always go into the type check slow path for the unresolved & - // interface check cases. + // We always go into the type check slow path for the unresolved + // and interface check cases. // // We cannot directly call the CheckCast runtime entry point // without resorting to a type checking slow path here (i.e. by @@ -6120,6 +6120,8 @@ void InstructionCodeGeneratorX86_64::GenerateGcRootFieldLoad(HInstruction* instr // Plain GC root load with no read barrier. // /* GcRoot */ root = *(obj + offset) __ movl(root_reg, Address(obj, offset)); + // Note that GC roots are not affected by heap poisoning, thus we + // do not have to unpoison `root_reg` here. } } @@ -6182,7 +6184,9 @@ void CodeGeneratorX86_64::GenerateReferenceLoadWithBakerReadBarrier(HInstruction // Note: the original implementation in ReadBarrier::Barrier is // slightly more complex as: // - it implements the load-load fence using a data dependency on - // the high-bits of rb_state, which are expected to be all zeroes; + // the high-bits of rb_state, which are expected to be all zeroes + // (we use CodeGeneratorX86_64::GenerateMemoryBarrier instead + // here, which is a no-op thanks to the x86-64 memory model); // - it performs additional checks that we do not do here for // performance reasons. diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h index 9de9d9e35..82aabb04d 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -400,7 +400,7 @@ class CodeGeneratorX86_64 : public CodeGenerator { // Fast path implementation of ReadBarrier::Barrier for a heap // reference field load when Baker's read barriers are used. void GenerateFieldLoadWithBakerReadBarrier(HInstruction* instruction, - Location out, + Location ref, CpuRegister obj, uint32_t offset, Location temp, @@ -408,7 +408,7 @@ class CodeGeneratorX86_64 : public CodeGenerator { // Fast path implementation of ReadBarrier::Barrier for a heap // reference array load when Baker's read barriers are used. void GenerateArrayLoadWithBakerReadBarrier(HInstruction* instruction, - Location out, + Location ref, CpuRegister obj, uint32_t data_offset, Location index,