Allow unresolved exception classes in boot image.
And incorporate dex2oat_image_test changes from
https://android-review.googlesource.com/1302586
to test that this works.
Test: m test-art-host-gtest
Bug: 153648261
Change-Id: I810de9c84973156c06a2c871bf2e0921c80a3fa4
diff --git a/dex2oat/dex2oat_image_test.cc b/dex2oat/dex2oat_image_test.cc
index d01b64f..71e9b1b 100644
--- a/dex2oat/dex2oat_image_test.cc
+++ b/dex2oat/dex2oat_image_test.cc
@@ -184,13 +184,11 @@
}
// Compile only a subset of the libcore dex files to make this test shorter.
std::vector<std::string> libcore_dex_files = GetLibCoreDexFileNames();
- // The primary image must contain at least core-oj and core-libart to initialize the runtime
- // and we also need the core-icu4j if we want to compile these with full profile.
+ // The primary image must contain at least core-oj and core-libart to initialize the runtime.
ASSERT_NE(std::string::npos, libcore_dex_files[0].find("core-oj"));
ASSERT_NE(std::string::npos, libcore_dex_files[1].find("core-libart"));
- ASSERT_NE(std::string::npos, libcore_dex_files[2].find("core-icu4j"));
ArrayRef<const std::string> dex_files =
- ArrayRef<const std::string>(libcore_dex_files).SubArray(/*pos=*/ 0u, /*length=*/ 3u);
+ ArrayRef<const std::string>(libcore_dex_files).SubArray(/*pos=*/ 0u, /*length=*/ 2u);
ImageSizes base_sizes = CompileImageAndGetSizes(dex_files, {});
ImageSizes everything_sizes;
@@ -274,19 +272,17 @@
ArrayRef<const std::string> full_bcp(libcore_dex_files);
size_t total_dex_files = full_bcp.size();
- ASSERT_GE(total_dex_files, 5u); // 3 for "head", 1 for "tail", at least one for "mid", see below.
+ ASSERT_GE(total_dex_files, 4u); // 2 for "head", 1 for "tail", at least one for "mid", see below.
- // The primary image must contain at least core-oj and core-libart to initialize the runtime
- // and we also need the core-icu4j if we want to compile these with full profile.
+ // The primary image must contain at least core-oj and core-libart to initialize the runtime.
ASSERT_NE(std::string::npos, full_bcp[0].find("core-oj"));
ASSERT_NE(std::string::npos, full_bcp[1].find("core-libart"));
- ASSERT_NE(std::string::npos, full_bcp[2].find("core-icu4j"));
- ArrayRef<const std::string> head_dex_files = full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ 3u);
+ ArrayRef<const std::string> head_dex_files = full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ 2u);
// Middle part is everything else except for conscrypt.
ASSERT_NE(std::string::npos, full_bcp[full_bcp.size() - 1u].find("conscrypt"));
ArrayRef<const std::string> mid_bcp =
full_bcp.SubArray(/*pos=*/ 0u, /*length=*/ total_dex_files - 1u);
- ArrayRef<const std::string> mid_dex_files = mid_bcp.SubArray(/*pos=*/ 3u);
+ ArrayRef<const std::string> mid_dex_files = mid_bcp.SubArray(/*pos=*/ 2u);
// Tail is just the conscrypt.
ArrayRef<const std::string> tail_dex_files =
full_bcp.SubArray(/*pos=*/ total_dex_files - 1u, /*length=*/ 1u);
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index e21f492..b97c1f0 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -976,8 +976,7 @@
return true;
}
- void FindExceptionTypesToResolve(
- std::set<std::pair<dex::TypeIndex, const DexFile*>>* exceptions_to_resolve)
+ void FindExceptionTypesToResolve(std::set<TypeReference>* exceptions_to_resolve)
REQUIRES_SHARED(Locks::mutator_lock_) {
const auto pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
for (ObjPtr<mirror::Class> klass : classes_) {
@@ -990,7 +989,7 @@
private:
void FindExceptionTypesToResolveForMethod(
ArtMethod* method,
- std::set<std::pair<dex::TypeIndex, const DexFile*>>* exceptions_to_resolve)
+ std::set<TypeReference>* exceptions_to_resolve)
REQUIRES_SHARED(Locks::mutator_lock_) {
if (method->GetCodeItem() == nullptr) {
return; // native or abstract method
@@ -1013,8 +1012,8 @@
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->IsResolvedTypeIdx(encoded_catch_handler_handlers_type_idx)) {
- exceptions_to_resolve->emplace(encoded_catch_handler_handlers_type_idx,
- method->GetDexFile());
+ exceptions_to_resolve->emplace(method->GetDexFile(),
+ encoded_catch_handler_handlers_type_idx);
}
// ignore address associated with catch handler
DecodeUnsignedLeb128(&encoded_catch_handler_list);
@@ -1107,10 +1106,12 @@
// Resolve exception classes referenced by the loaded classes. The catch logic assumes
// exceptions are resolved by the verifier when there is a catch block in an interested method.
// Do this here so that exception classes appear to have been specified image classes.
- std::set<std::pair<dex::TypeIndex, const DexFile*>> unresolved_exception_types;
- StackHandleScope<1> hs(self);
+ std::set<TypeReference> unresolved_exception_types;
+ StackHandleScope<2u> hs(self);
Handle<mirror::Class> java_lang_Throwable(
hs.NewHandle(class_linker->FindSystemClass(self, "Ljava/lang/Throwable;")));
+ MutableHandle<mirror::DexCache> dex_cache = hs.NewHandle(java_lang_Throwable->GetDexCache());
+ DCHECK(dex_cache != nullptr);
do {
unresolved_exception_types.clear();
{
@@ -1121,24 +1122,25 @@
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;
- StackHandleScope<1> hs2(self);
- Handle<mirror::DexCache> dex_cache(hs2.NewHandle(class_linker->RegisterDexFile(*dex_file,
- nullptr)));
- ObjPtr<mirror::Class> klass =
- (dex_cache != nullptr)
- ? class_linker->ResolveType(exception_type_idx,
- dex_cache,
- ScopedNullHandle<mirror::ClassLoader>())
- : nullptr;
+ for (auto it = unresolved_exception_types.begin(); it != unresolved_exception_types.end(); ) {
+ dex::TypeIndex exception_type_idx = it->TypeIndex();
+ const DexFile* dex_file = it->dex_file;
+ if (dex_cache->GetDexFile() != dex_file) {
+ dex_cache.Assign(class_linker->RegisterDexFile(*dex_file, /*class_loader=*/ nullptr));
+ DCHECK(dex_cache != nullptr);
+ }
+ ObjPtr<mirror::Class> klass = class_linker->ResolveType(
+ exception_type_idx, dex_cache, ScopedNullHandle<mirror::ClassLoader>());
if (klass == nullptr) {
const dex::TypeId& type_id = dex_file->GetTypeId(exception_type_idx);
const char* descriptor = dex_file->GetTypeDescriptor(type_id);
- LOG(FATAL) << "Failed to resolve class " << descriptor;
+ VLOG(compiler) << "Failed to resolve exception class " << descriptor;
+ self->ClearException();
+ it = unresolved_exception_types.erase(it);
+ } else {
+ DCHECK(java_lang_Throwable->IsAssignableFrom(klass));
+ ++it;
}
- DCHECK(java_lang_Throwable->IsAssignableFrom(klass));
}
// Resolving exceptions may load classes that reference more exceptions, iterate until no
// more are found