Revert^6 "Hash-based dex cache type array."
Fixed ImageWriter to write class table also if it contains
only boot class loader classes. Added a regression test and
added extra checks for debug-build to verify that dex cache
types from app image are also in the class table. Removed
some unnecessary debug output.
Test: 158-app-image-class-table
Bug: 34839984
Bug: 30627598
Bug: 34659969
This reverts commit 0b66d6174bf1f6023f9d36dda8538490b79c2e9f.
Change-Id: I6a747904940c6ebc297f4946feef99dc0adf930c
diff --git a/compiler/driver/compiler_driver-inl.h b/compiler/driver/compiler_driver-inl.h
index f296851..5823306 100644
--- a/compiler/driver/compiler_driver-inl.h
+++ b/compiler/driver/compiler_driver-inl.h
@@ -31,17 +31,12 @@
namespace art {
-inline mirror::ClassLoader* CompilerDriver::GetClassLoader(const ScopedObjectAccess& soa,
- const DexCompilationUnit* mUnit) {
- return soa.Decode<mirror::ClassLoader>(mUnit->GetClassLoader()).Ptr();
-}
-
inline mirror::Class* CompilerDriver::ResolveClass(
const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader, dex::TypeIndex cls_index,
const DexCompilationUnit* mUnit) {
DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile());
- DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit));
+ DCHECK_EQ(class_loader.Get(), mUnit->GetClassLoader().Get());
mirror::Class* cls = mUnit->GetClassLinker()->ResolveType(
*mUnit->GetDexFile(), cls_index, dex_cache, class_loader);
DCHECK_EQ(cls == nullptr, soa.Self()->IsExceptionPending());
@@ -56,7 +51,7 @@
const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit) {
DCHECK_EQ(dex_cache->GetDexFile(), mUnit->GetDexFile());
- DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit));
+ DCHECK_EQ(class_loader.Get(), mUnit->GetClassLoader().Get());
const DexFile::MethodId& referrer_method_id =
mUnit->GetDexFile()->GetMethodId(mUnit->GetDexMethodIndex());
return ResolveClass(soa, dex_cache, class_loader, referrer_method_id.class_idx_, mUnit);
@@ -87,7 +82,7 @@
const ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
uint32_t field_idx, bool is_static) {
- DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit));
+ DCHECK_EQ(class_loader.Get(), mUnit->GetClassLoader().Get());
return ResolveFieldWithDexFile(soa, dex_cache, class_loader, mUnit->GetDexFile(), field_idx,
is_static);
}
@@ -139,7 +134,7 @@
ScopedObjectAccess& soa, Handle<mirror::DexCache> dex_cache,
Handle<mirror::ClassLoader> class_loader, const DexCompilationUnit* mUnit,
uint32_t method_idx, InvokeType invoke_type, bool check_incompatible_class_change) {
- DCHECK_EQ(class_loader.Get(), GetClassLoader(soa, mUnit));
+ DCHECK_EQ(class_loader.Get(), mUnit->GetClassLoader().Get());
ArtMethod* resolved_method =
check_incompatible_class_change
? mUnit->GetClassLinker()->ResolveMethod<ClassLinker::kForceICCECheck>(
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index caab5fb..9950987 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -581,7 +581,7 @@
InvokeType invoke_type,
uint16_t class_def_idx,
uint32_t method_idx,
- jobject class_loader,
+ Handle<mirror::ClassLoader> class_loader,
const DexFile& dex_file,
optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level,
bool compilation_enabled,
@@ -622,9 +622,6 @@
// Look-up the ArtMethod associated with this code_item (if any)
// -- It is later used to lookup any [optimization] annotations for this method.
ScopedObjectAccess soa(self);
- StackHandleScope<1> hs(soa.Self());
- Handle<mirror::ClassLoader> class_loader_handle(hs.NewHandle(
- soa.Decode<mirror::ClassLoader>(class_loader)));
// TODO: Lookup annotation from DexFile directly without resolving method.
ArtMethod* method =
@@ -632,7 +629,7 @@
dex_file,
method_idx,
dex_cache,
- class_loader_handle,
+ class_loader,
/* referrer */ nullptr,
invoke_type);
@@ -679,9 +676,14 @@
if (compile) {
// 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_cache);
+ compiled_method = driver->GetCompiler()->Compile(code_item,
+ access_flags,
+ invoke_type,
+ class_def_idx,
+ method_idx,
+ class_loader,
+ dex_file,
+ dex_cache);
}
if (compiled_method == nullptr &&
dex_to_dex_compilation_level != optimizer::DexToDexCompilationLevel::kDontDexToDexCompile) {
@@ -728,12 +730,14 @@
uint32_t method_idx = method->GetDexMethodIndex();
uint32_t access_flags = method->GetAccessFlags();
InvokeType invoke_type = method->GetInvokeType();
- StackHandleScope<1> hs(self);
+ StackHandleScope<2> hs(self);
Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(
+ hs.NewHandle(method->GetDeclaringClass()->GetClassLoader()));
{
ScopedObjectAccessUnchecked soa(self);
ScopedLocalRef<jobject> local_class_loader(
- soa.Env(), soa.AddLocalReference<jobject>(method->GetDeclaringClass()->GetClassLoader()));
+ soa.Env(), soa.AddLocalReference<jobject>(class_loader.Get()));
jclass_loader = soa.Env()->NewGlobalRef(local_class_loader.get());
// Find the dex_file
dex_file = method->GetDexFile();
@@ -767,7 +771,7 @@
invoke_type,
class_def_idx,
method_idx,
- jclass_loader,
+ class_loader,
*dex_file,
dex_to_dex_compilation_level,
true,
@@ -793,7 +797,7 @@
invoke_type,
class_def_idx,
method_idx,
- jclass_loader,
+ class_loader,
*dex_file,
dex_to_dex_compilation_level,
true,
@@ -1073,22 +1077,30 @@
class ResolveCatchBlockExceptionsClassVisitor : public ClassVisitor {
public:
- explicit ResolveCatchBlockExceptionsClassVisitor(
- std::set<std::pair<dex::TypeIndex, const DexFile*>>& exceptions_to_resolve)
- : exceptions_to_resolve_(exceptions_to_resolve) {}
+ ResolveCatchBlockExceptionsClassVisitor() : classes_() {}
virtual bool operator()(ObjPtr<mirror::Class> c) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
- const auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
- for (auto& m : c->GetMethods(pointer_size)) {
- ResolveExceptionsForMethod(&m);
- }
+ classes_.push_back(c);
return true;
}
- private:
- void ResolveExceptionsForMethod(ArtMethod* method_handle)
+ void FindExceptionTypesToResolve(
+ std::set<std::pair<dex::TypeIndex, const DexFile*>>* exceptions_to_resolve)
REQUIRES_SHARED(Locks::mutator_lock_) {
- const DexFile::CodeItem* code_item = method_handle->GetCodeItem();
+ const auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+ for (ObjPtr<mirror::Class> klass : classes_) {
+ for (ArtMethod& method : klass->GetMethods(pointer_size)) {
+ FindExceptionTypesToResolveForMethod(&method, exceptions_to_resolve);
+ }
+ }
+ }
+
+ private:
+ void FindExceptionTypesToResolveForMethod(
+ ArtMethod* method,
+ std::set<std::pair<dex::TypeIndex, const DexFile*>>* exceptions_to_resolve)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ const DexFile::CodeItem* code_item = method->GetCodeItem();
if (code_item == nullptr) {
return; // native or abstract method
}
@@ -1108,9 +1120,9 @@
dex::TypeIndex encoded_catch_handler_handlers_type_idx =
dex::TypeIndex(DecodeUnsignedLeb128(&encoded_catch_handler_list));
// Add to set of types to resolve if not already in the dex cache resolved types
- if (!method_handle->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) {
- exceptions_to_resolve_.emplace(encoded_catch_handler_handlers_type_idx,
- method_handle->GetDexFile());
+ if (!method->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) {
+ exceptions_to_resolve->emplace(encoded_catch_handler_handlers_type_idx,
+ method->GetDexFile());
}
// ignore address associated with catch handler
DecodeUnsignedLeb128(&encoded_catch_handler_list);
@@ -1122,7 +1134,7 @@
}
}
- std::set<std::pair<dex::TypeIndex, const DexFile*>>& exceptions_to_resolve_;
+ std::vector<ObjPtr<mirror::Class>> classes_;
};
class RecordImageClassesVisitor : public ClassVisitor {
@@ -1176,8 +1188,14 @@
hs.NewHandle(class_linker->FindSystemClass(self, "Ljava/lang/Throwable;")));
do {
unresolved_exception_types.clear();
- ResolveCatchBlockExceptionsClassVisitor visitor(unresolved_exception_types);
- class_linker->VisitClasses(&visitor);
+ {
+ // Thread suspension is not allowed while ResolveCatchBlockExceptionsClassVisitor
+ // is using a std::vector<ObjPtr<mirror::Class>>.
+ ScopedAssertNoThreadSuspension ants(__FUNCTION__);
+ ResolveCatchBlockExceptionsClassVisitor visitor;
+ class_linker->VisitClasses(&visitor);
+ visitor.FindExceptionTypesToResolve(&unresolved_exception_types);
+ }
for (const auto& exception_type : unresolved_exception_types) {
dex::TypeIndex exception_type_idx = exception_type.first;
const DexFile* dex_file = exception_type.second;
@@ -1428,19 +1446,14 @@
dex_to_dex_references_.back().GetMethodIndexes().SetBit(method_ref.dex_method_index);
}
-bool CompilerDriver::CanAccessTypeWithoutChecks(uint32_t referrer_idx,
- Handle<mirror::DexCache> dex_cache,
- dex::TypeIndex type_idx) {
- // Get type from dex cache assuming it was populated by the verifier
- mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
+bool CompilerDriver::CanAccessTypeWithoutChecks(ObjPtr<mirror::Class> referrer_class,
+ ObjPtr<mirror::Class> resolved_class) {
if (resolved_class == nullptr) {
stats_->TypeNeedsAccessCheck();
return false; // Unknown class needs access checks.
}
- const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(referrer_idx);
bool is_accessible = resolved_class->IsPublic(); // Public classes are always accessible.
if (!is_accessible) {
- mirror::Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
if (referrer_class == nullptr) {
stats_->TypeNeedsAccessCheck();
return false; // Incomplete referrer knowledge needs access check.
@@ -1457,12 +1470,9 @@
return is_accessible;
}
-bool CompilerDriver::CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx,
- Handle<mirror::DexCache> dex_cache,
- dex::TypeIndex type_idx,
+bool CompilerDriver::CanAccessInstantiableTypeWithoutChecks(ObjPtr<mirror::Class> referrer_class,
+ ObjPtr<mirror::Class> resolved_class,
bool* finalizable) {
- // Get type from dex cache assuming it was populated by the verifier.
- mirror::Class* resolved_class = dex_cache->GetResolvedType(type_idx);
if (resolved_class == nullptr) {
stats_->TypeNeedsAccessCheck();
// Be conservative.
@@ -1470,10 +1480,8 @@
return false; // Unknown class needs access checks.
}
*finalizable = resolved_class->IsFinalizable();
- const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(referrer_idx);
bool is_accessible = resolved_class->IsPublic(); // Public classes are always accessible.
if (!is_accessible) {
- mirror::Class* referrer_class = dex_cache->GetResolvedType(method_id.class_idx_);
if (referrer_class == nullptr) {
stats_->TypeNeedsAccessCheck();
return false; // Incomplete referrer knowledge needs access check.
@@ -1517,9 +1525,7 @@
mirror::Class* referrer_class;
Handle<mirror::DexCache> dex_cache(mUnit->GetDexCache());
{
- StackHandleScope<1> hs(soa.Self());
- Handle<mirror::ClassLoader> class_loader_handle(
- hs.NewHandle(soa.Decode<mirror::ClassLoader>(mUnit->GetClassLoader())));
+ Handle<mirror::ClassLoader> class_loader_handle = mUnit->GetClassLoader();
resolved_field = ResolveField(soa, dex_cache, class_loader_handle, mUnit, field_idx, false);
referrer_class = resolved_field != nullptr
? ResolveCompilingMethodsClass(soa, dex_cache, class_loader_handle, mUnit) : nullptr;
@@ -2666,10 +2672,18 @@
continue;
}
previous_direct_method_idx = method_idx;
- 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, dex_cache);
+ CompileMethod(soa.Self(),
+ driver,
+ it.GetMethodCodeItem(),
+ it.GetMethodAccessFlags(),
+ it.GetMethodInvokeType(class_def),
+ class_def_index,
+ method_idx,
+ class_loader,
+ dex_file,
+ dex_to_dex_compilation_level,
+ compilation_enabled,
+ dex_cache);
it.Next();
}
// Compile virtual methods
@@ -2683,10 +2697,17 @@
continue;
}
previous_virtual_method_idx = method_idx;
- 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, dex_cache);
+ CompileMethod(soa.Self(),
+ driver, it.GetMethodCodeItem(),
+ it.GetMethodAccessFlags(),
+ it.GetMethodInvokeType(class_def),
+ class_def_index,
+ method_idx,
+ class_loader,
+ dex_file,
+ dex_to_dex_compilation_level,
+ compilation_enabled,
+ dex_cache);
it.Next();
}
DCHECK(!it.HasNext());
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 6ba1692..cbde587 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -187,16 +187,14 @@
REQUIRES(!requires_constructor_barrier_lock_);
// Are runtime access checks necessary in the compiled code?
- bool CanAccessTypeWithoutChecks(uint32_t referrer_idx,
- Handle<mirror::DexCache> dex_cache,
- dex::TypeIndex type_idx)
+ bool CanAccessTypeWithoutChecks(ObjPtr<mirror::Class> referrer_class,
+ ObjPtr<mirror::Class> resolved_class)
REQUIRES_SHARED(Locks::mutator_lock_);
// Are runtime access and instantiable checks necessary in the code?
// out_is_finalizable is set to whether the type is finalizable.
- bool CanAccessInstantiableTypeWithoutChecks(uint32_t referrer_idx,
- Handle<mirror::DexCache> dex_cache,
- dex::TypeIndex type_idx,
+ bool CanAccessInstantiableTypeWithoutChecks(ObjPtr<mirror::Class> referrer_class,
+ ObjPtr<mirror::Class> resolved_class,
bool* out_is_finalizable)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -374,10 +372,6 @@
uint32_t field_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
- mirror::ClassLoader* GetClassLoader(const ScopedObjectAccess& soa,
- const DexCompilationUnit* mUnit)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
private:
void PreCompile(jobject class_loader,
const std::vector<const DexFile*>& dex_files,
diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc
index 316117f..562f97b 100644
--- a/compiler/driver/compiler_driver_test.cc
+++ b/compiler/driver/compiler_driver_test.cc
@@ -101,6 +101,7 @@
};
// Disabled due to 10 second runtime on host
+// TODO: Update the test for hash-based dex cache arrays. Bug: 30627598
TEST_F(CompilerDriverTest, DISABLED_LARGE_CompileDexLibCore) {
CompileAll(nullptr);
diff --git a/compiler/driver/dex_compilation_unit.cc b/compiler/driver/dex_compilation_unit.cc
index 47b1929..7e8e812 100644
--- a/compiler/driver/dex_compilation_unit.cc
+++ b/compiler/driver/dex_compilation_unit.cc
@@ -21,7 +21,7 @@
namespace art {
-DexCompilationUnit::DexCompilationUnit(jobject class_loader,
+DexCompilationUnit::DexCompilationUnit(Handle<mirror::ClassLoader> class_loader,
ClassLinker* class_linker,
const DexFile& dex_file,
const DexFile::CodeItem* code_item,
diff --git a/compiler/driver/dex_compilation_unit.h b/compiler/driver/dex_compilation_unit.h
index 854927d..24a9a5b 100644
--- a/compiler/driver/dex_compilation_unit.h
+++ b/compiler/driver/dex_compilation_unit.h
@@ -34,7 +34,7 @@
class DexCompilationUnit : public DeletableArenaObject<kArenaAllocMisc> {
public:
- DexCompilationUnit(jobject class_loader,
+ DexCompilationUnit(Handle<mirror::ClassLoader> class_loader,
ClassLinker* class_linker,
const DexFile& dex_file,
const DexFile::CodeItem* code_item,
@@ -44,7 +44,7 @@
const VerifiedMethod* verified_method,
Handle<mirror::DexCache> dex_cache);
- jobject GetClassLoader() const {
+ Handle<mirror::ClassLoader> GetClassLoader() const {
return class_loader_;
}
@@ -113,7 +113,7 @@
}
private:
- const jobject class_loader_;
+ const Handle<mirror::ClassLoader> class_loader_;
ClassLinker* const class_linker_;
@@ -125,7 +125,7 @@
const uint32_t access_flags_;
const VerifiedMethod* verified_method_;
- Handle<mirror::DexCache> dex_cache_;
+ const Handle<mirror::DexCache> dex_cache_;
std::string symbol_;
};