Skip to content

Commit 7dc3669

Browse files
authored
Improve performance of Debugger.NotifyOfCrossThreadDependency under a debugger (#101864)
1 parent 4e626e2 commit 7dc3669

File tree

8 files changed

+199
-20
lines changed

8 files changed

+199
-20
lines changed

src/coreclr/debug/di/process.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5318,7 +5318,7 @@ void CordbProcess::RawDispatchEvent(
53185318
// if the class is NULL, that means the debugger never enabled notifications for it. Otherwise,
53195319
// the CordbClass instance would already have been created when the notifications were
53205320
// enabled.
5321-
if ((pNotificationClass != NULL) && pNotificationClass->CustomNotificationsEnabled())
5321+
if (pNotificationClass != NULL)
53225322

53235323
{
53245324
PUBLIC_CALLBACK_IN_THIS_SCOPE(this, pLockHolder, pEvent);
@@ -11414,14 +11414,37 @@ const EXCEPTION_RECORD * CordbProcess::ValidateExceptionRecord(
1141411414
HRESULT CordbProcess::SetEnableCustomNotification(ICorDebugClass * pClass, BOOL fEnable)
1141511415
{
1141611416
HRESULT hr = S_OK;
11417-
PUBLIC_API_BEGIN(this); // takes the lock
11417+
PUBLIC_API_ENTRY(this);
11418+
FAIL_IF_NEUTERED(this);
11419+
ATT_REQUIRE_STOPPED_MAY_FAIL(GetProcess());
1141811420

1141911421
ValidateOrThrow(pClass);
1142011422

11421-
((CordbClass *)pClass)->SetCustomNotifications(fEnable);
11423+
CordbProcess * pProcess = GetProcess();
11424+
RSLockHolder lockHolder(pProcess->GetProcessLock());
1142211425

11423-
PUBLIC_API_END(hr);
11424-
return hr;
11426+
DebuggerIPCEvent event;
11427+
CordbClass *pCordbClass = static_cast<CordbClass *>(pClass);
11428+
_ASSERTE(pCordbClass != NULL);
11429+
CordbAppDomain * pAppDomain = pCordbClass->GetAppDomain();
11430+
_ASSERTE (pAppDomain != NULL);
11431+
CordbModule *pModule = pCordbClass->GetModule();
11432+
11433+
pProcess->InitIPCEvent(&event,
11434+
DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION,
11435+
true,
11436+
pAppDomain->GetADToken());
11437+
event.CustomNotificationData.vmModule = pModule->GetRuntimeModule();
11438+
event.CustomNotificationData.classMetadataToken = pCordbClass->MDToken();
11439+
event.CustomNotificationData.Enabled = fEnable;
11440+
11441+
lockHolder.Release();
11442+
hr = pProcess->m_cordb->SendIPCEvent(pProcess, &event, sizeof(DebuggerIPCEvent));
11443+
lockHolder.Acquire();
11444+
11445+
_ASSERTE(event.type == DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION_RESULT);
11446+
11447+
return event.hr;
1142511448
} // CordbProcess::SetEnableCustomNotification
1142611449

1142711450
//---------------------------------------------------------------------------------------

src/coreclr/debug/di/rsclass.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ CordbClass::CordbClass(CordbModule *m, mdTypeDef classMetadataToken)
3434
m_fIsValueClassKnown(false),
3535
m_fIsValueClass(false),
3636
m_fHasTypeParams(false),
37-
m_continueCounterLastSync(0),
38-
m_fCustomNotificationsEnabled(false)
37+
m_continueCounterLastSync(0)
3938
{
4039
m_classInfo.Clear();
4140
}

src/coreclr/debug/di/rspriv.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5100,10 +5100,6 @@ class CordbClass : public CordbBase, public ICorDebugClass, public ICorDebugClas
51005100

51015101
public:
51025102

5103-
// set or clear the custom notifications flag to control whether we ignore custom debugger notifications
5104-
void SetCustomNotifications(BOOL fEnable) { m_fCustomNotificationsEnabled = fEnable; }
5105-
BOOL CustomNotificationsEnabled () { return m_fCustomNotificationsEnabled; }
5106-
51075103
HRESULT GetFieldInfo(mdFieldDef fldToken, FieldData ** ppFieldData);
51085104

51095105
// If you want to force the init to happen even if we think the class
@@ -5178,9 +5174,6 @@ class CordbClass : public CordbBase, public ICorDebugClass, public ICorDebugClas
51785174
// their value will be hung off the FieldDesc. Hold information about such fields here.
51795175
CordbHangingFieldTable m_hangingFieldsStatic;
51805176

5181-
// this indicates whether we should send custom debugger notifications
5182-
BOOL m_fCustomNotificationsEnabled;
5183-
51845177
};
51855178

51865179

src/coreclr/debug/ee/debugger.cpp

Lines changed: 66 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -916,6 +916,7 @@ Debugger::Debugger()
916916
m_ignoreThreadDetach(FALSE),
917917
m_pMethodInfos(NULL),
918918
m_pForceCatchHandlerFoundEventsTable(NULL),
919+
m_pCustomNotificationTable(NULL),
919920
m_mutex(CrstDebuggerMutex, (CrstFlags)(CRST_UNSAFE_ANYMODE | CRST_REENTRANCY | CRST_DEBUGGER_THREAD)),
920921
#ifdef _DEBUG
921922
m_mutexOwner(0),
@@ -958,8 +959,7 @@ Debugger::Debugger()
958959
m_processId = GetCurrentProcessId();
959960

960961
m_pForceCatchHandlerFoundEventsTable = new ForceCatchHandlerFoundTable();
961-
962-
962+
m_pCustomNotificationTable = new CustomNotificationTable();
963963

964964
//------------------------------------------------------------------------------
965965
// Metadata data structure version numbers
@@ -8045,6 +8045,20 @@ BOOL Debugger::ShouldSendCatchHandlerFound(Thread* pThread)
80458045
}
80468046
}
80478047

8048+
BOOL Debugger::ShouldSendCustomNotification(DomainAssembly *pAssembly, mdTypeDef typeDef)
8049+
{
8050+
CONTRACTL
8051+
{
8052+
THROWS;
8053+
GC_NOTRIGGER;
8054+
MODE_ANY;
8055+
}
8056+
CONTRACTL_END;
8057+
8058+
Module *pModule = pAssembly->GetModule();
8059+
TypeInModule tim(pModule, typeDef);
8060+
return !(m_pCustomNotificationTable->Lookup(tim).IsNull());
8061+
}
80488062

80498063
// Actually send the catch handler found event.
80508064
// This can be used to send CHF for both regular managed catchers as well
@@ -10485,6 +10499,26 @@ bool Debugger::HandleIPCEvent(DebuggerIPCEvent * pEvent)
1048510499
}
1048610500
break;
1048710501

