Skip to content

Commit 60f1dc1

Browse files
jkoritzinskyCopilotjkotas
authored
Rework built-in COM->CLR stubs to build on the UnmanagedCallersOnly model (#126002)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Jan Kotas <jkotas@microsoft.com>
1 parent cdce1c1 commit 60f1dc1

59 files changed

Lines changed: 892 additions & 3317 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/design/coreclr/botr/guide-for-porting.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,7 @@ Here is an annotated list of the stubs implemented for Unix on Arm64.
368368
FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP can be implemented as
369369
performance needs require.
370370

371-
7. `ComCallPreStub`/ `COMToCLRDispatchHelper` /`GenericComCallStub` - not
372-
necessary for non-Windows platforms at this time
371+
7. `ComCallPreStub` - not necessary for non-Windows platforms at this time
373372

374373
8. `TheUMEntryPrestub`/ `UMThunkStub` - used to enter the runtime from
375374
non-managed code through entrypoints generated from the

src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,19 @@ internal static void ClearNative(IntPtr pUnk)
638638
Marshal.Release(pUnk);
639639
}
640640
}
641+
642+
internal static object GetObjectForComCallableWrapperIUnknown(IntPtr unk)
643+
{
644+
object? retObject = null;
645+
GetObjectForComCallableWrapperIUnknown(unk, ObjectHandleOnStack.Create(ref retObject));
646+
return retObject!;
647+
}
648+
649+
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "InterfaceMarshaler_GetObjectForComCallableWrapperIUnknown")]
650+
private static partial void GetObjectForComCallableWrapperIUnknown(IntPtr unk, ObjectHandleOnStack retObject);
651+
652+
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "InterfaceMarshaler_ValidateComVisibilityForIUnknown")]
653+
internal static partial void ValidateComVisibilityForIUnknown(IntPtr unk);
641654
} // class InterfaceMarshaler
642655
#endif // FEATURE_COMINTEROP
643656

src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -603,42 +603,6 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thr
603603
frameData.vmCurrentAppDomainToken.SetHostPtr(pAppDomain);
604604

605605
MethodDesc * pMD = pFrame->GetFunction();
606-
#if defined(FEATURE_COMINTEROP)
607-
if (frameData.stubFrame.frameType == STUBFRAME_U2M)
608-
{
609-
_ASSERTE(pMD == NULL);
610-
611-
// U2M transition frame generally don't store the target MD because we know what the target
612-
// is by looking at the callee stack frame. However, for reverse COM interop, we can try
613-
// to get the MD for the interface.
614-
//
615-
// Note that some reverse COM interop cases don't have an intermediate interface MD, so
616-
// pMD may still be NULL.
617-
//
618-
// Even if there is an MD on the ComMethodFrame, it could be in a different appdomain than
619-
// the ComMethodFrame itself. The only known scenario is a cross-appdomain reverse COM
620-
// interop call. We need to check for this case. The end result is that GetFunction() and
621-
// GetFunctionToken() on ICDInternalFrame will return NULL.
622-
623-
// Minidumps without full memory don't guarantee to capture the CCW since we can do without
624-
// it. In this case, pMD will remain NULL.
625-
EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY
626-
{
627-
if (pFrame->GetFrameIdentifier() == FrameIdentifier::ComMethodFrame)
628-
{
629-
ComMethodFrame * pCOMFrame = dac_cast<PTR_ComMethodFrame>(pFrame);
630-
PTR_VOID pUnkStackSlot = pCOMFrame->GetPointerToArguments();
631-
PTR_IUnknown pUnk = dac_cast<PTR_IUnknown>(*dac_cast<PTR_TADDR>(pUnkStackSlot));
632-
ComCallWrapper * pCCW = ComCallWrapper::GetWrapperFromIP(pUnk);
633-
634-
ComCallMethodDesc * pCMD = NULL;
635-
pCMD = dac_cast<PTR_ComCallMethodDesc>(pCOMFrame->ComMethodFrame::GetDatum());
636-
pMD = pCMD->GetInterfaceMethodDesc();
637-
}
638-
}
639-
EX_END_CATCH_ALLOW_DATATARGET_MISSING_MEMORY
640-
}
641-
#endif // FEATURE_COMINTEROP
642606

