#endif
+#ifdef FEATURE_STUBS_AS_IL
+// DelegateObject from src/vm/object.h
+#define DelegateObject___target 0x04 // offset 0 is m_pMethTab of base class Object
+#define DelegateObject___methodBase 0x08
+#define DelegateObject___methodPtr 0x0c
+#define DelegateObject___methodPtrAux 0x10
+#define DelegateObject___invocationList 0x14
+#define DelegateObject___invocationCount 0x18
+
+ASMCONSTANTS_C_ASSERT(DelegateObject___target == offsetof(DelegateObject, _target));
+ASMCONSTANTS_C_ASSERT(DelegateObject___methodBase == offsetof(DelegateObject, _methodBase));
+ASMCONSTANTS_C_ASSERT(DelegateObject___methodPtr == offsetof(DelegateObject, _methodPtr));
+ASMCONSTANTS_C_ASSERT(DelegateObject___methodPtrAux == offsetof(DelegateObject, _methodPtrAux));
+ASMCONSTANTS_C_ASSERT(DelegateObject___invocationList == offsetof(DelegateObject, _invocationList));
+ASMCONSTANTS_C_ASSERT(DelegateObject___invocationCount == offsetof(DelegateObject, _invocationCount));
+
+#endif
+
#undef ASMCONSTANTS_C_ASSERT
#undef ASMCONSTANTS_RUNTIME_ASSERT
// Now jump to the target
jmp eax // continue on into the method
NESTED_END ResolveWorkerAsmStub, _TEXT
+
+#ifdef FEATURE_STUBS_AS_IL
+// ==========================================================================
+// void SinglecastDelegateInvokeStub();
+//
+LEAF_ENTRY SinglecastDelegateInvokeStub, _TEXT
+
+ test ecx, ecx
+ jz LOCAL_LABEL(NullObject)
+
+ mov eax, [ecx + DelegateObject___methodPtr]
+ mov ecx, [ecx + DelegateObject___target] // replace "this" pointer
+ jmp eax
+
+LOCAL_LABEL(NullObject):
+
+ mov ecx, CORINFO_NullReferenceException_ASM
+ jmp C_FUNC(JIT_InternalThrow)
+
+LEAF_END SinglecastDelegateInvokeStub, _TEXT
+#endif // FEATURE_STUBS_AS_IL
PORTABILITY_ASSERT("Implement for PAL");
}
-EXTERN_C VOID SinglecastDelegateInvokeStub()
-{
- PORTABILITY_ASSERT("SinglecastDelegateInvokeStub");
-}
-
EXTERN_C VOID ResolveWorkerChainLookupAsmStub()
{
PORTABILITY_ASSERT("ResolveWorkerChainLookupAsmStub");