diff options
Diffstat (limited to 'compiler/optimizing/code_generator_x86_64.cc')
-rw-r--r-- | compiler/optimizing/code_generator_x86_64.cc | 101 |
1 files changed, 17 insertions, 84 deletions
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 4d23062100..c495d48406 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -6267,9 +6267,8 @@ void CodeGeneratorX86_64::CheckGCCardIsValid(CpuRegister temp, // assert (!clean || !self->is_gc_marking) __ cmpb(Address(temp, card, TIMES_1, 0), Immediate(gc::accounting::CardTable::kCardClean)); __ j(kNotEqual, &done); - __ gs()->cmpl( - Address::Absolute(Thread::IsGcMarkingOffset<kX86_64PointerSize>(), /* no_rip= */ true), - Immediate(0)); + __ gs()->cmpl(Address::Absolute(Thread::IsGcMarkingOffset<kX86_64PointerSize>(), true), + Immediate(0)); __ j(kEqual, &done); __ int3(); __ Bind(&done); @@ -7008,9 +7007,6 @@ void InstructionCodeGeneratorX86_64::VisitThrow(HThrow* instruction) { // Temp is used for read barrier. static size_t NumberOfInstanceOfTemps(bool emit_read_barrier, TypeCheckKind type_check_kind) { - if (type_check_kind == TypeCheckKind::kInterfaceCheck) { - return 1; - } if (emit_read_barrier && !kUseBakerReadBarrier && (type_check_kind == TypeCheckKind::kAbstractClassCheck || @@ -7025,6 +7021,9 @@ static size_t NumberOfInstanceOfTemps(bool emit_read_barrier, TypeCheckKind type // interface pointer, the current interface is compared in memory. // The other checks have one temp for loading the object's class. static size_t NumberOfCheckCastTemps(bool emit_read_barrier, TypeCheckKind type_check_kind) { + if (type_check_kind == TypeCheckKind::kInterfaceCheck) { + return 2; + } return 1 + NumberOfInstanceOfTemps(emit_read_barrier, type_check_kind); } @@ -7036,16 +7035,15 @@ void LocationsBuilderX86_64::VisitInstanceOf(HInstanceOf* instruction) { case TypeCheckKind::kExactCheck: case TypeCheckKind::kAbstractClassCheck: case TypeCheckKind::kClassHierarchyCheck: - case TypeCheckKind::kArrayObjectCheck: - case TypeCheckKind::kInterfaceCheck: { + case TypeCheckKind::kArrayObjectCheck: { bool needs_read_barrier = codegen_->InstanceOfNeedsReadBarrier(instruction); call_kind = needs_read_barrier ? LocationSummary::kCallOnSlowPath : LocationSummary::kNoCall; - baker_read_barrier_slow_path = (kUseBakerReadBarrier && needs_read_barrier) && - (type_check_kind == TypeCheckKind::kInterfaceCheck); + baker_read_barrier_slow_path = kUseBakerReadBarrier && needs_read_barrier; break; } case TypeCheckKind::kArrayCheck: case TypeCheckKind::kUnresolvedCheck: + case TypeCheckKind::kInterfaceCheck: call_kind = LocationSummary::kCallOnSlowPath; break; case TypeCheckKind::kBitstringCheck: @@ -7062,8 +7060,6 @@ void LocationsBuilderX86_64::VisitInstanceOf(HInstanceOf* instruction) { locations->SetInAt(1, Location::ConstantLocation(instruction->InputAt(1))); locations->SetInAt(2, Location::ConstantLocation(instruction->InputAt(2))); locations->SetInAt(3, Location::ConstantLocation(instruction->InputAt(3))); - } else if (type_check_kind == TypeCheckKind::kInterfaceCheck) { - locations->SetInAt(1, Location::RequiresRegister()); } else { locations->SetInAt(1, Location::Any()); } @@ -7084,14 +7080,10 @@ void InstructionCodeGeneratorX86_64::VisitInstanceOf(HInstanceOf* instruction) { const size_t num_temps = NumberOfInstanceOfTemps(codegen_->EmitReadBarrier(), type_check_kind); DCHECK_LE(num_temps, 1u); Location maybe_temp_loc = (num_temps >= 1u) ? locations->GetTemp(0) : Location::NoLocation(); - const uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); - const uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value(); - const uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value(); - const uint32_t primitive_offset = mirror::Class::PrimitiveTypeOffset().Int32Value(); - const uint32_t iftable_offset = mirror::Class::IfTableOffset().Uint32Value(); - const uint32_t array_length_offset = mirror::Array::LengthOffset().Uint32Value(); - const uint32_t object_array_data_offset = - mirror::Array::DataOffset(kHeapReferenceSize).Uint32Value(); + uint32_t class_offset = mirror::Object::ClassOffset().Int32Value(); + uint32_t super_offset = mirror::Class::SuperClassOffset().Int32Value(); + uint32_t component_offset = mirror::Class::ComponentTypeOffset().Int32Value(); + uint32_t primitive_offset = mirror::Class::PrimitiveTypeOffset().Int32Value(); SlowPathCode* slow_path = nullptr; NearLabel done, zero; @@ -7266,70 +7258,11 @@ void InstructionCodeGeneratorX86_64::VisitInstanceOf(HInstanceOf* instruction) { break; } + case TypeCheckKind::kUnresolvedCheck: case TypeCheckKind::kInterfaceCheck: { - if (codegen_->InstanceOfNeedsReadBarrier(instruction)) { - DCHECK(locations->OnlyCallsOnSlowPath()); - slow_path = new (codegen_->GetScopedAllocator()) TypeCheckSlowPathX86_64( - instruction, /* is_fatal= */ false); - codegen_->AddSlowPath(slow_path); - if (codegen_->EmitNonBakerReadBarrier()) { - __ jmp(slow_path->GetEntryLabel()); - break; - } - // For Baker read barrier, take the slow path while marking. - __ gs()->cmpl( - Address::Absolute(Thread::IsGcMarkingOffset<kX86_64PointerSize>(), /* no_rip= */ true), - Immediate(0)); - __ j(kNotEqual, slow_path->GetEntryLabel()); - } - - // Fast-path without read barriers. - CpuRegister temp = maybe_temp_loc.AsRegister<CpuRegister>(); - // /* HeapReference<Class> */ temp = obj->klass_ - __ movl(temp, Address(obj, class_offset)); - __ MaybeUnpoisonHeapReference(temp); - // /* HeapReference<Class> */ temp = temp->iftable_ - __ movl(temp, Address(temp, iftable_offset)); - __ MaybeUnpoisonHeapReference(temp); - // Load the size of the `IfTable`. The `Class::iftable_` is never null. - __ movl(out, Address(temp, array_length_offset)); - // Maybe poison the `cls` for direct comparison with memory. - __ MaybePoisonHeapReference(cls.AsRegister<CpuRegister>()); - // Loop through the iftable and check if any class matches. - NearLabel loop, end; - __ Bind(&loop); - // Check if we still have an entry to compare. - __ subl(out, Immediate(2)); - __ j(kNegative, (zero.IsLinked() && !kPoisonHeapReferences) ? &zero : &end); - // Go to next interface if the classes do not match. - __ cmpl(cls.AsRegister<CpuRegister>(), - CodeGeneratorX86_64::ArrayAddress(temp, out_loc, TIMES_4, object_array_data_offset)); - __ j(kNotEqual, &loop); - if (zero.IsLinked()) { - __ movl(out, Immediate(1)); - // If `cls` was poisoned above, unpoison it. - __ MaybeUnpoisonHeapReference(cls.AsRegister<CpuRegister>()); - __ jmp(&done); - if (kPoisonHeapReferences) { - // The false case needs to unpoison the class before jumping to `zero`. - __ Bind(&end); - __ UnpoisonHeapReference(cls.AsRegister<CpuRegister>()); - __ jmp(&zero); - } - } else { - // To reduce branching, use the fact that the false case branches with a `-2` in `out`. - __ movl(out, Immediate(-1)); - __ Bind(&end); - __ addl(out, Immediate(2)); - // If `cls` was poisoned above, unpoison it. - __ MaybeUnpoisonHeapReference(cls.AsRegister<CpuRegister>()); - } - break; - } - - case TypeCheckKind::kUnresolvedCheck: { // Note that we indeed only call on slow path, but we always go - // into the slow path for the unresolved check case. + // into the slow path for the unresolved and interface check + // cases. // // We cannot directly call the InstanceofNonTrivial runtime // entry point without resorting to a type checking slow path @@ -7599,14 +7532,14 @@ void InstructionCodeGeneratorX86_64::VisitCheckCast(HCheckCast* instruction) { iftable_offset, maybe_temp2_loc, kWithoutReadBarrier); - // Load the size of the `IfTable`. The `Class::iftable_` is never null. + // Iftable is never null. __ movl(maybe_temp2_loc.AsRegister<CpuRegister>(), Address(temp, array_length_offset)); // Maybe poison the `cls` for direct comparison with memory. __ MaybePoisonHeapReference(cls.AsRegister<CpuRegister>()); // Loop through the iftable and check if any class matches. NearLabel start_loop; __ Bind(&start_loop); - // Check if we still have an entry to compare. + // Need to subtract first to handle the empty array case. __ subl(maybe_temp2_loc.AsRegister<CpuRegister>(), Immediate(2)); __ j(kNegative, type_check_slow_path->GetEntryLabel()); // Go to next interface if the classes do not match. |