-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve performance of Debugger.NotifyOfCrossThreadDependency under a debugger #101864
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -588,6 +588,88 @@ class EMPTY_BASES_DECL ForceCatchHandlerFoundSHashTraits : public DefaultSHashTr | |
} | ||
}; | ||
typedef SHash<ForceCatchHandlerFoundSHashTraits> ForceCatchHandlerFoundTable; | ||
|
||
class TypeInModule | ||
{ | ||
private: | ||
Module *m_module; | ||
mdTypeDef m_typeDef; | ||
|
||
public: | ||
|
||
bool operator ==(const TypeInModule& other) const | ||
{ | ||
return m_module == other.m_module && m_typeDef == other.m_typeDef; | ||
} | ||
|
||
bool operator !=(const TypeInModule& other) const | ||
{ | ||
return !(*this == other); | ||
} | ||
|
||
bool IsNull() const | ||
{ | ||
return m_module == NULL && m_typeDef == 0; | ||
} | ||
|
||
INT32 Hash() const | ||
{ | ||
return (INT32)((UINT_PTR)m_module ^ m_typeDef); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did you choose to use this hash function? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For a hash function you want it to be quick to calculate, and also relatively unique to each entry. This is very quick to compute and should be unique most of the time. On 64 bit platforms there is a very low chance that the lower 32 bits of a module could be the same as another module and the typeDef could be repeated. |
||
} | ||
|
||
TypeInModule(Module * module, mdTypeDef typeDef) | ||
:m_module(module), m_typeDef(typeDef) | ||
{ | ||
LIMITED_METHOD_DAC_CONTRACT; | ||
} | ||
|
||
TypeInModule() | ||
:m_module(NULL), m_typeDef(0) | ||
{ | ||
LIMITED_METHOD_DAC_CONTRACT; | ||
} | ||
}; | ||
|
||
class EMPTY_BASES_DECL CustomNotificationSHashTraits : public DefaultSHashTraits<TypeInModule> | ||
{ | ||
public: | ||
typedef TypeInModule element_t; | ||
typedef TypeInModule key_t; | ||
static const bool s_NoThrow = false; | ||
|
||
static BOOL Equals(const TypeInModule &e, const TypeInModule &f) | ||
{ | ||
return e == f; | ||
} | ||
static TypeInModule GetKey(const TypeInModule &e) | ||
{ | ||
return e; | ||
} | ||
static INT32 Hash(const TypeInModule &e) | ||
{ | ||
return e.Hash(); | ||
} | ||
static TypeInModule Null() | ||
{ | ||
TypeInModule tim; | ||
return tim; | ||
} | ||
static bool IsNull(const TypeInModule &e) | ||
{ | ||
return e.IsNull(); | ||
} | ||
static TypeInModule Deleted() | ||
{ | ||
TypeInModule tim((Module *)-1, -1); | ||
return tim; | ||
} | ||
static bool IsDeleted(const TypeInModule &e) | ||
{ | ||
TypeInModule tim((Module *)-1, -1); | ||
return e == tim; | ||
} | ||
}; | ||
typedef SHash<CustomNotificationSHashTraits> CustomNotificationTable; | ||
#endif | ||
|
||
/* ------------------------------------------------------------------------ * | ||
|
@@ -1974,6 +2056,8 @@ class Debugger : public DebugInterface | |
|
||
BOOL ShouldSendCatchHandlerFound(Thread* pThread); | ||
|
||
BOOL ShouldSendCustomNotification(DomainAssembly *pAssembly, mdTypeDef typeDef); | ||
|
||
void SendCatchHandlerFound(Thread *pThread, | ||
FramePointer fp, | ||
SIZE_T nOffset, | ||
|
@@ -2276,6 +2360,7 @@ class Debugger : public DebugInterface | |
#endif //DACCESS_COMPILE | ||
HRESULT IsMethodDeoptimized(Module *pModule, mdMethodDef methodDef, BOOL *pResult); | ||
HRESULT UpdateForceCatchHandlerFoundTable(BOOL enableEvents, OBJECTREF exObj, AppDomain *pAppDomain); | ||
HRESULT UpdateCustomNotificationTable(Module *pModule, mdTypeDef classToken, BOOL enabled); | ||
|
||
// | ||
// The debugger mutex is used to protect any "global" Left Side | ||
|
@@ -2865,9 +2950,11 @@ class Debugger : public DebugInterface | |
BOOL m_ignoreThreadDetach; | ||
PTR_DebuggerMethodInfoTable m_pMethodInfos; | ||
#ifdef DACCESS_COMPILE | ||
VOID * m_pForceCatchHandlerFoundEventsTable; | ||
VOID *m_pForceCatchHandlerFoundEventsTable; | ||
VOID *m_pCustomNotificationTable; | ||
#else | ||
ForceCatchHandlerFoundTable *m_pForceCatchHandlerFoundEventsTable; | ||
CustomNotificationTable *m_pCustomNotificationTable; | ||
#endif | ||
|
||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is there an && here instead of an ||?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have && because the NULL TypeInModule is defined as a NULL m_module pointer and a 0 m_typeDef. If one of them is true but not the other, it means that something has created a TypeInModule with invalid data, which is different than a NULL TypeInModule. We shouldn't ever see one or the other, only both