@@ -1630,6 +1630,10 @@ NDirectStubLinker::NDirectStubLinker(
1630
1630
m_pcsSetup->EmitSTLOC (m_dwTargetInterfacePointerLocalNum);
1631
1631
}
1632
1632
#endif // FEATURE_COMINTEROP
1633
+
1634
+ #if defined(TARGET_X86) && defined(TARGET_WINDOWS)
1635
+ m_dwCopyCtorChainLocalNum = (DWORD)-1 ;
1636
+ #endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
1633
1637
}
1634
1638
1635
1639
void NDirectStubLinker::SetCallingConvention (CorInfoCallConvExtension unmngCallConv, BOOL fIsVarArg )
@@ -1842,6 +1846,23 @@ DWORD NDirectStubLinker::GetReturnValueLocalNum()
1842
1846
return m_dwRetValLocalNum;
1843
1847
}
1844
1848
1849
+ #if defined(TARGET_X86) && defined(TARGET_WINDOWS)
1850
+ DWORD NDirectStubLinker::GetCopyCtorChainLocalNum ()
1851
+ {
1852
+ STANDARD_VM_CONTRACT;
1853
+
1854
+ if (m_dwCopyCtorChainLocalNum == (DWORD)-1 )
1855
+ {
1856
+ // The local is created and initialized lazily when first asked.
1857
+ m_dwCopyCtorChainLocalNum = NewLocal (CoreLibBinder::GetClass (CLASS__COPY_CONSTRUCTOR_CHAIN));
1858
+ m_pcsSetup->EmitLDLOCA (m_dwCopyCtorChainLocalNum);
1859
+ m_pcsSetup->EmitINITOBJ (m_pcsSetup->GetToken (CoreLibBinder::GetClass (CLASS__COPY_CONSTRUCTOR_CHAIN)));
1860
+ }
1861
+
1862
+ return m_dwCopyCtorChainLocalNum;
1863
+ }
1864
+ #endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
1865
+
1845
1866
BOOL NDirectStubLinker::IsCleanupNeeded ()
1846
1867
{
1847
1868
LIMITED_METHOD_CONTRACT;
@@ -2071,6 +2092,10 @@ void NDirectStubLinker::End(DWORD dwStubFlags)
2071
2092
}
2072
2093
}
2073
2094
2095
+ #if defined(TARGET_X86) && defined(TARGET_WINDOWS)
2096
+ EXTERN_C void STDCALL CopyConstructorCallStub (void );
2097
+ #endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
2098
+
2074
2099
void NDirectStubLinker::DoNDirect (ILCodeStream *pcsEmit, DWORD dwStubFlags, MethodDesc * pStubMD)
2075
2100
{
2076
2101
STANDARD_VM_CONTRACT;
@@ -2154,6 +2179,21 @@ void NDirectStubLinker::DoNDirect(ILCodeStream *pcsEmit, DWORD dwStubFlags, Meth
2154
2179
}
2155
2180
}
2156
2181
2182
+ #if defined(TARGET_X86) && defined(TARGET_WINDOWS)
2183
+ if (m_dwCopyCtorChainLocalNum != (DWORD)-1 )
2184
+ {
2185
+ // If we have a copy constructor chain local, we need to call the copy constructor stub
2186
+ // to ensure that the chain is called correctly.
2187
+ // Let's install the stub chain here and redirect the call to the stub.
2188
+ DWORD targetLoc = NewLocal (ELEMENT_TYPE_I);
2189
+ pcsEmit->EmitSTLOC (targetLoc);
2190
+ pcsEmit->EmitLDLOCA (m_dwCopyCtorChainLocalNum);
2191
+ pcsEmit->EmitLDLOC (targetLoc);
2192
+ pcsEmit->EmitCALL (METHOD__COPY_CONSTRUCTOR_CHAIN__INSTALL, 2 , 0 );
2193
+ pcsEmit->EmitLDC ((DWORD_PTR)&CopyConstructorCallStub);
2194
+ }
2195
+ #endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
2196
+
2157
2197
// For managed-to-native calls, the rest of the work is done by the JIT. It will
2158
2198
// erect InlinedCallFrame, flip GC mode, and use the specified calling convention
2159
2199
// to call the target. For native-to-managed calls, this is an ordinary managed
@@ -6101,5 +6141,21 @@ PCODE GetILStubForCalli(VASigCookie *pVASigCookie, MethodDesc *pMD)
6101
6141
RETURN pVASigCookie->pNDirectILStub ;
6102
6142
}
6103
6143
6144
+ #if defined(TARGET_X86) && defined(TARGET_WINDOWS)
6145
+ // Copy constructor support for C++/CLI
6146
+ EXTERN_C void * STDCALL CallCopyConstructorsWorker (void * esp)
6147
+ {
6148
+ STATIC_CONTRACT_THROWS;
6149
+ STATIC_CONTRACT_GC_TRIGGERS;
6150
+ STATIC_CONTRACT_MODE_PREEMPTIVE; // we've already switched to preemptive
6151
+
6152
+ using ExecuteCallback = void *(STDMETHODCALLTYPE*)(void *);
6153
+
6154
+ MethodDesc* pMD = CoreLibBinder::GetMethod (METHOD__COPY_CONSTRUCTOR_CHAIN__EXECUTE_CURRENT_COPIES_AND_GET_TARGET);
6155
+ ExecuteCallback pExecute = (ExecuteCallback)pMD->GetMultiCallableAddrOfCode ();
6156
+
6157
+ return pExecute (esp);
6158
+ }
6159
+ #endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
6104
6160
6105
6161
#endif // #ifndef DACCESS_COMPILE
0 commit comments