diff options
26 files changed, 267 insertions, 147 deletions
diff --git a/compiler/compiler.h b/compiler/compiler.h index 01ca46efd3..9b4dbe02e2 100644 --- a/compiler/compiler.h +++ b/compiler/compiler.h @@ -51,7 +51,8 @@ class Compiler { uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, - const DexFile& dex_file) const = 0; + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) const = 0; virtual CompiledMethod* JniCompile(uint32_t access_flags, uint32_t method_idx, diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc index 603130ab96..850cca0c88 100644 --- a/compiler/dex/dex_to_dex_compiler.cc +++ b/compiler/dex/dex_to_dex_compiler.cc @@ -324,9 +324,13 @@ CompiledMethod* ArtCompileDEX( DexToDexCompilationLevel dex_to_dex_compilation_level) { DCHECK(driver != nullptr); if (dex_to_dex_compilation_level != DexToDexCompilationLevel::kDontDexToDexCompile) { - art::DexCompilationUnit unit(nullptr, class_loader, art::Runtime::Current()->GetClassLinker(), + ScopedObjectAccess soa(Thread::Current()); + StackHandleScope<1> hs(soa.Self()); + ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); + art::DexCompilationUnit unit(nullptr, class_loader, class_linker, dex_file, code_item, class_def_idx, method_idx, access_flags, - driver->GetVerifiedMethod(&dex_file, method_idx)); + driver->GetVerifiedMethod(&dex_file, method_idx), + hs.NewHandle(class_linker->FindDexCache(soa.Self(), dex_file))); art::optimizer::DexCompiler dex_compiler(*driver, unit, dex_to_dex_compilation_level); dex_compiler.Compile(); if (dex_compiler.GetQuickenedInfo().empty()) { diff --git a/compiler/dex/mir_analysis.cc b/compiler/dex/mir_analysis.cc index 1cff8dc50c..39f8ee8f7e 100644 --- a/compiler/dex/mir_analysis.cc +++ b/compiler/dex/mir_analysis.cc @@ -30,6 +30,7 @@ #include "driver/compiler_driver.h" #include "driver/compiler_options.h" #include "driver/dex_compilation_unit.h" +#include "scoped_thread_state_change.h" #include "utils.h" namespace art { @@ -1283,8 +1284,12 @@ void MIRGraph::DoCacheFieldLoweringInfo() { ifield_lowering_infos_.push_back( MirIFieldLoweringInfo(masked_field_idx, field_types[pos], is_quickened)); } - MirIFieldLoweringInfo::Resolve(cu_->compiler_driver, GetCurrentDexCompilationUnit(), - ifield_lowering_infos_.data(), ifield_pos); + ScopedObjectAccess soa(Thread::Current()); + MirIFieldLoweringInfo::Resolve(soa, + cu_->compiler_driver, + GetCurrentDexCompilationUnit(), + ifield_lowering_infos_.data(), + ifield_pos); } if (sfield_pos != max_refs) { diff --git a/compiler/dex/mir_field_info.cc b/compiler/dex/mir_field_info.cc index 4dfec176af..13bbc3e983 100644 --- a/compiler/dex/mir_field_info.cc +++ b/compiler/dex/mir_field_info.cc @@ -29,7 +29,8 @@ namespace art { -void MirIFieldLoweringInfo::Resolve(CompilerDriver* compiler_driver, +void MirIFieldLoweringInfo::Resolve(const ScopedObjectAccess& soa, + CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit, MirIFieldLoweringInfo* field_infos, size_t count) { if (kIsDebugBuild) { @@ -44,7 +45,6 @@ void MirIFieldLoweringInfo::Resolve(CompilerDriver* compiler_driver, // We're going to resolve fields and check access in a tight loop. It's better to hold // the lock and needed references once than re-acquiring them again and again. - ScopedObjectAccess soa(Thread::Current()); StackHandleScope<3> hs(soa.Self()); Handle<mirror::DexCache> dex_cache(hs.NewHandle(compiler_driver->GetDexCache(mUnit))); Handle<mirror::ClassLoader> class_loader( diff --git a/compiler/dex/mir_field_info.h b/compiler/dex/mir_field_info.h index 053029d839..b6dc27d26e 100644 --- a/compiler/dex/mir_field_info.h +++ b/compiler/dex/mir_field_info.h @@ -26,6 +26,7 @@ namespace art { class CompilerDriver; class DexCompilationUnit; +class ScopedObjectAccess; /* * Field info is calculated from the perspective of the compilation unit that accesses @@ -133,9 +134,12 @@ class MirIFieldLoweringInfo : public MirFieldInfo { // For each requested instance field retrieve the field's declaring location (dex file, class // index and field index) and volatility and compute whether we can fast path the access // with IGET/IPUT. For fast path fields, retrieve the field offset. - static void Resolve(CompilerDriver* compiler_driver, const DexCompilationUnit* mUnit, - MirIFieldLoweringInfo* field_infos, size_t count) - REQUIRES(!Locks::mutator_lock_); + static void Resolve(const ScopedObjectAccess& soa, + CompilerDriver* compiler_driver, + const DexCompilationUnit* mUnit, + MirIFieldLoweringInfo* field_infos, + size_t count) + SHARED_REQUIRES(Locks::mutator_lock_); // Construct an unresolved instance field lowering info. MirIFieldLoweringInfo(uint16_t field_idx, DexMemAccessType type, bool is_quickened) diff --git a/compiler/dex/mir_graph.cc b/compiler/dex/mir_graph.cc index 38342420ac..7976a9aea8 100644 --- a/compiler/dex/mir_graph.cc +++ b/compiler/dex/mir_graph.cc @@ -699,16 +699,17 @@ BasicBlock* MIRGraph::ProcessCanThrow(BasicBlock* cur_block, MIR* insn, DexOffse /* Parse a Dex method and insert it into the MIRGraph at the current insert point. */ void MIRGraph::InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_flags, InvokeType invoke_type ATTRIBUTE_UNUSED, uint16_t class_def_idx, - uint32_t method_idx, jobject class_loader, const DexFile& dex_file) { + uint32_t method_idx, jobject class_loader, const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) { current_code_item_ = code_item; method_stack_.push_back(std::make_pair(current_method_, current_offset_)); current_method_ = m_units_.size(); current_offset_ = 0; // TODO: will need to snapshot stack image and use that as the mir context identification. m_units_.push_back(new (arena_) DexCompilationUnit( - cu_, class_loader, Runtime::Current()->GetClassLinker(), dex_file, - current_code_item_, class_def_idx, method_idx, access_flags, - cu_->compiler_driver->GetVerifiedMethod(&dex_file, method_idx))); + cu_, class_loader, Runtime::Current()->GetClassLinker(), dex_file, current_code_item_, + class_def_idx, method_idx, access_flags, + cu_->compiler_driver->GetVerifiedMethod(&dex_file, method_idx), dex_cache)); const uint16_t* code_ptr = current_code_item_->insns_; const uint16_t* code_end = current_code_item_->insns_ + current_code_item_->insns_size_in_code_units_; diff --git a/compiler/dex/mir_graph.h b/compiler/dex/mir_graph.h index 8bf709ab86..a9ebe9c84c 100644 --- a/compiler/dex/mir_graph.h +++ b/compiler/dex/mir_graph.h @@ -572,9 +572,14 @@ class MIRGraph { * Parse dex method and add MIR at current insert point. Returns id (which is * actually the index of the method in the m_units_ array). */ - void InlineMethod(const DexFile::CodeItem* code_item, uint32_t access_flags, - InvokeType invoke_type, uint16_t class_def_idx, - uint32_t method_idx, jobject class_loader, const DexFile& dex_file); + void InlineMethod(const DexFile::CodeItem* code_item, + uint32_t access_flags, + InvokeType invoke_type, + uint16_t class_def_idx, + uint32_t method_idx, + jobject class_loader, + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache); /* Find existing block */ BasicBlock* FindBlock(DexOffset code_offset, diff --git a/compiler/dex/mir_method_info.cc b/compiler/dex/mir_method_info.cc index 31c3808197..658e7d67a0 100644 --- a/compiler/dex/mir_method_info.cc +++ b/compiler/dex/mir_method_info.cc @@ -112,7 +112,8 @@ void MirMethodLoweringInfo::Resolve(CompilerDriver* compiler_driver, mUnit->GetCompilationUnit(), mUnit->GetClassLoader(), mUnit->GetClassLinker(), *it->target_dex_file_, nullptr /* code_item not used */, 0u /* class_def_idx not used */, it->target_method_idx_, 0u /* access_flags not used */, - nullptr /* verified_method not used */); + nullptr /* verified_method not used */, + current_dex_cache); resolved_method = compiler_driver->ResolveMethod(soa, current_dex_cache, class_loader, &cu, it->target_method_idx_, invoke_type, false); if (resolved_method == nullptr) { diff --git a/compiler/dex/mir_optimization.cc b/compiler/dex/mir_optimization.cc index 80b7ac1e5b..eb4915b821 100644 --- a/compiler/dex/mir_optimization.cc +++ b/compiler/dex/mir_optimization.cc @@ -17,6 +17,7 @@ #include "base/bit_vector-inl.h" #include "base/logging.h" #include "base/scoped_arena_containers.h" +#include "class_linker-inl.h" #include "dataflow_iterator-inl.h" #include "dex/verified_method.h" #include "dex_flags.h" @@ -30,6 +31,7 @@ #include "quick/dex_file_method_inliner.h" #include "quick/dex_file_to_method_inliner_map.h" #include "stack.h" +#include "thread-inl.h" #include "type_inference.h" #include "utils.h" @@ -1469,13 +1471,23 @@ void MIRGraph::ComputeInlineIFieldLoweringInfo(uint16_t field_idx, MIR* invoke, const MirMethodLoweringInfo& method_info = GetMethodLoweringInfo(invoke); MethodReference target = method_info.GetTargetMethod(); - DexCompilationUnit inlined_unit( - cu_, cu_->class_loader, cu_->class_linker, *target.dex_file, - nullptr /* code_item not used */, 0u /* class_def_idx not used */, target.dex_method_index, - 0u /* access_flags not used */, nullptr /* verified_method not used */); + ScopedObjectAccess soa(Thread::Current()); + StackHandleScope<1> hs(soa.Self()); + Handle<mirror::DexCache> dex_cache( + hs.NewHandle(cu_->class_linker->FindDexCache(hs.Self(), *target.dex_file))); + DexCompilationUnit inlined_unit(cu_, + cu_->class_loader, + cu_->class_linker, + *target.dex_file, + nullptr /* code_item not used */, + 0u /* class_def_idx not used */, + target.dex_method_index, + 0u /* access_flags not used */, + nullptr /* verified_method not used */, + dex_cache); DexMemAccessType type = IGetOrIPutMemAccessType(iget_or_iput->dalvikInsn.opcode); MirIFieldLoweringInfo inlined_field_info(field_idx, type, false); - MirIFieldLoweringInfo::Resolve(cu_->compiler_driver, &inlined_unit, &inlined_field_info, 1u); + MirIFieldLoweringInfo::Resolve(soa, cu_->compiler_driver, &inlined_unit, &inlined_field_info, 1u); DCHECK(inlined_field_info.IsResolved()); uint32_t field_info_index = ifield_lowering_infos_.size(); diff --git a/compiler/dex/quick/quick_compiler.cc b/compiler/dex/quick/quick_compiler.cc index 3642b8236a..b5ecf9c418 100644 --- a/compiler/dex/quick/quick_compiler.cc +++ b/compiler/dex/quick/quick_compiler.cc @@ -663,7 +663,8 @@ CompiledMethod* QuickCompiler::Compile(const DexFile::CodeItem* code_item, uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, - const DexFile& dex_file) const { + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) const { if (kPoisonHeapReferences) { VLOG(compiler) << "Skipping method : " << PrettyMethod(method_idx, dex_file) << " Reason = Quick does not support heap poisoning."; @@ -749,7 +750,7 @@ CompiledMethod* QuickCompiler::Compile(const DexFile::CodeItem* code_item, /* Build the raw MIR graph */ cu.mir_graph->InlineMethod(code_item, access_flags, invoke_type, class_def_idx, method_idx, - class_loader, dex_file); + class_loader, dex_file, dex_cache); if (!CanCompileMethod(method_idx, dex_file, &cu)) { VLOG(compiler) << cu.instruction_set << ": Cannot compile method : " diff --git a/compiler/dex/quick/quick_compiler.h b/compiler/dex/quick/quick_compiler.h index 4a39ab3565..d512b256cd 100644 --- a/compiler/dex/quick/quick_compiler.h +++ b/compiler/dex/quick/quick_compiler.h @@ -21,6 +21,10 @@ namespace art { +namespace mirror { +class DexCache; +} + class Compiler; class CompilerDriver; class Mir2Lir; @@ -43,7 +47,8 @@ class QuickCompiler : public Compiler { uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, - const DexFile& dex_file) const OVERRIDE; + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) const OVERRIDE; CompiledMethod* JniCompile(uint32_t access_flags, uint32_t method_idx, diff --git a/compiler/dex/type_inference_test.cc b/compiler/dex/type_inference_test.cc index eaa2bfac93..872a8d684b 100644 --- a/compiler/dex/type_inference_test.cc +++ b/compiler/dex/type_inference_test.cc @@ -252,7 +252,8 @@ class TypeInferenceTest : public testing::Test { cu_.mir_graph->m_units_.push_back(new (cu_.mir_graph->arena_) DexCompilationUnit( &cu_, cu_.class_loader, cu_.class_linker, *cu_.dex_file, nullptr /* code_item not used */, 0u /* class_def_idx not used */, 0u /* method_index not used */, - cu_.access_flags, nullptr /* verified_method not used */)); + cu_.access_flags, nullptr /* verified_method not used */, + NullHandle<mirror::DexCache>())); cu_.mir_graph->current_method_ = 0u; code_item_ = static_cast<DexFile::CodeItem*>( cu_.arena.Alloc(sizeof(DexFile::CodeItem), kArenaAllocMisc)); diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h index 8f1987a7db..e535afd272 100644 --- a/compiler/driver/compiler_driver-inl.h +++ b/compiler/driver/compiler_driver-inl.h @@ -34,7 +34,7 @@ inline mirror::DexCache* CompilerDriver::GetDexCache(const DexCompilationUnit* m return mUnit->GetClassLinker()->FindDexCache(Thread::Current(), *mUnit->GetDexFile(), false); } -inline mirror::ClassLoader* CompilerDriver::GetClassLoader(ScopedObjectAccess& soa, +inline mirror::ClassLoader* CompilerDriver::GetClassLoader(const ScopedObjectAccess& soa, const DexCompilationUnit* mUnit) { return soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()); } diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 6d3a960048..ded70cdaca 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -571,7 +571,8 @@ static void CompileMethod(Thread* self, jobject class_loader, const DexFile& dex_file, optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level, - bool compilation_enabled) + bool compilation_enabled, + Handle<mirror::DexCache> dex_cache) REQUIRES(!driver->compiled_methods_lock_) { DCHECK(driver != nullptr); CompiledMethod* compiled_method = nullptr; @@ -608,7 +609,7 @@ static void CompileMethod(Thread* self, // NOTE: if compiler declines to compile this method, it will return null. compiled_method = driver->GetCompiler()->Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx, class_loader, - dex_file); + dex_file, dex_cache); } if (compiled_method == nullptr && dex_to_dex_compilation_level != optimizer::DexToDexCompilationLevel::kDontDexToDexCompile) { @@ -673,6 +674,8 @@ void CompilerDriver::CompileOne(Thread* self, ArtMethod* method, TimingLogger* t uint32_t method_idx = method->GetDexMethodIndex(); uint32_t access_flags = method->GetAccessFlags(); InvokeType invoke_type = method->GetInvokeType(); + StackHandleScope<1> hs(self); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache())); { ScopedObjectAccessUnchecked soa(self); ScopedLocalRef<jobject> local_class_loader( @@ -683,6 +686,8 @@ void CompilerDriver::CompileOne(Thread* self, ArtMethod* method, TimingLogger* t class_def_idx = method->GetClassDefIndex(); } const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset()); + + // Go to native so that we don't block GC during compilation. self->TransitionFromRunnableToSuspended(kNative); std::vector<const DexFile*> dex_files; @@ -709,7 +714,8 @@ void CompilerDriver::CompileOne(Thread* self, ArtMethod* method, TimingLogger* t jclass_loader, *dex_file, dex_to_dex_compilation_level, - true); + true, + dex_cache); self->GetJniEnv()->DeleteGlobalRef(jclass_loader); self->TransitionFromSuspendedToRunnable(); @@ -719,9 +725,10 @@ CompiledMethod* CompilerDriver::CompileArtMethod(Thread* self, ArtMethod* method const uint32_t method_idx = method->GetDexMethodIndex(); const uint32_t access_flags = method->GetAccessFlags(); const InvokeType invoke_type = method->GetInvokeType(); - StackHandleScope<1> hs(self); + StackHandleScope<2> hs(self); Handle<mirror::ClassLoader> class_loader(hs.NewHandle( method->GetDeclaringClass()->GetClassLoader())); + Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache())); jobject jclass_loader = class_loader.ToJObject(); const DexFile* dex_file = method->GetDexFile(); const uint16_t class_def_idx = method->GetClassDefIndex(); @@ -729,6 +736,7 @@ CompiledMethod* CompilerDriver::CompileArtMethod(Thread* self, ArtMethod* method optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level = GetDexToDexCompilationLevel(self, *this, class_loader, *dex_file, class_def); const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset()); + // Go to native so that we don't block GC during compilation. self->TransitionFromRunnableToSuspended(kNative); CompileMethod(self, this, @@ -740,7 +748,8 @@ CompiledMethod* CompilerDriver::CompileArtMethod(Thread* self, ArtMethod* method jclass_loader, *dex_file, dex_to_dex_compilation_level, - true); + true, + dex_cache); auto* compiled_method = GetCompiledMethod(MethodReference(dex_file, method_idx)); self->TransitionFromSuspendedToRunnable(); return compiled_method; @@ -1422,24 +1431,19 @@ ArtField* CompilerDriver::ComputeInstanceFieldInfo(uint32_t field_idx, // Try to resolve the field and compiling method's class. ArtField* resolved_field; mirror::Class* referrer_class; - mirror::DexCache* dex_cache; + Handle<mirror::DexCache> dex_cache(mUnit->GetDexCache()); { - StackHandleScope<2> hs(soa.Self()); - Handle<mirror::DexCache> dex_cache_handle( - hs.NewHandle(mUnit->GetClassLinker()->FindDexCache( - soa.Self(), *mUnit->GetDexFile(), false))); + StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader_handle( hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()))); - resolved_field = - ResolveField(soa, dex_cache_handle, class_loader_handle, mUnit, field_idx, false); + resolved_field = ResolveField(soa, dex_cache, class_loader_handle, mUnit, field_idx, false); referrer_class = resolved_field != nullptr - ? ResolveCompilingMethodsClass(soa, dex_cache_handle, class_loader_handle, mUnit) : nullptr; - dex_cache = dex_cache_handle.Get(); + ? ResolveCompilingMethodsClass(soa, dex_cache, class_loader_handle, mUnit) : nullptr; } bool can_link = false; if (resolved_field != nullptr && referrer_class != nullptr) { std::pair<bool, bool> fast_path = IsFastInstanceField( - dex_cache, referrer_class, resolved_field, field_idx); + dex_cache.Get(), referrer_class, resolved_field, field_idx); can_link = is_put ? fast_path.second : fast_path.first; } ProcessedInstanceField(can_link); @@ -1473,25 +1477,21 @@ bool CompilerDriver::ComputeStaticFieldInfo(uint32_t field_idx, const DexCompila // Try to resolve the field and compiling method's class. ArtField* resolved_field; mirror::Class* referrer_class; - mirror::DexCache* dex_cache; + Handle<mirror::DexCache> dex_cache(mUnit->GetDexCache()); { - StackHandleScope<2> hs(soa.Self()); - Handle<mirror::DexCache> dex_cache_handle( - hs.NewHandle(mUnit->GetClassLinker()->FindDexCache( - soa.Self(), *mUnit->GetDexFile(), false))); + StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> class_loader_handle( hs.NewHandle(soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()))); resolved_field = - ResolveField(soa, dex_cache_handle, class_loader_handle, mUnit, field_idx, true); + ResolveField(soa, dex_cache, class_loader_handle, mUnit, field_idx, true); referrer_class = resolved_field != nullptr - ? ResolveCompilingMethodsClass(soa, dex_cache_handle, class_loader_handle, mUnit) : nullptr; - dex_cache = dex_cache_handle.Get(); + ? ResolveCompilingMethodsClass(soa, dex_cache, class_loader_handle, mUnit) : nullptr; } bool result = false; if (resolved_field != nullptr && referrer_class != nullptr) { *is_volatile = IsFieldVolatile(resolved_field); std::pair<bool, bool> fast_path = IsFastStaticField( - dex_cache, referrer_class, resolved_field, field_idx, storage_index); + dex_cache.Get(), referrer_class, resolved_field, field_idx, storage_index); result = is_put ? fast_path.second : fast_path.first; } if (result) { @@ -1662,10 +1662,8 @@ bool CompilerDriver::ComputeInvokeInfo(const DexCompilationUnit* mUnit, const ui int stats_flags = 0; ScopedObjectAccess soa(Thread::Current()); // Try to resolve the method and compiling method's class. - StackHandleScope<3> hs(soa.Self()); - Handle<mirror::DexCache> dex_cache( - hs.NewHandle(mUnit->GetClassLinker()->FindDexCache( - soa.Self(), *mUnit->GetDexFile(), false))); + StackHandleScope<2> hs(soa.Self()); + Handle<mirror::DexCache> dex_cache(mUnit->GetDexCache()); Handle<mirror::ClassLoader> class_loader(hs.NewHandle( soa.Decode<mirror::ClassLoader*>(mUnit->GetClassLoader()))); uint32_t method_idx = target_method->dex_method_index; @@ -2353,39 +2351,44 @@ class CompileClassVisitor : public CompilationVisitor { const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); ClassLinker* class_linker = manager_->GetClassLinker(); jobject jclass_loader = manager_->GetClassLoader(); - Thread* self = Thread::Current(); - { - // Use a scoped object access to perform to the quick SkipClass check. - const char* descriptor = dex_file.GetClassDescriptor(class_def); - ScopedObjectAccess soa(self); - StackHandleScope<3> hs(soa.Self()); - Handle<mirror::ClassLoader> class_loader( - hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader))); - Handle<mirror::Class> klass( - hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader))); - if (klass.Get() == nullptr) { - CHECK(soa.Self()->IsExceptionPending()); - soa.Self()->ClearException(); - } else if (SkipClass(jclass_loader, dex_file, klass.Get())) { - return; - } - } ClassReference ref(&dex_file, class_def_index); // Skip compiling classes with generic verifier failures since they will still fail at runtime if (manager_->GetCompiler()->verification_results_->IsClassRejected(ref)) { return; } + // Use a scoped object access to perform to the quick SkipClass check. + const char* descriptor = dex_file.GetClassDescriptor(class_def); + ScopedObjectAccess soa(Thread::Current()); + StackHandleScope<3> hs(soa.Self()); + Handle<mirror::ClassLoader> class_loader( + hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader))); + Handle<mirror::Class> klass( + hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader))); + Handle<mirror::DexCache> dex_cache; + if (klass.Get() == nullptr) { + soa.Self()->AssertPendingException(); + soa.Self()->ClearException(); + dex_cache = hs.NewHandle(class_linker->FindDexCache(soa.Self(), dex_file)); + } else if (SkipClass(jclass_loader, dex_file, klass.Get())) { + return; + } else { + dex_cache = hs.NewHandle(klass->GetDexCache()); + } + const uint8_t* class_data = dex_file.GetClassData(class_def); if (class_data == nullptr) { // empty class, probably a marker interface return; } + // Go to native so that we don't block GC during compilation. + soa.Self()->TransitionFromRunnableToSuspended(kNative); + CompilerDriver* const driver = manager_->GetCompiler(); // Can we run DEX-to-DEX compiler on this class ? optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level = - GetDexToDexCompilationLevel(self, *driver, jclass_loader, dex_file, class_def); + GetDexToDexCompilationLevel(soa.Self(), *driver, jclass_loader, dex_file, class_def); ClassDataItemIterator it(dex_file, class_data); // Skip fields @@ -2410,10 +2413,10 @@ class CompileClassVisitor : public CompilationVisitor { continue; } previous_direct_method_idx = method_idx; - CompileMethod(self, driver, it.GetMethodCodeItem(), it.GetMethodAccessFlags(), + CompileMethod(soa.Self(), driver, it.GetMethodCodeItem(), it.GetMethodAccessFlags(), it.GetMethodInvokeType(class_def), class_def_index, method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level, - compilation_enabled); + compilation_enabled, dex_cache); it.Next(); } // Compile virtual methods @@ -2427,13 +2430,15 @@ class CompileClassVisitor : public CompilationVisitor { continue; } previous_virtual_method_idx = method_idx; - CompileMethod(self, driver, it.GetMethodCodeItem(), it.GetMethodAccessFlags(), + CompileMethod(soa.Self(), driver, it.GetMethodCodeItem(), it.GetMethodAccessFlags(), it.GetMethodInvokeType(class_def), class_def_index, method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level, - compilation_enabled); + compilation_enabled, dex_cache); it.Next(); } DCHECK(!it.HasNext()); + + soa.Self()->TransitionFromSuspendedToRunnable(); } private: diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h index 5718be9e89..b229184909 100644 --- a/compiler/driver/compiler_driver.h +++ b/compiler/driver/compiler_driver.h @@ -226,7 +226,8 @@ class CompilerDriver { mirror::DexCache* GetDexCache(const DexCompilationUnit* mUnit) SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ClassLoader* GetClassLoader(ScopedObjectAccess& soa, const DexCompilationUnit* mUnit) + mirror::ClassLoader* GetClassLoader(const ScopedObjectAccess& soa, + const DexCompilationUnit* mUnit) SHARED_REQUIRES(Locks::mutator_lock_); // Resolve compiling method's class. Returns null on failure. diff --git a/compiler/driver/dex_compilation_unit.cc b/compiler/driver/dex_compilation_unit.cc index e6c8c181aa..cfaa01b48c 100644 --- a/compiler/driver/dex_compilation_unit.cc +++ b/compiler/driver/dex_compilation_unit.cc @@ -18,6 +18,7 @@ #include "base/stringprintf.h" #include "dex/compiler_ir.h" +#include "mirror/dex_cache.h" #include "utils.h" namespace art { @@ -30,7 +31,8 @@ DexCompilationUnit::DexCompilationUnit(CompilationUnit* cu, uint16_t class_def_idx, uint32_t method_idx, uint32_t access_flags, - const VerifiedMethod* verified_method) + const VerifiedMethod* verified_method, + Handle<mirror::DexCache> dex_cache) : cu_(cu), class_loader_(class_loader), class_linker_(class_linker), @@ -39,7 +41,8 @@ DexCompilationUnit::DexCompilationUnit(CompilationUnit* cu, class_def_idx_(class_def_idx), dex_method_idx_(method_idx), access_flags_(access_flags), - verified_method_(verified_method) { + verified_method_(verified_method), + dex_cache_(dex_cache) { } const std::string& DexCompilationUnit::GetSymbol() { diff --git a/compiler/driver/dex_compilation_unit.h b/compiler/driver/dex_compilation_unit.h index 398300699e..16872f41f3 100644 --- a/compiler/driver/dex_compilation_unit.h +++ b/compiler/driver/dex_compilation_unit.h @@ -19,9 +19,10 @@ #include <stdint.h> +#include "base/arena_object.h" #include "dex_file.h" +#include "handle.h" #include "jni.h" -#include "base/arena_object.h" namespace art { namespace mirror { @@ -36,10 +37,16 @@ class DexCompilationUnit : public DeletableArenaObject<kArenaAllocMisc> { public: explicit DexCompilationUnit(CompilationUnit* cu); - DexCompilationUnit(CompilationUnit* cu, jobject class_loader, ClassLinker* class_linker, - const DexFile& dex_file, const DexFile::CodeItem* code_item, - uint16_t class_def_idx, uint32_t method_idx, uint32_t access_flags, - const VerifiedMethod* verified_method); + DexCompilationUnit(CompilationUnit* cu, + jobject class_loader, + ClassLinker* class_linker, + const DexFile& dex_file, + const DexFile::CodeItem* code_item, + uint16_t class_def_idx, + uint32_t method_idx, + uint32_t access_flags, + const VerifiedMethod* verified_method, + Handle<mirror::DexCache> dex_cache); CompilationUnit* GetCompilationUnit() const { return cu_; @@ -109,6 +116,10 @@ class DexCompilationUnit : public DeletableArenaObject<kArenaAllocMisc> { const std::string& GetSymbol(); + Handle<mirror::DexCache> GetDexCache() const { + return dex_cache_; + } + private: CompilationUnit* const cu_; @@ -124,6 +135,8 @@ class DexCompilationUnit : public DeletableArenaObject<kArenaAllocMisc> { const uint32_t access_flags_; const VerifiedMethod* verified_method_; + Handle<mirror::DexCache> dex_cache_; + std::string symbol_; }; diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc index 23ab94e5fe..1650fd1ced 100644 --- a/compiler/optimizing/builder.cc +++ b/compiler/optimizing/builder.cc @@ -1205,7 +1205,8 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, resolved_field->GetOffset(), resolved_field->IsVolatile(), field_index, - *dex_file_)); + *dex_file_, + dex_compilation_unit_->GetDexCache())); } else { current_block_->AddInstruction(new (arena_) HInstanceFieldGet( current_block_->GetLastInstruction(), @@ -1213,7 +1214,8 @@ bool HGraphBuilder::BuildInstanceFieldAccess(const Instruction& instruction, resolved_field->GetOffset(), resolved_field->IsVolatile(), field_index, - *dex_file_)); + *dex_file_, + dex_compilation_unit_->GetDexCache())); UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction()); } @@ -1334,14 +1336,16 @@ bool HGraphBuilder::BuildStaticFieldAccess(const Instruction& instruction, resolved_field->GetOffset(), resolved_field->IsVolatile(), field_index, - *dex_file_)); + *dex_file_, + dex_cache_)); } else { current_block_->AddInstruction(new (arena_) HStaticFieldGet(cls, field_type, resolved_field->GetOffset(), resolved_field->IsVolatile(), field_index, - *dex_file_)); + *dex_file_, + dex_cache_)); UpdateLocal(source_or_dest_reg, current_block_->GetLastInstruction()); } return true; diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h index d6b25ee822..560ed86e50 100644 --- a/compiler/optimizing/builder.h +++ b/compiler/optimizing/builder.h @@ -40,7 +40,8 @@ class HGraphBuilder : public ValueObject { const DexFile* dex_file, CompilerDriver* driver, OptimizingCompilerStats* compiler_stats, - const uint8_t* interpreter_metadata) + const uint8_t* interpreter_metadata, + Handle<mirror::DexCache> dex_cache) : arena_(graph->GetArena()), branch_targets_(graph->GetArena(), 0), locals_(graph->GetArena(), 0), @@ -57,7 +58,8 @@ class HGraphBuilder : public ValueObject { latest_result_(nullptr), can_use_baseline_for_string_init_(true), compilation_stats_(compiler_stats), - interpreter_metadata_(interpreter_metadata) {} + interpreter_metadata_(interpreter_metadata), + dex_cache_(dex_cache) {} // Only for unit testing. HGraphBuilder(HGraph* graph, Primitive::Type return_type = Primitive::kPrimInt) @@ -77,7 +79,8 @@ class HGraphBuilder : public ValueObject { latest_result_(nullptr), can_use_baseline_for_string_init_(true), compilation_stats_(nullptr), - interpreter_metadata_(nullptr) {} + interpreter_metadata_(nullptr), + dex_cache_(NullHandle<mirror::DexCache>()) {} bool BuildGraph(const DexFile::CodeItem& code); @@ -334,6 +337,9 @@ class HGraphBuilder : public ValueObject { const uint8_t* interpreter_metadata_; + // Dex cache for dex_file_. + Handle<mirror::DexCache> dex_cache_; + DISALLOW_COPY_AND_ASSIGN(HGraphBuilder); }; diff --git a/compiler/optimizing/gvn_test.cc b/compiler/optimizing/gvn_test.cc index 42ef3ff4a5..32f45b5669 100644 --- a/compiler/optimizing/gvn_test.cc +++ b/compiler/optimizing/gvn_test.cc @@ -28,6 +28,7 @@ namespace art { TEST(GVNTest, LocalFieldElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); + NullHandle<mirror::DexCache> dex_cache; HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); @@ -45,20 +46,23 @@ TEST(GVNTest, LocalFieldElimination) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot, MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); HInstruction* to_remove = block->GetLastInstruction(); block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot, MemberOffset(43), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); HInstruction* different_offset = block->GetLastInstruction(); // Kill the value. block->AddInstruction(new (&allocator) HInstanceFieldSet(parameter, @@ -67,13 +71,15 @@ TEST(GVNTest, LocalFieldElimination) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); block->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimNot, MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); HInstruction* use_after_kill = block->GetLastInstruction(); block->AddInstruction(new (&allocator) HExit()); @@ -94,6 +100,7 @@ TEST(GVNTest, LocalFieldElimination) { TEST(GVNTest, GlobalFieldElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); + NullHandle<mirror::DexCache> dex_cache; HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); @@ -110,7 +117,8 @@ TEST(GVNTest, GlobalFieldElimination) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); block->AddInstruction(new (&allocator) HIf(block->GetLastInstruction())); HBasicBlock* then = new (&allocator) HBasicBlock(graph); @@ -130,21 +138,24 @@ TEST(GVNTest, GlobalFieldElimination) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); then->AddInstruction(new (&allocator) HGoto()); else_->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean, MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); else_->AddInstruction(new (&allocator) HGoto()); join->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean, MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); join->AddInstruction(new (&allocator) HExit()); graph->TryBuildingSsa(); @@ -161,6 +172,7 @@ TEST(GVNTest, GlobalFieldElimination) { TEST(GVNTest, LoopFieldElimination) { ArenaPool pool; ArenaAllocator allocator(&pool); + NullHandle<mirror::DexCache> dex_cache; HGraph* graph = CreateGraph(&allocator); HBasicBlock* entry = new (&allocator) HBasicBlock(graph); @@ -178,7 +190,8 @@ TEST(GVNTest, LoopFieldElimination) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); block->AddInstruction(new (&allocator) HGoto()); HBasicBlock* loop_header = new (&allocator) HBasicBlock(graph); @@ -198,7 +211,8 @@ TEST(GVNTest, LoopFieldElimination) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); HInstruction* field_get_in_loop_header = loop_header->GetLastInstruction(); loop_header->AddInstruction(new (&allocator) HIf(block->GetLastInstruction())); @@ -210,14 +224,16 @@ TEST(GVNTest, LoopFieldElimination) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); HInstruction* field_set = loop_body->GetLastInstruction(); loop_body->AddInstruction(new (&allocator) HInstanceFieldGet(parameter, Primitive::kPrimBoolean, MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); HInstruction* field_get_in_loop_body = loop_body->GetLastInstruction(); loop_body->AddInstruction(new (&allocator) HGoto()); @@ -226,7 +242,8 @@ TEST(GVNTest, LoopFieldElimination) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); HInstruction* field_get_in_exit = exit->GetLastInstruction(); exit->AddInstruction(new (&allocator) HExit()); @@ -265,6 +282,7 @@ TEST(GVNTest, LoopFieldElimination) { TEST(GVNTest, LoopSideEffects) { ArenaPool pool; ArenaAllocator allocator(&pool); + NullHandle<mirror::DexCache> dex_cache; static const SideEffects kCanTriggerGC = SideEffects::CanTriggerGC(); @@ -320,7 +338,8 @@ TEST(GVNTest, LoopSideEffects) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile())); + graph->GetDexFile(), + dex_cache)); SideEffectsAnalysis side_effects(graph); side_effects.Run(); @@ -342,7 +361,8 @@ TEST(GVNTest, LoopSideEffects) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile()), + graph->GetDexFile(), + dex_cache), outer_loop_body->GetLastInstruction()); SideEffectsAnalysis side_effects(graph); @@ -365,7 +385,8 @@ TEST(GVNTest, LoopSideEffects) { MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile()), + graph->GetDexFile(), + dex_cache), inner_loop_body->GetLastInstruction()); SideEffectsAnalysis side_effects(graph); diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 112d42e904..b5870ae914 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -182,10 +182,13 @@ bool HInliner::TryInline(HInvoke* invoke_instruction) { ArtMethod* resolved_method; if (invoke_instruction->IsInvokeStaticOrDirect()) { MethodReference ref = invoke_instruction->AsInvokeStaticOrDirect()->GetTargetMethod(); - resolved_method = class_linker->FindDexCache(soa.Self(), *ref.dex_file)->GetResolvedMethod( + mirror::DexCache* const dex_cache = (&caller_dex_file == ref.dex_file) + ? caller_compilation_unit_.GetDexCache().Get() + : class_linker->FindDexCache(soa.Self(), *ref.dex_file); + resolved_method = dex_cache->GetResolvedMethod( ref.dex_method_index, class_linker->GetImagePointerSize()); } else { - resolved_method = class_linker->FindDexCache(soa.Self(), caller_dex_file)->GetResolvedMethod( + resolved_method = caller_compilation_unit_.GetDexCache().Get()->GetResolvedMethod( method_index, class_linker->GetImagePointerSize()); } @@ -273,6 +276,7 @@ bool HInliner::TryBuildAndInline(ArtMethod* resolved_method, const DexFile& callee_dex_file = *resolved_method->GetDexFile(); uint32_t method_index = resolved_method->GetDexMethodIndex(); ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker(); + Handle<mirror::DexCache> dex_cache(handles_->NewHandle(resolved_method->GetDexCache())); DexCompilationUnit dex_compilation_unit( nullptr, caller_compilation_unit_.GetClassLoader(), @@ -282,7 +286,8 @@ bool HInliner::TryBuildAndInline(ArtMethod* resolved_method, resolved_method->GetDeclaringClass()->GetDexClassDefIndex(), method_index, resolved_method->GetAccessFlags(), - compiler_driver_->GetVerifiedMethod(&callee_dex_file, method_index)); + compiler_driver_->GetVerifiedMethod(&callee_dex_file, method_index), + dex_cache); bool requires_ctor_barrier = false; @@ -326,7 +331,8 @@ bool HInliner::TryBuildAndInline(ArtMethod* resolved_method, resolved_method->GetDexFile(), compiler_driver_, &inline_stats, - resolved_method->GetQuickenedInfo()); + resolved_method->GetQuickenedInfo(), + dex_cache); if (!builder.BuildGraph(*code_item)) { VLOG(compiler) << "Method " << PrettyMethod(method_index, callee_dex_file) diff --git a/compiler/optimizing/licm_test.cc b/compiler/optimizing/licm_test.cc index 2fc66e6de4..bc4a663b86 100644 --- a/compiler/optimizing/licm_test.cc +++ b/compiler/optimizing/licm_test.cc @@ -120,13 +120,14 @@ TEST_F(LICMTest, FieldHoisting) { BuildLoop(); // Populate the loop with instructions: set/get field with different types. + NullHandle<mirror::DexCache> dex_cache; HInstruction* get_field = new (&allocator_) HInstanceFieldGet( parameter_, Primitive::kPrimLong, MemberOffset(10), - false, kUnknownFieldIndex, graph_->GetDexFile()); + false, kUnknownFieldIndex, graph_->GetDexFile(), dex_cache); loop_body_->InsertInstructionBefore(get_field, loop_body_->GetLastInstruction()); HInstruction* set_field = new (&allocator_) HInstanceFieldSet( parameter_, constant_, Primitive::kPrimInt, MemberOffset(20), - false, kUnknownFieldIndex, graph_->GetDexFile()); + false, kUnknownFieldIndex, graph_->GetDexFile(), dex_cache); loop_body_->InsertInstructionBefore(set_field, loop_body_->GetLastInstruction()); EXPECT_EQ(get_field->GetBlock(), loop_body_); @@ -140,13 +141,14 @@ TEST_F(LICMTest, NoFieldHoisting) { BuildLoop(); // Populate the loop with instructions: set/get field with same types. + NullHandle<mirror::DexCache> dex_cache; HInstruction* get_field = new (&allocator_) HInstanceFieldGet( parameter_, Primitive::kPrimLong, MemberOffset(10), - false, kUnknownFieldIndex, graph_->GetDexFile()); + false, kUnknownFieldIndex, graph_->GetDexFile(), dex_cache); loop_body_->InsertInstructionBefore(get_field, loop_body_->GetLastInstruction()); HInstruction* set_field = new (&allocator_) HInstanceFieldSet( parameter_, get_field, Primitive::kPrimLong, MemberOffset(10), - false, kUnknownFieldIndex, graph_->GetDexFile()); + false, kUnknownFieldIndex, graph_->GetDexFile(), dex_cache); loop_body_->InsertInstructionBefore(set_field, loop_body_->GetLastInstruction()); EXPECT_EQ(get_field->GetBlock(), loop_body_); diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 2ed2d9ab20..1470e10081 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -58,6 +58,10 @@ class LocationSummary; class SlowPathCode; class SsaBuilder; +namespace mirror { +class DexCache; +} // namespace mirror + static const int kDefaultNumberOfBlocks = 8; static const int kDefaultNumberOfSuccessors = 2; static const int kDefaultNumberOfPredecessors = 2; @@ -4020,25 +4024,29 @@ class FieldInfo : public ValueObject { Primitive::Type field_type, bool is_volatile, uint32_t index, - const DexFile& dex_file) + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) : field_offset_(field_offset), field_type_(field_type), is_volatile_(is_volatile), index_(index), - dex_file_(dex_file) {} + dex_file_(dex_file), + dex_cache_(dex_cache) {} MemberOffset GetFieldOffset() const { return field_offset_; } Primitive::Type GetFieldType() const { return field_type_; } uint32_t GetFieldIndex() const { return index_; } const DexFile& GetDexFile() const { return dex_file_; } bool IsVolatile() const { return is_volatile_; } + Handle<mirror::DexCache> GetDexCache() const { return dex_cache_; } private: const MemberOffset field_offset_; const Primitive::Type field_type_; const bool is_volatile_; - uint32_t index_; + const uint32_t index_; const DexFile& dex_file_; + const Handle<mirror::DexCache> dex_cache_; }; class HInstanceFieldGet : public HExpression<1> { @@ -4048,11 +4056,12 @@ class HInstanceFieldGet : public HExpression<1> { MemberOffset field_offset, bool is_volatile, uint32_t field_idx, - const DexFile& dex_file) + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) : HExpression( field_type, SideEffects::FieldReadOfType(field_type, is_volatile)), - field_info_(field_offset, field_type, is_volatile, field_idx, dex_file) { + field_info_(field_offset, field_type, is_volatile, field_idx, dex_file, dex_cache) { SetRawInputAt(0, value); } @@ -4092,10 +4101,11 @@ class HInstanceFieldSet : public HTemplateInstruction<2> { MemberOffset field_offset, bool is_volatile, uint32_t field_idx, - const DexFile& dex_file) + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) : HTemplateInstruction( SideEffects::FieldWriteOfType(field_type, is_volatile)), - field_info_(field_offset, field_type, is_volatile, field_idx, dex_file), + field_info_(field_offset, field_type, is_volatile, field_idx, dex_file, dex_cache), value_can_be_null_(true) { SetRawInputAt(0, object); SetRawInputAt(1, value); @@ -4510,11 +4520,12 @@ class HStaticFieldGet : public HExpression<1> { MemberOffset field_offset, bool is_volatile, uint32_t field_idx, - const DexFile& dex_file) + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) : HExpression( field_type, SideEffects::FieldReadOfType(field_type, is_volatile)), - field_info_(field_offset, field_type, is_volatile, field_idx, dex_file) { + field_info_(field_offset, field_type, is_volatile, field_idx, dex_file, dex_cache) { SetRawInputAt(0, cls); } @@ -4551,10 +4562,11 @@ class HStaticFieldSet : public HTemplateInstruction<2> { MemberOffset field_offset, bool is_volatile, uint32_t field_idx, - const DexFile& dex_file) + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) : HTemplateInstruction( SideEffects::FieldWriteOfType(field_type, is_volatile)), - field_info_(field_offset, field_type, is_volatile, field_idx, dex_file), + field_info_(field_offset, field_type, is_volatile, field_idx, dex_file, dex_cache), value_can_be_null_(true) { SetRawInputAt(0, cls); SetRawInputAt(1, value); diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 6f251e8e6c..7044a8796a 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -243,7 +243,8 @@ class OptimizingCompiler FINAL : public Compiler { uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, - const DexFile& dex_file) const OVERRIDE; + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) const OVERRIDE; CompiledMethod* TryCompile(const DexFile::CodeItem* code_item, uint32_t access_flags, @@ -251,7 +252,8 @@ class OptimizingCompiler FINAL : public Compiler { uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, - const DexFile& dex_file) const; + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) const; CompiledMethod* JniCompile(uint32_t access_flags, uint32_t method_idx, @@ -638,7 +640,8 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite uint16_t class_def_idx, uint32_t method_idx, jobject class_loader, - const DexFile& dex_file) const { + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) const { UNUSED(invoke_type); std::string method_name = PrettyMethod(method_idx, dex_file); MaybeRecordStat(MethodCompilationStat::kAttemptCompilation); @@ -674,7 +677,7 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite DexCompilationUnit dex_compilation_unit( nullptr, class_loader, Runtime::Current()->GetClassLinker(), dex_file, code_item, class_def_idx, method_idx, access_flags, - compiler_driver->GetVerifiedMethod(&dex_file, method_idx)); + compiler_driver->GetVerifiedMethod(&dex_file, method_idx), dex_cache); bool requires_barrier = dex_compilation_unit.IsConstructor() && compiler_driver->RequiresConstructorBarrier(Thread::Current(), @@ -712,10 +715,7 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite const uint8_t* interpreter_metadata = nullptr; { ScopedObjectAccess soa(Thread::Current()); - StackHandleScope<4> hs(soa.Self()); - ClassLinker* class_linker = dex_compilation_unit.GetClassLinker(); - Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache( - soa.Self(), dex_file))); + StackHandleScope<1> hs(soa.Self()); Handle<mirror::ClassLoader> loader(hs.NewHandle( soa.Decode<mirror::ClassLoader*>(class_loader))); ArtMethod* art_method = compiler_driver->ResolveMethod( @@ -732,7 +732,8 @@ CompiledMethod* OptimizingCompiler::TryCompile(const DexFile::CodeItem* code_ite &dex_file, compiler_driver, compilation_stats_.get(), - interpreter_metadata); + interpreter_metadata, + dex_cache); VLOG(compiler) << "Building " << method_name; @@ -798,13 +799,14 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, uint16_t class_def_idx, uint32_t method_idx, jobject jclass_loader, - const DexFile& dex_file) const { + const DexFile& dex_file, + Handle<mirror::DexCache> dex_cache) const { CompilerDriver* compiler_driver = GetCompilerDriver(); CompiledMethod* method = nullptr; DCHECK(!compiler_driver->GetVerifiedMethod(&dex_file, method_idx)->HasRuntimeThrow()); if (compiler_driver->IsMethodVerifiedWithoutFailures(method_idx, class_def_idx, dex_file)) { method = TryCompile(code_item, access_flags, invoke_type, class_def_idx, - method_idx, jclass_loader, dex_file); + method_idx, jclass_loader, dex_file, dex_cache); } else { if (compiler_driver->GetCompilerOptions().VerifyAtRuntime()) { MaybeRecordStat(MethodCompilationStat::kNotCompiledVerifyAtRuntime); @@ -817,7 +819,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, return method; } method = delegate_->Compile(code_item, access_flags, invoke_type, class_def_idx, method_idx, - jclass_loader, dex_file); + jclass_loader, dex_file, dex_cache); if (method != nullptr) { MaybeRecordStat(MethodCompilationStat::kCompiledQuick); diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index 516638b33c..b887b890b5 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -434,8 +434,7 @@ void RTPVisitor::UpdateFieldAccessTypeInfo(HInstruction* instr, ScopedObjectAccess soa(Thread::Current()); ClassLinker* cl = Runtime::Current()->GetClassLinker(); - mirror::DexCache* dex_cache = cl->FindDexCache(soa.Self(), info.GetDexFile(), false); - ArtField* field = cl->GetResolvedField(info.GetFieldIndex(), dex_cache); + ArtField* field = cl->GetResolvedField(info.GetFieldIndex(), info.GetDexCache().Get()); // TODO: There are certain cases where we can't resolve the field. // b/21914925 is open to keep track of a repro case for this issue. mirror::Class* klass = (field == nullptr) ? nullptr : field->GetType<false>(); diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc index b7da36299d..965a8dfebf 100644 --- a/compiler/optimizing/register_allocator_test.cc +++ b/compiler/optimizing/register_allocator_test.cc @@ -472,6 +472,7 @@ static HGraph* BuildIfElseWithPhi(ArenaAllocator* allocator, HInstruction** input2) { HGraph* graph = CreateGraph(allocator); HBasicBlock* entry = new (allocator) HBasicBlock(graph); + NullHandle<mirror::DexCache> dex_cache; graph->AddBlock(entry); graph->SetEntryBlock(entry); HInstruction* parameter = new (allocator) HParameterValue(0, Primitive::kPrimNot); @@ -486,7 +487,8 @@ static HGraph* BuildIfElseWithPhi(ArenaAllocator* allocator, MemberOffset(22), false, kUnknownFieldIndex, - graph->GetDexFile()); + graph->GetDexFile(), + dex_cache); block->AddInstruction(test); block->AddInstruction(new (allocator) HIf(test)); HBasicBlock* then = new (allocator) HBasicBlock(graph); @@ -510,13 +512,15 @@ static HGraph* BuildIfElseWithPhi(ArenaAllocator* allocator, MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile()); + graph->GetDexFile(), + dex_cache); *input2 = new (allocator) HInstanceFieldGet(parameter, Primitive::kPrimInt, MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile()); + graph->GetDexFile(), + dex_cache); then->AddInstruction(*input1); else_->AddInstruction(*input2); join->AddInstruction(new (allocator) HExit()); @@ -613,6 +617,7 @@ static HGraph* BuildFieldReturn(ArenaAllocator* allocator, HInstruction** field, HInstruction** ret) { HGraph* graph = CreateGraph(allocator); + NullHandle<mirror::DexCache> dex_cache; HBasicBlock* entry = new (allocator) HBasicBlock(graph); graph->AddBlock(entry); graph->SetEntryBlock(entry); @@ -628,7 +633,8 @@ static HGraph* BuildFieldReturn(ArenaAllocator* allocator, MemberOffset(42), false, kUnknownFieldIndex, - graph->GetDexFile()); + graph->GetDexFile(), + dex_cache); block->AddInstruction(*field); *ret = new (allocator) HReturn(*field); block->AddInstruction(*ret); |