/* Initializes the representations registry, building up all of the various * representations. */ void REPR_initialize_registry(PARROT_INTERP) { PMC *dyn_reg_func, *lookup_func; /* Allocate name to ID map, and anchor it with the GC. */ repr_name_to_id_map = Parrot_pmc_new(interp, enum_class_Hash); Parrot_pmc_gc_register(interp, repr_name_to_id_map); /* Add all core representations. */ register_repr(interp, Parrot_str_new_constant(interp, "KnowHOWREPR"), KnowHOWREPR_initialize(interp)); register_repr(interp, Parrot_str_new_constant(interp, "P6opaque"), P6opaque_initialize(interp)); register_repr(interp, Parrot_str_new_constant(interp, "P6int"), P6int_initialize(interp)); register_repr(interp, Parrot_str_new_constant(interp, "P6num"), P6num_initialize(interp)); register_repr(interp, Parrot_str_new_constant(interp, "P6str"), P6str_initialize(interp)); register_repr(interp, Parrot_str_new_constant(interp, "HashAttrStore"), HashAttrStore_initialize(interp)); register_repr(interp, Parrot_str_new_constant(interp, "Uninstantiable"), Uninstantiable_initialize(interp)); register_repr(interp, Parrot_str_new_constant(interp, "NFA"), NFA_initialize(interp)); register_repr(interp, Parrot_str_new_constant(interp, "VMArray"), VMArray_initialize(interp)); register_repr(interp, Parrot_str_new_constant(interp, "VMHash"), VMHash_initialize(interp)); register_repr(interp, Parrot_str_new_constant(interp, "VMIter"), VMIter_initialize(interp)); /* Set up object for dynamically registering extra representations. */ dyn_reg_func = Parrot_pmc_new(interp, enum_class_Pointer); VTABLE_set_pointer(interp, dyn_reg_func, REPR_register_dynamic); VTABLE_set_pmc_keyed_str(interp, interp->root_namespace, Parrot_str_new_constant(interp, "_REGISTER_REPR"), dyn_reg_func); /* Set up object for looking up the id of representations. */ lookup_func = Parrot_pmc_new(interp, enum_class_Pointer); VTABLE_set_pointer(interp, lookup_func, REPR_name_to_id); VTABLE_set_pmc_keyed_str(interp, interp->root_namespace, Parrot_str_new_constant(interp, "_LOOKUP_REPR_ID"), lookup_func); }
static void PackFile_Constant_dump(PARROT_INTERP, ARGIN(const PackFile_ConstTable *ct), ARGIN(const PackFile_Constant *self)) { ASSERT_ARGS(PackFile_Constant_dump) PMC *key; size_t i; switch (self->type) { case PFC_NUMBER: Parrot_io_printf(interp, " [ 'PFC_NUMBER', %g ],\n", self->u.number); break; case PFC_STRING: Parrot_io_printf(interp, " [ 'PFC_STRING', {\n"); pobj_flag_dump(interp, (long)PObj_get_FLAGS(self->u.string)); Parrot_io_printf(interp, " CHARSET => %ld,\n", self->u.string->charset); i = self->u.string->bufused; Parrot_io_printf(interp, " SIZE => %ld,\n", (long)i); Parrot_io_printf(interp, " DATA => \"%Ss\"\n", Parrot_str_escape(interp, self->u.string)); Parrot_io_printf(interp, " } ],\n"); break; case PFC_KEY: for (i = 0, key = self->u.key; key; i++) { GETATTR_Key_next_key(interp, key, key); } /* number of key components */ Parrot_io_printf(interp, " [ 'PFC_KEY' (%ld items)\n", i); /* and now type / value per component */ for (key = self->u.key; key;) { opcode_t type = PObj_get_FLAGS(key); Parrot_io_printf(interp, " {\n"); type &= KEY_type_FLAGS; pobj_flag_dump(interp, (long)PObj_get_FLAGS(key)); switch (type) { case KEY_integer_FLAG: Parrot_io_printf(interp, " TYPE => INTEGER\n"); Parrot_io_printf(interp, " DATA => %ld\n", VTABLE_get_integer(interp, key)); Parrot_io_printf(interp, " },\n"); break; case KEY_number_FLAG: { const PackFile_Constant *detail; size_t ct_index; Parrot_io_printf(interp, " TYPE => NUMBER\n"); ct_index = PackFile_find_in_const(interp, ct, key, PFC_NUMBER); Parrot_io_printf(interp, " PFC_OFFSET => %ld\n", ct_index); detail = ct->constants[ct_index]; Parrot_io_printf(interp, " DATA => %ld\n", detail->u.number); Parrot_io_printf(interp, " },\n"); } break; case KEY_string_FLAG: { const PackFile_Constant *detail; size_t ct_index; Parrot_io_printf(interp, " TYPE => STRING\n"); ct_index = PackFile_find_in_const(interp, ct, key, PFC_STRING); Parrot_io_printf(interp, " PFC_OFFSET => %ld\n", ct_index); detail = ct->constants[ct_index]; Parrot_io_printf(interp, " DATA => '%Ss'\n", detail->u.string); Parrot_io_printf(interp, " },\n"); } break; case KEY_integer_FLAG | KEY_register_FLAG: Parrot_io_printf(interp, " TYPE => I REGISTER\n"); Parrot_io_printf(interp, " DATA => %ld\n", VTABLE_get_integer(interp, key)); Parrot_io_printf(interp, " },\n"); break; case KEY_number_FLAG | KEY_register_FLAG: Parrot_io_printf(interp, " TYPE => N REGISTER\n"); Parrot_io_printf(interp, " DATA => %ld\n", VTABLE_get_integer(interp, key)); Parrot_io_printf(interp, " },\n"); break; case KEY_string_FLAG | KEY_register_FLAG: Parrot_io_printf(interp, " TYPE => S REGISTER\n"); Parrot_io_printf(interp, " DATA => %ld\n", VTABLE_get_integer(interp, key)); Parrot_io_printf(interp, " },\n"); break; case KEY_pmc_FLAG | KEY_register_FLAG: Parrot_io_printf(interp, " TYPE => P REGISTER\n"); Parrot_io_printf(interp, " DATA => %ld\n", VTABLE_get_integer(interp, key)); Parrot_io_printf(interp, " },\n"); break; default: Parrot_io_eprintf(NULL, "PackFile_Constant_pack: " "unsupported constant type\n"); Parrot_exit(interp, 1); } GETATTR_Key_next_key(interp, key, key); } Parrot_io_printf(interp, " ],\n"); break; case PFC_PMC: Parrot_io_printf(interp, " [ 'PFC_PMC', {\n"); { PMC * const pmc = self->u.key; Parrot_Sub_attributes *sub; STRING * const null = Parrot_str_new_constant(interp, "(null)"); STRING *namespace_description; pobj_flag_dump(interp, (long)PObj_get_FLAGS(pmc)); switch (pmc->vtable->base_type) { case enum_class_FixedBooleanArray: case enum_class_FixedFloatArray: case enum_class_FixedPMCArray: case enum_class_FixedStringArray: case enum_class_ResizableBooleanArray: case enum_class_ResizableIntegerArray: case enum_class_ResizableFloatArray: case enum_class_ResizablePMCArray: case enum_class_ResizableStringArray: { const int n = VTABLE_get_integer(interp, pmc); STRING* const out_buffer = VTABLE_get_repr(interp, pmc); Parrot_io_printf(interp, "\tclass => %Ss,\n" "\telement count => %d,\n" "\telements => %Ss,\n", pmc->vtable->whoami, n, out_buffer); } break; case enum_class_Sub: case enum_class_Coroutine: PMC_get_sub(interp, pmc, sub); if (sub->namespace_name) { switch (sub->namespace_name->vtable->base_type) { case enum_class_String: namespace_description = Parrot_str_new(interp, "'", 1); namespace_description = Parrot_str_append(interp, namespace_description, VTABLE_get_string(interp, sub->namespace_name)); namespace_description = Parrot_str_append(interp, namespace_description, Parrot_str_new(interp, "'", 1)); break; case enum_class_Key: namespace_description = key_set_to_string(interp, sub->namespace_name); break; default: namespace_description = sub->namespace_name->vtable->whoami; } } else { namespace_description = null; } Parrot_io_printf(interp, "\tclass => %Ss,\n" "\tstart_offs => %d,\n" "\tend_offs => %d,\n" "\tname => '%Ss',\n" "\tsubid => '%Ss',\n" "\tmethod => '%Ss',\n" "\tnsentry => '%Ss',\n" "\tnamespace => %Ss\n" "\tHLL_id => %d,\n", pmc->vtable->whoami, sub->start_offs, sub->end_offs, sub->name, sub->subid, sub->method_name, sub->ns_entry_name, namespace_description, sub->HLL_id); break; case enum_class_FixedIntegerArray: Parrot_io_printf(interp, "\tclass => %Ss,\n" "\trepr => '%Ss'\n", pmc->vtable->whoami, VTABLE_get_repr(interp, pmc)); break; default: Parrot_io_printf(interp, "\tno dump info for PMC %ld %Ss\n", pmc->vtable->base_type, pmc->vtable->whoami); Parrot_io_printf(interp, "\tclass => %Ss,\n", pmc->vtable->whoami); } } Parrot_io_printf(interp, " } ],\n"); break; default: Parrot_io_printf(interp, " [ 'PFC_\?\?\?', type '0x%x' ],\n", self->type); break; } }
/* Locates all of the attributes. Puts them onto a flattened, ordered * list of attributes (populating the passed flat_list). Also builds * the index mapping for doing named lookups. Note index is not related * to the storage position. */ static PMC * index_mapping_and_flat_list(PARROT_INTERP, PMC *WHAT, P6opaqueREPRData *repr_data) { PMC *flat_list = Parrot_pmc_new(interp, enum_class_ResizablePMCArray); PMC *class_list = Parrot_pmc_new(interp, enum_class_ResizablePMCArray); PMC *attr_map_list = Parrot_pmc_new(interp, enum_class_ResizablePMCArray); STRING *attributes_str = Parrot_str_new_constant(interp, "attributes"); STRING *parents_str = Parrot_str_new_constant(interp, "parents"); STRING *name_str = Parrot_str_new_constant(interp, "name"); STRING *mro_str = Parrot_str_new_constant(interp, "mro"); INTVAL current_slot = 0; INTVAL num_classes, i; P6opaqueNameMap * result = NULL; /* Get the MRO. */ PMC *mro = introspection_call(interp, WHAT, STABLE(WHAT)->HOW, mro_str, 0); INTVAL mro_idx = VTABLE_elements(interp, mro); /* Walk through the parents list. */ while (mro_idx) { /* Get current class in MRO. */ PMC *current_class = decontainerize(interp, VTABLE_get_pmc_keyed_int(interp, mro, --mro_idx)); PMC *HOW = STABLE(current_class)->HOW; /* Get its local parents. */ PMC *parents = introspection_call(interp, current_class, HOW, parents_str, 1); INTVAL num_parents = VTABLE_elements(interp, parents); /* Get attributes and iterate over them. */ PMC *attributes = introspection_call(interp, current_class, HOW, attributes_str, 1); PMC *attr_map = PMCNULL; PMC *attr_iter = VTABLE_get_iter(interp, attributes); while (VTABLE_get_bool(interp, attr_iter)) { /* Get attribute. */ PMC * attr = VTABLE_shift_pmc(interp, attr_iter); /* Get its name. */ PMC *name_pmc = accessor_call(interp, attr, name_str); STRING *name = VTABLE_get_string(interp, name_pmc); /* Allocate a slot. */ if (PMC_IS_NULL(attr_map)) attr_map = Parrot_pmc_new(interp, enum_class_Hash); VTABLE_set_pmc_keyed_str(interp, attr_map, name, Parrot_pmc_new_init_int(interp, enum_class_Integer, current_slot)); current_slot++; /* Push attr onto the flat list. */ VTABLE_push_pmc(interp, flat_list, attr); } /* Add to class list and map list. */ VTABLE_push_pmc(interp, class_list, current_class); VTABLE_push_pmc(interp, attr_map_list, attr_map); /* If there's more than one parent, flag that we in an MI * situation. */ if (num_parents > 1) repr_data->mi = 1; } /* We can now form the name map. */ num_classes = VTABLE_elements(interp, class_list); result = (P6opaqueNameMap *) mem_sys_allocate_zeroed(sizeof(P6opaqueNameMap) * (1 + num_classes)); for (i = 0; i < num_classes; i++) { result[i].class_key = VTABLE_get_pmc_keyed_int(interp, class_list, i); result[i].name_map = VTABLE_get_pmc_keyed_int(interp, attr_map_list, i); } repr_data->name_to_index_mapping = result; return flat_list; }
/* 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); }
=item C<static void set_cstring_prop(PARROT_INTERP, PMC *lib_pmc, const char *what, STRING *name)> Sets a property C<name> with value C<what> on the C<ParrotLibrary> C<lib_pmc>. =cut */ static void set_cstring_prop(PARROT_INTERP, ARGMOD(PMC *lib_pmc), ARGIN(const char *what), ARGIN(STRING *name)) { ASSERT_ARGS(set_cstring_prop) STRING * const key = Parrot_str_new_constant(interp, what); PMC * const prop = Parrot_pmc_new(interp, enum_class_String); VTABLE_set_string_native(interp, prop, name); Parrot_pmc_setprop(interp, lib_pmc, key, prop); } /* =item C<static void store_lib_pmc(PARROT_INTERP, PMC *lib_pmc, STRING *path, STRING *type, STRING *lib_name)> Stores a C<ParrotLibrary> PMC in the interpreter's C<iglobals>. =cut
/* This works out an allocation strategy for the object. It takes care of * "inlining" storage of attributes that are natively typed, as well as * noting unbox targets. */ static void compute_allocation_strategy(PARROT_INTERP, PMC *WHAT, P6opaqueREPRData *repr_data) { STRING *type_str = Parrot_str_new_constant(interp, "type"); STRING *box_target_str = Parrot_str_new_constant(interp, "box_target"); STRING *avcont_str = Parrot_str_new_constant(interp, "auto_viv_container"); PMC *flat_list; /* * We have to block GC mark here. Because "repr" is assotiated with some * PMC which is not accessible in this function. And we have to write * barrier this PMC because we are poking inside it guts directly. We * do have WB in caller function, but it can be triggered too late is * any of allocation will cause GC run. * * This is kind of minor evil until after I'll find better solution. */ Parrot_block_GC_mark(interp); /* Compute index mapping table and get flat list of attributes. */ flat_list = index_mapping_and_flat_list(interp, WHAT, repr_data); /* If we have no attributes in the index mapping, then just the header. */ if (repr_data->name_to_index_mapping[0].class_key == NULL) { repr_data->allocation_size = sizeof(P6opaqueInstance); } /* Otherwise, we need to compute the allocation strategy. */ else { /* We track the size of the body part, since that's what we want offsets into. */ INTVAL cur_size = 0; /* Get number of attributes and set up various counters. */ INTVAL num_attrs = VTABLE_elements(interp, flat_list); INTVAL info_alloc = num_attrs == 0 ? 1 : num_attrs; INTVAL cur_pmc_attr = 0; INTVAL cur_init_slot = 0; INTVAL cur_mark_slot = 0; INTVAL cur_cleanup_slot = 0; INTVAL cur_unbox_slot = 0; INTVAL i; /* Allocate offset array and GC mark info arrays. */ repr_data->num_attributes = num_attrs; repr_data->attribute_offsets = (INTVAL *) mem_sys_allocate(info_alloc * sizeof(INTVAL)); repr_data->flattened_stables = (STable **) mem_sys_allocate_zeroed(info_alloc * sizeof(PMC *)); repr_data->unbox_int_slot = -1; repr_data->unbox_num_slot = -1; repr_data->unbox_str_slot = -1; /* Go over the attributes and arrange their allocation. */ for (i = 0; i < num_attrs; i++) { PMC *attr = VTABLE_get_pmc_keyed_int(interp, flat_list, i); /* Fetch its type and box target flag, if available. */ PMC *type = accessor_call(interp, attr, type_str); PMC *box_target = accessor_call(interp, attr, box_target_str); PMC *av_cont = accessor_call(interp, attr, avcont_str); /* Work out what unboxed type it is, if any. Default to a boxed. */ INTVAL unboxed_type = STORAGE_SPEC_BP_NONE; INTVAL bits = sizeof(PMC *) * 8; if (!PMC_IS_NULL(type)) { /* Get the storage spec of the type and see what it wants. */ storage_spec spec = REPR(type)->get_storage_spec(interp, STABLE(type)); if (spec.inlineable == STORAGE_SPEC_INLINED) { /* Yes, it's something we'll flatten. */ unboxed_type = spec.boxed_primitive; bits = spec.bits; repr_data->flattened_stables[i] = STABLE(type); /* Does it need special initialization? */ if (REPR(type)->initialize) { if (!repr_data->initialize_slots) repr_data->initialize_slots = (INTVAL *) mem_sys_allocate_zeroed((info_alloc + 1) * sizeof(INTVAL)); repr_data->initialize_slots[cur_init_slot] = i; cur_init_slot++; } /* Does it have special GC needs? */ if (REPR(type)->gc_mark) { if (!repr_data->gc_mark_slots) repr_data->gc_mark_slots = (INTVAL *) mem_sys_allocate_zeroed((info_alloc + 1) * sizeof(INTVAL)); repr_data->gc_mark_slots[cur_mark_slot] = i; cur_mark_slot++; } if (REPR(type)->gc_cleanup) { if (!repr_data->gc_cleanup_slots) repr_data->gc_cleanup_slots = (INTVAL *) mem_sys_allocate_zeroed((info_alloc + 1) * sizeof(INTVAL)); repr_data->gc_cleanup_slots[cur_cleanup_slot] = i; cur_cleanup_slot++; } /* Is it a target for box/unbox operations? */ if (!PMC_IS_NULL(box_target) && VTABLE_get_bool(interp, box_target)) { /* If it boxes a primitive, note that. */ switch (unboxed_type) { case STORAGE_SPEC_BP_INT: if (repr_data->unbox_int_slot >= 0) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Duplicate box_target for native int"); repr_data->unbox_int_slot = i; break; case STORAGE_SPEC_BP_NUM: if (repr_data->unbox_num_slot >= 0) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Duplicate box_target for native num"); repr_data->unbox_num_slot = i; break; case STORAGE_SPEC_BP_STR: if (repr_data->unbox_str_slot >= 0) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "Duplicate box_target for native str"); repr_data->unbox_str_slot = i; break; default: /* nothing, just suppress 'missing default' warning */ break; } /* Also list in the by-repr unbox list. */ if (repr_data->unbox_slots == NULL) repr_data->unbox_slots = (P6opaqueBoxedTypeMap *) mem_sys_allocate_zeroed(info_alloc * sizeof(P6opaqueBoxedTypeMap)); repr_data->unbox_slots[cur_unbox_slot].repr_id = REPR(type)->ID; repr_data->unbox_slots[cur_unbox_slot].slot = i; cur_unbox_slot++; } } } /* Handle PMC attributes, which need marking and may have auto-viv needs. */ if (unboxed_type == STORAGE_SPEC_BP_NONE) { if (!repr_data->gc_pmc_mark_offsets) repr_data->gc_pmc_mark_offsets = (INTVAL *) mem_sys_allocate_zeroed(info_alloc * sizeof(INTVAL)); repr_data->gc_pmc_mark_offsets[cur_pmc_attr] = cur_size; cur_pmc_attr++; if (!PMC_IS_NULL(av_cont)) { if (!repr_data->auto_viv_values) repr_data->auto_viv_values = (PMC **) mem_sys_allocate_zeroed(info_alloc * sizeof(PMC *)); repr_data->auto_viv_values[i] = av_cont; } } /* Do allocation. */ /* XXX TODO Alignment! Important when we get int1, int8, etc. */ repr_data->attribute_offsets[i] = cur_size; cur_size += bits / 8; } /* Finally, put computed allocation size in place; it's body size plus * header size. Also number of markables and sentinels. */ repr_data->allocation_size = cur_size + sizeof(P6opaqueInstance); repr_data->gc_pmc_mark_offsets_count = cur_pmc_attr; if (repr_data->initialize_slots) repr_data->initialize_slots[cur_init_slot] = -1; if (repr_data->gc_mark_slots) repr_data->gc_mark_slots[cur_mark_slot] = -1; if (repr_data->gc_cleanup_slots) repr_data->gc_cleanup_slots[cur_cleanup_slot] = -1; } Parrot_unblock_GC_mark(interp); }
/* Bootstraps the KnowHOW. This is were things "bottom out" in the meta-model * so it's a tad loopy. Basically, we create a KnowHOW type object. We then * create an instance from that and add a bunch of methods to it. Returns the * bootstrapped object. */ PMC * SixModelObject_bootstrap_knowhow(PARROT_INTERP, PMC *sc) { /* Create our KnowHOW type object. Note we don't have a HOW just yet, so * pass in null. */ REPROps *REPR = REPR_get_by_name(interp, Parrot_str_new_constant(interp, "KnowHOWREPR")); PMC *knowhow_pmc = REPR->type_object_for(interp, PMCNULL); /* We create a KnowHOW instance that can describe itself. This means * .HOW.HOW.HOW.HOW etc will always return that, which closes the model * up. Also pull out its underlying struct. */ PMC *knowhow_how_pmc = REPR->allocate(interp, NULL); KnowHOWREPRInstance *knowhow_how = (KnowHOWREPRInstance *)PMC_data(knowhow_how_pmc); /* Need to give the knowhow_how a twiddled STable with a different * dispatcher, so things bottom out. */ PMC *st_copy = create_stable(interp, REPR, knowhow_how_pmc); STABLE_STRUCT(st_copy)->WHAT = knowhow_pmc; STABLE_STRUCT(st_copy)->find_method = bottom_find_method; knowhow_how->common.stable = st_copy; /* Add various methods to the KnowHOW's HOW. */ knowhow_how->body.methods = Parrot_pmc_new(interp, enum_class_Hash); knowhow_how->body.attributes = Parrot_pmc_new(interp, enum_class_ResizablePMCArray); VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods, Parrot_str_new_constant(interp, "new_type"), wrap_c(interp, F2DPTR(new_type))); VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods, Parrot_str_new_constant(interp, "find_method"), wrap_c(interp, F2DPTR(find_method))); VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods, Parrot_str_new_constant(interp, "add_method"), wrap_c(interp, F2DPTR(add_method))); VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods, Parrot_str_new_constant(interp, "add_attribute"), wrap_c(interp, F2DPTR(add_attribute))); VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods, Parrot_str_new_constant(interp, "compose"), wrap_c(interp, F2DPTR(compose))); VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods, Parrot_str_new_constant(interp, "parents"), wrap_c(interp, F2DPTR(parents))); VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods, Parrot_str_new_constant(interp, "attributes"), wrap_c(interp, F2DPTR(attributes))); VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods, Parrot_str_new_constant(interp, "methods"), wrap_c(interp, F2DPTR(methods))); VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods, Parrot_str_new_constant(interp, "mro"), wrap_c(interp, F2DPTR(mro))); VTABLE_set_pmc_keyed_str(interp, knowhow_how->body.methods, Parrot_str_new_constant(interp, "name"), wrap_c(interp, F2DPTR(name))); /* Set name KnowHOW for the KnowHOW's HOW. */ knowhow_how->body.name = Parrot_str_new_constant(interp, "KnowHOW"); /* Set this built up HOW as the KnowHOW's HOW. */ STABLE(knowhow_pmc)->HOW = knowhow_how_pmc; /* Give it an authoritative method cache and type check list. */ STABLE(knowhow_pmc)->method_cache = knowhow_how->body.methods; STABLE(knowhow_pmc)->mode_flags = METHOD_CACHE_AUTHORITATIVE; STABLE(knowhow_pmc)->type_check_cache_length = 1; STABLE(knowhow_pmc)->type_check_cache = (PMC **)mem_sys_allocate(sizeof(PMC *)); STABLE(knowhow_pmc)->type_check_cache[0] = knowhow_pmc; /* Set up some string constants that the methods here use. */ repr_str = Parrot_str_new_constant(interp, "repr"); name_str = Parrot_str_new_constant(interp, "name"); empty_str = Parrot_str_new_constant(interp, ""); p6opaque_str = Parrot_str_new_constant(interp, "P6opaque"); attribute_str = Parrot_str_new_constant(interp, "attribute"); /* Associate the created objects with the intial core serialization * context. */ VTABLE_set_pmc_keyed_int(interp, sc, 0, knowhow_pmc); SC_PMC(knowhow_pmc) = sc; VTABLE_set_pmc_keyed_int(interp, sc, 1, knowhow_how_pmc); SC_PMC(knowhow_how_pmc) = sc; STABLE(knowhow_pmc)->sc = sc; STABLE(knowhow_how_pmc)->sc = sc; return knowhow_pmc; }
int main(int argc, const char *argv[]) { int nextarg; Parrot_Interp interp; PDB_t *pdb; const char *scriptname = NULL; interp = Parrot_interp_new(NULL); Parrot_debugger_init(interp); pdb = interp->pdb; pdb->state = PDB_ENTER; Parrot_block_GC_mark(interp); Parrot_block_GC_sweep(interp); nextarg = 1; if (argv[nextarg] && strcmp(argv[nextarg], "--script") == 0) { scriptname = argv [++nextarg]; ++nextarg; } if (argv[nextarg]) { const char * const filename = argv[nextarg]; if (*filename == '-') { fprintf(stderr, "parrot_debugger takes no -x or --xxxx flag arguments\n"); exit(1); } else { STRING * const filename_str = Parrot_str_new(interp, filename, 0); PackFile * const pfraw = Parrot_pf_read_pbc_file(interp, filename_str); Parrot_PackFile pf; if (pfraw == NULL) return 1; pf = Parrot_pf_get_packfile_pmc(interp, pfraw, filename_str); if (pf == NULL) return 1; Parrot_pf_set_current_packfile(interp, pf); Parrot_pf_prepare_packfile_init(interp, pf); } } else { /* Generate some code to be able to enter into runloop */ STRING * const compiler_s = Parrot_str_new_constant(interp, "PIR"); PMC * const compiler = Parrot_interp_get_compiler(interp, compiler_s); STRING * const source = Parrot_str_new_constant(interp, ".sub aux :main\nexit 0\n.end\n"); PMC * const code = Parrot_interp_compile_string(interp, compiler, source); if (PMC_IS_NULL(code)) Parrot_warn(interp, PARROT_WARNINGS_NONE_FLAG, "Unexpected compiler problem at debugger start"); } Parrot_unblock_GC_mark(interp); Parrot_unblock_GC_sweep(interp); if (scriptname) PDB_script_file(interp, scriptname); else PDB_printwelcome(); Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "debugger")); PDB_run_code(interp, argc - nextarg, argv + nextarg); Parrot_x_exit(interp, 0); }
/* This works out an allocation strategy for the object. It takes care of * "inlining" storage of attributes that are natively typed, as well as * noting unbox targets. */ static void compute_allocation_strategy(PARROT_INTERP, PMC *repr_info, CStructREPRData *repr_data) { STRING *type_str = Parrot_str_new_constant(interp, "type"); PMC *flat_list; /* * We have to block GC mark here. Because "repr" is assotiated with some * PMC which is not accessible in this function. And we have to write * barrier this PMC because we are poking inside it guts directly. We * do have WB in caller function, but it can be triggered too late is * any of allocation will cause GC run. * * This is kind of minor evil until after I'll find better solution. */ Parrot_block_GC_mark(interp); /* Compute index mapping table and get flat list of attributes. */ flat_list = index_mapping_and_flat_list(interp, repr_info, repr_data); /* If we have no attributes in the index mapping, then just the header. */ if (repr_data->name_to_index_mapping[0].class_key == NULL) { repr_data->struct_size = 1; /* avoid 0-byte malloc */ } /* Otherwise, we need to compute the allocation strategy. */ else { /* We track the size of the struct, which is what we'll want offsets into. */ INTVAL cur_size = 0; /* Get number of attributes and set up various counters. */ INTVAL num_attrs = VTABLE_elements(interp, flat_list); INTVAL info_alloc = num_attrs == 0 ? 1 : num_attrs; INTVAL cur_obj_attr = 0; INTVAL cur_str_attr = 0; INTVAL cur_init_slot = 0; INTVAL i; /* Allocate location/offset arrays and GC mark info arrays. */ repr_data->num_attributes = num_attrs; repr_data->attribute_locations = (INTVAL *) mem_sys_allocate(info_alloc * sizeof(INTVAL)); repr_data->struct_offsets = (INTVAL *) mem_sys_allocate(info_alloc * sizeof(INTVAL)); repr_data->flattened_stables = (STable **) mem_sys_allocate_zeroed(info_alloc * sizeof(PMC *)); repr_data->member_types = (PMC** ) mem_sys_allocate_zeroed(info_alloc * sizeof(PMC *)); /* Go over the attributes and arrange their allocation. */ for (i = 0; i < num_attrs; i++) { /* Fetch its type; see if it's some kind of unboxed type. */ PMC *attr = VTABLE_get_pmc_keyed_int(interp, flat_list, i); PMC *type = VTABLE_get_pmc_keyed_str(interp, attr, type_str); INTVAL type_id = REPR(type)->ID; INTVAL bits = sizeof(void *) * 8; INTVAL align = ALIGNOF1(void *); if (!PMC_IS_NULL(type)) { /* See if it's a type that we know how to handle in a C struct. */ storage_spec spec = REPR(type)->get_storage_spec(interp, STABLE(type)); if (spec.inlineable == STORAGE_SPEC_INLINED && (spec.boxed_primitive == STORAGE_SPEC_BP_INT || spec.boxed_primitive == STORAGE_SPEC_BP_NUM)) { /* It's a boxed int or num; pretty easy. It'll just live in the * body of the struct. Instead of masking in i here (which * would be the parallel to how we handle boxed types) we * repurpose it to store the bit-width of the type, so * that get_attribute_ref can find it later. */ bits = spec.bits; align = spec.align; if (bits % 8) { Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "CStruct only supports native types that are a multiple of 8 bits wide (was passed: %ld)", bits); } repr_data->attribute_locations[i] = (bits << CSTRUCT_ATTR_SHIFT) | CSTRUCT_ATTR_IN_STRUCT; repr_data->flattened_stables[i] = STABLE(type); if (REPR(type)->initialize) { if (!repr_data->initialize_slots) repr_data->initialize_slots = (INTVAL *) mem_sys_allocate_zeroed((info_alloc + 1) * sizeof(INTVAL)); repr_data->initialize_slots[cur_init_slot] = i; cur_init_slot++; } } else if(spec.can_box & STORAGE_SPEC_CAN_BOX_STR) { /* It's a string of some kind. */ repr_data->num_child_objs++; repr_data->attribute_locations[i] = (cur_obj_attr++ << CSTRUCT_ATTR_SHIFT) | CSTRUCT_ATTR_STRING; repr_data->member_types[i] = type; } else if(type_id == get_ca_repr_id()) { /* It's a CArray of some kind. */ repr_data->num_child_objs++; repr_data->attribute_locations[i] = (cur_obj_attr++ << CSTRUCT_ATTR_SHIFT) | CSTRUCT_ATTR_CARRAY; repr_data->member_types[i] = type; } else if(type_id == get_cs_repr_id()) { /* It's a CStruct. */ repr_data->num_child_objs++; repr_data->attribute_locations[i] = (cur_obj_attr++ << CSTRUCT_ATTR_SHIFT) | CSTRUCT_ATTR_CSTRUCT; repr_data->member_types[i] = type; } else if(type_id == get_cp_repr_id()) { /* It's a CPointer. */ repr_data->num_child_objs++; repr_data->attribute_locations[i] = (cur_obj_attr++ << CSTRUCT_ATTR_SHIFT) | CSTRUCT_ATTR_CPTR; repr_data->member_types[i] = type; } else { Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "CStruct representation only implements native int and float members so far"); } } else { Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "CStruct representation requires the types of all attributes to be specified"); } /* Do allocation. */ /* C structure needs careful alignment. If cur_size is not aligned * to align bytes (cur_size % align), make sure it is before we * add the next element. */ if (cur_size % align) { cur_size += align - cur_size % align; } repr_data->struct_offsets[i] = cur_size; cur_size += bits / 8; } /* Finally, put computed allocation size in place; it's body size plus * header size. Also number of markables and sentinels. */ repr_data->struct_size = cur_size; if (repr_data->initialize_slots) repr_data->initialize_slots[cur_init_slot] = -1; } Parrot_unblock_GC_mark(interp); }
/* Locates all of the attributes. Puts them onto a flattened, ordered * list of attributes (populating the passed flat_list). Also builds * the index mapping for doing named lookups. Note index is not related * to the storage position. */ static PMC * index_mapping_and_flat_list(PARROT_INTERP, PMC *mro, CStructREPRData *repr_data) { PMC *flat_list = Parrot_pmc_new(interp, enum_class_ResizablePMCArray); PMC *class_list = Parrot_pmc_new(interp, enum_class_ResizablePMCArray); PMC *attr_map_list = Parrot_pmc_new(interp, enum_class_ResizablePMCArray); STRING *name_str = Parrot_str_new_constant(interp, "name"); INTVAL current_slot = 0; INTVAL num_classes, i; CStructNameMap * result = NULL; /* Walk through the parents list. */ INTVAL mro_idx = VTABLE_elements(interp, mro); while (mro_idx) { /* Get current class in MRO. */ PMC *type_info = VTABLE_get_pmc_keyed_int(interp, mro, --mro_idx); PMC *current_class = decontainerize(interp, VTABLE_get_pmc_keyed_int(interp, type_info, 0)); /* Get its local parents; make sure we're not doing MI. */ PMC *parents = VTABLE_get_pmc_keyed_int(interp, type_info, 2); INTVAL num_parents = VTABLE_elements(interp, parents); if (num_parents <= 1) { /* Get attributes and iterate over them. */ PMC *attributes = VTABLE_get_pmc_keyed_int(interp, type_info, 1); PMC *attr_map = PMCNULL; PMC *attr_iter = VTABLE_get_iter(interp, attributes); while (VTABLE_get_bool(interp, attr_iter)) { /* Get attribute. */ PMC * attr = VTABLE_shift_pmc(interp, attr_iter); /* Get its name. */ PMC *name_pmc = VTABLE_get_pmc_keyed_str(interp, attr, name_str); STRING *name = VTABLE_get_string(interp, name_pmc); /* Allocate a slot. */ if (PMC_IS_NULL(attr_map)) attr_map = Parrot_pmc_new(interp, enum_class_Hash); VTABLE_set_pmc_keyed_str(interp, attr_map, name, Parrot_pmc_new_init_int(interp, enum_class_Integer, current_slot)); current_slot++; /* Push attr onto the flat list. */ VTABLE_push_pmc(interp, flat_list, attr); } /* Add to class list and map list. */ VTABLE_push_pmc(interp, class_list, current_class); VTABLE_push_pmc(interp, attr_map_list, attr_map); } else { Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "CStruct representation does not support multiple inheritance"); } } /* We can now form the name map. */ num_classes = VTABLE_elements(interp, class_list); result = (CStructNameMap *) mem_sys_allocate_zeroed(sizeof(CStructNameMap) * (1 + num_classes)); for (i = 0; i < num_classes; i++) { result[i].class_key = VTABLE_get_pmc_keyed_int(interp, class_list, i); result[i].name_map = VTABLE_get_pmc_keyed_int(interp, attr_map_list, i); } repr_data->name_to_index_mapping = result; return flat_list; }
void parrot_init_library_paths(PARROT_INTERP) { ASSERT_ARGS(parrot_init_library_paths) PMC *paths; STRING *entry; STRING *versionlib = NULL; STRING *builddir = NULL; PMC * const iglobals = interp->iglobals; PMC * const config_hash = VTABLE_get_pmc_keyed_int(interp, iglobals, (INTVAL)IGLOBALS_CONFIG_HASH); /* create the lib_paths array */ PMC * const lib_paths = Parrot_pmc_new_init_int(interp, enum_class_FixedPMCArray, PARROT_LIB_PATH_SIZE); VTABLE_set_pmc_keyed_int(interp, iglobals, IGLOBALS_LIB_PATHS, lib_paths); if (VTABLE_elements(interp, config_hash)) { STRING * const libkey = CONST_STRING(interp, "libdir"); STRING * const verkey = CONST_STRING(interp, "versiondir"); STRING * const builddirkey = CONST_STRING(interp, "build_dir"); STRING * const installed = CONST_STRING(interp, "installed"); versionlib = VTABLE_get_string_keyed_str(interp, config_hash, libkey); entry = VTABLE_get_string_keyed_str(interp, config_hash, verkey); versionlib = Parrot_str_concat(interp, versionlib, entry); if (!VTABLE_get_integer_keyed_str(interp, config_hash, installed)) builddir = VTABLE_get_string_keyed_str(interp, config_hash, builddirkey); } /* each is an array of strings */ /* define include paths */ paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray); VTABLE_set_pmc_keyed_int(interp, lib_paths, PARROT_LIB_PATH_INCLUDE, paths); { /* EXPERIMENTAL: add include path from environment */ const char *envvar = Parrot_getenv(interp, Parrot_str_new_constant(interp, "PARROT_INCLUDE")); if (envvar != NULL && envvar[0]) { entry = Parrot_str_new(interp, envvar, 0); VTABLE_push_string(interp, paths, entry); } } if (!STRING_IS_NULL(builddir)) { entry = Parrot_str_concat(interp, builddir, CONST_STRING(interp, "/")); VTABLE_push_string(interp, paths, entry); entry = Parrot_str_concat(interp, builddir, CONST_STRING(interp, "/runtime/parrot/include/")); VTABLE_push_string(interp, paths, entry); } entry = CONST_STRING(interp, "./"); VTABLE_push_string(interp, paths, entry); if (!STRING_IS_NULL(versionlib)) { entry = Parrot_str_concat(interp, versionlib, CONST_STRING(interp, "/include/")); VTABLE_push_string(interp, paths, entry); } /* define library paths */ paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray); VTABLE_set_pmc_keyed_int(interp, lib_paths, PARROT_LIB_PATH_LIBRARY, paths); { /* EXPERIMENTAL: add library path from environment */ const char *envvar = Parrot_getenv(interp, Parrot_str_new_constant(interp, "PARROT_LIBRARY")); if (envvar != NULL && envvar[0]) { entry = Parrot_str_new(interp, envvar, 0); VTABLE_push_string(interp, paths, entry); } } if (!STRING_IS_NULL(builddir)) { entry = Parrot_str_concat(interp, builddir, CONST_STRING(interp, "/runtime/parrot/library/")); VTABLE_push_string(interp, paths, entry); } entry = CONST_STRING(interp, "./"); VTABLE_push_string(interp, paths, entry); if (!STRING_IS_NULL(versionlib)) { entry = Parrot_str_concat(interp, versionlib, CONST_STRING(interp, "/library/")); VTABLE_push_string(interp, paths, entry); } /* define languages paths */ paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray); VTABLE_set_pmc_keyed_int(interp, lib_paths, PARROT_LIB_PATH_LANG, paths); if (!STRING_IS_NULL(builddir)) { entry = Parrot_str_concat(interp, builddir, CONST_STRING(interp, "/runtime/parrot/languages/")); VTABLE_push_string(interp, paths, entry); } entry = CONST_STRING(interp, "./"); VTABLE_push_string(interp, paths, entry); if (!STRING_IS_NULL(versionlib)) { entry = Parrot_str_concat(interp, versionlib, CONST_STRING(interp, "/languages/")); VTABLE_push_string(interp, paths, entry); } /* define dynext paths */ paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray); VTABLE_set_pmc_keyed_int(interp, lib_paths, PARROT_LIB_PATH_DYNEXT, paths); if (!STRING_IS_NULL(builddir)) { entry = Parrot_str_concat(interp, builddir, CONST_STRING(interp, "/runtime/parrot/dynext/")); VTABLE_push_string(interp, paths, entry); } entry = CONST_STRING(interp, "dynext/"); VTABLE_push_string(interp, paths, entry); if (!STRING_IS_NULL(versionlib)) { entry = Parrot_str_concat(interp, versionlib, CONST_STRING(interp, "/dynext/")); VTABLE_push_string(interp, paths, entry); } /* shared exts */ paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray); VTABLE_set_pmc_keyed_int(interp, lib_paths, PARROT_LIB_DYN_EXTS, paths); /* no CONST_STRING here - the c2str.pl preprocessor needs "real strs" */ entry = Parrot_str_new_constant(interp, PARROT_LOAD_EXT); VTABLE_push_string(interp, paths, entry); /* OS/X has .dylib and .bundle */ if (!STREQ(PARROT_LOAD_EXT, PARROT_SHARE_EXT)) { entry = Parrot_str_new_constant(interp, PARROT_SHARE_EXT); VTABLE_push_string(interp, paths, entry); } #ifdef PARROT_PLATFORM_LIB_PATH_INIT_HOOK PARROT_PLATFORM_LIB_PATH_INIT_HOOK(interp, lib_paths); #endif }
int main(int argc, const char *argv[]) { int nextarg; Parrot_Interp interp; PDB_t *pdb; const char *scriptname = NULL; const unsigned char * configbytes = Parrot_get_config_hash_bytes(); const int configlength = Parrot_get_config_hash_length(); interp = Parrot_new(NULL); Parrot_set_executable_name(interp, Parrot_str_new(interp, argv[0], 0)); Parrot_set_configuration_hash_legacy(interp, configlength, configbytes); Parrot_debugger_init(interp); pdb = interp->pdb; pdb->state = PDB_ENTER; Parrot_block_GC_mark(interp); Parrot_block_GC_sweep(interp); nextarg = 1; if (argv[nextarg] && strcmp(argv[nextarg], "--script") == 0) { scriptname = argv [++nextarg]; ++nextarg; } if (argv[nextarg]) { const char *filename = argv[nextarg]; const char *ext = strrchr(filename, '.'); if (ext && STREQ(ext, ".pbc")) { Parrot_PackFile pf = Parrot_pbc_read(interp, filename, 0); if (!pf) return 1; Parrot_pbc_load(interp, pf); PackFile_fixup_subs(interp, PBC_MAIN, NULL); } else { STRING *errmsg = NULL; Parrot_PackFile pf = PackFile_new(interp, 0); Parrot_pbc_load(interp, pf); Parrot_compile_file(interp, filename, &errmsg); if (errmsg) Parrot_ex_throw_from_c_args(interp, NULL, 1, "%S", errmsg); PackFile_fixup_subs(interp, PBC_POSTCOMP, NULL); /* load the source for debugger list */ PDB_load_source(interp, filename); PackFile_fixup_subs(interp, PBC_MAIN, NULL); } } else { /* Generate some code to be able to enter into runloop */ STRING *compiler = Parrot_str_new_constant(interp, "PIR"); STRING *errstr = NULL; const char source []= ".sub aux :main\nexit 0\n.end\n"; Parrot_compile_string(interp, compiler, source, &errstr); if (!STRING_IS_NULL(errstr)) Parrot_io_eprintf(interp, "%Ss\n", errstr); } Parrot_unblock_GC_mark(interp); Parrot_unblock_GC_sweep(interp); if (scriptname) PDB_script_file(interp, scriptname); else PDB_printwelcome(); Parrot_runcore_switch(interp, Parrot_str_new_constant(interp, "debugger")); PDB_run_code(interp, argc - nextarg, argv + nextarg); Parrot_x_exit(interp, 0); }
void parrot_init_library_paths(PARROT_INTERP) { ASSERT_ARGS(parrot_init_library_paths) PMC *paths; STRING *entry; PMC * const iglobals = interp->iglobals; /* create the lib_paths array */ PMC * const lib_paths = Parrot_pmc_new_init_int(interp, enum_class_FixedPMCArray, PARROT_LIB_PATH_SIZE); VTABLE_set_pmc_keyed_int(interp, iglobals, IGLOBALS_LIB_PATHS, lib_paths); /* each is an array of strings */ /* define include paths */ paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray); VTABLE_set_pmc_keyed_int(interp, lib_paths, PARROT_LIB_PATH_INCLUDE, paths); { /* EXPERIMENTAL: add include path from environment */ STRING *envvar = Parrot_getenv(interp, CONST_STRING(interp, "PARROT_INCLUDE")); Parrot_warn_experimental(interp, "PARROT_INCLUDE environment variable is experimental"); if (!STRING_IS_NULL(envvar) && !STRING_IS_EMPTY(envvar)) VTABLE_push_string(interp, paths, envvar); } entry = CONST_STRING(interp, "./"); VTABLE_push_string(interp, paths, entry); /* define library paths */ paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray); VTABLE_set_pmc_keyed_int(interp, lib_paths, PARROT_LIB_PATH_LIBRARY, paths); { /* EXPERIMENTAL: add library path from environment */ STRING *envvar = Parrot_getenv(interp, CONST_STRING(interp, "PARROT_LIBRARY")); Parrot_warn_experimental(interp, "PARROT_LIBRARY environment variable is experimental"); if (!STRING_IS_NULL(envvar) && !STRING_IS_EMPTY(envvar)) VTABLE_push_string(interp, paths, envvar); } entry = CONST_STRING(interp, "./"); VTABLE_push_string(interp, paths, entry); /* define languages paths */ paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray); VTABLE_set_pmc_keyed_int(interp, lib_paths, PARROT_LIB_PATH_LANG, paths); entry = CONST_STRING(interp, "./"); VTABLE_push_string(interp, paths, entry); /* define dynext paths */ paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray); VTABLE_set_pmc_keyed_int(interp, lib_paths, PARROT_LIB_PATH_DYNEXT, paths); entry = CONST_STRING(interp, "dynext/"); VTABLE_push_string(interp, paths, entry); /* shared exts */ paths = Parrot_pmc_new(interp, enum_class_ResizableStringArray); VTABLE_set_pmc_keyed_int(interp, lib_paths, PARROT_LIB_DYN_EXTS, paths); /* no CONST_STRING here - the c2str.pl preprocessor needs "real strs" */ entry = Parrot_str_new_constant(interp, PARROT_LOAD_EXT); VTABLE_push_string(interp, paths, entry); /* OS/X has .dylib and .bundle */ if (!STREQ(PARROT_LOAD_EXT, PARROT_SHARE_EXT)) { entry = Parrot_str_new_constant(interp, PARROT_SHARE_EXT); VTABLE_push_string(interp, paths, entry); } #ifdef PARROT_PLATFORM_LIB_PATH_INIT_HOOK PARROT_PLATFORM_LIB_PATH_INIT_HOOK(interp, lib_paths); #endif }
/* Initializes our cached versions of some strings and type IDs that we * use very commonly. For strings, this should mean we only compute their * hash value once, rather than every time we create and consume them. */ static void setup_binder_statics(PARROT_INTERP) { ACCEPTS = Parrot_str_new_constant(interp, "ACCEPTS"); HOW = Parrot_str_new_constant(interp, "HOW"); DO_str = Parrot_str_new_constant(interp, "$!do"); NAME_str = Parrot_str_new_constant(interp, "name"); SELF_str = Parrot_str_new_constant(interp, "self"); BLOCK_str = Parrot_str_new_constant(interp, "Block"); CAPTURE_str = Parrot_str_new_constant(interp, "Capture"); STORAGE_str = Parrot_str_new_constant(interp, "$!storage"); REST_str = Parrot_str_new_constant(interp, "$!rest"); LIST_str = Parrot_str_new_constant(interp, "$!list"); HASH_str = Parrot_str_new_constant(interp, "$!hash"); FLATTENS_str = Parrot_str_new_constant(interp, "$!flattens"); NEXTITER_str = Parrot_str_new_constant(interp, "$!nextiter"); HASH_SIGIL_str = Parrot_str_new_constant(interp, "%"); ARRAY_SIGIL_str = Parrot_str_new_constant(interp, "@"); BANG_TWIGIL_str = Parrot_str_new_constant(interp, "!"); SCALAR_SIGIL_str = Parrot_str_new_constant(interp, "$"); NAMED_str = Parrot_str_new_constant(interp, "named"); INSTANTIATE_GENERIC_str = Parrot_str_new_constant(interp, "instantiate_generic"); smo_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "SixModelObject", 0)); p6l_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "Perl6LexPad", 0)); qrpa_id = Parrot_pmc_get_type_str(interp, Parrot_str_new(interp, "QRPA", 0)); }
PARROT_EXPORT void Parrot_disassemble(PARROT_INTERP, ARGIN_NULLOK(const char *outfile), Parrot_disassemble_options options) { ASSERT_ARGS(Parrot_disassemble) PDB_line_t *line; PDB_t * const pdb = mem_gc_allocate_zeroed_typed(interp, PDB_t); int num_mappings = 0; int curr_mapping = 0; int op_code_seq_num = 0; int debugs; PMC *output; if (outfile != NULL) { output = Parrot_io_open_handle(interp, PMCNULL, Parrot_str_new(interp, outfile, 0), Parrot_str_new_constant(interp, "tw")); } else output = Parrot_io_stdhandle(interp, PIO_STDOUT_FILENO, PMCNULL); interp->pdb = pdb; pdb->cur_opcode = interp->code->base.data; PDB_disassemble(interp, NULL); line = pdb->file->line; debugs = (interp->code->debugs != NULL); print_constant_table(interp, output); if (options & enum_DIS_HEADER) return; if (!(options & enum_DIS_BARE)) Parrot_io_fprintf(interp, output, "# %12s-%12s", "Seq_Op_Num", "Relative-PC"); if (debugs) { if (!(options & enum_DIS_BARE)) Parrot_io_fprintf(interp, output, " %6s:\n", "SrcLn#"); num_mappings = interp->code->debugs->num_mappings; } else { Parrot_io_fprintf(interp, output, "\n"); } while (line->next) { const char *c; /* Parrot_io_fprintf(interp, output, "%i < %i %i == %i \n", curr_mapping, * num_mappings, op_code_seq_num, * interp->code->debugs->mappings[curr_mapping].offset); */ if (debugs && curr_mapping < num_mappings) { if (op_code_seq_num == interp->code->debugs->mappings[curr_mapping].offset) { const int filename_const_offset = interp->code->debugs->mappings[curr_mapping].filename; Parrot_io_fprintf(interp, output, "# Current Source Filename '%Ss'\n", interp->code->const_table->str.constants[filename_const_offset]); ++curr_mapping; } } if (!(options & enum_DIS_BARE)) Parrot_io_fprintf(interp, output, "%012i-%012i", op_code_seq_num, line->opcode - interp->code->base.data); if (debugs && !(options & enum_DIS_BARE)) Parrot_io_fprintf(interp, output, " %06i: ", interp->code->debugs->base.data[op_code_seq_num]); /* If it has a label print it */ if (line->label) Parrot_io_fprintf(interp, output, "L%li:\t", line->label->number); else Parrot_io_fprintf(interp, output, "\t"); c = pdb->file->source + line->source_offset; while (c && *c != '\n') Parrot_io_fprintf(interp, output, "%c", *(c++)); Parrot_io_fprintf(interp, output, "\n"); line = line->next; ++op_code_seq_num; } if (outfile != NULL) Parrot_io_close_handle(interp, output); return; }
/* Wraps up a C function as a raw NCI method. */ static PMC * wrap_c(PARROT_INTERP, void *func) { PMC * const wrapped = Parrot_pmc_new(interp, enum_class_NativePCCMethod); VTABLE_set_pointer_keyed_str(interp, wrapped, Parrot_str_new_constant(interp, "->"), func); return wrapped; }
/* Initializes our cached versions of some strings and type IDs that we * use very commonly. For strings, this should mean we only compute their * hash value once, rather than every time we create and consume them. */ static void setup_binder_statics(PARROT_INTERP) { ACCEPTS = Parrot_str_new_constant(interp, "ACCEPTS"); HOW = Parrot_str_new_constant(interp, "HOW"); DO_str = Parrot_str_new_constant(interp, "$!do"); RW_str = Parrot_str_new_constant(interp, "rw"); PUN_str = Parrot_str_new_constant(interp, "!pun"); PERL_str = Parrot_str_new_constant(interp, "perl"); HASH_str = Parrot_str_new_constant(interp, "Hash"); LIST_str = Parrot_str_new_constant(interp, "List"); SELF_str = Parrot_str_new_constant(interp, "self"); ARRAY_str = Parrot_str_new_constant(interp, "Array"); BLOCK_str = Parrot_str_new_constant(interp, "Block"); STORE_str = Parrot_str_new_constant(interp, "!STORE"); CREATE_str = Parrot_str_new_constant(interp, "CREATE"); SCALAR_str = Parrot_str_new_constant(interp, "scalar"); SELECT_str = Parrot_str_new_constant(interp, "!select"); CAPTURE_str = Parrot_str_new_constant(interp, "Capture"); SNAPCAP_str = Parrot_str_new_constant(interp, "!snapshot_capture"); STORAGE_str = Parrot_str_new_constant(interp, "$!storage"); JUNCTION_str = Parrot_str_new_constant(interp, "Junction"); P6_SCALAR_str = Parrot_str_new_constant(interp, "Perl6Scalar"); SHORTNAME_str = Parrot_str_new_constant(interp, "shortname"); HASH_SIGIL_str = Parrot_str_new_constant(interp, "%"); ARRAY_SIGIL_str = Parrot_str_new_constant(interp, "@"); BANG_TWIGIL_str = Parrot_str_new_constant(interp, "!"); CALLCONTEXT_str = Parrot_str_new_constant(interp, "CallContext"); SCALAR_SIGIL_str = Parrot_str_new_constant(interp, "$"); or_id = pmc_type(interp, Parrot_str_new(interp, "ObjectRef", 0)); lls_id = pmc_type(interp, Parrot_str_new(interp, "P6LowLevelSig", 0)); p6s_id = pmc_type(interp, P6_SCALAR_str); p6r_id = pmc_type(interp, Parrot_str_new(interp, "P6role", 0)); p6o_id = pmc_type(interp, Parrot_str_new(interp, "P6opaque", 0)); }