static void setup_process_stdio(MVMThreadContext *tc, MVMObject *handle, uv_process_t *process, uv_stdio_container_t *stdio, int fd, MVMint64 flags, const char *op) { if (flags & MVM_PIPE_CAPTURE) { MVMIOSyncPipeData *pipedata; if (REPR(handle)->ID != MVM_REPR_ID_MVMOSHandle) MVM_exception_throw_adhoc(tc, "%s requires an object with REPR MVMOSHandle", op); pipedata = (MVMIOSyncPipeData *)((MVMOSHandle *)handle)->body.data; pipedata->process = process; stdio->flags = UV_CREATE_PIPE | (fd == 0 ? UV_READABLE_PIPE : UV_WRITABLE_PIPE); stdio->data.stream = pipedata->ss.handle; } else if (flags & MVM_PIPE_INHERIT) { if (handle == tc->instance->VMNull) { stdio->flags = UV_INHERIT_FD; stdio->data.fd = fd; } else { MVMOSHandleBody body = ((MVMOSHandle *)handle)->body; if (REPR(handle)->ID != MVM_REPR_ID_MVMOSHandle) MVM_exception_throw_adhoc(tc, "%s requires an object with REPR MVMOSHandle", op); body.ops->pipeable->bind_stdio_handle(tc, ((MVMOSHandle *)handle), stdio, process); } } else stdio->flags = UV_IGNORE; }
MVMObject * MVM_repr_alloc_init(MVMThreadContext *tc, MVMObject *type) { MVMObject *obj = REPR(type)->allocate(tc, STABLE(type)); if (REPR(obj)->initialize) { MVMROOT(tc, obj, { REPR(obj)->initialize(tc, STABLE(obj), obj, OBJECT_BODY(obj)); });
/* Grabs a NativeCall body. */ static MVMNativeCallBody * get_nc_body(MVMThreadContext *tc, MVMObject *obj) { if (REPR(obj)->ID == MVM_REPR_ID_MVMNativeCall) return (MVMNativeCallBody *)OBJECT_BODY(obj); else return (MVMNativeCallBody *)REPR(obj)->box_funcs.get_boxed_ref(tc, STABLE(obj), obj, OBJECT_BODY(obj), MVM_REPR_ID_MVMNativeCall); }
/* 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); }
/* If we know the type of a significant operand, we might try to specialize by * representation. */ static void optimize_repr_op(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshBB *bb, MVMSpeshIns *ins, MVMint32 type_operand) { MVMSpeshFacts *facts = MVM_spesh_get_facts(tc, g, ins->operands[type_operand]); if (facts->flags & MVM_SPESH_FACT_KNOWN_TYPE && facts->type) if (REPR(facts->type)->spesh) REPR(facts->type)->spesh(tc, STABLE(facts->type), g, bb, ins); }
/* Attribute new method. */ static void attr_new(PARROT_INTERP, PMC *nci) { PMC * unused; PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *type = VTABLE_get_pmc_keyed_int(interp, capture, 0); STRING *name = VTABLE_get_string_keyed_str(interp, capture, name_str); PMC *self = REPR(type)->allocate(interp, STABLE(type)); REPR(self)->box_funcs->set_str(interp, STABLE(self), OBJECT_BODY(self), name); unused = Parrot_pcc_build_call_from_c_args(interp, capture, "P", self); }
/* Given the specified code object, copies it and returns a copy which * captures a closure over the current scope. */ MVMObject * MVM_frame_takeclosure(MVMThreadContext *tc, MVMObject *code) { MVMCode *closure; if (REPR(code)->ID != MVM_REPR_ID_MVMCode) MVM_exception_throw_adhoc(tc, "Can only perform takeclosure on object with representation MVMCode"); MVMROOT(tc, code, { closure = (MVMCode *)REPR(code)->allocate(tc, STABLE(code)); });
/* Marks a collectable item (object, type object, STable). */ void MVM_gc_mark_collectable(MVMThreadContext *tc, MVMGCWorklist *worklist, MVMCollectable *new_addr) { MVMuint16 i; MVM_gc_worklist_add(tc, worklist, &new_addr->sc); if (!(new_addr->flags & (MVM_CF_TYPE_OBJECT | MVM_CF_STABLE))) { /* Need to view it as an object in here. */ MVMObject *new_addr_obj = (MVMObject *)new_addr; /* Add the STable to the worklist. */ MVM_gc_worklist_add(tc, worklist, &new_addr_obj->st); /* If needed, mark it. This will add addresses to the worklist * that will need updating. Note that we are passing the address * of the object *after* copying it since those are the addresses * we care about updating; the old chunk of memory is now dead! */ if (MVM_GC_DEBUG_ENABLED(MVM_GC_DEBUG_COLLECT) && !STABLE(new_addr_obj)) MVM_panic(MVM_exitcode_gcnursery, "Found an outdated reference to address %p", new_addr); if (REPR(new_addr_obj)->gc_mark) REPR(new_addr_obj)->gc_mark(tc, STABLE(new_addr_obj), OBJECT_BODY(new_addr_obj), worklist); } else if (new_addr->flags & MVM_CF_TYPE_OBJECT) { /* Add the STable to the worklist. */ MVM_gc_worklist_add(tc, worklist, &((MVMObject *)new_addr)->st); } else if (new_addr->flags & MVM_CF_STABLE) { /* Add all references in the STable to the work list. */ MVMSTable *new_addr_st = (MVMSTable *)new_addr; MVM_gc_worklist_add(tc, worklist, &new_addr_st->HOW); MVM_gc_worklist_add(tc, worklist, &new_addr_st->WHAT); MVM_gc_worklist_add(tc, worklist, &new_addr_st->method_cache); for (i = 0; i < new_addr_st->vtable_length; i++) MVM_gc_worklist_add(tc, worklist, &new_addr_st->vtable[i]); for (i = 0; i < new_addr_st->type_check_cache_length; i++) MVM_gc_worklist_add(tc, worklist, &new_addr_st->type_check_cache[i]); if (new_addr_st->container_spec) if (new_addr_st->container_spec->gc_mark_data) new_addr_st->container_spec->gc_mark_data(tc, new_addr_st, worklist); if (new_addr_st->boolification_spec) MVM_gc_worklist_add(tc, worklist, &new_addr_st->boolification_spec->method); if (new_addr_st->invocation_spec) { MVM_gc_worklist_add(tc, worklist, &new_addr_st->invocation_spec->class_handle); MVM_gc_worklist_add(tc, worklist, &new_addr_st->invocation_spec->attr_name); MVM_gc_worklist_add(tc, worklist, &new_addr_st->invocation_spec->invocation_handler); } MVM_gc_worklist_add(tc, worklist, &new_addr_st->WHO); /* If it needs to have its REPR data marked, do that. */ if (new_addr_st->REPR->gc_mark_repr_data) new_addr_st->REPR->gc_mark_repr_data(tc, new_addr_st, worklist); } else { MVM_panic(MVM_exitcode_gcnursery, "Internal error: impossible case encountered in GC marking"); } }
/* KnowHOW.new_type method. Creates a new type with this HOW as its meta-object. */ static void new_type(MVMThreadContext *tc, MVMCallsite *callsite, MVMRegister *args) { MVMObject *self, *HOW, *type_object, *BOOTHash, *stash; MVMArgInfo repr_arg, name_arg; MVMString *repr_name, *name; const MVMREPROps *repr_to_use; MVMInstance *instance = tc->instance; /* Get arguments. */ MVMArgProcContext arg_ctx; arg_ctx.named_used = NULL; MVM_args_proc_init(tc, &arg_ctx, callsite, args); MVM_args_checkarity(tc, &arg_ctx, 1, 1); self = MVM_args_get_pos_obj(tc, &arg_ctx, 0, MVM_ARG_REQUIRED).arg.o; repr_arg = MVM_args_get_named_str(tc, &arg_ctx, instance->str_consts.repr, MVM_ARG_OPTIONAL); name_arg = MVM_args_get_named_str(tc, &arg_ctx, instance->str_consts.name, MVM_ARG_OPTIONAL); MVM_args_proc_cleanup(tc, &arg_ctx); if (REPR(self)->ID != MVM_REPR_ID_KnowHOWREPR) MVM_exception_throw_adhoc(tc, "KnowHOW methods must be called on object with REPR KnowHOWREPR"); /* See if we have a representation name; if not default to P6opaque. */ repr_name = repr_arg.exists ? repr_arg.arg.s : instance->str_consts.P6opaque; repr_to_use = MVM_repr_get_by_name(tc, repr_name); MVM_gc_root_temp_push(tc, (MVMCollectable **)&name_arg); /* We first create a new HOW instance. */ HOW = REPR(self)->allocate(tc, STABLE(self)); MVM_gc_root_temp_push(tc, (MVMCollectable **)&HOW); /* 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. */ type_object = repr_to_use->type_object_for(tc, HOW); MVM_gc_root_temp_push(tc, (MVMCollectable **)&type_object); /* This may move name_arg.arg.s so do it first: */ REPR(HOW)->initialize(tc, STABLE(HOW), HOW, OBJECT_BODY(HOW)); /* See if we were given a name; put it into the meta-object if so. */ name = name_arg.exists ? name_arg.arg.s : instance->str_consts.anon; MVM_ASSIGN_REF(tc, &(HOW->header), ((MVMKnowHOWREPR *)HOW)->body.name, name); /* Set .WHO to an empty hash. */ BOOTHash = tc->instance->boot_types.BOOTHash; stash = REPR(BOOTHash)->allocate(tc, STABLE(BOOTHash)); MVM_gc_root_temp_push(tc, (MVMCollectable **)&stash); MVM_ASSIGN_REF(tc, &(STABLE(type_object)->header), STABLE(type_object)->WHO, stash); /* Return the type object. */ MVM_args_set_result_obj(tc, type_object, MVM_RETURN_CURRENT_FRAME); MVM_gc_root_temp_pop_n(tc, 4); }
/* 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) { CStructREPRData *repr_data = (CStructREPRData *)st->REPR_data; CStructBody *body = (CStructBody *)data; INTVAL slot; /* Look up slot, then offset and compute address. */ slot = hint >= 0 ? hint : try_get_slot(interp, repr_data, class_handle, name); if (slot >= 0) { INTVAL type = repr_data->attribute_locations[slot] & CSTRUCT_ATTR_MASK; INTVAL real_slot = repr_data->attribute_locations[slot] >> CSTRUCT_ATTR_SHIFT; if(type == CSTRUCT_ATTR_IN_STRUCT) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "CStruct Can't perform boxed get on flattened attributes yet"); else { PMC *obj = body->child_objs[real_slot]; PMC *typeobj = repr_data->member_types[slot]; if(!obj) { void *cobj = get_ptr_at_offset(body->cstruct, repr_data->struct_offsets[slot]); if(cobj) { if(type == CSTRUCT_ATTR_CARRAY) { obj = make_carray_result(interp, typeobj, cobj); } else if(type == CSTRUCT_ATTR_CSTRUCT) { obj = make_cstruct_result(interp, typeobj, cobj); } else if(type == CSTRUCT_ATTR_CPTR) { obj = make_cpointer_result(interp, typeobj, cobj); } else if(type == CSTRUCT_ATTR_STRING) { char *cstr = (char *) cobj; STRING *str = Parrot_str_new_init(interp, cstr, strlen(cstr), Parrot_utf8_encoding_ptr, 0); obj = REPR(typeobj)->allocate(interp, STABLE(typeobj)); REPR(obj)->initialize(interp, STABLE(obj), OBJECT_BODY(obj)); REPR(obj)->box_funcs->set_str(interp, STABLE(obj), OBJECT_BODY(obj), str); PARROT_GC_WRITE_BARRIER(interp, obj); } body->child_objs[real_slot] = obj; } else { obj = typeobj; } } return obj; } }
/* 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); }
static void optimize_is_reprid(MVMThreadContext *tc, MVMSpeshGraph *g, MVMSpeshIns *ins) { MVMSpeshFacts *obj_facts = MVM_spesh_get_facts(tc, g, ins->operands[1]); MVMuint32 wanted_repr_id; MVMuint64 result_value; if (!(obj_facts->flags & MVM_SPESH_FACT_KNOWN_TYPE)) { return; } switch (ins->info->opcode) { case MVM_OP_islist: wanted_repr_id = MVM_REPR_ID_MVMArray; break; case MVM_OP_ishash: wanted_repr_id = MVM_REPR_ID_MVMHash; break; case MVM_OP_isint: wanted_repr_id = MVM_REPR_ID_P6int; break; case MVM_OP_isnum: wanted_repr_id = MVM_REPR_ID_P6num; break; case MVM_OP_isstr: wanted_repr_id = MVM_REPR_ID_P6str; break; default: return; } result_value = REPR(obj_facts->type)->ID == wanted_repr_id; if (result_value == 0) { MVMSpeshFacts *result_facts = MVM_spesh_get_facts(tc, g, ins->operands[0]); ins->info = MVM_op_get_op(MVM_OP_const_i64_16); ins->operands[1].lit_i16 = 0; result_facts->flags |= MVM_SPESH_FACT_KNOWN_VALUE; result_facts->value.i64 = 0; } else { ins->info = MVM_op_get_op(MVM_OP_isnonnull); } }
MVMObject * MVM_hll_set_config(MVMThreadContext *tc, MVMString *name, MVMObject *config_hash) { MVMHLLConfig *config; config = MVM_hll_get_config_for(tc, name); if (!config_hash || REPR(config_hash)->ID != MVM_REPR_ID_MVMHash || !IS_CONCRETE(config_hash)) { MVM_exception_throw_adhoc(tc, "set hll config needs concrete hash"); } /* MVM_string_utf8_decode() can potentially allocate, and hence gc. */ MVMROOT(tc, config_hash, { check_config_key(tc, config_hash, "int_box", int_box_type, config); check_config_key(tc, config_hash, "num_box", num_box_type, config); check_config_key(tc, config_hash, "str_box", str_box_type, config); check_config_key(tc, config_hash, "slurpy_array", slurpy_array_type, config); check_config_key(tc, config_hash, "slurpy_hash", slurpy_hash_type, config); check_config_key(tc, config_hash, "array_iter", array_iterator_type, config); check_config_key(tc, config_hash, "hash_iter", hash_iterator_type, config); check_config_key(tc, config_hash, "foreign_type_int", foreign_type_int, config); check_config_key(tc, config_hash, "foreign_type_num", foreign_type_num, config); check_config_key(tc, config_hash, "foreign_type_str", foreign_type_str, config); check_config_key(tc, config_hash, "foreign_transform_array", foreign_transform_array, config); check_config_key(tc, config_hash, "foreign_transform_hash", foreign_transform_hash, config); check_config_key(tc, config_hash, "foreign_transform_code", foreign_transform_code, config); check_config_key(tc, config_hash, "null_value", null_value, config); check_config_key(tc, config_hash, "exit_handler", exit_handler, config); check_config_key(tc, config_hash, "bind_error", bind_error, config); check_config_key(tc, config_hash, "method_not_found_error", method_not_found_error, config); });
/* return an OSHandle representing one of the standard streams */ static MVMObject * MVM_file_get_stdstream(MVMThreadContext *tc, MVMuint8 type) { MVMOSHandle *result; apr_file_t *handle; apr_status_t rv; MVMObject *type_object = tc->instance->boot_types->BOOTIO; result = (MVMOSHandle *)REPR(type_object)->allocate(tc, STABLE(type_object)); /* need a temporary pool */ if ((rv = apr_pool_create(&result->body.mem_pool, NULL)) != APR_SUCCESS) { MVM_exception_throw_apr_error(tc, rv, "get_stream failed to create pool: "); } switch(type) { case 0: apr_file_open_stdin(&handle, result->body.mem_pool); break; case 1: apr_file_open_stdout(&handle, result->body.mem_pool); break; case 2: apr_file_open_stderr(&handle, result->body.mem_pool); break; } result->body.file_handle = handle; result->body.handle_type = MVM_OSHANDLE_FILE; result->body.encoding_type = MVM_encoding_type_utf8; return (MVMObject *)result; }
/* Attribute name introspection. */ static void attr_name(PARROT_INTERP, PMC *nci) { PMC * unused; PMC *capture = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); PMC *self = VTABLE_get_pmc_keyed_int(interp, capture, 0); STRING *name = REPR(self)->box_funcs->get_str(interp, STABLE(self), OBJECT_BODY(self)); unused = Parrot_pcc_build_call_from_c_args(interp, capture, "S", name); }
static STRING *get_str(PARROT_INTERP, STable *st, void *data) { CStrBody *body = (CStrBody *) data; PMC *old_ctx, *cappy, *meth, *enc_pmc; STRING *enc; STR_VTABLE *encoding; if (!body->cstr) return (STRING *) NULL; /* Look up "encoding" method. */ meth = VTABLE_find_method(interp, st->WHAT, Parrot_str_new_constant(interp, "encoding")); if (PMC_IS_NULL(meth)) Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION, "CStr representation expects an 'encoding' method, specifying the encoding"); old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); cappy = Parrot_pmc_new(interp, enum_class_CallContext); VTABLE_push_pmc(interp, cappy, st->WHAT); Parrot_pcc_invoke_from_sig_object(interp, meth, cappy); cappy = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp)); Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx); enc_pmc = decontainerize(interp, VTABLE_get_pmc_keyed_int(interp, cappy, 0)); enc = REPR(enc_pmc)->box_funcs->get_str(interp, STABLE(enc_pmc), OBJECT_BODY(enc_pmc)); return new_from_cstring(interp, body->cstr, enc); }
/* 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); }
/* Creates a Perl 6 Hash. */ static PMC * Rakudo_binding_create_hash(PARROT_INTERP, PMC *storage) { PMC *type = Rakudo_types_hash_get(); PMC *hash = REPR(type)->allocate(interp, STABLE(type)); VTABLE_set_attr_keyed(interp, hash, Rakudo_types_enummap_get(), STORAGE_str, storage); return hash; }
/* Boxes a native value. */ static PMC * create_box(PARROT_INTERP, Rakudo_BindVal bv) { PMC *box_type_obj = box_type(bv); PMC *boxed = REPR(box_type_obj)->allocate(interp, STABLE(box_type_obj)); switch (bv.type) { case BIND_VAL_INT: REPR(boxed)->box_funcs->set_int(interp, STABLE(boxed), OBJECT_BODY(boxed), bv.val.i); break; case BIND_VAL_NUM: REPR(boxed)->box_funcs->set_num(interp, STABLE(boxed), OBJECT_BODY(boxed), bv.val.n); break; case BIND_VAL_STR: REPR(boxed)->box_funcs->set_str(interp, STABLE(boxed), OBJECT_BODY(boxed), bv.val.s); break; } return boxed; }
/* This function gets shared with perl6.ops for the perl6_iter_from_rpa op. */ PMC * Rakudo_binding_iter_from_rpa(PARROT_INTERP, PMC *rpa, PMC *list) { PMC *type = Rakudo_types_listiter_get(); PMC *iter = REPR(type)->allocate(interp, STABLE(type)); VTABLE_set_attr_keyed(interp, iter, type, REST_str, rpa); VTABLE_set_attr_keyed(interp, iter, type, LIST_str, list); return iter; }
void MVM_coerce_smart_stringify(MVMThreadContext *tc, MVMObject *obj, MVMRegister *res_reg) { MVMObject *strmeth; const MVMStorageSpec *ss; /* Handle null case. */ if (MVM_is_null(tc, obj)) { res_reg->s = tc->instance->str_consts.empty; return; } /* If it can unbox as a string, that wins right off. */ ss = REPR(obj)->get_storage_spec(tc, STABLE(obj)); if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_STR && IS_CONCRETE(obj)) { res_reg->s = REPR(obj)->box_funcs.get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj)); return; } /* Check if there is a Str method. */ strmeth = MVM_6model_find_method_cache_only(tc, obj, tc->instance->str_consts.Str); if (!MVM_is_null(tc, strmeth)) { /* We need to do the invocation; just set it up with our result reg as * the one for the call. */ MVMObject *code = MVM_frame_find_invokee(tc, strmeth, NULL); MVMCallsite *inv_arg_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_INV_ARG); MVM_args_setup_thunk(tc, res_reg, MVM_RETURN_STR, inv_arg_callsite); tc->cur_frame->args[0].o = obj; STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args); return; } /* Otherwise, guess something appropriate. */ if (!IS_CONCRETE(obj)) res_reg->s = tc->instance->str_consts.empty; else { if (REPR(obj)->ID == MVM_REPR_ID_MVMException) res_reg->s = ((MVMException *)obj)->body.message; else if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_INT) res_reg->s = MVM_coerce_i_s(tc, REPR(obj)->box_funcs.get_int(tc, STABLE(obj), obj, OBJECT_BODY(obj))); else if (ss->can_box & MVM_STORAGE_SPEC_CAN_BOX_NUM) res_reg->s = MVM_coerce_n_s(tc, REPR(obj)->box_funcs.get_num(tc, STABLE(obj), obj, OBJECT_BODY(obj))); else MVM_exception_throw_adhoc(tc, "cannot stringify this"); } }
/* Takes two objects, which must be of VMArray representation and holding * 32-bit integers. Performs normalization to the specified form. */ static void assert_codepoint_array(MVMThreadContext *tc, MVMObject *arr, char *error) { if (IS_CONCRETE(arr) && REPR(arr)->ID == MVM_REPR_ID_MVMArray) { MVMuint8 slot_type = ((MVMArrayREPRData *)STABLE(arr)->REPR_data)->slot_type; if (slot_type == MVM_ARRAY_I32 || slot_type == MVM_ARRAY_U32) return; } MVM_exception_throw_adhoc(tc, "%s", error); }
/* Casts to a handle, checking it's a directory handle along the way. */ static MVMOSHandle * get_dirhandle(MVMThreadContext *tc, MVMObject *oshandle, const char *msg) { MVMOSHandle *handle = (MVMOSHandle *)oshandle; if (REPR(oshandle)->ID != MVM_REPR_ID_MVMOSHandle) MVM_exception_throw_adhoc(tc, "%s requires an object with REPR MVMOSHandle", msg); if (handle->body.ops != &op_table) MVM_exception_throw_adhoc(tc, "%s got incorrect kind of handle", msg); return handle; }
init_builtins () { long rule, alt; equal = get_builtin ("equal"); if (meta_uniq_flag) *(REPR (equal)) = 'f'; notequal = get_builtin ("notequal"); if (meta_uniq_flag) *(REPR (notequal)) = 'f'; endofsentence = get_builtin ("endofsentence"); evalmeta = get_builtin ("evalmeta"); explintersect = get_builtin ("explintersect_"); falseip = get_builtin ("falseip_"); getip = get_builtin ("getip_"); initmeta = get_builtin ("initmeta"); initmint = get_builtin ("initmint_"); intersect = get_builtin ("intersect_"); metaterminal = get_builtin ("metaterminal"); metaterminal2 = get_builtin ("metaterminal2_"); nestaralt = get_builtin ("nestaralt_"); nestarset = get_builtin ("nestarset"); detnestarset = get_builtin ("detnestarset"); detprefix = get_builtin ("detprefix"); detprefix2 = get_builtin ("detprefix2_"); equalsempty = get_builtin ("equalsempty"); nlcr = get_builtin ("nlcr"); pair = get_builtin ("pair"); repair = get_builtin ("repair"); resetinputptr = get_builtin ("resetinputptr_"); restoreip = get_builtin ("restoreip_"); setinputptrto = get_builtin ("setinputptrto_"); skip = get_builtin ("skip_"); tltraditional = get_builtin ("tltraditional_"); tltraditionalterm = get_builtin ("tltraditionalterm_"); transformlattice = get_builtin ("transformlattice_"); transformlatticeterm = get_builtin ("transformlatticeterm_"); unpair = get_builtin ("unpair"); where = get_builtin ("where"); getlist_ = get_builtin ("getlist_"); add_to = get_builtin ("addto"); assign = get_builtin ("assign"); meta_empty = get_meta_builtin ("empty"); }
/* Returns the body of a P6bigint, containing the bigint/smallint union, for * operations that want to explicitly handle the two. */ static MVMP6bigintBody * get_bigint_body(MVMThreadContext *tc, MVMObject *obj) { if (IS_CONCRETE(obj)) return (MVMP6bigintBody *)REPR(obj)->box_funcs.get_boxed_ref(tc, STABLE(obj), obj, OBJECT_BODY(obj), MVM_REPR_ID_P6bigint); else MVM_exception_throw_adhoc(tc, "Can only perform big integer operations on concrete objects"); }
/* Adds a method into the KnowHOW.HOW method table. */ static void add_knowhow_how_method(MVMThreadContext *tc, MVMKnowHOWREPR *knowhow_how, char *name, void (*func) (MVMThreadContext *, MVMCallsite *, MVMRegister *)) { MVMObject *BOOTCCode, *code_obj, *method_table, *name_str; /* Create string for name. */ name_str = (MVMObject *)MVM_string_ascii_decode_nt(tc, tc->instance->VMString, name); /* Allocate a BOOTCCode and put pointer in. */ BOOTCCode = tc->instance->boot_types->BOOTCCode; code_obj = REPR(BOOTCCode)->allocate(tc, STABLE(BOOTCCode)); ((MVMCFunction *)code_obj)->body.func = func; /* Add into the table. */ method_table = knowhow_how->body.methods; REPR(method_table)->ass_funcs->bind_key_boxed(tc, STABLE(method_table), method_table, OBJECT_BODY(method_table), name_str, code_obj); }
static void verify_filehandle_type(MVMThreadContext *tc, MVMObject *oshandle, MVMOSHandle **handle, const char *msg) { /* work on only MVMOSHandle of type MVM_OSHANDLE_FILE */ if (REPR(oshandle)->ID != MVM_REPR_ID_MVMOSHandle) { MVM_exception_throw_adhoc(tc, "%s requires an object with REPR MVMOSHandle", msg); } *handle = (MVMOSHandle *)oshandle; if ((*handle)->body.handle_type != MVM_OSHANDLE_FILE) { MVM_exception_throw_adhoc(tc, "%s requires an MVMOSHandle of type file handle", msg); } }
/* This function gets shared with perl6.ops for the perl6_list_from_rpa op. */ PMC * Rakudo_binding_list_from_rpa(PARROT_INTERP, PMC *rpa, PMC *type, PMC *flattens) { PMC *list = REPR(type)->allocate(interp, STABLE(type)); PMC *List = Rakudo_types_list_get(); if (!PMC_IS_NULL(rpa)) VTABLE_set_attr_keyed(interp, list, List, NEXTITER_str, Rakudo_binding_iter_from_rpa(interp, rpa, list)); VTABLE_set_attr_keyed(interp, list, List, FLATTENS_str, flattens); return list; }
/* Creates a new timer. */ MVMObject * MVM_io_timer_create(MVMThreadContext *tc, MVMObject *queue, MVMObject *schedulee, MVMint64 timeout, MVMint64 repeat, MVMObject *async_type) { MVMAsyncTask *task; TimerInfo *timer_info; /* Validate REPRs. */ if (REPR(queue)->ID != MVM_REPR_ID_ConcBlockingQueue) MVM_exception_throw_adhoc(tc, "timer target queue must have ConcBlockingQueue REPR"); if (REPR(async_type)->ID != MVM_REPR_ID_MVMAsyncTask) MVM_exception_throw_adhoc(tc, "timer result type must have REPR AsyncTask"); /* Create async task handle. */ MVMROOT(tc, queue, { MVMROOT(tc, schedulee, { task = (MVMAsyncTask *)MVM_repr_alloc_init(tc, async_type); }); });
void MVM_coerce_smart_stringify(MVMThreadContext *tc, MVMObject *obj, MVMRegister *res_reg) { MVMObject *strmeth; /* Handle null case. */ if (!obj) { res_reg->s = tc->instance->str_consts->empty; return; } /* Check if there is a Str method. */ strmeth = MVM_6model_find_method_cache_only(tc, obj, tc->instance->str_consts->Str); if (strmeth) { /* We need to do the invocation; just set it up with our result reg as * the one for the call. */ MVMObject *code = MVM_frame_find_invokee(tc, strmeth); tc->cur_frame->return_value = res_reg; tc->cur_frame->return_type = MVM_RETURN_STR; tc->cur_frame->return_address = *(tc->interp_cur_op); tc->cur_frame->args[0].o = obj; STABLE(code)->invoke(tc, code, get_inv_callsite(), tc->cur_frame->args); return; } /* Otherwise, guess something appropriate. */ if (!IS_CONCRETE(obj)) res_reg->s = tc->instance->str_consts->empty; else { MVMStorageSpec ss = REPR(obj)->get_storage_spec(tc, STABLE(obj)); if (REPR(obj)->ID == MVM_REPR_ID_MVMString) res_reg->s = (MVMString *)obj; else if (ss.can_box & MVM_STORAGE_SPEC_CAN_BOX_STR) res_reg->s = REPR(obj)->box_funcs->get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj)); else if (ss.can_box & MVM_STORAGE_SPEC_CAN_BOX_INT) res_reg->s = MVM_coerce_i_s(tc, REPR(obj)->box_funcs->get_int(tc, STABLE(obj), obj, OBJECT_BODY(obj))); else if (ss.can_box & MVM_STORAGE_SPEC_CAN_BOX_NUM) res_reg->s = MVM_coerce_n_s(tc, REPR(obj)->box_funcs->get_num(tc, STABLE(obj), obj, OBJECT_BODY(obj))); else MVM_exception_throw_adhoc(tc, "cannot stringify this"); } }