summaryrefslogtreecommitdiffstats
path: root/runtime/runtime.cc
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2015-02-17 10:38:49 -0800
committerMathieu Chartier <mathieuc@google.com>2015-02-23 16:45:49 -0800
commit2535abe7d1fcdd0e6aca782b1f1932a703ed50a4 (patch)
tree140026ff9638ff34050680b6c706b82fa1740b56 /runtime/runtime.cc
parent38fee8ef4bc0f4dbe2c6d1f5585895f0c4d16984 (diff)
downloadart-2535abe7d1fcdd0e6aca782b1f1932a703ed50a4.zip
art-2535abe7d1fcdd0e6aca782b1f1932a703ed50a4.tar.gz
art-2535abe7d1fcdd0e6aca782b1f1932a703ed50a4.tar.bz2
Add JIT
Currently disabled by default unless -Xjit is passed in. The proposed JIT is a method JIT which works by utilizing interpreter instrumentation to request compilation of hot methods async during runtime. JIT options: -Xjit / -Xnojit -Xjitcodecachesize:N -Xjitthreshold:integervalue The JIT has a shared copy of a compiler driver which is accessed by worker threads to compile individual methods. Added JIT code cache and data cache, currently sized at 2 MB capacity by default. Most apps will only fill a small fraction of this cache however. Added support to the compiler for compiling interpreter quickened byte codes. Added test target ART_TEST_JIT=TRUE and --jit for run-test. TODO: Clean up code cache. Delete compiled methods after they are added to code cache. Add more optimizations related to runtime checks e.g. direct pointers for invokes. Add method recompilation. Move instrumentation to DexFile to improve performance and reduce memory usage. Bug: 17950037 Change-Id: Ifa5b2684a2d5059ec5a5210733900aafa3c51bca
Diffstat (limited to 'runtime/runtime.cc')
-rw-r--r--runtime/runtime.cc101
1 files changed, 78 insertions, 23 deletions
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index f38f65e..749418d 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -65,6 +65,8 @@
#include "image.h"
#include "instrumentation.h"
#include "intern_table.h"
+#include "interpreter/interpreter.h"
+#include "jit/jit.h"
#include "jni_internal.h"
#include "mirror/array.h"
#include "mirror/art_field-inl.h"
@@ -225,6 +227,12 @@ Runtime::~Runtime() {
// Make sure to let the GC complete if it is running.
heap_->WaitForGcToComplete(gc::kGcCauseBackground, self);
heap_->DeleteThreadPool();
+ if (jit_.get() != nullptr) {
+ VLOG(jit) << "Deleting jit thread pool";
+ // Delete thread pool before the thread list since we don't want to wait forever on the
+ // JIT compiler threads.
+ jit_->DeleteThreadPool();
+ }
// Make sure our internal threads are dead before we start tearing down things they're using.
Dbg::StopJdwp();
@@ -233,6 +241,13 @@ Runtime::~Runtime() {
// Make sure all other non-daemon threads have terminated, and all daemon threads are suspended.
delete thread_list_;
+ // Delete the JIT after thread list to ensure that there is no remaining threads which could be
+ // accessing the instrumentation when we delete it.
+ if (jit_.get() != nullptr) {
+ VLOG(jit) << "Deleting jit";
+ jit_.reset(nullptr);
+ }
+
// Shutdown the fault manager if it was initialized.
fault_manager.Shutdown();
@@ -455,17 +470,24 @@ bool Runtime::Start() {
started_ = true;
- // Use !IsCompiler so that we get test coverage, tests are never the zygote.
- if (!IsCompiler()) {
+ // Use !IsAotCompiler so that we get test coverage, tests are never the zygote.
+ if (!IsAotCompiler()) {
ScopedObjectAccess soa(self);
gc::space::ImageSpace* image_space = heap_->GetImageSpace();
if (image_space != nullptr) {
- Runtime::Current()->GetInternTable()->AddImageStringsToTable(image_space);
- Runtime::Current()->GetClassLinker()->MoveImageClassesToClassTable();
+ GetInternTable()->AddImageStringsToTable(image_space);
+ GetClassLinker()->MoveImageClassesToClassTable();
}
}
- if (!IsImageDex2OatEnabled() || !Runtime::Current()->GetHeap()->HasImageSpace()) {
+ // If we are the zygote then we need to wait until after forking to create the code cache due to
+ // SELinux restrictions on r/w/x memory regions.
+ if (!IsZygote() && jit_.get() != nullptr) {
+ jit_->CreateInstrumentationCache(jit_options_->GetCompileThreshold());
+ jit_->CreateThreadPool();
+ }
+
+ if (!IsImageDex2OatEnabled() || !GetHeap()->HasImageSpace()) {
ScopedObjectAccess soa(self);
StackHandleScope<1> hs(soa.Self());
auto klass(hs.NewHandle<mirror::Class>(mirror::Class::GetJavaLangClass()));
@@ -584,8 +606,14 @@ void Runtime::DidForkFromZygote(JNIEnv* env, NativeBridgeAction action, const ch
}
}
- // Create the thread pool.
+ // Create the thread pools.
heap_->CreateThreadPool();
+ if (jit_options_.get() != nullptr && jit_.get() == nullptr) {
+ // Create the JIT if the flag is set and we haven't already create it (happens for run-tests).
+ CreateJit();
+ jit_->CreateInstrumentationCache(jit_options_->GetCompileThreshold());
+ jit_->CreateThreadPool();
+ }
StartSignalCatcher();
@@ -806,6 +834,17 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized)
Dbg::ConfigureJdwp(runtime_options.GetOrDefault(Opt::JdwpOptions));
}
+ if (!IsCompiler()) {
+ // If we are already the compiler at this point, we must be dex2oat. Don't create the jit in
+ // this case.
+ // If runtime_options doesn't have UseJIT set to true then CreateFromRuntimeArguments returns
+ // nullptr and we don't create the jit.
+ jit_options_.reset(jit::JitOptions::CreateFromRuntimeArguments(runtime_options));
+ }
+ if (!IsZygote() && jit_options_.get() != nullptr) {
+ CreateJit();
+ }
+
BlockSignals();
InitPlatformSignalHandlers();
@@ -1054,26 +1093,26 @@ void Runtime::InitThreadGroups(Thread* self) {
env->NewGlobalRef(env->GetStaticObjectField(
WellKnownClasses::java_lang_ThreadGroup,
WellKnownClasses::java_lang_ThreadGroup_mainThreadGroup));
- CHECK(main_thread_group_ != NULL || IsCompiler());
+ CHECK(main_thread_group_ != NULL || IsAotCompiler());
system_thread_group_ =
env->NewGlobalRef(env->GetStaticObjectField(
WellKnownClasses::java_lang_ThreadGroup,
WellKnownClasses::java_lang_ThreadGroup_systemThreadGroup));
- CHECK(system_thread_group_ != NULL || IsCompiler());
+ CHECK(system_thread_group_ != NULL || IsAotCompiler());
}
jobject Runtime::GetMainThreadGroup() const {
- CHECK(main_thread_group_ != NULL || IsCompiler());
+ CHECK(main_thread_group_ != NULL || IsAotCompiler());
return main_thread_group_;
}
jobject Runtime::GetSystemThreadGroup() const {
- CHECK(system_thread_group_ != NULL || IsCompiler());
+ CHECK(system_thread_group_ != NULL || IsAotCompiler());
return system_thread_group_;
}
jobject Runtime::GetSystemClassLoader() const {
- CHECK(system_class_loader_ != NULL || IsCompiler());
+ CHECK(system_class_loader_ != NULL || IsAotCompiler());
return system_class_loader_;
}
@@ -1329,7 +1368,7 @@ mirror::ArtMethod* Runtime::CreateImtConflictMethod() {
// TODO: use a special method for imt conflict method saves.
method->SetDexMethodIndex(DexFile::kDexNoIndex);
// When compiling, the code pointer will get set later when the image is loaded.
- if (runtime->IsCompiler()) {
+ if (runtime->IsAotCompiler()) {
size_t pointer_size = GetInstructionSetPointerSize(instruction_set_);
method->SetEntryPointFromQuickCompiledCodePtrSize(nullptr, pointer_size);
} else {
@@ -1338,6 +1377,10 @@ mirror::ArtMethod* Runtime::CreateImtConflictMethod() {
return method.Get();
}
+void Runtime::SetImtConflictMethod(mirror::ArtMethod* method) {
+ imt_conflict_method_ = GcRoot<mirror::ArtMethod>(method);
+}
+
mirror::ArtMethod* Runtime::CreateResolutionMethod() {
Thread* self = Thread::Current();
Runtime* runtime = Runtime::Current();
@@ -1348,7 +1391,7 @@ mirror::ArtMethod* Runtime::CreateResolutionMethod() {
// TODO: use a special method for resolution method saves
method->SetDexMethodIndex(DexFile::kDexNoIndex);
// When compiling, the code pointer will get set later when the image is loaded.
- if (runtime->IsCompiler()) {
+ if (runtime->IsAotCompiler()) {
size_t pointer_size = GetInstructionSetPointerSize(instruction_set_);
method->SetEntryPointFromQuickCompiledCodePtrSize(nullptr, pointer_size);
} else {
@@ -1479,14 +1522,14 @@ void Runtime::StartProfiler(const char* profile_output_filename) {
// Transaction support.
void Runtime::EnterTransactionMode(Transaction* transaction) {
- DCHECK(IsCompiler());
+ DCHECK(IsAotCompiler());
DCHECK(transaction != nullptr);
DCHECK(!IsActiveTransaction());
preinitialization_transaction_ = transaction;
}
void Runtime::ExitTransactionMode() {
- DCHECK(IsCompiler());
+ DCHECK(IsAotCompiler());
DCHECK(IsActiveTransaction());
preinitialization_transaction_ = nullptr;
}
@@ -1546,51 +1589,51 @@ void Runtime::RecordWriteFieldShort(mirror::Object* obj, MemberOffset field_offs
void Runtime::RecordWriteField32(mirror::Object* obj, MemberOffset field_offset,
uint32_t value, bool is_volatile) const {
- DCHECK(IsCompiler());
+ DCHECK(IsAotCompiler());
DCHECK(IsActiveTransaction());
preinitialization_transaction_->RecordWriteField32(obj, field_offset, value, is_volatile);
}
void Runtime::RecordWriteField64(mirror::Object* obj, MemberOffset field_offset,
uint64_t value, bool is_volatile) const {
- DCHECK(IsCompiler());
+ DCHECK(IsAotCompiler());
DCHECK(IsActiveTransaction());
preinitialization_transaction_->RecordWriteField64(obj, field_offset, value, is_volatile);
}
void Runtime::RecordWriteFieldReference(mirror::Object* obj, MemberOffset field_offset,
mirror::Object* value, bool is_volatile) const {
- DCHECK(IsCompiler());
+ DCHECK(IsAotCompiler());
DCHECK(IsActiveTransaction());
preinitialization_transaction_->RecordWriteFieldReference(obj, field_offset, value, is_volatile);
}
void Runtime::RecordWriteArray(mirror::Array* array, size_t index, uint64_t value) const {
- DCHECK(IsCompiler());
+ DCHECK(IsAotCompiler());
DCHECK(IsActiveTransaction());
preinitialization_transaction_->RecordWriteArray(array, index, value);
}
void Runtime::RecordStrongStringInsertion(mirror::String* s) const {
- DCHECK(IsCompiler());
+ DCHECK(IsAotCompiler());
DCHECK(IsActiveTransaction());
preinitialization_transaction_->RecordStrongStringInsertion(s);
}
void Runtime::RecordWeakStringInsertion(mirror::String* s) const {
- DCHECK(IsCompiler());
+ DCHECK(IsAotCompiler());
DCHECK(IsActiveTransaction());
preinitialization_transaction_->RecordWeakStringInsertion(s);
}
void Runtime::RecordStrongStringRemoval(mirror::String* s) const {
- DCHECK(IsCompiler());
+ DCHECK(IsAotCompiler());
DCHECK(IsActiveTransaction());
preinitialization_transaction_->RecordStrongStringRemoval(s);
}
void Runtime::RecordWeakStringRemoval(mirror::String* s) const {
- DCHECK(IsCompiler());
+ DCHECK(IsAotCompiler());
DCHECK(IsActiveTransaction());
preinitialization_transaction_->RecordWeakStringRemoval(s);
}
@@ -1622,4 +1665,16 @@ void Runtime::AddCurrentRuntimeFeaturesAsDex2OatArguments(std::vector<std::strin
void Runtime::UpdateProfilerState(int state) {
VLOG(profiler) << "Profiler state updated to " << state;
}
+
+void Runtime::CreateJit() {
+ CHECK(jit_options_.get() != nullptr);
+ std::string error_msg;
+ jit_.reset(jit::Jit::Create(jit_options_.get(), &error_msg));
+ if (jit_.get() != nullptr) {
+ compiler_callbacks_ = jit_->GetCompilerCallbacks();
+ } else {
+ LOG(WARNING) << "Failed to create JIT " << error_msg;
+ }
+}
+
} // namespace art