Fix the bug that Secure Delegate Stubs are compiled every time. (dotnet/coreclr#8592)
authorSujin Kim <sjsujin.kim@samsung.com>
Tue, 20 Dec 2016 06:53:51 +0000 (15:53 +0900)
committerJan Kotas <jkotas@microsoft.com>
Tue, 20 Dec 2016 06:53:51 +0000 (22:53 -0800)
* Fix the bug that Secure Delegate Stubs are compiled every time.

I found that Secure Delegate stubs are compiled every time during application execution, which has a negative impact on execution performance. dotnet/coreclr#8554

Like the GetMulticastInvoke() method, GetSecureInvoke() checks the hashtable when the method is executed and uses it if it already exists.

* Fix pDelMT bug and change file rights

Commit migrated from https://github.com/dotnet/coreclr/commit/dea1b9e5c0393daa420831eb74177b1fd6546181

src/coreclr/src/vm/class.cpp
src/coreclr/src/vm/class.h
src/coreclr/src/vm/comdelegate.cpp

index 0b9efd5..cff71f3 100644 (file)
@@ -3068,6 +3068,7 @@ void EEClass::Fixup(DataImage *image, MethodTable *pMT)
         image->ZeroPointerField(this, offsetof(DelegateEEClass, m_pUMThunkMarshInfo));
         image->ZeroPointerField(this, offsetof(DelegateEEClass, m_pStaticCallStub));
         image->ZeroPointerField(this, offsetof(DelegateEEClass, m_pMultiCastInvokeStub));
+        image->ZeroPointerField(this, offsetof(DelegateEEClass, m_pSecureDelegateInvokeStub));
         image->ZeroPointerField(this, offsetof(DelegateEEClass, m_pMarshalStub));
 
 #ifdef FEATURE_COMINTEROP
index 391955d..7517863 100644 (file)
@@ -2416,6 +2416,7 @@ public:
     PTR_Stub            m_pInstRetBuffCallStub;
     PTR_MethodDesc      m_pInvokeMethod;
     PTR_Stub            m_pMultiCastInvokeStub;
+    PTR_Stub            m_pSecureDelegateInvokeStub;
     UMThunkMarshInfo*   m_pUMThunkMarshInfo;
     PTR_MethodDesc      m_pBeginInvokeMethod;
     PTR_MethodDesc      m_pEndInvokeMethod;
index 0246611..c6b3df4 100644 (file)
@@ -2931,47 +2931,61 @@ PCODE COMDelegate::GetSecureInvoke(MethodDesc* pMD)
 #ifdef FEATURE_CAS_POLICY
 #error GetSecureInvoke not implemented
 #else
-    GCX_PREEMP();
+    MethodTable *       pDelegateMT = pMD->GetMethodTable();
+    DelegateEEClass*    delegateEEClass = (DelegateEEClass*) pDelegateMT->GetClass();
+    Stub *pStub = delegateEEClass->m_pSecureDelegateInvokeStub;
+
+    if (pStub == NULL)
+    {
+
+        GCX_PREEMP();
+
+        MetaSig sig(pMD);
+
+        BOOL fReturnVal = !sig.IsReturnTypeVoid();
+
+        SigTypeContext emptyContext;
+        ILStubLinker sl(pMD->GetModule(), pMD->GetSignature(), &emptyContext, pMD, TRUE, TRUE, FALSE);
 
-    MetaSig sig(pMD);
+        ILCodeStream *pCode = sl.NewCodeStream(ILStubLinker::kDispatch);
 
-    BOOL fReturnVal = !sig.IsReturnTypeVoid();
+        // Load the "real" delegate
+        pCode->EmitLoadThis();
+        pCode->EmitLDFLD(pCode->GetToken(MscorlibBinder::GetField(FIELD__MULTICAST_DELEGATE__INVOCATION_LIST)));
 
-    SigTypeContext emptyContext;
-    ILStubLinker sl(pMD->GetModule(), pMD->GetSignature(), &emptyContext, pMD, TRUE, TRUE, FALSE);
+        // Load the arguments
+        UINT paramCount = 0;
+        while(paramCount < sig.NumFixedArgs())
+          pCode->EmitLDARG(paramCount++);
 
-    ILCodeStream *pCode = sl.NewCodeStream(ILStubLinker::kDispatch);
+        // Call the delegate
+        pCode->EmitCALL(pCode->GetToken(pMD), sig.NumFixedArgs(), fReturnVal);
 
-    // Load the "real" delegate
-    pCode->EmitLoadThis();
-    pCode->EmitLDFLD(pCode->GetToken(MscorlibBinder::GetField(FIELD__MULTICAST_DELEGATE__INVOCATION_LIST)));
+        // Return
+        pCode->EmitRET();
 
-    // Load the arguments
-    UINT paramCount = 0;
-    while(paramCount < sig.NumFixedArgs())
-      pCode->EmitLDARG(paramCount++);
+        PCCOR_SIGNATURE pSig;
+        DWORD cbSig;
 
-    // Call the delegate
-    pCode->EmitCALL(pCode->GetToken(pMD), sig.NumFixedArgs(), fReturnVal);
+        pMD->GetSig(&pSig,&cbSig);
 
-    // Return
-    pCode->EmitRET();
+        MethodDesc* pStubMD =
+          ILStubCache::CreateAndLinkNewILStubMethodDesc(pMD->GetLoaderAllocator(),
+                                                        pMD->GetMethodTable(),
+                                                        ILSTUB_SECUREDELEGATE_INVOKE,
+                                                        pMD->GetModule(),
+                                                        pSig, cbSig,
+                                                        NULL,
+                                                        &sl);
 
-    PCCOR_SIGNATURE pSig;
-    DWORD cbSig;
+        pStub = Stub::NewStub(JitILStub(pStubMD));
 
-    pMD->GetSig(&pSig,&cbSig);
+           g_IBCLogger.LogEEClassCOWTableAccess(pDelegateMT);
 
-    MethodDesc* pStubMD =
-      ILStubCache::CreateAndLinkNewILStubMethodDesc(pMD->GetLoaderAllocator(),
-                                                    pMD->GetMethodTable(),
-                                                    ILSTUB_SECUREDELEGATE_INVOKE,
-                                                    pMD->GetModule(),
-                                                    pSig, cbSig,
-                                                    NULL,
-                                                    &sl);
+           InterlockedCompareExchangeT<PTR_Stub>(EnsureWritablePages(&delegateEEClass->m_pSecureDelegateInvokeStub), pStub, NULL);
 
-    return Stub::NewStub(JitILStub(pStubMD))->GetEntryPoint();
+    }
+    return pStub->GetEntryPoint();
 #endif
 }
 #else // FEATURE_STUBS_AS_IL
