Object* Class::allocate(STATE) { Object* obj = cNil; object_type obj_type = type_info()->type; if(obj_type == PackedObject::type) { obj = allocate_packed(state, this); } else if(!type_info()->allow_user_allocate || kind_of<SingletonClass>(this)) { std::ostringstream msg; msg << "direct allocation disabled for "; if(kind_of<SingletonClass>(this)) { msg << to_string(state); } else { msg << module_name()->debug_str(state); } Exception::raise_type_error(state, msg.str().c_str()); } else if(obj_type == Object::type) { auto_pack(state); obj = allocate_packed(state, this); } else { // type_info()->type is neither PackedObject nor Object, so use the // generic path. obj = state->memory()->new_object<Object>( state, this, type_info()->instance_size, obj_type); } #ifdef RBX_ALLOC_TRACKING if(unlikely(state->vm()->allocation_tracking())) { new_obj->setup_allocation_site(state); } #endif return obj; }
Object* Class::allocate(STATE, GCToken gct, CallFrame* calling_environment) { object_type obj_type = type_info_->type; if(obj_type == PackedObject::type) { Object* new_obj = allocate_packed(state, gct, this, calling_environment); #ifdef RBX_ALLOC_TRACKING if(unlikely(state->vm()->allocation_tracking())) { new_obj->setup_allocation_site(state, calling_environment); } #endif #ifdef RBX_GC_STRESS state->shared().gc_soon(); #endif return new_obj; } else if(!type_info_->allow_user_allocate || kind_of<SingletonClass>(this)) { std::ostringstream msg; msg << "direct allocation disabled for "; if(kind_of<SingletonClass>(this)) { msg << to_string(state); } else { msg << module_name()->debug_str(state); } Exception::type_error(state, msg.str().c_str()); return cNil; } else if(obj_type == Object::type) { // transition all normal object classes to PackedObject Class* self = this; OnStack<1> os(state, self); auto_pack(state, gct, calling_environment); Object* new_obj = allocate_packed(state, gct, self, calling_environment); #ifdef RBX_ALLOC_TRACKING if(unlikely(state->vm()->allocation_tracking())) { new_obj->setup_allocation_site(state, calling_environment); } #endif #ifdef RBX_GC_STRESS state->shared().gc_soon(); #endif return new_obj; } else { // type_info_->type is neither PackedObject nor Object, so use the // generic path. Object* new_obj = state->vm()->new_object_typed(this, type_info_->instance_size, obj_type); #ifdef RBX_ALLOC_TRACKING if(unlikely(state->vm()->allocation_tracking())) { new_obj->setup_allocation_site(state, calling_environment); } #endif #ifdef RBX_GC_STRESS state->shared().gc_soon(); #endif return new_obj; } }
Object* Class::allocate(STATE, GCToken gct, CallFrame* calling_environment) { if(type_info_->type == PackedObject::type) { Object* new_obj = allocate_packed(state, gct, this, calling_environment); #ifdef RBX_ALLOC_TRACKING if(unlikely(state->vm()->allocation_tracking())) { new_obj->setup_allocation_site(state, calling_environment); } #endif return new_obj; } else if(!type_info_->allow_user_allocate || kind_of<SingletonClass>(this)) { Exception::type_error(state, "direct allocation disabled"); return cNil; } else if(type_info_->type == Object::type) { // transition all normal object classes to PackedObject Class* self = this; OnStack<1> os(state, self); auto_pack(state, gct); Object* new_obj = allocate_packed(state, gct, this, calling_environment); #ifdef RBX_ALLOC_TRACKING if(unlikely(state->vm()->allocation_tracking())) { new_obj->setup_allocation_site(state, calling_environment); } #endif return new_obj; } else { // type_info_->type is neither PackedObject nor Object, so use the // generic path. Object* new_obj = state->vm()->new_object_typed(this, type_info_->instance_size, type_info_->type); #ifdef RBX_ALLOC_TRACKING if(unlikely(state->vm()->allocation_tracking())) { new_obj->setup_allocation_site(state, calling_environment); } #endif return new_obj; } }
Object* Class::allocate(STATE, CallFrame* calling_environment) { if(type_info_->type == PackedObject::type) { use_packed: assert(packed_size_ > 0); // Pull the size out into a local to deal with this moving later on. uint32_t size = packed_size_; PackedObject* obj = state->local_slab().allocate(size).as<PackedObject>(); if(likely(obj)) { obj->init_header(this, YoungObjectZone, PackedObject::type); } else { if(state->shared.om->refill_slab(state, state->local_slab())) { obj = state->local_slab().allocate(size).as<PackedObject>(); if(likely(obj)) { obj->init_header(this, YoungObjectZone, PackedObject::type); } else { obj = reinterpret_cast<PackedObject*>( state->om->new_object_fast(state, this, size, PackedObject::type)); } } else { state->shared.om->collect_young_now = true; Class* self = this; OnStack<1> os(state, self); state->collect_maybe(calling_environment); // Don't use 'this' after here! it's been moved! use 'self'! obj = state->local_slab().allocate(size).as<PackedObject>(); if(likely(obj)) { obj->init_header(self, YoungObjectZone, PackedObject::type); } else { obj = reinterpret_cast<PackedObject*>( state->om->new_object_fast(state, self, size, PackedObject::type)); } } } // Don't use 'this' !!! The above code might have GC'd uintptr_t body = reinterpret_cast<uintptr_t>(obj->body_as_array()); for(size_t i = 0; i < size - sizeof(ObjectHeader); i += sizeof(Object*)) { Object** pos = reinterpret_cast<Object**>(body + i); *pos = Qundef; } return obj; } else if(!type_info_->allow_user_allocate || kind_of<SingletonClass>(this)) { Exception::type_error(state, "direct allocation disabled"); return Qnil; } else if(type_info_->type == Object::type) { // transition all normal object classes to PackedObject auto_pack(state); goto use_packed; } // type_info_->type is neither PackedObject nor Object, so use the // generic path. return state->new_object_typed(this, type_info_->instance_size, type_info_->type); }