From 27e0d1f3da2e0b7046dacb40794739d739e454a3 Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Wed, 26 Jul 2017 00:16:07 -0700 Subject: Pass the class loader context to dex2oat when optimizing at runtime Until now we always passed the special shared library symbol "&" when we called dex2oat at runtime without an explicit class path. This CL changes that and passes the class loader context inferred from the runtime class loaders to dex2oat. If any of the runtime class loaders is not supported we continue to pass the special library symbol. Bug: 38138251 Test: m test-art-host Change-Id: Ica43ee8a3f36dab2d9ed0e634a9f6341379c8e1c --- runtime/class_loader_context.cc | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) (limited to 'runtime/class_loader_context.cc') diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index 92d0f8d5ae..b50aec0b63 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -263,7 +263,16 @@ bool ClassLoaderContext::RemoveLocationsFromClassPaths( return removed_locations; } +std::string ClassLoaderContext::EncodeContextForDex2oat(const std::string& base_dir) const { + return EncodeContext(base_dir, /*for_dex2oat*/ true); +} + std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_dir) const { + return EncodeContext(base_dir, /*for_dex2oat*/ false); +} + +std::string ClassLoaderContext::EncodeContext(const std::string& base_dir, + bool for_dex2oat) const { CheckDexFilesOpened("EncodeContextForOatFile"); if (special_shared_library_) { return OatFile::kSpecialSharedLibrary; @@ -286,8 +295,17 @@ std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_ } out << GetClassLoaderTypeName(info.type); out << kClassLoaderOpeningMark; + std::set seen_locations; for (size_t k = 0; k < info.opened_dex_files.size(); k++) { const std::unique_ptr& dex_file = info.opened_dex_files[k]; + if (for_dex2oat) { + // dex2oat only needs the base location. It cannot accept multidex locations. + // So ensure we only add each file once. + bool new_insert = seen_locations.insert(dex_file->GetBaseLocation()).second; + if (!new_insert) { + continue; + } + } const std::string& location = dex_file->GetLocation(); if (k > 0) { out << kClasspathSeparator; @@ -298,8 +316,11 @@ std::string ClassLoaderContext::EncodeContextForOatFile(const std::string& base_ } else { out << dex_file->GetLocation().c_str(); } - out << kDexFileChecksumSeparator; - out << dex_file->GetLocationChecksum(); + // dex2oat does not need the checksums. + if (!for_dex2oat) { + out << kDexFileChecksumSeparator; + out << dex_file->GetLocationChecksum(); + } } out << kClassLoaderClosingMark; } @@ -593,7 +614,7 @@ std::unique_ptr ClassLoaderContext::CreateContextForClassLoa } } -bool ClassLoaderContext::VerifyClassLoaderContextMatch(const std::string& context_spec) { +bool ClassLoaderContext::VerifyClassLoaderContextMatch(const std::string& context_spec) const { ClassLoaderContext expected_context; if (!expected_context.Parse(context_spec, /*parse_checksums*/ true)) { LOG(WARNING) << "Invalid class loader context: " << context_spec; -- cgit v1.2.3-59-g8ed1b From 84f82b9972ec29bd05b1575ae6d638255be2f285 Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Wed, 2 Aug 2017 18:28:08 -0700 Subject: Stop using the runtime classpath in dex2oat Use only --class-loader-context to infer the classpath that should be used for compilation. The tests and benchmarks no longer rely on --runtime-arg --classpath being passed to dex2oat. Bug: 36044779 Test: m test-art-host Change-Id: Iba4cb3489f4a1a4a421071e1889d806d6c1d0738 --- dex2oat/dex2oat.cc | 18 +++++------------- runtime/class_loader_context.cc | 4 ++++ runtime/class_loader_context.h | 10 +++++++--- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'runtime/class_loader_context.cc') diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index 0826fa1488..fd22dcdcc4 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1304,7 +1304,7 @@ class Dex2Oat FINAL { } else if (option.starts_with("--class-loader-context=")) { class_loader_context_ = ClassLoaderContext::Create( option.substr(strlen("--class-loader-context=")).data()); - if (class_loader_context_== nullptr) { + if (class_loader_context_ == nullptr) { Usage("Option --class-loader-context has an incorrect format: %s", option.data()); } } else if (!compiler_options_->ParseCompilerOption(option, Usage)) { @@ -1569,20 +1569,12 @@ class Dex2Oat FINAL { } // Open dex files for class path. + if (class_loader_context_ == nullptr) { - // TODO(calin): Temporary workaround while we transition to use - // --class-loader-context instead of --runtime-arg -cp - if (runtime_->GetClassPathString().empty()) { - class_loader_context_ = std::unique_ptr( - new ClassLoaderContext()); - } else { - std::string spec = runtime_->GetClassPathString() == OatFile::kSpecialSharedLibrary - ? OatFile::kSpecialSharedLibrary - : "PCL[" + runtime_->GetClassPathString() + "]"; - class_loader_context_ = ClassLoaderContext::Create(spec); - } + // If no context was specified use the default one (which is an empty PathClassLoader). + class_loader_context_ = std::unique_ptr(ClassLoaderContext::Default()); } - CHECK(class_loader_context_ != nullptr); + DCHECK_EQ(oat_writers_.size(), 1u); // Note: Ideally we would reject context where the source dex files are also diff --git a/runtime/class_loader_context.cc b/runtime/class_loader_context.cc index b50aec0b63..e7051b35d8 100644 --- a/runtime/class_loader_context.cc +++ b/runtime/class_loader_context.cc @@ -68,6 +68,10 @@ ClassLoaderContext::~ClassLoaderContext() { } } +std::unique_ptr ClassLoaderContext::Default() { + return Create(""); +} + std::unique_ptr ClassLoaderContext::Create(const std::string& spec) { std::unique_ptr result(new ClassLoaderContext()); if (result->Parse(spec)) { diff --git a/runtime/class_loader_context.h b/runtime/class_loader_context.h index 85299d41c0..9afa880da4 100644 --- a/runtime/class_loader_context.h +++ b/runtime/class_loader_context.h @@ -34,9 +34,6 @@ class OatFile; // Utility class which holds the class loader context used during compilation/verification. class ClassLoaderContext { public: - // Creates an empty context (with no class loaders). - ClassLoaderContext(); - ~ClassLoaderContext(); // Opens requested class path files and appends them to ClassLoaderInfo::opened_dex_files. @@ -126,6 +123,10 @@ class ClassLoaderContext { static std::unique_ptr CreateContextForClassLoader(jobject class_loader, jobjectArray dex_elements); + // Returns the default class loader context to be used when none is specified. + // This will return a context with a single and empty PathClassLoader. + static std::unique_ptr Default(); + private: enum ClassLoaderType { kInvalidClassLoader = 0, @@ -151,6 +152,9 @@ class ClassLoaderContext { explicit ClassLoaderInfo(ClassLoaderType cl_type) : type(cl_type) {} }; + // Creates an empty context (with no class loaders). + ClassLoaderContext(); + // Constructs an empty context. // `owns_the_dex_files` specifies whether or not the context will own the opened dex files // present in the class loader chain. If `owns_the_dex_files` is true then OpenDexFiles cannot -- cgit v1.2.3-59-g8ed1b