@@ -2986,33 +3000,45 @@ PCODE COMDelegate::GetSecureInvoke(MethodDesc* pMD)
     }
     CONTRACT_END;
 
-    GCX_PREEMP();
+    MethodTable *       pDelegateMT = pMD->GetMethodTable();
+    DelegateEEClass*    delegateEEClass = (DelegateEEClass*) pDelegateMT->GetClass();
+
+       Stub *pStub = delegateEEClass->m_pSecureDelegateInvokeStub;
+
+       if (pStub == NULL)
+       {
+        GCX_PREEMP();
     
-    MetaSig sig(pMD);
+        MetaSig sig(pMD);
 
-    UINT_PTR hash = CPUSTUBLINKER::HashMulticastInvoke(&sig);
+        UINT_PTR hash = CPUSTUBLINKER::HashMulticastInvoke(&sig);
 
-    Stub *pStub = m_pSecureDelegateStubCache->GetStub(hash);
-    if (!pStub)
-    {
-        CPUSTUBLINKER sl;
+        pStub = m_pSecureDelegateStubCache->GetStub(hash);
+        if (!pStub)
+        {
+            CPUSTUBLINKER sl;
 
-        LOG((LF_CORDB,LL_INFO10000, "COMD::GIMS making a multicast delegate\n"));
-        sl.EmitSecureDelegateInvoke(hash);
+            LOG((LF_CORDB,LL_INFO10000, "COMD::GIMS making a multicast delegate\n"));
+            sl.EmitSecureDelegateInvoke(hash);
 
-        // The cache is process-wide, based on signature.  It never unloads
-        Stub *pCandidate = sl.Link(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_MULTICAST);
+            // The cache is process-wide, based on signature.  It never unloads
+            Stub *pCandidate = sl.Link(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap(), NEWSTUB_FL_MULTICAST);
+
+            Stub *pWinner = m_pSecureDelegateStubCache->AttemptToSetStub(hash, pCandidate);
+            pCandidate->DecRef();
+            if (!pWinner)
+                COMPlusThrowOM();
 
-        Stub *pWinner = m_pSecureDelegateStubCache->AttemptToSetStub(hash, pCandidate);
-        pCandidate->DecRef();
-        if (!pWinner)
-            COMPlusThrowOM();
+            LOG((LF_CORDB,LL_INFO10000, "Putting a MC stub at 0x%x (code:0x%x)\n",
+                pWinner, (BYTE*)pWinner+sizeof(Stub)));
 
-        LOG((LF_CORDB,LL_INFO10000, "Putting a MC stub at 0x%x (code:0x%x)\n",
-            pWinner, (BYTE*)pWinner+sizeof(Stub)));
+            pStub = pWinner;
+        }
 
-        pStub = pWinner;
-    }
+               g_IBCLogger.LogEEClassCOWTableAccess(pDelegateMT);
+        EnsureWritablePages(&delegateEEClass->m_pSecureDelegateInvokeStub);
+        delegateEEClass->m_pSecureDelegateInvokeStub = pStub;
+       }
     RETURN (pStub->GetEntryPoint());
 }
 #endif // FEATURE_STUBS_AS_IL