643607
Module * pModule = (pMD ? pMD->GetModule() : NULL);
644608
DomainAssembly * pDomainAssembly = (pModule ? pModule->GetDomainAssembly() : NULL);
@@ -902,7 +866,7 @@ void DacDbiInterfaceImpl::InitFrameData(StackFrameIterator * pIter,
902866
pFrameData->v.fVarArgs = pMD->IsVarArg();
903867

904868
// Check if this is a NoMetadata method or if the method should be hidden.
905-
// These methods should not be visible in the debugger both for convenience and
869+
// These methods should not be visible in the debugger both for convenience and
906870
// because they don't have backing metadata. For more information see comments in
907871
// MethodDesc::IsNoMetadata and MethodDesc::IsDiagnosticsHidden.
908872
pFrameData->v.fNoMetadata = pMD->IsNoMetadata() || pMD->IsDiagnosticsHidden();

src/coreclr/debug/ee/frameinfo.cpp

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -801,28 +801,8 @@ void FrameInfo::InitForM2UInternalFrame(CrawlFrame * pCF)
801801
void FrameInfo::InitForU2MInternalFrame(CrawlFrame * pCF)
802802
{
803803
_ASSERTE(pCF != NULL);
804-
MethodDesc * pMDHint = NULL;
805-
806-
#ifdef FEATURE_COMINTEROP
807-
Frame * pFrame = pCF->GetFrame();
808-
_ASSERTE(pFrame != NULL);
809-
810-
811-
// For regular U2M PInvoke cases, we don't care about MD b/c it's just going to
812-
// be the next frame.
813-
// If we're a COM2CLR call, perhaps we can get the MD for the interface.
814-
if (pFrame->GetFrameIdentifier() == FrameIdentifier::ComMethodFrame)
815-
{
816-
ComMethodFrame* pCOMFrame = dac_cast<PTR_ComMethodFrame> (pFrame);
817-
ComCallMethodDesc* pCMD = reinterpret_cast<ComCallMethodDesc *> (pCOMFrame->ComMethodFrame::GetDatum());
818-
pMDHint = pCMD->GetInterfaceMethodDesc();
819-
820-
// Some COM-interop cases don't have an intermediate interface method desc, so
821-
// pMDHint may be null.
822-
}
823-
#endif
824804

825-
InitFromStubHelper(pCF, pMDHint, STUBFRAME_U2M);
805+
InitFromStubHelper(pCF, NULL, STUBFRAME_U2M);
826806
InitForScratchFrameInfo();
827807
}
828808

src/coreclr/inc/CrstTypes.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ Crst UnresolvedClassLock
463463
End
464464

465465
Crst WrapperTemplate
466-
AcquiredBefore ExecutableAllocatorLock
466+
AcquiredBefore LoaderHeap
467467
End
468468

469469
Crst UMEntryThunkCache
@@ -536,4 +536,4 @@ End
536536

537537
Crst CallStubCache
538538
AcquiredBefore LoaderHeap
539-
End
539+
End

src/coreclr/inc/clrtypes.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,6 @@ static_assert(sizeof(CLR_BOOL) == 1);
215215
#define CLR_BOOL_MAX BOOL_MAX
216216
#define CLR_BOOL_MIN BOOL_MIN
217217

218-
#define CLR_NAN_32 0xFFC00000
219-
#define CLR_NAN_64 0xFFF8000000000000LL
220-
221218
// ================================================================================
222219
// Simple utility functions
223220
// ================================================================================

src/coreclr/inc/crsttypes_generated.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ int g_rgCrstLevelMap[] =
235235
2, // CrstUnwindInfoTablePendingLock
236236
3, // CrstUnwindInfoTablePublishLock
237237
3, // CrstVSDIndirectionCellLock
238-
2, // CrstWrapperTemplate
238+
3, // CrstWrapperTemplate
239239
};
240240

241241
// An array mapping CrstType to a stringized name.

src/coreclr/vm/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,6 @@ elseif(CLR_CMAKE_TARGET_WIN32)
662662
${ARCH_SOURCES_DIR}/CachedInterfaceDispatchCoreCLR.asm
663663
${ARCH_SOURCES_DIR}/CallDescrWorkerAMD64.asm
664664
${ARCH_SOURCES_DIR}/ComCallPreStub.asm
665-
${ARCH_SOURCES_DIR}/GenericComCallStubs.asm
666665
${ARCH_SOURCES_DIR}/GenericCLRToCOMCallStubs.asm
667666
${ARCH_SOURCES_DIR}/getstate.asm
668667
${ARCH_SOURCES_DIR}/JitHelpers_Fast.asm

src/coreclr/vm/FrameTypes.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ FRAME_TYPE_NAME(SoftwareExceptionFrame)
1919
FRAME_TYPE_NAME(FuncEvalFrame)
2020
#endif // DEBUGGING_SUPPORTED
2121
#ifdef FEATURE_COMINTEROP
22-
FRAME_TYPE_NAME(ComMethodFrame)
2322
FRAME_TYPE_NAME(CLRToCOMMethodFrame)
24-
FRAME_TYPE_NAME(ComPrestubMethodFrame)
2523
#endif // FEATURE_COMINTEROP
2624
FRAME_TYPE_NAME(PInvokeCalliFrame)
2725
#ifdef FEATURE_HIJACK

src/coreclr/vm/amd64/AsmHelpers.asm

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -106,41 +106,6 @@ NESTED_ENTRY JIT_RareDisableHelper, _TEXT
106106

107107
NESTED_END JIT_RareDisableHelper, _TEXT
108108

109-
110-
; extern "C" void setFPReturn(int fpSize, INT64 retVal);
111-
LEAF_ENTRY setFPReturn, _TEXT
112-
cmp ecx, 4
113-
je setFPReturn4
114-
cmp ecx, 8
115-
jne setFPReturnNot8
116-
mov [rsp+10h], rdx
117-
movsd xmm0, real8 ptr [rsp+10h]
118-
setFPReturnNot8:
119-
REPRET
120-
121-
setFPReturn4:
122-
mov [rsp+10h], rdx
123-
movss xmm0, real4 ptr [rsp+10h]
124-
ret
125-
LEAF_END setFPReturn, _TEXT
126-
127-
128-
; extern "C" void getFPReturn(int fpSize, INT64 *retval);
129-
LEAF_ENTRY getFPReturn, _TEXT
130-
cmp ecx, 4
131-
je getFPReturn4
132-
cmp ecx, 8
133-
jne getFPReturnNot8
134-
movsd real8 ptr [rdx], xmm0
135-
getFPReturnNot8:
136-
REPRET
137-
138-
getFPReturn4:
139-
movss real4 ptr [rdx], xmm0
140-
ret
141-
LEAF_END getFPReturn, _TEXT
142-
143-
144109
; A JITted method's return address was hijacked to return to us here.
145110
; VOID OnHijackTripThread()
146111
NESTED_ENTRY OnHijackTripThread, _TEXT

0 commit comments

Comments
 (0)