@@ -1623,6 +1623,10 @@ NDirectStubLinker::NDirectStubLinker(
1623
1623
m_pcsSetup->EmitSTLOC (m_dwTargetInterfacePointerLocalNum);
1624
1624
}
1625
1625
#endif // FEATURE_COMINTEROP
1626
+
1627
+ #if defined(TARGET_X86) && defined(TARGET_WINDOWS)
1628
+ m_dwCopyCtorChainLocalNum = (DWORD)-1 ;
1629
+ #endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
1626
1630
}
1627
1631
1628
1632
void NDirectStubLinker::SetCallingConvention (CorInfoCallConvExtension unmngCallConv, BOOL fIsVarArg )
@@ -1835,6 +1839,23 @@ DWORD NDirectStubLinker::GetReturnValueLocalNum()
1835
1839
return m_dwRetValLocalNum;
1836
1840
}
1837
1841
1842
+ #if defined(TARGET_X86) && defined(TARGET_WINDOWS)
1843
+ DWORD NDirectStubLinker::GetCopyCtorChainLocalNum ()
1844
+ {
1845
+ STANDARD_VM_CONTRACT;
1846
+
1847
+ if (m_dwCopyCtorChainLocalNum == (DWORD)-1 )
1848
+ {
1849
+ // The local is created and initialized lazily when first asked.
1850
+ m_dwCopyCtorChainLocalNum = NewLocal (CoreLibBinder::GetClass (CLASS__COPY_CONSTRUCTOR_CHAIN));
1851
+ m_pcsSetup->EmitLDLOCA (m_dwCopyCtorChainLocalNum);
1852
+ m_pcsSetup->EmitINITOBJ (m_pcsSetup->GetToken (CoreLibBinder::GetClass (CLASS__COPY_CONSTRUCTOR_CHAIN)));
1853
+ }
1854
+
1855
+ return m_dwCopyCtorChainLocalNum;
1856
+ }
1857
+ #endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
1858
+
1838
1859
BOOL NDirectStubLinker::IsCleanupNeeded ()
1839
1860
{
1840
1861
LIMITED_METHOD_CONTRACT;
@@ -2064,6 +2085,10 @@ void NDirectStubLinker::End(DWORD dwStubFlags)
2064
2085
}
2065
2086
}
2066
2087
2088
+ #if defined(TARGET_X86) && defined(TARGET_WINDOWS)
2089
+ EXTERN_C void STDCALL CopyConstructorCallStub (void );
2090
+ #endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
2091
+
2067
2092
void NDirectStubLinker::DoNDirect (ILCodeStream *pcsEmit, DWORD dwStubFlags, MethodDesc * pStubMD)
2068
2093
{
2069
2094
STANDARD_VM_CONTRACT;
@@ -2150,6 +2175,21 @@ void NDirectStubLinker::DoNDirect(ILCodeStream *pcsEmit, DWORD dwStubFlags, Meth
2150
2175
}
2151
2176
}
2152
2177
2178
+ #if defined(TARGET_X86) && defined(TARGET_WINDOWS)
2179
+ if (m_dwCopyCtorChainLocalNum != (DWORD)-1 )
2180
+ {
2181
+ // If we have a copy constructor chain local, we need to call the copy constructor stub
2182
+ // to ensure that the chain is called correctly.
2183
+ // Let's install the stub chain here and redirect the call to the stub.
2184
+ DWORD targetLoc = NewLocal (ELEMENT_TYPE_I);
2185
+ pcsEmit->EmitSTLOC (targetLoc);
2186
+ pcsEmit->EmitLDLOCA (m_dwCopyCtorChainLocalNum);
2187
+ pcsEmit->EmitLDLOC (targetLoc);
2188
+ pcsEmit->EmitCALL (METHOD__COPY_CONSTRUCTOR_CHAIN__INSTALL, 2 , 0 );
2189
+ pcsEmit->EmitLDC ((DWORD_PTR)&CopyConstructorCallStub);
2190
+ }
2191
+ #endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
2192
+
2153
2193
// For managed-to-native calls, the rest of the work is done by the JIT. It will
2154
2194
// erect InlinedCallFrame, flip GC mode, and use the specified calling convention
2155
2195
// to call the target. For native-to-managed calls, this is an ordinary managed
@@ -6078,5 +6118,21 @@ PCODE GetILStubForCalli(VASigCookie *pVASigCookie, MethodDesc *pMD)
6078
6118
RETURN pVASigCookie->pNDirectILStub ;
6079
6119
}
6080
6120
6121
+ #if defined(TARGET_X86) && defined(TARGET_WINDOWS)
6122
+ // Copy constructor support for C++/CLI
6123
+ EXTERN_C void * STDCALL CallCopyConstructorsWorker (void * esp)
6124
+ {
6125
+ STATIC_CONTRACT_THROWS;
6126
+ STATIC_CONTRACT_GC_TRIGGERS;
6127
+ STATIC_CONTRACT_MODE_PREEMPTIVE; // we've already switched to preemptive
6128
+
6129
+ using ExecuteCallback = void *(STDMETHODCALLTYPE*)(void *);
6130
+
6131
+ MethodDesc* pMD = CoreLibBinder::GetMethod (METHOD__COPY_CONSTRUCTOR_CHAIN__EXECUTE_CURRENT_COPIES_AND_GET_TARGET);
6132
+ ExecuteCallback pExecute = (ExecuteCallback)pMD->GetMultiCallableAddrOfCode ();
6133
+
6134
+ return pExecute (esp);
6135
+ }
6136
+ #endif // defined(TARGET_X86) && defined(TARGET_WINDOWS)
6081
6137
6082
6138
#endif // #ifndef DACCESS_COMPILE
0 commit comments