diff options
Diffstat (limited to 'src/vm/remoting.h')
-rw-r--r-- | src/vm/remoting.h | 957 |
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__ |