summaryrefslogtreecommitdiff
path: root/src/vm/arm64/asmhelpers.S
diff options
context:
space:
mode:
authorSteve MacLean <sdmaclea.qdt@qualcommdatacenter.com>2017-08-25 18:10:50 -0400
committerJan Kotas <jkotas@microsoft.com>2017-08-25 15:10:50 -0700
commitf2bbee2ec637c7e2c87d9ab547f3e5ba7d6977e7 (patch)
treed2184b48fa0bc6010559fd7b920056740e842bcf /src/vm/arm64/asmhelpers.S
parentff3be834b81ee76736e0ddc1b292b7b2440848ff (diff)
downloadcoreclr-f2bbee2ec637c7e2c87d9ab547f3e5ba7d6977e7.tar.gz
coreclr-f2bbee2ec637c7e2c87d9ab547f3e5ba7d6977e7.tar.bz2
coreclr-f2bbee2ec637c7e2c87d9ab547f3e5ba7d6977e7.zip
[Arm64/Unix] Add JIT_Stelem_Ref helper (#13588)
Diffstat (limited to 'src/vm/arm64/asmhelpers.S')
-rw-r--r--src/vm/arm64/asmhelpers.S97
1 files changed, 97 insertions, 0 deletions
diff --git a/src/vm/arm64/asmhelpers.S b/src/vm/arm64/asmhelpers.S
index 7a64665b29..017cc50f68 100644
--- a/src/vm/arm64/asmhelpers.S
+++ b/src/vm/arm64/asmhelpers.S
@@ -1302,3 +1302,100 @@ LEAF_ENTRY JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
ldr x0, [x0, #DomainLocalModule__m_pGCStatics]
ret lr
LEAF_END JIT_GetSharedGCStaticBaseNoCtor_SingleAppDomain, _TEXT
+
+// ------------------------------------------------------------------
+// __declspec(naked) void F_CALL_CONV JIT_Stelem_Ref(PtrArray* array, unsigned idx, Object* val)
+LEAF_ENTRY JIT_Stelem_Ref, _TEXT
+ // We retain arguments as they were passed and use x0 == array x1 == idx x2 == val
+
+ // check for null array
+ cbz x0, LOCAL_LABEL(ThrowNullReferenceException)
+
+ // idx bounds check
+ ldr x3,[x0,#ArrayBase__m_NumComponents]
+ cmp x3, x1
+ bls LOCAL_LABEL(ThrowIndexOutOfRangeException)
+
+ // fast path to null assignment (doesn't need any write-barriers)
+ cbz x2, LOCAL_LABEL(AssigningNull)
+
+ // Verify the array-type and val-type matches before writing
+ ldr x12, [x0] // x12 = array MT
+ ldr x3, [x2] // x3 = val->GetMethodTable()
+ ldr x12, [x12, #MethodTable__m_ElementType] // array->GetArrayElementTypeHandle()
+ cmp x3, x12
+ beq C_FUNC(JIT_Stelem_DoWrite)
+
+ // Types didnt match but allow writing into an array of objects
+ ldr x3, =g_pObjectClass
+ ldr x3, [x3] // x3 = *g_pObjectClass
+ cmp x3, x12 // array type matches with Object*
+ beq C_FUNC(JIT_Stelem_DoWrite)
+
+ // array type and val type do not exactly match. Raise frame and do detailed match
+ b C_FUNC(JIT_Stelem_Ref_NotExactMatch)
+
+LOCAL_LABEL(AssigningNull):
+ // Assigning null doesn't need write barrier
+ add x0, x0, x1, LSL #3 // x0 = x0 + (x1 x 8) = array->m_array[idx]
+ str x2, [x0, #PtrArray__m_Array] // array->m_array[idx] = val
+ ret
+
+LOCAL_LABEL(ThrowNullReferenceException):
+ // Tail call JIT_InternalThrow(NullReferenceException)
+ ldr x0, =CORINFO_NullReferenceException_ASM
+ b C_FUNC(JIT_InternalThrow)
+
+LOCAL_LABEL(ThrowIndexOutOfRangeException):
+ // Tail call JIT_InternalThrow(NullReferenceException)
+ ldr x0, =CORINFO_IndexOutOfRangeException_ASM
+ b C_FUNC(JIT_InternalThrow)
+
+LEAF_END JIT_Stelem_Ref, _TEXT
+
+// ------------------------------------------------------------------
+// __declspec(naked) void F_CALL_CONV JIT_Stelem_Ref_NotExactMatch(PtrArray* array,
+// unsigned idx, Object* val)
+// x12 = array->GetArrayElementTypeHandle()
+//
+NESTED_ENTRY JIT_Stelem_Ref_NotExactMatch, _TEXT, NoHandler
+ PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -48
+ // Spill callee saved registers
+ PROLOG_SAVE_REG_PAIR x0, x1, 16
+ PROLOG_SAVE_REG x2, 32
+
+ // allow in case val can be casted to array element type
+ // call ObjIsInstanceOfNoGC(val, array->GetArrayElementTypeHandle())
+ mov x1, x12 // array->GetArrayElementTypeHandle()
+ mov x0, x2
+ bl C_FUNC(ObjIsInstanceOfNoGC)
+ cmp x0, TypeHandle_CanCast
+ beq LOCAL_LABEL(DoWrite) // ObjIsInstance returned TypeHandle::CanCast
+
+ // check via raising frame
+LOCAL_LABEL(NeedFrame):
+ add x1, sp, #16 // x1 = &array
+ add x0, sp, #32 // x0 = &val
+
+ bl C_FUNC(ArrayStoreCheck) // ArrayStoreCheck(&val, &array)
+
+LOCAL_LABEL(DoWrite):
+ EPILOG_RESTORE_REG_PAIR x0, x1, 16
+ EPILOG_RESTORE_REG x2, 32
+ EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 48
+ b C_FUNC(JIT_Stelem_DoWrite)
+NESTED_END JIT_Stelem_Ref_NotExactMatch, _TEXT
+
+// ------------------------------------------------------------------
+// __declspec(naked) void F_CALL_CONV JIT_Stelem_DoWrite(PtrArray* array, unsigned idx, Object* val)
+LEAF_ENTRY JIT_Stelem_DoWrite, _TEXT
+
+ // Setup args for JIT_WriteBarrier. x14 = &array->m_array[idx] x15 = val
+ add x14, x0, #PtrArray__m_Array // x14 = &array->m_array
+ add x14, x14, x1, LSL #3
+ mov x15, x2 // x15 = val
+
+ // Branch to the write barrier (which is already correctly overwritten with
+ // single or multi-proc code based on the current CPU
+ b C_FUNC(JIT_WriteBarrier)
+LEAF_END JIT_Stelem_DoWrite, _TEXT