/* Creates a new type with this HOW as its meta-object. */ static void new_type(PARROT_INTERP, PMC *nci) { PMC * unused; /* We first create a new HOW instance. */ PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0); PMC *HOW = REPR(self)->allocate(interp, STABLE(self)); /* See if we have a representation name; if not default to P6opaque. */ STRING *repr_name = VTABLE_exists_keyed_str(interp, capture, repr_str) ? VTABLE_get_string_keyed_str(interp, capture, repr_str) : p6opaque_str; /* Create a new type object of the desired REPR. (Note that we can't * default to KnowHOWREPR here, since it doesn't know how to actually * store attributes, it's just for bootstrapping knowhow's. */ REPROps *repr_to_use = REPR_get_by_name(interp, repr_name); PMC *type_object = repr_to_use->type_object_for(interp, HOW); /* See if we were given a name; put it into the meta-object if so. */ STRING *name = VTABLE_exists_keyed_str(interp, capture, name_str) ? VTABLE_get_string_keyed_str(interp, capture, name_str) : empty_str; REPR(HOW)->initialize(interp, STABLE(HOW), OBJECT_BODY(HOW)); ((KnowHOWREPRInstance *)PMC_data(HOW))->body.name = name; PARROT_GC_WRITE_BARRIER(interp, HOW); /* Set .WHO to an empty hash. */ STABLE(type_object)->WHO = Parrot_pmc_new(interp, enum_class_Hash); PARROT_GC_WRITE_BARRIER(interp, STABLE_PMC(type_object)); /* Put it into capture to act as return value. */ unused = Parrot_pcc_build_call_from_c_args(interp, capture, "P", type_object); }
/* Creates a new instance based on the type object. */ static PMC * instance_of(PARROT_INTERP, PMC *WHAT) { KnowHOWREPRInstance *obj = mem_allocate_zeroed_typed(KnowHOWREPRInstance); obj->common.stable = STABLE_PMC(WHAT); obj->methods = pmc_new(interp, enum_class_Hash); obj->attributes = pmc_new(interp, enum_class_ResizablePMCArray); return wrap_object(interp, obj); }
/* Clones the current object. This involves cloning the method and * attribute lists and copying the (immutable string) name. */ static PMC * repr_clone(PARROT_INTERP, PMC *to_clone) { KnowHOWREPRInstance *obj = mem_allocate_zeroed_typed(KnowHOWREPRInstance); obj->common.stable = STABLE_PMC(to_clone); obj->methods = VTABLE_clone(interp, ((KnowHOWREPRInstance *)PMC_data(to_clone))->methods); obj->attributes = VTABLE_clone(interp, ((KnowHOWREPRInstance *)PMC_data(to_clone))->attributes); obj->name = ((KnowHOWREPRInstance *)PMC_data(to_clone))->name; return wrap_object(interp, obj); }
/* Clone. Clone object body and the attribute storage hash. */ static PMC * repr_clone(PARROT_INTERP, PMC *to_clone) { HashAttrStoreInstance *obj; /* Allocate and set up object instance. */ obj = (HashAttrStoreInstance *) Parrot_gc_allocate_fixed_size_storage(interp, sizeof(HashAttrStoreInstance)); obj->common.stable = STABLE_PMC(to_clone); obj->store = VTABLE_clone(interp, ((HashAttrStoreInstance *)PMC_data(to_clone))->store); return wrap_object(interp, obj); }
/* Creates a new instance based on the type object. */ static PMC * instance_of(PARROT_INTERP, PMC *WHAT) { HashAttrStoreInstance *obj; /* Allocate and set up object instance. */ obj = (HashAttrStoreInstance *) Parrot_gc_allocate_fixed_size_storage(interp, sizeof(HashAttrStoreInstance)); obj->common.stable = STABLE_PMC(WHAT); obj->store = pmc_new(interp, enum_class_Hash); return wrap_object(interp, obj); }
/* Creates a new instance based on the type object. */ static PMC * instance_of(PARROT_INTERP, PMC *WHAT) { P6opaqueInstance * obj; /* Compute allocation strategy if we've not already done so. */ P6opaqueREPRData * repr_data = (P6opaqueREPRData *) STABLE(WHAT)->REPR_data; if (!repr_data->allocation_size) { compute_allocation_strategy(interp, WHAT, repr_data); PARROT_GC_WRITE_BARRIER(interp, STABLE_PMC(WHAT)); } /* Allocate and set up object instance. */ obj = (P6opaqueInstance *) Parrot_gc_allocate_fixed_size_storage(interp, repr_data->allocation_size); memset(obj, 0, repr_data->allocation_size); obj->common.stable = STABLE_PMC(WHAT); /* The spill slot gets set to PMCNULL; it not being (C) NULL is what * lets us know it's actually a real instance, not a type object. */ obj->spill = PMCNULL; return wrap_object(interp, obj); }
/* Clones the current object. */ static PMC * repr_clone(PARROT_INTERP, PMC *to_clone) { UninstantiableInstance *obj = mem_allocate_zeroed_typed(UninstantiableInstance); obj->common.stable = STABLE_PMC(to_clone); return wrap_object(interp, obj); }
/* Performs a change of type, where possible. */ static void change_type(PARROT_INTERP, PMC *obj, PMC *new_type) { P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj); P6opaqueREPRData *cur_repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; P6opaqueREPRData *new_repr_data = (P6opaqueREPRData *)STABLE(new_type)->REPR_data; STRING *mro_str = Parrot_str_new_constant(interp, "mro"); PMC *cur_mro, *new_mro; INTVAL cur_mro_elems, new_mro_elems, mro_is_suffix; /* Ensure we're not trying to change the type of a type object. */ if (PObj_flag_TEST(private0, obj)) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Cannot change the type of a type object"); /* Ensure that the destination type REPR is P6opaque also. */ if (REPR(obj) != REPR(new_type)) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "P6opaque can only change type to another type with P6opaque REPR"); /* Ensure that MRO of new type has current type's MRO as a suffix. */ mro_is_suffix = 1; cur_mro = introspection_call(interp, STABLE(obj)->WHAT, STABLE(obj)->HOW, mro_str, 0); new_mro = introspection_call(interp, STABLE(new_type)->WHAT, STABLE(new_type)->HOW, mro_str, 0); cur_mro_elems = VTABLE_elements(interp, cur_mro); new_mro_elems = VTABLE_elements(interp, new_mro); if (new_mro_elems >= cur_mro_elems) { INTVAL start = new_mro_elems - cur_mro_elems; INTVAL i; for (i = 0; i < cur_mro_elems; i++) { PMC *cur_elem = VTABLE_get_pmc_keyed_int(interp, cur_mro, i); PMC *new_elem = VTABLE_get_pmc_keyed_int(interp, new_mro, i + start); if (decontainerize(interp, cur_elem) != decontainerize(interp, new_elem)) { mro_is_suffix = 0; break; } } } else { mro_is_suffix = 0; } if (!mro_is_suffix) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "P6opaque only supports type changes where the MRO of the original type is a suffix of the MRO of the new type"); /* If the new REPR never calculated it's object layout, do so now. */ if (!new_repr_data->allocation_size) { compute_allocation_strategy(interp, new_type, new_repr_data); PARROT_GC_WRITE_BARRIER(interp, STABLE_PMC(new_type)); } /* Reallocate ourself to the new allocation size, if needed, and * ensure new chunk of the memory is zeroed. Note that we can't * really re-alloc, we need to go deal with the fixed size pool * allocator. */ if (new_repr_data->allocation_size > cur_repr_data->allocation_size) { P6opaqueInstance *new_body = (P6opaqueInstance *) Parrot_gc_allocate_fixed_size_storage(interp, new_repr_data->allocation_size); memset(new_body, 0, new_repr_data->allocation_size); memcpy(new_body, instance, cur_repr_data->allocation_size); PMC_data(obj) = new_body; Parrot_gc_free_fixed_size_storage(interp, cur_repr_data->allocation_size, instance); instance = new_body; } /* Finally, we're ready to switch the S-Table pointer. */ instance->common.stable = STABLE_PMC(new_type); PARROT_GC_WRITE_BARRIER(interp, obj); }
/* Clones the current object; simply copies the value. */ static PMC * repr_clone(PARROT_INTERP, PMC *to_clone) { P6intInstance *obj = mem_allocate_zeroed_typed(P6intInstance); obj->common.stable = STABLE_PMC(to_clone); obj->value = ((P6intInstance *)PMC_data(to_clone))->value; return wrap_object(interp, obj); }
/* Creates a new instance based on the type object. */ static PMC * instance_of(PARROT_INTERP, PMC *WHAT) { P6intInstance *obj = mem_allocate_zeroed_typed(P6intInstance); obj->common.stable = STABLE_PMC(WHAT); obj->value = 0; return wrap_object(interp, obj); }