Initial runtime support routines for ART LLVM.

Change-Id: Id5bb87685e1a95444bdd7a676f68b378e1b88d3f
diff --git a/build/Android.common.mk b/build/Android.common.mk
index 73c5a00..7680f06 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -200,6 +200,7 @@
 	src/reference_table.cc \
 	src/reflection.cc \
 	src/runtime.cc \
+	src/runtime_support.cc \
 	src/signal_catcher.cc \
 	src/space.cc \
 	src/stack.cc \
@@ -211,7 +212,6 @@
 	src/thread.cc \
 	src/thread_list.cc \
 	src/trace.cc \
-	src/runtime_support.cc \
 	src/utf.cc \
 	src/utils.cc \
 	src/zip_archive.cc
@@ -227,6 +227,7 @@
 	src/compiler_llvm/ir_builder.cc \
 	src/compiler_llvm/jni_compiler.cc \
 	src/compiler_llvm/method_compiler.cc \
+	src/compiler_llvm/runtime_support_llvm.cc \
 	src/compiler_llvm/upcall_compiler.cc \
 	src/compiler_llvm/utils_llvm.cc
 else
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
new file mode 100644
index 0000000..e3a981e
--- /dev/null
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -0,0 +1,145 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+#include "class_linker.h"
+#include "dex_verifier.h"
+#include "object.h"
+#include "object_utils.h"
+#include "runtime_support_llvm.h"
+#include "thread.h"
+
+#include <stdint.h>
+
+namespace art {
+
+//----------------------------------------------------------------------------
+// Thread
+//----------------------------------------------------------------------------
+
+void art_push_shadow_frame_from_code(void* new_shadow_frame) {
+  Thread* thread = Thread::Current();
+  thread->PushSirt(
+      static_cast<StackIndirectReferenceTable*>(new_shadow_frame)
+                   );
+}
+
+void art_pop_shadow_frame_from_code() {
+  Thread* thread = Thread::Current();
+  thread->PopSirt();
+}
+
+
+//----------------------------------------------------------------------------
+// Exception
+//----------------------------------------------------------------------------
+
+static std::string MethodNameFromIndex(const Method* method,
+                                       uint32_t ref,
+                                       verifier::VerifyErrorRefType ref_type,
+                                       bool access) {
+  CHECK_EQ(static_cast<int>(ref_type),
+           static_cast<int>(verifier::VERIFY_ERROR_REF_METHOD));
+
+  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  const DexFile& dex_file =
+      class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
+
+  const DexFile::MethodId& id = dex_file.GetMethodId(ref);
+  std::string class_name(
+      PrettyDescriptor(dex_file.GetMethodDeclaringClassDescriptor(id))
+                         );
+  const char* method_name = dex_file.StringDataByIdx(id.name_idx_);
+  if (!access) {
+    return class_name + "." + method_name;
+  }
+
+  std::string result;
+  result += "tried to access method ";
+  result += class_name + "." + method_name + ":" +
+      dex_file.CreateMethodSignature(id.proto_idx_, NULL);
+  result += " from class ";
+  result += PrettyDescriptor(method->GetDeclaringClass());
+  return result;
+}
+
+bool art_is_exception_pending_from_code() {
+  return Thread::Current()->IsExceptionPending();
+}
+
+void art_throw_div_zero_from_code() {
+  Thread* thread = Thread::Current();
+  thread->ThrowNewException("Ljava/lang/ArithmeticException;",
+                            "divide by zero");
+}
+
+void art_throw_array_bounds_from_code(int32_t length, int32_t index) {
+  Thread* thread = Thread::Current();
+  thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
+                             "length=%d; index=%d", length, index);
+}
+
+void art_throw_no_such_method_from_code(int32_t method_idx) {
+  Thread* thread = Thread::Current();
+  // We need the calling method as context for the method_idx
+  Frame frame = thread->GetTopOfStack();
+  frame.Next();
+  Method* method = frame.GetMethod();
+  thread->ThrowNewException("Ljava/lang/NoSuchMethodError;",
+                            MethodNameFromIndex(method,
+                                                method_idx,
+                                                verifier::VERIFY_ERROR_REF_METHOD,
+                                                false).c_str());
+}
+
+void art_throw_null_pointer_exception_from_code() {
+  Thread* thread = Thread::Current();
+  thread->ThrowNewException("Ljava/lang/NullPointerException;", NULL);
+}
+
+void art_throw_stack_overflow_from_code(void*) {
+  Thread* thread = Thread::Current();
+  thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;",
+      "stack size %zdkb; default stack size: %zdkb",
+      thread->GetStackSize() / KB,
+      Runtime::Current()->GetDefaultStackSize() / KB);
+}
+
+void art_throw_exception_from_code(Object* exception) {
+  Thread* thread = Thread::Current();
+  thread->SetException(static_cast<Throwable*>(exception));
+}
+
+int32_t art_find_catch_block_from_code(Object* exception, int32_t dex_pc) {
+  Class* exception_type = exception->GetClass();
+  Method* current_method = Thread::Current()->GetCurrentMethod();
+  MethodHelper mh(current_method);
+  const DexFile::CodeItem* code_item = mh.GetCodeItem();
+  int iter_index = 0;
+  // Iterate over the catch handlers associated with dex_pc
+  for (CatchHandlerIterator it(*code_item, dex_pc); it.HasNext(); it.Next()) {
+    uint16_t iter_type_idx = it.GetHandlerTypeIndex();
+    // Catch all case
+    if (iter_type_idx == DexFile::kDexNoIndex16) {
+      return iter_index;
+    }
+    // Does this catch exception type apply?
+    Class* iter_exception_type = mh.GetDexCacheResolvedType(iter_type_idx);
+    if (iter_exception_type == NULL) {
+      // The verifier should take care of resolving all exception classes early
+      LOG(WARNING) << "Unresolved exception class when finding catch block: "
+          << mh.GetTypeDescriptorFromTypeIdx(iter_type_idx);
+    } else if (iter_exception_type->IsAssignableFrom(exception_type)) {
+      return iter_index;
+    }
+    ++iter_index;
+  }
+  // Handler not found
+  return -1;
+}
+
+void art_test_suspend_from_code() {
+}
+
+void art_set_current_thread_from_code(void* thread_object_addr) {
+}
+
+}  // namespace art
diff --git a/src/compiler_llvm/runtime_support_llvm.h b/src/compiler_llvm/runtime_support_llvm.h
new file mode 100644
index 0000000..548222a
--- /dev/null
+++ b/src/compiler_llvm/runtime_support_llvm.h
@@ -0,0 +1,20 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+#ifndef ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_LLVM_H_
+#define ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_LLVM_H_
+
+namespace art {
+
+void art_push_shadow_frame_from_code(void* new_shadow_frame);
+
+void art_pop_shadow_frame_from_code();
+
+bool art_is_exception_pending_from_code();
+
+void art_test_suspend_from_code();
+
+void art_set_current_thread_from_code(void* thread_object_addr);
+
+}  // namespace art
+
+#endif  // ART_SRC_COMPILER_LLVM_RUNTIME_SUPPORT_LLVM_H_
diff --git a/src/compiler_llvm/utils_llvm.cc b/src/compiler_llvm/utils_llvm.cc
index 405d7e2..93fad37 100644
--- a/src/compiler_llvm/utils_llvm.cc
+++ b/src/compiler_llvm/utils_llvm.cc
@@ -26,6 +26,8 @@
 #include "object.h"
 #include "object_utils.h"
 
