Reduce how often we call FindDexCache
Before host boot.oat -j4 optimizing compile:
real 1m17.792s
user 3m26.140s
sys 0m8.340s
After:
real 1m12.324s
user 3m22.718s
sys 0m8.320s
Change-Id: If18e9e79e06cdf1676692e5efacb682bf93889c3
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h
index 8f1987a..e535afd 100644
--- a/compiler/driver/compiler_driver-inl.h
+++ b/compiler/driver/compiler_driver-inl.h
@@ -34,7 +34,7 @@
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 6d3a960..ded70cd 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -571,7 +571,8 @@
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 @@
// 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 @@
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 @@
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 @@
jclass_loader,
*dex_file,
dex_to_dex_compilation_level,
- true);
+ true,
+ dex_cache);
self->GetJniEnv()->DeleteGlobalRef(jclass_loader);
self->TransitionFromSuspendedToRunnable();
@@ -719,9 +725,10 @@
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 @@
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 @@
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 @@
// 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 @@
// 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 @@
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 @@
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 @@
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 @@
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 5718be9..b229184 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -226,7 +226,8 @@
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 e6c8c18..cfaa01b 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 @@
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 @@
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 3983006..16872f4 100644
--- a/compiler/driver/dex_compilation_unit.h
+++ b/compiler/driver/dex_compilation_unit.h
@@ -19,9 +19,10 @@
#include <stdint.h>
-#include "dex_file.h"
-#include "jni.h"
#include "base/arena_object.h"
+#include "dex_file.h"
+#include "handle.h"
+#include "jni.h"
namespace art {
namespace mirror {
@@ -36,10 +37,16 @@
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 @@
const std::string& GetSymbol();
+ Handle<mirror::DexCache> GetDexCache() const {
+ return dex_cache_;
+ }
+
private:
CompilationUnit* const cu_;
@@ -124,6 +135,8 @@
const uint32_t access_flags_;
const VerifiedMethod* verified_method_;
+ Handle<mirror::DexCache> dex_cache_;
+
std::string symbol_;
};