ART: Move DexCache arrays to native.
This CL has a companion CL in libcore/
https://android-review.googlesource.com/162985
Change-Id: Icbc9e20ad1b565e603195b12714762bb446515fa
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index 981ab2c..eb8730c 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -677,10 +677,11 @@
FALLTHROUGH_INTENDED;
case 1: // Get method->dex_cache_resolved_methods_
if (!use_pc_rel) {
- cg->LoadRefDisp(arg0_ref,
- ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
- arg0_ref,
- kNotVolatile);
+ cg->LoadBaseDisp(arg0_ref,
+ ArtMethod::DexCacheResolvedMethodsOffset(kArmPointerSize).Int32Value(),
+ arg0_ref,
+ k32,
+ kNotVolatile);
}
// Set up direct code if known.
if (direct_code != 0) {
@@ -702,8 +703,8 @@
CHECK_EQ(cu->dex_file, target_method.dex_file);
if (!use_pc_rel) {
cg->LoadRefDisp(arg0_ref,
- mirror::ObjectArray<mirror::Object>::OffsetOfElement(
- target_method.dex_method_index).Int32Value(),
+ cg->GetCachePointerOffset(target_method.dex_method_index,
+ kArmPointerSize),
arg0_ref,
kNotVolatile);
} else {
diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc
index 83a6aff..036da2e 100644
--- a/compiler/dex/quick/arm64/call_arm64.cc
+++ b/compiler/dex/quick/arm64/call_arm64.cc
@@ -511,10 +511,11 @@
FALLTHROUGH_INTENDED;
case 1: // Get method->dex_cache_resolved_methods_
if (!use_pc_rel) {
- cg->LoadRefDisp(arg0_ref,
- ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
- arg0_ref,
- kNotVolatile);
+ cg->LoadBaseDisp(arg0_ref,
+ ArtMethod::DexCacheResolvedMethodsOffset(kArm64PointerSize).Int32Value(),
+ arg0_ref,
+ k64,
+ kNotVolatile);
}
// Set up direct code if known.
if (direct_code != 0) {
@@ -536,8 +537,9 @@
CHECK_EQ(cu->dex_file, target_method.dex_file);
if (!use_pc_rel) {
cg->LoadWordDisp(arg0_ref,
- mirror::Array::DataOffset(kArm64PointerSize).Uint32Value() +
- target_method.dex_method_index * kArm64PointerSize, arg0_ref);
+ cg->GetCachePointerOffset(target_method.dex_method_index,
+ kArm64PointerSize),
+ arg0_ref);
} else {
size_t offset = cg->dex_cache_arrays_layout_.MethodOffset(target_method.dex_method_index);
cg->OpPcRelDexCacheArrayLoad(cu->dex_file, offset, arg0_ref, true);
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc
index af10817..2a1d644 100644
--- a/compiler/dex/quick/gen_common.cc
+++ b/compiler/dex/quick/gen_common.cc
@@ -88,24 +88,30 @@
r_result));
}
+void Mir2Lir::LoadTypeFromCache(uint32_t type_index, RegStorage class_reg) {
+ if (CanUseOpPcRelDexCacheArrayLoad()) {
+ uint32_t offset = dex_cache_arrays_layout_.TypeOffset(type_index);
+ OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg, false);
+ } else {
+ RegStorage r_method = LoadCurrMethodWithHint(class_reg);
+ MemberOffset resolved_types_offset = ArtMethod::DexCacheResolvedTypesOffset(
+ GetInstructionSetPointerSize(cu_->instruction_set));
+ LoadBaseDisp(r_method, resolved_types_offset.Int32Value(), class_reg,
+ cu_->target64 ? k64 : k32, kNotVolatile);
+ int32_t offset_of_type = GetCacheOffset(type_index);
+ LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
+ }
+}
+
RegStorage Mir2Lir::GenGetOtherTypeForSgetSput(const MirSFieldLoweringInfo& field_info,
int opt_flags) {
DCHECK_NE(field_info.StorageIndex(), DexFile::kDexNoIndex);
// May do runtime call so everything to home locations.
FlushAllRegs();
+ // Using fixed register to sync with possible call to runtime support.
RegStorage r_base = TargetReg(kArg0, kRef);
LockTemp(r_base);
- if (CanUseOpPcRelDexCacheArrayLoad()) {
- uint32_t offset = dex_cache_arrays_layout_.TypeOffset(field_info.StorageIndex());
- OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, r_base, false);
- } else {
- // Using fixed register to sync with possible call to runtime support.
- RegStorage r_method = LoadCurrMethodWithHint(r_base);
- LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(), r_base,
- kNotVolatile);
- int32_t offset_of_field = ObjArray::OffsetOfElement(field_info.StorageIndex()).Int32Value();
- LoadRefDisp(r_base, offset_of_field, r_base, kNotVolatile);
- }
+ LoadTypeFromCache(field_info.StorageIndex(), r_base);
// r_base now points at static storage (Class*) or null if the type is not yet resolved.
LIR* unresolved_branch = nullptr;
if (!field_info.IsClassInDexCache() && (opt_flags & MIR_CLASS_IS_IN_DEX_CACHE) == 0) {
@@ -1029,19 +1035,7 @@
} else {
rl_result = EvalLoc(rl_dest, kRefReg, true);
// We don't need access checks, load type from dex cache
- if (CanUseOpPcRelDexCacheArrayLoad()) {
- size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
- OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, rl_result.reg, false);
- } else {
- int32_t dex_cache_offset =
- ArtMethod::DexCacheResolvedTypesOffset().Int32Value();
- RegStorage res_reg = AllocTempRef();
- RegStorage r_method = LoadCurrMethodWithHint(res_reg);
- LoadRefDisp(r_method, dex_cache_offset, res_reg, kNotVolatile);
- int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
- LoadRefDisp(res_reg, offset_of_type, rl_result.reg, kNotVolatile);
- FreeTemp(res_reg);
- }
+ LoadTypeFromCache(type_idx, rl_result.reg);
if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file,
type_idx) || ForceSlowTypePath(cu_)) {
// Slow path, at runtime test if type is null and if so initialize
@@ -1054,8 +1048,7 @@
void Mir2Lir::GenConstString(uint32_t string_idx, RegLocation rl_dest) {
/* NOTE: Most strings should be available at compile time */
- int32_t offset_of_string = mirror::ObjectArray<mirror::String>::OffsetOfElement(string_idx).
- Int32Value();
+ int32_t offset_of_string = GetCacheOffset(string_idx);
if (!cu_->compiler_driver->CanAssumeStringIsPresentInDexCache(
*cu_->dex_file, string_idx) || ForceSlowStringPath(cu_)) {
// slow path, resolve string if not in dex cache
@@ -1073,7 +1066,8 @@
RegStorage r_method = LoadCurrMethodWithHint(arg0);
LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(), arg0, kNotVolatile);
// Declaring class to dex cache strings.
- LoadRefDisp(arg0, mirror::Class::DexCacheStringsOffset().Int32Value(), arg0, kNotVolatile);
+ LoadBaseDisp(arg0, mirror::Class::DexCacheStringsOffset().Int32Value(), arg0,
+ cu_->target64 ? k64 : k32, kNotVolatile);
LoadRefDisp(arg0, offset_of_string, ret0, kNotVolatile);
}
@@ -1091,8 +1085,8 @@
RegStorage res_reg = AllocTempRef();
LoadRefDisp(rl_method.reg, ArtMethod::DeclaringClassOffset().Int32Value(), res_reg,
kNotVolatile);
- LoadRefDisp(res_reg, mirror::Class::DexCacheStringsOffset().Int32Value(), res_reg,
- kNotVolatile);
+ LoadBaseDisp(res_reg, mirror::Class::DexCacheStringsOffset().Int32Value(), res_reg,
+ cu_->target64 ? k64 : k32, kNotVolatile);
LoadRefDisp(res_reg, offset_of_string, rl_result.reg, kNotVolatile);
FreeTemp(res_reg);
}
@@ -1176,19 +1170,10 @@
kNotVolatile);
LoadRefDisp(object.reg, mirror::Object::ClassOffset().Int32Value(), object_class,
kNotVolatile);
- } else if (CanUseOpPcRelDexCacheArrayLoad()) {
- size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
- OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, check_class, false);
- LoadRefDisp(object.reg, mirror::Object::ClassOffset().Int32Value(), object_class,
- kNotVolatile);
} else {
- RegStorage r_method = LoadCurrMethodWithHint(check_class);
- LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
- check_class, kNotVolatile);
+ LoadTypeFromCache(type_idx, check_class);
LoadRefDisp(object.reg, mirror::Object::ClassOffset().Int32Value(), object_class,
kNotVolatile);
- int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
- LoadRefDisp(check_class, offset_of_type, check_class, kNotVolatile);
}
// FIXME: what should we be comparing here? compressed or decompressed references?
@@ -1239,17 +1224,8 @@
LoadValueDirectFixed(rl_src, ref_reg); // kArg0 <= ref
}
- if (CanUseOpPcRelDexCacheArrayLoad()) {
- size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
- OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg, false);
- } else {
- RegStorage r_method = LoadCurrMethodWithHint(class_reg);
- // Load dex cache entry into class_reg (kArg2)
- LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
- class_reg, kNotVolatile);
- int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
- LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
- }
+ // Load dex cache entry into class_reg (kArg2)
+ LoadTypeFromCache(type_idx, class_reg);
if (!can_assume_type_is_in_dex_cache) {
GenIfNullUseHelperImm(class_reg, kQuickInitializeType, type_idx);
@@ -1370,17 +1346,7 @@
class_reg, kNotVolatile);
} else {
// Load dex cache entry into class_reg (kArg2)
- if (CanUseOpPcRelDexCacheArrayLoad()) {
- size_t offset = dex_cache_arrays_layout_.TypeOffset(type_idx);
- OpPcRelDexCacheArrayLoad(cu_->dex_file, offset, class_reg, false);
- } else {
- RegStorage r_method = LoadCurrMethodWithHint(class_reg);
-
- LoadRefDisp(r_method, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
- class_reg, kNotVolatile);
- int32_t offset_of_type = ClassArray::OffsetOfElement(type_idx).Int32Value();
- LoadRefDisp(class_reg, offset_of_type, class_reg, kNotVolatile);
- }
+ LoadTypeFromCache(type_idx, class_reg);
if (!cu_->compiler_driver->CanAssumeTypeIsPresentInDexCache(*cu_->dex_file, type_idx)) {
// Need to test presence of type in dex cache at runtime
GenIfNullUseHelperImm(class_reg, kQuickInitializeType, type_idx);
diff --git a/compiler/dex/quick/mips/call_mips.cc b/compiler/dex/quick/mips/call_mips.cc
index 853980d..8863c05 100644
--- a/compiler/dex/quick/mips/call_mips.cc
+++ b/compiler/dex/quick/mips/call_mips.cc
@@ -415,10 +415,11 @@
* Bit of a hack here - in the absence of a real scheduling pass,
* emit the next instruction in static & direct invoke sequences.
*/
-static int NextSDCallInsn(CompilationUnit* cu, CallInfo* info, int state,
- const MethodReference& target_method, uint32_t, uintptr_t direct_code,
- uintptr_t direct_method, InvokeType type) {
- Mir2Lir* cg = static_cast<Mir2Lir*>(cu->cg.get());
+int MipsMir2Lir::MipsNextSDCallInsn(CompilationUnit* cu, CallInfo* info, int state,
+ const MethodReference& target_method, uint32_t,
+ uintptr_t direct_code, uintptr_t direct_method,
+ InvokeType type) {
+ MipsMir2Lir* cg = static_cast<MipsMir2Lir*>(cu->cg.get());
if (info->string_init_offset != 0) {
RegStorage arg0_ref = cg->TargetReg(kArg0, kRef);
switch (state) {
@@ -469,10 +470,12 @@
cg->LoadCurrMethodDirect(arg0_ref);
break;
case 1: // Get method->dex_cache_resolved_methods_
- cg->LoadRefDisp(arg0_ref,
- ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
- arg0_ref,
- kNotVolatile);
+ cg->LoadBaseDisp(arg0_ref,
+ ArtMethod::DexCacheResolvedMethodsOffset(
+ cu->target64 ? kMips64PointerSize : kMipsPointerSize).Int32Value(),
+ arg0_ref,
+ cu->target64 ? k64 : k32,
+ kNotVolatile);
// Set up direct code if known.
if (direct_code != 0) {
if (direct_code != static_cast<uintptr_t>(-1)) {
@@ -492,8 +495,9 @@
CHECK_EQ(cu->dex_file, target_method.dex_file);
const size_t pointer_size = GetInstructionSetPointerSize(cu->instruction_set);
cg->LoadWordDisp(arg0_ref,
- mirror::Array::DataOffset(pointer_size).Uint32Value() +
- target_method.dex_method_index * pointer_size, arg0_ref);
+ cg->GetCachePointerOffset(target_method.dex_method_index,
+ pointer_size),
+ arg0_ref);
break;
}
case 3: // Grab the code from the method*
@@ -512,7 +516,7 @@
}
NextCallInsn MipsMir2Lir::GetNextSDCallInsn() {
- return NextSDCallInsn;
+ return MipsNextSDCallInsn;
}
LIR* MipsMir2Lir::GenCallInsn(const MirMethodLoweringInfo& method_info ATTRIBUTE_UNUSED) {
diff --git a/compiler/dex/quick/mips/codegen_mips.h b/compiler/dex/quick/mips/codegen_mips.h
index 2173253..378b9a0 100644
--- a/compiler/dex/quick/mips/codegen_mips.h
+++ b/compiler/dex/quick/mips/codegen_mips.h
@@ -269,6 +269,11 @@
const bool fpuIs32Bit_;
private:
+ static int MipsNextSDCallInsn(CompilationUnit* cu, CallInfo* info, int state,
+ const MethodReference& target_method, uint32_t,
+ uintptr_t direct_code, uintptr_t direct_method,
+ InvokeType type);
+
void GenNegLong(RegLocation rl_dest, RegLocation rl_src);
void GenAddLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
void GenSubLong(RegLocation rl_dest, RegLocation rl_src1, RegLocation rl_src2);
diff --git a/compiler/dex/quick/mir_to_lir-inl.h b/compiler/dex/quick/mir_to_lir-inl.h
index 767fe25..f96816c 100644
--- a/compiler/dex/quick/mir_to_lir-inl.h
+++ b/compiler/dex/quick/mir_to_lir-inl.h
@@ -21,6 +21,7 @@
#include "base/logging.h"
#include "dex/compiler_ir.h"
+#include "gc_root.h"
#include "utils.h"
namespace art {
@@ -278,6 +279,14 @@
}
}
+inline size_t Mir2Lir::GetCacheOffset(uint32_t index) {
+ return sizeof(GcRoot<mirror::Object>) * index;
+}
+
+inline size_t Mir2Lir::GetCachePointerOffset(uint32_t index, size_t pointer_size) {
+ return pointer_size * index;
+}
+
inline Mir2Lir::ShortyIterator::ShortyIterator(const char* shorty, bool is_static)
: cur_(shorty + 1), pending_this_(!is_static), initialized_(false) {
DCHECK(shorty != nullptr);
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 73787e9..4e3aab2 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -1771,6 +1771,11 @@
return (core_spill_mask_ & (1u << reg)) != 0;
}
+ size_t GetCacheOffset(uint32_t index);
+ size_t GetCachePointerOffset(uint32_t index, size_t pointer_size);
+
+ void LoadTypeFromCache(uint32_t type_index, RegStorage class_reg);
+
public:
// TODO: add accessors for these.
LIR* literal_list_; // Constants.
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index 43167a1..9cb45a4 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -394,18 +394,19 @@
cg->LoadCurrMethodDirect(arg0_ref);
break;
case 1: // Get method->dex_cache_resolved_methods_
- cg->LoadRefDisp(arg0_ref,
- ArtMethod::DexCacheResolvedMethodsOffset().Int32Value(),
- arg0_ref,
- kNotVolatile);
+ cg->LoadBaseDisp(arg0_ref,
+ ArtMethod::DexCacheResolvedMethodsOffset(
+ cu->target64 ? kX86_64PointerSize : kX86PointerSize).Int32Value(),
+ arg0_ref,
+ cu->target64 ? k64 : k32,
+ kNotVolatile);
break;
case 2: {
// Grab target method*
CHECK_EQ(cu->dex_file, target_method.dex_file);
const size_t pointer_size = GetInstructionSetPointerSize(cu->instruction_set);
cg->LoadWordDisp(arg0_ref,
- mirror::Array::DataOffset(pointer_size).Uint32Value() +
- target_method.dex_method_index * pointer_size,
+ cg->GetCachePointerOffset(target_method.dex_method_index, pointer_size),
arg0_ref);
break;
}
diff --git a/compiler/dex/quick/x86/int_x86.cc b/compiler/dex/quick/x86/int_x86.cc
index d1fe167..ecd23e9 100755
--- a/compiler/dex/quick/x86/int_x86.cc
+++ b/compiler/dex/quick/x86/int_x86.cc
@@ -3031,31 +3031,12 @@
// The LoadRefDisp(s) below will work normally, even in 64 bit mode.
RegStorage check_class = AllocTemp();
- // If Method* is already in a register, we can save a copy.
- RegLocation rl_method = mir_graph_->GetMethodLoc();
- int32_t offset_of_type = mirror::Array::DataOffset(
- sizeof(mirror::HeapReference<mirror::Class*>)).Int32Value() +
- (sizeof(mirror::HeapReference<mirror::Class*>) * type_idx);
-
- if (rl_method.location == kLocPhysReg) {
- if (use_declaring_class) {
- LoadRefDisp(rl_method.reg, ArtMethod::DeclaringClassOffset().Int32Value(),
- check_class, kNotVolatile);
- } else {
- LoadRefDisp(rl_method.reg, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
- check_class, kNotVolatile);
- LoadRefDisp(check_class, offset_of_type, check_class, kNotVolatile);
- }
+ if (use_declaring_class) {
+ RegStorage r_method = LoadCurrMethodWithHint(check_class);
+ LoadRefDisp(r_method, ArtMethod::DeclaringClassOffset().Int32Value(),
+ check_class, kNotVolatile);
} else {
- LoadCurrMethodDirect(check_class);
- if (use_declaring_class) {
- LoadRefDisp(check_class, ArtMethod::DeclaringClassOffset().Int32Value(),
- check_class, kNotVolatile);
- } else {
- LoadRefDisp(check_class, ArtMethod::DexCacheResolvedTypesOffset().Int32Value(),
- check_class, kNotVolatile);
- LoadRefDisp(check_class, offset_of_type, check_class, kNotVolatile);
- }
+ LoadTypeFromCache(type_idx, check_class);
}
// Compare the computed class to the class in the object.