SingletonClass* SingletonClass::attach(STATE, Object* obj, Class* sup) { SingletonClass *sc; sc = state->memory()->new_object_enduring<SingletonClass>(state, G(klass)); sc->init(state); sc->attached_instance(state, obj); sc->setup(state); if(kind_of<PackedObject>(obj)) { sc->set_type_info(state->memory()->type_info[Object::type]); } else { sc->set_type_info(obj->klass()->type_info()); } sc->set_packed_size(obj->klass()->packed_size()); sc->packed_ivar_info(state, obj->klass()->packed_ivar_info()); /* The superclass hierarchy for singleton classes lives in parallel to * that of classes. This code ensures that the superclasses of singleton * classes are also singleton classes. */ if(SingletonClass* already_sc = try_as<SingletonClass>(obj)) { /* If we are attaching a singleton class to something that is already a * SingletonClass, make the singleton class's superclass be the attachee's * superclass. klass and superclass are both singleton classes in this * case. */ sc->klass(state, sc); Class* super = already_sc->true_superclass(state)->singleton_class_instance(state); sc->superclass(state, super); super->track_subclass(state, sc); } else { /* If we are attaching to anything but a SingletonClass, the new * singleton class's class is the same as its superclass. This is where * the superclass chains for singleton and non-singleton classes * diverge. If no superclass argument was provided, we use the klass we * are replacing. */ if(!sup) { sup = obj->klass(); } /* Tell the new SingletonClass about the attachee's existing hierarchy */ Class* super_klass = Class::real_class(state, sup)->klass(); sc->klass(state, super_klass); sc->superclass(state, sup); sup->track_subclass(state, sc); } /* Finally, attach the new SingletonClass */ obj->klass(state, sc); return sc; }
SingletonClass* SingletonClass::create(STATE, Object* obj) { SingletonClass *sc; sc = state->memory()->new_object_enduring<SingletonClass>(state, G(klass)); sc->init(state); WeakRef* weakref = WeakRef::create(state, obj); sc->object_reference(state, weakref); sc->setup(state); return sc; }