diff options
author | 2017-04-21 17:16:44 +0100 | |
---|---|---|
committer | 2017-04-27 16:04:13 +0100 | |
commit | 4e868fa7b8c47600695ff92deeb373674956a67d (patch) | |
tree | acdb92a2b765cc87a08459267e430a8866e608cf | |
parent | 4dc06e2ef900132d8395539842c35533da8b912a (diff) |
Make vdex and dexlayout compatible.
Unquicken the vdex before dexlayout, to keep the dex integrity.
bug: 37558732
Test: run-test with speed-profile
Change-Id: Ifcd5c2e4378ccb0df0a66d07f68df31d94b83220
-rw-r--r-- | compiler/Android.bp | 1 | ||||
-rw-r--r-- | compiler/dex/dex_to_dex_decompiler_test.cc | 2 | ||||
-rw-r--r-- | compiler/dex/verification_results.cc | 5 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 71 | ||||
-rw-r--r-- | compiler/oat_writer.cc | 23 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 37 | ||||
-rw-r--r-- | dex2oat/dex2oat_test.cc | 6 | ||||
-rw-r--r-- | dexlayout/dexdiag.cc | 1 | ||||
-rw-r--r-- | runtime/Android.bp | 1 | ||||
-rw-r--r-- | runtime/base/stl_util.h | 11 | ||||
-rw-r--r-- | runtime/dex_to_dex_decompiler.cc (renamed from compiler/dex/dex_to_dex_decompiler.cc) | 0 | ||||
-rw-r--r-- | runtime/dex_to_dex_decompiler.h (renamed from compiler/dex/dex_to_dex_decompiler.h) | 6 | ||||
-rw-r--r-- | runtime/oat_file.cc | 2 | ||||
-rw-r--r-- | runtime/oat_file_assistant.cc | 1 | ||||
-rw-r--r-- | runtime/openjdkjvmti/fixed_up_dex_file.cc | 4 | ||||
-rw-r--r-- | runtime/runtime.cc | 1 | ||||
-rw-r--r-- | runtime/vdex_file.cc | 91 | ||||
-rw-r--r-- | runtime/vdex_file.h | 12 | ||||
-rw-r--r-- | runtime/vdex_file_test.cc | 4 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 2 | ||||
-rwxr-xr-x | test/etc/run-test-jar | 2 | ||||
-rw-r--r-- | test/knownfailures.json | 18 |
22 files changed, 182 insertions, 119 deletions
diff --git a/compiler/Android.bp b/compiler/Android.bp index dec8b577d8..6ef866a3c6 100644 --- a/compiler/Android.bp +++ b/compiler/Android.bp @@ -28,7 +28,6 @@ art_cc_defaults { "compiled_method.cc", "debug/elf_debug_writer.cc", "dex/dex_to_dex_compiler.cc", - "dex/dex_to_dex_decompiler.cc", "dex/inline_method_analyser.cc", "dex/verified_method.cc", "dex/verification_results.cc", diff --git a/compiler/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc index 43100c9ddb..e486e2e6ec 100644 --- a/compiler/dex/dex_to_dex_decompiler_test.cc +++ b/compiler/dex/dex_to_dex_decompiler_test.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "dex/dex_to_dex_decompiler.h" +#include "dex_to_dex_decompiler.h" #include "class_linker.h" #include "compiler/common_compiler_test.h" diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc index 4c50797067..3f0df3b2c8 100644 --- a/compiler/dex/verification_results.cc +++ b/compiler/dex/verification_results.cc @@ -104,11 +104,12 @@ void VerificationResults::CreateVerifiedMethodFor(MethodReference ref) { // This method should only be called for classes verified at compile time, // which have no verifier error, nor has methods that we know will throw // at runtime. - AtomicMap::InsertResult result = atomic_verified_methods_.Insert( + atomic_verified_methods_.Insert( ref, /*expected*/ nullptr, new VerifiedMethod(/* encountered_error_types */ 0, /* has_runtime_throw */ false)); - DCHECK_EQ(result, AtomicMap::kInsertResultSuccess); + // We don't check the result of `Insert` as we could insert twice for the same + // MethodReference in the presence of duplicate methods. } void VerificationResults::AddRejectedClass(ClassReference ref) { diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 4f55ed6b8e..fbfa087cfd 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -45,7 +45,6 @@ #include "dex_file-inl.h" #include "dex_instruction-inl.h" #include "dex/dex_to_dex_compiler.h" -#include "dex/dex_to_dex_decompiler.h" #include "dex/verification_results.h" #include "dex/verified_method.h" #include "driver/compiler_options.h" @@ -431,61 +430,6 @@ INTRINSICS_LIST(SETUP_INTRINSICS) FreeThreadPools(); } -// In-place unquicken the given `dex_files` based on `quickening_info`. -static void Unquicken(const std::vector<const DexFile*>& dex_files, - const ArrayRef<const uint8_t>& quickening_info, - bool decompile_return_instruction) { - const uint8_t* quickening_info_ptr = quickening_info.data(); - const uint8_t* const quickening_info_end = quickening_info.data() + quickening_info.size(); - for (const DexFile* dex_file : dex_files) { - for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { - const DexFile::ClassDef& class_def = dex_file->GetClassDef(i); - const uint8_t* class_data = dex_file->GetClassData(class_def); - if (class_data == nullptr) { - continue; - } - ClassDataItemIterator it(*dex_file, class_data); - // Skip fields - while (it.HasNextStaticField()) { - it.Next(); - } - while (it.HasNextInstanceField()) { - it.Next(); - } - - while (it.HasNextDirectMethod()) { - const DexFile::CodeItem* code_item = it.GetMethodCodeItem(); - if (code_item != nullptr) { - uint32_t quickening_size = *reinterpret_cast<const uint32_t*>(quickening_info_ptr); - quickening_info_ptr += sizeof(uint32_t); - optimizer::ArtDecompileDEX(*code_item, - ArrayRef<const uint8_t>(quickening_info_ptr, quickening_size), - decompile_return_instruction); - quickening_info_ptr += quickening_size; - } - it.Next(); - } - - while (it.HasNextVirtualMethod()) { - const DexFile::CodeItem* code_item = it.GetMethodCodeItem(); - if (code_item != nullptr) { - uint32_t quickening_size = *reinterpret_cast<const uint32_t*>(quickening_info_ptr); - quickening_info_ptr += sizeof(uint32_t); - optimizer::ArtDecompileDEX(*code_item, - ArrayRef<const uint8_t>(quickening_info_ptr, quickening_size), - decompile_return_instruction); - quickening_info_ptr += quickening_size; - } - it.Next(); - } - DCHECK(!it.HasNext()); - } - } - if (quickening_info_ptr != quickening_info_end) { - LOG(FATAL) << "Failed to use all quickening info"; - } -} - void CompilerDriver::CompileAll(jobject class_loader, const std::vector<const DexFile*>& dex_files, VdexFile* vdex_file, @@ -494,15 +438,12 @@ void CompilerDriver::CompileAll(jobject class_loader, // TODO: we unquicken unconditionnally, as we don't know // if the boot image has changed. How exactly we'll know is under // experimentation. - if (vdex_file->GetQuickeningInfo().size() != 0) { - TimingLogger::ScopedTiming t("Unquicken", timings); - // We do not decompile a RETURN_VOID_NO_BARRIER into a RETURN_VOID, as the quickening - // optimization does not depend on the boot image (the optimization relies on not - // having final fields in a class, which does not change for an app). - Unquicken(dex_files, - vdex_file->GetQuickeningInfo(), - /* decompile_return_instruction */ false); - } + TimingLogger::ScopedTiming t("Unquicken", timings); + // We do not decompile a RETURN_VOID_NO_BARRIER into a RETURN_VOID, as the quickening + // optimization does not depend on the boot image (the optimization relies on not + // having final fields in a class, which does not change for an app). + VdexFile::Unquicken(dex_files, vdex_file->GetQuickeningInfo()); + Runtime::Current()->GetCompilerCallbacks()->SetVerifierDeps( new verifier::VerifierDeps(dex_files, vdex_file->GetVerifierDepsData())); } diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index 964692776c..6b5387ae19 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -2474,11 +2474,28 @@ bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_fil /* verify */ true, /* verify_checksum */ true, &error_msg); - } else { - CHECK(oat_dex_file->source_.IsRawFile()) - << static_cast<size_t>(oat_dex_file->source_.GetType()); + } else if (oat_dex_file->source_.IsRawFile()) { File* raw_file = oat_dex_file->source_.GetRawFile(); dex_file = DexFile::OpenDex(raw_file->Fd(), location, /* verify_checksum */ true, &error_msg); + } else { + // The source data is a vdex file. + CHECK(oat_dex_file->source_.IsRawData()) + << static_cast<size_t>(oat_dex_file->source_.GetType()); + const uint8_t* raw_dex_file = oat_dex_file->source_.GetRawData(); + // Note: The raw data has already been checked to contain the header + // and all the data that the header specifies as the file size. + DCHECK(raw_dex_file != nullptr); + DCHECK(ValidateDexFileHeader(raw_dex_file, oat_dex_file->GetLocation())); + const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file); + // Since the source may have had its layout changed, or may be quickened, don't verify it. + dex_file = DexFile::Open(raw_dex_file, + header->file_size_, + location, + oat_dex_file->dex_file_location_checksum_, + nullptr, + /* verify */ false, + /* verify_checksum */ false, + &error_msg); } if (dex_file == nullptr) { LOG(ERROR) << "Failed to open dex file for layout: " << error_msg; diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 68864daffc..4cba36aef6 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -718,6 +718,10 @@ class Dex2Oat FINAL { Usage("Can't have both --input-vdex-fd and --input-vdex"); } + if (output_vdex_fd_ != -1 && !output_vdex_.empty()) { + Usage("Can't have both --output-vdex-fd and --output-vdex"); + } + if (!oat_filenames_.empty() && oat_fd_ != -1) { Usage("--oat-file should not be used with --oat-fd"); } @@ -1122,6 +1126,8 @@ class Dex2Oat FINAL { ParseInputVdexFd(option); } else if (option.starts_with("--input-vdex=")) { input_vdex_ = option.substr(strlen("--input-vdex=")).data(); + } else if (option.starts_with("--output-vdex=")) { + output_vdex_ = option.substr(strlen("--output-vdex=")).data(); } else if (option.starts_with("--output-vdex-fd=")) { ParseOutputVdexFd(option); } else if (option.starts_with("--oat-file=")) { @@ -1257,6 +1263,7 @@ class Dex2Oat FINAL { } // OAT and VDEX file handling + bool eagerly_unquicken_vdex = DoDexLayoutOptimizations(); if (oat_fd_ == -1) { DCHECK(!oat_filenames_.empty()); @@ -1278,12 +1285,15 @@ class Dex2Oat FINAL { input_vdex_file_ = VdexFile::Open(input_vdex_, /* writable */ false, /* low_4gb */ false, + eagerly_unquicken_vdex, &error_msg); } DCHECK_EQ(output_vdex_fd_, -1); - std::string vdex_filename = ReplaceFileExtension(oat_filename, "vdex"); - if (vdex_filename == input_vdex_) { + std::string vdex_filename = output_vdex_.empty() + ? ReplaceFileExtension(oat_filename, "vdex") + : output_vdex_; + if (vdex_filename == input_vdex_ && output_vdex_.empty()) { update_input_vdex_ = true; std::unique_ptr<File> vdex_file(OS::OpenFileReadWrite(vdex_filename.c_str())); vdex_files_.push_back(std::move(vdex_file)); @@ -1325,6 +1335,7 @@ class Dex2Oat FINAL { "vdex", /* writable */ false, /* low_4gb */ false, + eagerly_unquicken_vdex, &error_msg); // If there's any problem with the passed vdex, just warn and proceed // without it. @@ -2089,10 +2100,6 @@ class Dex2Oat FINAL { return DoProfileGuidedOptimizations(); } - bool HasInputVdexFile() const { - return input_vdex_file_ != nullptr || input_vdex_fd_ != -1 || !input_vdex_.empty(); - } - bool LoadProfile() { DCHECK(UseProfile()); @@ -2148,16 +2155,6 @@ class Dex2Oat FINAL { return dex_files_size >= very_large_threshold_; } - template <typename T> - static std::vector<T*> MakeNonOwningPointerVector(const std::vector<std::unique_ptr<T>>& src) { - std::vector<T*> result; - result.reserve(src.size()); - for (const std::unique_ptr<T>& t : src) { - result.push_back(t.get()); - } - return result; - } - std::vector<std::string> GetClassPathLocations(const std::string& class_path) { // This function is used only for apps and for an app we have exactly one oat file. DCHECK(!IsBootImage()); @@ -2690,6 +2687,7 @@ class Dex2Oat FINAL { int input_vdex_fd_; int output_vdex_fd_; std::string input_vdex_; + std::string output_vdex_; std::unique_ptr<VdexFile> input_vdex_file_; std::vector<const char*> dex_filenames_; std::vector<const char*> dex_locations_; @@ -2896,13 +2894,6 @@ static dex2oat::ReturnCode Dex2oat(int argc, char** argv) { } } - if (dex2oat->DoDexLayoutOptimizations()) { - if (dex2oat->HasInputVdexFile()) { - LOG(ERROR) << "Dexlayout is incompatible with an input VDEX"; - return dex2oat::ReturnCode::kOther; - } - } - art::MemMap::Init(); // For ZipEntry::ExtractToMemMap, and vdex. // Check early that the result of compilation can be written diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc index 9d9f8c6a2a..a267766456 100644 --- a/dex2oat/dex2oat_test.cc +++ b/dex2oat/dex2oat_test.cc @@ -736,12 +736,12 @@ class Dex2oatLayoutTest : public Dex2oatTest { /* use_fd */ true, /* num_profile_classes */ 1, { input_vdex, output_vdex }, - /* expect_success */ false); - EXPECT_EQ(vdex_file2.GetFile()->GetLength(), 0u); + /* expect_success */ true); + EXPECT_GT(vdex_file2.GetFile()->GetLength(), 0u); } ASSERT_EQ(vdex_file1->FlushCloseOrErase(), 0) << "Could not flush and close vdex file"; CheckValidity(); - ASSERT_FALSE(success_); + ASSERT_TRUE(success_); } void CheckResult(const std::string& dex_location, diff --git a/dexlayout/dexdiag.cc b/dexlayout/dexdiag.cc index 688201b6b8..ea2679a1e3 100644 --- a/dexlayout/dexdiag.cc +++ b/dexlayout/dexdiag.cc @@ -313,6 +313,7 @@ static bool DisplayMappingIfFromVdexFile(pm_map_t* map, Printer* printer) { std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_name, false /*writeable*/, false /*low_4gb*/, + false /*unquicken */, &error_msg /*out*/)); if (vdex == nullptr) { std::cerr << "Could not open vdex file " diff --git a/runtime/Android.bp b/runtime/Android.bp index cff2cbccdb..186996894e 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -57,6 +57,7 @@ cc_defaults { "dex_file_annotations.cc", "dex_file_verifier.cc", "dex_instruction.cc", + "dex_to_dex_decompiler.cc", "elf_file.cc", "exec_utils.cc", "fault_handler.cc", diff --git a/runtime/base/stl_util.h b/runtime/base/stl_util.h index d5f375a5d9..cfe27f3811 100644 --- a/runtime/base/stl_util.h +++ b/runtime/base/stl_util.h @@ -194,6 +194,17 @@ static inline void MergeSets(std::set<T>& to_update, const std::set<T>& other) { to_update.insert(other.begin(), other.end()); } +// Returns a copy of the passed vector that doesn't memory-own its entries. +template <typename T> +static inline std::vector<T*> MakeNonOwningPointerVector(const std::vector<std::unique_ptr<T>>& src) { + std::vector<T*> result; + result.reserve(src.size()); + for (const std::unique_ptr<T>& t : src) { + result.push_back(t.get()); + } + return result; +} + } // namespace art #endif // ART_RUNTIME_BASE_STL_UTIL_H_ diff --git a/compiler/dex/dex_to_dex_decompiler.cc b/runtime/dex_to_dex_decompiler.cc index 85d5784c7a..85d5784c7a 100644 --- a/compiler/dex/dex_to_dex_decompiler.cc +++ b/runtime/dex_to_dex_decompiler.cc diff --git a/compiler/dex/dex_to_dex_decompiler.h b/runtime/dex_to_dex_decompiler.h index b5d5b91915..d7cb1641e1 100644 --- a/compiler/dex/dex_to_dex_decompiler.h +++ b/runtime/dex_to_dex_decompiler.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef ART_COMPILER_DEX_DEX_TO_DEX_DECOMPILER_H_ -#define ART_COMPILER_DEX_DEX_TO_DEX_DECOMPILER_H_ +#ifndef ART_RUNTIME_DEX_TO_DEX_DECOMPILER_H_ +#define ART_RUNTIME_DEX_TO_DEX_DECOMPILER_H_ #include "base/array_ref.h" #include "dex_file.h" @@ -36,4 +36,4 @@ bool ArtDecompileDEX(const DexFile::CodeItem& code_item, } // namespace optimizer } // namespace art -#endif // ART_COMPILER_DEX_DEX_TO_DEX_DECOMPILER_H_ +#endif // ART_RUNTIME_DEX_TO_DEX_DECOMPILER_H_ diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 4a85d4795e..9affeb0fcc 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -193,7 +193,7 @@ bool OatFileBase::LoadVdex(const std::string& vdex_filename, bool writable, bool low_4gb, std::string* error_msg) { - vdex_ = VdexFile::Open(vdex_filename, writable, low_4gb, error_msg); + vdex_ = VdexFile::Open(vdex_filename, writable, low_4gb, /* unquicken*/ false, error_msg); if (vdex_.get() == nullptr) { *error_msg = StringPrintf("Failed to load vdex file '%s' %s", vdex_filename.c_str(), diff --git a/runtime/oat_file_assistant.cc b/runtime/oat_file_assistant.cc index 9471cbad6c..2c2b6fdcc2 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -808,6 +808,7 @@ OatFileAssistant::OatStatus OatFileAssistant::OatFileInfo::Status() { std::unique_ptr<VdexFile> vdex = VdexFile::Open(vdex_filename, /*writeable*/false, /*low_4gb*/false, + /*unquicken*/false, &error_msg); if (vdex == nullptr) { status_ = kOatCannotOpen; diff --git a/runtime/openjdkjvmti/fixed_up_dex_file.cc b/runtime/openjdkjvmti/fixed_up_dex_file.cc index 3338358796..29aebae4b6 100644 --- a/runtime/openjdkjvmti/fixed_up_dex_file.cc +++ b/runtime/openjdkjvmti/fixed_up_dex_file.cc @@ -32,10 +32,8 @@ #include "fixed_up_dex_file.h" #include "dex_file-inl.h" -// Compiler includes. -#include "dex/dex_to_dex_decompiler.h" - // Runtime includes. +#include "dex_to_dex_decompiler.h" #include "oat_file.h" #include "vdex_file.h" diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 9ca7abf2b5..e61ec23036 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -905,6 +905,7 @@ static bool OpenDexFilesFromImage(const std::string& image_location, std::unique_ptr<VdexFile> vdex_file(VdexFile::Open(vdex_filename, false /* writable */, false /* low_4gb */, + false, /* unquicken */ &error_msg)); if (vdex_file.get() == nullptr) { return false; diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc index 945f08b58a..e93f04d082 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -21,8 +21,10 @@ #include <memory> #include "base/logging.h" +#include "base/stl_util.h" #include "base/unix_file/fd_file.h" #include "dex_file.h" +#include "dex_to_dex_decompiler.h" namespace art { @@ -54,6 +56,7 @@ VdexFile::Header::Header(uint32_t number_of_dex_files, std::unique_ptr<VdexFile> VdexFile::Open(const std::string& vdex_filename, bool writable, bool low_4gb, + bool unquicken, std::string* error_msg) { if (!OS::FileExists(vdex_filename.c_str())) { *error_msg = "File " + vdex_filename + " does not exist."; @@ -78,7 +81,7 @@ std::unique_ptr<VdexFile> VdexFile::Open(const std::string& vdex_filename, return nullptr; } - return Open(vdex_file->Fd(), vdex_length, vdex_filename, writable, low_4gb, error_msg); + return Open(vdex_file->Fd(), vdex_length, vdex_filename, writable, low_4gb, unquicken, error_msg); } std::unique_ptr<VdexFile> VdexFile::Open(int file_fd, @@ -86,15 +89,17 @@ std::unique_ptr<VdexFile> VdexFile::Open(int file_fd, const std::string& vdex_filename, bool writable, bool low_4gb, + bool unquicken, std::string* error_msg) { - std::unique_ptr<MemMap> mmap(MemMap::MapFile(vdex_length, - writable ? PROT_READ | PROT_WRITE : PROT_READ, - MAP_SHARED, - file_fd, - 0 /* start offset */, - low_4gb, - vdex_filename.c_str(), - error_msg)); + std::unique_ptr<MemMap> mmap(MemMap::MapFile( + vdex_length, + (writable || unquicken) ? PROT_READ | PROT_WRITE : PROT_READ, + unquicken ? MAP_PRIVATE : MAP_SHARED, + file_fd, + 0 /* start offset */, + low_4gb, + vdex_filename.c_str(), + error_msg)); if (mmap == nullptr) { *error_msg = "Failed to mmap file " + vdex_filename + " : " + *error_msg; return nullptr; @@ -106,6 +111,16 @@ std::unique_ptr<VdexFile> VdexFile::Open(int file_fd, return nullptr; } + if (unquicken) { + std::vector<std::unique_ptr<const DexFile>> unique_ptr_dex_files; + if (!vdex->OpenAllDexFiles(&unique_ptr_dex_files, error_msg)) { + return nullptr; + } + Unquicken(MakeNonOwningPointerVector(unique_ptr_dex_files), vdex->GetQuickeningInfo()); + // Update the quickening info size to pretend there isn't any. + reinterpret_cast<Header*>(vdex->mmap_->Begin())->quickening_info_size_ = 0; + } + *error_msg = "Success"; return vdex; } @@ -148,4 +163,62 @@ bool VdexFile::OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_ return true; } +void VdexFile::Unquicken(const std::vector<const DexFile*>& dex_files, + const ArrayRef<const uint8_t>& quickening_info) { + if (quickening_info.size() == 0) { + // If there is no quickening info, we bail early, as the code below expects at + // least the size of quickening data for each method that has a code item. + return; + } + const uint8_t* quickening_info_ptr = quickening_info.data(); + const uint8_t* const quickening_info_end = quickening_info.data() + quickening_info.size(); + for (const DexFile* dex_file : dex_files) { + for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { + const DexFile::ClassDef& class_def = dex_file->GetClassDef(i); + const uint8_t* class_data = dex_file->GetClassData(class_def); + if (class_data == nullptr) { + continue; + } + ClassDataItemIterator it(*dex_file, class_data); + // Skip fields + while (it.HasNextStaticField()) { + it.Next(); + } + while (it.HasNextInstanceField()) { + it.Next(); + } + + while (it.HasNextDirectMethod()) { + const DexFile::CodeItem* code_item = it.GetMethodCodeItem(); + if (code_item != nullptr) { + uint32_t quickening_size = *reinterpret_cast<const uint32_t*>(quickening_info_ptr); + quickening_info_ptr += sizeof(uint32_t); + optimizer::ArtDecompileDEX(*code_item, + ArrayRef<const uint8_t>(quickening_info_ptr, quickening_size), + /* decompile_return_instruction */ false); + quickening_info_ptr += quickening_size; + } + it.Next(); + } + + while (it.HasNextVirtualMethod()) { + const DexFile::CodeItem* code_item = it.GetMethodCodeItem(); + if (code_item != nullptr) { + uint32_t quickening_size = *reinterpret_cast<const uint32_t*>(quickening_info_ptr); + quickening_info_ptr += sizeof(uint32_t); + optimizer::ArtDecompileDEX(*code_item, + ArrayRef<const uint8_t>(quickening_info_ptr, quickening_size), + /* decompile_return_instruction */ false); + quickening_info_ptr += quickening_size; + } + it.Next(); + } + DCHECK(!it.HasNext()); + } + } + if (quickening_info_ptr != quickening_info_end) { + LOG(FATAL) << "Failed to use all quickening info"; + } +} + } // namespace art diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h index 9840555bbd..9c0d9dba8f 100644 --- a/runtime/vdex_file.h +++ b/runtime/vdex_file.h @@ -71,6 +71,8 @@ class VdexFile { uint32_t dex_size_; uint32_t verifier_deps_size_; uint32_t quickening_info_size_; + + friend class VdexFile; }; typedef uint32_t VdexChecksum; @@ -79,6 +81,7 @@ class VdexFile { static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename, bool writable, bool low_4gb, + bool unquicken, std::string* error_msg); // Returns nullptr if the vdex file cannot be opened or is not valid. @@ -87,6 +90,7 @@ class VdexFile { const std::string& vdex_filename, bool writable, bool low_4gb, + bool unquicken, std::string* error_msg); const uint8_t* Begin() const { return mmap_->Begin(); } @@ -124,12 +128,14 @@ class VdexFile { return reinterpret_cast<const uint32_t*>(Begin() + sizeof(Header))[dex_file_index]; } - // Opens all the dex files contained in this vdex file. This is currently - // used for dumping tools only, and has not been tested for use by the - // remainder of the runtime. + // Opens all the dex files contained in this vdex file. bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files, std::string* error_msg); + // In-place unquicken the given `dex_files` based on `quickening_info`. + static void Unquicken(const std::vector<const DexFile*>& dex_files, + const ArrayRef<const uint8_t>& quickening_info); + private: explicit VdexFile(MemMap* mmap) : mmap_(mmap) {} diff --git a/runtime/vdex_file_test.cc b/runtime/vdex_file_test.cc index 909e117ccc..ced6e28577 100644 --- a/runtime/vdex_file_test.cc +++ b/runtime/vdex_file_test.cc @@ -36,10 +36,12 @@ TEST_F(VdexFileTest, OpenEmptyVdex) { tmp.GetFilename(), /*writable*/false, /*low_4gb*/false, + /*quicken*/false, &error_msg); EXPECT_TRUE(vdex == nullptr); - vdex = VdexFile::Open(tmp.GetFilename(), /*writable*/false, /*low_4gb*/false, &error_msg); + vdex = VdexFile::Open( + tmp.GetFilename(), /*writable*/false, /*low_4gb*/false, /*quicken*/ false, &error_msg); EXPECT_TRUE(vdex == nullptr); } diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 2b0c6127af..cb9c6052a2 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -3764,7 +3764,7 @@ const RegType& MethodVerifier::ResolveClassAndCheckAccess(dex::TypeIndex class_i const RegType& referrer = GetDeclaringClass(); if (!referrer.IsUnresolvedTypes() && !referrer.CanAccess(*result)) { Fail(VERIFY_ERROR_ACCESS_CLASS) << "illegal class access: '" - << referrer << "' -> '" << result << "'"; + << referrer << "' -> '" << *result << "'"; } } return *result; diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar index 5e5b4098b3..f725b89eb1 100755 --- a/test/etc/run-test-jar +++ b/test/etc/run-test-jar @@ -605,6 +605,8 @@ if [ "$PREBUILD" = "y" ]; then fi if [ "$TEST_VDEX" = "y" ]; then vdex_cmdline="${dex2oat_cmdline} ${VDEX_FILTER} --input-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex" + elif [ "$PROFILE" = "y" ] || [ "$RANDOM_PROFILE" = "y" ]; then + vdex_cmdline="${dex2oat_cmdline} --input-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex --output-vdex=$DEX_LOCATION/oat/$ISA/$TEST_NAME.vdex" fi fi diff --git a/test/knownfailures.json b/test/knownfailures.json index 9ab9bfa896..c7ad5bf9c1 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -665,5 +665,23 @@ "description": "The tests above fail with --build-with-javac-dx.", "env_vars": {"ANDROID_COMPILE_WITH_JACK": "false"}, "bug": "b/37636792" + }, + { + "tests": "648-many-direct-methods", + "variant": "optimizing", + "description": "Test disabled with AOT because of dex2oatd timeouts.", + "bug": "b/33650497" + }, + { + "tests": [ + "536-checker-needs-access-check", + "537-checker-inline-and-unverified", + "569-checker-pattern-replacement", + "586-checker-null-array-get" + ], + "description": [ + "Tests that have verify-at-runtime classes, but being compiled when using vdex." + ], + "variant": "speed-profile" } ] |