summaryrefslogtreecommitdiff
path: root/src/vm/remoting.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/vm/remoting.h')
-rw-r--r--src/vm/remoting.h957
1 files changed, 957 insertions, 0 deletions
diff --git a/src/vm/remoting.h b/src/vm/remoting.h
new file mode 100644
index 0000000000..4a63df6295
--- /dev/null
+++ b/src/vm/remoting.h
@@ -0,0 +1,957 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+//
+// File: remoting.h
+//
+
+//
+// Purpose: Defines various remoting related objects such as
+// proxies
+//
+
+//
+
+
+#ifndef __REMOTING_H__
+#define __REMOTING_H__
+
+#ifndef FEATURE_REMOTING
+#error FEATURE_REMOTING is not set, please do not include remoting.h
+#endif
+
+#include "fcall.h"
+#include "stubmgr.h"
+
+// Forward declaration
+class TPMethodFrame;
+
+// <TODO>@TODO: Set the hashtable to delete the data.</TODO>
+
+// Thunk hash table - the keys are MethodDesc
+typedef EEHashTable<MethodDesc *, EEPtrHashTableHelper<MethodDesc *>, FALSE> EEThunkHashTable;
+
+// ConstVirtualThunkSize declares the size of the code generated by
+// CTPMethodTable::CreateThunkForVirtualMethod
+#ifdef _TARGET_X86_
+
+static const DWORD ConstVirtualThunkSize = sizeof(BYTE) + sizeof(DWORD) + sizeof(BYTE) + sizeof(LONG);
+
+#elif defined(_TARGET_AMD64_)
+
+static const DWORD ConstVirtualThunkSize = sizeof(DWORD) + sizeof(UINT64) + 7;
+
+#elif defined(_TARGET_ARM_)
+
+static const DWORD ConstVirtualThunkSize = 12;
+
+#else
+PORTABILITY_WARNING("Remoting thunk size not defined for this platform.")
+static const DWORD ConstVirtualThunkSize = sizeof(LPVOID);
+#endif
+
+extern "C"
+{
+ UINT_PTR __stdcall CRemotingServices__CheckForContextMatch(Object* pStubData);
+ void __stdcall CRemotingServices__DispatchInterfaceCall();
+ void __stdcall CRemotingServices__CallFieldGetter(MethodDesc *pMD, LPVOID pThis, LPVOID pFirst, LPVOID pSecond, LPVOID pThird);
+ void __stdcall CRemotingServices__CallFieldSetter(MethodDesc *pMD, LPVOID pThis, LPVOID pFirst, LPVOID pSecond, LPVOID pThird);
+}
+
+extern "C" LPVOID __stdcall CTPMethodTable__CallTargetHelper2(const void *pTarget, LPVOID pvFirst, LPVOID pvSecond);
+extern "C" LPVOID __stdcall CTPMethodTable__CallTargetHelper3(const void *pTarget, LPVOID pvFirst, LPVOID pvSecond, LPVOID pvThird);
+extern "C" BOOL __stdcall CTPMethodTable__GenericCheckForContextMatch(Object* orTP);
+
+
+// These are the values returned by RequiresManagedActivation
+enum ManagedActivationType
+{
+ NoManagedActivation = 0,
+ ManagedActivation = 0x1,
+#ifdef FEATURE_COMINTEROP
+ ComObjectType = 0x2,
+#endif // FEATURE_COMINTEROP
+};
+
+
+struct timingData
+{
+ DWORD threadId;
+ BYTE stage;
+ __int64 cycleCount;
+};
+
+
+// This struct is also accessed from managed world
+struct messageData
+{
+ PVOID pFrame;
+ MethodDesc *pMethodDesc;
+ MethodDesc *pDelegateMD;
+ MetaSig *pSig;
+ TypeHandle thGoverningType;
+ INT32 iFlags;
+};
+
+
+// The real proxy class is the class behind the
+// transparent proxy class
+class CRealProxy
+{
+public:
+ // Native helpers
+ static FCDECL2(VOID, SetStubData, Object* orRPUNSAFE, Object* orStubDataUNSAFE);
+ static FCDECL1(Object*, GetStubData, Object* orRPUNSAFE);
+ static FCDECL1(LPVOID, GetStub, Object* orRPUNSAFE);
+ static FCDECL0(LPVOID, GetDefaultStub);
+ static FCDECL1(Object*, GetProxiedType, Object* orRPUNSAFE);
+
+ static VOID UpdateOptFlags(OBJECTREF refTP);
+ static BOOL ProxyTypeIdentityCheck(MethodTable *pCliHierarchy, MethodTable *pSrvHierarchy);
+};
+
+// Forward declarations
+class CVirtualThunkMgr;
+class CNonVirtualThunkMgr;
+
+
+
+
+// Class that provides various remoting services
+// to the exposed world
+class CRemotingServices
+{
+private:
+ //+-------------------------------------------------------------------
+ //
+ // Struct: FieldArgs
+ //
+ // Synopsis: Structure to GC protect arguments for a field accessor call.
+ // DO NOT add non OBJECTREF data types in the structure
+ // see GCPROTECT_BEGIN() for a better explanation.
+ //
+ //+-------------------------------------------------------------------
+ typedef struct _FieldArgs
+ {
+ OBJECTREF obj;
+ OBJECTREF val;
+ STRINGREF typeName;
+ STRINGREF fieldName;
+ } FieldArgs;
+
+public:
+
+ // Methods related to interception of non virtual methods & virtual methods called
+ // non virtually
+ static PCODE GetNonVirtualEntryPointForVirtualMethod(MethodDesc* pMD);
+
+#ifndef HAS_REMOTING_PRECODE
+ static Stub* GetStubForNonVirtualMethod(MethodDesc* pMD, LPVOID pvAddrOfCode, Stub* pInnerStub);
+#endif
+
+ static void DestroyThunk(MethodDesc* pMD);
+
+ // Methods related to interception of interface calls
+ static PCODE GetDispatchInterfaceHelper(MethodDesc* pMD);
+
+ static OBJECTREF CreateProxyOrObject(MethodTable *pMT, BOOL fIsCom = FALSE, BOOL fIsNewObj = FALSE);
+
+ // Methods related to field accessors
+ static void FieldAccessor(FieldDesc* pFD, OBJECTREF o, LPVOID pVal, BOOL fIsGetter);
+
+ // Methods related to wrapping/unwrapping of objects
+ static OBJECTREF WrapHelper(OBJECTREF obj);
+
+ static OBJECTREF Wrap(OBJECTREF obj);
+ static OBJECTREF GetProxyFromObject(OBJECTREF obj);
+ static OBJECTREF GetObjectFromProxy(OBJECTREF obj);
+ static BOOL IsProxyToRemoteObject(OBJECTREF obj);
+ static OBJECTREF GetServerContext(OBJECTREF obj);
+
+ // Methods related to creation and marshaling of appdomains
+ static OBJECTREF CreateProxyForDomain(AppDomain *pDomain);
+
+ // Extract the true class of a proxy
+ static REFLECTCLASSBASEREF GetClass(OBJECTREF pThis);
+
+ // Initialization function.
+ static VOID Initialize();
+
+ // Start up function. This actually starts up the remoting services.
+ static void EnsureRemotingStarted();
+
+ // Other helper functions.
+ inline static MethodDesc *MDofPrivateInvoke()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pRPPrivateInvoke;
+ }
+
+ inline static MethodDesc *MDofInvokeStatic()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pRPInvokeStatic;
+ }
+
+ inline static MethodDesc *MDofIsCurrentContextOK()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pIsCurrentContextOK;
+ }
+
+ inline static MethodDesc *MDofCheckCast()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pCheckCast;
+ }
+
+ inline static MethodDesc *MDofWrap()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pWrapMethodDesc;
+ }
+
+ inline static MethodDesc *MDofFieldSetter()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pFieldSetterDesc;
+ }
+
+ inline static MethodDesc *MDofFieldGetter()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pFieldGetterDesc;
+ }
+
+ inline static MethodDesc *MDofGetType()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pGetTypeDesc;
+ }
+
+ inline static MethodDesc *MDofObjectGetType()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pObjectGetTypeDesc;
+ }
+
+#ifdef FEATURE_COMINTEROP
+ inline static MethodDesc *MDofCreateObjectForCom()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pCreateObjectForCom;
+ }
+
+
+ static BOOL CallSupportsInterface(OBJECTREF realProxy, REFIID iid, ARG_SLOT *pret);
+
+ // helpers to call methods in real proxy
+ static VOID CallSetDCOMProxy(OBJECTREF realProxy, IUnknown* pUnk);
+
+#endif // FEATURE_COMINTEROP
+
+ inline static BOOL IsInstanceOfServerIdentity(MethodTable* pMT)
+ {
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(pMT));
+ }
+ CONTRACTL_END;
+
+ return s_pServerIdentityClass == pMT;
+ }
+
+ inline static MethodTable *GetMarshalByRefClass()
+ {
+ CONTRACT (MethodTable*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pMarshalByRefObjectClass;
+ }
+
+ static INT32 IsTransparentProxy(Object* obj);
+ static Object* GetRealProxy(Object* obj);
+
+ static BOOL CheckCast(OBJECTREF orTP, TypeHandle ty);
+ static BOOL CheckCast(OBJECTREF orTP, TypeHandle objTy, TypeHandle ty);
+ static OBJECTREF GetExposedContext();
+ static AppDomain *GetServerDomainForProxy(OBJECTREF orTP);
+ static Context *GetServerContextForProxy(OBJECTREF orTP);
+ static int GetServerDomainIdForProxy(OBJECTREF orTP);
+ static UINT_PTR CheckForContextMatch(Object* pStubData);
+
+ static ManagedActivationType __stdcall RequiresManagedActivation(TypeHandle ty);
+ static BOOL IsRemotingStarted()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return s_fRemotingStarted;
+ };
+
+ static DWORD GetOffsetOfSrvIdentityInRP() { return s_dwSrvIdentityOffsetInRealProxy; }
+ static DWORD GetOffsetOfCliIdentityInRP() { return s_dwIdOffset; }
+ static DWORD GetOffsetOfTPOrObjInIdentity() { return s_dwTPOrObjOffsetInIdentity; }
+ static DWORD GetOffsetOfLeaseInIdentity() { return s_dwLeaseOffsetInIdentity; }
+ static DWORD GetOffsetOfURIInIdentity() { return s_dwURIOffsetInIdentity; }
+ inline static MethodDesc *MDofRenewLeaseOnCall() { return s_pRenewLeaseOnCallDesc; }
+
+ static PCODE GetStubForInterfaceMethod(MethodDesc *pItfMD);
+private:
+ static void StartRemoting();
+ static void CopyDestToSrc(LPVOID pDest, LPVOID pSrc, UINT cbSize);
+ static void CallFieldAccessor(FieldDesc* pFD, OBJECTREF o, VOID * pVal,
+ BOOL fIsGetter, BOOL fIsByValue, BOOL fIsGCRef,
+ TypeHandle ty, TypeHandle fldTy,
+ CorElementType fieldType, UINT cbSize);
+
+ static void GetTypeAndFieldName(FieldArgs *pArgs, FieldDesc *pFD, TypeHandle thEnclosingClass);
+ static BOOL MatchField(FieldDesc* pCurField, LPCUTF8 szFieldName);
+ static OBJECTREF SetExposedContext(OBJECTREF newContext);
+ static OBJECTREF GetServerIdentityFromProxy(OBJECTREF obj);
+ inline static MethodDesc *MDOfCreateProxyForDomain()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pProxyForDomainDesc;
+ }
+
+ inline static MethodDesc *MDofGetServerContextForProxy()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pServerContextForProxyDesc;
+ }
+
+ inline static MethodDesc *MDofGetServerDomainIdForProxy()
+ {
+ CONTRACT (MethodDesc*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN s_pServerDomainIdForProxyDesc;
+ }
+
+ static VOID InitActivationServicesClass();
+ static VOID InitRealProxyClass();
+ static VOID InitRemotingProxyClass();
+ static VOID InitServerIdentityClass();
+ static VOID InitIdentityClass();
+ static VOID InitMarshalByRefObjectClass();
+ static VOID InitRemotingServicesClass();
+ static VOID InitObjectClass();
+ static VOID InitLeaseClass();
+
+ static MethodTable *s_pMarshalByRefObjectClass;
+ static MethodTable *CRemotingServices::s_pServerIdentityClass;
+ static MethodTable *CRemotingServices::s_pContextClass;
+
+ static MethodDesc *s_pRPPrivateInvoke;
+ static MethodDesc *s_pRPInvokeStatic;
+ static MethodDesc *s_pIsCurrentContextOK;
+ static MethodDesc *s_pCheckCast;
+ static MethodDesc *s_pWrapMethodDesc;
+ static MethodDesc *s_pFieldSetterDesc;
+ static MethodDesc *s_pFieldGetterDesc;
+ static MethodDesc *s_pObjectGetTypeDesc;
+ static MethodDesc *s_pGetTypeDesc;
+ static MethodDesc *s_pProxyForDomainDesc;
+ static MethodDesc *s_pServerContextForProxyDesc;
+ static MethodDesc *s_pServerDomainIdForProxyDesc;
+ static MethodDesc *s_pRenewLeaseOnCallDesc;
+ static DWORD s_dwIdOffset;
+ static DWORD s_dwServerOffsetInRealProxy;
+ static DWORD s_dwSrvIdentityOffsetInRealProxy;
+ static DWORD s_dwTPOrObjOffsetInIdentity;
+ static DWORD s_dwLeaseOffsetInIdentity;
+ static DWORD s_dwURIOffsetInIdentity;
+ static DWORD s_dwMBRIDOffset;
+ static CrstStatic s_RemotingCrst;
+ static BOOL s_fRemotingStarted;
+
+#ifdef FEATURE_COMINTEROP
+ static MethodDesc *s_pCreateObjectForCom;
+#endif // FEATURE_COMINTEROP
+
+};
+
+// Class that manages transparent proxy thunks
+class CVirtualThunks
+{
+public:
+ inline static CVirtualThunks* GetVirtualThunks()
+ {
+ CONTRACT (CVirtualThunks*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
+ SO_TOLERANT;
+ }
+ CONTRACT_END;
+
+ RETURN s_pVirtualThunks;
+ }
+
+ inline static CVirtualThunks* SetVirtualThunks(CVirtualThunks* pThunks)
+ {
+ CONTRACT (CVirtualThunks*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(pThunks));
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN (s_pVirtualThunks = pThunks);
+ }
+
+ inline CVirtualThunks* GetNextThunk()
+ {
+ CONTRACT (CVirtualThunks*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
+ SO_TOLERANT;
+ }
+ CONTRACT_END;
+
+ RETURN _pNext;
+ }
+
+ // Public member variables
+ CVirtualThunks *_pNext;
+ DWORD _dwReservedThunks;
+ DWORD _dwStartThunk;
+ DWORD _dwCurrentThunk;
+
+#ifdef CVIRTUALTHUNKS_ALIGNPAD_BYTES
+ BYTE pad[CVIRTUALTHUNKS_ALIGNPAD_BYTES];
+#endif
+
+ struct tagThunkCode
+ {
+ BYTE pCode[ConstVirtualThunkSize];
+ } ThunkCode[1];
+
+private:
+ // Cannot be created
+ CVirtualThunks(CVirtualThunks *pNext, DWORD dwCommitedSlots, DWORD dwReservedSlots, DWORD dwStartSlot, DWORD dwCurrentSlot)
+ {
+ LIMITED_METHOD_CONTRACT;
+ }
+
+ // Private statics
+ static CVirtualThunks *s_pVirtualThunks;
+};
+
+
+#ifndef HAS_REMOTING_PRECODE
+
+class CNonVirtualThunk
+{
+public:
+ // Constructor
+ CNonVirtualThunk(const BYTE* pbCode)
+ : _addrOfCode(pbCode), _pNext(NULL)
+ {
+ WRAPPER_NO_CONTRACT;
+ }
+
+ ~CNonVirtualThunk();
+
+ inline LPVOID* GetAddrOfCode()
+ {
+ CONTRACT (LPVOID*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN (LPVOID*)&_addrOfCode;
+ }
+
+ inline const BYTE* GetThunkCode()
+ {
+ CONTRACT (const BYTE*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ SO_TOLERANT;
+ }
+ CONTRACT_END;
+
+ RETURN _addrOfCode;
+ }
+
+ inline CNonVirtualThunk* GetNextThunk()
+ {
+ CONTRACT (CNonVirtualThunk*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
+ SO_TOLERANT;
+ }
+ CONTRACT_END;
+
+ RETURN _pNext;
+ }
+
+ static void InitializeListLock();
+ static CNonVirtualThunk* AddrToThunk(LPVOID pAddr);
+ inline static CNonVirtualThunk* GetNonVirtualThunks()
+ {
+ CONTRACT (CNonVirtualThunk*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL, NULL_OK));
+ SO_TOLERANT;
+ }
+ CONTRACT_END;
+
+ RETURN s_pNonVirtualThunks;
+ }
+
+ inline static SimpleRWLock* GetThunksListLock()
+ {
+ LIMITED_METHOD_CONTRACT;
+
+ return s_pNonVirtualThunksListLock;
+ }
+
+ static CNonVirtualThunk* SetNonVirtualThunks(const BYTE* pbCode);
+
+ const BYTE* _addrOfCode;
+
+private:
+
+ void SetNextThunk();
+
+ // Private statics
+ static CNonVirtualThunk *s_pNonVirtualThunks;
+
+ // reader/writer lock to be taken when manipulating s_pNonVirtualThunks
+ static SimpleRWLock* s_pNonVirtualThunksListLock;
+
+ // Private members
+ CNonVirtualThunk* _pNext;
+};
+
+inline void CNonVirtualThunk::InitializeListLock()
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ }
+ CONTRACTL_END;
+
+ if (s_pNonVirtualThunksListLock == NULL)
+ s_pNonVirtualThunksListLock = new SimpleRWLock(COOPERATIVE_OR_PREEMPTIVE, LOCK_TYPE_DEFAULT);
+}
+
+inline void CNonVirtualThunk::SetNextThunk()
+{
+ LIMITED_METHOD_CONTRACT;
+
+ SimpleRWLock::SimpleWriteLockHolder swlh(s_pNonVirtualThunksListLock);
+
+ _pNext = s_pNonVirtualThunks;
+ s_pNonVirtualThunks = this;
+}
+
+inline CNonVirtualThunk* CNonVirtualThunk::AddrToThunk(LPVOID pAddr)
+{
+ CONTRACT (CNonVirtualThunk*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(pAddr));
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN (CNonVirtualThunk *)((size_t)pAddr - (size_t)offsetof(CNonVirtualThunk, _addrOfCode));
+}
+
+#endif // HAS_REMOTING_PRECODE
+
+
+class CTPMethodTable
+{
+ friend class CRemotingServices;
+ friend class RemotingNative;
+
+public:
+ // Public statics
+ static DWORD GetCommitedTPSlots()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return s_dwCommitedTPSlots;
+ }
+
+ static MethodTable *GetMethodTable()
+ {
+ CONTRACT (MethodTable*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ POSTCONDITION(CheckPointer(RETVAL));
+ SO_TOLERANT;
+ }
+ CONTRACT_END;
+
+ RETURN s_pThunkTable;
+ }
+
+ static VOID Initialize();
+
+#ifndef HAS_REMOTING_PRECODE
+ static PTR_PCODE GetOrCreateNonVirtualSlotForVirtualMethod(MethodDesc* pMD);
+ static PCODE CreateNonVirtualThunkForVirtualMethod(MethodDesc* pMD);
+ static Stub* CreateStubForNonVirtualMethod(MethodDesc* pMD, CPUSTUBLINKER *psl, LPVOID pvAddrOfCode, Stub* pInnerStub);
+#endif // HAS_REMOTING_PRECODE
+
+ static REALPROXYREF GetRP(OBJECTREF orTP);
+ static MethodTable * GetMethodTableBeingProxied(OBJECTREF orTP);
+
+ static LPVOID __stdcall CallTarget(MethodDesc* pTargetMD, LPVOID pvFirst, LPVOID pvSecond);
+ static LPVOID __stdcall CallTarget(MethodDesc* pTargetMD, LPVOID pvFirst, LPVOID pvSecond, LPVOID pvThird);
+ static BOOL CheckCastHelper(MethodDesc* pTargetMD, LPVOID pvFirst, LPVOID pvSecond);
+ static BOOL CheckCast(MethodDesc* pTargetMD, TRANSPARENTPROXYREF orTP, TypeHandle ty);
+ static void RefineProxy(TRANSPARENTPROXYREF orTP, TypeHandle ty);
+
+ static PCODE GetTPStubEntryPoint();
+ static PCODE GetDelegateStubEntryPoint();
+
+ static void DestroyThunk(MethodDesc* pMD);
+
+ // Interpretation of __TransparentProxy._stub
+ typedef UINT_PTR CheckContextCrossingProc (Object*);
+
+ inline static BOOL IsInstanceOfRemotingProxy(MethodTable *pMT)
+ {
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(pMT));
+ }
+ CONTRACTL_END;
+
+ return s_pRemotingProxyClass == pMT;
+ }
+
+private:
+
+#ifndef DACCESS_COMPILE
+
+ // Private statics
+ static void InitThunkTable(DWORD dwCommitedTPSlots, DWORD dwReservedTPSlots, MethodTable* pTPMethodTable)
+ {
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(pTPMethodTable));
+ }
+ CONTRACTL_END;
+
+ s_dwCommitedTPSlots = dwCommitedTPSlots;
+ s_dwReservedTPSlots = dwReservedTPSlots;
+ s_pThunkTable = pTPMethodTable;
+ }
+
+
+ static void DestroyThunkTable()
+ {
+ WRAPPER_NO_CONTRACT;
+ ::ClrVirtualFree(MTToAlloc(s_pThunkTable, s_dwGCInfoBytes), 0, MEM_RELEASE);
+ s_pThunkTable = NULL;
+ s_dwCommitedTPSlots = 0;
+ s_dwReservedTPSlots = 0;
+ }
+
+#endif // #ifndef DACCESS_COMPILE
+
+ static void EnsureFieldsInitialized();
+
+ static void CreateTPOfClassForRP(TypeHandle ty, REALPROXYREF *pRP, TRANSPARENTPROXYREF *pTP);
+ static void CreateTPMethodTable(MethodTable* pTPMT);
+ static BOOL ExtendCommitedSlots(_In_range_(1,64*1024) DWORD dwSlots);
+ static BOOL AllocateThunks(DWORD dwSlots, DWORD dwCommitSize);
+#ifdef HAS_REMOTING_PRECODE
+ static void ActivatePrecodeRemotingThunk();
+#endif // HAS_REMOTING_PRECODE
+ static MethodTable *AllocToMT(BYTE *Alloc, LONG off)
+ {
+ CONTRACT (MethodTable*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(Alloc));
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN (MethodTable *) (Alloc + off);
+ }
+
+ static BYTE *MTToAlloc(MethodTable *MT, LONG off)
+ {
+ CONTRACT (BYTE*)
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ PRECONDITION(CheckPointer(MT));
+ POSTCONDITION(CheckPointer(RETVAL));
+ }
+ CONTRACT_END;
+
+ RETURN (((BYTE *) MT) - off);
+ }
+
+ static PCODE CreateThunkForVirtualMethod(DWORD dwSlot, BYTE *bCode);
+
+ // Static members
+ static DWORD s_dwCommitedTPSlots;
+ static DWORD s_dwReservedTPSlots;
+ static DWORD s_dwReservedTPIndirectionSlotSize;
+ SPTR_DECL(MethodTable, s_pThunkTable);
+ static MethodTable* s_pRemotingProxyClass;
+ static DWORD s_dwGCInfoBytes;
+ static DWORD s_dwMTDataSlots;
+ static CrstStatic s_TPMethodTableCrst;
+ static EEThunkHashTable *s_pThunkHashTable;
+ static BOOL s_fTPTableFieldsInitialized;
+};
+
+extern "C" UINT32 STDCALL TransparentProxyStubWorker(TransitionBlock * pTransitionBlock, TADDR pMethodDescOrSlot);
+
+// Holder for remoting profiler notifications
+class ProfilerRemotingClientCallbackHolder
+{
+public:
+ ProfilerRemotingClientCallbackHolder();
+ ~ProfilerRemotingClientCallbackHolder();
+};
+
+// These stub manager classes help the debugger to step
+// through the various stubs and thunks generated by the
+// remoting infrastructure
+class CVirtualThunkMgr :public StubManager
+{
+ friend class CTPMethodTable;
+
+ VPTR_VTABLE_CLASS(CVirtualThunkMgr, StubManager)
+
+public:
+ static void InitVirtualThunkManager();
+#ifndef DACCESS_COMPILE
+ CVirtualThunkMgr()
+ {
+ WRAPPER_NO_CONTRACT;
+ }
+#endif
+
+public:
+#ifdef _DEBUG
+ virtual const char * DbgGetName() { LIMITED_METHOD_CONTRACT; return "CVirtualThunkMgr"; }
+#endif
+
+ virtual BOOL CheckIsStub_Internal(PCODE stubStartAddress);
+
+ virtual BOOL DoTraceStub(PCODE stubStartAddress, TraceDestination *trace) DAC_EMPTY_RET(FALSE);
+
+ static MethodDesc *Entry2MethodDesc(PCODE StubStartAddress, MethodTable *pMT);
+
+private:
+ // Private methods
+ LPBYTE FindThunk(const BYTE *stubStartAddress);
+ static MethodDesc *GetMethodDescByASM(PCODE startaddr, MethodTable *pMT);
+ static BOOL IsThunkByASM(PCODE startaddr);
+
+ // Private statics
+ static CVirtualThunkMgr *s_pVirtualThunkMgr;
+
+#ifdef DACCESS_COMPILE
+protected:
+ virtual LPCWSTR GetStubManagerName(PCODE addr)
+ { LIMITED_METHOD_CONTRACT; return W("CVirtualThunk"); }
+#endif
+};
+
+
+#ifndef HAS_REMOTING_PRECODE
+
+class CNonVirtualThunkMgr :public StubManager
+{
+ friend class CTPMethodTable;
+
+ VPTR_VTABLE_CLASS(CNonVirtualThunkMgr, StubManager)
+
+public:
+ static void InitNonVirtualThunkManager();
+
+public:
+#ifdef _DEBUG
+ virtual const char * DbgGetName() { return "CNonVirtualThunkMgr"; }
+#endif
+
+ virtual BOOL CheckIsStub_Internal(PCODE stubStartAddress);
+
+ virtual BOOL DoTraceStub(PCODE stubStartAddress, TraceDestination *trace) DAC_EMPTY_RET(FALSE);
+
+ virtual BOOL TraceManager(Thread *thread,
+ TraceDestination *trace,
+ CONTEXT *pContext,
+ BYTE **pRetAddr) DAC_EMPTY_RET(FALSE);
+
+ static MethodDesc *Entry2MethodDesc(PCODE StubStartAddress, MethodTable *pMT);
+
+private:
+ // Private methods
+ CNonVirtualThunk* FindThunk(const BYTE *stubStartAddress);
+ static MethodDesc *GetMethodDescByASM(PCODE startaddr);
+ static BOOL IsThunkByASM(PCODE startaddr);
+
+ // Private statics
+ static CNonVirtualThunkMgr *s_pNonVirtualThunkMgr;
+
+#ifdef DACCESS_COMPILE
+protected:
+ virtual LPCWSTR GetStubManagerName(PCODE addr)
+ { LIMITED_METHOD_CONTRACT; return W("CNonVirtualThunk"); }
+#endif
+};
+
+#endif // HAS_REMOTING_PRECODE
+
+#endif // __REMOTING_H__