Move from code field routines to runtime support.
Add support for exceptions from these routines. Use a macro for pending
exception delivery. Fix bug in object_test where the signature of a
FromCode function had changed.
Change-Id: If486eff8659e5f6bb38d95b1139e8981656e4fb0
diff --git a/src/asm_support.h b/src/asm_support.h
index 305e17d..19a930d 100644
--- a/src/asm_support.h
+++ b/src/asm_support.h
@@ -10,6 +10,8 @@
#define SUSPEND_CHECK_INTERVAL (1000)
// Offset of field Thread::suspend_count_ verified in InitCpu
#define THREAD_SUSPEND_COUNT_OFFSET 388
+// Offset of field Thread::suspend_count_ verified in InitCpu
+#define THREAD_EXCEPTION_OFFSET 384
#elif defined(__i386__)
// Offset of field Thread::self_ verified in InitCpu
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index 025f9e3..264b669 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -9,6 +9,7 @@
#include "dex_cache.h"
#include "dex_file.h"
#include "heap.h"
+#include "runtime_support.h"
namespace art {
@@ -924,8 +925,6 @@
EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2));
}
-extern Class* InitializeStaticStorage(uint32_t type_idx, const Method* referrer, Thread* self);
-
TEST_F(ClassLinkerTest, InitializeStaticStorageFromCode) {
// pretend we are trying to get the static storage for the StaticsFromCode class.
diff --git a/src/object.cc b/src/object.cc
index 9f225d7..58ffa6b 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -123,60 +123,6 @@
GetType(); // Sets type_ as a side-effect. May throw.
}
-Field* Field::FindInstanceFieldFromCode(uint32_t field_idx, const Method* referrer) {
- return FindFieldFromCode(field_idx, referrer, false);
-}
-
-Field* Field::FindStaticFieldFromCode(uint32_t field_idx, const Method* referrer) {
- return FindFieldFromCode(field_idx, referrer, true);
-}
-
-Field* Field::FindFieldFromCode(uint32_t field_idx, const Method* referrer, bool is_static) {
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- Field* f = class_linker->ResolveField(field_idx, referrer, is_static);
- if (f != NULL) {
- Class* c = f->GetDeclaringClass();
- // If the class is already initializing, we must be inside <clinit>, or
- // we'd still be waiting for the lock.
- if (c->GetStatus() == Class::kStatusInitializing || class_linker->EnsureInitialized(c, true)) {
- return f;
- }
- }
- UNIMPLEMENTED(FATAL) << "throw an error and unwind";
- return NULL;
-}
-
-uint32_t Field::Get32StaticFromCode(uint32_t field_idx, const Method* referrer) {
- Field* field = FindStaticFieldFromCode(field_idx, referrer);
- DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t));
- return field->Get32(NULL);
-}
-void Field::Set32StaticFromCode(uint32_t field_idx, const Method* referrer, uint32_t new_value) {
- Field* field = FindStaticFieldFromCode(field_idx, referrer);
- DCHECK(field->GetType()->PrimitiveSize() == sizeof(int32_t));
- field->Set32(NULL, new_value);
-}
-uint64_t Field::Get64StaticFromCode(uint32_t field_idx, const Method* referrer) {
- Field* field = FindStaticFieldFromCode(field_idx, referrer);
- DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t));
- return field->Get64(NULL);
-}
-void Field::Set64StaticFromCode(uint32_t field_idx, const Method* referrer, uint64_t new_value) {
- Field* field = FindStaticFieldFromCode(field_idx, referrer);
- DCHECK(field->GetType()->PrimitiveSize() == sizeof(int64_t));
- field->Set64(NULL, new_value);
-}
-Object* Field::GetObjStaticFromCode(uint32_t field_idx, const Method* referrer) {
- Field* field = FindStaticFieldFromCode(field_idx, referrer);
- DCHECK(!field->GetType()->IsPrimitive());
- return field->GetObj(NULL);
-}
-void Field::SetObjStaticFromCode(uint32_t field_idx, const Method* referrer, Object* new_value) {
- Field* field = FindStaticFieldFromCode(field_idx, referrer);
- DCHECK(!field->GetType()->IsPrimitive());
- field->SetObj(NULL, new_value);
-}
-
uint32_t Field::Get32(const Object* object) const {
CHECK((object == NULL) == IsStatic());
if (IsStatic()) {
diff --git a/src/object.h b/src/object.h
index d8eb179..80a4ce9 100644
--- a/src/object.h
+++ b/src/object.h
@@ -471,10 +471,6 @@
return MemberOffset(OFFSETOF_MEMBER(Field, offset_));
}
- static Field* FindInstanceFieldFromCode(uint32_t field_idx, const Method* referrer);
- static Field* FindStaticFieldFromCode(uint32_t field_idx, const Method* referrer);
- static Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, bool is_static);
-
MemberOffset GetOffsetDuringLinking() const;
void SetOffset(MemberOffset num_bytes);
@@ -499,20 +495,13 @@
Object* GetObject(const Object* object) const;
void SetObject(Object* object, const Object* l) const;
- // Slow path routines for static field access when field was unresolved at
- // compile time
- static uint32_t Get32StaticFromCode(uint32_t field_idx,
- const Method* referrer);
- static void Set32StaticFromCode(uint32_t field_idx, const Method* referrer,
- uint32_t new_value);
- static uint64_t Get64StaticFromCode(uint32_t field_idx,
- const Method* referrer);
- static void Set64StaticFromCode(uint32_t field_idx, const Method* referrer,
- uint64_t new_value);
- static Object* GetObjStaticFromCode(uint32_t field_idx,
- const Method* referrer);
- static void SetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
- Object* new_value);
+ // raw field accesses
+ uint32_t Get32(const Object* object) const;
+ void Set32(Object* object, uint32_t new_value) const;
+ uint64_t Get64(const Object* object) const;
+ void Set64(Object* object, uint64_t new_value) const;
+ Object* GetObj(const Object* object) const;
+ void SetObj(Object* object, const Object* new_value) const;
static Class* GetJavaLangReflectField() {
DCHECK(java_lang_reflect_Field_ != NULL);
@@ -529,14 +518,6 @@
void InitJavaFields();
private:
- // private implementation of field access using raw data
- uint32_t Get32(const Object* object) const;
- void Set32(Object* object, uint32_t new_value) const;
- uint64_t Get64(const Object* object) const;
- void Set64(Object* object, uint64_t new_value) const;
- Object* GetObj(const Object* object) const;
- void SetObj(Object* object, const Object* new_value) const;
-
void InitJavaFieldsLocked();
// Field order required by test "ValidateFieldOrderOfJavaCppUnionClasses".
diff --git a/src/object_test.cc b/src/object_test.cc
index 6979b75..6b1f818 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -10,6 +10,7 @@
#include "common_test.h"
#include "dex_file.h"
#include "heap.h"
+#include "runtime_support.h"
namespace art {
@@ -162,14 +163,12 @@
TestPrimitiveArray<ShortArray>(class_linker_);
}
-extern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method,
- int32_t component_count);
TEST_F(ObjectTest, CheckAndAllocArrayFromCode) {
// pretend we are trying to call 'new char[3]' from String.toCharArray
Class* java_util_Arrays = class_linker_->FindSystemClass("Ljava/util/Arrays;");
Method* sort = java_util_Arrays->FindDirectMethod("sort", "([I)V");
uint32_t type_idx = FindTypeIdxByDescriptor(*java_lang_dex_file_.get(), "[I");
- Object* array = artCheckAndAllocArrayFromCode(type_idx, sort, 3);
+ Object* array = CheckAndAllocArrayFromCode(type_idx, sort, 3, Thread::Current());
EXPECT_TRUE(array->IsArrayInstance());
EXPECT_EQ(3, array->AsArray()->GetLength());
EXPECT_TRUE(array->GetClass()->IsArrayClass());
@@ -185,15 +184,16 @@
Class* klass = class_linker_->FindClass("LStaticsFromCode;", class_loader);
Method* clinit = klass->FindDirectMethod("<clinit>", "()V");
uint32_t field_idx = FindFieldIdxByDescriptorAndName(*dex_file, "LStaticsFromCode;", "s0");
- Object* s0 = Field::GetObjStaticFromCode(field_idx, clinit);
+ Field* field = FindFieldFromCode(field_idx, clinit, true);
+ Object* s0 = field->GetObj(NULL);
EXPECT_EQ(NULL, s0);
CharArray* char_array = CharArray::Alloc(0);
- Field::SetObjStaticFromCode(field_idx, clinit, char_array);
- EXPECT_EQ(char_array, Field::GetObjStaticFromCode(field_idx, clinit));
+ field->SetObj(NULL, char_array);
+ EXPECT_EQ(char_array, field->GetObj(NULL));
- Field::SetObjStaticFromCode(field_idx, clinit, NULL);
- EXPECT_EQ(NULL, Field::GetObjStaticFromCode(field_idx, clinit));
+ field->SetObj(NULL, NULL);
+ EXPECT_EQ(NULL, field->GetObj(NULL));
// TODO: more exhaustive tests of all 6 cases of Field::*FromCode
}
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 6a11e11..db6cbf0 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -22,6 +22,7 @@
// Place a special frame at the TOS that will save the callee saves for the given type
static void FinishCalleeSaveFrameSetup(Thread* self, Method** sp, Runtime::CalleeSaveType type) {
+ // Be aware the store below may well stomp on an incoming argument
*sp = Runtime::Current()->GetCalleeSaveMethod(type);
self->SetTopOfStack(sp, 0);
}
@@ -398,10 +399,135 @@
*/
}
+Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, bool is_static) {
+ ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Field* f = class_linker->ResolveField(field_idx, referrer, is_static);
+ if (f != NULL) {
+ Class* c = f->GetDeclaringClass();
+ // If the class is already initializing, we must be inside <clinit>, or
+ // we'd still be waiting for the lock.
+ if (c->GetStatus() == Class::kStatusInitializing || class_linker->EnsureInitialized(c, true)) {
+ return f;
+ }
+ }
+ DCHECK(Thread::Current()->IsExceptionPending()); // Throw exception and unwind
+ return NULL;
+}
+
+extern "C" Field* artFindInstanceFieldFromCode(uint32_t field_idx, const Method* referrer,
+ Thread* self, Method** sp) {
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ return FindFieldFromCode(field_idx, referrer, false);
+}
+
+extern "C" uint32_t artGet32StaticFromCode(uint32_t field_idx, const Method* referrer,
+ Thread* self, Method** sp) {
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ Field* field = FindFieldFromCode(field_idx, referrer, true);
+ if (field != NULL) {
+ Class* type = field->GetType();
+ if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t)) {
+ self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
+ "Attempted read of 32-bit primitive on field '%s'",
+ PrettyField(field, true).c_str());
+ } else {
+ return field->Get32(NULL);
+ }
+ }
+ return 0; // Will throw exception by checking with Thread::Current
+}
+
+extern "C" uint64_t artGet64StaticFromCode(uint32_t field_idx, const Method* referrer,
+ Thread* self, Method** sp) {
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ Field* field = FindFieldFromCode(field_idx, referrer, true);
+ if (field != NULL) {
+ Class* type = field->GetType();
+ if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t)) {
+ self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
+ "Attempted read of 64-bit primitive on field '%s'",
+ PrettyField(field, true).c_str());
+ } else {
+ return field->Get64(NULL);
+ }
+ }
+ return 0; // Will throw exception by checking with Thread::Current
+}
+
+extern "C" Object* artGetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
+ Thread* self, Method** sp) {
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ Field* field = FindFieldFromCode(field_idx, referrer, true);
+ if (field != NULL) {
+ Class* type = field->GetType();
+ if (type->IsPrimitive()) {
+ self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
+ "Attempted read of reference on primitive field '%s'",
+ PrettyField(field, true).c_str());
+ } else {
+ return field->GetObj(NULL);
+ }
+ }
+ return NULL; // Will throw exception by checking with Thread::Current
+}
+
+extern "C" int artSet32StaticFromCode(uint32_t field_idx, const Method* referrer,
+ uint32_t new_value, Thread* self, Method** sp) {
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ Field* field = FindFieldFromCode(field_idx, referrer, true);
+ if (field != NULL) {
+ Class* type = field->GetType();
+ if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int32_t)) {
+ self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
+ "Attempted write of 32-bit primitive to field '%s'",
+ PrettyField(field, true).c_str());
+ } else {
+ field->Set32(NULL, new_value);
+ return 0; // success
+ }
+ }
+ return -1; // failure
+}
+
+extern "C" int artSet64StaticFromCode(uint32_t field_idx, const Method* referrer,
+ uint64_t new_value, Thread* self, Method** sp) {
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ Field* field = FindFieldFromCode(field_idx, referrer, true);
+ if (field != NULL) {
+ Class* type = field->GetType();
+ if (!type->IsPrimitive() || type->PrimitiveSize() != sizeof(int64_t)) {
+ self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
+ "Attempted write of 64-bit primitive to field '%s'",
+ PrettyField(field, true).c_str());
+ } else {
+ field->Set64(NULL, new_value);
+ return 0; // success
+ }
+ }
+ return -1; // failure
+}
+
+extern "C" int artSetObjStaticFromCode(uint32_t field_idx, const Method* referrer,
+ Object* new_value, Thread* self, Method** sp) {
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ Field* field = FindFieldFromCode(field_idx, referrer, true);
+ if (field != NULL) {
+ Class* type = field->GetType();
+ if (type->IsPrimitive()) {
+ self->ThrowNewExceptionF("Ljava/lang/NoSuchFieldError;",
+ "Attempted write of reference to primitive field '%s'",
+ PrettyField(field, true).c_str());
+ } else {
+ field->SetObj(NULL, new_value);
+ return 0; // success
+ }
+ }
+ return -1; // failure
+}
+
// Given the context of a calling Method, use its DexCache to resolve a type to a Class. If it
// cannot be resolved, throw an error. If it can, use it to create an instance.
extern "C" Object* artAllocObjectFromCode(uint32_t type_idx, Method* method, Thread* self, Method** sp) {
- // Place a special frame at the TOS that will save all callee saves
FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
Runtime* runtime = Runtime::Current();
@@ -419,12 +545,10 @@
return klass->AllocObject();
}
-// Helper function to alloc array for OP_FILLED_NEW_ARRAY
-extern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method,
- int32_t component_count, Thread* self, Method** sp) {
+Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
+ Thread* self) {
if (component_count < 0) {
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d",
- component_count);
+ self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", component_count);
return NULL; // Failure
}
Class* klass = method->GetDexCacheResolvedTypes()->Get(type_idx);
@@ -452,6 +576,13 @@
}
}
+// Helper function to alloc array for OP_FILLED_NEW_ARRAY
+extern "C" Array* artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method,
+ int32_t component_count, Thread* self, Method** sp) {
+ FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsOnly);
+ return CheckAndAllocArrayFromCode(type_idx, method, component_count, self);
+}
+
// Given the context of a calling Method, use its DexCache to resolve a type to an array Class. If
// it cannot be resolved, throw an error. If it can, use it to create an array.
extern "C" Array* artAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
diff --git a/src/runtime_support.h b/src/runtime_support.h
index 0a70c61..d05ece0 100644
--- a/src/runtime_support.h
+++ b/src/runtime_support.h
@@ -10,11 +10,15 @@
namespace art {
+extern Array* CheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t component_count,
+ Thread* self);
extern void DebugMe(Method* method, uint32_t info);
extern Object* DecodeJObjectInThread(Thread* thread, jobject obj);
+extern Field* FindFieldFromCode(uint32_t field_idx, const Method* referrer, bool is_static);
extern void* FindNativeMethod(Thread* thread);
extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp);
void* UnresolvedDirectMethodTrampolineFromCode(int32_t, void*, Thread*, Runtime::TrampolineType);
+extern Class* InitializeStaticStorage(uint32_t type_idx, const Method* referrer, Thread* self);
extern Class* InitializeTypeFromCode(uint32_t type_idx, Method* method);
extern void ResolveMethodFromCode(Method* method, uint32_t method_idx);
extern void LockObjectFromCode(Thread* thread, Object* obj);
@@ -23,7 +27,6 @@
extern int64_t F2L(float f);
} // namespace art
-
/* Helper for both JNI and regular compiled code */
extern "C" void art_deliver_exception_from_code(void*);
@@ -34,9 +37,17 @@
extern "C" void* art_check_and_alloc_array_from_code(uint32_t, void*, int32_t);
extern "C" void art_can_put_array_element_from_code(void*, void*);
extern "C" void art_check_cast_from_code(void*, void*);
+ extern "C" void* art_find_instance_field_from_code(uint32_t, void*);
+ extern "C" void* art_find_static_field_from_code(uint32_t, void*);
+ extern "C" int32_t art_get32_static_from_code(uint32_t, void*);
+ extern "C" int64_t art_get64_static_from_code(uint32_t, void*);
+ extern "C" void* art_get_obj_static_from_code(uint32_t, void*);
extern "C" void art_handle_fill_data_from_code(void*, void*);
extern "C" void* art_initialize_static_storage_from_code(uint32_t, void*);
extern "C" void art_invoke_interface_trampoline(uint32_t, void*);
+ extern "C" int art_set32_static_from_code(uint32_t, void*, int32_t);
+ extern "C" int art_set64_static_from_code(uint32_t, void*, int64_t);
+ extern "C" int art_set_obj_static_from_code(uint32_t, void*, void*);
extern "C" void art_test_suspend();
extern "C" void art_throw_array_bounds_from_code(int32_t index, int32_t limit);
extern "C" void art_throw_div_zero_from_code();
diff --git a/src/runtime_support_asm.S b/src/runtime_support_asm.S
index 5b70fb7..d86d1fb 100644
--- a/src/runtime_support_asm.S
+++ b/src/runtime_support_asm.S
@@ -52,6 +52,17 @@
pop {r1-r3, r5-r8, r10-r11, lr} @ 10 words of callee saves
.endm
+ /*
+ * Macro that set calls through to artDeliverPendingExceptionFromCode, where the pending
+ * exception is Thread::Current()->exception_
+ */
+.macro DELIVER_PENDING_EXCEPTION
+ SETUP_CALLEE_SAVE_FRAME @ save callee saves for throw
+ mov r0, r9 @ pass Thread::Current
+ mov r1, sp @ pass SP
+ b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
+.endm
+
.global art_deliver_exception_from_code
/*
* Called by managed code, saves mosts registers (forms basis of long jump context) and passes
@@ -156,10 +167,7 @@
RESTORE_REF_AND_ARGS_CALLEE_SAVE_FRAME
cmp r0, #0 @ did we find the target?
bxne r12 @ tail call to target if so
- SETUP_CALLEE_SAVE_FRAME @ set up for throwing exception
- mov r0, r9 @ pass Thread::Current
- mov r1, sp @ pass SP
- b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
+ DELIVER_PENDING_EXCEPTION
.global art_handle_fill_data_from_code
.extern artHandleFillArrayDataFromCode
@@ -175,10 +183,7 @@
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success?
moveq pc, lr @ return on success
- SETUP_CALLEE_SAVE_FRAME @ set up for throwing exception
- mov r0, r9 @ pass Thread::Current
- mov r1, sp @ pass SP
- b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
+ DELIVER_PENDING_EXCEPTION
.global art_lock_object_from_code
.extern artLockObjectFromCode
@@ -205,10 +210,7 @@
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success?
moveq pc, lr @ return on success
- SETUP_CALLEE_SAVE_FRAME @ set up for throwing exception
- mov r0, r9 @ pass Thread::Current
- mov r1, sp @ pass SP
- b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
+ DELIVER_PENDING_EXCEPTION
.global art_check_cast_from_code
.extern artCheckCastFromCode
@@ -223,10 +225,7 @@
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success?
moveq pc, lr @ return on success
- SETUP_CALLEE_SAVE_FRAME @ set up for throwing exception
- mov r0, r9 @ pass Thread::Current
- mov r1, sp @ pass SP
- b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
+ DELIVER_PENDING_EXCEPTION
.global art_can_put_array_element_from_code
.extern artCanPutArrayElementFromCode
@@ -244,10 +243,7 @@
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success?
moveq pc, lr @ return on success
- SETUP_CALLEE_SAVE_FRAME @ set up for throwing exception
- mov r0, r9 @ pass Thread::Current
- mov r1, sp @ pass SP
- b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
+ DELIVER_PENDING_EXCEPTION
.global art_initialize_static_storage_from_code
.extern artInitializeStaticStorageFromCode
@@ -265,10 +261,117 @@
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success if result is non-null
movne pc, lr @ return on success
- SETUP_CALLEE_SAVE_FRAME @ set up for throwing exception
- mov r0, r9 @ pass Thread::Current
- mov r1, sp @ pass SP
- b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
+ DELIVER_PENDING_EXCEPTION
+
+ .global art_find_instance_field_from_code
+ .extern artFindInstanceFieldFromCode
+ /*
+ * Called by managed code to resolve a field of an object
+ */
+art_find_instance_field_from_code:
+ SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
+ mov r2, r9 @ pass Thread::Current
+ mov r3, sp @ pass SP
+ bl artFindInstanceFieldFromCode @ (uint32_t field_idx, const Method* referrer, Thread*, SP)
+ RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+ cmp r0, #0 @ success if result is non-null
+ movne pc, lr @ return on success
+ DELIVER_PENDING_EXCEPTION
+
+ .global art_get32_static_from_code
+ .extern artGet32StaticFromCode
+ /*
+ * Called by managed code to resolve a static field and load a 32-bit primitive value
+ */
+art_get32_static_from_code:
+ SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
+ mov r2, r9 @ pass Thread::Current
+ mov r3, sp @ pass SP
+ bl artGet32StaticFromCode @ (uint32_t field_idx, const Method* referrer, Thread*, SP)
+ ldr r12, [r9, #THREAD_EXCEPTION_OFFSET] @ load Thread::Current()->exception_
+ RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+ cmp r12, #0 @ success if no exception is pending
+ moveq pc, lr @ return on success
+ DELIVER_PENDING_EXCEPTION
+
+ .global art_get64_static_from_code
+ .extern artGet64StaticFromCode
+ /*
+ * Called by managed code to resolve a static field and load a 64-bit primitive value
+ */
+art_get64_static_from_code:
+ SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
+ mov r2, r9 @ pass Thread::Current
+ mov r3, sp @ pass SP
+ bl artGet64StaticFromCode @ (uint32_t field_idx, const Method* referrer, Thread*, SP)
+ ldr r12, [r9, #THREAD_EXCEPTION_OFFSET] @ load Thread::Current()->exception_
+ RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+ cmp r12, #0 @ success if no exception is pending
+ moveq pc, lr @ return on success
+ DELIVER_PENDING_EXCEPTION
+
+ .global art_get_obj_static_from_code
+ .extern artGetObjStaticFromCode
+ /*
+ * Called by managed code to resolve a static field and load an object reference
+ */
+art_get_obj_static_from_code:
+ SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
+ mov r2, r9 @ pass Thread::Current
+ mov r3, sp @ pass SP
+ bl artGetObjStaticFromCode @ (uint32_t field_idx, const Method* referrer, Thread*, SP)
+ ldr r12, [r9, #THREAD_EXCEPTION_OFFSET] @ load Thread::Current()->exception_
+ RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+ cmp r12, #0 @ success if no exception is pending
+ moveq pc, lr @ return on success
+ DELIVER_PENDING_EXCEPTION
+
+ .global art_set32_static_from_code
+ .extern artSet32StaticFromCode
+ /*
+ * Called by managed code to resolve a static field and store a 32-bit primitive value
+ */
+art_set32_static_from_code:
+ SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
+ mov r3, r9 @ pass Thread::Current
+ str sp, [sp, #0] @ pass SP
+ bl artSet32StaticFromCode @ (field_idx, referrer, new_val, Thread*, SP)
+ RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+ cmp r0, #0 @ success if result is 0
+ moveq pc, lr @ return on success
+ DELIVER_PENDING_EXCEPTION
+
+ .global art_set64_static_from_code
+ .extern artSet32StaticFromCode
+ /*
+ * Called by managed code to resolve a static field and store a 64-bit primitive value
+ */
+art_set64_static_from_code:
+ SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
+ mov r12, sp @ save SP
+ sub sp, #8 @ grow frame for alignment with stack args
+ push {r9, r12} @ pass Thread::Current and SP
+ bl artSet64StaticFromCode @ (field_idx, referrer, new_val, Thread*, SP)
+ add sp, #16 @ release out args
+ RESTORE_REF_ONLY_CALLEE_SAVE_FRAME @ TODO: we can clearly save an add here
+ cmp r0, #0 @ success if result is 0
+ moveq pc, lr @ return on success
+ DELIVER_PENDING_EXCEPTION
+
+ .global art_set_obj_static_from_code
+ .extern artSetObjStaticFromCode
+ /*
+ * Called by managed code to resolve a static field and store an object reference
+ */
+art_set_obj_static_from_code:
+ SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case of GC
+ mov r3, r9 @ pass Thread::Current
+ str sp, [sp, #0] @ pass SP
+ bl artSetObjStaticFromCode @ (field_idx, referrer, new_val, Thread*, SP)
+ RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
+ cmp r0, #0 @ success if result is 0
+ moveq pc, lr @ return on success
+ DELIVER_PENDING_EXCEPTION
.global art_alloc_object_from_code
.extern artAllocObjectFromCode
@@ -283,10 +386,7 @@
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success if result is non-null
movne pc, lr @ return on success
- SETUP_CALLEE_SAVE_FRAME @ set up for throwing exception
- mov r0, r9 @ pass Thread::Current
- mov r1, sp @ pass SP
- b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
+ DELIVER_PENDING_EXCEPTION
.global art_alloc_array_from_code
.extern artAllocArrayFromCode
@@ -302,10 +402,7 @@
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
cmp r0, #0 @ success if result is non-null
movne pc, lr @ return on success
- SETUP_CALLEE_SAVE_FRAME @ set up for throwing exception
- mov r0, r9 @ pass Thread::Current
- mov r1, sp @ pass SP
- b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
+ DELIVER_PENDING_EXCEPTION
.global art_check_and_alloc_array_from_code
.extern artCheckAndAllocArrayFromCode
@@ -319,12 +416,9 @@
@ artCheckAndAllocArrayFromCode(uint32_t type_idx, Method* method, int32_t count, Thread* , SP)
bl artCheckAndAllocArrayFromCode
RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
- cmp r0, #0 @ success if result is non-null
- movne pc, lr @ return on success
- SETUP_CALLEE_SAVE_FRAME @ set up for throwing exception
- mov r0, r9 @ pass Thread::Current
- mov r1, sp @ pass SP
- b artDeliverPendingExceptionFromCode @ artDeliverPendingExceptionFromCode(Thread*, SP)
+ cmp r0, #0 @ success if result is non-null
+ movne pc, lr @ return on success
+ DELIVER_PENDING_EXCEPTION
.global art_test_suspend
.extern artCheckSuspendFromCode
diff --git a/src/thread.cc b/src/thread.cc
index b3dbcb6..079954b 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -110,9 +110,16 @@
pCanPutArrayElementFromCode = art_can_put_array_element_from_code;
pCheckAndAllocArrayFromCode = art_check_and_alloc_array_from_code;
pCheckCastFromCode = art_check_cast_from_code;
+ pFindInstanceFieldFromCode = art_find_instance_field_from_code;
+ pGet32Static = art_get32_static_from_code;
+ pGet64Static = art_get64_static_from_code;
+ pGetObjStatic = art_get_obj_static_from_code;
pHandleFillArrayDataFromCode = art_handle_fill_data_from_code;
pInitializeStaticStorage = art_initialize_static_storage_from_code;
pInvokeInterfaceTrampoline = art_invoke_interface_trampoline;
+ pSet32Static = art_set32_static_from_code;
+ pSet64Static = art_set64_static_from_code;
+ pSetObjStatic = art_set_obj_static_from_code;
pTestSuspendFromCode = art_test_suspend;
pThrowArrayBoundsFromCode = art_throw_array_bounds_from_code;
pThrowDivZeroFromCode = art_throw_div_zero_from_code;
@@ -130,16 +137,9 @@
pF2l = F2L;
pD2l = D2L;
pMemcpy = memcpy;
- pGet32Static = Field::Get32StaticFromCode;
- pSet32Static = Field::Set32StaticFromCode;
- pGet64Static = Field::Get64StaticFromCode;
- pSet64Static = Field::Set64StaticFromCode;
- pGetObjStatic = Field::GetObjStaticFromCode;
- pSetObjStatic = Field::SetObjStaticFromCode;
pInitializeTypeFromCode = InitializeTypeFromCode;
pResolveMethodFromCode = ResolveMethodFromCode;
pInstanceofNonTrivialFromCode = Class::IsAssignableFromCode;
- pFindInstanceFieldFromCode = Field::FindInstanceFieldFromCode;
pCheckSuspendFromCode = artCheckSuspendFromJni;
pFindNativeMethod = FindNativeMethod;
pDecodeJObjectInThread = DecodeJObjectInThread;
diff --git a/src/thread.h b/src/thread.h
index c66e77e..12302ad 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -116,31 +116,32 @@
int (*pIdiv)(int, int);
long long (*pLmul)(long long, long long);
long long (*pLdivmod)(long long, long long);
- void* (*pUnresolvedDirectMethodTrampolineFromCode)(int32_t, void*, Thread*,
- Runtime::TrampolineType);
void* (*pAllocObjectFromCode)(uint32_t, void*);
void* (*pAllocArrayFromCode)(uint32_t, void*, int32_t);
- void* (*pCheckAndAllocArrayFromCode)(uint32_t, void*, int32_t);
- uint32_t (*pGet32Static)(uint32_t, const Method*);
- void (*pSet32Static)(uint32_t, const Method*, uint32_t);
- uint64_t (*pGet64Static)(uint32_t, const Method*);
- void (*pSet64Static)(uint32_t, const Method*, uint64_t);
- Object* (*pGetObjStatic)(uint32_t, const Method*);
- void (*pSetObjStatic)(uint32_t, const Method*, Object*);
void (*pCanPutArrayElementFromCode)(void*, void*);
- uint32_t (*pInstanceofNonTrivialFromCode) (const Class*, const Class*);
+ void* (*pCheckAndAllocArrayFromCode)(uint32_t, void*, int32_t);
void (*pCheckCastFromCode) (void*, void*);
- Method* (*pFindInterfaceMethodInCache)(Class*, uint32_t, const Method*, struct DvmDex*);
- void (*pUnlockObjectFromCode)(void*);
- void (*pLockObjectFromCode)(void*);
- void (*pDeliverException)(void*);
- void (*pHandleFillArrayDataFromCode)(void*, void*);
- Class* (*pInitializeTypeFromCode)(uint32_t, Method*);
- void (*pResolveMethodFromCode)(Method*, uint32_t);
- void (*pInvokeInterfaceTrampoline)(uint32_t, void*);
- void* (*pInitializeStaticStorage)(uint32_t, void*);
- Field* (*pFindInstanceFieldFromCode)(uint32_t, const Method*);
void (*pCheckSuspendFromCode)(Thread*);
+ Object* (*pDecodeJObjectInThread)(Thread* thread, jobject obj);
+ void (*pDeliverException)(void*);
+ void* (*pFindInstanceFieldFromCode)(uint32_t, void*);
+ Method* (*pFindInterfaceMethodInCache)(Class*, uint32_t, const Method*, struct DvmDex*);
+ void* (*pFindNativeMethod)(Thread* thread);
+ int32_t (*pGet32Static)(uint32_t, void*);
+ int64_t (*pGet64Static)(uint32_t, void*);
+ void* (*pGetObjStatic)(uint32_t, void*);
+ void (*pHandleFillArrayDataFromCode)(void*, void*);
+ void* (*pInitializeStaticStorage)(uint32_t, void*);
+ uint32_t (*pInstanceofNonTrivialFromCode) (const Class*, const Class*);
+ void (*pInvokeInterfaceTrampoline)(uint32_t, void*);
+ Class* (*pInitializeTypeFromCode)(uint32_t, Method*);
+ void (*pLockObjectFromCode)(void*);
+ void (*pObjectInit)(Object*);
+ void (*pResolveMethodFromCode)(Method*, uint32_t);
+ String* (*pResolveStringFromCode)(Method*, int32_t);
+ int (*pSet32Static)(uint32_t, void*, int32_t);
+ int (*pSet64Static)(uint32_t, void*, int64_t);
+ int (*pSetObjStatic)(uint32_t, void*, void*);
void (*pTestSuspendFromCode)();
void (*pThrowStackOverflowFromCode)(void*);
void (*pThrowNullPointerFromCode)();
@@ -150,10 +151,9 @@
void (*pThrowNegArraySizeFromCode)(int32_t);
void (*pThrowNoSuchMethodFromCode)(int32_t);
void (*pThrowAbstractMethodErrorFromCode)(Method* method, Thread* thread, Method** sp);
- void* (*pFindNativeMethod)(Thread* thread);
- Object* (*pDecodeJObjectInThread)(Thread* thread, jobject obj);
- String* (*pResolveStringFromCode)(Method*, int32_t);
- void (*pObjectInit)(Object*);
+ void (*pUnlockObjectFromCode)(void*);
+ void* (*pUnresolvedDirectMethodTrampolineFromCode)(int32_t, void*, Thread*,
+ Runtime::TrampolineType);
class StackVisitor {
public:
diff --git a/src/thread_arm.cc b/src/thread_arm.cc
index a7efc1a..0196eb8 100644
--- a/src/thread_arm.cc
+++ b/src/thread_arm.cc
@@ -9,6 +9,7 @@
void Thread::InitCpu() {
CHECK_EQ(THREAD_SUSPEND_COUNT_OFFSET, OFFSETOF_MEMBER(Thread, suspend_count_));
+ CHECK_EQ(THREAD_EXCEPTION_OFFSET, OFFSETOF_MEMBER(Thread, exception_));
}
} // namespace art