10502+
case DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION:
10503+
{
10504+
Module * pModule = pEvent->CustomNotificationData.vmModule.GetRawPtr();
10505+
mdTypeDef classToken = pEvent->CustomNotificationData.classMetadataToken;
10506+
BOOL enabled = pEvent->CustomNotificationData.Enabled;
10507+
10508+
HRESULT hr = UpdateCustomNotificationTable(pModule, classToken, enabled);
10509+
10510+
DebuggerIPCEvent * pIPCResult = m_pRCThread->GetIPCEventReceiveBuffer();
10511+
InitIPCEvent(pIPCResult,
10512+
DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION_RESULT,
10513+
g_pEEInterface->GetThread(),
10514+
pEvent->vmAppDomain);
10515+
10516+
pIPCResult->hr = hr;
10517+
10518+
m_pRCThread->SendIPCReply();
10519+
}
10520+
break;
10521+
1048810522
case DB_IPCE_BREAKPOINT_ADD:
1048910523
{
1049010524

@@ -12408,6 +12442,35 @@ HRESULT Debugger::IsMethodDeoptimized(Module *pModule, mdMethodDef methodDef, BO
1240812442
return S_OK;
1240912443
}
1241012444

12445+
HRESULT Debugger::UpdateCustomNotificationTable(Module *pModule, mdTypeDef classToken, BOOL enabled)
12446+
{
12447+
CONTRACTL
12448+
{
12449+
THROWS;
12450+
CAN_TAKE_LOCK;
12451+
GC_NOTRIGGER;
12452+
}
12453+
CONTRACTL_END;
12454+
12455+
TypeInModule tim(pModule, classToken);
12456+
if (enabled)
12457+
{
12458+
if (m_pCustomNotificationTable->Lookup(tim).IsNull())
12459+
{
12460+
m_pCustomNotificationTable->Add(tim);
12461+
}
12462+
}
12463+
else
12464+
{
12465+
if (!(m_pCustomNotificationTable->Lookup(tim).IsNull()))
12466+
{
12467+
m_pCustomNotificationTable->Remove(tim);
12468+
}
12469+
}
12470+
12471+
return S_OK;
12472+
}
12473+
1241112474
HRESULT Debugger::UpdateForceCatchHandlerFoundTable(BOOL enableEvents, OBJECTREF exObj, AppDomain *pAppDomain)
1241212475
{
1241312476
CONTRACTL
@@ -14583,7 +14646,7 @@ void Debugger::SendCustomDebuggerNotification(Thread * pThread,
1458314646
Thread *curThread = g_pEEInterface->GetThread();
1458414647
SENDIPCEVENT_BEGIN(this, curThread);
1458514648

14586-
if (CORDebuggerAttached())
14649+
if (CORDebuggerAttached() && ShouldSendCustomNotification(pDomain, classToken))
1458714650
{
1458814651
DebuggerIPCEvent* ipce = m_pRCThread->GetIPCEventSendBuffer();
1458914652
InitIPCEvent(ipce,

src/coreclr/debug/ee/debugger.h

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,88 @@ class EMPTY_BASES_DECL ForceCatchHandlerFoundSHashTraits : public DefaultSHashTr
588588
}
589589
};
590590
typedef SHash<ForceCatchHandlerFoundSHashTraits> ForceCatchHandlerFoundTable;
591+
592+
class TypeInModule
593+
{
594+
private:
595+
Module *m_module;
596+
mdTypeDef m_typeDef;
597+
598+
public:
599+
600+
bool operator ==(const TypeInModule& other) const
601+
{
602+
return m_module == other.m_module && m_typeDef == other.m_typeDef;
603+
}
604+
605+
bool operator !=(const TypeInModule& other) const
606+
{
607+
return !(*this == other);
608+
}
609+
610+
bool IsNull() const
611+
{
612+
return m_module == NULL && m_typeDef == 0;
613+
}
614+
615+
INT32 Hash() const
616+
{
617+
return (INT32)((UINT_PTR)m_module ^ m_typeDef);
618+
}
619+
620+
TypeInModule(Module * module, mdTypeDef typeDef)
621+
:m_module(module), m_typeDef(typeDef)
622+
{
623+
LIMITED_METHOD_DAC_CONTRACT;
624+
}
625+
626+
TypeInModule()
627+
:m_module(NULL), m_typeDef(0)
628+
{
629+
LIMITED_METHOD_DAC_CONTRACT;
630+
}
631+
};
632+
633+
class EMPTY_BASES_DECL CustomNotificationSHashTraits : public DefaultSHashTraits<TypeInModule>
634+
{
635+
public:
636+
typedef TypeInModule element_t;
637+
typedef TypeInModule key_t;
638+
static const bool s_NoThrow = false;
639+
640+
static BOOL Equals(const TypeInModule &e, const TypeInModule &f)
641+
{
642+
return e == f;
643+
}
644+
static TypeInModule GetKey(const TypeInModule &e)
645+
{
646+
return e;
647+
}
648+
static INT32 Hash(const TypeInModule &e)
649+
{
650+
return e.Hash();
651+
}
652+
static TypeInModule Null()
653+
{
654+
TypeInModule tim;
655+
return tim;
656+
}
657+
static bool IsNull(const TypeInModule &e)
658+
{
659+
return e.IsNull();
660+
}
661+
static TypeInModule Deleted()
662+
{
663+
TypeInModule tim((Module *)-1, -1);
664+
return tim;
665+
}
666+
static bool IsDeleted(const TypeInModule &e)
667+
{
668+
TypeInModule tim((Module *)-1, -1);
669+
return e == tim;
670+
}
671+
};
672+
typedef SHash<CustomNotificationSHashTraits> CustomNotificationTable;
591673
#endif
592674

593675
/* ------------------------------------------------------------------------ *
@@ -1974,6 +2056,8 @@ class Debugger : public DebugInterface
19742056

19752057
BOOL ShouldSendCatchHandlerFound(Thread* pThread);
19762058

2059+
BOOL ShouldSendCustomNotification(DomainAssembly *pAssembly, mdTypeDef typeDef);
2060+
19772061
void SendCatchHandlerFound(Thread *pThread,
19782062
FramePointer fp,
19792063
SIZE_T nOffset,
@@ -2276,6 +2360,7 @@ class Debugger : public DebugInterface
22762360
#endif //DACCESS_COMPILE
22772361
HRESULT IsMethodDeoptimized(Module *pModule, mdMethodDef methodDef, BOOL *pResult);
22782362
HRESULT UpdateForceCatchHandlerFoundTable(BOOL enableEvents, OBJECTREF exObj, AppDomain *pAppDomain);
2363+
HRESULT UpdateCustomNotificationTable(Module *pModule, mdTypeDef classToken, BOOL enabled);
22792364

22802365
//
22812366
// The debugger mutex is used to protect any "global" Left Side
@@ -2865,9 +2950,11 @@ class Debugger : public DebugInterface
28652950
BOOL m_ignoreThreadDetach;
28662951
PTR_DebuggerMethodInfoTable m_pMethodInfos;
28672952
#ifdef DACCESS_COMPILE
2868-
VOID * m_pForceCatchHandlerFoundEventsTable;
2953+
VOID *m_pForceCatchHandlerFoundEventsTable;
2954+
VOID *m_pCustomNotificationTable;
28692955
#else
28702956
ForceCatchHandlerFoundTable *m_pForceCatchHandlerFoundEventsTable;
2957+
CustomNotificationTable *m_pCustomNotificationTable;
28712958
#endif
28722959

28732960

src/coreclr/debug/inc/dbgipcevents.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2060,6 +2060,13 @@ struct MSLAYOUT DebuggerIPCEvent
20602060
VMPTR_Object vmObj;
20612061
} ForceCatchHandlerFoundData;
20622062

2063+
struct MSLAYOUT
2064+
{
2065+
VMPTR_Module vmModule;
2066+
mdTypeDef classMetadataToken;
2067+
BOOL Enabled;
2068+
} CustomNotificationData;
2069+
20632070
struct MSLAYOUT
20642071
{
20652072
LSPTR_BREAKPOINT breakpointToken;

src/coreclr/debug/inc/dbgipceventtypes.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ IPC_EVENT_TYPE1(DB_IPCE_BEFORE_GARBAGE_COLLECTION ,0x0161)
9494
IPC_EVENT_TYPE1(DB_IPCE_AFTER_GARBAGE_COLLECTION ,0x0162)
9595
IPC_EVENT_TYPE1(DB_IPCE_DISABLE_OPTS_RESULT ,0x0163)
9696
IPC_EVENT_TYPE1(DB_IPCE_CATCH_HANDLER_FOUND_RESULT ,0x0165)
97-
IPC_EVENT_TYPE0(DB_IPCE_RUNTIME_LAST ,0x0166) // The last event from runtime
97+
IPC_EVENT_TYPE1(DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION_RESULT, 0x0166)
98+
IPC_EVENT_TYPE0(DB_IPCE_RUNTIME_LAST ,0x0167) // The last event from runtime
9899

99100

100101

@@ -145,5 +146,6 @@ IPC_EVENT_TYPE2(DB_IPCE_RESOLVE_UPDATE_METADATA_1 ,0x0256)
145146
IPC_EVENT_TYPE2(DB_IPCE_RESOLVE_UPDATE_METADATA_2 ,0x0257)
146147
IPC_EVENT_TYPE2(DB_IPCE_DISABLE_OPTS ,0x0258)
147148
IPC_EVENT_TYPE2(DB_IPCE_FORCE_CATCH_HANDLER_FOUND ,0x025A)
148-
IPC_EVENT_TYPE0(DB_IPCE_DEBUGGER_LAST ,0x025B) // The last event from the debugger
149+
IPC_EVENT_TYPE2(DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION, 0x025B)
150+
IPC_EVENT_TYPE0(DB_IPCE_DEBUGGER_LAST ,0x025C) // The last event from the debugger
149151

src/coreclr/debug/shared/dbgtransportsession.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2502,10 +2502,15 @@ DWORD DbgTransportSession::GetEventSize(DebuggerIPCEvent *pEvent)
25022502
case DB_IPCE_DISABLE_OPTS:
25032503
cbAdditionalSize = sizeof(pEvent->DisableOptData);
25042504
break;
2505+
25052506
case DB_IPCE_FORCE_CATCH_HANDLER_FOUND:
25062507
cbAdditionalSize = sizeof(pEvent->ForceCatchHandlerFoundData);
25072508
break;
25082509

2510+
case DB_IPCE_SET_ENABLE_CUSTOM_NOTIFICATION:
2511+
cbAdditionalSize = sizeof(pEvent->CustomNotificationData);
2512+
break;
2513+
25092514
default:
25102515
STRESS_LOG1(LF_CORDB, LL_INFO1000, "Unknown debugger event type: 0x%x\n", (pEvent->type & DB_IPCE_TYPE_MASK));
25112516
_ASSERTE(!"Unknown debugger event type");

0 commit comments

Comments
 (0)