Introduce -Xint flag for ART.
Change-Id: I0f7d8c0b0f33e77ca2d3fbf05b7a16fedb86a545
diff --git a/src/object.cc b/src/object.cc
index aaaa245..4eb5066 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -657,33 +657,41 @@
// Pass everything as arguments.
AbstractMethod::InvokeStub* stub = GetInvokeStub();
-
if (UNLIKELY(!Runtime::Current()->IsStarted())){
- LOG(INFO) << "Not invoking " << PrettyMethod(this) << " for a runtime that isn't started.";
+ LOG(INFO) << "Not invoking " << PrettyMethod(this) << " for a runtime that isn't started";
if (result != NULL) {
result->SetJ(0);
}
} else {
- if (GetCode() != NULL && stub != NULL) {
- bool log = false;
- if (log) {
- LOG(INFO) << StringPrintf("invoking %s code=%p stub=%p",
+ bool interpret = self->ReadFlag(kEnterInterpreter);
+ const bool kLogInvocationStartAndReturn = false;
+ if (!interpret && GetCode() != NULL && stub != NULL) {
+ if (kLogInvocationStartAndReturn) {
+ LOG(INFO) << StringPrintf("Invoking '%s' code=%p stub=%p",
PrettyMethod(this).c_str(), GetCode(), stub);
}
(*stub)(this, receiver, self, args, result);
- if (log) {
- LOG(INFO) << StringPrintf("returned %s code=%p stub=%p",
+ if (kLogInvocationStartAndReturn) {
+ LOG(INFO) << StringPrintf("Returned '%s' code=%p stub=%p",
PrettyMethod(this).c_str(), GetCode(), stub);
}
} else {
- LOG(INFO) << "Not invoking " << PrettyMethod(this)
- << " code=" << reinterpret_cast<const void*>(GetCode())
- << " stub=" << reinterpret_cast<void*>(stub);
const bool kInterpretMethodsWithNoCode = false;
- if (kInterpretMethodsWithNoCode) {
+ if (interpret || kInterpretMethodsWithNoCode) {
+ if (kLogInvocationStartAndReturn) {
+ LOG(INFO) << "Interpreting " << PrettyMethod(this) << "'";
+ }
art::interpreter::EnterInterpreterFromInvoke(self, this, receiver, args, result);
- } else if (result != NULL) {
+ if (kLogInvocationStartAndReturn) {
+ LOG(INFO) << "Returned '" << PrettyMethod(this) << "'";
+ }
+ } else {
+ LOG(INFO) << "Not invoking '" << PrettyMethod(this)
+ << "' code=" << reinterpret_cast<const void*>(GetCode())
+ << " stub=" << reinterpret_cast<void*>(stub);
+ if (result != NULL) {
result->SetJ(0);
+ }
}
}
}
diff --git a/src/runtime.cc b/src/runtime.cc
index 4cc3b4f..ec2f569 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -364,6 +364,7 @@
parsed->is_compiler_ = false;
parsed->is_zygote_ = false;
+ parsed->interpreter_only_ = false;
parsed->is_concurrent_gc_enabled_ = true;
parsed->jni_globals_max_ = 0;
@@ -508,6 +509,8 @@
parsed->is_compiler_ = true;
} else if (option == "-Xzygote") {
parsed->is_zygote_ = true;
+ } else if (option == "-Xint") {
+ parsed->interpreter_only_ = true;
} else if (StartsWith(option, "-Xgc:")) {
std::vector<std::string> gc_options;
Split(option.substr(strlen("-Xgc:")), ',', gc_options);
@@ -756,6 +759,7 @@
is_compiler_ = options->is_compiler_;
is_zygote_ = options->is_zygote_;
+ interpreter_only_ = options->interpreter_only_;
is_concurrent_gc_enabled_ = options->is_concurrent_gc_enabled_;
vfprintf_ = options->hook_vfprintf_;
diff --git a/src/runtime.h b/src/runtime.h
index d2238ae..79c0592 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -76,6 +76,7 @@
std::string jni_trace_;
bool is_compiler_;
bool is_zygote_;
+ bool interpreter_only_;
bool is_concurrent_gc_enabled_;
size_t heap_initial_size_;
size_t heap_maximum_size_;
@@ -112,6 +113,10 @@
return is_zygote_;
}
+ bool InterpreterOnly() const {
+ return interpreter_only_;
+ }
+
bool IsConcurrentGcEnabled() const {
return is_concurrent_gc_enabled_;
}
@@ -377,6 +382,7 @@
bool is_compiler_;
bool is_zygote_;
+ bool interpreter_only_;
bool is_concurrent_gc_enabled_;
// The host prefix is used during cross compilation. It is removed
diff --git a/src/thread.cc b/src/thread.cc
index 744a8aa..8037886 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -288,13 +288,14 @@
// we can handshake with the corresponding native thread when it's ready.) Check this native
// thread hasn't been through here already...
CHECK(Thread::Current() == NULL);
-
SetUpAlternateSignalStack();
InitCpu();
InitFunctionPointers();
InitCardTable();
InitTid();
-
+ if (Runtime::Current()->InterpreterOnly()) {
+ AtomicSetFlag(kEnterInterpreter);
+ }
// Set pthread_self_ ahead of pthread_setspecific, that makes Thread::Current function, this
// avoids pthread_self_ ever being invalid when discovered from Thread::Current().
pthread_self_ = pthread_self();
diff --git a/src/thread.h b/src/thread.h
index 3eabe08..be7c673 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -96,10 +96,11 @@
};
enum ThreadFlag {
- kSuspendRequest = 1, // If set implies that suspend_count_ > 0.
- kExceptionPending = 2, // If set implies that exception_ != NULL.
- kEnterInterpreter = 4, // Instruct managed code it should enter the interpreter.
- kCheckpointRequest = 8, // Request that the thread do some set of work.
+ kSuspendRequest = 1, // If set implies that suspend_count_ > 0 and the Thread should enter the
+ // safepoint handler.
+ kCheckpointRequest = 2, // Request that the thread do some checkpoint work and then continue.
+ kExceptionPending = 4, // If set implies that exception_ != NULL.
+ kEnterInterpreter = 8, // Instruct managed code it should enter the interpreter.
};
class PACKED Thread {