diff options
55 files changed, 508 insertions, 535 deletions
diff --git a/build/Android.oat.mk b/build/Android.oat.mk index c733febd06..3f9ea15fb3 100644 --- a/build/Android.oat.mk +++ b/build/Android.oat.mk @@ -56,11 +56,11 @@ define create-core-oat-host-rules core_dex2oat_dependency := $(DEX2OAT) endif ifeq ($(1),interpreter) - core_compile_options += --compiler-filter=interpret-only + core_compile_options += --compiler-filter=quicken core_infix := -interpreter endif ifeq ($(1),interp-ac) - core_compile_options += --compiler-filter=verify-at-runtime --runtime-arg -Xverify:softfail + core_compile_options += --compiler-filter=extract --runtime-arg -Xverify:softfail core_infix := -interp-ac endif ifneq ($(filter-out interpreter interp-ac optimizing,$(1)),) @@ -166,11 +166,11 @@ define create-core-oat-target-rules core_dex2oat_dependency := $(DEX2OAT) endif ifeq ($(1),interpreter) - core_compile_options += --compiler-filter=interpret-only + core_compile_options += --compiler-filter=quicken core_infix := -interpreter endif ifeq ($(1),interp-ac) - core_compile_options += --compiler-filter=verify-at-runtime --runtime-arg -Xverify:softfail + core_compile_options += --compiler-filter=extract --runtime-arg -Xverify:softfail core_infix := -interp-ac endif ifneq ($(filter-out interpreter interp-ac optimizing,$(1)),) 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 9a8d27cd03..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" @@ -38,7 +38,7 @@ class DexToDexDecompilerTest : public CommonCompilerTest { TimingLogger timings("CompilerDriverTest::CompileAll", false, false); TimingLogger::ScopedTiming t(__FUNCTION__, &timings); compiler_options_->boot_image_ = false; - compiler_options_->SetCompilerFilter(CompilerFilter::kInterpretOnly); + compiler_options_->SetCompilerFilter(CompilerFilter::kQuicken); compiler_driver_->CompileAll(class_loader, GetDexFiles(class_loader), /* verifier_deps */ nullptr, diff --git a/compiler/dex/verification_results.cc b/compiler/dex/verification_results.cc index 00a7d44bac..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) { @@ -126,7 +127,7 @@ bool VerificationResults::IsClassRejected(ClassReference ref) { bool VerificationResults::IsCandidateForCompilation(MethodReference&, const uint32_t access_flags) { - if (!compiler_options_->IsBytecodeCompilationEnabled()) { + if (!compiler_options_->IsAotCompilationEnabled()) { return false; } // Don't compile class initializers unless kEverything. diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index f77b3ddfe0..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" @@ -421,7 +420,7 @@ INTRINSICS_LIST(SETUP_INTRINSICS) // Compile: // 1) Compile all classes and methods enabled for compilation. May fall back to dex-to-dex // compilation. - if (GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (GetCompilerOptions().IsAnyCompilationEnabled()) { Compile(class_loader, dex_files, timings); } if (dump_stats_) { @@ -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())); } @@ -514,7 +455,7 @@ static optimizer::DexToDexCompilationLevel GetDexToDexCompilationLevel( const DexFile& dex_file, const DexFile::ClassDef& class_def) REQUIRES_SHARED(Locks::mutator_lock_) { auto* const runtime = Runtime::Current(); - DCHECK(driver.GetCompilerOptions().IsAnyMethodCompilationEnabled()); + DCHECK(driver.GetCompilerOptions().IsQuickeningCompilationEnabled()); const char* descriptor = dex_file.GetClassDescriptor(class_def); ClassLinker* class_linker = runtime->GetClassLinker(); mirror::Class* klass = class_linker->FindClass(self, descriptor, class_loader); @@ -986,7 +927,8 @@ void CompilerDriver::PreCompile(jobject class_loader, LoadImageClasses(timings); VLOG(compiler) << "LoadImageClasses: " << GetMemoryUsageString(false); - if (compiler_options_->IsAnyMethodCompilationEnabled()) { + if (compiler_options_->IsAnyCompilationEnabled()) { + // Resolve eagerly to prepare for compilation. Resolve(class_loader, dex_files, timings); VLOG(compiler) << "Resolve: " << GetMemoryUsageString(false); } @@ -1014,7 +956,7 @@ void CompilerDriver::PreCompile(jobject class_loader, << "situations. Please check the log."; } - if (compiler_options_->IsAnyMethodCompilationEnabled()) { + if (compiler_options_->IsAnyCompilationEnabled()) { if (kIsDebugBuild) { EnsureVerifiedOrVerifyAtRuntime(class_loader, dex_files); } @@ -2017,7 +1959,7 @@ bool CompilerDriver::FastVerify(jobject jclass_loader, return false; } - bool compiler_only_verifies = !GetCompilerOptions().IsAnyMethodCompilationEnabled(); + bool compiler_only_verifies = !GetCompilerOptions().IsAnyCompilationEnabled(); // We successfully validated the dependencies, now update class status // of verified classes. Note that the dependencies also record which classes diff --git a/compiler/driver/compiler_driver_test.cc b/compiler/driver/compiler_driver_test.cc index 42ff1e748a..17854fd61a 100644 --- a/compiler/driver/compiler_driver_test.cc +++ b/compiler/driver/compiler_driver_test.cc @@ -325,7 +325,7 @@ TEST_F(CompilerDriverProfileTest, ProfileGuidedCompilation) { class CompilerDriverVerifyTest : public CompilerDriverTest { protected: CompilerFilter::Filter GetCompilerFilter() const OVERRIDE { - return CompilerFilter::kVerifyProfile; + return CompilerFilter::kVerify; } void CheckVerifiedClass(jobject class_loader, const std::string& clazz) const { diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h index 2376fbf5f5..957ea99c49 100644 --- a/compiler/driver/compiler_options.h +++ b/compiler/driver/compiler_options.h @@ -84,32 +84,32 @@ class CompilerOptions FINAL { compiler_filter_ = compiler_filter; } - bool VerifyAtRuntime() const { - return compiler_filter_ == CompilerFilter::kVerifyAtRuntime; - } - - bool IsBytecodeCompilationEnabled() const { - return CompilerFilter::IsBytecodeCompilationEnabled(compiler_filter_); + bool IsAotCompilationEnabled() const { + return CompilerFilter::IsAotCompilationEnabled(compiler_filter_); } bool IsJniCompilationEnabled() const { return CompilerFilter::IsJniCompilationEnabled(compiler_filter_); } + bool IsQuickeningCompilationEnabled() const { + return CompilerFilter::IsQuickeningCompilationEnabled(compiler_filter_); + } + bool IsVerificationEnabled() const { return CompilerFilter::IsVerificationEnabled(compiler_filter_); } bool AssumeClassesAreVerified() const { - return compiler_filter_ == CompilerFilter::kVerifyNone; + return compiler_filter_ == CompilerFilter::kAssumeVerified; } - bool VerifyOnlyProfile() const { - return compiler_filter_ == CompilerFilter::kVerifyProfile; + bool VerifyAtRuntime() const { + return compiler_filter_ == CompilerFilter::kExtract; } - bool IsAnyMethodCompilationEnabled() const { - return CompilerFilter::IsAnyMethodCompilationEnabled(compiler_filter_); + bool IsAnyCompilationEnabled() const { + return CompilerFilter::IsAnyCompilationEnabled(compiler_filter_); } size_t GetHugeMethodThreshold() const { diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc index ead41240c2..1578c0cd3e 100644 --- a/compiler/oat_test.cc +++ b/compiler/oat_test.cc @@ -519,7 +519,7 @@ TEST_F(OatTest, EmptyTextSection) { if (insn_set == kArm) insn_set = kThumb2; std::string error_msg; std::vector<std::string> compiler_options; - compiler_options.push_back("--compiler-filter=verify-at-runtime"); + compiler_options.push_back("--compiler-filter=extract"); SetupCompiler(compiler_kind, insn_set, compiler_options, /*out*/ &error_msg); jobject class_loader; diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc index af60def11e..6b5387ae19 100644 --- a/compiler/oat_writer.cc +++ b/compiler/oat_writer.cc @@ -1675,7 +1675,7 @@ bool OatWriter::VisitDexMethods(DexMethodVisitor* visitor) { if (UNLIKELY(!visitor->StartClass(dex_file, class_def_index))) { return false; } - if (compiler_driver_->GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) { const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); const uint8_t* class_data = dex_file->GetClassData(class_def); if (class_data != nullptr) { // ie not an empty class, such as a marker interface @@ -1757,7 +1757,7 @@ size_t OatWriter::InitOatClasses(size_t offset) { } size_t OatWriter::InitOatMaps(size_t offset) { - if (!compiler_driver_->GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) { return offset; } { @@ -1813,7 +1813,7 @@ size_t OatWriter::InitOatCode(size_t offset) { } size_t OatWriter::InitOatCodeDexFiles(size_t offset) { - if (!compiler_driver_->GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) { return offset; } InitCodeMethodVisitor code_visitor(this, offset, vdex_quickening_info_offset_); @@ -1982,7 +1982,7 @@ bool OatWriter::WriteQuickeningInfo(OutputStream* vdex_out) { return false; } - if (compiler_driver_->GetCompilerOptions().IsAnyMethodCompilationEnabled()) { + if (compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) { WriteQuickeningInfoMethodVisitor visitor(this, vdex_out, start_offset); if (!VisitDexMethods(&visitor)) { PLOG(ERROR) << "Failed to write the vdex quickening info. File: " << vdex_out->GetLocation(); @@ -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/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc index 34b52a87b5..12340b416d 100644 --- a/compiler/optimizing/graph_checker.cc +++ b/compiler/optimizing/graph_checker.cc @@ -497,8 +497,7 @@ void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) { "has a null pointer as last input.", invoke->DebugName(), invoke->GetId())); - } - if (!last_input->IsClinitCheck() && !last_input->IsLoadClass()) { + } else if (!last_input->IsClinitCheck() && !last_input->IsLoadClass()) { AddError(StringPrintf("Static invoke %s:%d marked as having an explicit clinit check " "has a last instruction (%s:%d) which is neither a clinit check " "nor a load class instruction.", diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 5090c1192a..4cba36aef6 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -268,20 +268,17 @@ NO_RETURN static void Usage(const char* fmt, ...) { UsageError(" Default: Optimizing"); UsageError(""); UsageError(" --compiler-filter=" - "(verify-none" - "|verify-at-runtime" - "|verify-profile" - "|interpret-only" - "|time" + "(assume-verified" + "|extract" + "|verify" + "|quicken" "|space-profile" "|space" - "|balanced" "|speed-profile" "|speed" "|everything-profile" "|everything):"); UsageError(" select compiler filter."); - UsageError(" verify-profile requires a --profile(-fd) to also be passed in."); UsageError(" Example: --compiler-filter=everything"); UsageError(" Default: speed"); UsageError(""); @@ -721,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"); } @@ -1125,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=")) { @@ -1260,6 +1263,7 @@ class Dex2Oat FINAL { } // OAT and VDEX file handling + bool eagerly_unquicken_vdex = DoDexLayoutOptimizations(); if (oat_fd_ == -1) { DCHECK(!oat_filenames_.empty()); @@ -1281,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)); @@ -1328,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. @@ -1570,14 +1578,14 @@ class Dex2Oat FINAL { // If we need to downgrade the compiler-filter for size reasons, do that check now. if (!IsBootImage() && IsVeryLarge(dex_files_)) { - if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kVerifyAtRuntime, + if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kExtract, compiler_options_->GetCompilerFilter())) { - LOG(INFO) << "Very large app, downgrading to verify-at-runtime."; + LOG(INFO) << "Very large app, downgrading to extract."; // Note: this change won't be reflected in the key-value store, as that had to be // finalized before loading the dex files. This setup is currently required // to get the size from the DexFile objects. // TODO: refactor. b/29790079 - compiler_options_->SetCompilerFilter(CompilerFilter::kVerifyAtRuntime); + compiler_options_->SetCompilerFilter(CompilerFilter::kExtract); } } @@ -2085,17 +2093,13 @@ class Dex2Oat FINAL { } bool DoProfileGuidedOptimizations() const { - return UseProfile() && compiler_options_->GetCompilerFilter() != CompilerFilter::kVerifyProfile; + return UseProfile(); } bool DoDexLayoutOptimizations() const { return DoProfileGuidedOptimizations(); } - bool HasInputVdexFile() const { - return input_vdex_file_ != nullptr || input_vdex_fd_ != -1 || !input_vdex_.empty(); - } - bool LoadProfile() { DCHECK(UseProfile()); @@ -2151,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()); @@ -2693,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_; @@ -2899,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 8c14b50094..a267766456 100644 --- a/dex2oat/dex2oat_test.cc +++ b/dex2oat/dex2oat_test.cc @@ -161,7 +161,7 @@ class Dex2oatTest : public Dex2oatEnvironmentTest { runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv); if (!runtime->IsVerificationEnabled()) { - argv.push_back("--compiler-filter=verify-none"); + argv.push_back("--compiler-filter=assume-verified"); } if (runtime->MustRelocateIfPossible()) { @@ -514,7 +514,7 @@ class Dex2oatVeryLargeTest : public Dex2oatTest { } // If the input filter was "below," it should have been used. - if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kVerifyAtRuntime, filter)) { + if (!CompilerFilter::IsAsGoodAs(CompilerFilter::kExtract, filter)) { EXPECT_EQ(odex_file->GetCompilerFilter(), filter); } } else { @@ -536,11 +536,11 @@ class Dex2oatVeryLargeTest : public Dex2oatTest { void CheckHostResult(bool expect_large) { if (!kIsTargetBuild) { if (expect_large) { - EXPECT_NE(output_.find("Very large app, downgrading to verify-at-runtime."), + EXPECT_NE(output_.find("Very large app, downgrading to extract."), std::string::npos) << output_; } else { - EXPECT_EQ(output_.find("Very large app, downgrading to verify-at-runtime."), + EXPECT_EQ(output_.find("Very large app, downgrading to extract."), std::string::npos) << output_; } @@ -567,21 +567,21 @@ class Dex2oatVeryLargeTest : public Dex2oatTest { }; TEST_F(Dex2oatVeryLargeTest, DontUseVeryLarge) { - RunTest(CompilerFilter::kVerifyNone, false); - RunTest(CompilerFilter::kVerifyAtRuntime, false); - RunTest(CompilerFilter::kInterpretOnly, false); + RunTest(CompilerFilter::kAssumeVerified, false); + RunTest(CompilerFilter::kExtract, false); + RunTest(CompilerFilter::kQuicken, false); RunTest(CompilerFilter::kSpeed, false); - RunTest(CompilerFilter::kVerifyNone, false, { "--very-large-app-threshold=1000000" }); - RunTest(CompilerFilter::kVerifyAtRuntime, false, { "--very-large-app-threshold=1000000" }); - RunTest(CompilerFilter::kInterpretOnly, false, { "--very-large-app-threshold=1000000" }); + RunTest(CompilerFilter::kAssumeVerified, false, { "--very-large-app-threshold=1000000" }); + RunTest(CompilerFilter::kExtract, false, { "--very-large-app-threshold=1000000" }); + RunTest(CompilerFilter::kQuicken, false, { "--very-large-app-threshold=1000000" }); RunTest(CompilerFilter::kSpeed, false, { "--very-large-app-threshold=1000000" }); } TEST_F(Dex2oatVeryLargeTest, UseVeryLarge) { - RunTest(CompilerFilter::kVerifyNone, false, { "--very-large-app-threshold=100" }); - RunTest(CompilerFilter::kVerifyAtRuntime, false, { "--very-large-app-threshold=100" }); - RunTest(CompilerFilter::kInterpretOnly, true, { "--very-large-app-threshold=100" }); + RunTest(CompilerFilter::kAssumeVerified, false, { "--very-large-app-threshold=100" }); + RunTest(CompilerFilter::kExtract, false, { "--very-large-app-threshold=100" }); + RunTest(CompilerFilter::kQuicken, true, { "--very-large-app-threshold=100" }); RunTest(CompilerFilter::kSpeed, true, { "--very-large-app-threshold=100" }); } @@ -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/dexoptanalyzer/dexoptanalyzer_test.cc b/dexoptanalyzer/dexoptanalyzer_test.cc index 57d3f1f68b..1703ff4cbc 100644 --- a/dexoptanalyzer/dexoptanalyzer_test.cc +++ b/dexoptanalyzer/dexoptanalyzer_test.cc @@ -89,8 +89,8 @@ TEST_F(DexoptAnalyzerTest, DexNoOat) { Copy(GetDexSrc1(), dex_location); Verify(dex_location, CompilerFilter::kSpeed); - Verify(dex_location, CompilerFilter::kVerifyAtRuntime); - Verify(dex_location, CompilerFilter::kInterpretOnly); + Verify(dex_location, CompilerFilter::kExtract); + Verify(dex_location, CompilerFilter::kQuicken); Verify(dex_location, CompilerFilter::kSpeedProfile); } @@ -101,8 +101,8 @@ TEST_F(DexoptAnalyzerTest, OatUpToDate) { GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); Verify(dex_location, CompilerFilter::kSpeed); - Verify(dex_location, CompilerFilter::kInterpretOnly); - Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kQuicken); + Verify(dex_location, CompilerFilter::kExtract); Verify(dex_location, CompilerFilter::kEverything); } @@ -113,9 +113,9 @@ TEST_F(DexoptAnalyzerTest, ProfileOatUpToDate) { GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeedProfile); Verify(dex_location, CompilerFilter::kSpeedProfile, false); - Verify(dex_location, CompilerFilter::kInterpretOnly, false); + Verify(dex_location, CompilerFilter::kQuicken, false); Verify(dex_location, CompilerFilter::kSpeedProfile, true); - Verify(dex_location, CompilerFilter::kInterpretOnly, true); + Verify(dex_location, CompilerFilter::kQuicken, true); } // Case: We have a MultiDEX file and up-to-date OAT file for it. @@ -154,7 +154,7 @@ TEST_F(DexoptAnalyzerTest, OatDexOutOfDate) { GenerateOatForTest(dex_location.c_str(), CompilerFilter::kSpeed); Copy(GetDexSrc2(), dex_location); - Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kExtract); Verify(dex_location, CompilerFilter::kSpeed); } @@ -170,8 +170,8 @@ TEST_F(DexoptAnalyzerTest, OatImageOutOfDate) { /*pic*/false, /*with_alternate_image*/true); - Verify(dex_location, CompilerFilter::kVerifyAtRuntime); - Verify(dex_location, CompilerFilter::kInterpretOnly); + Verify(dex_location, CompilerFilter::kExtract); + Verify(dex_location, CompilerFilter::kQuicken); Verify(dex_location, CompilerFilter::kSpeed); } @@ -184,13 +184,13 @@ TEST_F(DexoptAnalyzerTest, OatVerifyAtRuntimeImageOutOfDate) { Copy(GetDexSrc1(), dex_location); GenerateOatForTest(dex_location.c_str(), - CompilerFilter::kVerifyAtRuntime, + CompilerFilter::kExtract, /*relocate*/true, /*pic*/false, /*with_alternate_image*/true); - Verify(dex_location, CompilerFilter::kVerifyAtRuntime); - Verify(dex_location, CompilerFilter::kInterpretOnly); + Verify(dex_location, CompilerFilter::kExtract); + Verify(dex_location, CompilerFilter::kQuicken); } // Case: We have a DEX file and an ODEX file, but no OAT file. @@ -201,7 +201,7 @@ TEST_F(DexoptAnalyzerTest, DexOdexNoOat) { Copy(GetDexSrc1(), dex_location); GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kSpeed); - Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kExtract); Verify(dex_location, CompilerFilter::kSpeed); } @@ -235,7 +235,7 @@ TEST_F(DexoptAnalyzerTest, StrippedDexOdexOat) { // Strip the dex file. Copy(GetStrippedDexSrc1(), dex_location); - Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kExtract); Verify(dex_location, CompilerFilter::kSpeed); Verify(dex_location, CompilerFilter::kEverything); } @@ -248,8 +248,8 @@ TEST_F(DexoptAnalyzerTest, ResourceOnlyDex) { Copy(GetStrippedDexSrc1(), dex_location); Verify(dex_location, CompilerFilter::kSpeed); - Verify(dex_location, CompilerFilter::kVerifyAtRuntime); - Verify(dex_location, CompilerFilter::kInterpretOnly); + Verify(dex_location, CompilerFilter::kExtract); + Verify(dex_location, CompilerFilter::kQuicken); } // Case: We have a DEX file, an ODEX file and an OAT file, where the ODEX and @@ -287,9 +287,9 @@ TEST_F(DexoptAnalyzerTest, DexVerifyAtRuntimeOdexNoOat) { std::string odex_location = GetOdexDir() + "/DexVerifyAtRuntimeOdexNoOat.odex"; Copy(GetDexSrc1(), dex_location); - GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerifyAtRuntime); + GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract); - Verify(dex_location, CompilerFilter::kVerifyAtRuntime); + Verify(dex_location, CompilerFilter::kExtract); Verify(dex_location, CompilerFilter::kSpeed); } 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/arch/context-inl.h b/runtime/arch/context-inl.h new file mode 100644 index 0000000000..ddcbbb18e5 --- /dev/null +++ b/runtime/arch/context-inl.h @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// This file is special-purpose for cases where you want a stack context. Most users should use +// Context::Create(). + +#include "context.h" + +#ifndef ART_RUNTIME_ARCH_CONTEXT_INL_H_ +#define ART_RUNTIME_ARCH_CONTEXT_INL_H_ + +#if defined(__arm__) +#include "arm/context_arm.h" +#define RUNTIME_CONTEXT_TYPE arm::ArmContext +#elif defined(__aarch64__) +#include "arm64/context_arm64.h" +#define RUNTIME_CONTEXT_TYPE arm64::Arm64Context +#elif defined(__mips__) && !defined(__LP64__) +#include "mips/context_mips.h" +#define RUNTIME_CONTEXT_TYPE mips::MipsContext +#elif defined(__mips__) && defined(__LP64__) +#include "mips64/context_mips64.h" +#define RUNTIME_CONTEXT_TYPE mips64::Mips64Context +#elif defined(__i386__) +#include "x86/context_x86.h" +#define RUNTIME_CONTEXT_TYPE x86::X86Context +#elif defined(__x86_64__) +#include "x86_64/context_x86_64.h" +#define RUNTIME_CONTEXT_TYPE x86_64::X86_64Context +#else +#error unimplemented +#endif + +namespace art { + +using RuntimeContextType = RUNTIME_CONTEXT_TYPE; + +} // namespace art + +#undef RUNTIME_CONTEXT_TYPE + +#endif // ART_RUNTIME_ARCH_CONTEXT_INL_H_ diff --git a/runtime/arch/context.cc b/runtime/arch/context.cc index bf40a3f8ce..82d8b6ca00 100644 --- a/runtime/arch/context.cc +++ b/runtime/arch/context.cc @@ -14,43 +14,12 @@ * limitations under the License. */ -#include "context.h" - -#if defined(__arm__) -#include "arm/context_arm.h" -#elif defined(__aarch64__) -#include "arm64/context_arm64.h" -#elif defined(__mips__) && !defined(__LP64__) -#include "mips/context_mips.h" -#elif defined(__mips__) && defined(__LP64__) -#include "mips64/context_mips64.h" -#elif defined(__i386__) -#include "x86/context_x86.h" -#elif defined(__x86_64__) -#include "x86_64/context_x86_64.h" -#else -#include "base/logging.h" -#endif +#include "context-inl.h" namespace art { Context* Context::Create() { -#if defined(__arm__) - return new arm::ArmContext(); -#elif defined(__aarch64__) - return new arm64::Arm64Context(); -#elif defined(__mips__) && !defined(__LP64__) - return new mips::MipsContext(); -#elif defined(__mips__) && defined(__LP64__) - return new mips64::Mips64Context(); -#elif defined(__i386__) - return new x86::X86Context(); -#elif defined(__x86_64__) - return new x86_64::X86_64Context(); -#else - UNIMPLEMENTED(FATAL); - return nullptr; -#endif + return new RuntimeContextType; } } // namespace art 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/runtime/compiler_filter.cc b/runtime/compiler_filter.cc index dc55ab8931..dbfcdfe874 100644 --- a/runtime/compiler_filter.cc +++ b/runtime/compiler_filter.cc @@ -20,17 +20,15 @@ namespace art { -bool CompilerFilter::IsBytecodeCompilationEnabled(Filter filter) { +bool CompilerFilter::IsAotCompilationEnabled(Filter filter) { switch (filter) { - case CompilerFilter::kVerifyNone: - case CompilerFilter::kVerifyAtRuntime: - case CompilerFilter::kVerifyProfile: - case CompilerFilter::kInterpretOnly: return false; + case CompilerFilter::kAssumeVerified: + case CompilerFilter::kExtract: + case CompilerFilter::kVerify: + case CompilerFilter::kQuicken: return false; case CompilerFilter::kSpaceProfile: case CompilerFilter::kSpace: - case CompilerFilter::kBalanced: - case CompilerFilter::kTime: case CompilerFilter::kSpeedProfile: case CompilerFilter::kSpeed: case CompilerFilter::kEverythingProfile: @@ -41,15 +39,13 @@ bool CompilerFilter::IsBytecodeCompilationEnabled(Filter filter) { bool CompilerFilter::IsJniCompilationEnabled(Filter filter) { switch (filter) { - case CompilerFilter::kVerifyNone: - case CompilerFilter::kVerifyAtRuntime: return false; + case CompilerFilter::kAssumeVerified: + case CompilerFilter::kExtract: + case CompilerFilter::kVerify: return false; - case CompilerFilter::kVerifyProfile: - case CompilerFilter::kInterpretOnly: + case CompilerFilter::kQuicken: case CompilerFilter::kSpaceProfile: case CompilerFilter::kSpace: - case CompilerFilter::kBalanced: - case CompilerFilter::kTime: case CompilerFilter::kSpeedProfile: case CompilerFilter::kSpeed: case CompilerFilter::kEverythingProfile: @@ -58,17 +54,15 @@ bool CompilerFilter::IsJniCompilationEnabled(Filter filter) { UNREACHABLE(); } -bool CompilerFilter::IsAnyMethodCompilationEnabled(Filter filter) { +bool CompilerFilter::IsQuickeningCompilationEnabled(Filter filter) { switch (filter) { - case CompilerFilter::kVerifyNone: - case CompilerFilter::kVerifyAtRuntime: - case CompilerFilter::kVerifyProfile: return false; + case CompilerFilter::kAssumeVerified: + case CompilerFilter::kExtract: + case CompilerFilter::kVerify: return false; - case CompilerFilter::kInterpretOnly: + case CompilerFilter::kQuicken: case CompilerFilter::kSpaceProfile: case CompilerFilter::kSpace: - case CompilerFilter::kBalanced: - case CompilerFilter::kTime: case CompilerFilter::kSpeedProfile: case CompilerFilter::kSpeed: case CompilerFilter::kEverythingProfile: @@ -77,17 +71,21 @@ bool CompilerFilter::IsAnyMethodCompilationEnabled(Filter filter) { UNREACHABLE(); } +bool CompilerFilter::IsAnyCompilationEnabled(Filter filter) { + return IsJniCompilationEnabled(filter) || + IsQuickeningCompilationEnabled(filter) || + IsAotCompilationEnabled(filter); +} + bool CompilerFilter::IsVerificationEnabled(Filter filter) { switch (filter) { - case CompilerFilter::kVerifyNone: - case CompilerFilter::kVerifyAtRuntime: return false; + case CompilerFilter::kAssumeVerified: + case CompilerFilter::kExtract: return false; - case CompilerFilter::kVerifyProfile: - case CompilerFilter::kInterpretOnly: + case CompilerFilter::kVerify: + case CompilerFilter::kQuicken: case CompilerFilter::kSpaceProfile: case CompilerFilter::kSpace: - case CompilerFilter::kBalanced: - case CompilerFilter::kTime: case CompilerFilter::kSpeedProfile: case CompilerFilter::kSpeed: case CompilerFilter::kEverythingProfile: @@ -104,19 +102,14 @@ bool CompilerFilter::DependsOnImageChecksum(Filter filter) { bool CompilerFilter::DependsOnProfile(Filter filter) { switch (filter) { - case CompilerFilter::kVerifyNone: - case CompilerFilter::kVerifyAtRuntime: - case CompilerFilter::kInterpretOnly: + case CompilerFilter::kAssumeVerified: + case CompilerFilter::kExtract: + case CompilerFilter::kVerify: + case CompilerFilter::kQuicken: case CompilerFilter::kSpace: - case CompilerFilter::kBalanced: - case CompilerFilter::kTime: case CompilerFilter::kSpeed: case CompilerFilter::kEverything: return false; - // verify-profile doesn't look at profiles anymore. - // TODO(ngeoffray): this will be cleaned up with b/34715556. - case CompilerFilter::kVerifyProfile: return false; - case CompilerFilter::kSpaceProfile: case CompilerFilter::kSpeedProfile: case CompilerFilter::kEverythingProfile: return true; @@ -126,21 +119,15 @@ bool CompilerFilter::DependsOnProfile(Filter filter) { CompilerFilter::Filter CompilerFilter::GetNonProfileDependentFilterFrom(Filter filter) { switch (filter) { - case CompilerFilter::kVerifyNone: - case CompilerFilter::kVerifyAtRuntime: - case CompilerFilter::kInterpretOnly: + case CompilerFilter::kAssumeVerified: + case CompilerFilter::kExtract: + case CompilerFilter::kVerify: + case CompilerFilter::kQuicken: case CompilerFilter::kSpace: - case CompilerFilter::kBalanced: - case CompilerFilter::kTime: case CompilerFilter::kSpeed: case CompilerFilter::kEverything: return filter; - case CompilerFilter::kVerifyProfile: - // verify-profile doesn't look at profiles anymore. - // TODO(ngeoffray): this will be cleaned up with b/34715556. - return filter; - case CompilerFilter::kSpaceProfile: return CompilerFilter::kSpace; @@ -160,14 +147,12 @@ bool CompilerFilter::IsAsGoodAs(Filter current, Filter target) { std::string CompilerFilter::NameOfFilter(Filter filter) { switch (filter) { - case CompilerFilter::kVerifyNone: return "verify-none"; - case CompilerFilter::kVerifyAtRuntime: return "verify-at-runtime"; - case CompilerFilter::kVerifyProfile: return "verify-profile"; - case CompilerFilter::kInterpretOnly: return "interpret-only"; + case CompilerFilter::kAssumeVerified: return "assume-verified"; + case CompilerFilter::kExtract: return "extract"; + case CompilerFilter::kVerify: return "verify"; + case CompilerFilter::kQuicken: return "quicken"; case CompilerFilter::kSpaceProfile: return "space-profile"; case CompilerFilter::kSpace: return "space"; - case CompilerFilter::kBalanced: return "balanced"; - case CompilerFilter::kTime: return "time"; case CompilerFilter::kSpeedProfile: return "speed-profile"; case CompilerFilter::kSpeed: return "speed"; case CompilerFilter::kEverythingProfile: return "everything-profile"; @@ -180,19 +165,41 @@ bool CompilerFilter::ParseCompilerFilter(const char* option, Filter* filter) { CHECK(filter != nullptr); if (strcmp(option, "verify-none") == 0) { - *filter = kVerifyNone; + LOG(WARNING) << "'verify-none' is an obsolete compiler filter name that will be " + << "removed in future releases, please use 'assume-verified' instead."; + *filter = kAssumeVerified; } else if (strcmp(option, "interpret-only") == 0) { - *filter = kInterpretOnly; + LOG(WARNING) << "'interpret-only' is an obsolete compiler filter name that will be " + << "removed in future releases, please use 'quicken' instead."; + *filter = kQuicken; } else if (strcmp(option, "verify-profile") == 0) { - *filter = kVerifyProfile; + LOG(WARNING) << "'verify-profile' is an obsolete compiler filter name that will be " + << "removed in future releases, please use 'verify' instead."; + *filter = kVerify; } else if (strcmp(option, "verify-at-runtime") == 0) { - *filter = kVerifyAtRuntime; + LOG(WARNING) << "'verify-at-runtime' is an obsolete compiler filter name that will be " + << "removed in future releases, please use 'extract' instead."; + *filter = kExtract; + } else if (strcmp(option, "balanced") == 0) { + LOG(WARNING) << "'balanced' is an obsolete compiler filter name that will be " + << "removed in future releases, please use 'speed' instead."; + *filter = kSpeed; + } else if (strcmp(option, "time") == 0) { + LOG(WARNING) << "'time' is an obsolete compiler filter name that will be " + << "removed in future releases, please use 'space' instead."; + *filter = kSpace; + } else if (strcmp(option, "assume-verified") == 0) { + *filter = kAssumeVerified; + } else if (strcmp(option, "extract") == 0) { + *filter = kExtract; + } else if (strcmp(option, "verify") == 0) { + *filter = kVerify; + } else if (strcmp(option, "quicken") == 0) { + *filter = kQuicken; } else if (strcmp(option, "space") == 0) { *filter = kSpace; } else if (strcmp(option, "space-profile") == 0) { *filter = kSpaceProfile; - } else if (strcmp(option, "balanced") == 0) { - *filter = kBalanced; } else if (strcmp(option, "speed") == 0) { *filter = kSpeed; } else if (strcmp(option, "speed-profile") == 0) { @@ -201,8 +208,6 @@ bool CompilerFilter::ParseCompilerFilter(const char* option, Filter* filter) { *filter = kEverything; } else if (strcmp(option, "everything-profile") == 0) { *filter = kEverythingProfile; - } else if (strcmp(option, "time") == 0) { - *filter = kTime; } else { return false; } diff --git a/runtime/compiler_filter.h b/runtime/compiler_filter.h index 796f4aad0c..9cb54b14b6 100644 --- a/runtime/compiler_filter.h +++ b/runtime/compiler_filter.h @@ -30,14 +30,12 @@ class CompilerFilter FINAL { // Note: Order here matters. Later filter choices are considered "as good // as" earlier filter choices. enum Filter { - kVerifyNone, // Skip verification but mark all classes as verified anyway. - kVerifyAtRuntime, // Delay verication to runtime, do not compile anything. - kVerifyProfile, // Verify only the classes in the profile, compile only JNI stubs. - kInterpretOnly, // Verify everything, compile only JNI stubs. - kTime, // Compile methods, but minimize compilation time. + kAssumeVerified, // Skip verification but mark all classes as verified anyway. + kExtract, // Delay verication to runtime, do not compile anything. + kVerify, // Only verify classes. + kQuicken, // Verify, quicken, and compile JNI stubs. kSpaceProfile, // Maximize space savings based on profile. kSpace, // Maximize space savings. - kBalanced, // Good performance return on compilation investment. kSpeedProfile, // Maximize runtime performance based on profile. kSpeed, // Maximize runtime performance. kEverythingProfile, // Compile everything capable of being compiled based on profile. @@ -48,17 +46,21 @@ class CompilerFilter FINAL { // Returns true if an oat file with this compiler filter contains // compiled executable code for bytecode. - static bool IsBytecodeCompilationEnabled(Filter filter); + static bool IsAotCompilationEnabled(Filter filter); // Returns true if an oat file with this compiler filter contains // compiled executable code for bytecode, JNI methods, or quickened dex // bytecode. - static bool IsAnyMethodCompilationEnabled(Filter filter); + static bool IsAnyCompilationEnabled(Filter filter); // Returns true if an oat file with this compiler filter contains // compiled executable code for JNI methods. static bool IsJniCompilationEnabled(Filter filter); + // Returns true if an oat file with this compiler filter contains + // quickened dex bytecode. + static bool IsQuickeningCompilationEnabled(Filter filter); + // Returns true if this compiler filter requires running verification. static bool IsVerificationEnabled(Filter filter); diff --git a/runtime/compiler_filter_test.cc b/runtime/compiler_filter_test.cc index c603be6e52..a59165f958 100644 --- a/runtime/compiler_filter_test.cc +++ b/runtime/compiler_filter_test.cc @@ -33,14 +33,12 @@ static void TestCompilerFilterName(CompilerFilter::Filter filter, std::string na TEST(CompilerFilterTest, ParseCompilerFilter) { CompilerFilter::Filter filter; - TestCompilerFilterName(CompilerFilter::kVerifyNone, "verify-none"); - TestCompilerFilterName(CompilerFilter::kVerifyAtRuntime, "verify-at-runtime"); - TestCompilerFilterName(CompilerFilter::kVerifyProfile, "verify-profile"); - TestCompilerFilterName(CompilerFilter::kInterpretOnly, "interpret-only"); - TestCompilerFilterName(CompilerFilter::kTime, "time"); + TestCompilerFilterName(CompilerFilter::kAssumeVerified, "assume-verified"); + TestCompilerFilterName(CompilerFilter::kExtract, "extract"); + TestCompilerFilterName(CompilerFilter::kVerify, "verify"); + TestCompilerFilterName(CompilerFilter::kQuicken, "quicken"); TestCompilerFilterName(CompilerFilter::kSpaceProfile, "space-profile"); TestCompilerFilterName(CompilerFilter::kSpace, "space"); - TestCompilerFilterName(CompilerFilter::kBalanced, "balanced"); TestCompilerFilterName(CompilerFilter::kSpeedProfile, "speed-profile"); TestCompilerFilterName(CompilerFilter::kSpeed, "speed"); TestCompilerFilterName(CompilerFilter::kEverythingProfile, "everything-profile"); diff --git a/runtime/debugger.cc b/runtime/debugger.cc index 63794bff6f..d0b50fe820 100644 --- a/runtime/debugger.cc +++ b/runtime/debugger.cc @@ -1092,6 +1092,23 @@ JDWP::JdwpError Dbg::GetSignature(JDWP::RefTypeId class_id, std::string* signatu return JDWP::ERR_NONE; } +JDWP::JdwpError Dbg::GetSourceDebugExtension(JDWP::RefTypeId class_id, + std::string* extension_data) { + JDWP::JdwpError error; + mirror::Class* c = DecodeClass(class_id, &error); + if (c == nullptr) { + return error; + } + StackHandleScope<1> hs(Thread::Current()); + Handle<mirror::Class> klass(hs.NewHandle(c)); + const char* data = annotations::GetSourceDebugExtension(klass); + if (data == nullptr) { + return JDWP::ERR_ABSENT_INFORMATION; + } + *extension_data = data; + return JDWP::ERR_NONE; +} + JDWP::JdwpError Dbg::GetSourceFile(JDWP::RefTypeId class_id, std::string* result) { JDWP::JdwpError error; mirror::Class* c = DecodeClass(class_id, &error); diff --git a/runtime/debugger.h b/runtime/debugger.h index 27124e19fb..4f3ff40e86 100644 --- a/runtime/debugger.h +++ b/runtime/debugger.h @@ -288,6 +288,9 @@ class Dbg { REQUIRES_SHARED(Locks::mutator_lock_); static JDWP::JdwpError GetSignature(JDWP::RefTypeId ref_type_id, std::string* signature) REQUIRES_SHARED(Locks::mutator_lock_); + static JDWP::JdwpError GetSourceDebugExtension(JDWP::RefTypeId ref_type_id, + std::string* extension_data) + REQUIRES_SHARED(Locks::mutator_lock_); static JDWP::JdwpError GetSourceFile(JDWP::RefTypeId ref_type_id, std::string* source_file) REQUIRES_SHARED(Locks::mutator_lock_); static JDWP::JdwpError GetObjectTag(JDWP::ObjectId object_id, uint8_t* tag) diff --git a/runtime/dex_file_annotations.cc b/runtime/dex_file_annotations.cc index 6b9654dc49..7d56bca6ce 100644 --- a/runtime/dex_file_annotations.cc +++ b/runtime/dex_file_annotations.cc @@ -1420,6 +1420,40 @@ mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirro return GetSignatureValue(data, annotation_set); } +const char* GetSourceDebugExtension(Handle<mirror::Class> klass) { + ClassData data(klass); + const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); + if (annotation_set == nullptr) { + return nullptr; + } + const DexFile::AnnotationItem* annotation_item = SearchAnnotationSet( + data.GetDexFile(), + annotation_set, + "Ldalvik/annotation/SourceDebugExtension;", + DexFile::kDexVisibilitySystem); + if (annotation_item == nullptr) { + return nullptr; + } + const uint8_t* annotation = + SearchEncodedAnnotation(data.GetDexFile(), annotation_item->annotation_, "value"); + if (annotation == nullptr) { + return nullptr; + } + DexFile::AnnotationValue annotation_value; + if (!ProcessAnnotationValue<false>(data, + &annotation, + &annotation_value, + ScopedNullHandle<mirror::Class>(), + DexFile::kAllRaw)) { + return nullptr; + } + if (annotation_value.type_ != DexFile::kDexAnnotationString) { + return nullptr; + } + dex::StringIndex index(static_cast<uint32_t>(annotation_value.value_.GetI())); + return data.GetDexFile().StringDataByIdx(index); +} + bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) { ClassData data(klass); const DexFile::AnnotationSetItem* annotation_set = FindAnnotationSetForClass(data); diff --git a/runtime/dex_file_annotations.h b/runtime/dex_file_annotations.h index c66c5bdb8b..651c9844eb 100644 --- a/runtime/dex_file_annotations.h +++ b/runtime/dex_file_annotations.h @@ -89,6 +89,8 @@ bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) REQUIRES_SHARED(Locks::mutator_lock_); mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass) REQUIRES_SHARED(Locks::mutator_lock_); +const char* GetSourceDebugExtension(Handle<mirror::Class> klass) + REQUIRES_SHARED(Locks::mutator_lock_); bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) REQUIRES_SHARED(Locks::mutator_lock_); 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/dexopt_test.cc b/runtime/dexopt_test.cc index db65e40da5..24b1abbad4 100644 --- a/runtime/dexopt_test.cc +++ b/runtime/dexopt_test.cc @@ -122,7 +122,7 @@ void DexoptTest::GenerateOatForTest(const std::string& dex_location, } if (!with_alternate_image) { - if (CompilerFilter::IsBytecodeCompilationEnabled(filter)) { + if (CompilerFilter::IsAotCompilationEnabled(filter)) { if (relocate) { EXPECT_EQ(reinterpret_cast<uintptr_t>(image_header->GetOatDataBegin()), oat_header.GetImageFileLocationOatDataBegin()); diff --git a/runtime/jdwp/jdwp_handler.cc b/runtime/jdwp/jdwp_handler.cc index 971d03958c..e8a9904dc6 100644 --- a/runtime/jdwp/jdwp_handler.cc +++ b/runtime/jdwp/jdwp_handler.cc @@ -335,7 +335,7 @@ static JdwpError VM_CapabilitiesNew(JdwpState*, Request* request, ExpandBuf* rep expandBufAdd1(reply, false); // canUnrestrictedlyRedefineClasses expandBufAdd1(reply, false); // canPopFrames expandBufAdd1(reply, true); // canUseInstanceFilters - expandBufAdd1(reply, false); // canGetSourceDebugExtension + expandBufAdd1(reply, true); // canGetSourceDebugExtension expandBufAdd1(reply, false); // canRequestVMDeathEvent expandBufAdd1(reply, false); // canSetDefaultStratum expandBufAdd1(reply, true); // 1.6: canGetInstanceInfo @@ -499,13 +499,18 @@ static JdwpError RT_ClassObject(JdwpState*, Request* request, ExpandBuf* pReply) /* * Returns the value of the SourceDebugExtension attribute. - * - * JDB seems interested, but DEX files don't currently support this. */ -static JdwpError RT_SourceDebugExtension(JdwpState*, Request*, ExpandBuf*) +static JdwpError RT_SourceDebugExtension(JdwpState*, Request* request, ExpandBuf* pReply) REQUIRES_SHARED(Locks::mutator_lock_) { /* referenceTypeId in, string out */ - return ERR_ABSENT_INFORMATION; + RefTypeId refTypeId = request->ReadRefTypeId(); + std::string extension_data; + JdwpError status = Dbg::GetSourceDebugExtension(refTypeId, &extension_data); + if (status != ERR_NONE) { + return status; + } + expandBufAddUtf8String(pReply, extension_data); + return ERR_NONE; } static JdwpError RT_Signature(JdwpState*, Request* request, ExpandBuf* pReply, bool with_generic) diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc index 2eaa8c71b1..0515ec6339 100644 --- a/runtime/native/dalvik_system_ZygoteHooks.cc +++ b/runtime/native/dalvik_system_ZygoteHooks.cc @@ -192,8 +192,8 @@ static void EnableDebugFeatures(uint32_t debug_flags) { const bool safe_mode = (debug_flags & DEBUG_ENABLE_SAFEMODE) != 0; if (safe_mode) { - // Ensure that any (secondary) oat files will be interpreted. - runtime->AddCompilerOption("--compiler-filter=interpret-only"); + // Only quicken oat files. + runtime->AddCompilerOption("--compiler-filter=quicken"); runtime->SetSafeMode(true); debug_flags &= ~DEBUG_ENABLE_SAFEMODE; } 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 a7be73a849..2c2b6fdcc2 100644 --- a/runtime/oat_file_assistant.cc +++ b/runtime/oat_file_assistant.cc @@ -439,7 +439,7 @@ OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& VLOG(oat) << "Image checksum test skipped for compiler filter " << current_compiler_filter; } - if (CompilerFilter::IsBytecodeCompilationEnabled(current_compiler_filter)) { + if (CompilerFilter::IsAotCompilationEnabled(current_compiler_filter)) { if (!file.IsPic()) { const ImageInfo* image_info = GetImageInfo(); if (image_info == nullptr) { @@ -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; @@ -834,7 +835,7 @@ OatFileAssistant::OatStatus OatFileAssistant::OatFileInfo::Status() { OatFileAssistant::DexOptNeeded OatFileAssistant::OatFileInfo::GetDexOptNeeded( CompilerFilter::Filter target, bool profile_changed) { - bool compilation_desired = CompilerFilter::IsBytecodeCompilationEnabled(target); + bool compilation_desired = CompilerFilter::IsAotCompilationEnabled(target); bool filter_okay = CompilerFilterIsOkay(target, profile_changed); if (filter_okay && Status() == kOatUpToDate) { diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc index 4a738ab0a3..198f8e68e0 100644 --- a/runtime/oat_file_assistant_test.cc +++ b/runtime/oat_file_assistant_test.cc @@ -53,9 +53,9 @@ TEST_F(OatFileAssistantTest, DexNoOat) { OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile)); EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, @@ -99,9 +99,9 @@ TEST_F(OatFileAssistantTest, OatUpToDate) { EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); EXPECT_EQ(OatFileAssistant::kDex2OatForFilter, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kEverything)); @@ -204,11 +204,11 @@ TEST_F(OatFileAssistantTest, ProfileOatUpToDate) { EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, false)); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly, false)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, false)); EXPECT_EQ(OatFileAssistant::kDex2OatForFilter, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeedProfile, true)); EXPECT_EQ(OatFileAssistant::kDex2OatForFilter, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly, true)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken, true)); EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); @@ -269,7 +269,7 @@ TEST_F(OatFileAssistantTest, StrippedMultiDexNonMainOutOfDate) { // Compile the odex from GetMultiDexSrc2, which has a different non-main // dex checksum. Copy(GetMultiDexSrc2(), dex_location); - GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kInterpretOnly); + GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kQuicken); // Strip the dex file. Copy(GetStrippedDexSrc1(), dex_location); @@ -332,7 +332,7 @@ TEST_F(OatFileAssistantTest, OatDexOutOfDate) { OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); EXPECT_EQ(OatFileAssistant::kDex2OatFromScratch, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); @@ -406,9 +406,9 @@ TEST_F(OatFileAssistantTest, OatImageOutOfDate) { OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); EXPECT_EQ(OatFileAssistant::kDex2OatForBootImage, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); @@ -427,16 +427,16 @@ TEST_F(OatFileAssistantTest, OatVerifyAtRuntimeImageOutOfDate) { Copy(GetDexSrc1(), dex_location); GenerateOatForTest(dex_location.c_str(), - CompilerFilter::kVerifyAtRuntime, + CompilerFilter::kExtract, /*relocate*/true, /*pic*/false, /*with_alternate_image*/true); OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); EXPECT_EQ(OatFileAssistant::kDex2OatForFilter, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); @@ -457,7 +457,7 @@ TEST_F(OatFileAssistantTest, DexOdexNoOat) { OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); EXPECT_EQ(-OatFileAssistant::kDex2OatForRelocation, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); @@ -523,7 +523,7 @@ TEST_F(OatFileAssistantTest, StrippedDexOdexOat) { OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, // Can't run dex2oat because dex file is stripped. @@ -556,9 +556,9 @@ TEST_F(OatFileAssistantTest, ResourceOnlyDex) { EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); EXPECT_FALSE(oat_file_assistant.IsInBootClassPath()); EXPECT_EQ(OatFileAssistant::kOatCannotOpen, oat_file_assistant.OdexFileStatus()); @@ -653,13 +653,13 @@ TEST_F(OatFileAssistantTest, DexVerifyAtRuntimeOdexNoOat) { // Create the dex and odex files Copy(GetDexSrc1(), dex_location); - GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kVerifyAtRuntime); + GenerateOdexForTest(dex_location, odex_location, CompilerFilter::kExtract); // Verify the status. OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kVerifyAtRuntime)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kExtract)); EXPECT_EQ(-OatFileAssistant::kDex2OatForFilter, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); @@ -688,13 +688,13 @@ TEST_F(OatFileAssistantTest, LoadOatUpToDate) { EXPECT_EQ(1u, dex_files.size()); } -// Case: We have a DEX file and up-to-date interpret-only OAT file for it. +// Case: We have a DEX file and up-to-date quicken OAT file for it. // Expect: We should still load the oat file as executable. TEST_F(OatFileAssistantTest, LoadExecInterpretOnlyOatUpToDate) { std::string dex_location = GetScratchDir() + "/LoadExecInterpretOnlyOatUpToDate.jar"; Copy(GetDexSrc1(), dex_location); - GenerateOatForTest(dex_location.c_str(), CompilerFilter::kInterpretOnly); + GenerateOatForTest(dex_location.c_str(), CompilerFilter::kQuicken); // Load the oat using an oat file assistant. OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, true); @@ -1003,11 +1003,11 @@ TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) { OatFileAssistant oat_file_assistant(dex_location.c_str(), kRuntimeISA, false); std::string error_msg; - Runtime::Current()->AddCompilerOption("--compiler-filter=interpret-only"); + Runtime::Current()->AddCompilerOption("--compiler-filter=quicken"); EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg; EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); EXPECT_EQ(OatFileAssistant::kDex2OatForFilter, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); @@ -1015,7 +1015,7 @@ TEST_F(OatFileAssistantTest, RuntimeCompilerFilterOptionUsed) { EXPECT_EQ(OatFileAssistant::kUpdateSucceeded, oat_file_assistant.MakeUpToDate(false, &error_msg)) << error_msg; EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, - oat_file_assistant.GetDexOptNeeded(CompilerFilter::kInterpretOnly)); + oat_file_assistant.GetDexOptNeeded(CompilerFilter::kQuicken)); EXPECT_EQ(OatFileAssistant::kNoDexOptNeeded, oat_file_assistant.GetDexOptNeeded(CompilerFilter::kSpeed)); 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 0125539ab0..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; @@ -2133,7 +2134,7 @@ void Runtime::SetFaultMessage(const std::string& message) { void Runtime::AddCurrentRuntimeFeaturesAsDex2OatArguments(std::vector<std::string>* argv) const { if (GetInstrumentation()->InterpretOnly()) { - argv->push_back("--compiler-filter=interpret-only"); + argv->push_back("--compiler-filter=quicken"); } // Make the dex2oat instruction set match that of the launching runtime. If we have multiple diff --git a/runtime/thread.cc b/runtime/thread.cc index 201701a510..62a616b646 100644 --- a/runtime/thread.cc +++ b/runtime/thread.cc @@ -35,6 +35,7 @@ #include "android-base/stringprintf.h" #include "arch/context.h" +#include "arch/context-inl.h" #include "art_field-inl.h" #include "art_method-inl.h" #include "base/bit_utils.h" @@ -3413,11 +3414,10 @@ void Thread::VisitRoots(RootVisitor* visitor) { verifier->VisitRoots(visitor, RootInfo(kRootNativeStack, thread_id)); } // Visit roots on this thread's stack - Context* context = GetLongJumpContext(); + RuntimeContextType context; RootCallbackVisitor visitor_to_callback(visitor, thread_id); - ReferenceMapVisitor<RootCallbackVisitor, kPrecise> mapper(this, context, visitor_to_callback); + ReferenceMapVisitor<RootCallbackVisitor, kPrecise> mapper(this, &context, visitor_to_callback); mapper.template WalkStack<StackVisitor::CountTransitions::kNo>(false); - ReleaseLongJumpContext(context); for (instrumentation::InstrumentationStackFrame& frame : *GetInstrumentationStack()) { visitor->VisitRootIfNonNull(&frame.this_object_, RootInfo(kRootVMInternal, thread_id)); } 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/117-nopatchoat/nopatchoat.cc b/test/117-nopatchoat/nopatchoat.cc index 3236bde5a2..2248fc4efd 100644 --- a/test/117-nopatchoat/nopatchoat.cc +++ b/test/117-nopatchoat/nopatchoat.cc @@ -56,7 +56,7 @@ class NoPatchoatTest { const OatFile* oat_file = oat_dex_file->GetOatFile(); return !oat_file->IsPic() - && CompilerFilter::IsBytecodeCompilationEnabled(oat_file->GetCompilerFilter()); + && CompilerFilter::IsAotCompilationEnabled(oat_file->GetCompilerFilter()); } }; diff --git a/test/157-void-class/run b/test/157-void-class/run index 59e852c8cd..8c6159fc4c 100755 --- a/test/157-void-class/run +++ b/test/157-void-class/run @@ -14,9 +14,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Let the test build its own core image with --no-image and use verify-profile, +# Let the test build its own core image with --no-image and use verify, # so that the compiler does not try to initialize classes. This leaves the # java.lang.Void compile-time verified but uninitialized. ./default-run "$@" --no-image \ --runtime-option -Ximage-compiler-option \ - --runtime-option --compiler-filter=verify-profile + --runtime-option --compiler-filter=verify diff --git a/test/595-profile-saving/run b/test/595-profile-saving/run index 068ad03ce0..fce6ac15d8 100644 --- a/test/595-profile-saving/run +++ b/test/595-profile-saving/run @@ -15,13 +15,13 @@ # limitations under the License. # Use -# --compiler-filter=interpret-only to make sure that the test is not compiled AOT +# --compiler-filter=quicken to make sure that the test is not compiled AOT # and to make sure the test is not compiled when loaded (by PathClassLoader) # -Xjitsaveprofilinginfo to enable profile saving # -Xusejit:false to disable jit and only test profiles. exec ${RUN} \ - -Xcompiler-option --compiler-filter=interpret-only \ - --runtime-option '-Xcompiler-option --compiler-filter=interpret-only' \ + -Xcompiler-option --compiler-filter=quicken \ + --runtime-option '-Xcompiler-option --compiler-filter=quicken' \ --runtime-option -Xjitsaveprofilinginfo \ --runtime-option -Xusejit:false \ "${@}" diff --git a/test/628-vdex/run b/test/628-vdex/run index 4cbcea3b7e..bf0ac910c1 100644 --- a/test/628-vdex/run +++ b/test/628-vdex/run @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -exec ${RUN} -Xcompiler-option --compiler-filter=verify-profile --vdex "${@}" +exec ${RUN} -Xcompiler-option --compiler-filter=verify --vdex "${@}" diff --git a/test/634-vdex-duplicate/run b/test/634-vdex-duplicate/run index 1ccb84150b..571ccd90e1 100644 --- a/test/634-vdex-duplicate/run +++ b/test/634-vdex-duplicate/run @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -exec ${RUN} -Xcompiler-option --compiler-filter=verify-profile --vdex-filter speed --vdex "${@}" +exec ${RUN} -Xcompiler-option --compiler-filter=verify --vdex-filter speed --vdex "${@}" diff --git a/test/648-many-direct-methods/build b/test/648-many-direct-methods/build deleted file mode 100755 index 7e888e5bca..0000000000 --- a/test/648-many-direct-methods/build +++ /dev/null @@ -1,25 +0,0 @@ -#! /bin/bash -# -# Copyright 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Exit on a failure. -set -e - -mkdir -p ./src - -# Generate the Java file or fail. -./util-src/generate_java.py ./src - -./default-build "$@" diff --git a/test/648-many-direct-methods/expected.txt b/test/648-many-direct-methods/expected.txt deleted file mode 100644 index b0aad4deb5..0000000000 --- a/test/648-many-direct-methods/expected.txt +++ /dev/null @@ -1 +0,0 @@ -passed diff --git a/test/648-many-direct-methods/info.txt b/test/648-many-direct-methods/info.txt deleted file mode 100644 index a65ab8066f..0000000000 --- a/test/648-many-direct-methods/info.txt +++ /dev/null @@ -1,2 +0,0 @@ -Regression test checking that the runtime can handle a huge number of -direct methods (b/33650497). diff --git a/test/648-many-direct-methods/util-src/generate_java.py b/test/648-many-direct-methods/util-src/generate_java.py deleted file mode 100755 index 6cae868915..0000000000 --- a/test/648-many-direct-methods/util-src/generate_java.py +++ /dev/null @@ -1,137 +0,0 @@ -#! /usr/bin/python3 -# -# Copyright (C) 2017 The Android Open Source Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -""" -Generate Java test files for test 648-many-direct-methods. -""" - -import os -import sys -from pathlib import Path - -BUILD_TOP = os.getenv("ANDROID_BUILD_TOP") -if BUILD_TOP is None: - print("ANDROID_BUILD_TOP not set. Please run build/envsetup.sh", file=sys.stderr) - sys.exit(1) - -# Allow us to import utils and mixins. -sys.path.append(str(Path(BUILD_TOP)/"art"/"test"/"utils"/"python")) - -from testgen.utils import get_copyright, subtree_sizes, gensym, filter_blanks -import testgen.mixins as mixins - -class MainClass(mixins.DumpMixin, mixins.Named, mixins.JavaFileMixin): - """ - A Main.java file containing the Main class and the main function. It will run - all the test functions we have. - """ - - MAIN_CLASS_TEMPLATE = """{copyright} -public class Main {{ -{main_func} -{test_groups} - -}}""" - - MAIN_FUNCTION_TEMPLATE = """ - public static void main(String[] args) { - System.out.println("passed"); - }""" - - def __init__(self): - """ - Initialize this MainClass. We start out with no tests. - """ - self.tests = set() - - def add_test_method(self, num): - """ - Add test method number 'num' - """ - self.tests.add(TestMethod(num)) - - def get_name(self): - """ - Get the name of this class - """ - return "Main" - - def __str__(self): - """ - Print the MainClass Java code. - """ - all_tests = sorted(self.tests) - test_groups = "" - for t in all_tests: - test_groups += str(t) - main_func = self.MAIN_FUNCTION_TEMPLATE - - return self.MAIN_CLASS_TEMPLATE.format(copyright = get_copyright("java"), - main_func = main_func, - test_groups = test_groups) - -class TestMethod(mixins.Named, mixins.NameComparableMixin): - """ - A function that represents a test method. Should only be - constructed by MainClass.add_test_method. - """ - - TEST_FUNCTION_TEMPLATE = """ - public static void {fname}() {{}}""" - - def __init__(self, farg): - """ - Initialize a test method for the given argument. - """ - self.farg = farg - - def get_name(self): - """ - Get the name of this test method. - """ - return "method{:05d}".format(self.farg) - - def __str__(self): - """ - Print the Java code of this test method. - """ - return self.TEST_FUNCTION_TEMPLATE.format(fname=self.get_name()) - -# Number of generated test methods. This number has been chosen to -# make sure the number of direct methods in class Main is greater or -# equal to 2^16, and thus requires an *unsigned* 16-bit (short) -# integer to be represented (b/33650497). -NUM_TEST_METHODS = 32768 - -def create_test_file(): - """ - Creates the object representing the test file. It just needs to be dumped. - """ - mc = MainClass() - for i in range(1, NUM_TEST_METHODS + 1): - mc.add_test_method(i) - return mc - -def main(argv): - java_dir = Path(argv[1]) - if not java_dir.exists() or not java_dir.is_dir(): - print("{} is not a valid Java dir".format(java_dir), file=sys.stderr) - sys.exit(1) - mainclass = create_test_file() - mainclass.dump(java_dir) - -if __name__ == '__main__': - main(sys.argv) diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar index b34da08716..f725b89eb1 100755 --- a/test/etc/run-test-jar +++ b/test/etc/run-test-jar @@ -469,15 +469,15 @@ fi if [ "$INTERPRETER" = "y" ]; then INT_OPTS="-Xint" if [ "$VERIFY" = "y" ] ; then - INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=interpret-only" - COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=interpret-only" + INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=quicken" + COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=quicken" elif [ "$VERIFY" = "s" ]; then - INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=verify-at-runtime" - COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-at-runtime" + INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=extract" + COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=extract" DEX_VERIFY="${DEX_VERIFY} -Xverify:softfail" else # VERIFY = "n" - INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=verify-none" - COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-none" + INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=assume-verified" + COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=assume-verified" DEX_VERIFY="${DEX_VERIFY} -Xverify:none" fi fi @@ -485,11 +485,11 @@ fi if [ "$JIT" = "y" ]; then INT_OPTS="-Xusejit:true" if [ "$VERIFY" = "y" ] ; then - INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=interpret-only" - COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=interpret-only" + INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=quicken" + COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=quicken" else - INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=verify-none" - COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-none" + INT_OPTS="${INT_OPTS} -Xcompiler-option --compiler-filter=assume-verified" + COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=assume-verified" DEX_VERIFY="${DEX_VERIFY} -Xverify:none" fi fi @@ -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 8df7466cf8..f7fb3573e6 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -667,9 +667,15 @@ "bug": "b/37636792" }, { - "tests": "648-many-direct-methods", - "variant": "optimizing | speed-profile | no-image", - "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" } ] @@ -46,17 +46,17 @@ function find_libdir() { fi } -function replace_compiler_filter_with_interepret_only() { - ARGS_WITH_INTERPRET_ONLY=("$@") +function replace_compiler_filter_with_quicken() { + ARGS_WITH_QUICKEN=("$@") found="false" ((index=0)) while ((index <= $#)); do - what="${ARGS_WITH_INTERPRET_ONLY[$index]}" + what="${ARGS_WITH_QUICKEN[$index]}" case "$what" in --compiler-filter=*) - ARGS_WITH_INTERPRET_ONLY[$index]="--compiler-filter=interpret-only" + ARGS_WITH_QUICKEN[$index]="--compiler-filter=quicken" found="true" ;; esac @@ -65,7 +65,7 @@ function replace_compiler_filter_with_interepret_only() { shift done if [ "$found" != "true" ]; then - ARGS_WITH_INTERPRET_ONLY=(-Xcompiler-option --compiler-filter=interpret-only "${ARGS_WITH_INTERPRET_ONLY[@]}") + ARGS_WITH_QUICKEN=(-Xcompiler-option --compiler-filter=quicken "${ARGS_WITH_QUICKEN[@]}") fi } @@ -224,10 +224,10 @@ if [ "$JIT_PROFILE" = "yes" ]; then PROFILE_PATH="$ANDROID_DATA/primary.prof" touch $PROFILE_PATH - # Replace the compiler filter with interpret-only so that we + # Replace the compiler filter with quicken so that we # can capture the profile. - ARGS_WITH_INTERPRET_ONLY= - replace_compiler_filter_with_interepret_only "$@" + ARGS_WITH_QUICKEN= + replace_compiler_filter_with_quicken "$@" run_art -Xjitsaveprofilinginfo \ -Xps-min-methods-to-save:1 \ @@ -235,7 +235,7 @@ if [ "$JIT_PROFILE" = "yes" ]; then -Xps-min-notification-before-wake:10 \ -Xps-profile-path:$PROFILE_PATH \ -Xusejit:true \ - "${ARGS_WITH_INTERPRET_ONLY[@]}" \ + "${ARGS_WITH_QUICKEN[@]}" \ "&>" "$ANDROID_DATA/profile_gen.log" EXIT_STATUS=$? diff --git a/tools/dexfuzz/src/dexfuzz/executors/Executor.java b/tools/dexfuzz/src/dexfuzz/executors/Executor.java index 2bcf3a1a77..074672d0ff 100644 --- a/tools/dexfuzz/src/dexfuzz/executors/Executor.java +++ b/tools/dexfuzz/src/dexfuzz/executors/Executor.java @@ -117,7 +117,7 @@ public abstract class Executor { commandBuilder.append("--runtime-arg -classpath "); commandBuilder.append("--runtime-arg ").append(programName).append(" "); commandBuilder.append("--dex-file=").append(programName).append(" "); - commandBuilder.append("--compiler-filter=interpret-only --runtime-arg -Xnorelocate "); + commandBuilder.append("--compiler-filter=quicken --runtime-arg -Xnorelocate "); ExecutionResult verificationResult = device.executeCommand(commandBuilder.toString(), true, outputConsumer, errorConsumer); diff --git a/tools/run-jdwp-tests.sh b/tools/run-jdwp-tests.sh index 07c300e7a7..d48d8579be 100755 --- a/tools/run-jdwp-tests.sh +++ b/tools/run-jdwp-tests.sh @@ -132,8 +132,8 @@ if [[ "$image" != "" ]]; then vm_args="--vm-arg $image" fi if $use_jit; then - vm_args="$vm_args --vm-arg -Xcompiler-option --vm-arg --compiler-filter=interpret-only" - debuggee_args="$debuggee_args -Xcompiler-option --compiler-filter=interpret-only" + vm_args="$vm_args --vm-arg -Xcompiler-option --vm-arg --compiler-filter=quicken" + debuggee_args="$debuggee_args -Xcompiler-option --compiler-filter=quicken" fi vm_args="$vm_args --vm-arg -Xusejit:$use_jit" debuggee_args="$debuggee_args -Xusejit:$use_jit" diff --git a/tools/run-libcore-tests.sh b/tools/run-libcore-tests.sh index 729a3e5ac4..b860a6273f 100755 --- a/tools/run-libcore-tests.sh +++ b/tools/run-libcore-tests.sh @@ -127,7 +127,7 @@ vogar_args="$vogar_args --toolchain jack --language JO" # JIT settings. if $use_jit; then - vogar_args="$vogar_args --vm-arg -Xcompiler-option --vm-arg --compiler-filter=interpret-only" + vogar_args="$vogar_args --vm-arg -Xcompiler-option --vm-arg --compiler-filter=quicken" fi vogar_args="$vogar_args --vm-arg -Xusejit:$use_jit" |