1. weak弱引用代码逻辑实现?
     // Update a weak variable.
     // If HaveOld is true, the variable has an existing value 
     //   that needs to be cleaned up. This value might be nil.
     // If HaveNew is true, there is a new value that needs to be 
     //   assigned into the variable. This value might be nil.
     // If CrashIfDeallocating is true, the process is halted if newObj is 
     //   deallocating or newObj's class does not support weak references. 
     //   If CrashIfDeallocating is false, nil is stored instead.
     enum CrashIfDeallocating {
         DontCrashIfDeallocating = false, DoCrashIfDeallocating = true
     };
     template <HaveOld haveOld, HaveNew haveNew,
               enum CrashIfDeallocating crashIfDeallocating>
     static id 
     storeWeak(id *location, objc_object *newObj)
     {
         ASSERT(haveOld  ||  haveNew);
         if (!haveNew) ASSERT(newObj == nil);
    
         Class previouslyInitializedClass = nil;
         id oldObj;
         SideTable *oldTable;
         SideTable *newTable;
    
         // Acquire locks for old and new values.
         // Order by lock address to prevent lock ordering problems. 
         // Retry if the old value changes underneath us.
      retry:
         if (haveOld) {
             oldObj = *location;
             oldTable = &SideTables()[oldObj];
         } else {
             oldTable = nil;
         }
         if (haveNew) {
             newTable = &SideTables()[newObj];
         } else {
             newTable = nil;
         }
    
         SideTable::lockTwo<haveOld, haveNew>(oldTable, newTable);
    
         if (haveOld  &&  *location != oldObj) {
             SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable);
             goto retry;
         }
    
         // Prevent a deadlock between the weak reference machinery
         // and the +initialize machinery by ensuring that no 
         // weakly-referenced object has an un-+initialized isa.
         if (haveNew  &&  newObj) {
             Class cls = newObj->getIsa();
             if (cls != previouslyInitializedClass  &&  
                 !((objc_class *)cls)->isInitialized()) 
             {
                 SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable);
                 class_initialize(cls, (id)newObj);
    
                 // If this class is finished with +initialize then we're good.
                 // If this class is still running +initialize on this thread 
                 // (i.e. +initialize called storeWeak on an instance of itself)
                 // then we may proceed but it will appear initializing and 
                 // not yet initialized to the check above.
                 // Instead set previouslyInitializedClass to recognize it on retry.
                 previouslyInitializedClass = cls;
    
                 goto retry;
             }
         }
    
         // Clean up old value, if any.
         if (haveOld) {
             weak_unregister_no_lock(&oldTable->weak_table, oldObj, location);
         }
    
         // Assign new value, if any.
         if (haveNew) {
             newObj = (objc_object *)
                 weak_register_no_lock(&newTable->weak_table, (id)newObj, location, 
                                       crashIfDeallocating ? CrashIfDeallocating : ReturnNilIfDeallocating);
             // weak_register_no_lock returns nil if weak store should be rejected
    
             // Set is-weakly-referenced bit in refcount table.
             if (!newObj->isTaggedPointerOrNil()) {
                 newObj->setWeaklyReferenced_nolock();
             }
    
             // Do not set *location anywhere else. That would introduce a race.
             *location = (id)newObj;
         }
         else {
             // No new value. The storage is not changed.
         }
    
         SideTable::unlockTwo<haveOld, haveNew>(oldTable, newTable);
    
         // This must be called without the locks held, as it can invoke
         // arbitrary code. In particular, even if _setWeaklyReferenced
         // is not implemented, resolveInstanceMethod: may be, and may
         // call back into the weak reference machinery.
         callSetWeaklyReferenced((id)newObj);
    
         return (id)newObj;
     }
    
    
     /** 
      * This function stores a new value into a __weak variable. It would
      * be used anywhere a __weak variable is the target of an assignment.
      * 
      * @param location The address of the weak pointer itself
      * @param newObj The new object this weak ptr should now point to
      * 
      * @return \e newObj
      */
     id
     objc_storeWeak(id *location, id newObj)
     {
         return storeWeak<DoHaveOld, DoHaveNew, DoCrashIfDeallocating>
             (location, (objc_object *)newObj);
     }
    
    
  2. weak的自动设置为nil是怎么实现的?

     //一个对象的销毁的调用轨迹是
     dealloc
     _objc_rootDealloc
     rootDealloc
     object_dispose
     objc_destructInstance
     free
    
  3. SideTable结构是怎样的?
     struct SideTable {
         spinlock_t slock;
         RefcountMap refcnts;
         weak_table_t weak_table;
    
         SideTable() {
             memset(&weak_table, 0, sizeof(weak_table));
         }
    
         ~SideTable() {
             _objc_fatal("Do not delete SideTable.");
         }
    
         void lock() { slock.lock(); }
         void unlock() { slock.unlock(); }
         void forceReset() { slock.forceReset(); }
    
         // Address-ordered lock discipline for a pair of side tables.
    
         template<HaveOld, HaveNew>
         static void lockTwo(SideTable *lock1, SideTable *lock2);
         template<HaveOld, HaveNew>
         static void unlockTwo(SideTable *lock1, SideTable *lock2);
     };