Implement runtime support inlining.
Change-Id: I8608b246a4dfde9959b5b86872f65dfa61646c84
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 18e4842..c526847 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -31,6 +31,8 @@
#include <cstdarg>
#include <stdint.h>
+#include "asm_support.h"
+
namespace art {
//----------------------------------------------------------------------------
@@ -38,16 +40,23 @@
//----------------------------------------------------------------------------
Thread* art_get_current_thread_from_code() {
+#if defined(__i386__)
+ Thread* ptr;
+ asm volatile("movl %%fs:(%1), %0"
+ : "=r"(ptr) // output
+ : "r"(THREAD_SELF_OFFSET) // input
+ :); // clobber
+ return ptr;
+#else
return Thread::Current();
+#endif
}
void art_set_current_thread_from_code(void* thread_object_addr) {
- // TODO: LLVM IR generating something like "r9 = thread_object_addr"
- // UNIMPLEMENTED(WARNING);
}
void art_lock_object_from_code(Object* obj) {
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
DCHECK(obj != NULL); // Assumed to have been checked before entry
obj->MonitorEnter(thread); // May block
DCHECK(thread->HoldsLock(obj));
@@ -56,24 +65,24 @@
}
void art_unlock_object_from_code(Object* obj) {
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
DCHECK(obj != NULL); // Assumed to have been checked before entry
// MonitorExit may throw exception
obj->MonitorExit(thread);
}
void art_test_suspend_from_code() {
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
Runtime::Current()->GetThreadList()->FullSuspendCheck(thread);
}
void art_push_shadow_frame_from_code(void* new_shadow_frame) {
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
thread->PushShadowFrame(static_cast<ShadowFrame*>(new_shadow_frame));
}
void art_pop_shadow_frame_from_code() {
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
thread->PopShadowFrame();
}
@@ -84,23 +93,23 @@
//----------------------------------------------------------------------------
bool art_is_exception_pending_from_code() {
- return Thread::Current()->IsExceptionPending();
+ return art_get_current_thread_from_code()->IsExceptionPending();
}
void art_throw_div_zero_from_code() {
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
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* thread = art_get_current_thread_from_code();
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();
+ Thread* thread = art_get_current_thread_from_code();
// We need the calling method as context for the method_idx
Frame frame = thread->GetTopOfStack();
frame.Next();
@@ -113,7 +122,7 @@
}
void art_throw_null_pointer_exception_from_code(uint32_t dex_pc) {
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
NthCallerVisitor visitor(0);
thread->WalkStack(&visitor);
Method* throw_method = visitor.caller;
@@ -121,7 +130,7 @@
}
void art_throw_stack_overflow_from_code() {
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
if (Runtime::Current()->IsMethodTracingActive()) {
TraceMethodUnwindFromCode(thread);
}
@@ -134,7 +143,7 @@
}
void art_throw_exception_from_code(Object* exception) {
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
if (exception == NULL) {
thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
} else {
@@ -145,11 +154,11 @@
void art_throw_verification_error_from_code(Method* current_method,
int32_t kind,
int32_t ref) {
- ThrowVerificationError(Thread::Current(), current_method, kind, ref);
+ ThrowVerificationError(art_get_current_thread_from_code(), current_method, kind, ref);
}
int32_t art_find_catch_block_from_code(Method* current_method, int32_t dex_pc) {
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
Class* exception_type = thread->GetException()->GetClass();
MethodHelper mh(current_method);
const DexFile::CodeItem* code_item = mh.GetCodeItem();
@@ -182,33 +191,33 @@
//----------------------------------------------------------------------------
Object* art_alloc_object_from_code(uint32_t type_idx, Method* referrer) {
- return AllocObjectFromCode(type_idx, referrer, Thread::Current(), false);
+ return AllocObjectFromCode(type_idx, referrer, art_get_current_thread_from_code(), false);
}
Object* art_alloc_object_from_code_with_access_check(uint32_t type_idx, Method* referrer) {
- return AllocObjectFromCode(type_idx, referrer, Thread::Current(), true);
+ return AllocObjectFromCode(type_idx, referrer, art_get_current_thread_from_code(), true);
}
Object* art_alloc_array_from_code(uint32_t type_idx, Method* referrer, uint32_t length) {
- return AllocArrayFromCode(type_idx, referrer, length, Thread::Current(), false);
+ return AllocArrayFromCode(type_idx, referrer, length, art_get_current_thread_from_code(), false);
}
Object* art_alloc_array_from_code_with_access_check(uint32_t type_idx,
Method* referrer,
uint32_t length) {
- return AllocArrayFromCode(type_idx, referrer, length, Thread::Current(), true);
+ return AllocArrayFromCode(type_idx, referrer, length, art_get_current_thread_from_code(), true);
}
Object* art_check_and_alloc_array_from_code(uint32_t type_idx,
Method* referrer,
uint32_t length) {
- return CheckAndAllocArrayFromCode(type_idx, referrer, length, Thread::Current(), false);
+ return CheckAndAllocArrayFromCode(type_idx, referrer, length, art_get_current_thread_from_code(), false);
}
Object* art_check_and_alloc_array_from_code_with_access_check(uint32_t type_idx,
Method* referrer,
uint32_t length) {
- return CheckAndAllocArrayFromCode(type_idx, referrer, length, Thread::Current(), true);
+ return CheckAndAllocArrayFromCode(type_idx, referrer, length, art_get_current_thread_from_code(), true);
}
static Method* FindMethodHelper(uint32_t method_idx, Object* this_object, Method* caller_method,
@@ -216,13 +225,13 @@
Method* method = FindMethodFast(method_idx, this_object, caller_method, access_check, type);
if (UNLIKELY(method == NULL)) {
method = FindMethodFromCode(method_idx, this_object, caller_method,
- Thread::Current(), access_check, type);
+ art_get_current_thread_from_code(), access_check, type);
if (UNLIKELY(method == NULL)) {
- CHECK(Thread::Current()->IsExceptionPending());
+ CHECK(art_get_current_thread_from_code()->IsExceptionPending());
return 0; // failure
}
}
- DCHECK(!Thread::Current()->IsExceptionPending());
+ DCHECK(!art_get_current_thread_from_code()->IsExceptionPending());
return method;
}
@@ -264,17 +273,17 @@
}
Object* art_initialize_static_storage_from_code(uint32_t type_idx, Method* referrer) {
- return ResolveVerifyAndClinit(type_idx, referrer, Thread::Current(), true, false);
+ return ResolveVerifyAndClinit(type_idx, referrer, art_get_current_thread_from_code(), true, false);
}
Object* art_initialize_type_from_code(uint32_t type_idx, Method* referrer) {
- return ResolveVerifyAndClinit(type_idx, referrer, Thread::Current(), false, false);
+ return ResolveVerifyAndClinit(type_idx, referrer, art_get_current_thread_from_code(), false, false);
}
Object* art_initialize_type_and_verify_access_from_code(uint32_t type_idx, Method* referrer) {
// Called when caller isn't guaranteed to have access to a type and the dex cache may be
// unpopulated
- return ResolveVerifyAndClinit(type_idx, referrer, Thread::Current(), false, true);
+ return ResolveVerifyAndClinit(type_idx, referrer, art_get_current_thread_from_code(), false, true);
}
Object* art_resolve_string_from_code(Method* referrer, uint32_t string_idx) {
@@ -287,7 +296,7 @@
field->Set32(NULL, new_value);
return 0;
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
true, true, true, sizeof(uint32_t));
if (LIKELY(field != NULL)) {
field->Set32(NULL, new_value);
@@ -302,7 +311,7 @@
field->Set64(NULL, new_value);
return 0;
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
true, true, true, sizeof(uint64_t));
if (LIKELY(field != NULL)) {
field->Set64(NULL, new_value);
@@ -317,7 +326,7 @@
field->SetObj(NULL, new_value);
return 0;
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
true, false, true, sizeof(Object*));
if (LIKELY(field != NULL)) {
field->SetObj(NULL, new_value);
@@ -331,7 +340,7 @@
if (LIKELY(field != NULL)) {
return field->Get32(NULL);
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
true, true, false, sizeof(uint32_t));
if (LIKELY(field != NULL)) {
return field->Get32(NULL);
@@ -344,7 +353,7 @@
if (LIKELY(field != NULL)) {
return field->Get64(NULL);
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
true, true, false, sizeof(uint64_t));
if (LIKELY(field != NULL)) {
return field->Get64(NULL);
@@ -357,7 +366,7 @@
if (LIKELY(field != NULL)) {
return field->GetObj(NULL);
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
true, false, false, sizeof(Object*));
if (LIKELY(field != NULL)) {
return field->GetObj(NULL);
@@ -372,7 +381,7 @@
field->Set32(obj, new_value);
return 0;
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
false, true, true, sizeof(uint32_t));
if (LIKELY(field != NULL)) {
field->Set32(obj, new_value);
@@ -388,7 +397,7 @@
field->Set64(obj, new_value);
return 0;
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
false, true, true, sizeof(uint64_t));
if (LIKELY(field != NULL)) {
field->Set64(obj, new_value);
@@ -404,7 +413,7 @@
field->SetObj(obj, new_value);
return 0;
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
false, false, true, sizeof(Object*));
if (LIKELY(field != NULL)) {
field->SetObj(obj, new_value);
@@ -418,7 +427,7 @@
if (LIKELY(field != NULL)) {
return field->Get32(obj);
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
false, true, false, sizeof(uint32_t));
if (LIKELY(field != NULL)) {
return field->Get32(obj);
@@ -431,7 +440,7 @@
if (LIKELY(field != NULL)) {
return field->Get64(obj);
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
false, true, false, sizeof(uint64_t));
if (LIKELY(field != NULL)) {
return field->Get64(obj);
@@ -444,7 +453,7 @@
if (LIKELY(field != NULL)) {
return field->GetObj(obj);
}
- field = FindFieldFromCode(field_idx, referrer, Thread::Current(),
+ field = FindFieldFromCode(field_idx, referrer, art_get_current_thread_from_code(),
false, false, false, sizeof(Object*));
if (LIKELY(field != NULL)) {
return field->GetObj(obj);
@@ -473,10 +482,11 @@
DCHECK(dest_type->IsClass()) << PrettyClass(dest_type);
DCHECK(src_type->IsClass()) << PrettyClass(src_type);
if (UNLIKELY(!dest_type->IsAssignableFrom(src_type))) {
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
- "%s cannot be cast to %s",
- PrettyDescriptor(dest_type).c_str(),
- PrettyDescriptor(src_type).c_str());
+ Thread* thread = art_get_current_thread_from_code();
+ thread->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
+ "%s cannot be cast to %s",
+ PrettyDescriptor(dest_type).c_str(),
+ PrettyDescriptor(src_type).c_str());
}
}
@@ -490,10 +500,11 @@
Class* component_type = array_class->GetComponentType();
Class* element_class = element->GetClass();
if (UNLIKELY(!component_type->IsAssignableFrom(element_class))) {
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
- "%s cannot be stored in an array of type %s",
- PrettyDescriptor(element_class).c_str(),
- PrettyDescriptor(array_class).c_str());
+ Thread* thread = art_get_current_thread_from_code();
+ thread->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
+ "%s cannot be stored in an array of type %s",
+ PrettyDescriptor(element_class).c_str(),
+ PrettyDescriptor(array_class).c_str());
}
return;
}
@@ -566,7 +577,7 @@
// Resolve method.
ClassLinker* linker = Runtime::Current()->GetClassLinker();
called = linker->ResolveMethod(dex_method_idx, caller, !is_virtual);
- if (UNLIKELY(Thread::Current()->IsExceptionPending())) {
+ if (UNLIKELY(art_get_current_thread_from_code()->IsExceptionPending())) {
return NULL;
}
if (LIKELY(called->IsDirect() == !is_virtual)) {
@@ -575,10 +586,11 @@
linker->EnsureInitialized(called_class, true, true);
return called;
} else {
+ Thread* thread = art_get_current_thread_from_code();
// Direct method has been made virtual
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
- "Expected direct method but found virtual: %s",
- PrettyMethod(called, true).c_str());
+ thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
+ "Expected direct method but found virtual: %s",
+ PrettyMethod(called, true).c_str());
return NULL;
}
}
@@ -609,7 +621,7 @@
} else if (called_class->IsInitializing()) {
return linker->GetOatCodeFor(called);
} else {
- DCHECK(Thread::Current()->IsExceptionPending());
+ DCHECK(art_get_current_thread_from_code()->IsExceptionPending());
DCHECK(called_class->IsErroneous());
return NULL;
}
@@ -617,8 +629,9 @@
// 2. The code address is AbstractMethodErrorStub. -> AbstractMethodErrorStub
if (UNLIKELY(code == runtime->GetAbstractMethodErrorStubArray()->GetData())) {
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
- "abstract method \"%s\"", PrettyMethod(called).c_str());
+ art_get_current_thread_from_code()->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
+ "abstract method \"%s\"",
+ PrettyMethod(called).c_str());
return NULL;
}
@@ -638,7 +651,7 @@
va_start(ap, proxy_method);
Object* receiver = va_arg(ap, Object*);
- Thread* thread = Thread::Current();
+ Thread* thread = art_get_current_thread_from_code();
MethodHelper proxy_mh(proxy_method);
const size_t num_params = proxy_mh.NumArgs();