Refactor Integer.valueOf() intrinsic implementation.
Prepare for Reference.getReferent() intrinsic implementation
by a refactoring to separate the retrieval of an intrinsic
method's declaring class to its own helper function, rather
than being a part of a larger one.
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: Ib6c0e55d0c6fcc932999428f21c51afe32ab7ef2
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index c2ae0e0..23ac91b 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -891,7 +891,6 @@
static uint32_t GetBootImageOffsetImpl(const void* object, ImageHeader::ImageSections section) {
Runtime* runtime = Runtime::Current();
- DCHECK(runtime->IsAotCompiler());
const std::vector<gc::space::ImageSpace*>& boot_image_spaces =
runtime->GetHeap()->GetBootImageSpaces();
// Check that the `object` is in the expected section of one of the boot image files.
@@ -907,6 +906,10 @@
return dchecked_integral_cast<uint32_t>(offset);
}
+uint32_t CodeGenerator::GetBootImageOffset(ObjPtr<mirror::Object> object) {
+ return GetBootImageOffsetImpl(object.Ptr(), ImageHeader::kSectionObjects);
+}
+
// NO_THREAD_SAFETY_ANALYSIS: Avoid taking the mutator lock, boot image classes are non-moveable.
uint32_t CodeGenerator::GetBootImageOffset(HLoadClass* load_class) NO_THREAD_SAFETY_ANALYSIS {
DCHECK_EQ(load_class->GetLoadKind(), HLoadClass::LoadKind::kBootImageRelRo);
@@ -929,6 +932,16 @@
return GetBootImageOffsetImpl(method, ImageHeader::kSectionArtMethods);
}
+// NO_THREAD_SAFETY_ANALYSIS: Avoid taking the mutator lock, boot image classes are non-moveable.
+uint32_t CodeGenerator::GetBootImageOffsetOfIntrinsicDeclaringClass(HInvoke* invoke)
+ NO_THREAD_SAFETY_ANALYSIS {
+ DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
+ ArtMethod* method = invoke->GetResolvedMethod();
+ DCHECK(method != nullptr);
+ ObjPtr<mirror::Class> declaring_class = method->GetDeclaringClass<kWithoutReadBarrier>();
+ return GetBootImageOffsetImpl(declaring_class.Ptr(), ImageHeader::kSectionObjects);
+}
+
void CodeGenerator::BlockIfInRegister(Location location, bool is_out) const {
// The DCHECKS below check that a register is not specified twice in
// the summary. The out location can overlap with an input, so we need
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 22804a9..bd5483c 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -630,9 +630,12 @@
Location runtime_return_location);
void GenerateLoadMethodTypeRuntimeCall(HLoadMethodType* method_type);
- uint32_t GetBootImageOffset(HLoadClass* load_class);
- uint32_t GetBootImageOffset(HLoadString* load_string);
- uint32_t GetBootImageOffset(HInvoke* invoke);
+ static uint32_t GetBootImageOffset(ObjPtr<mirror::Object> object)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+ static uint32_t GetBootImageOffset(HLoadClass* load_class);
+ static uint32_t GetBootImageOffset(HLoadString* load_string);
+ static uint32_t GetBootImageOffset(HInvoke* invoke);
+ static uint32_t GetBootImageOffsetOfIntrinsicDeclaringClass(HInvoke* invoke);
static void CreateSystemArrayCopyLocationSummary(HInvoke* invoke);
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 5920a48..2c7cf85 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -4956,28 +4956,23 @@
}
}
-void CodeGeneratorARM64::AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke,
- uint32_t boot_image_offset) {
- DCHECK(invoke->IsStatic());
- InvokeRuntimeCallingConvention calling_convention;
- Register argument = calling_convention.GetRegisterAt(0);
+void CodeGeneratorARM64::LoadIntrinsicDeclaringClass(vixl::aarch64::Register reg, HInvoke* invoke) {
+ DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
if (GetCompilerOptions().IsBootImage()) {
- DCHECK_EQ(boot_image_offset, IntrinsicVisitor::IntegerValueOfInfo::kInvalidReference);
// Load the class the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
MethodReference target_method = invoke->GetResolvedMethodReference();
dex::TypeIndex type_idx = target_method.dex_file->GetMethodId(target_method.index).class_idx_;
// Add ADRP with its PC-relative type patch.
vixl::aarch64::Label* adrp_label = NewBootImageTypePatch(*target_method.dex_file, type_idx);
- EmitAdrpPlaceholder(adrp_label, argument.X());
+ EmitAdrpPlaceholder(adrp_label, reg.X());
// Add ADD with its PC-relative type patch.
vixl::aarch64::Label* add_label =
NewBootImageTypePatch(*target_method.dex_file, type_idx, adrp_label);
- EmitAddPlaceholder(add_label, argument.X(), argument.X());
+ EmitAddPlaceholder(add_label, reg.X(), reg.X());
} else {
- LoadBootImageAddress(argument, boot_image_offset);
+ uint32_t boot_image_offset = GetBootImageOffsetOfIntrinsicDeclaringClass(invoke);
+ LoadBootImageAddress(reg, boot_image_offset);
}
- InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
- CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
}
template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)>
@@ -5267,7 +5262,7 @@
}
case HLoadClass::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
- uint32_t boot_image_offset = codegen_->GetBootImageOffset(cls);
+ uint32_t boot_image_offset = CodeGenerator::GetBootImageOffset(cls);
// Add ADRP with its PC-relative .data.bimg.rel.ro patch.
vixl::aarch64::Label* adrp_label = codegen_->NewBootImageRelRoPatch(boot_image_offset);
codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
@@ -5443,7 +5438,7 @@
case HLoadString::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
// Add ADRP with its PC-relative .data.bimg.rel.ro patch.
- uint32_t boot_image_offset = codegen_->GetBootImageOffset(load);
+ uint32_t boot_image_offset = CodeGenerator::GetBootImageOffset(load);
vixl::aarch64::Label* adrp_label = codegen_->NewBootImageRelRoPatch(boot_image_offset);
codegen_->EmitAdrpPlaceholder(adrp_label, out.X());
// Add LDR with its PC-relative .data.bimg.rel.ro patch.
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index bebf762..eb374b5 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -787,7 +787,7 @@
vixl::aarch64::Register base);
void LoadBootImageAddress(vixl::aarch64::Register reg, uint32_t boot_image_reference);
- void AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke, uint32_t boot_image_offset);
+ void LoadIntrinsicDeclaringClass(vixl::aarch64::Register reg, HInvoke* invoke);
void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) override;
bool NeedsThunkCode(const linker::LinkerPatch& patch) const override;
diff --git a/compiler/optimizing/code_generator_arm_vixl.cc b/compiler/optimizing/code_generator_arm_vixl.cc
index 76b8be1..00b2586 100644
--- a/compiler/optimizing/code_generator_arm_vixl.cc
+++ b/compiler/optimizing/code_generator_arm_vixl.cc
@@ -7415,7 +7415,7 @@
case HLoadClass::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
- codegen_->NewBootImageRelRoPatch(codegen_->GetBootImageOffset(cls));
+ codegen_->NewBootImageRelRoPatch(CodeGenerator::GetBootImageOffset(cls));
codegen_->EmitMovwMovtPlaceholder(labels, out);
__ Ldr(out, MemOperand(out, /* offset= */ 0));
break;
@@ -7640,7 +7640,7 @@
case HLoadString::LoadKind::kBootImageRelRo: {
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
CodeGeneratorARMVIXL::PcRelativePatchInfo* labels =
- codegen_->NewBootImageRelRoPatch(codegen_->GetBootImageOffset(load));
+ codegen_->NewBootImageRelRoPatch(CodeGenerator::GetBootImageOffset(load));
codegen_->EmitMovwMovtPlaceholder(labels, out);
__ Ldr(out, MemOperand(out, /* offset= */ 0));
return;
@@ -9410,23 +9410,18 @@
}
}
-void CodeGeneratorARMVIXL::AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke,
- uint32_t boot_image_offset) {
- DCHECK(invoke->IsStatic());
- InvokeRuntimeCallingConventionARMVIXL calling_convention;
- vixl32::Register argument = calling_convention.GetRegisterAt(0);
+void CodeGeneratorARMVIXL::LoadIntrinsicDeclaringClass(vixl32::Register reg, HInvoke* invoke) {
+ DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
if (GetCompilerOptions().IsBootImage()) {
- DCHECK_EQ(boot_image_offset, IntrinsicVisitor::IntegerValueOfInfo::kInvalidReference);
// Load the class the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
MethodReference target_method = invoke->GetResolvedMethodReference();
dex::TypeIndex type_idx = target_method.dex_file->GetMethodId(target_method.index).class_idx_;
PcRelativePatchInfo* labels = NewBootImageTypePatch(*target_method.dex_file, type_idx);
- EmitMovwMovtPlaceholder(labels, argument);
+ EmitMovwMovtPlaceholder(labels, reg);
} else {
- LoadBootImageAddress(argument, boot_image_offset);
+ uint32_t boot_image_offset = GetBootImageOffsetOfIntrinsicDeclaringClass(invoke);
+ LoadBootImageAddress(reg, boot_image_offset);
}
- InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
- CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
}
template <linker::LinkerPatch (*Factory)(size_t, const DexFile*, uint32_t, uint32_t)>
diff --git a/compiler/optimizing/code_generator_arm_vixl.h b/compiler/optimizing/code_generator_arm_vixl.h
index 12594ed..8f3d41c 100644
--- a/compiler/optimizing/code_generator_arm_vixl.h
+++ b/compiler/optimizing/code_generator_arm_vixl.h
@@ -638,7 +638,7 @@
Handle<mirror::Class> handle);
void LoadBootImageAddress(vixl::aarch32::Register reg, uint32_t boot_image_reference);
- void AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke, uint32_t boot_image_offset);
+ void LoadIntrinsicDeclaringClass(vixl::aarch32::Register reg, HInvoke* invoke);
void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) override;
bool NeedsThunkCode(const linker::LinkerPatch& patch) const override;
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 0f68f3f..916f223 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -5506,29 +5506,24 @@
}
}
-void CodeGeneratorX86::AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke,
- uint32_t boot_image_offset) {
- DCHECK(invoke->IsStatic());
- InvokeRuntimeCallingConvention calling_convention;
- Register argument = calling_convention.GetRegisterAt(0);
+void CodeGeneratorX86::LoadIntrinsicDeclaringClass(Register reg, HInvokeStaticOrDirect* invoke) {
+ DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
if (GetCompilerOptions().IsBootImage()) {
- DCHECK_EQ(boot_image_offset, IntrinsicVisitor::IntegerValueOfInfo::kInvalidReference);
// Load the class the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
HX86ComputeBaseMethodAddress* method_address =
invoke->InputAt(invoke->GetSpecialInputIndex())->AsX86ComputeBaseMethodAddress();
DCHECK(method_address != nullptr);
Register method_address_reg =
invoke->GetLocations()->InAt(invoke->GetSpecialInputIndex()).AsRegister<Register>();
- __ leal(argument, Address(method_address_reg, CodeGeneratorX86::kPlaceholder32BitOffset));
+ __ leal(reg, Address(method_address_reg, CodeGeneratorX86::kPlaceholder32BitOffset));
MethodReference target_method = invoke->GetResolvedMethodReference();
dex::TypeIndex type_idx = target_method.dex_file->GetMethodId(target_method.index).class_idx_;
boot_image_type_patches_.emplace_back(method_address, target_method.dex_file, type_idx.index_);
__ Bind(&boot_image_type_patches_.back().label);
} else {
- LoadBootImageAddress(argument, boot_image_offset, invoke);
+ uint32_t boot_image_offset = GetBootImageOffsetOfIntrinsicDeclaringClass(invoke);
+ LoadBootImageAddress(reg, boot_image_offset, invoke);
}
- InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
- CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
}
// The label points to the end of the "movl" or another instruction but the literal offset
@@ -7147,7 +7142,7 @@
Register method_address = locations->InAt(0).AsRegister<Register>();
__ movl(out, Address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset));
codegen_->RecordBootImageRelRoPatch(cls->InputAt(0)->AsX86ComputeBaseMethodAddress(),
- codegen_->GetBootImageOffset(cls));
+ CodeGenerator::GetBootImageOffset(cls));
break;
}
case HLoadClass::LoadKind::kBssEntry:
@@ -7346,7 +7341,7 @@
Register method_address = locations->InAt(0).AsRegister<Register>();
__ movl(out, Address(method_address, CodeGeneratorX86::kPlaceholder32BitOffset));
codegen_->RecordBootImageRelRoPatch(load->InputAt(0)->AsX86ComputeBaseMethodAddress(),
- codegen_->GetBootImageOffset(load));
+ CodeGenerator::GetBootImageOffset(load));
return;
}
case HLoadString::LoadKind::kBssEntry: {
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 119494c..b024eeb 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -495,7 +495,7 @@
void LoadBootImageAddress(Register reg,
uint32_t boot_image_reference,
HInvokeStaticOrDirect* invoke);
- void AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke, uint32_t boot_image_offset);
+ void LoadIntrinsicDeclaringClass(Register reg, HInvokeStaticOrDirect* invoke);
Label* NewJitRootStringPatch(const DexFile& dex_file,
dex::StringIndex string_index,
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index dac04a5..b8496db 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -1254,25 +1254,20 @@
}
}
-void CodeGeneratorX86_64::AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke,
- uint32_t boot_image_offset) {
- DCHECK(invoke->IsStatic());
- InvokeRuntimeCallingConvention calling_convention;
- CpuRegister argument = CpuRegister(calling_convention.GetRegisterAt(0));
+void CodeGeneratorX86_64::LoadIntrinsicDeclaringClass(CpuRegister reg, HInvoke* invoke) {
+ DCHECK_NE(invoke->GetIntrinsic(), Intrinsics::kNone);
if (GetCompilerOptions().IsBootImage()) {
- DCHECK_EQ(boot_image_offset, IntrinsicVisitor::IntegerValueOfInfo::kInvalidReference);
// Load the class the same way as for HLoadClass::LoadKind::kBootImageLinkTimePcRelative.
- __ leal(argument,
+ __ leal(reg,
Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
MethodReference target_method = invoke->GetResolvedMethodReference();
dex::TypeIndex type_idx = target_method.dex_file->GetMethodId(target_method.index).class_idx_;
boot_image_type_patches_.emplace_back(target_method.dex_file, type_idx.index_);
__ Bind(&boot_image_type_patches_.back().label);
} else {
- LoadBootImageAddress(argument, boot_image_offset);
+ uint32_t boot_image_offset = GetBootImageOffsetOfIntrinsicDeclaringClass(invoke);
+ LoadBootImageAddress(reg, boot_image_offset);
}
- InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
- CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
}
// The label points to the end of the "movl" or another instruction but the literal offset
@@ -6274,7 +6269,7 @@
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
__ movl(out,
Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
- codegen_->RecordBootImageRelRoPatch(codegen_->GetBootImageOffset(cls));
+ codegen_->RecordBootImageRelRoPatch(CodeGenerator::GetBootImageOffset(cls));
break;
}
case HLoadClass::LoadKind::kBssEntry:
@@ -6433,7 +6428,7 @@
DCHECK(!codegen_->GetCompilerOptions().IsBootImage());
__ movl(out,
Address::Absolute(CodeGeneratorX86_64::kPlaceholder32BitOffset, /* no_rip= */ false));
- codegen_->RecordBootImageRelRoPatch(codegen_->GetBootImageOffset(load));
+ codegen_->RecordBootImageRelRoPatch(CodeGenerator::GetBootImageOffset(load));
return;
}
case HLoadString::LoadKind::kBssEntry: {
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index 2c93f18..6038223 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -475,7 +475,7 @@
Handle<mirror::Class> handle);
void LoadBootImageAddress(CpuRegister reg, uint32_t boot_image_reference);
- void AllocateInstanceForIntrinsic(HInvokeStaticOrDirect* invoke, uint32_t boot_image_offset);
+ void LoadIntrinsicDeclaringClass(CpuRegister reg, HInvoke* invoke);
void EmitLinkerPatches(ArenaVector<linker::LinkerPatch>* linker_patches) override;
diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc
index 653d92a..1663ee9 100644
--- a/compiler/optimizing/intrinsics.cc
+++ b/compiler/optimizing/intrinsics.cc
@@ -21,6 +21,7 @@
#include "base/utils.h"
#include "class_linker.h"
#include "class_root-inl.h"
+#include "code_generator.h"
#include "dex/invoke_type.h"
#include "driver/compiler_options.h"
#include "gc/space/image_space.h"
@@ -152,13 +153,14 @@
// 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()) {
+ return;
+ }
if (compiler_options.IsBootImage()) {
- // Piggyback on the method load kind to determine whether we can use PC-relative addressing.
- // 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 (!invoke->AsInvokeStaticOrDirect()->HasPcRelativeMethodLoadKind()) {
- return;
- }
if (!compiler_options.IsImageClass(kIntegerCacheDescriptor) ||
!compiler_options.IsImageClass(kIntegerDescriptor)) {
return;
@@ -261,18 +263,10 @@
return GetIntegerCacheField(cache_class, kLowFieldName);
}
-static uint32_t CalculateBootImageOffset(ObjPtr<mirror::Object> object)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- gc::Heap* heap = Runtime::Current()->GetHeap();
- DCHECK(heap->ObjectIsInBootImageSpace(object));
- return reinterpret_cast<const uint8_t*>(object.Ptr()) - heap->GetBootImageSpaces()[0]->Begin();
-}
-
inline IntrinsicVisitor::IntegerValueOfInfo::IntegerValueOfInfo()
: value_offset(0),
low(0),
length(0u),
- integer_boot_image_offset(kInvalidReference),
value_boot_image_reference(kInvalidReference) {}
IntrinsicVisitor::IntegerValueOfInfo IntrinsicVisitor::ComputeIntegerValueOfInfo(
@@ -293,8 +287,8 @@
IntegerValueOfInfo info;
if (compiler_options.IsBootImage()) {
- ObjPtr<mirror::Class> integer_class =
- LookupInitializedClass(self, class_linker, kIntegerDescriptor);
+ ObjPtr<mirror::Class> integer_class = invoke->GetResolvedMethod()->GetDeclaringClass();
+ DCHECK(integer_class->DescriptorEquals(kIntegerDescriptor));
ArtField* value_field = integer_class->FindDeclaredInstanceField(kValueFieldName, "I");
DCHECK(value_field != nullptr);
info.value_offset = value_field->GetOffset().Uint32Value();
@@ -304,7 +298,6 @@
int32_t high = GetIntegerCacheField(cache_class, kHighFieldName);
info.length = dchecked_integral_cast<uint32_t>(high - info.low + 1);
- info.integer_boot_image_offset = IntegerValueOfInfo::kInvalidReference;
if (invoke->InputAt(0)->IsIntConstant()) {
int32_t input_value = invoke->InputAt(0)->AsIntConstant()->GetValue();
uint32_t index = static_cast<uint32_t>(input_value) - static_cast<uint32_t>(info.low);
@@ -340,21 +333,20 @@
info.length = dchecked_integral_cast<uint32_t>(
IntrinsicObjects::GetIntegerValueOfCache(boot_image_live_objects)->GetLength());
- info.integer_boot_image_offset = CalculateBootImageOffset(integer_class);
if (invoke->InputAt(0)->IsIntConstant()) {
int32_t input_value = invoke->InputAt(0)->AsIntConstant()->GetValue();
uint32_t index = static_cast<uint32_t>(input_value) - static_cast<uint32_t>(info.low);
if (index < static_cast<uint32_t>(info.length)) {
ObjPtr<mirror::Object> integer =
IntrinsicObjects::GetIntegerValueOfObject(boot_image_live_objects, index);
- info.value_boot_image_reference = CalculateBootImageOffset(integer);
+ info.value_boot_image_reference = CodeGenerator::GetBootImageOffset(integer);
} else {
// Not in the cache.
info.value_boot_image_reference = IntegerValueOfInfo::kInvalidReference;
}
} else {
info.array_data_boot_image_reference =
- CalculateBootImageOffset(boot_image_live_objects) +
+ CodeGenerator::GetBootImageOffset(boot_image_live_objects) +
IntrinsicObjects::GetIntegerValueOfArrayDataOffset(boot_image_live_objects).Uint32Value();
}
}
diff --git a/compiler/optimizing/intrinsics.h b/compiler/optimizing/intrinsics.h
index f3c6d8b..cc26e41 100644
--- a/compiler/optimizing/intrinsics.h
+++ b/compiler/optimizing/intrinsics.h
@@ -117,9 +117,6 @@
// The length of the cache array.
uint32_t length;
- // Boot image offset of java.lang.Integer for allocating an instance.
- uint32_t integer_boot_image_offset; // Set to kInvalidReference when compiling the boot image.
-
// This union contains references to the boot image. For app AOT or JIT compilation,
// these are the boot image offsets of the target. For boot image compilation, the
// location shall be known only at link time, so we encode a symbolic reference using
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index c38f5d6..a7d5b31 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -2825,6 +2825,12 @@
Register out = RegisterFrom(locations->Out(), DataType::Type::kReference);
UseScratchRegisterScope temps(masm);
Register temp = temps.AcquireW();
+ auto allocate_instance = [&]() {
+ DCHECK(out.X().Is(InvokeRuntimeCallingConvention().GetRegisterAt(0)));
+ codegen_->LoadIntrinsicDeclaringClass(out, invoke);
+ codegen_->InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
+ CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
+ };
if (invoke->InputAt(0)->IsConstant()) {
int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
if (static_cast<uint32_t>(value - info.low) < info.length) {
@@ -2836,12 +2842,10 @@
// Allocate and initialize a new j.l.Integer.
// TODO: If we JIT, we could allocate the j.l.Integer now, and store it in the
// JIT object table.
- codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
- info.integer_boot_image_offset);
+ allocate_instance();
__ Mov(temp.W(), value);
__ Str(temp.W(), HeapOperand(out.W(), info.value_offset));
- // `value` is a final field :-( Ideally, we'd merge this memory barrier with the allocation
- // one.
+ // `value` is a final field, emit the barrier after we have stored it.
codegen_->GenerateMemoryBarrier(MemBarrierKind::kStoreStore);
}
} else {
@@ -2861,11 +2865,9 @@
__ B(&done);
__ Bind(&allocate);
// Otherwise allocate and initialize a new j.l.Integer.
- codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
- info.integer_boot_image_offset);
+ allocate_instance();
__ Str(in.W(), HeapOperand(out.W(), info.value_offset));
- // `value` is a final field :-( Ideally, we'd merge this memory barrier with the allocation
- // one.
+ // `value` is a final field, emit the barrier after we have stored it.
codegen_->GenerateMemoryBarrier(MemBarrierKind::kStoreStore);
__ Bind(&done);
}
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index fdef006..2901c47 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -2945,6 +2945,12 @@
vixl32::Register out = RegisterFrom(locations->Out());
UseScratchRegisterScope temps(assembler->GetVIXLAssembler());
vixl32::Register temp = temps.Acquire();
+ auto allocate_instance = [&]() {
+ DCHECK(out.Is(InvokeRuntimeCallingConventionARMVIXL().GetRegisterAt(0)));
+ codegen_->LoadIntrinsicDeclaringClass(out, invoke);
+ codegen_->InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
+ CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
+ };
if (invoke->InputAt(0)->IsConstant()) {
int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
if (static_cast<uint32_t>(value - info.low) < info.length) {
@@ -2956,12 +2962,10 @@
// Allocate and initialize a new j.l.Integer.
// TODO: If we JIT, we could allocate the j.l.Integer now, and store it in the
// JIT object table.
- codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
- info.integer_boot_image_offset);
+ allocate_instance();
__ Mov(temp, value);
assembler->StoreToOffset(kStoreWord, temp, out, info.value_offset);
- // `value` is a final field :-( Ideally, we'd merge this memory barrier with the allocation
- // one.
+ // `value` is a final field, emit the barrier after we have stored it.
codegen_->GenerateMemoryBarrier(MemBarrierKind::kStoreStore);
}
} else {
@@ -2979,11 +2983,9 @@
__ B(&done);
__ Bind(&allocate);
// Otherwise allocate and initialize a new j.l.Integer.
- codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
- info.integer_boot_image_offset);
+ allocate_instance();
assembler->StoreToOffset(kStoreWord, in, out, info.value_offset);
- // `value` is a final field :-( Ideally, we'd merge this memory barrier with the allocation
- // one.
+ // `value` is a final field, emit the barrier after we have stored it.
codegen_->GenerateMemoryBarrier(MemBarrierKind::kStoreStore);
__ Bind(&done);
}
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 045cacd..4095259 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -3043,7 +3043,12 @@
X86Assembler* assembler = GetAssembler();
Register out = locations->Out().AsRegister<Register>();
- InvokeRuntimeCallingConvention calling_convention;
+ auto allocate_instance = [&]() {
+ DCHECK_EQ(out, InvokeRuntimeCallingConvention().GetRegisterAt(0));
+ codegen_->LoadIntrinsicDeclaringClass(out, invoke->AsInvokeStaticOrDirect());
+ codegen_->InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
+ CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
+ };
if (invoke->InputAt(0)->IsConstant()) {
int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
if (static_cast<uint32_t>(value - info.low) < info.length) {
@@ -3056,8 +3061,7 @@
// Allocate and initialize a new j.l.Integer.
// TODO: If we JIT, we could allocate the j.l.Integer now, and store it in the
// JIT object table.
- codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
- info.integer_boot_image_offset);
+ allocate_instance();
__ movl(Address(out, info.value_offset), Immediate(value));
}
} else {
@@ -3097,8 +3101,7 @@
__ jmp(&done);
__ Bind(&allocate);
// Otherwise allocate and initialize a new j.l.Integer.
- codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
- info.integer_boot_image_offset);
+ allocate_instance();
__ movl(Address(out, info.value_offset), in);
__ Bind(&done);
}
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index 7ebc632..985f095 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -2616,6 +2616,11 @@
CpuRegister out = locations->Out().AsRegister<CpuRegister>();
InvokeRuntimeCallingConvention calling_convention;
CpuRegister argument = CpuRegister(calling_convention.GetRegisterAt(0));
+ auto allocate_instance = [&]() {
+ codegen_->LoadIntrinsicDeclaringClass(argument, invoke);
+ codegen_->InvokeRuntime(kQuickAllocObjectInitialized, invoke, invoke->GetDexPc());
+ CheckEntrypointTypes<kQuickAllocObjectWithChecks, void*, mirror::Class*>();
+ };
if (invoke->InputAt(0)->IsIntConstant()) {
int32_t value = invoke->InputAt(0)->AsIntConstant()->GetValue();
if (static_cast<uint32_t>(value - info.low) < info.length) {
@@ -2627,8 +2632,7 @@
// Allocate and initialize a new j.l.Integer.
// TODO: If we JIT, we could allocate the j.l.Integer now, and store it in the
// JIT object table.
- codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
- info.integer_boot_image_offset);
+ allocate_instance();
__ movl(Address(out, info.value_offset), Immediate(value));
}
} else {
@@ -2649,8 +2653,7 @@
__ jmp(&done);
__ Bind(&allocate);
// Otherwise allocate and initialize a new j.l.Integer.
- codegen_->AllocateInstanceForIntrinsic(invoke->AsInvokeStaticOrDirect(),
- info.integer_boot_image_offset);
+ allocate_instance();
__ movl(Address(out, info.value_offset), in);
__ Bind(&done);
}