Implement Reference.getReferent() intrinsic.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing --jit
Test: aosp_blueline-userdebug boots.
Test: run-gtests.sh
Test: testrunner.py --target --optimizing --jit
Bug: 170286013
Change-Id: I4762f7c1cf3d61de2215ec8f1d14be80289c2372
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 00b2586..1dedfc5 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -8893,12 +8893,12 @@
Location ref,
vixl32::Register obj,
uint32_t offset,
- Location temp,
+ Location maybe_temp,
bool needs_null_check) {
DCHECK_ALIGNED(offset, sizeof(mirror::HeapReference<mirror::Object>));
vixl32::Register base = obj;
if (offset >= kReferenceLoadMinFarOffset) {
- base = RegisterFrom(temp);
+ base = RegisterFrom(maybe_temp);
static_assert(IsPowerOfTwo(kReferenceLoadMinFarOffset), "Expecting a power of 2.");
__ Add(base, obj, Operand(offset & ~(kReferenceLoadMinFarOffset - 1u)));
offset &= (kReferenceLoadMinFarOffset - 1u);
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 8f3d41c..23d05ae 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -677,7 +677,7 @@
Location ref,
vixl::aarch32::Register obj,
uint32_t offset,
- Location temp,
+ Location maybe_temp,
bool needs_null_check);
// Fast path implementation of ReadBarrier::Barrier for a heap
// reference array load when Baker's read barriers are used.
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 1663ee9..10d0b89 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -146,6 +146,22 @@
return true;
}
+static bool CanReferenceBootImageObjects(HInvoke* invoke, const CompilerOptions& compiler_options) {
+ // Piggyback on the method load kind to determine whether we can use PC-relative addressing
+ // for AOT. This should cover both the testing config (non-PIC boot image) and codegens that
+ // reject PC-relative load kinds and fall back to the runtime call.
+ if (compiler_options.IsAotCompiler() &&
+ !invoke->AsInvokeStaticOrDirect()->HasPcRelativeMethodLoadKind()) {
+ return false;
+ }
+ if (!compiler_options.IsBootImage() &&
+ Runtime::Current()->GetHeap()->GetBootImageSpaces().empty()) {
+ DCHECK(compiler_options.IsJitCompiler());
+ return false; // Running without boot image, cannot use required boot image objects.
+ }
+ return true;
+}
+
void IntrinsicVisitor::ComputeIntegerValueOfLocations(HInvoke* invoke,
CodeGenerator* codegen,
Location return_location,
@@ -153,11 +169,7 @@
// The intrinsic will call if it needs to allocate a j.l.Integer.
LocationSummary::CallKind call_kind = LocationSummary::kCallOnMainOnly;
const CompilerOptions& compiler_options = codegen->GetCompilerOptions();
- // Piggyback on the method load kind to determine whether we can use PC-relative addressing
- // for AOT. This should cover both the testing config (non-PIC boot image) and codegens that
- // reject PC-relative load kinds and fall back to the runtime call.
- if (compiler_options.IsAotCompiler() &&
- !invoke->AsInvokeStaticOrDirect()->HasPcRelativeMethodLoadKind()) {
+ if (!CanReferenceBootImageObjects(invoke, compiler_options)) {
return;
}
if (compiler_options.IsBootImage()) {
@@ -206,9 +218,6 @@
}
} else {
Runtime* runtime = Runtime::Current();
- if (runtime->GetHeap()->GetBootImageSpaces().empty()) {
- return; // Running without boot image, cannot use required boot image objects.
- }
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects = GetBootImageLiveObjects();
@@ -244,7 +253,7 @@
}
}
- ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetAllocator();
+ ArenaAllocator* allocator = codegen->GetGraph()->GetAllocator();
LocationSummary* locations = new (allocator) LocationSummary(invoke, call_kind, kIntrinsified);
if (call_kind == LocationSummary::kCallOnMainOnly) {
locations->SetInAt(0, Location::RegisterOrConstant(invoke->InputAt(0)));
@@ -354,10 +363,39 @@
return info;
}
+MemberOffset IntrinsicVisitor::GetReferenceDisableIntrinsicOffset() {
+ ScopedObjectAccess soa(Thread::Current());
+ // The "disableIntrinsic" is the first static field.
+ ArtField* field = GetClassRoot<mirror::Reference>()->GetStaticField(0);
+ DCHECK_STREQ(field->GetName(), "disableIntrinsic");
+ return field->GetOffset();
+}
+
+MemberOffset IntrinsicVisitor::GetReferenceSlowPathEnabledOffset() {
+ ScopedObjectAccess soa(Thread::Current());
+ // The "slowPathEnabled" is the second static field.
+ ArtField* field = GetClassRoot<mirror::Reference>()->GetStaticField(1);
+ DCHECK_STREQ(field->GetName(), "slowPathEnabled");
+ return field->GetOffset();
+}
+
+void IntrinsicVisitor::CreateReferenceGetReferentLocations(HInvoke* invoke,
+ CodeGenerator* codegen) {
+ if (!CanReferenceBootImageObjects(invoke, codegen->GetCompilerOptions())) {
+ return;
+ }
+
+ ArenaAllocator* allocator = codegen->GetGraph()->GetAllocator();
+ LocationSummary* locations =
+ new (allocator) LocationSummary(invoke, LocationSummary::kCallOnSlowPath, kIntrinsified);
+ locations->SetInAt(0, Location::RequiresRegister());
+ locations->SetOut(Location::RequiresRegister());
+}
+
void IntrinsicVisitor::AssertNonMovableStringClass() {
if (kIsDebugBuild) {
ScopedObjectAccess soa(Thread::Current());
- ObjPtr<mirror::Class> string_class = GetClassRoot<art::mirror::String>();
+ ObjPtr<mirror::Class> string_class = GetClassRoot<mirror::String>();
CHECK(!art::Runtime::Current()->GetHeap()->IsMovableObject(string_class));
}
}
diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h
index cc26e41..a0f9420 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -136,6 +136,10 @@
static IntegerValueOfInfo ComputeIntegerValueOfInfo(
HInvoke* invoke, const CompilerOptions& compiler_options);
+ static MemberOffset GetReferenceDisableIntrinsicOffset();
+ static MemberOffset GetReferenceSlowPathEnabledOffset();
+ static void CreateReferenceGetReferentLocations(HInvoke* invoke, CodeGenerator* codegen);
+
protected:
IntrinsicVisitor() {}
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index a7d5b31..1c8c5e1 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -2873,6 +2873,66 @@
}
}
+void IntrinsicLocationsBuilderARM64::VisitReferenceGetReferent(HInvoke* invoke) {
+ IntrinsicVisitor::CreateReferenceGetReferentLocations(invoke, codegen_);
+
+ if (kEmitCompilerReadBarrier && kUseBakerReadBarrier && invoke->GetLocations() != nullptr) {
+ invoke->GetLocations()->AddTemp(Location::RequiresRegister());
+ }
+}
+
+void IntrinsicCodeGeneratorARM64::VisitReferenceGetReferent(HInvoke* invoke) {
+ MacroAssembler* masm = GetVIXLAssembler();
+ LocationSummary* locations = invoke->GetLocations();
+
+ Location obj = locations->InAt(0);
+ Location out = locations->Out();
+
+ SlowPathCodeARM64* slow_path = new (GetAllocator()) IntrinsicSlowPathARM64(invoke);
+ codegen_->AddSlowPath(slow_path);
+
+ if (kEmitCompilerReadBarrier) {
+ // Check self->GetWeakRefAccessEnabled().
+ UseScratchRegisterScope temps(masm);
+ Register temp = temps.AcquireW();
+ __ Ldr(temp,
+ MemOperand(tr, Thread::WeakRefAccessEnabledOffset<kArm64PointerSize>().Uint32Value()));
+ __ Cbz(temp, slow_path->GetEntryLabel());
+ }
+
+ {
+ // Load the java.lang.ref.Reference class.
+ UseScratchRegisterScope temps(masm);
+ Register temp = temps.AcquireW();
+ codegen_->LoadIntrinsicDeclaringClass(temp, invoke);
+
+ // Check static fields java.lang.ref.Reference.{disableIntrinsic,slowPathEnabled} together.
+ MemberOffset disable_intrinsic_offset = IntrinsicVisitor::GetReferenceDisableIntrinsicOffset();
+ DCHECK_ALIGNED(disable_intrinsic_offset.Uint32Value(), 2u);
+ DCHECK_EQ(disable_intrinsic_offset.Uint32Value() + 1u,
+ IntrinsicVisitor::GetReferenceSlowPathEnabledOffset().Uint32Value());
+ __ Ldrh(temp, HeapOperand(temp, disable_intrinsic_offset.Uint32Value()));
+ __ Cbnz(temp, slow_path->GetEntryLabel());
+ }
+
+ // Load the value from the field.
+ uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+ if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+ codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+ out,
+ WRegisterFrom(obj),
+ referent_offset,
+ /*maybe_temp=*/ locations->GetTemp(0),
+ /*needs_null_check=*/ true,
+ /*use_load_acquire=*/ true);
+ } else {
+ MemOperand field = HeapOperand(WRegisterFrom(obj), referent_offset);
+ codegen_->LoadAcquire(invoke, WRegisterFrom(out), field, /*needs_null_check=*/ true);
+ codegen_->MaybeGenerateReadBarrierSlow(invoke, out, out, obj, referent_offset);
+ }
+ __ Bind(slow_path->GetExitLabel());
+}
+
void IntrinsicLocationsBuilderARM64::VisitThreadInterrupted(HInvoke* invoke) {
LocationSummary* locations =
new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
@@ -3828,8 +3888,6 @@
GenerateVarHandleSet(invoke, codegen_, /*use_store_release=*/ true);
}
-UNIMPLEMENTED_INTRINSIC(ARM64, ReferenceGetReferent)
-
UNIMPLEMENTED_INTRINSIC(ARM64, StringStringIndexOf);
UNIMPLEMENTED_INTRINSIC(ARM64, StringStringIndexOfAfter);
UNIMPLEMENTED_INTRINSIC(ARM64, StringBufferAppend);
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 2901c47..f629ad3 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -2991,6 +2991,68 @@
}
}
+void IntrinsicLocationsBuilderARMVIXL::VisitReferenceGetReferent(HInvoke* invoke) {
+ IntrinsicVisitor::CreateReferenceGetReferentLocations(invoke, codegen_);
+}
+
+void IntrinsicCodeGeneratorARMVIXL::VisitReferenceGetReferent(HInvoke* invoke) {
+ ArmVIXLAssembler* assembler = GetAssembler();
+ LocationSummary* locations = invoke->GetLocations();
+
+ Location obj = locations->InAt(0);
+ Location out = locations->Out();
+
+ SlowPathCodeARMVIXL* slow_path = new (GetAllocator()) IntrinsicSlowPathARMVIXL(invoke);
+ codegen_->AddSlowPath(slow_path);
+
+ if (kEmitCompilerReadBarrier) {
+ // Check self->GetWeakRefAccessEnabled().
+ UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+ vixl32::Register temp = temps.Acquire();
+ __ Ldr(temp,
+ MemOperand(tr, Thread::WeakRefAccessEnabledOffset<kArmPointerSize>().Uint32Value()));
+ __ Cmp(temp, 0);
+ __ B(eq, slow_path->GetEntryLabel());
+ }
+
+ {
+ // Load the java.lang.ref.Reference class.
+ UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
+ vixl32::Register temp = temps.Acquire();
+ codegen_->LoadIntrinsicDeclaringClass(temp, invoke);
+
+ // Check static fields java.lang.ref.Reference.{disableIntrinsic,slowPathEnabled} together.
+ MemberOffset disable_intrinsic_offset = IntrinsicVisitor::GetReferenceDisableIntrinsicOffset();
+ DCHECK_ALIGNED(disable_intrinsic_offset.Uint32Value(), 2u);
+ DCHECK_EQ(disable_intrinsic_offset.Uint32Value() + 1u,
+ IntrinsicVisitor::GetReferenceSlowPathEnabledOffset().Uint32Value());
+ __ Ldrh(temp, MemOperand(temp, disable_intrinsic_offset.Uint32Value()));
+ __ Cmp(temp, 0);
+ __ B(ne, slow_path->GetEntryLabel());
+ }
+
+ // Load the value from the field.
+ uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+ if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+ codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+ out,
+ RegisterFrom(obj),
+ referent_offset,
+ /*maybe_temp=*/ Location::NoLocation(),
+ /*needs_null_check=*/ true);
+ codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny); // `referent` is volatile.
+ } else {
+ {
+ vixl::EmissionCheckScope guard(codegen_->GetVIXLAssembler(), kMaxMacroInstructionSizeInBytes);
+ __ Ldr(RegisterFrom(out), MemOperand(RegisterFrom(obj), referent_offset));
+ codegen_->MaybeRecordImplicitNullCheck(invoke);
+ }
+ codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny); // `referent` is volatile.
+ codegen_->MaybeGenerateReadBarrierSlow(invoke, out, out, obj, referent_offset);
+ }
+ __ Bind(slow_path->GetExitLabel());
+}
+
void IntrinsicLocationsBuilderARMVIXL::VisitThreadInterrupted(HInvoke* invoke) {
LocationSummary* locations =
new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
@@ -3049,7 +3111,6 @@
UNIMPLEMENTED_INTRINSIC(ARMVIXL, MathRoundDouble) // Could be done by changing rounding mode, maybe?
UNIMPLEMENTED_INTRINSIC(ARMVIXL, UnsafeCASLong) // High register pressure.
UNIMPLEMENTED_INTRINSIC(ARMVIXL, SystemArrayCopyChar)
-UNIMPLEMENTED_INTRINSIC(ARMVIXL, ReferenceGetReferent)
UNIMPLEMENTED_INTRINSIC(ARMVIXL, LongDivideUnsigned)
UNIMPLEMENTED_INTRINSIC(ARMVIXL, CRC32Update)
UNIMPLEMENTED_INTRINSIC(ARMVIXL, CRC32UpdateBytes)
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 4095259..cd41e1a 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -3014,6 +3014,21 @@
__ Bind(intrinsic_slow_path->GetExitLabel());
}
+static void RequestBaseMethodAddressInRegister(HInvoke* invoke) {
+ LocationSummary* locations = invoke->GetLocations();
+ if (locations != nullptr) {
+ HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect();
+ // Note: The base method address is not present yet when this is called from the
+ // PCRelativeHandlerVisitor via IsCallFreeIntrinsic() to determine whether to insert it.
+ if (invoke_static_or_direct->HasSpecialInput()) {
+ DCHECK(invoke_static_or_direct->InputAt(invoke_static_or_direct->GetSpecialInputIndex())
+ ->IsX86ComputeBaseMethodAddress());
+ locations->SetInAt(invoke_static_or_direct->GetSpecialInputIndex(),
+ Location::RequiresRegister());
+ }
+ }
+}
+
void IntrinsicLocationsBuilderX86::VisitIntegerValueOf(HInvoke* invoke) {
DCHECK(invoke->IsInvokeStaticOrDirect());
InvokeRuntimeCallingConvention calling_convention;
@@ -3022,17 +3037,7 @@
codegen_,
Location::RegisterLocation(EAX),
Location::RegisterLocation(calling_convention.GetRegisterAt(0)));
-
- LocationSummary* locations = invoke->GetLocations();
- if (locations != nullptr) {
- HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect();
- if (invoke_static_or_direct->HasSpecialInput() &&
- invoke->InputAt(invoke_static_or_direct->GetSpecialInputIndex())
- ->IsX86ComputeBaseMethodAddress()) {
- locations->SetInAt(invoke_static_or_direct->GetSpecialInputIndex(),
- Location::RequiresRegister());
- }
- }
+ RequestBaseMethodAddressInRegister(invoke);
}
void IntrinsicCodeGeneratorX86::VisitIntegerValueOf(HInvoke* invoke) {
@@ -3107,6 +3112,61 @@
}
}
+void IntrinsicLocationsBuilderX86::VisitReferenceGetReferent(HInvoke* invoke) {
+ IntrinsicVisitor::CreateReferenceGetReferentLocations(invoke, codegen_);
+ RequestBaseMethodAddressInRegister(invoke);
+}
+
+void IntrinsicCodeGeneratorX86::VisitReferenceGetReferent(HInvoke* invoke) {
+ X86Assembler* assembler = GetAssembler();
+ LocationSummary* locations = invoke->GetLocations();
+
+ Location obj = locations->InAt(0);
+ Location out = locations->Out();
+
+ SlowPathCode* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(invoke);
+ codegen_->AddSlowPath(slow_path);
+
+ if (kEmitCompilerReadBarrier) {
+ // Check self->GetWeakRefAccessEnabled().
+ ThreadOffset32 offset = Thread::WeakRefAccessEnabledOffset<kX86PointerSize>();
+ __ fs()->cmpl(Address::Absolute(offset), Immediate(0));
+ __ j(kEqual, slow_path->GetEntryLabel());
+ }
+
+ // Load the java.lang.ref.Reference class, use the output register as a temporary.
+ codegen_->LoadIntrinsicDeclaringClass(out.AsRegister<Register>(),
+ invoke->AsInvokeStaticOrDirect());
+
+ // Check static fields java.lang.ref.Reference.{disableIntrinsic,slowPathEnabled} together.
+ MemberOffset disable_intrinsic_offset = IntrinsicVisitor::GetReferenceDisableIntrinsicOffset();
+ DCHECK_ALIGNED(disable_intrinsic_offset.Uint32Value(), 2u);
+ DCHECK_EQ(disable_intrinsic_offset.Uint32Value() + 1u,
+ IntrinsicVisitor::GetReferenceSlowPathEnabledOffset().Uint32Value());
+ __ cmpw(Address(out.AsRegister<Register>(), disable_intrinsic_offset.Uint32Value()),
+ Immediate(0));
+ __ j(kNotEqual, slow_path->GetEntryLabel());
+
+ // Load the value from the field.
+ uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+ if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+ codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+ out,
+ obj.AsRegister<Register>(),
+ referent_offset,
+ /*needs_null_check=*/ true);
+ // Note that the fence is a no-op, thanks to the x86 memory model.
+ codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny); // `referent` is volatile.
+ } else {
+ __ movl(out.AsRegister<Register>(), Address(obj.AsRegister<Register>(), referent_offset));
+ codegen_->MaybeRecordImplicitNullCheck(invoke);
+ // Note that the fence is a no-op, thanks to the x86 memory model.
+ codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny); // `referent` is volatile.
+ codegen_->MaybeGenerateReadBarrierSlow(invoke, out, out, obj, referent_offset);
+ }
+ __ Bind(slow_path->GetExitLabel());
+}
+
void IntrinsicLocationsBuilderX86::VisitThreadInterrupted(HInvoke* invoke) {
LocationSummary* locations =
new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
@@ -4499,7 +4559,6 @@
}
UNIMPLEMENTED_INTRINSIC(X86, MathRoundDouble)
-UNIMPLEMENTED_INTRINSIC(X86, ReferenceGetReferent)
UNIMPLEMENTED_INTRINSIC(X86, FloatIsInfinite)
UNIMPLEMENTED_INTRINSIC(X86, DoubleIsInfinite)
UNIMPLEMENTED_INTRINSIC(X86, IntegerHighestOneBit)
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 985f095..c22fdd9 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -2659,6 +2659,59 @@
}
}
+void IntrinsicLocationsBuilderX86_64::VisitReferenceGetReferent(HInvoke* invoke) {
+ IntrinsicVisitor::CreateReferenceGetReferentLocations(invoke, codegen_);
+}
+
+void IntrinsicCodeGeneratorX86_64::VisitReferenceGetReferent(HInvoke* invoke) {
+ X86_64Assembler* assembler = GetAssembler();
+ LocationSummary* locations = invoke->GetLocations();
+
+ Location obj = locations->InAt(0);
+ Location out = locations->Out();
+
+ SlowPathCode* slow_path = new (GetAllocator()) IntrinsicSlowPathX86_64(invoke);
+ codegen_->AddSlowPath(slow_path);
+
+ if (kEmitCompilerReadBarrier) {
+ // Check self->GetWeakRefAccessEnabled().
+ ThreadOffset64 offset = Thread::WeakRefAccessEnabledOffset<kX86_64PointerSize>();
+ __ gs()->cmpl(Address::Absolute(offset, /* no_rip= */ true), Immediate(0));
+ __ j(kEqual, slow_path->GetEntryLabel());
+ }
+
+ // Load the java.lang.ref.Reference class, use the output register as a temporary.
+ codegen_->LoadIntrinsicDeclaringClass(out.AsRegister<CpuRegister>(), invoke);
+
+ // Check static fields java.lang.ref.Reference.{disableIntrinsic,slowPathEnabled} together.
+ MemberOffset disable_intrinsic_offset = IntrinsicVisitor::GetReferenceDisableIntrinsicOffset();
+ DCHECK_ALIGNED(disable_intrinsic_offset.Uint32Value(), 2u);
+ DCHECK_EQ(disable_intrinsic_offset.Uint32Value() + 1u,
+ IntrinsicVisitor::GetReferenceSlowPathEnabledOffset().Uint32Value());
+ __ cmpw(Address(out.AsRegister<CpuRegister>(), disable_intrinsic_offset.Uint32Value()),
+ Immediate(0));
+ __ j(kNotEqual, slow_path->GetEntryLabel());
+
+ // Load the value from the field.
+ uint32_t referent_offset = mirror::Reference::ReferentOffset().Uint32Value();
+ if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
+ codegen_->GenerateFieldLoadWithBakerReadBarrier(invoke,
+ out,
+ obj.AsRegister<CpuRegister>(),
+ referent_offset,
+ /*needs_null_check=*/ true);
+ // Note that the fence is a no-op, thanks to the x86-64 memory model.
+ codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny); // `referent` is volatile.
+ } else {
+ __ movl(out.AsRegister<CpuRegister>(), Address(obj.AsRegister<CpuRegister>(), referent_offset));
+ codegen_->MaybeRecordImplicitNullCheck(invoke);
+ // Note that the fence is a no-op, thanks to the x86-64 memory model.
+ codegen_->GenerateMemoryBarrier(MemBarrierKind::kLoadAny); // `referent` is volatile.
+ codegen_->MaybeGenerateReadBarrierSlow(invoke, out, out, obj, referent_offset);
+ }
+ __ Bind(slow_path->GetExitLabel());
+}
+
void IntrinsicLocationsBuilderX86_64::VisitThreadInterrupted(HInvoke* invoke) {
LocationSummary* locations =
new (allocator_) LocationSummary(invoke, LocationSummary::kNoCall, kIntrinsified);
@@ -2723,7 +2776,6 @@
}
-UNIMPLEMENTED_INTRINSIC(X86_64, ReferenceGetReferent)
UNIMPLEMENTED_INTRINSIC(X86_64, FloatIsInfinite)
UNIMPLEMENTED_INTRINSIC(X86_64, DoubleIsInfinite)
UNIMPLEMENTED_INTRINSIC(X86_64, CRC32Update)
diff --git a/runtime/thread.h b/runtime/thread.h
index 8cd16c3..b23f647 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -689,6 +689,13 @@
}
template<PointerSize pointer_size>
+ static constexpr ThreadOffset<pointer_size> WeakRefAccessEnabledOffset() {
+ return ThreadOffset<pointer_size>(
+ OFFSETOF_MEMBER(Thread, tls32_) +
+ OFFSETOF_MEMBER(tls_32bit_sized_values, weak_ref_access_enabled));
+ }
+
+ template<PointerSize pointer_size>
static constexpr ThreadOffset<pointer_size> ThreadFlagsOffset() {
return ThreadOffset<pointer_size>(
OFFSETOF_MEMBER(Thread, tls32_) +