summaryrefslogtreecommitdiffstats
path: root/runtime/arch/arm
diff options
context:
space:
mode:
authorIan Rogers <irogers@google.com>2013-10-04 11:17:26 -0700
committerIan Rogers <irogers@google.com>2013-10-08 15:54:54 -0700
commita9a8254c920ce8e22210abfc16c9842ce0aea28f (patch)
tree56614ee997940e8e3b88fef43b890e8a33e78112 /runtime/arch/arm
parent34633b22f74393344987a50b8aaee548a9dadc18 (diff)
downloadart-a9a8254c920ce8e22210abfc16c9842ce0aea28f.zip
art-a9a8254c920ce8e22210abfc16c9842ce0aea28f.tar.gz
art-a9a8254c920ce8e22210abfc16c9842ce0aea28f.tar.bz2
Improve quick codegen for aput-object.
1) don't type check known null. 2) if we know types in verify don't check at runtime. 3) if we're runtime checking then move all the code out-of-line. Also, don't set up a callee-save frame for check-cast, do an instance-of test then throw an exception if that fails. Tidy quick entry point of Ldivmod to Lmod which it is on x86 and mips. Fix monitor-enter/exit NPE for MIPS. Fix benign bug in mirror::Class::CannotBeAssignedFromOtherTypes, a byte[] cannot be assigned to from other types. Change-Id: I9cb3859ec70cca71ed79331ec8df5bec969d6745
Diffstat (limited to 'runtime/arch/arm')
-rw-r--r--runtime/arch/arm/asm_support_arm.h2
-rw-r--r--runtime/arch/arm/entrypoints_init_arm.cc14
-rw-r--r--runtime/arch/arm/quick_entrypoints_arm.S107
-rw-r--r--runtime/arch/arm/thread_arm.cc1
4 files changed, 98 insertions, 26 deletions
diff --git a/runtime/arch/arm/asm_support_arm.h b/runtime/arch/arm/asm_support_arm.h
index 69fb9c3..cfffbea 100644
--- a/runtime/arch/arm/asm_support_arm.h
+++ b/runtime/arch/arm/asm_support_arm.h
@@ -25,6 +25,8 @@
#define rSELF r9
// Offset of field Thread::suspend_count_ verified in InitCpu
#define THREAD_FLAGS_OFFSET 0
+// Offset of field Thread::card_table_ verified in InitCpu
+#define THREAD_CARD_TABLE_OFFSET 8
// Offset of field Thread::exception_ verified in InitCpu
#define THREAD_EXCEPTION_OFFSET 12
// Offset of field Thread::thin_lock_thread_id_ verified in InitCpu
diff --git a/runtime/arch/arm/entrypoints_init_arm.cc b/runtime/arch/arm/entrypoints_init_arm.cc
index e6e13be..352982f 100644
--- a/runtime/arch/arm/entrypoints_init_arm.cc
+++ b/runtime/arch/arm/entrypoints_init_arm.cc
@@ -52,7 +52,6 @@ extern "C" void* art_quick_check_and_alloc_array_with_access_check_instrumented(
// Cast entrypoints.
extern "C" uint32_t artIsAssignableFromCode(const mirror::Class* klass,
const mirror::Class* ref_class);
-extern "C" void art_quick_can_put_array_element(void*, void*);
extern "C" void art_quick_check_cast(void*, void*);
// DexCache entrypoints.
@@ -78,7 +77,10 @@ extern "C" int64_t art_quick_get64_static(uint32_t);
extern "C" void* art_quick_get_obj_instance(uint32_t, void*);
extern "C" void* art_quick_get_obj_static(uint32_t);
-// FillArray entrypoint.
+// Array entrypoints.
+extern "C" void art_quick_aput_obj_with_null_and_bound_check(void*, uint32_t, void*);
+extern "C" void art_quick_aput_obj_with_bound_check(void*, uint32_t, void*);
+extern "C" void art_quick_aput_obj(void*, uint32_t, void*);
extern "C" void art_quick_handle_fill_data(void*, void*);
// Lock entrypoints.
@@ -182,7 +184,6 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
// Cast
qpoints->pInstanceofNonTrivial = artIsAssignableFromCode;
- qpoints->pCanPutArrayElement = art_quick_can_put_array_element;
qpoints->pCheckCast = art_quick_check_cast;
// DexCache
@@ -205,7 +206,10 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
qpoints->pGet64Static = art_quick_get64_static;
qpoints->pGetObjStatic = art_quick_get_obj_static;
- // FillArray
+ // Array
+ qpoints->pAputObjectWithNullAndBoundCheck = art_quick_aput_obj_with_null_and_bound_check;
+ qpoints->pAputObjectWithBoundCheck = art_quick_aput_obj_with_bound_check;
+ qpoints->pAputObject = art_quick_aput_obj;
qpoints->pHandleFillArrayData = art_quick_handle_fill_data;
// JNI
@@ -236,7 +240,7 @@ void InitEntryPoints(InterpreterEntryPoints* ipoints, JniEntryPoints* jpoints,
qpoints->pD2l = art_d2l;
qpoints->pF2l = art_f2l;
qpoints->pLdiv = __aeabi_ldivmod;
- qpoints->pLdivmod = __aeabi_ldivmod; // result returned in r2:r3
+ qpoints->pLmod = __aeabi_ldivmod; // result returned in r2:r3
qpoints->pLmul = art_quick_mul_long;
qpoints->pShlLong = art_quick_shl_long;
qpoints->pShrLong = art_quick_shr_long;
diff --git a/runtime/arch/arm/quick_entrypoints_arm.S b/runtime/arch/arm/quick_entrypoints_arm.S
index cb61698..d073177 100644
--- a/runtime/arch/arm/quick_entrypoints_arm.S
+++ b/runtime/arch/arm/quick_entrypoints_arm.S
@@ -152,6 +152,7 @@ ENTRY \c_name
mov r1, r9 @ pass Thread::Current
mov r2, sp @ pass SP
b \cxx_name @ \cxx_name(Thread*, SP)
+ bkpt
END \c_name
.endm
@@ -162,6 +163,7 @@ ENTRY \c_name
mov r2, r9 @ pass Thread::Current
mov r3, sp @ pass SP
b \cxx_name @ \cxx_name(Thread*, SP)
+ bkpt
END \c_name
.endm
@@ -389,33 +391,96 @@ slow_unlock:
END art_quick_unlock_object
/*
- * Entry from managed code that calls artCheckCastFromCode and delivers exception on failure.
+ * Entry from managed code that calls artIsAssignableFromCode and on failure calls
+ * artThrowClassCastException.
*/
- .extern artCheckCastFromCode
+ .extern artThrowClassCastException
ENTRY art_quick_check_cast
- SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case exception allocation triggers GC
- mov r2, r9 @ pass Thread::Current
- mov r3, sp @ pass SP
- bl artCheckCastFromCode @ (Class* a, Class* b, Thread*, SP)
- RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
- RETURN_IF_RESULT_IS_ZERO
- DELIVER_PENDING_EXCEPTION
+ push {r0-r1, lr} @ save arguments, link register and pad
+ .save {r0-r1, lr}
+ .cfi_adjust_cfa_offset 12
+ .cfi_rel_offset r0, 0
+ .cfi_rel_offset r1, 4
+ .cfi_rel_offset lr, 8
+ sub sp, #4
+ .pad #4
+ .cfi_adjust_cfa_offset 4
+ bl artIsAssignableFromCode
+ cbz r0, throw_class_cast_exception
+ add sp, #4
+ .cfi_adjust_cfa_offset -4
+ pop {r0-r1, pc}
+throw_class_cast_exception:
+ add sp, #4
+ .cfi_adjust_cfa_offset -4
+ pop {r0-r1, lr}
+ SETUP_SAVE_ALL_CALLEE_SAVE_FRAME // save all registers as basis for long jump context
+ mov r2, r9 @ pass Thread::Current
+ mov r3, sp @ pass SP
+ b artThrowClassCastException @ (Class*, Class*, Thread*, SP)
+ bkpt
END art_quick_check_cast
/*
- * Entry from managed code that calls artCanPutArrayElementFromCode and delivers exception on
- * failure.
+ * Entry from managed code for array put operations of objects where the value being stored
+ * needs to be checked for compatibility.
+ * r0 = array, r1 = index, r2 = value
*/
- .extern artCanPutArrayElementFromCode
-ENTRY art_quick_can_put_array_element
- SETUP_REF_ONLY_CALLEE_SAVE_FRAME @ save callee saves in case exception allocation triggers GC
- mov r2, r9 @ pass Thread::Current
- mov r3, sp @ pass SP
- bl artCanPutArrayElementFromCode @ (Object* element, Class* array_class, Thread*, SP)
- RESTORE_REF_ONLY_CALLEE_SAVE_FRAME
- RETURN_IF_RESULT_IS_ZERO
- DELIVER_PENDING_EXCEPTION
-END art_quick_can_put_array_element
+ENTRY art_quick_aput_obj_with_null_and_bound_check
+ tst r0, r0
+ bne art_quick_aput_obj_with_bound_check
+ b art_quick_throw_null_pointer_exception
+END art_quick_aput_obj_with_null_and_bound_check
+
+ENTRY art_quick_aput_obj_with_bound_check
+ ldr r3, [r0, #ARRAY_LENGTH_OFFSET]
+ cmp r3, r1
+ bhi art_quick_aput_obj
+ mov r0, r1
+ mov r1, r3
+ b art_quick_throw_array_bounds
+END art_quick_aput_obj_with_bound_check
+
+ENTRY art_quick_aput_obj
+ cbz r2, do_aput_null
+ ldr r3, [r0, #CLASS_OFFSET]
+ ldr ip, [r2, #CLASS_OFFSET]
+ ldr r3, [r3, #CLASS_COMPONENT_TYPE_OFFSET]
+ cmp r3, ip @ value's type == array's component type - trivial assignability
+ bne check_assignability
+do_aput:
+ add r3, r0, #OBJECT_ARRAY_DATA_OFFSET
+ str r2, [r3, r1, lsl #2]
+ ldr r3, [r9, #THREAD_CARD_TABLE_OFFSET]
+ lsr r0, r0, #7
+ strb r3, [r3, r0]
+ blx lr
+do_aput_null:
+ add r3, r0, #OBJECT_ARRAY_DATA_OFFSET
+ str r2, [r3, r1, lsl #2]
+ blx lr
+check_assignability:
+ push {r0-r2, lr} @ save arguments
+ mov r1, ip
+ mov r0, r3
+ bl artIsAssignableFromCode
+ cbz r0, throw_array_store_exception
+ pop {r0-r2, lr}
+ add r3, r0, #OBJECT_ARRAY_DATA_OFFSET
+ str r2, [r3, r1, lsl #2]
+ ldr r3, [r9, #THREAD_CARD_TABLE_OFFSET]
+ lsr r0, r0, #7
+ strb r3, [r3, r0]
+ blx lr
+throw_array_store_exception:
+ pop {r0-r2, lr}
+ SETUP_SAVE_ALL_CALLEE_SAVE_FRAME
+ mov r1, r2
+ mov r2, r9 @ pass Thread::Current
+ mov r3, sp @ pass SP
+ b artThrowArrayStoreException @ (Class*, Class*, Thread*, SP)
+ bkpt @ unreached
+END art_quick_aput_obj
/*
* Entry from managed code when uninitialized static storage, this stub will run the class
diff --git a/runtime/arch/arm/thread_arm.cc b/runtime/arch/arm/thread_arm.cc
index 75eef60..8c1efeb 100644
--- a/runtime/arch/arm/thread_arm.cc
+++ b/runtime/arch/arm/thread_arm.cc
@@ -23,6 +23,7 @@ namespace art {
void Thread::InitCpu() {
CHECK_EQ(THREAD_FLAGS_OFFSET, OFFSETOF_MEMBER(Thread, state_and_flags_));
+ CHECK_EQ(THREAD_CARD_TABLE_OFFSET, OFFSETOF_MEMBER(Thread, card_table_));
CHECK_EQ(THREAD_EXCEPTION_OFFSET, OFFSETOF_MEMBER(Thread, exception_));
CHECK_EQ(THREAD_ID_OFFSET, OFFSETOF_MEMBER(Thread, thin_lock_thread_id_));
}