@@ -3313,9 +3313,10 @@ void ComMethodTable::LayOutClassMethodTable()
33133313 pCurrParentInteropMD = &pCurrParentInteropMT->pVTable [i];
33143314 pParentMD = pCurrParentInteropMD->pMD ;
33153315
3316- if (pMD &&
3317- !(pCurrInteropMD ? IsDuplicateClassItfMD (pCurrInteropMD, i) : IsDuplicateClassItfMD (pMD, i)) &&
3318- IsOverloadedComVisibleMember (pMD, pParentMD))
3316+ if (pMD
3317+ && !(pCurrInteropMD ? IsDuplicateClassItfMD (pCurrInteropMD, i) : IsDuplicateClassItfMD (pMD, i))
3318+ && IsOverloadedComVisibleMember (pMD, pParentMD)
3319+ && !pMD->IsAsyncMethod ())
33193320 {
33203321 // some bytes are reserved for CALL xxx before the method desc
33213322 ComCallMethodDesc* pNewMD = (ComCallMethodDesc *) (pMethodDescMemory + COMMETHOD_PREPAD);
@@ -3346,9 +3347,10 @@ void ComMethodTable::LayOutClassMethodTable()
33463347 pCurrInteropMD = &pCurrInteropMT->pVTable [i];
33473348 pMD = pCurrInteropMD->pMD ;
33483349
3349- if (pMD &&
3350- !(pCurrInteropMD ? IsDuplicateClassItfMD (pCurrInteropMD, i) : IsDuplicateClassItfMD (pMD, i)) &&
3351- IsNewComVisibleMember (pMD))
3350+ if (pMD
3351+ && !(pCurrInteropMD ? IsDuplicateClassItfMD (pCurrInteropMD, i) : IsDuplicateClassItfMD (pMD, i))
3352+ && IsNewComVisibleMember (pMD)
3353+ && !pMD->IsAsyncMethod ())
33523354 {
33533355 // some bytes are reserved for CALL xxx before the method desc
33543356 ComCallMethodDesc* pNewMD = (ComCallMethodDesc *) (pMethodDescMemory + COMMETHOD_PREPAD);
@@ -3376,8 +3378,12 @@ void ComMethodTable::LayOutClassMethodTable()
33763378 if (!it.IsVirtual ()) {
33773379 MethodDesc* pMD = it.GetMethodDesc ();
33783380
3379- if (pMD != NULL && !IsDuplicateClassItfMD (pMD, it.GetSlotNumber ()) &&
3380- IsNewComVisibleMember (pMD) && !pMD->IsStatic () && !pMD->IsCtor ()
3381+ if (pMD != NULL
3382+ && !IsDuplicateClassItfMD (pMD, it.GetSlotNumber ())
3383+ && IsNewComVisibleMember (pMD)
3384+ && !pMD->IsStatic ()
3385+ && !pMD->IsCtor ()
3386+ && !pMD->IsAsyncMethod ()
33813387 && (!pCurrMT->IsValueType () || (GetClassInterfaceType () != clsIfAutoDual && IsStrictlyUnboxed (pMD))))
33823388 {
33833389 // some bytes are reserved for CALL xxx before the method desc
@@ -3558,6 +3564,8 @@ BOOL ComMethodTable::LayOutInterfaceMethodTable(MethodTable* pClsMT)
35583564 ArrayList NewCOMMethodDescs;
35593565 ComCallMethodDescArrayHolder NewCOMMethodDescsHolder (&NewCOMMethodDescs);
35603566
3567+ unsigned numVtableSlots = 0 ;
3568+
35613569 for (i = 0 ; i < cbSlots; i++)
35623570 {
35633571 // Some space for a CALL xx xx xx xx stub is reserved before the beginning of the MethodDesc
@@ -3566,6 +3574,15 @@ BOOL ComMethodTable::LayOutInterfaceMethodTable(MethodTable* pClsMT)
35663574
35673575 MethodDesc* pIntfMD = m_pMT->GetMethodDescForSlot (i);
35683576
3577+ if (pIntfMD->IsAsyncMethod ())
3578+ {
3579+ // Async methods are not supported on COM interfaces
3580+ // And we don't include them in the calculation of COM vtable slots.
3581+ continue ;
3582+ }
3583+
3584+ numVtableSlots++;
3585+
35693586 if (m_pMT->HasInstantiation ())
35703587 {
35713588 pIntfMD = MethodDesc::FindOrCreateAssociatedMethodDesc (
@@ -3616,23 +3633,36 @@ BOOL ComMethodTable::LayOutInterfaceMethodTable(MethodTable* pClsMT)
36163633 SLOT *pComVtableRW = (SLOT*)((BYTE*)pComVtable + writeableOffset);
36173634
36183635 // Method descs are at the end of the vtable
3619- // m_cbSlots interfaces methods + IUnk methods
3636+ // numVtableSlots interfaces methods + IUnk methods
3637+ unsigned cbEmittedSlots = 0 ;
36203638 pMethodDescMemory = (BYTE *)&pComVtable[m_cbSlots];
3639+ _ASSERTE (numVtableSlots <= m_cbSlots);
36213640 for (i = 0 ; i < cbSlots; i++)
36223641 {
36233642 ComCallMethodDesc* pNewMD = (ComCallMethodDesc *) (pMethodDescMemory + COMMETHOD_PREPAD);
36243643 ComCallMethodDesc* pNewMDRW = (ComCallMethodDesc *) (pMethodDescMemory + writeableOffset + COMMETHOD_PREPAD);
36253644
36263645 MethodDesc* pIntfMD = m_pMT->GetMethodDescForSlot (i);
36273646
3647+ if (pIntfMD->IsAsyncMethod ())
3648+ {
3649+ // Async methods are not supported on COM interfaces
3650+ // We skip them above in the vtable calculation
3651+ // so don't fill in the COM vtable slot here.
3652+ continue ;
3653+ }
3654+
36283655 emitCOMStubCall (pNewMD, pNewMDRW, GetEEFuncEntryPoint (ComCallPreStub));
36293656
36303657 UINT slotIndex = (pIntfMD->GetComSlot () - cbExtraSlots);
36313658 FillInComVtableSlot (pComVtableRW, slotIndex, pNewMD);
36323659
36333660 pMethodDescMemory += (COMMETHOD_PREPAD + sizeof (ComCallMethodDesc));
3661+ cbEmittedSlots++;
36343662 }
36353663
3664+ _ASSERTE (numVtableSlots == cbEmittedSlots);
3665+
36363666 // Set the layout complete flag and release the lock.
36373667 comMTWriterHolder.GetRW ()->m_Flags |= enum_LayoutComplete;
36383668 NewCOMMethodDescsHolder.SuppressRelease ();
@@ -4248,9 +4278,10 @@ ComMethodTable* ComCallWrapperTemplate::CreateComMethodTableForClass(MethodTable
42484278 pCurrParentInteropMD = &pCurrParentInteropMT->pVTable [i];
42494279 pParentMD = pCurrParentInteropMD->pMD ;
42504280
4251- if (pMD &&
4252- !(pCurrInteropMD ? IsDuplicateClassItfMD (pCurrInteropMD, i) : IsDuplicateClassItfMD (pMD, i)) &&
4253- IsOverloadedComVisibleMember (pMD, pParentMD))
4281+ if (pMD
4282+ && !(pCurrInteropMD ? IsDuplicateClassItfMD (pCurrInteropMD, i) : IsDuplicateClassItfMD (pMD, i))
4283+ && IsOverloadedComVisibleMember (pMD, pParentMD)
4284+ && !pMD->IsAsyncMethod ())
42544285 {
42554286 cbNewPublicMethods++;
42564287 }
@@ -4267,9 +4298,10 @@ ComMethodTable* ComCallWrapperTemplate::CreateComMethodTableForClass(MethodTable
42674298 pCurrInteropMD = &pCurrInteropMT->pVTable [i];
42684299 pMD = pCurrInteropMD->pMD ;
42694300
4270- if (pMD &&
4271- !(pCurrInteropMD ? IsDuplicateClassItfMD (pCurrInteropMD, i) : IsDuplicateClassItfMD (pMD, i)) &&
4272- IsNewComVisibleMember (pMD))
4301+ if (pMD
4302+ && !(pCurrInteropMD ? IsDuplicateClassItfMD (pCurrInteropMD, i) : IsDuplicateClassItfMD (pMD, i))
4303+ && IsNewComVisibleMember (pMD)
4304+ && !pMD->IsAsyncMethod ())
42734305 {
42744306 cbNewPublicMethods++;
42754307 }
@@ -4282,9 +4314,13 @@ ComMethodTable* ComCallWrapperTemplate::CreateComMethodTableForClass(MethodTable
42824314 if (!it.IsVirtual ())
42834315 {
42844316 MethodDesc* pMD = it.GetMethodDesc ();
4285- if (pMD && !IsDuplicateClassItfMD (pMD, it.GetSlotNumber ()) && IsNewComVisibleMember (pMD) &&
4286- !pMD->IsStatic () && !pMD->IsCtor () &&
4287- (!pCurrMT->IsValueType () || (ClassItfType != clsIfAutoDual && IsStrictlyUnboxed (pMD))))
4317+ if (pMD
4318+ && !IsDuplicateClassItfMD (pMD, it.GetSlotNumber ())
4319+ && IsNewComVisibleMember (pMD)
4320+ && !pMD->IsStatic ()
4321+ && !pMD->IsCtor ()
4322+ && !pMD->IsAsyncMethod ()
4323+ && (!pCurrMT->IsValueType () || (ClassItfType != clsIfAutoDual && IsStrictlyUnboxed (pMD))))
42884324 {
42894325 cbNewPublicMethods++;
42904326 }
0 commit comments