summaryrefslogtreecommitdiff
path: root/compiler/driver/compiler_driver.cc
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/driver/compiler_driver.cc')
-rw-r--r--compiler/driver/compiler_driver.cc138
1 files changed, 108 insertions, 30 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 53604761d12..41b7e7be47f 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -264,8 +264,6 @@ CompilerDriver::CompilerDriver(
InstructionSet instruction_set,
const InstructionSetFeatures* instruction_set_features,
std::unordered_set<std::string>* image_classes,
- std::unordered_set<std::string>* compiled_classes,
- std::unordered_set<std::string>* compiled_methods,
size_t thread_count,
int swap_fd,
const ProfileCompilationInfo* profile_compilation_info)
@@ -279,8 +277,6 @@ CompilerDriver::CompilerDriver(
requires_constructor_barrier_lock_("constructor barrier lock"),
non_relative_linker_patch_count_(0u),
image_classes_(image_classes),
- classes_to_compile_(compiled_classes),
- methods_to_compile_(compiled_methods),
number_of_soft_verifier_failures_(0),
had_hard_verifier_failure_(false),
parallel_thread_count_(thread_count),
@@ -638,7 +634,6 @@ static void CompileMethodQuick(
(verified_method->GetEncounteredVerificationFailures() &
(verifier::VERIFY_ERROR_FORCE_INTERPRETER | verifier::VERIFY_ERROR_LOCKING)) == 0 &&
// Is eligable for compilation by methods-to-compile filter.
- driver->IsMethodToCompile(method_ref) &&
driver->ShouldCompileBasedOnProfile(method_ref);
if (compile) {
@@ -781,7 +776,8 @@ void CompilerDriver::Resolve(jobject class_loader,
// TODO: Collect the relevant string indices in parallel, then allocate them sequentially in a
// stable order.
-static void ResolveConstStrings(Handle<mirror::DexCache> dex_cache,
+static void ResolveConstStrings(ClassLinker* class_linker,
+ Handle<mirror::DexCache> dex_cache,
const DexFile& dex_file,
const DexFile::CodeItem* code_item)
REQUIRES_SHARED(Locks::mutator_lock_) {
@@ -790,7 +786,6 @@ static void ResolveConstStrings(Handle<mirror::DexCache> dex_cache,
return;
}
- ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
for (const DexInstructionPcPair& inst : CodeItemInstructionAccessor(dex_file, code_item)) {
switch (inst->Opcode()) {
case Instruction::CONST_STRING:
@@ -838,22 +833,105 @@ static void ResolveConstStrings(CompilerDriver* driver,
dex_file->StringByTypeIdx(class_def.class_idx_));
if (!compilation_enabled) {
// Compilation is skipped, do not resolve const-string in code of this class.
- // TODO: Make sure that inlining honors this.
+ // FIXME: Make sure that inlining honors this. b/26687569
continue;
}
// Direct and virtual methods.
- int64_t previous_method_idx = -1;
while (it.HasNextMethod()) {
- uint32_t method_idx = it.GetMemberIndex();
- if (method_idx == previous_method_idx) {
- // smali can create dex files with two encoded_methods sharing the same method_idx
- // http://code.google.com/p/smali/issues/detail?id=119
- it.Next();
- continue;
+ ResolveConstStrings(class_linker, dex_cache, *dex_file, it.GetMethodCodeItem());
+ it.Next();
+ }
+ DCHECK(!it.HasNext());
+ }
+ }
+}
+
+// Initialize type check bit strings for check-cast and instance-of in the code. Done to have
+// deterministic allocation behavior. Right now this is single-threaded for simplicity.
+// TODO: Collect the relevant type indices in parallel, then process them sequentially in a
+// stable order.
+
+static void InitializeTypeCheckBitstrings(CompilerDriver* driver,
+ ClassLinker* class_linker,
+ Handle<mirror::DexCache> dex_cache,
+ const DexFile& dex_file,
+ const DexFile::CodeItem* code_item)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (code_item == nullptr) {
+ // Abstract or native method.
+ return;
+ }
+
+ for (const DexInstructionPcPair& inst : CodeItemInstructionAccessor(dex_file, code_item)) {
+ switch (inst->Opcode()) {
+ case Instruction::CHECK_CAST:
+ case Instruction::INSTANCE_OF: {
+ dex::TypeIndex type_index(
+ (inst->Opcode() == Instruction::CHECK_CAST) ? inst->VRegB_21c() : inst->VRegC_22c());
+ const char* descriptor = dex_file.StringByTypeIdx(type_index);
+ // We currently do not use the bitstring type check for array or final (including
+ // 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)) {
+ ObjPtr<mirror::Class> klass =
+ class_linker->LookupResolvedType(type_index,
+ dex_cache.Get(),
+ /* class_loader */ nullptr);
+ CHECK(klass != nullptr) << descriptor << " should have been previously resolved.";
+ // Now assign the bitstring if the class is not final. Keep this in sync with sharpening.
+ if (!klass->IsFinal()) {
+ MutexLock subtype_check_lock(Thread::Current(), *Locks::subtype_check_lock_);
+ SubtypeCheck<ObjPtr<mirror::Class>>::EnsureAssigned(klass);
+ }
}
- previous_method_idx = method_idx;
- ResolveConstStrings(dex_cache, *dex_file, it.GetMethodCodeItem());
+ break;
+ }
+
+ default:
+ break;
+ }
+ }
+}
+
+static void InitializeTypeCheckBitstrings(CompilerDriver* driver,
+ const std::vector<const DexFile*>& dex_files,
+ TimingLogger* timings) {
+ ScopedObjectAccess soa(Thread::Current());
+ StackHandleScope<1> hs(soa.Self());
+ ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
+ MutableHandle<mirror::DexCache> dex_cache(hs.NewHandle<mirror::DexCache>(nullptr));
+
+ for (const DexFile* dex_file : dex_files) {
+ dex_cache.Assign(class_linker->FindDexCache(soa.Self(), *dex_file));
+ TimingLogger::ScopedTiming t("Initialize type check bitstrings", timings);
+
+ size_t class_def_count = dex_file->NumClassDefs();
+ for (size_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
+ 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) {
+ // empty class, probably a marker interface
+ continue;
+ }
+
+ ClassDataItemIterator it(*dex_file, class_data);
+ it.SkipAllFields();
+
+ bool compilation_enabled = driver->IsClassToCompile(
+ dex_file->StringByTypeIdx(class_def.class_idx_));
+ if (!compilation_enabled) {
+ // Compilation is skipped, do not look for type checks in code of this class.
+ // FIXME: Make sure that inlining honors this. b/26687569
+ continue;
+ }
+
+ // Direct and virtual methods.
+ while (it.HasNextMethod()) {
+ InitializeTypeCheckBitstrings(
+ driver, class_linker, dex_cache, *dex_file, it.GetMethodCodeItem());
it.Next();
}
DCHECK(!it.HasNext());
@@ -955,6 +1033,14 @@ void CompilerDriver::PreCompile(jobject class_loader,
UpdateImageClasses(timings);
VLOG(compiler) << "UpdateImageClasses: " << GetMemoryUsageString(false);
+
+ if (kBitstringSubtypeCheckEnabled &&
+ GetCompilerOptions().IsForceDeterminism() && GetCompilerOptions().IsBootImage()) {
+ // Initialize type check bit string used by check-cast and instanceof.
+ // Do this now to have a deterministic image.
+ // Note: This is done after UpdateImageClasses() at it relies on the image classes to be final.
+ InitializeTypeCheckBitstrings(this, dex_files, timings);
+ }
}
bool CompilerDriver::IsImageClass(const char* descriptor) const {
@@ -974,15 +1060,6 @@ bool CompilerDriver::IsClassToCompile(const char* descriptor) const {
return classes_to_compile_->find(descriptor) != classes_to_compile_->end();
}
-bool CompilerDriver::IsMethodToCompile(const MethodReference& method_ref) const {
- if (methods_to_compile_ == nullptr) {
- return true;
- }
-
- std::string tmp = method_ref.PrettyMethod();
- return methods_to_compile_->find(tmp.c_str()) != methods_to_compile_->end();
-}
-
bool CompilerDriver::ShouldCompileBasedOnProfile(const MethodReference& method_ref) const {
// Profile compilation info may be null if no profile is passed.
if (!CompilerFilter::DependsOnProfile(compiler_options_->GetCompilerFilter())) {
@@ -1555,7 +1632,7 @@ class ParallelCompilationManager {
self->AssertNoPendingException();
CHECK_GT(work_units, 0U);
- index_.StoreRelaxed(begin);
+ index_.store(begin, std::memory_order_relaxed);
for (size_t i = 0; i < work_units; ++i) {
thread_pool_->AddTask(self, new ForAllClosureLambda<Fn>(this, end, fn));
}
@@ -1573,7 +1650,7 @@ class ParallelCompilationManager {
}
size_t NextIndex() {
- return index_.FetchAndAddSequentiallyConsistent(1);
+ return index_.fetch_add(1, std::memory_order_seq_cst);
}
private:
@@ -2838,7 +2915,8 @@ void CompilerDriver::AddCompiledMethod(const MethodReference& method_ref,
/*expected*/ nullptr,
compiled_method);
CHECK(result == MethodTable::kInsertResultSuccess);
- non_relative_linker_patch_count_.FetchAndAddRelaxed(non_relative_linker_patch_count);
+ non_relative_linker_patch_count_.fetch_add(non_relative_linker_patch_count,
+ std::memory_order_relaxed);
DCHECK(GetCompiledMethod(method_ref) != nullptr) << method_ref.PrettyMethod();
}
@@ -2949,7 +3027,7 @@ bool CompilerDriver::IsMethodVerifiedWithoutFailures(uint32_t method_idx,
}
size_t CompilerDriver::GetNonRelativeLinkerPatchCount() const {
- return non_relative_linker_patch_count_.LoadRelaxed();
+ return non_relative_linker_patch_count_.load(std::memory_order_relaxed);
}
void CompilerDriver::SetRequiresConstructorBarrier(Thread* self,