/* Look at this class and it's superclass contents (which includes * included modules) and calculate out how to allocate the slots. * * This locks the class so that construction is serialized. */ void Class::auto_pack(STATE) { hard_lock(state); // If another thread did this work while we were waiting on the lock, // don't redo it. if(type_info_->type == PackedObject::type) return; size_t slots = 0; LookupTable* lt = LookupTable::create(state); // If autopacking is enabled, figure out how many slots to use. if(state->shared.config.gc_autopack) { Module* mod = this; int slot = 0; while(!mod->nil_p()) { Array* info = 0; if(Class* cls = try_as<Class>(mod)) { info = cls->seen_ivars(); } else if(IncludedModule* im = try_as<IncludedModule>(mod)) { info = im->module()->seen_ivars(); } if(info && !info->nil_p()) { for(size_t i = 0; i < info->size(); i++) { if(Symbol* sym = try_as<Symbol>(info->get(state, i))) { bool found = false; lt->fetch(state, sym, &found); if(!found) { lt->store(state, sym, Fixnum::from(slot++)); } } // Limit the number of packed ivars to 25. if(slot > 25) break; } } mod = mod->superclass(); } slots = lt->entries()->to_native(); } packed_size_ = sizeof(Object) + (slots * sizeof(Object*)); packed_ivar_info(state, lt); set_object_type(state, PackedObject::type); hard_unlock(state); }
Object* Class::set_packed(STATE, Array* info) { // Only transition Object typed objects to Packed if(type_info_->type != Object::type) return Fixnum::from(1); // Reject methods that already have packing. if(packed_size_) return Fixnum::from(2); LookupTable* lt = LookupTable::create(state); size_t s = info->size(); for(size_t i = 0; i < s; i++) { Symbol* sym = as<Symbol>(info->get(state, i)); lt->store(state, sym, Fixnum::from(i)); } packed_size_ = sizeof(Object) + (s * sizeof(Object*)); packed_ivar_info(state, lt); set_object_type(state, PackedObject::type); return Qtrue; }
Object* Class::set_superclass(STATE, Object* obj) { if(obj->nil_p()) { superclass(state, (Class*)Qnil); return Qnil; } Class* sup; if((sup = try_as<Class>(obj)) == 0) { return Primitives::failure(); } superclass(state, sup); instance_type(state, sup->instance_type()); set_type_info(sup->type_info()); packed_ivar_info(state, sup->packed_ivar_info()); set_packed_size(sup->packed_size()); MetaClass::attach(state, this, sup->metaclass(state)); return Qnil; }