+#include "runtime_support_llvm.h"
+
 namespace art {
 
 std::string MangleForLLVM(const std::string& s) {
@@ -105,23 +107,6 @@
   return stub_name;
 }
 
-// TODO: Remove these when art_llvm.ll runtime support is ready.
-void art_push_shadow_frame_from_code(void* frame) {
-}
-
-void art_pop_shadow_frame_from_code() {
-}
-
-int art_is_exception_pending_from_code() {
-  return 0;
-}
-
-void art_test_suspend_from_code() {
-}
-
-void art_set_current_thread_from_code(void* thread_object_addr) {
-}
-
 // Linker's call back function. Added some for debugging.
 void* find_sym(void* context, char const* name) {
   struct func_entry_t {
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index de07c0c..607542e 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -323,7 +323,7 @@
 }
 
 static std::string MethodNameFromIndex(const Method* method, uint32_t ref,
-                                verifier::VerifyErrorRefType ref_type, bool access) {
+                                       verifier::VerifyErrorRefType ref_type, bool access) {
   CHECK_EQ(static_cast<int>(ref_type), static_cast<int>(verifier::VERIFY_ERROR_REF_METHOD));
 
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
diff --git a/src/stack_indirect_reference_table.h b/src/stack_indirect_reference_table.h
index 5f37294..77cbddc 100644
--- a/src/stack_indirect_reference_table.h
+++ b/src/stack_indirect_reference_table.h
@@ -88,8 +88,13 @@
  private:
   StackIndirectReferenceTable() {}
 
-  size_t number_of_references_;
   StackIndirectReferenceTable* link_;
+#if defined(ART_USE_LLVM_COMPILER)
+  Object* method_;
+  uint32_t line_num_;
+#endif
+
+  size_t number_of_references_;
 
   // number_of_references_ are available if this is allocated and filled in by jni_compiler.
   Object* references_[1];