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();