Initial runtime support routines for ART LLVM.
Change-Id: Id5bb87685e1a95444bdd7a676f68b378e1b88d3f
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];