@@ -728,9 +728,6 @@ VOID GenerateShuffleArray(MethodDesc* pInvoke, MethodDesc *pTargetMeth, SArray<S
728728
729729
730730ShuffleThunkCache *COMDelegate::m_pShuffleThunkCache = NULL ;
731- #ifndef FEATURE_MULTICASTSTUB_AS_IL
732- MulticastStubCache *COMDelegate::m_pMulticastStubCache = NULL ;
733- #endif
734731
735732CrstStatic COMDelegate::s_DelegateToFPtrHashCrst;
736733PtrHashMap* COMDelegate::s_pDelegateToFPtrHash = NULL ;
@@ -755,9 +752,6 @@ void COMDelegate::Init()
755752 s_pDelegateToFPtrHash->Init (TRUE , &lock);
756753
757754 m_pShuffleThunkCache = new ShuffleThunkCache (SystemDomain::GetGlobalLoaderAllocator ()->GetStubHeap ());
758- #ifndef FEATURE_MULTICASTSTUB_AS_IL
759- m_pMulticastStubCache = new MulticastStubCache ();
760- #endif
761755}
762756
763757#ifdef FEATURE_COMINTEROP
@@ -2139,7 +2133,6 @@ FCIMPL1(MethodDesc*, COMDelegate::GetInvokeMethod, Object* refThisIn)
21392133}
21402134FCIMPLEND
21412135
2142- #ifdef FEATURE_MULTICASTSTUB_AS_IL
21432136FCIMPL1 (PCODE, COMDelegate::GetMulticastInvoke, Object* refThisIn)
21442137{
21452138 FCALL_CONTRACT;
@@ -2166,49 +2159,34 @@ FCIMPL1(PCODE, COMDelegate::GetMulticastInvoke, Object* refThisIn)
21662159
21672160 ILCodeStream *pCode = sl.NewCodeStream (ILStubLinker::kDispatch );
21682161
2169- DWORD dwInvocationCountNum = pCode->NewLocal (ELEMENT_TYPE_I4);
21702162 DWORD dwLoopCounterNum = pCode->NewLocal (ELEMENT_TYPE_I4);
21712163
21722164 DWORD dwReturnValNum = -1 ;
21732165 if (fReturnVal )
21742166 dwReturnValNum = pCode->NewLocal (sig.GetRetTypeHandleNT ());
21752167
21762168 ILCodeLabel *nextDelegate = pCode->NewCodeLabel ();
2177- ILCodeLabel *endOfMethod = pCode->NewCodeLabel ();
2178-
2179- // Get count of delegates
2180- pCode->EmitLoadThis ();
2181- pCode->EmitLDFLD (pCode->GetToken (CoreLibBinder::GetField (FIELD__MULTICAST_DELEGATE__INVOCATION_COUNT)));
2182- pCode->EmitSTLOC (dwInvocationCountNum);
2169+ ILCodeLabel *checkCount = pCode->NewCodeLabel ();
21832170
21842171 // initialize counter
21852172 pCode->EmitLDC (0 );
21862173 pCode->EmitSTLOC (dwLoopCounterNum);
21872174
2175+ // Make the shape of the loop similar to what C# compiler emits
2176+ pCode->EmitBR (checkCount);
2177+
21882178 // Label_nextDelegate:
21892179 pCode->EmitLabel (nextDelegate);
21902180
2191- #ifdef DEBUGGING_SUPPORTED
2192- pCode->EmitLoadThis ();
2193- pCode->EmitLDLOC (dwLoopCounterNum);
2194- pCode->EmitCALL (METHOD__STUBHELPERS__MULTICAST_DEBUGGER_TRACE_HELPER, 2 , 0 );
2195- #endif // DEBUGGING_SUPPORTED
2196-
2197- // compare LoopCounter with InvocationCount. If equal then branch to Label_endOfMethod
2198- pCode->EmitLDLOC (dwLoopCounterNum);
2199- pCode->EmitLDLOC (dwInvocationCountNum);
2200- pCode->EmitBEQ (endOfMethod);
2201-
22022181 // Load next delegate from array using LoopCounter as index
22032182 pCode->EmitLoadThis ();
22042183 pCode->EmitLDFLD (pCode->GetToken (CoreLibBinder::GetField (FIELD__MULTICAST_DELEGATE__INVOCATION_LIST)));
22052184 pCode->EmitLDLOC (dwLoopCounterNum);
22062185 pCode->EmitLDELEM_REF ();
22072186
22082187 // Load the arguments
2209- UINT paramCount = 0 ;
2210- while (paramCount < sig.NumFixedArgs ())
2211- pCode->EmitLDARG (paramCount++);
2188+ for (UINT paramCount = 0 ; paramCount < sig.NumFixedArgs (); paramCount++)
2189+ pCode->EmitLDARG (paramCount);
22122190
22132191 // call the delegate
22142192 pCode->EmitCALL (pCode->GetToken (pMD), sig.NumFixedArgs (), fReturnVal );
@@ -2223,11 +2201,31 @@ FCIMPL1(PCODE, COMDelegate::GetMulticastInvoke, Object* refThisIn)
22232201 pCode->EmitADD ();
22242202 pCode->EmitSTLOC (dwLoopCounterNum);
22252203
2226- // branch to next delegate
2227- pCode->EmitBR (nextDelegate);
2204+ // Label_checkCount
2205+ pCode->EmitLabel (checkCount);
2206+
2207+ #ifdef DEBUGGING_SUPPORTED
2208+ ILCodeLabel *invokeTraceHelper = pCode->NewCodeLabel ();
2209+ ILCodeLabel *debuggerCheckEnd = pCode->NewCodeLabel ();
2210+
2211+ // Call MulticastDebuggerTraceHelper only if any debugger is attached
2212+ pCode->EmitLDC ((DWORD_PTR)&g_CORDebuggerControlFlags);
2213+ pCode->EmitCONV_I ();
2214+ pCode->EmitLDIND_I4 ();
22282215
2229- // Label_endOfMethod
2230- pCode->EmitLabel (endOfMethod);
2216+ // (g_CORDebuggerControlFlags & DBCF_ATTACHED) != 0
2217+ pCode->EmitLDC (DBCF_ATTACHED);
2218+ pCode->EmitAND ();
2219+ pCode->EmitBRTRUE (invokeTraceHelper);
2220+
2221+ pCode->EmitLabel (debuggerCheckEnd);
2222+ #endif // DEBUGGING_SUPPORTED
2223+
2224+ // compare LoopCounter with InvocationCount. If less then branch to nextDelegate
2225+ pCode->EmitLDLOC (dwLoopCounterNum);
2226+ pCode->EmitLoadThis ();
2227+ pCode->EmitLDFLD (pCode->GetToken (CoreLibBinder::GetField (FIELD__MULTICAST_DELEGATE__INVOCATION_COUNT)));
2228+ pCode->EmitBLT (nextDelegate);
22312229
22322230 // load the return value. return value from the last delegate call is returned
22332231 if (fReturnVal )
@@ -2236,6 +2234,17 @@ FCIMPL1(PCODE, COMDelegate::GetMulticastInvoke, Object* refThisIn)
22362234 // return
22372235 pCode->EmitRET ();
22382236
2237+ #ifdef DEBUGGING_SUPPORTED
2238+ // Emit debugging support at the end of the method for better perf
2239+ pCode->EmitLabel (invokeTraceHelper);
2240+
2241+ pCode->EmitLoadThis ();
2242+ pCode->EmitLDLOC (dwLoopCounterNum);
2243+ pCode->EmitCALL (METHOD__STUBHELPERS__MULTICAST_DEBUGGER_TRACE_HELPER, 2 , 0 );
2244+
2245+ pCode->EmitBR (debuggerCheckEnd);
2246+ #endif // DEBUGGING_SUPPORTED
2247+
22392248 PCCOR_SIGNATURE pSig;
22402249 DWORD cbSig;
22412250
@@ -2260,66 +2269,6 @@ FCIMPL1(PCODE, COMDelegate::GetMulticastInvoke, Object* refThisIn)
22602269}
22612270FCIMPLEND
22622271
2263- #else // FEATURE_MULTICASTSTUB_AS_IL
2264-
2265- FCIMPL1 (PCODE, COMDelegate::GetMulticastInvoke, Object* refThisIn)
2266- {
2267- FCALL_CONTRACT;
2268-
2269- OBJECTREF refThis = ObjectToOBJECTREF (refThisIn);
2270- MethodTable *pDelegateMT = refThis->GetMethodTable ();
2271-
2272- DelegateEEClass *delegateEEClass = ((DelegateEEClass*)(pDelegateMT->GetClass ()));
2273- Stub *pStub = delegateEEClass->m_pMultiCastInvokeStub ;
2274- if (pStub == NULL )
2275- {
2276- MethodDesc* pMD = delegateEEClass->GetInvokeMethod ();
2277-
2278- HELPER_METHOD_FRAME_BEGIN_RET_0 ();
2279-
2280- GCX_PREEMP ();
2281-
2282- MetaSig sig (pMD);
2283-
2284- UINT_PTR hash = CPUSTUBLINKER::HashMulticastInvoke (&sig);
2285-
2286- pStub = m_pMulticastStubCache->GetStub (hash);
2287- if (!pStub)
2288- {
2289- CPUSTUBLINKER sl;
2290-
2291- LOG ((LF_CORDB,LL_INFO10000, " COMD::GIMS making a multicast delegate\n " ));
2292-
2293- sl.EmitMulticastInvoke (hash);
2294-
2295- // The cache is process-wide, based on signature. It never unloads
2296- Stub *pCandidate = sl.Link (SystemDomain::GetGlobalLoaderAllocator ()->GetStubHeap (), NEWSTUB_FL_MULTICAST);
2297-
2298- Stub *pWinner = m_pMulticastStubCache->AttemptToSetStub (hash,pCandidate);
2299- ExecutableWriterHolder<Stub> candidateWriterHolder (pCandidate, sizeof (Stub));
2300- candidateWriterHolder.GetRW ()->DecRef ();
2301-
2302- if (!pWinner)
2303- COMPlusThrowOM ();
2304-
2305- LOG ((LF_CORDB,LL_INFO10000, " Putting a MC stub at 0x%p (code:0x%p)\n " ,
2306- pWinner, (BYTE*)pWinner+sizeof (Stub)));
2307-
2308- pStub = pWinner;
2309- }
2310-
2311- // we don't need to do an InterlockedCompareExchange here - the m_pMulticastStubCache->AttemptToSetStub
2312- // will make sure all threads racing here will get the same stub, so they'll all store the same value
2313- delegateEEClass->m_pMultiCastInvokeStub = pStub;
2314-
2315- HELPER_METHOD_FRAME_END ();
2316- }
2317-
2318- return pStub->GetEntryPoint ();
2319- }
2320- FCIMPLEND
2321- #endif // FEATURE_MULTICASTSTUB_AS_IL
2322-
23232272PCODE COMDelegate::GetWrapperInvoke (MethodDesc* pMD)
23242273{
23252274 CONTRACTL
0 commit comments