Merge "Move image_classes_ to CompilerOptions."
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index c37d452..7491173 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -31,6 +31,7 @@
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
#include "driver/compiler_options.h"
+#include "jni/java_vm_ext.h"
#include "interpreter/interpreter.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
@@ -134,8 +135,7 @@
}
}
-// Get the set of image classes given to the compiler-driver in SetUp. Note: the compiler
-// driver assumes ownership of the set, so the test should properly release the set.
+// Get the set of image classes given to the compiler options in SetUp.
std::unique_ptr<HashSet<std::string>> CommonCompilerTest::GetImageClasses() {
// Empty set: by default no classes are retained in the image.
return std::make_unique<HashSet<std::string>>();
@@ -173,12 +173,13 @@
size_t number_of_threads) {
compiler_options_->boot_image_ = true;
compiler_options_->SetCompilerFilter(GetCompilerFilter());
+ compiler_options_->image_classes_.swap(*GetImageClasses());
compiler_driver_.reset(new CompilerDriver(compiler_options_.get(),
verification_results_.get(),
kind,
isa,
instruction_set_features_.get(),
- GetImageClasses(),
+ &compiler_options_->image_classes_,
number_of_threads,
/* swap_fd */ -1,
GetProfileCompilationInfo()));
@@ -235,9 +236,49 @@
void CommonCompilerTest::CompileMethod(ArtMethod* method) {
CHECK(method != nullptr);
- TimingLogger timings("CommonTest::CompileMethod", false, false);
+ TimingLogger timings("CommonCompilerTest::CompileMethod", false, false);
TimingLogger::ScopedTiming t(__FUNCTION__, &timings);
- compiler_driver_->CompileOne(Thread::Current(), method, &timings);
+ {
+ Thread* self = Thread::Current();
+ jobject class_loader = self->GetJniEnv()->GetVm()->AddGlobalRef(self, method->GetClassLoader());
+
+ DCHECK(!Runtime::Current()->IsStarted());
+ const DexFile* dex_file = method->GetDexFile();
+ uint16_t class_def_idx = method->GetClassDefIndex();
+ uint32_t method_idx = method->GetDexMethodIndex();
+ uint32_t access_flags = method->GetAccessFlags();
+ InvokeType invoke_type = method->GetInvokeType();
+ StackHandleScope<2> hs(self);
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
+ Handle<mirror::ClassLoader> h_class_loader = hs.NewHandle(
+ self->DecodeJObject(class_loader)->AsClassLoader());
+ const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
+
+ std::vector<const DexFile*> dex_files;
+ dex_files.push_back(dex_file);
+
+ // Go to native so that we don't block GC during compilation.
+ ScopedThreadSuspension sts(self, kNative);
+
+ compiler_driver_->InitializeThreadPools();
+
+ compiler_driver_->PreCompile(class_loader, dex_files, &timings);
+
+ compiler_driver_->CompileOne(self,
+ class_loader,
+ *dex_file,
+ class_def_idx,
+ method_idx,
+ access_flags,
+ invoke_type,
+ code_item,
+ dex_cache,
+ h_class_loader);
+
+ compiler_driver_->FreeThreadPools();
+
+ self->GetJniEnv()->DeleteGlobalRef(class_loader);
+ }
TimingLogger::ScopedTiming t2("MakeExecutable", &timings);
MakeExecutable(method);
}
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index bd2b107..ed4fb6f 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -67,7 +67,6 @@
#include "mirror/object-refvisitor-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/throwable.h"
-#include "nativehelper/ScopedLocalRef.h"
#include "object_lock.h"
#include "profile/profile_compilation_info.h"
#include "runtime.h"
@@ -264,7 +263,7 @@
Compiler::Kind compiler_kind,
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features,
- std::unique_ptr<HashSet<std::string>>&& image_classes,
+ HashSet<std::string>* image_classes,
size_t thread_count,
int swap_fd,
const ProfileCompilationInfo* profile_compilation_info)
@@ -293,7 +292,7 @@
compiler_->Init();
if (GetCompilerOptions().IsBootImage()) {
- CHECK(image_classes_.get() != nullptr) << "Expected image classes for boot image";
+ CHECK(image_classes_ != nullptr) << "Expected image classes for boot image";
}
compiled_method_storage_.SetDedupeEnabled(compiler_options_->DeduplicateCode());
@@ -351,12 +350,6 @@
InitializeThreadPools();
- VLOG(compiler) << "Before precompile " << GetMemoryUsageString(false);
- // Precompile:
- // 1) Load image classes
- // 2) Resolve all classes
- // 3) Attempt to verify all classes
- // 4) Attempt to initialize image classes, and trivially initialized classes
PreCompile(class_loader, dex_files, timings);
if (GetCompilerOptions().IsBootImage()) {
// We don't need to setup the intrinsics for non boot image compilation, as
@@ -673,46 +666,24 @@
quick_fn);
}
-void CompilerDriver::CompileOne(Thread* self, ArtMethod* method, TimingLogger* timings) {
- DCHECK(!Runtime::Current()->IsStarted());
- jobject jclass_loader;
- const DexFile* dex_file;
- uint16_t class_def_idx;
- uint32_t method_idx = method->GetDexMethodIndex();
- uint32_t access_flags = method->GetAccessFlags();
- InvokeType invoke_type = method->GetInvokeType();
- StackHandleScope<2> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(method->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(method->GetDeclaringClass()->GetClassLoader()));
- {
- ScopedObjectAccessUnchecked soa(self);
- ScopedLocalRef<jobject> local_class_loader(
- soa.Env(), soa.AddLocalReference<jobject>(class_loader.Get()));
- jclass_loader = soa.Env()->NewGlobalRef(local_class_loader.get());
- // Find the dex_file
- dex_file = method->GetDexFile();
- class_def_idx = method->GetClassDefIndex();
- }
- const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
-
- // Go to native so that we don't block GC during compilation.
- ScopedThreadSuspension sts(self, kNative);
-
- std::vector<const DexFile*> dex_files;
- dex_files.push_back(dex_file);
-
- InitializeThreadPools();
-
- PreCompile(jclass_loader, dex_files, timings);
-
+// Compile a single Method. (For testing only.)
+void CompilerDriver::CompileOne(Thread* self,
+ jobject class_loader,
+ const DexFile& dex_file,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ uint32_t access_flags,
+ InvokeType invoke_type,
+ const DexFile::CodeItem* code_item,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> h_class_loader) {
// Can we run DEX-to-DEX compiler on this class ?
optimizer::DexToDexCompiler::CompilationLevel dex_to_dex_compilation_level =
GetDexToDexCompilationLevel(self,
*this,
- jclass_loader,
- *dex_file,
- dex_file->GetClassDef(class_def_idx));
+ class_loader,
+ dex_file,
+ dex_file.GetClassDef(class_def_idx));
CompileMethodQuick(self,
this,
@@ -721,8 +692,8 @@
invoke_type,
class_def_idx,
method_idx,
- class_loader,
- *dex_file,
+ h_class_loader,
+ dex_file,
dex_to_dex_compilation_level,
true,
dex_cache);
@@ -737,17 +708,13 @@
invoke_type,
class_def_idx,
method_idx,
- class_loader,
- *dex_file,
+ h_class_loader,
+ dex_file,
dex_to_dex_compilation_level,
true,
dex_cache);
dex_to_dex_compiler_.ClearState();
}
-
- FreeThreadPools();
-
- self->GetJniEnv()->DeleteGlobalRef(jclass_loader);
}
void CompilerDriver::Resolve(jobject class_loader,
@@ -838,7 +805,7 @@
// primitive) classes. We may reconsider this in future if it's deemed to be beneficial.
// And we cannot use it for classes outside the boot image as we do not know the runtime
// value of their bitstring when compiling (it may not even get assigned at runtime).
- if (descriptor[0] == 'L' && driver->IsImageClass(descriptor)) {
+ if (descriptor[0] == 'L' && driver->GetCompilerOptions().IsImageClass(descriptor)) {
ObjPtr<mirror::Class> klass =
class_linker->LookupResolvedType(type_index,
dex_cache.Get(),
@@ -918,6 +885,16 @@
const std::vector<const DexFile*>& dex_files,
TimingLogger* timings) {
CheckThreadPools();
+ VLOG(compiler) << "Before precompile " << GetMemoryUsageString(false);
+
+ // Precompile:
+ // 1) Load image classes.
+ // 2) Resolve all classes.
+ // 3) For deterministic boot image, resolve strings for const-string instructions.
+ // 4) Attempt to verify all classes.
+ // 5) Attempt to initialize image classes, and trivially initialized classes.
+ // 6) Update the set of image classes.
+ // 7) For deterministic boot image, initialize bitstrings for type checking.
LoadImageClasses(timings);
VLOG(compiler) << "LoadImageClasses: " << GetMemoryUsageString(false);
@@ -988,16 +965,6 @@
}
}
-bool CompilerDriver::IsImageClass(const char* descriptor) const {
- if (image_classes_ != nullptr) {
- // If we have a set of image classes, use those.
- return image_classes_->find(StringPiece(descriptor)) != image_classes_->end();
- }
- // No set of image classes, assume we include all the classes.
- // NOTE: Currently only reachable from InitImageMethodVisitor for the app image case.
- return !GetCompilerOptions().IsBootImage();
-}
-
bool CompilerDriver::IsClassToCompile(const char* descriptor) const {
if (classes_to_compile_ == nullptr) {
return true;
@@ -1116,7 +1083,7 @@
Thread* self = Thread::Current();
ScopedObjectAccess soa(self);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- CHECK(image_classes_.get() != nullptr);
+ CHECK(image_classes_ != nullptr);
for (auto it = image_classes_->begin(), end = image_classes_->end(); it != end;) {
const std::string& descriptor(*it);
StackHandleScope<1> hs(self);
@@ -1174,7 +1141,7 @@
// We walk the roots looking for classes so that we'll pick up the
// above classes plus any classes them depend on such super
// classes, interfaces, and the required ClassLinker roots.
- RecordImageClassesVisitor visitor(image_classes_.get());
+ RecordImageClassesVisitor visitor(image_classes_);
class_linker->VisitClasses(&visitor);
CHECK(!image_classes_->empty());
@@ -1358,7 +1325,7 @@
VariableSizedHandleScope hs(Thread::Current());
std::string error_msg;
std::unique_ptr<ClinitImageUpdate> update(ClinitImageUpdate::Create(hs,
- image_classes_.get(),
+ image_classes_,
Thread::Current(),
runtime->GetClassLinker()));
@@ -1382,7 +1349,7 @@
}
std::string temp;
const char* descriptor = klass->GetDescriptor(&temp);
- return IsImageClass(descriptor);
+ return GetCompilerOptions().IsImageClass(descriptor);
}
bool CompilerDriver::CanAccessTypeWithoutChecks(ObjPtr<mirror::Class> referrer_class,
@@ -2292,7 +2259,7 @@
(is_app_image || is_boot_image) &&
is_superclass_initialized &&
!too_many_encoded_fields &&
- manager_->GetCompiler()->IsImageClass(descriptor)) {
+ manager_->GetCompiler()->GetCompilerOptions().IsImageClass(descriptor)) {
bool can_init_static_fields = false;
if (is_boot_image) {
// We need to initialize static fields, we only do this for image classes that aren't
@@ -2982,8 +2949,7 @@
const DexFile* inlined_into) const {
// We're not allowed to inline across dex files if we're the no-inline-from dex file.
if (inlined_from != inlined_into &&
- compiler_options_->GetNoInlineFromDexFile() != nullptr &&
- ContainsElement(*compiler_options_->GetNoInlineFromDexFile(), inlined_from)) {
+ ContainsElement(compiler_options_->GetNoInlineFromDexFile(), inlined_from)) {
return false;
}
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index ff70d96..36e93a8 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -99,7 +99,7 @@
Compiler::Kind compiler_kind,
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features,
- std::unique_ptr<HashSet<std::string>>&& image_classes,
+ HashSet<std::string>* image_classes,
size_t thread_count,
int swap_fd,
const ProfileCompilationInfo* profile_compilation_info);
@@ -122,9 +122,18 @@
TimingLogger* timings)
REQUIRES(!Locks::mutator_lock_);
- // Compile a single Method.
- void CompileOne(Thread* self, ArtMethod* method, TimingLogger* timings)
- REQUIRES_SHARED(Locks::mutator_lock_);
+ // Compile a single Method. (For testing only.)
+ void CompileOne(Thread* self,
+ jobject class_loader,
+ const DexFile& dex_file,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ uint32_t access_flags,
+ InvokeType invoke_type,
+ const DexFile::CodeItem* code_item,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> h_class_loader)
+ REQUIRES(!Locks::mutator_lock_);
VerificationResults* GetVerificationResults() const;
@@ -144,10 +153,6 @@
return compiler_.get();
}
- const HashSet<std::string>* GetImageClasses() const {
- return image_classes_.get();
- }
-
// Generate the trampolines that are invoked by unresolved direct methods.
std::unique_ptr<const std::vector<uint8_t>> CreateJniDlsymLookup() const;
std::unique_ptr<const std::vector<uint8_t>> CreateQuickGenericJniTrampoline() const;
@@ -308,9 +313,6 @@
return compiled_method_storage_.DedupeEnabled();
}
- // Checks if class specified by type_idx is one of the image_classes_
- bool IsImageClass(const char* descriptor) const;
-
// Checks whether the provided class should be compiled, i.e., is in classes_to_compile_.
bool IsClassToCompile(const char* descriptor) const;
@@ -491,9 +493,11 @@
// in the .oat_patches ELF section if requested in the compiler options.
Atomic<size_t> non_relative_linker_patch_count_;
- // If image_ is true, specifies the classes that will be included in the image.
- // Note if image_classes_ is null, all classes are included in the image.
- std::unique_ptr<HashSet<std::string>> image_classes_;
+ // Image classes to be updated by PreCompile().
+ // TODO: Remove this member which is a non-const pointer to the CompilerOptions' data.
+ // Pass this explicitly to the PreCompile() which should be called directly from
+ // Dex2Oat rather than implicitly by CompileAll().
+ HashSet<std::string>* image_classes_;
// Specifies the classes that will be compiled. Note that if classes_to_compile_ is null,
// all classes are eligible for compilation (duplication filters etc. will still apply).
@@ -505,8 +509,8 @@
bool had_hard_verifier_failure_;
// A thread pool that can (potentially) run tasks in parallel.
- std::unique_ptr<ThreadPool> parallel_thread_pool_;
size_t parallel_thread_count_;
+ std::unique_ptr<ThreadPool> parallel_thread_pool_;
// A thread pool that guarantees running single-threaded on the main thread.
std::unique_ptr<ThreadPool> single_thread_pool_;
@@ -534,6 +538,7 @@
// Compiler for dex to dex (quickening).
optimizer::DexToDexCompiler dex_to_dex_compiler_;
+ friend class CommonCompilerTest;
friend class CompileClassVisitor;
friend class DexToDexDecompilerTest;
friend class verifier::VerifierDepsTest;
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index 933be4f..3d37b68 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -37,7 +37,8 @@
tiny_method_threshold_(kDefaultTinyMethodThreshold),
num_dex_methods_threshold_(kDefaultNumDexMethodsThreshold),
inline_max_code_units_(kUnsetInlineMaxCodeUnits),
- no_inline_from_(nullptr),
+ no_inline_from_(),
+ image_classes_(),
boot_image_(false),
core_image_(false),
app_image_(false),
@@ -67,8 +68,8 @@
}
CompilerOptions::~CompilerOptions() {
- // The destructor looks empty but it destroys a PassManagerOptions object. We keep it here
- // because we don't want to include the PassManagerOptions definition from the header file.
+ // Everything done by member destructors.
+ // The definitions of classes forward-declared in the header have now been #included.
}
namespace {
@@ -129,4 +130,11 @@
#pragma GCC diagnostic pop
+bool CompilerOptions::IsImageClass(const char* descriptor) const {
+ // Historical note: We used to hold the set indirectly and there was a distinction between an
+ // empty set and a null, null meaning to include all classes. However, the distiction has been
+ // removed; if we don't have a profile, we treat it as an empty set of classes. b/77340429
+ return image_classes_.find(StringPiece(descriptor)) != image_classes_.end();
+}
+
} // namespace art
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index cee989b..0709faf 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -22,6 +22,7 @@
#include <vector>
#include "base/globals.h"
+#include "base/hash_set.h"
#include "base/macros.h"
#include "base/utils.h"
#include "compiler_filter.h"
@@ -230,10 +231,16 @@
return abort_on_soft_verifier_failure_;
}
- const std::vector<const DexFile*>* GetNoInlineFromDexFile() const {
+ const std::vector<const DexFile*>& GetNoInlineFromDexFile() const {
return no_inline_from_;
}
+ const HashSet<std::string>& GetImageClasses() const {
+ return image_classes_;
+ }
+
+ bool IsImageClass(const char* descriptor) const;
+
bool ParseCompilerOptions(const std::vector<std::string>& options,
bool ignore_unrecognized,
std::string* error_msg);
@@ -301,10 +308,14 @@
size_t num_dex_methods_threshold_;
size_t inline_max_code_units_;
- // Dex files from which we should not inline code.
+ // Dex files from which we should not inline code. Does not own the dex files.
// This is usually a very short list (i.e. a single dex file), so we
// prefer vector<> over a lookup-oriented container, such as set<>.
- const std::vector<const DexFile*>* no_inline_from_;
+ std::vector<const DexFile*> no_inline_from_;
+
+ // Image classes, specifies the classes that will be included in the image if creating an image.
+ // Must not be empty for real boot image, only for tests pretending to compile boot image.
+ HashSet<std::string> image_classes_;
bool boot_image_;
bool core_image_;
diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc
index 8a347df..7cda6e9 100644
--- a/compiler/optimizing/instruction_builder.cc
+++ b/compiler/optimizing/instruction_builder.cc
@@ -1879,7 +1879,7 @@
Handle<mirror::Class> klass = ResolveClass(soa, type_index);
bool needs_access_check = LoadClassNeedsAccessCheck(klass);
TypeCheckKind check_kind = HSharpening::ComputeTypeCheckKind(
- klass.Get(), code_generator_, compiler_driver_, needs_access_check);
+ klass.Get(), code_generator_, needs_access_check);
HInstruction* class_or_null = nullptr;
HIntConstant* bitstring_path_to_root = nullptr;
diff --git a/compiler/optimizing/sharpening.cc b/compiler/optimizing/sharpening.cc
index 6541043..ebac3f6 100644
--- a/compiler/optimizing/sharpening.cc
+++ b/compiler/optimizing/sharpening.cc
@@ -71,7 +71,8 @@
}
static bool BootImageAOTCanEmbedMethod(ArtMethod* method, CompilerDriver* compiler_driver) {
- DCHECK(compiler_driver->GetCompilerOptions().IsBootImage());
+ const CompilerOptions& compiler_options = compiler_driver->GetCompilerOptions();
+ DCHECK(compiler_options.IsBootImage());
if (!compiler_driver->GetSupportBootImageFixup()) {
return false;
}
@@ -79,7 +80,7 @@
ObjPtr<mirror::Class> klass = method->GetDeclaringClass();
DCHECK(klass != nullptr);
const DexFile& dex_file = klass->GetDexFile();
- return compiler_driver->IsImageClass(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
+ return compiler_options.IsImageClass(dex_file.StringByTypeIdx(klass->GetDexTypeIndex()));
}
void HSharpening::SharpenInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke,
@@ -177,14 +178,15 @@
bool is_in_boot_image = false;
HLoadClass::LoadKind desired_load_kind = HLoadClass::LoadKind::kInvalid;
Runtime* runtime = Runtime::Current();
- if (codegen->GetCompilerOptions().IsBootImage()) {
+ const CompilerOptions& compiler_options = codegen->GetCompilerOptions();
+ if (compiler_options.IsBootImage()) {
// Compiling boot image. Check if the class is a boot image class.
DCHECK(!runtime->UseJitCompilation());
if (!compiler_driver->GetSupportBootImageFixup()) {
// compiler_driver_test. Do not sharpen.
desired_load_kind = HLoadClass::LoadKind::kRuntimeCall;
} else if ((klass != nullptr) &&
- compiler_driver->IsImageClass(dex_file.StringByTypeIdx(type_index))) {
+ compiler_options.IsImageClass(dex_file.StringByTypeIdx(type_index))) {
is_in_boot_image = true;
desired_load_kind = HLoadClass::LoadKind::kBootImageLinkTimePcRelative;
} else {
@@ -241,9 +243,7 @@
return load_kind;
}
-static inline bool CanUseTypeCheckBitstring(ObjPtr<mirror::Class> klass,
- CodeGenerator* codegen,
- CompilerDriver* compiler_driver)
+static inline bool CanUseTypeCheckBitstring(ObjPtr<mirror::Class> klass, CodeGenerator* codegen)
REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(!klass->IsProxyClass());
DCHECK(!klass->IsArrayClass());
@@ -252,7 +252,7 @@
// If we're JITting, try to assign a type check bitstring (fall through).
} else if (codegen->GetCompilerOptions().IsBootImage()) {
const char* descriptor = klass->GetDexFile().StringByTypeIdx(klass->GetDexTypeIndex());
- if (!compiler_driver->IsImageClass(descriptor)) {
+ if (!codegen->GetCompilerOptions().IsImageClass(descriptor)) {
return false;
}
// If the target is a boot image class, try to assign a type check bitstring (fall through).
@@ -281,7 +281,6 @@
TypeCheckKind HSharpening::ComputeTypeCheckKind(ObjPtr<mirror::Class> klass,
CodeGenerator* codegen,
- CompilerDriver* compiler_driver,
bool needs_access_check) {
if (klass == nullptr) {
return TypeCheckKind::kUnresolvedCheck;
@@ -299,7 +298,7 @@
return TypeCheckKind::kExactCheck;
} else if (kBitstringSubtypeCheckEnabled &&
!needs_access_check &&
- CanUseTypeCheckBitstring(klass, codegen, compiler_driver)) {
+ CanUseTypeCheckBitstring(klass, codegen)) {
// TODO: We should not need the `!needs_access_check` check but getting rid of that
// requires rewriting some optimizations in instruction simplifier.
return TypeCheckKind::kBitstringCheck;
diff --git a/compiler/optimizing/sharpening.h b/compiler/optimizing/sharpening.h
index 9ccbcaf..e777328 100644
--- a/compiler/optimizing/sharpening.h
+++ b/compiler/optimizing/sharpening.h
@@ -59,7 +59,6 @@
// Used by the builder.
static TypeCheckKind ComputeTypeCheckKind(ObjPtr<mirror::Class> klass,
CodeGenerator* codegen,
- CompilerDriver* compiler_driver,
bool needs_access_check)
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index 6cd947c..779128f 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -642,7 +642,6 @@
driver_(nullptr),
opened_dex_files_maps_(),
opened_dex_files_(),
- no_inline_from_dex_files_(),
avoid_storing_invocation_(false),
swap_fd_(kInvalidFd),
app_image_fd_(kInvalidFd),
@@ -1489,22 +1488,21 @@
if (!IsImage()) {
return;
}
- // If we don't have a profile, treat it as an empty set of classes. b/77340429
- if (image_classes_ == nullptr) {
- // May be non-null when --image-classes is passed in, in that case avoid clearing the list.
- image_classes_.reset(new HashSet<std::string>());
- }
if (profile_compilation_info_ != nullptr) {
+ // TODO: The following comment looks outdated or misplaced.
// Filter out class path classes since we don't want to include these in the image.
- image_classes_.reset(
- new HashSet<std::string>(profile_compilation_info_->GetClassDescriptors(dex_files_)));
- VLOG(compiler) << "Loaded " << image_classes_->size()
+ HashSet<std::string> image_classes =
+ profile_compilation_info_->GetClassDescriptors(dex_files_);
+ VLOG(compiler) << "Loaded " << image_classes.size()
<< " image class descriptors from profile";
if (VLOG_IS_ON(compiler)) {
- for (const std::string& s : *image_classes_) {
+ for (const std::string& s : image_classes) {
LOG(INFO) << "Image class " << s;
}
}
+ // Note: If we have a profile, classes previously loaded for the --image-classes
+ // option are overwritten here.
+ compiler_options_->image_classes_.swap(image_classes);
}
}
@@ -1810,6 +1808,7 @@
class_path_files = class_loader_context_->FlattenOpenedDexFiles();
}
+ std::vector<const DexFile*> no_inline_from_dex_files;
std::vector<const std::vector<const DexFile*>*> dex_file_vectors = {
&class_linker->GetBootClassPath(),
&class_path_files,
@@ -1832,14 +1831,14 @@
if (android::base::StartsWith(dex_location, filter.c_str())) {
VLOG(compiler) << "Disabling inlining from " << dex_file->GetLocation();
- no_inline_from_dex_files_.push_back(dex_file);
+ no_inline_from_dex_files.push_back(dex_file);
break;
}
}
}
}
- if (!no_inline_from_dex_files_.empty()) {
- compiler_options_->no_inline_from_ = &no_inline_from_dex_files_;
+ if (!no_inline_from_dex_files.empty()) {
+ compiler_options_->no_inline_from_.swap(no_inline_from_dex_files);
}
}
@@ -1848,7 +1847,7 @@
compiler_kind_,
instruction_set_,
instruction_set_features_.get(),
- std::move(image_classes_),
+ &compiler_options_->image_classes_,
thread_count_,
swap_fd_,
profile_compilation_info_.get()));
@@ -2381,14 +2380,14 @@
bool PrepareImageClasses() {
// If --image-classes was specified, calculate the full list of classes to include in the image.
+ DCHECK(compiler_options_->image_classes_.empty());
if (image_classes_filename_ != nullptr) {
- image_classes_ =
+ std::unique_ptr<HashSet<std::string>> image_classes =
ReadClasses(image_classes_zip_filename_, image_classes_filename_, "image");
- if (image_classes_ == nullptr) {
+ if (image_classes == nullptr) {
return false;
}
- } else if (IsBootImage()) {
- image_classes_.reset(new HashSet<std::string>);
+ compiler_options_->image_classes_.swap(*image_classes);
}
return true;
}
@@ -2704,8 +2703,7 @@
LOG(ERROR) << "Failed to open input file " << input_filename;
return nullptr;
}
- std::unique_ptr<T> result(
- ReadCommentedInputStream<T>(*input_file, process));
+ std::unique_ptr<T> result = ReadCommentedInputStream<T>(*input_file, process);
input_file->close();
return result;
}
@@ -2851,7 +2849,6 @@
ImageHeader::StorageMode image_storage_mode_;
const char* passes_to_run_filename_;
const char* dirty_image_objects_filename_;
- std::unique_ptr<HashSet<std::string>> image_classes_;
std::unique_ptr<HashSet<std::string>> dirty_image_objects_;
std::unique_ptr<std::vector<std::string>> passes_to_run_;
bool multi_image_;
@@ -2872,9 +2869,6 @@
std::vector<std::unique_ptr<MemMap>> opened_dex_files_maps_;
std::vector<std::unique_ptr<const DexFile>> opened_dex_files_;
- // Note that this might contain pointers owned by class_loader_context_.
- std::vector<const DexFile*> no_inline_from_dex_files_;
-
bool avoid_storing_invocation_;
std::string swap_file_name_;
int swap_fd_;
diff --git a/dex2oat/linker/image_test.h b/dex2oat/linker/image_test.h
index 12ecd3a..2acdf25 100644
--- a/dex2oat/linker/image_test.h
+++ b/dex2oat/linker/image_test.h
@@ -426,9 +426,6 @@
image_file_sizes.push_back(file->GetLength());
}
- ASSERT_TRUE(compiler_driver_->GetImageClasses() != nullptr);
- HashSet<std::string> image_classes(*compiler_driver_->GetImageClasses());
-
// Need to delete the compiler since it has worker threads which are attached to runtime.
compiler_driver_.reset();
@@ -469,6 +466,7 @@
// We loaded the runtime with an explicit image, so it must exist.
ASSERT_EQ(heap->GetBootImageSpaces().size(), image_file_sizes.size());
+ const HashSet<std::string>& image_classes = compiler_options_->GetImageClasses();
for (size_t i = 0; i < helper.dex_file_locations.size(); ++i) {
std::unique_ptr<const DexFile> dex(
LoadExpectSingleDexFile(helper.dex_file_locations[i].c_str()));
diff --git a/dex2oat/linker/image_writer.cc b/dex2oat/linker/image_writer.cc
index a61ad8f..b98dc68 100644
--- a/dex2oat/linker/image_writer.cc
+++ b/dex2oat/linker/image_writer.cc
@@ -38,6 +38,7 @@
#include "dex/dex_file-inl.h"
#include "dex/dex_file_types.h"
#include "driver/compiler_driver.h"
+#include "driver/compiler_options.h"
#include "elf_file.h"
#include "elf_utils.h"
#include "gc/accounting/card_table-inl.h"
@@ -851,7 +852,8 @@
std::string temp;
// Prune if not an image class, this handles any broken sets of image classes such as having a
// class in the set but not it's superclass.
- result = result || !compiler_driver_.IsImageClass(klass->GetDescriptor(&temp));
+ result = result ||
+ !compiler_driver_.GetCompilerOptions().IsImageClass(klass->GetDescriptor(&temp));
bool my_early_exit = false; // Only for ourselves, ignore caller.
// Remove classes that failed to verify since we don't want to have java.lang.VerifyError in the
// app image.
@@ -941,7 +943,7 @@
return true;
}
std::string temp;
- if (!compiler_driver_.IsImageClass(klass->GetDescriptor(&temp))) {
+ if (!compiler_driver_.GetCompilerOptions().IsImageClass(klass->GetDescriptor(&temp))) {
return false;
}
if (compile_app_image_) {
@@ -1212,27 +1214,22 @@
}
void ImageWriter::CheckNonImageClassesRemoved() {
- if (compiler_driver_.GetImageClasses() != nullptr) {
- auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
- if (obj->IsClass() && !IsInBootImage(obj)) {
- Class* klass = obj->AsClass();
- if (!KeepClass(klass)) {
- DumpImageClasses();
- std::string temp;
- CHECK(KeepClass(klass))
- << Runtime::Current()->GetHeap()->GetVerification()->FirstPathFromRootSet(klass);
- }
+ auto visitor = [&](Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (obj->IsClass() && !IsInBootImage(obj)) {
+ Class* klass = obj->AsClass();
+ if (!KeepClass(klass)) {
+ DumpImageClasses();
+ CHECK(KeepClass(klass))
+ << Runtime::Current()->GetHeap()->GetVerification()->FirstPathFromRootSet(klass);
}
- };
- gc::Heap* heap = Runtime::Current()->GetHeap();
- heap->VisitObjects(visitor);
- }
+ }
+ };
+ gc::Heap* heap = Runtime::Current()->GetHeap();
+ heap->VisitObjects(visitor);
}
void ImageWriter::DumpImageClasses() {
- auto image_classes = compiler_driver_.GetImageClasses();
- CHECK(image_classes != nullptr);
- for (const std::string& image_class : *image_classes) {
+ for (const std::string& image_class : compiler_driver_.GetCompilerOptions().GetImageClasses()) {
LOG(INFO) << " " << image_class;
}
}
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 9951668..0ed9579 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -366,6 +366,7 @@
zipped_dex_files_(),
zipped_dex_file_locations_(),
compiler_driver_(nullptr),
+ compiler_options_(nullptr),
image_writer_(nullptr),
compiling_boot_image_(compiling_boot_image),
extract_dex_files_into_vdex_(true),
@@ -642,8 +643,7 @@
}
bool OatWriter::MayHaveCompiledMethods() const {
- return CompilerFilter::IsAnyCompilationEnabled(
- GetCompilerDriver()->GetCompilerOptions().GetCompilerFilter());
+ return GetCompilerOptions().IsAnyCompilationEnabled();
}
bool OatWriter::WriteAndOpenDexFiles(
@@ -703,6 +703,16 @@
return true;
}
+// Initialize the writer with the given parameters.
+void OatWriter::Initialize(const CompilerDriver* compiler_driver,
+ ImageWriter* image_writer,
+ const std::vector<const DexFile*>& dex_files) {
+ compiler_driver_ = compiler_driver;
+ compiler_options_ = &compiler_driver->GetCompilerOptions();
+ image_writer_ = image_writer;
+ dex_files_ = &dex_files;
+}
+
void OatWriter::PrepareLayout(MultiOatRelativePatcher* relative_patcher) {
CHECK(write_state_ == WriteState::kPrepareLayout);
@@ -1157,7 +1167,7 @@
size_t debug_info_idx = OrderedMethodData::kDebugInfoIdxInvalid;
{
- const CompilerOptions& compiler_options = writer_->compiler_driver_->GetCompilerOptions();
+ const CompilerOptions& compiler_options = writer_->GetCompilerOptions();
ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode();
uint32_t code_size = quick_code.size() * sizeof(uint8_t);
@@ -1238,7 +1248,7 @@
OrderedMethodList ordered_methods)
: LayoutReserveOffsetCodeMethodVisitor(writer,
offset,
- writer->GetCompilerDriver()->GetCompilerOptions(),
+ writer->GetCompilerOptions(),
std::move(ordered_methods)) {
}
@@ -1651,7 +1661,7 @@
const DexFile::TypeId& type_id =
dex_file_->GetTypeId(dex_file_->GetClassDef(class_def_index_).class_idx_);
const char* class_descriptor = dex_file_->GetTypeDescriptor(type_id);
- return writer_->GetCompilerDriver()->IsImageClass(class_descriptor);
+ return writer_->GetCompilerOptions().IsImageClass(class_descriptor);
}
// Check whether specified dex file is in the compiled oat file.
@@ -1717,7 +1727,7 @@
// Ordered method visiting is only for compiled methods.
DCHECK(writer_->MayHaveCompiledMethods());
- if (writer_->GetCompilerDriver()->GetCompilerOptions().IsAotCompilationEnabled()) {
+ if (writer_->GetCompilerOptions().IsAotCompilationEnabled()) {
// Only need to set the dex cache if we have compilation. Other modes might have unloaded it.
if (dex_cache_ == nullptr || dex_cache_->GetDexFile() != dex_file) {
dex_cache_ = class_linker_->FindDexCache(Thread::Current(), *dex_file);
@@ -2388,9 +2398,9 @@
// TODO: Remove unused trampoline offsets from the OatHeader (requires oat version change).
oat_header_->SetInterpreterToInterpreterBridgeOffset(0);
oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0);
- if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
+ if (GetCompilerOptions().IsBootImage()) {
InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
- const bool generate_debug_info = compiler_driver_->GetCompilerOptions().GenerateAnyDebugInfo();
+ const bool generate_debug_info = GetCompilerOptions().GenerateAnyDebugInfo();
size_t adjusted_offset = offset;
#define DO_TRAMPOLINE(field, fn_name) \
@@ -2428,7 +2438,7 @@
}
size_t OatWriter::InitOatCodeDexFiles(size_t offset) {
- if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) {
+ if (!GetCompilerOptions().IsAnyCompilationEnabled()) {
if (kOatWriterDebugOatCodeLayout) {
LOG(INFO) << "InitOatCodeDexFiles: OatWriter("
<< this << "), "
@@ -2741,7 +2751,7 @@
}
size_t current_offset = start_offset;
- if (compiler_driver_->GetCompilerOptions().IsQuickeningCompilationEnabled()) {
+ if (GetCompilerOptions().IsQuickeningCompilationEnabled()) {
std::vector<uint32_t> dex_files_indices;
WriteQuickeningInfoMethodVisitor write_quicken_info_visitor(this, vdex_out);
if (!write_quicken_info_visitor.VisitDexMethods(*dex_files_)) {
@@ -3019,7 +3029,7 @@
oat_header_->SetImageFileLocationOatChecksum(image_file_location_oat_checksum);
oat_header_->SetImageFileLocationOatDataBegin(image_file_location_oat_begin);
- if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
+ if (GetCompilerOptions().IsBootImage()) {
CHECK_EQ(image_patch_delta, 0);
CHECK_EQ(oat_header_->GetImagePatchDelta(), 0);
} else {
@@ -3283,7 +3293,7 @@
}
size_t OatWriter::WriteCode(OutputStream* out, size_t file_offset, size_t relative_offset) {
- if (compiler_driver_->GetCompilerOptions().IsBootImage()) {
+ if (GetCompilerOptions().IsBootImage()) {
InstructionSet instruction_set = compiler_driver_->GetInstructionSet();
#define DO_TRAMPOLINE(field) \
@@ -3314,7 +3324,7 @@
size_t OatWriter::WriteCodeDexFiles(OutputStream* out,
size_t file_offset,
size_t relative_offset) {
- if (!compiler_driver_->GetCompilerOptions().IsAnyCompilationEnabled()) {
+ if (!GetCompilerOptions().IsAnyCompilationEnabled()) {
// As with InitOatCodeDexFiles, also skip the writer if
// compilation was disabled.
if (kOatWriterDebugOatCodeLayout) {
diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h
index 619743e..ccafe05 100644
--- a/dex2oat/linker/oat_writer.h
+++ b/dex2oat/linker/oat_writer.h
@@ -42,6 +42,7 @@
class BitVector;
class CompiledMethod;
class CompilerDriver;
+class CompilerOptions;
class DexContainer;
class ProfileCompilationInfo;
class TimingLogger;
@@ -180,17 +181,13 @@
CopyOption copy_dex_files,
/*out*/ std::vector<std::unique_ptr<MemMap>>* opened_dex_files_map,
/*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files);
+ // Initialize the writer with the given parameters.
+ void Initialize(const CompilerDriver* compiler_driver,
+ ImageWriter* image_writer,
+ const std::vector<const DexFile*>& dex_files);
bool WriteQuickeningInfo(OutputStream* vdex_out);
bool WriteVerifierDeps(OutputStream* vdex_out, verifier::VerifierDeps* verifier_deps);
bool WriteChecksumsAndVdexHeader(OutputStream* vdex_out);
- // Initialize the writer with the given parameters.
- void Initialize(const CompilerDriver* compiler,
- ImageWriter* image_writer,
- const std::vector<const DexFile*>& dex_files) {
- compiler_driver_ = compiler;
- image_writer_ = image_writer;
- dex_files_ = &dex_files;
- }
// Prepare layout of remaining data.
void PrepareLayout(MultiOatRelativePatcher* relative_patcher);
@@ -263,6 +260,11 @@
return compiler_driver_;
}
+ const CompilerOptions& GetCompilerOptions() const {
+ DCHECK(compiler_options_ != nullptr);
+ return *compiler_options_;
+ }
+
private:
class DexFileSource;
class OatClassHeader;
@@ -388,6 +390,7 @@
dchecked_vector<debug::MethodDebugInfo> method_info_;
const CompilerDriver* compiler_driver_;
+ const CompilerOptions* compiler_options_;
ImageWriter* image_writer_;
const bool compiling_boot_image_;
// Whether the dex files being compiled are going to be extracted to the vdex.