From a8072b77eb93b6bdf64fef202c24891f87dd5205 Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 13 Jun 2024 19:18:03 +0800 Subject: [PATCH 1/4] Call managed ArrayTypeCheck --- .../Runtime/CompilerServices/CastHelpers.cs | 30 +++++++++++++++++++ src/coreclr/vm/array.cpp | 2 +- src/coreclr/vm/corelib.h | 3 ++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index 0c640dd1c2f0a4..96178d937765b1 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -462,5 +462,35 @@ private static void StelemRef_Helper_NoCacheLookup(ref object? element, void* el WriteBarrier(ref element, obj); } + +#if FEATURE_ARRAYSTUB_AS_IL + [DebuggerHidden] + private static unsafe void ArrayTypeCheck(object obj, object[] array) + { + Debug.Assert(obj != null); + + void* elementType = RuntimeHelpers.GetMethodTable(array)->ElementType; + CastResult result = CastCache.TryGet(s_table!, (nuint)RuntimeHelpers.GetMethodTable(obj), (nuint)elementType); + if (result == CastResult.CanCast) + { + return; + } + + ArrayTypeCheck_Helper(obj, elementType); + } + + [DebuggerHidden] + [MethodImpl(MethodImplOptions.NoInlining)] + private static unsafe void ArrayTypeCheck_Helper(object obj, void* elementType) + { + Debug.Assert(obj != null); + + obj = IsInstanceOfAny_NoCacheLookup(elementType, obj); + if (obj == null) + { + ThrowArrayMismatchException(); + } + } +#endif } } diff --git a/src/coreclr/vm/array.cpp b/src/coreclr/vm/array.cpp index bb05b85f4f10ce..806db9309f0fb3 100644 --- a/src/coreclr/vm/array.cpp +++ b/src/coreclr/vm/array.cpp @@ -706,7 +706,7 @@ class ArrayOpLinker : public ILStubLinker // Call type check helper m_pCode->EmitLDARG(rank); m_pCode->EmitLoadThis(); - m_pCode->EmitCALL(METHOD__STUBHELPERS__ARRAY_TYPE_CHECK,2,0); + m_pCode->EmitCALL(METHOD__CASTHELPERS__ARRAYTYPECHECK,2,0); m_pCode->EmitLabel(pTypeCheckOK); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index df42e52eab9527..7dbe5aacbefd1e 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1169,6 +1169,9 @@ DEFINE_METHOD(CASTHELPERS, CHKCASTCLASSSPECIAL, ChkCastClassSpecial, SM_Ptr DEFINE_METHOD(CASTHELPERS, UNBOX, Unbox, SM_PtrVoid_Obj_RetRefByte) DEFINE_METHOD(CASTHELPERS, STELEMREF, StelemRef, SM_ArrObject_IntPtr_Obj_RetVoid) DEFINE_METHOD(CASTHELPERS, LDELEMAREF, LdelemaRef, SM_ArrObject_IntPtr_PtrVoid_RetRefObj) +#ifdef FEATURE_ARRAYSTUB_AS_IL +DEFINE_METHOD(CASTHELPERS, ARRAYTYPECHECK, ArrayTypeCheck, SM_Obj_ArrObject_RetVoid) +#endif #ifdef FEATURE_EH_FUNCLETS DEFINE_CLASS(EH, Runtime, EH) From 7f4186c445b127671e54582abe0279a54f12c08e Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 13 Jun 2024 19:21:54 +0800 Subject: [PATCH 2/4] Delete FCall of StubHelpers.ArrayTypeCheck --- .../src/System/StubHelpers.cs | 5 ---- src/coreclr/vm/corelib.h | 4 --- src/coreclr/vm/ecalllist.h | 3 --- src/coreclr/vm/stubhelpers.cpp | 26 ------------------- src/coreclr/vm/stubhelpers.h | 4 --- 5 files changed, 42 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index e772613855c767..cd96be08049005 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -1616,11 +1616,6 @@ internal static unsafe void LayoutDestroyNativeInternal(object obj, byte* pNativ [MethodImpl(MethodImplOptions.InternalCall)] internal static extern IntPtr GetStubContext(); -#if FEATURE_ARRAYSTUB_AS_IL - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void ArrayTypeCheck(object o, object[] arr); -#endif - #if FEATURE_MULTICASTSTUB_AS_IL [MethodImpl(MethodImplOptions.InternalCall)] internal static extern void MulticastDebuggerTraceHelper(object o, int count); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 7dbe5aacbefd1e..751aa245b354b9 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -939,10 +939,6 @@ DEFINE_METHOD(STUBHELPERS, PROFILER_BEGIN_TRANSITION_CALLBACK, Profiler DEFINE_METHOD(STUBHELPERS, PROFILER_END_TRANSITION_CALLBACK, ProfilerEndTransitionCallback, SM_IntPtr_IntPtr_RetVoid) #endif -#ifdef FEATURE_ARRAYSTUB_AS_IL -DEFINE_METHOD(STUBHELPERS, ARRAY_TYPE_CHECK, ArrayTypeCheck, SM_Obj_ArrObject_RetVoid) -#endif - #ifdef FEATURE_MULTICASTSTUB_AS_IL DEFINE_METHOD(STUBHELPERS, MULTICAST_DEBUGGER_TRACE_HELPER, MulticastDebuggerTraceHelper, SM_Obj_Int_RetVoid) #endif diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index 7e00292a146b17..4a9f2355f395c2 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -479,9 +479,6 @@ FCFuncStart(gStubHelperFuncs) FCFuncElement("ValidateByref", StubHelpers::ValidateByref) FCFuncElement("LogPinnedArgument", StubHelpers::LogPinnedArgument) FCFuncElement("GetStubContext", StubHelpers::GetStubContext) -#ifdef FEATURE_ARRAYSTUB_AS_IL - FCFuncElement("ArrayTypeCheck", StubHelpers::ArrayTypeCheck) -#endif //FEATURE_ARRAYSTUB_AS_IL #ifdef FEATURE_MULTICASTSTUB_AS_IL FCFuncElement("MulticastDebuggerTraceHelper", StubHelpers::MulticastDebuggerTraceHelper) #endif //FEATURE_MULTICASTSTUB_AS_IL diff --git a/src/coreclr/vm/stubhelpers.cpp b/src/coreclr/vm/stubhelpers.cpp index c5d2666826cd43..187c86f53a375f 100644 --- a/src/coreclr/vm/stubhelpers.cpp +++ b/src/coreclr/vm/stubhelpers.cpp @@ -808,32 +808,6 @@ FCIMPL1(DWORD, StubHelpers::CalcVaListSize, VARARGS *varargs) } FCIMPLEND -#ifdef FEATURE_ARRAYSTUB_AS_IL -NOINLINE static void ArrayTypeCheckSlow(Object* element, PtrArray* arr) -{ - FC_INNER_PROLOG(StubHelpers::ArrayTypeCheck); - HELPER_METHOD_FRAME_BEGIN_ATTRIB(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2); - - if (!ObjIsInstanceOf(element, arr->GetArrayElementTypeHandle())) - COMPlusThrow(kArrayTypeMismatchException); - - HELPER_METHOD_FRAME_END(); - - FC_INNER_EPILOG(); -} - -FCIMPL2(void, StubHelpers::ArrayTypeCheck, Object* element, PtrArray* arr) -{ - FCALL_CONTRACT; - - if (ObjIsInstanceOfCached(element, arr->GetArrayElementTypeHandle()) == TypeHandle::CanCast) - return; - - FC_INNER_RETURN_VOID(ArrayTypeCheckSlow(element, arr)); -} -FCIMPLEND -#endif // FEATURE_ARRAYSTUB_AS_IL - #ifdef FEATURE_MULTICASTSTUB_AS_IL FCIMPL2(void, StubHelpers::MulticastDebuggerTraceHelper, Object* element, INT32 count) { diff --git a/src/coreclr/vm/stubhelpers.h b/src/coreclr/vm/stubhelpers.h index 9f8c2a173b9147..16b3f9230fcd78 100644 --- a/src/coreclr/vm/stubhelpers.h +++ b/src/coreclr/vm/stubhelpers.h @@ -75,10 +75,6 @@ class StubHelpers static FCDECL2(void, ProfilerEndTransitionCallback, MethodDesc* pRealMD, Thread* pThread); #endif -#ifdef FEATURE_ARRAYSTUB_AS_IL - static FCDECL2(void, ArrayTypeCheck, Object*, PtrArray*); -#endif - #ifdef FEATURE_MULTICASTSTUB_AS_IL static FCDECL2(void, MulticastDebuggerTraceHelper, Object*, INT32); #endif From beae9b6725d6b2555fcb225b307275ef71bd32ff Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 13 Jun 2024 19:38:58 +0800 Subject: [PATCH 3/4] Use proper argument type for MD array --- .../src/System/Runtime/CompilerServices/CastHelpers.cs | 2 +- src/coreclr/vm/corelib.h | 2 +- src/coreclr/vm/metasig.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index 96178d937765b1..0ce8c21d17abe8 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -465,7 +465,7 @@ private static void StelemRef_Helper_NoCacheLookup(ref object? element, void* el #if FEATURE_ARRAYSTUB_AS_IL [DebuggerHidden] - private static unsafe void ArrayTypeCheck(object obj, object[] array) + private static unsafe void ArrayTypeCheck(object obj, Array array) { Debug.Assert(obj != null); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 751aa245b354b9..6db24bedadb969 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -1166,7 +1166,7 @@ DEFINE_METHOD(CASTHELPERS, UNBOX, Unbox, SM_Ptr DEFINE_METHOD(CASTHELPERS, STELEMREF, StelemRef, SM_ArrObject_IntPtr_Obj_RetVoid) DEFINE_METHOD(CASTHELPERS, LDELEMAREF, LdelemaRef, SM_ArrObject_IntPtr_PtrVoid_RetRefObj) #ifdef FEATURE_ARRAYSTUB_AS_IL -DEFINE_METHOD(CASTHELPERS, ARRAYTYPECHECK, ArrayTypeCheck, SM_Obj_ArrObject_RetVoid) +DEFINE_METHOD(CASTHELPERS, ARRAYTYPECHECK, ArrayTypeCheck, SM_Obj_Array_RetVoid) #endif #ifdef FEATURE_EH_FUNCLETS diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index 35e6472b4b8daf..b7f033fbbf54f3 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -211,7 +211,7 @@ DEFINE_METASIG(SM(IntPtr_IntPtr_IntPtr_UShrt_IntPtr_RetVoid, I I I H I, v)) DEFINE_METASIG(SM(IntPtr_Int_IntPtr_RetIntPtr, I i I, I)) DEFINE_METASIG(SM(IntPtr_IntPtr_Int_Bool_IntPtr_RetVoid, I I i F I, v)) DEFINE_METASIG(SM(IntPtr_IntPtr_Obj_RetVoid, I I j, v)) -DEFINE_METASIG(SM(Obj_ArrObject_RetVoid, j a(j), v)) +DEFINE_METASIG_T(SM(Obj_Array_RetVoid, j C(ARRAY), v)) DEFINE_METASIG(SM(Obj_IntPtr_Obj_RetVoid, j I j, v)) DEFINE_METASIG(SM(RetUIntPtr, _, U)) DEFINE_METASIG(SM(RetIntPtr, _, I)) From aeb1541fdcc2540a19701ca4c2f17cc83eb6306f Mon Sep 17 00:00:00 2001 From: Huo Yaoyuan Date: Thu, 13 Jun 2024 19:39:59 +0800 Subject: [PATCH 4/4] Add assert --- .../src/System/Runtime/CompilerServices/CastHelpers.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs index 0ce8c21d17abe8..dbc3d064acc7a0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs @@ -470,6 +470,8 @@ private static unsafe void ArrayTypeCheck(object obj, Array array) Debug.Assert(obj != null); void* elementType = RuntimeHelpers.GetMethodTable(array)->ElementType; + Debug.Assert(elementType != RuntimeHelpers.GetMethodTable(obj)); // Should be handled by caller + CastResult result = CastCache.TryGet(s_table!, (nuint)RuntimeHelpers.GetMethodTable(obj), (nuint)elementType); if (result == CastResult.CanCast) {