diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/dex/quick/dex_file_method_inliner.cc | 10 | ||||
| -rw-r--r-- | compiler/dex/quick/dex_file_method_inliner.h | 3 | ||||
| -rwxr-xr-x | compiler/dex/quick/gen_invoke.cc | 85 | ||||
| -rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 1 |
4 files changed, 99 insertions, 0 deletions
diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc index 45dd7f08a6..0e46c96501 100644 --- a/compiler/dex/quick/dex_file_method_inliner.cc +++ b/compiler/dex/quick/dex_file_method_inliner.cc @@ -48,6 +48,7 @@ static constexpr bool kIntrinsicIsStatic[] = { true, // kIntrinsicMinMaxFloat true, // kIntrinsicMinMaxDouble true, // kIntrinsicSqrt + false, // kIntrinsicGet false, // kIntrinsicCharAt false, // kIntrinsicCompareTo false, // kIntrinsicIsEmptyOrLength @@ -74,6 +75,7 @@ COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxLong], MinMaxLong_must_be_stat COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxFloat], MinMaxFloat_must_be_static); COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicMinMaxDouble], MinMaxDouble_must_be_static); COMPILE_ASSERT(kIntrinsicIsStatic[kIntrinsicSqrt], Sqrt_must_be_static); +COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicGet], Get_must_not_be_static); COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicCharAt], CharAt_must_not_be_static); COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicCompareTo], CompareTo_must_not_be_static); COMPILE_ASSERT(!kIntrinsicIsStatic[kIntrinsicIsEmptyOrLength], IsEmptyOrLength_must_not_be_static); @@ -126,6 +128,7 @@ const char* const DexFileMethodInliner::kClassCacheNames[] = { "D", // kClassCacheDouble "V", // kClassCacheVoid "Ljava/lang/Object;", // kClassCacheJavaLangObject + "Ljava/lang/ref/Reference;", // kClassCacheJavaLangRefReference "Ljava/lang/String;", // kClassCacheJavaLangString "Ljava/lang/Double;", // kClassCacheJavaLangDouble "Ljava/lang/Float;", // kClassCacheJavaLangFloat @@ -152,6 +155,7 @@ const char* const DexFileMethodInliner::kNameCacheNames[] = { "max", // kNameCacheMax "min", // kNameCacheMin "sqrt", // kNameCacheSqrt + "get", // kNameCacheGet "charAt", // kNameCacheCharAt "compareTo", // kNameCacheCompareTo "isEmpty", // kNameCacheIsEmpty @@ -220,6 +224,8 @@ const DexFileMethodInliner::ProtoDef DexFileMethodInliner::kProtoCacheDefs[] = { { kClassCacheBoolean, 0, { } }, // kProtoCache_I { kClassCacheInt, 0, { } }, + // kProtoCache_Object + { kClassCacheJavaLangObject, 0, { } }, // kProtoCache_Thread { kClassCacheJavaLangThread, 0, { } }, // kProtoCacheJ_B @@ -308,6 +314,8 @@ const DexFileMethodInliner::IntrinsicDef DexFileMethodInliner::kIntrinsicMethods INTRINSIC(JavaLangMath, Sqrt, D_D, kIntrinsicSqrt, 0), INTRINSIC(JavaLangStrictMath, Sqrt, D_D, kIntrinsicSqrt, 0), + INTRINSIC(JavaLangRefReference, Get, _Object, kIntrinsicGet, 0), + INTRINSIC(JavaLangString, CharAt, I_C, kIntrinsicCharAt, 0), INTRINSIC(JavaLangString, CompareTo, String_I, kIntrinsicCompareTo, 0), INTRINSIC(JavaLangString, IsEmpty, _Z, kIntrinsicIsEmptyOrLength, kIntrinsicFlagIsEmpty), @@ -428,6 +436,8 @@ bool DexFileMethodInliner::GenIntrinsic(Mir2Lir* backend, CallInfo* info) { return backend->GenInlinedMinMaxFP(info, intrinsic.d.data & kIntrinsicFlagMin, true /* is_double */); case kIntrinsicSqrt: return backend->GenInlinedSqrt(info); + case kIntrinsicGet: + return backend->GenInlinedGet(info); case kIntrinsicCharAt: return backend->GenInlinedCharAt(info); case kIntrinsicCompareTo: diff --git a/compiler/dex/quick/dex_file_method_inliner.h b/compiler/dex/quick/dex_file_method_inliner.h index 5b3b104150..cb8c165ce5 100644 --- a/compiler/dex/quick/dex_file_method_inliner.h +++ b/compiler/dex/quick/dex_file_method_inliner.h @@ -107,6 +107,7 @@ class DexFileMethodInliner { kClassCacheDouble, kClassCacheVoid, kClassCacheJavaLangObject, + kClassCacheJavaLangRefReference, kClassCacheJavaLangString, kClassCacheJavaLangDouble, kClassCacheJavaLangFloat, @@ -140,6 +141,7 @@ class DexFileMethodInliner { kNameCacheMax, kNameCacheMin, kNameCacheSqrt, + kNameCacheGet, kNameCacheCharAt, kNameCacheCompareTo, kNameCacheIsEmpty, @@ -199,6 +201,7 @@ class DexFileMethodInliner { kProtoCacheString_I, kProtoCache_Z, kProtoCache_I, + kProtoCache_Object, kProtoCache_Thread, kProtoCacheJ_B, kProtoCacheJ_I, diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc index 79065b3474..9dedeae071 100755 --- a/compiler/dex/quick/gen_invoke.cc +++ b/compiler/dex/quick/gen_invoke.cc @@ -23,9 +23,12 @@ #include "invoke_type.h" #include "mirror/array.h" #include "mirror/class-inl.h" +#include "mirror/dex_cache.h" #include "mirror/object_array-inl.h" +#include "mirror/reference-inl.h" #include "mirror/string.h" #include "mir_to_lir-inl.h" +#include "scoped_thread_state_change.h" #include "x86/codegen_x86.h" namespace art { @@ -1218,6 +1221,88 @@ RegLocation Mir2Lir::InlineTargetWide(CallInfo* info) { return res; } +bool Mir2Lir::GenInlinedGet(CallInfo* info) { + if (cu_->instruction_set == kMips) { + // TODO - add Mips implementation + return false; + } + + // the refrence class is stored in the image dex file which might not be the same as the cu's + // dex file. Query the reference class for the image dex file then reset to starting dex file + // in after loading class type. + uint16_t type_idx = 0; + const DexFile* ref_dex_file = nullptr; + { + ScopedObjectAccess soa(Thread::Current()); + type_idx = mirror::Reference::GetJavaLangRefReference()->GetDexTypeIndex(); + ref_dex_file = mirror::Reference::GetJavaLangRefReference()->GetDexCache()->GetDexFile(); + } + CHECK(LIKELY(ref_dex_file != nullptr)); + + // address is either static within the image file, or needs to be patched up after compilation. + bool unused_type_initialized; + bool use_direct_type_ptr; + uintptr_t direct_type_ptr; + bool is_finalizable; + const DexFile* old_dex = cu_->dex_file; + cu_->dex_file = ref_dex_file; + RegStorage reg_class = TargetPtrReg(kArg1); + if (!cu_->compiler_driver->CanEmbedTypeInCode(*ref_dex_file, type_idx, &unused_type_initialized, + &use_direct_type_ptr, &direct_type_ptr, + &is_finalizable) || is_finalizable) { + cu_->dex_file = old_dex; + // address is not known and post-compile patch is not possible, cannot insert intrinsic. + return false; + } + if (use_direct_type_ptr) { + LoadConstant(reg_class, direct_type_ptr); + } else { + LoadClassType(type_idx, kArg1); + } + cu_->dex_file = old_dex; + + // get the offset for flags in reference class. + uint32_t slow_path_flag_offset = 0; + uint32_t disable_flag_offset = 0; + { + ScopedObjectAccess soa(Thread::Current()); + mirror::Class* reference_class = mirror::Reference::GetJavaLangRefReference(); + slow_path_flag_offset = reference_class->GetSlowPathFlagOffset().Uint32Value(); + disable_flag_offset = reference_class->GetDisableIntrinsicFlagOffset().Uint32Value(); + } + CHECK(slow_path_flag_offset && disable_flag_offset && + (slow_path_flag_offset != disable_flag_offset)); + + // intrinsic logic start. + RegLocation rl_obj = info->args[0]; + rl_obj = LoadValue(rl_obj); + + RegStorage reg_slow_path = AllocTemp(); + RegStorage reg_disabled = AllocTemp(); + Load32Disp(reg_class, slow_path_flag_offset, reg_slow_path); + Load32Disp(reg_class, disable_flag_offset, reg_disabled); + OpRegRegReg(kOpOr, reg_slow_path, reg_slow_path, reg_disabled); + FreeTemp(reg_disabled); + + // if slow path, jump to JNI path target + LIR* slow_path_branch = OpCmpImmBranch(kCondNe, reg_slow_path, 0, nullptr); + FreeTemp(reg_slow_path); + + // slow path not enabled, simply load the referent of the reference object + RegLocation rl_dest = InlineTarget(info); + RegLocation rl_result = EvalLoc(rl_dest, kRefReg, true); + GenNullCheck(rl_obj.reg, info->opt_flags); + LoadRefDisp(rl_obj.reg, mirror::Reference::ReferentOffset().Int32Value(), rl_result.reg, + kNotVolatile); + MarkPossibleNullPointerException(info->opt_flags); + StoreValue(rl_dest, rl_result); + + LIR* intrinsic_finish = NewLIR0(kPseudoTargetLabel); + AddIntrinsicSlowPath(info, slow_path_branch, intrinsic_finish); + + return true; +} + bool Mir2Lir::GenInlinedCharAt(CallInfo* info) { if (cu_->instruction_set == kMips) { // TODO - add Mips implementation diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index fd0fe6e119..c68ad6be4b 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -982,6 +982,7 @@ class Mir2Lir : public Backend { */ RegLocation InlineTargetWide(CallInfo* info); + bool GenInlinedGet(CallInfo* info); bool GenInlinedCharAt(CallInfo* info); bool GenInlinedStringIsEmptyOrLength(CallInfo* info, bool is_empty); virtual bool GenInlinedReverseBits(CallInfo* info, OpSize size); |