new (&table_buf[i * SIDE_TABLE_SIZE]) SideTable;
}
}
+
+ static bool noLocksHeld(void) {
+ bool gotAll = true;
+ for (int i = 0; i < SIDE_TABLE_STRIPE && gotAll; i++) {
+ SideTable *s = (SideTable *)(&table_buf[i * SIDE_TABLE_SIZE]);
+ if (OSSpinLockTry(&s->slock)) {
+ OSSpinLockUnlock(&s->slock);
+ } else {
+ gotAll = false;
+ }
+ }
+ return gotAll;
+ }
};
STATIC_ASSERT(sizeof(SideTable) <= SIDE_TABLE_SIZE);
// anonymous namespace
};
+bool noSideTableLocksHeld(void)
+{
+ return SideTable::noLocksHeld();
+}
//
// The -fobjc-arr flag causes the compiler to issue calls to objc_{retain/release/autorelease/retain_block}
extern int DebuggerMode;
extern void gdb_objc_debuggerModeFailure(void);
extern BOOL isManagedDuringDebugger(void *lock);
-extern BOOL isLockedDuringDebugger(mutex_t *lock);
+extern BOOL isLockedDuringDebugger(void *lock);
static inline int _mutex_lock_nodebug(mutex_t *m) {
if (DebuggerMode && isManagedDuringDebugger(m)) {
#endif
+extern bool noSideTableLocksHeld(void);
+
#define rwlock_unlock(m, s) \
do { \
if ((s) == RDONLY) rwlock_unlock_read(m); \
return DEBUGGER_OFF;
}
+ // side table locks are not optional
+ if (!noSideTableLocksHeld()) {
+ rwlock_unlock(&runtimeLock, debugger_runtimeLock);
+ mutex_unlock(&cacheUpdateLock);
+ debugger_runtimeLock = 0;
+ return DEBUGGER_OFF;
+ }
+
// selLock is optional
if (rwlock_try_write(&selLock)) {
debugger_selLock = RDWR;
* Locking a managed mutex during debugger mode causes a trap unless
* this returns YES.
**********************************************************************/
-PRIVATE_EXTERN BOOL isLockedDuringDebugger(mutex_t *lock)
+PRIVATE_EXTERN BOOL isLockedDuringDebugger(void *lock)
{
assert(DebuggerMode);
return DEBUGGER_OFF;
}
+ // side table locks are not optional because we're being conservative
+ if (!noSideTableLocksHeld()) {
+ mutex_unlock(&cacheUpdateLock);
+ mutex_unlock(&methodListLock);
+ mutex_unlock(&classLock);
+ return DEBUGGER_OFF;
+ }
+
// selLock is optional
if (rwlock_try_write(&selLock)) {
debugger_selLock = RDWR;
* Locking a managed mutex during debugger mode causes a trap unless
* this returns YES.
**********************************************************************/
-PRIVATE_EXTERN BOOL isLockedDuringDebugger(mutex_t *lock)
+PRIVATE_EXTERN BOOL isLockedDuringDebugger(void *lock)
{
assert(DebuggerMode);
PRIVATE_EXTERN id weak_register_no_lock(weak_table_t *weak_table, id referent, id *referrer) {
- if (referent) {
+ if (referent && !OBJC_IS_TAGGED_PTR(referent)) {
// ensure that the referenced object is viable
BOOL (*allowsWeakReference)(id, SEL) = (BOOL(*)(id, SEL))
class_getMethodImplementation(object_getClass(referent),
// find entry and mark that it needs retaining
{
referent = *referrer;
+ if (OBJC_IS_TAGGED_PTR(referent)) return referent;
weak_entry_t *entry;
if (referent == NULL || !(entry = weak_entry_for_referent(weak_table, referent))) {
*referrer = NULL;