/* Gets the current value for an attribute. */ static PMC * get_attribute(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) { P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj); P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; INTVAL slot; /* Ensure it is a defined object. */ if (!instance->spill) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Cannot access attributes in a type object"); /* Try the slot allocation first. */ slot = try_get_slot(interp, repr_data, class_handle, name); if (slot >= 0) { PMC *result = get_pmc_at_offset(instance, repr_data->attribute_offsets[slot]); if (result) { return result; } else { /* Maybe we know how to auto-viv it to a container. */ if (repr_data->auto_viv_values) { PMC *value = repr_data->auto_viv_values[slot]; if (value != NULL) { value = REPR(value)->clone(interp, value); set_pmc_at_offset(instance, repr_data->attribute_offsets[slot], value); return value; } } return PMCNULL; } } /* Otherwise, complain that the attribute doesn't exist. */ no_such_attribute(interp, "get", class_handle, name); }
/* Checks if an attribute has been initialized. */ static INTVAL is_attribute_initialized(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint) { P6opaqueREPRData *repr_data = (P6opaqueREPRData *)st->REPR_data; INTVAL slot = try_get_slot(interp, repr_data, class_handle, name); if (slot >= 0) return NULL != get_pmc_at_offset(data, repr_data->attribute_offsets[slot]); else no_such_attribute(interp, "initializedness check", class_handle, name); }
/* This Parrot-specific addition to the API is used to mark an object. */ static void gc_mark(PARROT_INTERP, PMC *obj) { P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj); /* Mark STable and SC. */ if (!PMC_IS_NULL(instance->common.stable)) Parrot_gc_mark_PMC_alive(interp, instance->common.stable); if (!PMC_IS_NULL(instance->common.sc)) Parrot_gc_mark_PMC_alive(interp, instance->common.sc); /* If there's spill storage, mark that. */ if (!PMC_IS_NULL(instance->spill)) Parrot_gc_mark_PMC_alive(interp, instance->spill); /* Mark contained PMC and string attributes, provided this is a * real object. */ if (instance->spill) { P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; INTVAL i; /* Mark PMCs. */ if (repr_data->gc_pmc_mark_offsets) { for (i = 0; i < repr_data->num_attributes; i++) { INTVAL offset = repr_data->gc_pmc_mark_offsets[i]; if (offset) { PMC *to_mark = get_pmc_at_offset(instance, offset); if (!PMC_IS_NULL(to_mark)) Parrot_gc_mark_PMC_alive(interp, to_mark); } else { break; } } } /* Mark strings. */ if (repr_data->gc_str_mark_offsets) { for (i = 0; i < repr_data->num_attributes; i++) { INTVAL offset = repr_data->gc_str_mark_offsets[i]; if (offset) { STRING *to_mark = get_str_at_offset(instance, offset); if (to_mark) Parrot_gc_mark_STRING_alive(interp, to_mark); } else { break; } } } } }
/* Gets the current value for an attribute. */ static PMC * get_attribute_boxed(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint) { P6opaqueREPRData *repr_data = (P6opaqueREPRData *)st->REPR_data; INTVAL slot; /* Try the slot allocation first. */ slot = hint >= 0 && !(repr_data->mi) ? hint : try_get_slot(interp, repr_data, class_handle, name); if (slot >= 0) { if (!repr_data->flattened_stables[slot]) { PMC *result = get_pmc_at_offset(data, repr_data->attribute_offsets[slot]); if (result) { return result; } else { /* Maybe we know how to auto-viv it to a container. */ if (repr_data->auto_viv_values) { PMC *value = repr_data->auto_viv_values[slot]; if (value != NULL) { if (IS_CONCRETE(value)) { PMC *cloned = REPR(value)->allocate(interp, STABLE(value)); REPR(value)->copy_to(interp, STABLE(value), OBJECT_BODY(value), OBJECT_BODY(cloned)); PARROT_GC_WRITE_BARRIER(interp, cloned); set_pmc_at_offset(data, repr_data->attribute_offsets[slot], cloned); return cloned; } else { set_pmc_at_offset(data, repr_data->attribute_offsets[slot], value); return value; } } } return PMCNULL; } } else { /* Need to produce a boxed version of this attribute. */ STable *st = repr_data->flattened_stables[slot]; PMC *result = st->REPR->allocate(interp, st); st->REPR->copy_to(interp, st, (char *)data + repr_data->attribute_offsets[slot], OBJECT_BODY(result)); PARROT_GC_WRITE_BARRIER(interp, result); return result; } } /* Otherwise, complain that the attribute doesn't exist. */ no_such_attribute(interp, "get", class_handle, name); }
/* Checks if an attribute has been initialized. */ static INTVAL is_attribute_initialized(PARROT_INTERP, PMC *obj, PMC *class_handle, STRING *name, INTVAL hint) { P6opaqueInstance *instance = (P6opaqueInstance *)PMC_data(obj); P6opaqueREPRData *repr_data = (P6opaqueREPRData *)STABLE(obj)->REPR_data; INTVAL slot; if (!instance->spill) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Cannot access attributes in a type object"); slot = try_get_slot(interp, repr_data, class_handle, name); if (slot >= 0) return NULL != get_pmc_at_offset(instance, repr_data->attribute_offsets[slot]); else no_such_attribute(interp, "initializedness check", class_handle, name); }
/* This Parrot-specific addition to the API is used to mark an object. */ static void gc_mark(PARROT_INTERP, STable *st, void *data) { P6opaqueREPRData *repr_data = (P6opaqueREPRData *)st->REPR_data; INTVAL i; /* Mark PMCs. */ if (repr_data->gc_pmc_mark_offsets) { for (i = 0; i < repr_data->gc_pmc_mark_offsets_count; i++) { INTVAL offset = repr_data->gc_pmc_mark_offsets[i]; PMC *to_mark = get_pmc_at_offset(data, offset); if (!PMC_IS_NULL(to_mark)) Parrot_gc_mark_PMC_alive(interp, to_mark); } } /* Mark any nested reprs that need it. */ if (repr_data->gc_mark_slots) { for (i = 0; repr_data->gc_mark_slots[i] >= 0; i++) { INTVAL offset = repr_data->attribute_offsets[repr_data->gc_mark_slots[i]]; STable *st = repr_data->flattened_stables[repr_data->gc_mark_slots[i]]; st->REPR->gc_mark(interp, st, (char *)data + offset); } } }
/* Serializes the data. */ static void serialize(PARROT_INTERP, STable *st, void *data, SerializationWriter *writer) { P6opaqueREPRData *repr_data = (P6opaqueREPRData *)st->REPR_data; INTVAL num_attributes, i; if (!repr_data->allocation_size) { compute_allocation_strategy(interp, st->WHAT, repr_data); PARROT_GC_WRITE_BARRIER(interp, st->stable_pmc); } num_attributes = repr_data->num_attributes; for (i = 0; i < num_attributes; i++) { INTVAL a_offset = repr_data->attribute_offsets[i]; STable *a_st = repr_data->flattened_stables[i]; if (a_st) { if (a_st->REPR->serialize) a_st->REPR->serialize(interp, a_st, (char *)data + a_offset, writer); else Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Missing serialize REPR function"); } else writer->write_ref(interp, writer, get_pmc_at_offset(data, a_offset)); } }