Slow ART.
Run ART with the interpreter for all but boot.oat code.
Change-Id: I1654ecff6769a6c754f713be7580717d5ce07dc1
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 43755b4..55dd7ef 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -14,6 +14,12 @@
# limitations under the License.
#
+ART_SLOW_MODE := false
+ifneq ($(wildcard art/SLOW_ART),)
+$(info Enabling ART_SLOW_MODE because of existence of art/SLOW_ART)
+ART_SLOW_MODE := true
+endif
+
ART_USE_PORTABLE_COMPILER := false
ifneq ($(wildcard art/USE_PORTABLE_COMPILER),)
$(info Enabling ART_USE_PORTABLE_COMPILER because of existence of art/USE_PORTABLE_COMPILER)
@@ -54,6 +60,10 @@
-Wthread-safety \
-fstrict-aliasing
+ifeq ($(ART_SLOW_MODE),true)
+ art_cflags += -DART_SLOW_MODE=1
+endif
+
# TODO: enable -std=gnu++0x for auto support when on Ubuntu 12.04 LTS (Precise Pangolin)
# On 10.04 LTS (Lucid Lynx), it can cause dependencies on GLIBCXX_3.4.14 version symbols.
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 76b3177..39fefcb 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1561,7 +1561,12 @@
// Special case to get oat code without overwriting a trampoline.
const void* ClassLinker::GetOatCodeFor(const mirror::AbstractMethod* method) {
CHECK(Runtime::Current()->IsCompiler() || method->GetDeclaringClass()->IsInitializing());
- return GetOatMethodFor(method).GetCode();
+ const void* result = GetOatMethodFor(method).GetCode();
+ if (result == NULL) {
+ // No code? You must mean to go into the interpreter.
+ result = GetInterpreterEntryPoint();
+ }
+ return result;
}
const void* ClassLinker::GetOatCodeFor(const DexFile& dex_file, uint32_t method_idx) {
@@ -1611,8 +1616,10 @@
}
} else if (method->GetCode() == trampoline) {
const void* code = oat_class->GetOatMethod(method_index).GetCode();
- CHECK(code != NULL)
- << "Resolving a static trampoline but found no code for: " << PrettyMethod(method);
+ if (code == NULL) {
+ // No code? You must mean to go into the interpreter.
+ code = GetInterpreterEntryPoint();
+ }
method->SetCode(code);
}
method_index++;
@@ -1646,6 +1653,11 @@
Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
instrumentation->SaveAndUpdateCode(method.get());
}
+
+ if (method->GetCode() == NULL) {
+ // No code? You must mean to go into the interpreter.
+ method->SetCode(GetInterpreterEntryPoint());
+ }
}
void ClassLinker::LoadClass(const DexFile& dex_file,
diff --git a/src/common_test.h b/src/common_test.h
index 368e4a7..ad6bcb4 100644
--- a/src/common_test.h
+++ b/src/common_test.h
@@ -223,21 +223,24 @@
LOG(INFO) << "MakeExecutable " << PrettyMethod(method)
<< " invoke_stub=" << reinterpret_cast<void*>(method_invoke_stub);
+ const CompiledMethod* compiled_method = NULL;
if (!method->IsAbstract()) {
const mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
const DexFile& dex_file = *dex_cache->GetDexFile();
- const CompiledMethod* compiled_method =
+ compiled_method =
compiler_driver_->GetCompiledMethod(CompilerDriver::MethodReference(&dex_file,
method->GetDexMethodIndex()));
- CHECK(compiled_method != NULL) << PrettyMethod(method);
+#ifndef ART_SLOW_MODE
+ CHECK(compiled_method != NULL) << PrettyMethod(method);
+#endif
+ }
+ if (compiled_method != NULL) {
const std::vector<uint8_t>& code = compiled_method->GetCode();
MakeExecutable(code);
const void* method_code = CompiledMethod::CodePointer(&code[0],
compiled_method->GetInstructionSet());
-
LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
-
OatFile::OatMethod oat_method = CreateOatMethod(method_code,
compiled_method->GetFrameSizeInBytes(),
compiled_method->GetCoreSpillMask(),
@@ -248,8 +251,14 @@
method_invoke_stub);
oat_method.LinkMethod(method);
} else {
- MakeExecutable(runtime_->GetAbstractMethodErrorStubArray());
- const void* method_code = runtime_->GetAbstractMethodErrorStubArray()->GetData();
+ const void* method_code;
+ if (method->IsAbstract()) {
+ MakeExecutable(runtime_->GetAbstractMethodErrorStubArray());
+ method_code = runtime_->GetAbstractMethodErrorStubArray()->GetData();
+ } else {
+ // No code? You must mean to go into the interpreter.
+ method_code = GetInterpreterEntryPoint();
+ }
LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
OatFile::OatMethod oat_method = CreateOatMethod(method_code,
kStackAlignment,
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index cc17031..169790f 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -1655,9 +1655,18 @@
CHECK(compiled_method != NULL);
} else if ((access_flags & kAccAbstract) != 0) {
} else {
- compiled_method = (*compiler_)(*this, code_item, access_flags, invoke_type, class_def_idx,
- method_idx, class_loader, dex_file);
- CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
+ bool dont_compile = false;
+#if ART_SLOW_MODE
+ dont_compile = (image_classes_ == NULL) || (image_classes_->size() == 0);
+ if (dont_compile) {
+ LOG(INFO) << "Not compiling code as ART_SLOW_MODE is enabled";
+ }
+#endif // ART_SLOW_MODE
+ if (!dont_compile) {
+ compiled_method = (*compiler_)(*this, code_item, access_flags, invoke_type, class_def_idx,
+ method_idx, class_loader, dex_file);
+ CHECK(compiled_method != NULL) << PrettyMethod(method_idx, dex_file);
+ }
}
uint64_t duration_ns = NanoTime() - start_ns;
#ifdef ART_USE_PORTABLE_COMPILER
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 3564497..29781bc 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -1927,6 +1927,12 @@
JValue EnterInterpreterFromStub(Thread* self, MethodHelper& mh, const DexFile::CodeItem* code_item,
ShadowFrame& shadow_frame)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK_EQ(self, Thread::Current());
+ if (__builtin_frame_address(0) < self->GetStackEnd()) {
+ ThrowStackOverflowError(self);
+ return JValue();
+ }
+
return Execute(self, mh, code_item, shadow_frame, JValue());
}
diff --git a/src/oat/runtime/support_interpreter.cc b/src/oat/runtime/support_interpreter.cc
index 7f413c3..ada19a3 100644
--- a/src/oat/runtime/support_interpreter.cc
+++ b/src/oat/runtime/support_interpreter.cc
@@ -20,8 +20,8 @@
#include "interpreter/interpreter.h"
#include "mirror/abstract_method-inl.h"
#include "mirror/class-inl.h"
-#include "mirror/object_array-inl.h"
#include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
#include "object_utils.h"
namespace art {
@@ -43,6 +43,7 @@
} else {
sf_.SetVRegLong(cur_reg_, *reinterpret_cast<jlong*>(GetParamAddress()));
}
+ ++cur_reg_;
break;
case Primitive::kPrimNot:
sf_.SetVRegReference(cur_reg_, *reinterpret_cast<mirror::Object**>(GetParamAddress()));
@@ -90,6 +91,16 @@
self->PushManagedStackFragment(&fragment);
self->PushShadowFrame(shadow_frame.get());
self->EndAssertNoThreadSuspension(old_cause);
+
+ if (method->IsStatic() && !method->GetDeclaringClass()->IsInitializing()) {
+ // Ensure static method's class is initialized.
+ if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
+ true, true)) {
+ DCHECK(Thread::Current()->IsExceptionPending());
+ return 0;
+ }
+ }
+
JValue result = interpreter::EnterInterpreterFromStub(self, mh, code_item, *shadow_frame.get());
// Pop transition.
self->PopManagedStackFragment(fragment);
diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc
index 25d7cd2..0cb3fe4 100644
--- a/src/oat/runtime/support_stubs.cc
+++ b/src/oat/runtime/support_stubs.cc
@@ -240,6 +240,7 @@
if (UNLIKELY(code == NULL)) {
// Something went wrong in ResolveMethod or EnsureInitialized,
// go into deliver exception with the pending exception in r0
+ CHECK(thread->IsExceptionPending());
code = reinterpret_cast<void*>(art_quick_deliver_exception_from_code);
regs[0] = reinterpret_cast<uintptr_t>(thread->GetException());
thread->ClearException();