diff options
Diffstat (limited to 'compiler/dex/quick/gen_common.cc')
-rw-r--r-- | compiler/dex/quick/gen_common.cc | 49 |
1 files changed, 45 insertions, 4 deletions
diff --git a/compiler/dex/quick/gen_common.cc b/compiler/dex/quick/gen_common.cc index 3bd0298a22..daf21df19d 100644 --- a/compiler/dex/quick/gen_common.cc +++ b/compiler/dex/quick/gen_common.cc @@ -19,6 +19,7 @@ #include "dex/quick/mir_to_lir-inl.h" #include "entrypoints/quick/quick_entrypoints.h" #include "mirror/array.h" +#include "mirror/object-inl.h" #include "verifier/method_verifier.h" namespace art { @@ -883,13 +884,53 @@ void Mir2Lir::GenNewInstance(uint32_t type_idx, RegLocation rl_dest) { // alloc will always check for resolution, do we also need to verify // access because the verifier was unable to? ThreadOffset func_offset(-1); - if (cu_->compiler_driver->CanAccessInstantiableTypeWithoutChecks( - cu_->method_idx, *cu_->dex_file, type_idx)) { - func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObject); + const DexFile* dex_file = cu_->dex_file; + CompilerDriver* driver = cu_->compiler_driver; + if (driver->CanAccessInstantiableTypeWithoutChecks( + cu_->method_idx, *dex_file, type_idx)) { + bool is_type_initialized; + bool use_direct_type_ptr; + uintptr_t direct_type_ptr; + if (kEmbedClassInCode && + driver->CanEmbedTypeInCode(*dex_file, type_idx, + &is_type_initialized, &use_direct_type_ptr, &direct_type_ptr)) { + // The fast path. + if (!use_direct_type_ptr) { + // Use the literal pool and a PC-relative load from a data word. + LIR* data_target = ScanLiteralPool(class_literal_list_, type_idx, 0); + if (data_target == nullptr) { + data_target = AddWordData(&class_literal_list_, type_idx); + } + LIR* load_pc_rel = OpPcRelLoad(TargetReg(kArg0), data_target); + AppendLIR(load_pc_rel); + if (!is_type_initialized) { + func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectResolved); + CallRuntimeHelperRegMethod(func_offset, TargetReg(kArg0), true); + } else { + func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectInitialized); + CallRuntimeHelperRegMethod(func_offset, TargetReg(kArg0), true); + } + } else { + // Use the direct pointer. + if (!is_type_initialized) { + func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectResolved); + CallRuntimeHelperImmMethod(func_offset, direct_type_ptr, true); + } else { + func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectInitialized); + CallRuntimeHelperImmMethod(func_offset, direct_type_ptr, true); + } + } + } else { + // The slow path. + DCHECK_EQ(func_offset.Int32Value(), -1); + func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObject); + CallRuntimeHelperImmMethod(func_offset, type_idx, true); + } + DCHECK_NE(func_offset.Int32Value(), -1); } else { func_offset = QUICK_ENTRYPOINT_OFFSET(pAllocObjectWithAccessCheck); + CallRuntimeHelperImmMethod(func_offset, type_idx, true); } - CallRuntimeHelperImmMethod(func_offset, type_idx, true); RegLocation rl_result = GetReturn(false); StoreValue(rl_dest, rl_result); } |