am 8a8cefa3: am d8406781: Merge "ART: Wire up DexToDexCompiler without extern"
* commit '8a8cefa3d0331d07c49d11ea936b33d03d124e73':
ART: Wire up DexToDexCompiler without extern
diff --git a/compiler/Android.mk b/compiler/Android.mk
index 3947078..4944915 100644
--- a/compiler/Android.mk
+++ b/compiler/Android.mk
@@ -171,6 +171,7 @@
dex/quick/mips/mips_lir.h \
dex/quick/resource_mask.h \
dex/compiler_enums.h \
+ dex/dex_to_dex_compiler.h \
dex/global_value_numbering.h \
dex/pass_me.h \
driver/compiler_driver.h \
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 4b56b69..603130a 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "dex_to_dex_compiler.h"
+
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/logging.h"
@@ -65,7 +67,7 @@
}
bool PerformOptimizations() const {
- return dex_to_dex_compilation_level_ >= kOptimize;
+ return dex_to_dex_compilation_level_ >= DexToDexCompilationLevel::kOptimize;
}
// Compiles a RETURN-VOID into a RETURN-VOID-BARRIER within a constructor where
@@ -108,7 +110,7 @@
};
void DexCompiler::Compile() {
- DCHECK_GE(dex_to_dex_compilation_level_, kRequired);
+ DCHECK_GE(dex_to_dex_compilation_level_, DexToDexCompilationLevel::kRequired);
const DexFile::CodeItem* code_item = unit_.GetCodeItem();
const uint16_t* insns = code_item->insns_;
const uint32_t insns_size = code_item->insns_size_in_code_units_;
@@ -310,21 +312,22 @@
}
}
-extern "C" CompiledMethod* ArtCompileDEX(
- art::CompilerDriver& driver,
- const art::DexFile::CodeItem* code_item,
+CompiledMethod* ArtCompileDEX(
+ CompilerDriver* driver,
+ const DexFile::CodeItem* code_item,
uint32_t access_flags,
- art::InvokeType invoke_type ATTRIBUTE_UNUSED,
+ InvokeType invoke_type ATTRIBUTE_UNUSED,
uint16_t class_def_idx,
uint32_t method_idx,
jobject class_loader,
- const art::DexFile& dex_file,
- art::DexToDexCompilationLevel dex_to_dex_compilation_level) {
- if (dex_to_dex_compilation_level != art::kDontDexToDexCompile) {
+ const DexFile& dex_file,
+ DexToDexCompilationLevel dex_to_dex_compilation_level) {
+ DCHECK(driver != nullptr);
+ if (dex_to_dex_compilation_level != DexToDexCompilationLevel::kDontDexToDexCompile) {
art::DexCompilationUnit unit(nullptr, class_loader, art::Runtime::Current()->GetClassLinker(),
dex_file, code_item, class_def_idx, method_idx, access_flags,
- driver.GetVerifiedMethod(&dex_file, method_idx));
- art::optimizer::DexCompiler dex_compiler(driver, unit, dex_to_dex_compilation_level);
+ driver->GetVerifiedMethod(&dex_file, method_idx));
+ art::optimizer::DexCompiler dex_compiler(*driver, unit, dex_to_dex_compilation_level);
dex_compiler.Compile();
if (dex_compiler.GetQuickenedInfo().empty()) {
// No need to create a CompiledMethod if there are no quickened opcodes.
@@ -337,13 +340,13 @@
builder.PushBackUnsigned(info.dex_pc);
builder.PushBackUnsigned(info.dex_member_index);
}
- InstructionSet instruction_set = driver.GetInstructionSet();
+ InstructionSet instruction_set = driver->GetInstructionSet();
if (instruction_set == kThumb2) {
// Don't use the thumb2 instruction set to avoid the one off code delta.
instruction_set = kArm;
}
return CompiledMethod::SwapAllocCompiledMethod(
- &driver,
+ driver,
instruction_set,
ArrayRef<const uint8_t>(), // no code
0,
diff --git a/compiler/dex/dex_to_dex_compiler.h b/compiler/dex/dex_to_dex_compiler.h
new file mode 100644
index 0000000..3fad6d4
--- /dev/null
+++ b/compiler/dex/dex_to_dex_compiler.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 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.
+ */
+
+#ifndef ART_COMPILER_DEX_DEX_TO_DEX_COMPILER_H_
+#define ART_COMPILER_DEX_DEX_TO_DEX_COMPILER_H_
+
+#include "jni.h"
+
+#include "dex_file.h"
+#include "invoke_type.h"
+
+namespace art {
+
+class CompiledMethod;
+class CompilerDriver;
+
+namespace optimizer {
+
+enum class DexToDexCompilationLevel {
+ kDontDexToDexCompile, // Only meaning wrt image time interpretation.
+ kRequired, // Dex-to-dex compilation required for correctness.
+ kOptimize // Perform required transformation and peep-hole optimizations.
+};
+std::ostream& operator<<(std::ostream& os, const DexToDexCompilationLevel& rhs);
+
+CompiledMethod* ArtCompileDEX(CompilerDriver* driver,
+ const DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ InvokeType invoke_type,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const DexFile& dex_file,
+ DexToDexCompilationLevel dex_to_dex_compilation_level);
+
+} // namespace optimizer
+
+} // namespace art
+
+#endif // ART_COMPILER_DEX_DEX_TO_DEX_COMPILER_H_
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index affa52a..299b995 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -39,6 +39,7 @@
#include "compiler_driver-inl.h"
#include "dex_compilation_unit.h"
#include "dex_file-inl.h"
+#include "dex/dex_to_dex_compiler.h"
#include "dex/verification_results.h"
#include "dex/verified_method.h"
#include "dex/quick/dex_file_method_inliner.h"
@@ -334,16 +335,6 @@
DISALLOW_COPY_AND_ASSIGN(AOTCompilationStats);
};
-
-extern "C" art::CompiledMethod* ArtCompileDEX(art::CompilerDriver& compiler,
- const art::DexFile::CodeItem* code_item,
- uint32_t access_flags,
- art::InvokeType invoke_type,
- uint16_t class_def_idx,
- uint32_t method_idx,
- jobject class_loader,
- const art::DexFile& dex_file);
-
CompilerDriver::CompilerDriver(const CompilerOptions* compiler_options,
VerificationResults* verification_results,
DexFileToMethodInlinerMap* method_inliner_map,
@@ -394,8 +385,6 @@
DCHECK(verification_results_ != nullptr);
DCHECK(method_inliner_map_ != nullptr);
- dex_to_dex_compiler_ = reinterpret_cast<DexToDexCompilerFn>(ArtCompileDEX);
-
compiler_->Init();
CHECK_EQ(image_, image_classes_.get() != nullptr);
@@ -508,13 +497,14 @@
}
}
-DexToDexCompilationLevel CompilerDriver::GetDexToDexCompilationlevel(
- Thread* self, Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file,
- const DexFile::ClassDef& class_def) {
+static optimizer::DexToDexCompilationLevel GetDexToDexCompilationLevel(
+ Thread* self, const CompilerDriver& driver, Handle<mirror::ClassLoader> class_loader,
+ const DexFile& dex_file, const DexFile::ClassDef& class_def)
+ SHARED_REQUIRES(Locks::mutator_lock_) {
auto* const runtime = Runtime::Current();
- if (runtime->UseJit() || GetCompilerOptions().VerifyAtRuntime()) {
+ if (runtime->UseJit() || driver.GetCompilerOptions().VerifyAtRuntime()) {
// Verify at runtime shouldn't dex to dex since we didn't resolve of verify.
- return kDontDexToDexCompile;
+ return optimizer::DexToDexCompilationLevel::kDontDexToDexCompile;
}
const char* descriptor = dex_file.GetClassDescriptor(class_def);
ClassLinker* class_linker = runtime->GetClassLinker();
@@ -522,7 +512,7 @@
if (klass == nullptr) {
CHECK(self->IsExceptionPending());
self->ClearException();
- return kDontDexToDexCompile;
+ return optimizer::DexToDexCompilationLevel::kDontDexToDexCompile;
}
// DexToDex at the kOptimize level may introduce quickened opcodes, which replace symbolic
// references with actual offsets. We cannot re-verify such instructions.
@@ -532,14 +522,142 @@
// optimize when a class has been fully verified before.
if (klass->IsVerified()) {
// Class is verified so we can enable DEX-to-DEX compilation for performance.
- return kOptimize;
+ return optimizer::DexToDexCompilationLevel::kOptimize;
} else if (klass->IsCompileTimeVerified()) {
// Class verification has soft-failed. Anyway, ensure at least correctness.
DCHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime);
- return kRequired;
+ return optimizer::DexToDexCompilationLevel::kRequired;
} else {
// Class verification has failed: do not run DEX-to-DEX compilation.
- return kDontDexToDexCompile;
+ return optimizer::DexToDexCompilationLevel::kDontDexToDexCompile;
+ }
+}
+
+static optimizer::DexToDexCompilationLevel GetDexToDexCompilationLevel(
+ Thread* self,
+ const CompilerDriver& driver,
+ jobject jclass_loader,
+ const DexFile& dex_file,
+ const DexFile::ClassDef& class_def) {
+ ScopedObjectAccess soa(self);
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::ClassLoader> class_loader(
+ hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
+ return GetDexToDexCompilationLevel(self, driver, class_loader, dex_file, class_def);
+}
+
+// Does the runtime for the InstructionSet provide an implementation returned by
+// GetQuickGenericJniStub allowing down calls that aren't compiled using a JNI compiler?
+static bool InstructionSetHasGenericJniStub(InstructionSet isa) {
+ switch (isa) {
+ case kArm:
+ case kArm64:
+ case kThumb2:
+ case kMips:
+ case kMips64:
+ case kX86:
+ case kX86_64: return true;
+ default: return false;
+ }
+}
+
+static void CompileMethod(Thread* self,
+ CompilerDriver* driver,
+ const DexFile::CodeItem* code_item,
+ uint32_t access_flags,
+ InvokeType invoke_type,
+ uint16_t class_def_idx,
+ uint32_t method_idx,
+ jobject class_loader,
+ const DexFile& dex_file,
+ optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level,
+ bool compilation_enabled)
+ REQUIRES(!driver->compiled_methods_lock_) {
+ DCHECK(driver != nullptr);
+ CompiledMethod* compiled_method = nullptr;
+ uint64_t start_ns = kTimeCompileMethod ? NanoTime() : 0;
+ MethodReference method_ref(&dex_file, method_idx);
+
+ if ((access_flags & kAccNative) != 0) {
+ // Are we interpreting only and have support for generic JNI down calls?
+ if (!driver->GetCompilerOptions().IsCompilationEnabled() &&
+ InstructionSetHasGenericJniStub(driver->GetInstructionSet())) {
+ // Leaving this empty will trigger the generic JNI version
+ } else {
+ compiled_method = driver->GetCompiler()->JniCompile(access_flags, method_idx, dex_file);
+ CHECK(compiled_method != nullptr);
+ }
+ } else if ((access_flags & kAccAbstract) != 0) {
+ // Abstract methods don't have code.
+ } else {
+ bool has_verified_method = driver->GetVerificationResults()
+ ->GetVerifiedMethod(method_ref) != nullptr;
+ bool compile = compilation_enabled &&
+ // Basic checks, e.g., not <clinit>.
+ driver->GetVerificationResults()
+ ->IsCandidateForCompilation(method_ref, access_flags) &&
+ // Did not fail to create VerifiedMethod metadata.
+ has_verified_method &&
+ // Is eligable for compilation by methods-to-compile filter.
+ driver->IsMethodToCompile(method_ref);
+ if (compile) {
+ // NOTE: if compiler declines to compile this method, it will return null.
+ compiled_method = driver->GetCompiler()->Compile(code_item, access_flags, invoke_type,
+ class_def_idx, method_idx, class_loader,
+ dex_file);
+ }
+ if (compiled_method == nullptr &&
+ dex_to_dex_compilation_level != optimizer::DexToDexCompilationLevel::kDontDexToDexCompile) {
+ // TODO: add a command-line option to disable DEX-to-DEX compilation ?
+ // Do not optimize if a VerifiedMethod is missing. SafeCast elision, for example, relies on
+ // it.
+ compiled_method = optimizer::ArtCompileDEX(
+ driver,
+ code_item,
+ access_flags,
+ invoke_type,
+ class_def_idx,
+ method_idx,
+ class_loader,
+ dex_file,
+ has_verified_method
+ ? dex_to_dex_compilation_level
+ : optimizer::DexToDexCompilationLevel::kRequired);
+ }
+ }
+ if (kTimeCompileMethod) {
+ uint64_t duration_ns = NanoTime() - start_ns;
+ if (duration_ns > MsToNs(driver->GetCompiler()->GetMaximumCompilationTimeBeforeWarning())) {
+ LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
+ << " took " << PrettyDuration(duration_ns);
+ }
+ }
+
+ if (compiled_method != nullptr) {
+ // Count non-relative linker patches.
+ size_t non_relative_linker_patch_count = 0u;
+ for (const LinkerPatch& patch : compiled_method->GetPatches()) {
+ if (!patch.IsPcRelative()) {
+ ++non_relative_linker_patch_count;
+ }
+ }
+ bool compile_pic = driver->GetCompilerOptions().GetCompilePic(); // Off by default
+ // When compiling with PIC, there should be zero non-relative linker patches
+ CHECK(!compile_pic || non_relative_linker_patch_count == 0u);
+
+ driver->AddCompiledMethod(method_ref, compiled_method, non_relative_linker_patch_count);
+ }
+
+ // Done compiling, delete the verified method to reduce native memory usage. Do not delete in
+ // optimizing compiler, which may need the verified method again for inlining.
+ if (driver->GetCompilerKind() != Compiler::kOptimizing) {
+ driver->GetVerificationResults()->RemoveVerifiedMethod(method_ref);
+ }
+
+ if (self->IsExceptionPending()) {
+ ScopedObjectAccess soa(self);
+ LOG(FATAL) << "Unexpected exception compiling: " << PrettyMethod(method_idx, dex_file) << "\n"
+ << self->GetException()->Dump();
}
}
@@ -570,24 +688,30 @@
PreCompile(jclass_loader, dex_files, thread_pool.get(), timings);
// Can we run DEX-to-DEX compiler on this class ?
- DexToDexCompilationLevel dex_to_dex_compilation_level = kDontDexToDexCompile;
- {
- ScopedObjectAccess soa(self);
- const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx);
- StackHandleScope<1> hs(soa.Self());
- Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
- dex_to_dex_compilation_level = GetDexToDexCompilationlevel(self, class_loader, *dex_file,
- class_def);
- }
- CompileMethod(self, code_item, access_flags, invoke_type, class_def_idx, method_idx,
- jclass_loader, *dex_file, dex_to_dex_compilation_level, true);
+ optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level =
+ GetDexToDexCompilationLevel(self,
+ *this,
+ jclass_loader,
+ *dex_file,
+ dex_file->GetClassDef(class_def_idx));
+
+ CompileMethod(self,
+ this,
+ code_item,
+ access_flags,
+ invoke_type,
+ class_def_idx,
+ method_idx,
+ jclass_loader,
+ *dex_file,
+ dex_to_dex_compilation_level,
+ true);
self->GetJniEnv()->DeleteGlobalRef(jclass_loader);
self->TransitionFromSuspendedToRunnable();
}
-CompiledMethod* CompilerDriver::CompileMethod(Thread* self, ArtMethod* method) {
+CompiledMethod* CompilerDriver::CompileArtMethod(Thread* self, ArtMethod* method) {
const uint32_t method_idx = method->GetDexMethodIndex();
const uint32_t access_flags = method->GetAccessFlags();
const InvokeType invoke_type = method->GetInvokeType();
@@ -598,12 +722,21 @@
const DexFile* dex_file = method->GetDexFile();
const uint16_t class_def_idx = method->GetClassDefIndex();
const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx);
- DexToDexCompilationLevel dex_to_dex_compilation_level =
- GetDexToDexCompilationlevel(self, class_loader, *dex_file, class_def);
+ optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level =
+ GetDexToDexCompilationLevel(self, *this, class_loader, *dex_file, class_def);
const DexFile::CodeItem* code_item = dex_file->GetCodeItem(method->GetCodeItemOffset());
self->TransitionFromRunnableToSuspended(kNative);
- CompileMethod(self, code_item, access_flags, invoke_type, class_def_idx, method_idx,
- jclass_loader, *dex_file, dex_to_dex_compilation_level, true);
+ CompileMethod(self,
+ this,
+ code_item,
+ access_flags,
+ invoke_type,
+ class_def_idx,
+ method_idx,
+ jclass_loader,
+ *dex_file,
+ dex_to_dex_compilation_level,
+ true);
auto* compiled_method = GetCompiledMethod(MethodReference(dex_file, method_idx));
self->TransitionFromSuspendedToRunnable();
return compiled_method;
@@ -2237,15 +2370,9 @@
CompilerDriver* const driver = manager_->GetCompiler();
// Can we run DEX-to-DEX compiler on this class ?
- DexToDexCompilationLevel dex_to_dex_compilation_level = kDontDexToDexCompile;
- {
- ScopedObjectAccess soa(self);
- StackHandleScope<1> hs(soa.Self());
- Handle<mirror::ClassLoader> class_loader(
- hs.NewHandle(soa.Decode<mirror::ClassLoader*>(jclass_loader)));
- dex_to_dex_compilation_level = driver->GetDexToDexCompilationlevel(
- soa.Self(), class_loader, dex_file, class_def);
- }
+ optimizer::DexToDexCompilationLevel dex_to_dex_compilation_level =
+ GetDexToDexCompilationLevel(self, *driver, jclass_loader, dex_file, class_def);
+
ClassDataItemIterator it(dex_file, class_data);
// Skip fields
while (it.HasNextStaticField()) {
@@ -2269,10 +2396,10 @@
continue;
}
previous_direct_method_idx = method_idx;
- driver->CompileMethod(self, it.GetMethodCodeItem(), it.GetMethodAccessFlags(),
- it.GetMethodInvokeType(class_def), class_def_index,
- method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level,
- compilation_enabled);
+ CompileMethod(self, driver, it.GetMethodCodeItem(), it.GetMethodAccessFlags(),
+ it.GetMethodInvokeType(class_def), class_def_index,
+ method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level,
+ compilation_enabled);
it.Next();
}
// Compile virtual methods
@@ -2286,10 +2413,10 @@
continue;
}
previous_virtual_method_idx = method_idx;
- driver->CompileMethod(self, it.GetMethodCodeItem(), it.GetMethodAccessFlags(),
- it.GetMethodInvokeType(class_def), class_def_index,
- method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level,
- compilation_enabled);
+ CompileMethod(self, driver, it.GetMethodCodeItem(), it.GetMethodAccessFlags(),
+ it.GetMethodInvokeType(class_def), class_def_index,
+ method_idx, jclass_loader, dex_file, dex_to_dex_compilation_level,
+ compilation_enabled);
it.Next();
}
DCHECK(!it.HasNext());
@@ -2309,112 +2436,18 @@
context.ForAll(0, dex_file.NumClassDefs(), &visitor, thread_count_);
}
-// Does the runtime for the InstructionSet provide an implementation returned by
-// GetQuickGenericJniStub allowing down calls that aren't compiled using a JNI compiler?
-static bool InstructionSetHasGenericJniStub(InstructionSet isa) {
- switch (isa) {
- case kArm:
- case kArm64:
- case kThumb2:
- case kMips:
- case kMips64:
- case kX86:
- case kX86_64: return true;
- default: return false;
+void CompilerDriver::AddCompiledMethod(const MethodReference& method_ref,
+ CompiledMethod* const compiled_method,
+ size_t non_relative_linker_patch_count) {
+ DCHECK(GetCompiledMethod(method_ref) == nullptr)
+ << PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file);
+ {
+ MutexLock mu(Thread::Current(), compiled_methods_lock_);
+ compiled_methods_.Put(method_ref, compiled_method);
+ non_relative_linker_patch_count_ += non_relative_linker_patch_count;
}
-}
-
-void CompilerDriver::CompileMethod(Thread* self, const DexFile::CodeItem* code_item,
- uint32_t access_flags, InvokeType invoke_type,
- uint16_t class_def_idx, uint32_t method_idx,
- jobject class_loader, const DexFile& dex_file,
- DexToDexCompilationLevel dex_to_dex_compilation_level,
- bool compilation_enabled) {
- CompiledMethod* compiled_method = nullptr;
- uint64_t start_ns = kTimeCompileMethod ? NanoTime() : 0;
- MethodReference method_ref(&dex_file, method_idx);
-
- if ((access_flags & kAccNative) != 0) {
- // Are we interpreting only and have support for generic JNI down calls?
- if (!compiler_options_->IsCompilationEnabled() &&
- InstructionSetHasGenericJniStub(instruction_set_)) {
- // Leaving this empty will trigger the generic JNI version
- } else {
- compiled_method = compiler_->JniCompile(access_flags, method_idx, dex_file);
- CHECK(compiled_method != nullptr);
- }
- } else if ((access_flags & kAccAbstract) != 0) {
- // Abstract methods don't have code.
- } else {
- bool has_verified_method = verification_results_->GetVerifiedMethod(method_ref) != nullptr;
- bool compile = compilation_enabled &&
- // Basic checks, e.g., not <clinit>.
- verification_results_->IsCandidateForCompilation(method_ref, access_flags) &&
- // Did not fail to create VerifiedMethod metadata.
- has_verified_method &&
- // Is eligable for compilation by methods-to-compile filter.
- IsMethodToCompile(method_ref);
- if (compile) {
- // NOTE: if compiler declines to compile this method, it will return null.
- compiled_method = compiler_->Compile(code_item, access_flags, invoke_type, class_def_idx,
- method_idx, class_loader, dex_file);
- }
- if (compiled_method == nullptr && dex_to_dex_compilation_level != kDontDexToDexCompile) {
- // TODO: add a command-line option to disable DEX-to-DEX compilation ?
- // Do not optimize if a VerifiedMethod is missing. SafeCast elision, for example, relies on
- // it.
- compiled_method = (*dex_to_dex_compiler_)(
- *this,
- code_item,
- access_flags,
- invoke_type,
- class_def_idx,
- method_idx,
- class_loader,
- dex_file,
- has_verified_method ? dex_to_dex_compilation_level : kRequired);
- }
- }
- if (kTimeCompileMethod) {
- uint64_t duration_ns = NanoTime() - start_ns;
- if (duration_ns > MsToNs(compiler_->GetMaximumCompilationTimeBeforeWarning())) {
- LOG(WARNING) << "Compilation of " << PrettyMethod(method_idx, dex_file)
- << " took " << PrettyDuration(duration_ns);
- }
- }
-
- if (compiled_method != nullptr) {
- // Count non-relative linker patches.
- size_t non_relative_linker_patch_count = 0u;
- for (const LinkerPatch& patch : compiled_method->GetPatches()) {
- if (!patch.IsPcRelative()) {
- ++non_relative_linker_patch_count;
- }
- }
- bool compile_pic = GetCompilerOptions().GetCompilePic(); // Off by default
- // When compiling with PIC, there should be zero non-relative linker patches
- CHECK(!compile_pic || non_relative_linker_patch_count == 0u);
-
- DCHECK(GetCompiledMethod(method_ref) == nullptr) << PrettyMethod(method_idx, dex_file);
- {
- MutexLock mu(self, compiled_methods_lock_);
- compiled_methods_.Put(method_ref, compiled_method);
- non_relative_linker_patch_count_ += non_relative_linker_patch_count;
- }
- DCHECK(GetCompiledMethod(method_ref) != nullptr) << PrettyMethod(method_idx, dex_file);
- }
-
- // Done compiling, delete the verified method to reduce native memory usage. Do not delete in
- // optimizing compiler, which may need the verified method again for inlining.
- if (compiler_kind_ != Compiler::kOptimizing) {
- verification_results_->RemoveVerifiedMethod(method_ref);
- }
-
- if (self->IsExceptionPending()) {
- ScopedObjectAccess soa(self);
- LOG(FATAL) << "Unexpected exception compiling: " << PrettyMethod(method_idx, dex_file) << "\n"
- << self->GetException()->Dump();
- }
+ DCHECK(GetCompiledMethod(method_ref) != nullptr)
+ << PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file);
}
void CompilerDriver::RemoveCompiledMethod(const MethodReference& method_ref) {
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 88e03a2..4de9c73 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -80,13 +80,6 @@
kQuickAbi
};
-enum DexToDexCompilationLevel {
- kDontDexToDexCompile, // Only meaning wrt image time interpretation.
- kRequired, // Dex-to-dex compilation required for correctness.
- kOptimize // Perform required transformation and peep-hole optimizations.
-};
-std::ostream& operator<<(std::ostream& os, const DexToDexCompilationLevel& rhs);
-
static constexpr bool kUseMurmur3Hash = true;
class CompilerDriver {
@@ -116,7 +109,7 @@
TimingLogger* timings)
REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_);
- CompiledMethod* CompileMethod(Thread* self, ArtMethod*)
+ CompiledMethod* CompileArtMethod(Thread* self, ArtMethod*)
SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!compiled_methods_lock_) WARN_UNUSED;
// Compile a single Method.
@@ -185,6 +178,11 @@
size_t GetNonRelativeLinkerPatchCount() const
REQUIRES(!compiled_methods_lock_);
+ // Add a compiled method.
+ void AddCompiledMethod(const MethodReference& method_ref,
+ CompiledMethod* const compiled_method,
+ size_t non_relative_linker_patch_count)
+ REQUIRES(!compiled_methods_lock_);
// Remove and delete a compiled method.
void RemoveCompiledMethod(const MethodReference& method_ref) REQUIRES(!compiled_methods_lock_);
@@ -476,6 +474,10 @@
had_hard_verifier_failure_ = true;
}
+ Compiler::Kind GetCompilerKind() {
+ return compiler_kind_;
+ }
+
private:
// Return whether the declaring class of `resolved_member` is
// available to `referrer_class` for read or write access using two
@@ -546,10 +548,6 @@
SHARED_REQUIRES(Locks::mutator_lock_);
private:
- DexToDexCompilationLevel GetDexToDexCompilationlevel(
- Thread* self, Handle<mirror::ClassLoader> class_loader, const DexFile& dex_file,
- const DexFile::ClassDef& class_def) SHARED_REQUIRES(Locks::mutator_lock_);
-
void PreCompile(jobject class_loader, const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings)
REQUIRES(!Locks::mutator_lock_, !compiled_classes_lock_);
@@ -599,12 +597,6 @@
const std::vector<const DexFile*>& dex_files,
ThreadPool* thread_pool, TimingLogger* timings)
REQUIRES(!Locks::mutator_lock_);
- void CompileMethod(Thread* self, const DexFile::CodeItem* code_item, uint32_t access_flags,
- InvokeType invoke_type, uint16_t class_def_idx, uint32_t method_idx,
- jobject class_loader, const DexFile& dex_file,
- DexToDexCompilationLevel dex_to_dex_compilation_level,
- bool compilation_enabled)
- REQUIRES(!compiled_methods_lock_);
// Swap pool and allocator used for native allocations. May be file-backed. Needs to be first
// as other fields rely on this.
@@ -634,8 +626,13 @@
ClassTable compiled_classes_ GUARDED_BY(compiled_classes_lock_);
typedef SafeMap<const MethodReference, CompiledMethod*, MethodReferenceComparator> MethodTable;
- // All method references that this compiler has compiled.
+
+ public:
+ // Lock is public so that non-members can have lock annotations.
mutable Mutex compiled_methods_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+
+ private:
+ // All method references that this compiler has compiled.
MethodTable compiled_methods_ GUARDED_BY(compiled_methods_lock_);
// Number of non-relative patches in all compiled methods. These patches need space
// in the .oat_patches ELF section if requested in the compiler options.
@@ -675,15 +672,6 @@
typedef void (*CompilerCallbackFn)(CompilerDriver& driver);
typedef MutexLock* (*CompilerMutexLockFn)(CompilerDriver& driver);
- typedef CompiledMethod* (*DexToDexCompilerFn)(
- CompilerDriver& driver,
- const DexFile::CodeItem* code_item,
- uint32_t access_flags, InvokeType invoke_type,
- uint32_t class_dex_idx, uint32_t method_idx,
- jobject class_loader, const DexFile& dex_file,
- DexToDexCompilationLevel dex_to_dex_compilation_level);
- DexToDexCompilerFn dex_to_dex_compiler_;
-
void* compiler_context_;
bool support_boot_image_fixup_;
diff --git a/compiler/jit/jit_compiler.cc b/compiler/jit/jit_compiler.cc
index c95bac2..4215f3c 100644
--- a/compiler/jit/jit_compiler.cc
+++ b/compiler/jit/jit_compiler.cc
@@ -153,7 +153,7 @@
CompiledMethod* compiled_method = nullptr;
{
TimingLogger::ScopedTiming t2("Compiling", &logger);
- compiled_method = compiler_driver_->CompileMethod(self, method);
+ compiled_method = compiler_driver_->CompileArtMethod(self, method);
}
{
TimingLogger::ScopedTiming t2("TrimMaps", &logger);