+ bool result = false;
+ SideTable *table = SideTable::tableForPointer(this);
+
+ spinlock_lock(&table->slock);
+
+ RefcountMap::iterator it = table->refcnts.find(this);
+ if (it != table->refcnts.end()) result = true;
+
+ if (weak_is_registered_no_lock(&table->weak_table, (id)this)) result = true;
+
+ spinlock_unlock(&table->slock);
+
+ return result;
+}
+#endif
+
+#if SUPPORT_NONPOINTER_ISA
+
+void
+objc_object::sidetable_lock()
+{
+ SideTable *table = SideTable::tableForPointer(this);
+ spinlock_lock(&table->slock);
+}
+
+void
+objc_object::sidetable_unlock()
+{
+ SideTable *table = SideTable::tableForPointer(this);
+ spinlock_unlock(&table->slock);
+}
+
+
+// Move the entire retain count to the side table,
+// as well as isDeallocating and weaklyReferenced.
+void
+objc_object::sidetable_moveExtraRC_nolock(size_t extra_rc,
+ bool isDeallocating,
+ bool weaklyReferenced)
+{
+ assert(!isa.indexed); // should already be changed to not-indexed
+ SideTable *table = SideTable::tableForPointer(this);
+
+ size_t& refcntStorage = table->refcnts[this];
+ size_t oldRefcnt = refcntStorage;
+ // not deallocating - that was in the isa
+ assert((oldRefcnt & SIDE_TABLE_DEALLOCATING) == 0);
+ assert((oldRefcnt & SIDE_TABLE_WEAKLY_REFERENCED) == 0);
+
+ uintptr_t carry;
+ size_t refcnt = addc(oldRefcnt, extra_rc<<SIDE_TABLE_RC_SHIFT, 0, &carry);
+ if (carry) refcnt = SIDE_TABLE_RC_PINNED;
+ if (isDeallocating) refcnt |= SIDE_TABLE_DEALLOCATING;
+ if (weaklyReferenced) refcnt |= SIDE_TABLE_WEAKLY_REFERENCED;
+
+ refcntStorage = refcnt;
+}
+
+
+// Move some retain counts to the side table from the isa field.
+// Returns true if the object is now pinned.
+bool
+objc_object::sidetable_addExtraRC_nolock(size_t delta_rc)
+{
+ assert(isa.indexed);
+ SideTable *table = SideTable::tableForPointer(this);
+
+ size_t& refcntStorage = table->refcnts[this];
+ size_t oldRefcnt = refcntStorage;
+ // not deallocating - that is in the isa
+ assert((oldRefcnt & SIDE_TABLE_DEALLOCATING) == 0);
+ assert((oldRefcnt & SIDE_TABLE_WEAKLY_REFERENCED) == 0);
+
+ if (oldRefcnt & SIDE_TABLE_RC_PINNED) return true;
+
+ uintptr_t carry;
+ size_t newRefcnt =
+ addc(oldRefcnt, delta_rc << SIDE_TABLE_RC_SHIFT, 0, &carry);
+ if (carry) {
+ refcntStorage =
+ SIDE_TABLE_RC_PINNED | (oldRefcnt & SIDE_TABLE_FLAG_MASK);
+ return true;
+ }
+ else {
+ refcntStorage = newRefcnt;
+ return false;
+ }
+}
+
+
+// Move some retain counts from the side table to the isa field.
+// Returns true if the sidetable retain count is now 0.
+bool
+objc_object::sidetable_subExtraRC_nolock(size_t delta_rc)
+{
+ assert(isa.indexed);
+ SideTable *table = SideTable::tableForPointer(this);
+
+ size_t& refcntStorage = table->refcnts[this];
+ size_t oldRefcnt = refcntStorage;
+ // not deallocating - that is in the isa
+ assert((oldRefcnt & SIDE_TABLE_DEALLOCATING) == 0);
+ assert((oldRefcnt & SIDE_TABLE_WEAKLY_REFERENCED) == 0);
+
+ if (oldRefcnt < delta_rc) {
+ _objc_inform_now_and_on_crash("refcount underflow error for object %p",
+ this);
+ _objc_fatal("refcount underflow error for %s %p",
+ object_getClassName((id)this), this);
+ }
+
+ size_t newRefcnt = oldRefcnt - (delta_rc << SIDE_TABLE_RC_SHIFT);
+ if (newRefcnt == 0) {
+ table->refcnts.erase(this);
+ return true;
+ }
+ else {
+ refcntStorage = newRefcnt;
+ return false;
+ }
+}
+
+
+size_t
+objc_object::sidetable_getExtraRC_nolock()
+{
+ assert(isa.indexed);
+ SideTable *table = SideTable::tableForPointer(this);
+ RefcountMap::iterator it = table->refcnts.find(this);
+ assert(it != table->refcnts.end());
+ return it->second >> SIDE_TABLE_RC_SHIFT;
+}