Example #1
0
void MVM_6model_can_method(MVMThreadContext *tc, MVMObject *obj, MVMString *name, MVMRegister *res) {
    MVMObject *HOW, *find_method, *code;
    MVMCallsite *findmeth_callsite;

    MVMint64 can_cached = MVM_6model_can_method_cache_only(tc, obj, name);

    if (can_cached == 0 || can_cached == 1) {
        res->i64 = can_cached;
        return;
    }

    /* If no method in cache and the cache is not authoritative, need to make
     * a late-bound call to find_method. */
    HOW = MVM_6model_get_how(tc, STABLE(obj));
    find_method = MVM_6model_find_method_cache_only(tc, HOW,
        tc->instance->str_consts.find_method);
    if (MVM_is_null(tc, find_method)) {
        /* This'll count as a "no"... */
        res->i64 = 0;
        return;
    }

    /* Set up the call, using the result register as the target. A little bad
     * as we're really talking about     */
    code = MVM_frame_find_invokee(tc, find_method, NULL);
    findmeth_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_FIND_METHOD);
    MVM_args_setup_thunk(tc, res, MVM_RETURN_OBJ, findmeth_callsite);
    tc->cur_frame->special_return      = late_bound_can_return;
    tc->cur_frame->special_return_data = res;
    tc->cur_frame->args[0].o = HOW;
    tc->cur_frame->args[1].o = obj;
    tc->cur_frame->args[2].s = name;
    STABLE(code)->invoke(tc, code, findmeth_callsite, tc->cur_frame->args);
}
/* 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);
}
Example #3
0
/* Binds the given value to the specified attribute. */
static void bind_attribute_boxed(PARROT_INTERP, STable *st, void *data, PMC *class_handle, STRING *name, INTVAL hint, PMC *value) {
    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) {
        STable *st = repr_data->flattened_stables[slot];
        if (st) {
            if (value->vtable->base_type == smo_id && st == STABLE(value))
                st->REPR->copy_to(interp, st, OBJECT_BODY(value),
                    (char *)data + repr_data->attribute_offsets[slot]);
            else
                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
                    "Type mismatch when storing value to attribute '%Ss' on class '%Ss'",
                    name, VTABLE_get_string(interp, introspection_call(interp,
                        class_handle, STABLE(class_handle)->HOW,
                        Parrot_str_new_constant(interp, "name"), 0)));
        }
        else {
            set_pmc_at_offset(data, repr_data->attribute_offsets[slot], value);
        }
    }
    else {
        /* Otherwise, complain that the attribute doesn't exist. */
        no_such_attribute(interp, "bind", class_handle, name);
    }
}
Example #4
0
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));
        });
Example #5
0
static void code_pair_store_internal(MVMThreadContext *tc, MVMObject *cont, MVMRegister value, MVMCallsite *cs) {
    CodePairContData         *data = (CodePairContData *)STABLE(cont)->container_data;
    MVMObject                *code = MVM_frame_find_invokee(tc, data->store_code, NULL);
    MVM_args_setup_thunk(tc, NULL, MVM_RETURN_VOID, cs);
    tc->cur_frame->args[0].o       = cont;
    tc->cur_frame->args[1]         = value;
    STABLE(code)->invoke(tc, code, cs, tc->cur_frame->args);
}
Example #6
0
static void code_pair_fetch_internal(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res, MVMReturnType res_type) {
    CodePairContData        *data = (CodePairContData *)STABLE(cont)->container_data;
    MVMObject               *code = MVM_frame_find_invokee(tc, data->fetch_code, NULL);
    MVMCallsite *inv_arg_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_INV_ARG);
    MVM_args_setup_thunk(tc, res, res_type, inv_arg_callsite);
    tc->cur_frame->args[0].o      = cont;
    STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
}
Example #7
0
static void rakudo_scalar_store(MVMThreadContext *tc, MVMObject *cont, MVMObject *value) {
    RakudoContData *data = (RakudoContData *)STABLE(cont)->container_data;
    MVMObject *code = MVM_frame_find_invokee(tc, data->store, NULL);
    MVMCallsite *cs = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_TWO_OBJ);
    MVM_args_setup_thunk(tc, NULL, MVM_RETURN_VOID, cs);
    tc->cur_frame->args[0].o = cont;
    tc->cur_frame->args[1].o = value;
    STABLE(code)->invoke(tc, code, cs, tc->cur_frame->args);
}
/* 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);
}
Example #9
0
static void code_pair_fetch(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
    CodePairContData      *data   = (CodePairContData *)STABLE(cont)->container_data;
    MVMObject             *code   = MVM_frame_find_invokee(tc, data->fetch_code, NULL);

    MVM_args_setup_thunk(tc, res, MVM_RETURN_OBJ, &fetch_arg_callsite);
    tc->cur_frame->args[0].o      = cont;

    STABLE(code)->invoke(tc, code, &fetch_arg_callsite, tc->cur_frame->args);
}
Example #10
0
/* Determines if there's a matching spesh candidate for a callee and a given
 * set of argument info. */
static MVMint32 try_find_spesh_candidate(MVMThreadContext *tc, MVMCode *code, MVMSpeshCallInfo *arg_info) {
    MVMStaticFrameBody *sfb = &(code->body.sf->body);
    MVMint32 num_spesh      = sfb->num_spesh_candidates;
    MVMint32 i, j;
    for (i = 0; i < num_spesh; i++) {
        MVMSpeshCandidate *cand = &sfb->spesh_candidates[i];
        if (cand->cs == arg_info->cs) {
            /* Matching callsite, now see if we have enough information to
             * test the guards. */
            MVMint32 guard_failed = 0;
            for (j = 0; j < cand->num_guards; j++) {
                MVMint32       slot    = cand->guards[j].slot;
                MVMSpeshFacts *facts   = slot < MAX_ARGS_FOR_OPT ? arg_info->arg_facts[slot] : NULL;
                MVMSTable     *want_st = (MVMSTable *)cand->guards[j].match;
                if (!facts) {
                    guard_failed = 1;
                    break;
                }
                switch (cand->guards[j].kind) {
                case MVM_SPESH_GUARD_CONC:
                    if (!(facts->flags & MVM_SPESH_FACT_CONCRETE) ||
                            !(facts->flags & MVM_SPESH_FACT_KNOWN_TYPE) ||
                            STABLE(facts->type) != want_st)
                        guard_failed = 1;
                    break;
                case MVM_SPESH_GUARD_TYPE:
                    if (!(facts->flags & MVM_SPESH_FACT_TYPEOBJ) ||
                            !(facts->flags & MVM_SPESH_FACT_KNOWN_TYPE) ||
                            STABLE(facts->type) != want_st)
                        guard_failed = 1;
                    break;
                case MVM_SPESH_GUARD_DC_CONC:
                    if (!(facts->flags & MVM_SPESH_FACT_DECONT_CONCRETE) ||
                            !(facts->flags & MVM_SPESH_FACT_KNOWN_DECONT_TYPE) ||
                            STABLE(facts->decont_type) != want_st)
                        guard_failed = 1;
                    break;
                case MVM_SPESH_GUARD_DC_TYPE:
                    if (!(facts->flags & MVM_SPESH_FACT_DECONT_TYPEOBJ) ||
                            !(facts->flags & MVM_SPESH_FACT_KNOWN_DECONT_TYPE) ||
                            STABLE(facts->decont_type) != want_st)
                        guard_failed = 1;
                    break;
                default:
                    guard_failed = 1;
                    break;
                }
                if (guard_failed)
                    break;
            }
            if (!guard_failed)
                return i;
        }
    }
    return -1;
}
Example #11
0
/* Sets up a very simple attribute meta-object. Just supports having a
 * name, and even uses the P6str representation to store it, so that's
 * really all that it supports. */
PMC * SixModelObject_setup_knowhow_attribute(PARROT_INTERP, PMC *sc, PMC *knowhow) {
    PMC *old_ctx, *cappy, *meth, *knowhow_attr, *how;
    
    /* Create a new KnowHOWAttribute type using P6str repr.. */
    meth = STABLE(knowhow)->find_method(interp, knowhow,
        Parrot_str_new_constant(interp, "new_type"), NO_HINT);
    old_ctx = Parrot_pcc_get_signature(interp, CURRENT_CONTEXT(interp));
    cappy   = Parrot_pmc_new(interp, enum_class_CallContext);
    VTABLE_push_pmc(interp, cappy, knowhow);
    VTABLE_set_string_keyed_str(interp, cappy, name_str,
        Parrot_str_new_constant(interp, "KnowHOWAttribute"));
    VTABLE_set_string_keyed_str(interp, cappy, repr_str,
        Parrot_str_new_constant(interp, "P6str"));
    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);
    knowhow_attr = VTABLE_get_pmc_keyed_int(interp, cappy, 0);
    how = STABLE(knowhow_attr)->HOW;
    
    /* Add new method. */
    meth = STABLE(how)->find_method(interp, how,
        Parrot_str_new_constant(interp, "add_method"), NO_HINT);
    cappy   = Parrot_pmc_new(interp, enum_class_CallContext);
    VTABLE_push_pmc(interp, cappy, how);
    VTABLE_push_pmc(interp, cappy, knowhow_attr);
    VTABLE_push_string(interp, cappy, Parrot_str_new_constant(interp, "new"));
    VTABLE_push_pmc(interp, cappy, wrap_c(interp, F2DPTR(attr_new)));
    Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
    Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
    
    /* Add name method. */
    cappy   = Parrot_pmc_new(interp, enum_class_CallContext);
    VTABLE_push_pmc(interp, cappy, how);
    VTABLE_push_pmc(interp, cappy, knowhow_attr);
    VTABLE_push_string(interp, cappy, name_str);
    VTABLE_push_pmc(interp, cappy, wrap_c(interp, F2DPTR(attr_name)));
    Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
    Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
    
    /* Compose. */
    meth = STABLE(knowhow)->find_method(interp, how,
        Parrot_str_new_constant(interp, "compose"), NO_HINT);
    cappy   = Parrot_pmc_new(interp, enum_class_CallContext);
    VTABLE_push_pmc(interp, cappy, how);
    VTABLE_push_pmc(interp, cappy, knowhow_attr);
    Parrot_pcc_invoke_from_sig_object(interp, meth, cappy);
    Parrot_pcc_set_signature(interp, CURRENT_CONTEXT(interp), old_ctx);
    
    /* Associate the created object with the intial core serialization
     * context. */
    VTABLE_set_pmc_keyed_int(interp, sc, 2, knowhow_attr);
    SC_PMC(knowhow_attr) = sc;
    STABLE(knowhow_attr)->sc = sc;
    
    return knowhow_attr;
}
Example #12
0
static void code_pair_store(MVMThreadContext *tc, MVMObject *cont, MVMObject *obj) {
    CodePairContData      *data   = (CodePairContData *)STABLE(cont)->container_data;
    MVMObject             *code   = MVM_frame_find_invokee(tc, data->store_code, NULL);

    MVM_args_setup_thunk(tc, NULL, MVM_RETURN_VOID, &store_arg_callsite);
    tc->cur_frame->args[0].o      = cont;
    tc->cur_frame->args[1].o      = obj;

    STABLE(code)->invoke(tc, code, &store_arg_callsite, tc->cur_frame->args);
}
Example #13
0
/* 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");
    }
}
Example #14
0
static void code_pair_fetch(MVMThreadContext *tc, MVMObject *cont, MVMRegister *res) {
    CodePairContData      *data   = (CodePairContData *)STABLE(cont)->container_data;
    MVMObject             *code   = MVM_frame_find_invokee(tc, data->fetch_code);

    tc->cur_frame->return_value   = res;
    tc->cur_frame->return_type    = MVM_RETURN_OBJ;
    tc->cur_frame->return_address = *(tc->interp_cur_op);
    tc->cur_frame->args[0].o      = cont;

    STABLE(code)->invoke(tc, code, &fetch_arg_callsite, tc->cur_frame->args);
}
Example #15
0
/* Bootstraps the KnowHOW type. */
static void bootstrap_KnowHOW(MVMThreadContext *tc) {
    MVMObject *VMString  = tc->instance->VMString;
    MVMObject *BOOTArray = tc->instance->boot_types->BOOTArray;
    MVMObject *BOOTHash  = tc->instance->boot_types->BOOTHash;
    
    /* Create our KnowHOW type object. Note we don't have a HOW just yet, so
     * pass in NULL. */
    MVMREPROps *REPR    = MVM_repr_get_by_id(tc, MVM_REPR_ID_KnowHOWREPR);
    MVMObject  *knowhow = REPR->type_object_for(tc, NULL);

    /* We create a KnowHOW instance that can describe itself. This means
     * (once we tie the knot) that .HOW.HOW.HOW.HOW etc will always return
     * that, which closes the model up. Note that the STable for it must
     * be allocated first, since that holds the allocation size. */
    MVMKnowHOWREPR *knowhow_how;
    MVMSTable *st = MVM_gc_allocate_stable(tc, REPR, NULL);
    st->WHAT      = (MVMObject *)knowhow;
    st->size      = sizeof(MVMKnowHOWREPR);
    knowhow_how   = (MVMKnowHOWREPR *)REPR->allocate(tc, st);
    st->HOW       = (MVMObject *)knowhow_how;
    knowhow_how->common.st = st;
    
    /* Add various methods to the KnowHOW's HOW. */
    REPR->initialize(tc, NULL, (MVMObject *)knowhow_how, &knowhow_how->body);
    add_knowhow_how_method(tc, knowhow_how, "new_type", new_type);
    add_knowhow_how_method(tc, knowhow_how, "add_method", add_method);
    add_knowhow_how_method(tc, knowhow_how, "add_attribute", add_attribute);
    add_knowhow_how_method(tc, knowhow_how, "compose", compose);
    add_knowhow_how_method(tc, knowhow_how, "attributes", attributes);
    add_knowhow_how_method(tc, knowhow_how, "methods", methods);
    add_knowhow_how_method(tc, knowhow_how, "name", name);
    
    /* Set name KnowHOW for the KnowHOW's HOW. */
    knowhow_how->body.name = MVM_string_ascii_decode_nt(tc, VMString, "KnowHOW");

    /* Set this built up HOW as the KnowHOW's HOW. */
    STABLE(knowhow)->HOW = (MVMObject *)knowhow_how;
    
    /* Give it an authoritative method cache; this in turn will make the
     * method dispatch bottom out. */
    STABLE(knowhow)->method_cache = knowhow_how->body.methods;
    STABLE(knowhow)->mode_flags   = MVM_METHOD_CACHE_AUTHORITATIVE;
    STABLE(knowhow_how)->method_cache = knowhow_how->body.methods;
    STABLE(knowhow_how)->mode_flags   = MVM_METHOD_CACHE_AUTHORITATIVE;
    
    /* Associate the created objects with the initial core serialization
     * context. */
    /* XXX TODO */

    /* Stash the created KnowHOW. */
    tc->instance->KnowHOW = (MVMObject *)knowhow;
    MVM_gc_root_add_permanent(tc, (MVMCollectable **)&tc->instance->KnowHOW);
}
Example #16
0
static void code_pair_store(MVMThreadContext *tc, MVMObject *cont, MVMObject *obj) {
    CodePairContData      *data   = (CodePairContData *)STABLE(cont)->container_data;
    MVMObject             *code   = MVM_frame_find_invokee(tc, data->store_code);

    tc->cur_frame->return_value   = NULL;
    tc->cur_frame->return_type    = MVM_RETURN_VOID;
    tc->cur_frame->return_address = *(tc->interp_cur_op);
    tc->cur_frame->args[0].o      = cont;
    tc->cur_frame->args[1].o      = obj;

    STABLE(code)->invoke(tc, code, &store_arg_callsite, tc->cur_frame->args);
}
Example #17
0
/* Locates a method by name. Returns the method if it exists, or throws an
 * exception if it can not be found. */
void MVM_6model_find_method(MVMThreadContext *tc, MVMObject *obj, MVMString *name, MVMRegister *res) {
    MVMObject *cache, *HOW, *find_method, *code;

    if (MVM_is_null(tc, obj))
        MVM_exception_throw_adhoc(tc,
            "Cannot call method '%s' on a null object",
             MVM_string_utf8_encode_C_string(tc, name));

    /* First try to find it in the cache. If we find it, we have a result.
     * If we don't find it, but the cache is authoritative, then error. */
    cache = STABLE(obj)->method_cache;
    if (cache && IS_CONCRETE(cache)) {
        MVMObject *meth = MVM_repr_at_key_o(tc, cache, name);
        if (!MVM_is_null(tc, meth)) {
            res->o = meth;
            return;
        }
        if (STABLE(obj)->mode_flags & MVM_METHOD_CACHE_AUTHORITATIVE) {
            MVMObject *handler = MVM_hll_current(tc)->method_not_found_error;
            if (!MVM_is_null(tc, handler)) {
                handler = MVM_frame_find_invokee(tc, handler, NULL);
                MVM_args_setup_thunk(tc, NULL, MVM_RETURN_VOID, &mnfe_callsite);
                tc->cur_frame->args[0].o = obj;
                tc->cur_frame->args[1].s = name;
                STABLE(handler)->invoke(tc, handler, &mnfe_callsite, tc->cur_frame->args);
                return;
            }
            else {
                MVM_exception_throw_adhoc(tc,
                    "Cannot find method '%s'",
                    MVM_string_utf8_encode_C_string(tc, name));
            }
        }
    }

    /* Otherwise, need to call the find_method method. We make the assumption
     * that the invocant's meta-object's type is composed. */
    HOW = STABLE(obj)->HOW;
    find_method = MVM_6model_find_method_cache_only(tc, HOW,
        tc->instance->str_consts.find_method);
    if (MVM_is_null(tc, find_method))
        MVM_exception_throw_adhoc(tc,
            "Cannot find method '%s': no method cache and no .^find_method",
             MVM_string_utf8_encode_C_string(tc, name));

    /* Set up the call, using the result register as the target. */
    code = MVM_frame_find_invokee(tc, find_method, NULL);
    MVM_args_setup_thunk(tc, res, MVM_RETURN_OBJ, &fm_callsite);
    tc->cur_frame->args[0].o = HOW;
    tc->cur_frame->args[1].o = obj;
    tc->cur_frame->args[2].s = name;
    STABLE(code)->invoke(tc, code, &fm_callsite, tc->cur_frame->args);
}
Example #18
0
/* Composes the meta-object. */
static void compose(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);
    PMC    *obj     = VTABLE_get_pmc_keyed_int(interp, capture, 1);
    STABLE(obj)->method_cache            = ((KnowHOWREPRInstance *)PMC_data(self))->body.methods;
    STABLE(obj)->mode_flags              = METHOD_CACHE_AUTHORITATIVE;
    STABLE(obj)->type_check_cache_length = 1;
    STABLE(obj)->type_check_cache        = (PMC **)mem_sys_allocate(sizeof(PMC *));
    STABLE(obj)->type_check_cache[0]     = obj;
    unused = Parrot_pcc_build_call_from_c_args(interp, capture, "P", obj);
}
Example #19
0
void MVM_6model_find_method(MVMThreadContext *tc, MVMObject *obj, MVMString *name, MVMRegister *res) {
    MVMObject *cache, *HOW, *find_method, *code;
    MVMCallsite *findmeth_callsite;

    if (MVM_is_null(tc, obj))
        MVM_exception_throw_adhoc(tc,
            "Cannot call method '%s' on a null object",
             MVM_string_utf8_encode_C_string(tc, name));

    /* First try to find it in the cache. If we find it, we have a result.
     * If we don't find it, but the cache is authoritative, then error. */
    cache = get_method_cache(tc, STABLE(obj));
    if (cache && IS_CONCRETE(cache)) {
        MVMObject *meth = MVM_repr_at_key_o(tc, cache, name);
        if (!MVM_is_null(tc, meth)) {
            res->o = meth;
            return;
        }
        if (STABLE(obj)->mode_flags & MVM_METHOD_CACHE_AUTHORITATIVE) {
            die_over_missing_method(tc, obj, name);
            return;
        }
    }

    /* Otherwise, need to call the find_method method. We make the assumption
     * that the invocant's meta-object's type is composed. */
    HOW = MVM_6model_get_how(tc, STABLE(obj));
    find_method = MVM_6model_find_method_cache_only(tc, HOW,
        tc->instance->str_consts.find_method);
    if (MVM_is_null(tc, find_method))
        MVM_exception_throw_adhoc(tc,
            "Cannot find method '%s': no method cache and no .^find_method",
             MVM_string_utf8_encode_C_string(tc, name));

    /* Set up the call, using the result register as the target. */
    code = MVM_frame_find_invokee(tc, find_method, NULL);
    findmeth_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_FIND_METHOD);
    MVM_args_setup_thunk(tc, res, MVM_RETURN_OBJ, findmeth_callsite);
    {
        FindMethodSRData *fm = MVM_malloc(sizeof(FindMethodSRData));
        fm->obj  = obj;
        fm->name = name;
        fm->res  = res;
        tc->cur_frame->special_return           = late_bound_find_method_return;
        tc->cur_frame->special_return_data      = fm;
        tc->cur_frame->mark_special_return_data = mark_find_method_sr_data;
    }
    tc->cur_frame->args[0].o = HOW;
    tc->cur_frame->args[1].o = obj;
    tc->cur_frame->args[2].s = name;
    STABLE(code)->invoke(tc, code, findmeth_callsite, tc->cur_frame->args);
}
Example #20
0
/* Checks if an object has a given type, using the cache only. */
MVMint64 MVM_6model_istype_cache_only(MVMThreadContext *tc, MVMObject *obj, MVMObject *type) {
    if (!MVM_is_null(tc, obj)) {
        MVMuint16 i, elems = STABLE(obj)->type_check_cache_length;
        MVMObject  **cache = STABLE(obj)->type_check_cache;
        if (cache)
            for (i = 0; i < elems; i++) {
                if (cache[i] == type)
                    return 1;
            }
    }

    return 0;
}
Example #21
0
/* 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);
}
Example #22
0
/* Takes a stub object that existed before we had bootstrapped things and
 * gives it a meta-object. */
static void add_meta_object(MVMThreadContext *tc, MVMObject *type_obj, char *name) {
    MVMObject *meta_obj;
    MVMString *name_str;
    
    /* Create meta-object. */
    meta_obj = MVM_repr_alloc_init(tc, STABLE(tc->instance->KnowHOW)->HOW);
    MVMROOT(tc, meta_obj, {
        /* Put it in place. */
        MVM_ASSIGN_REF(tc, STABLE(type_obj), STABLE(type_obj)->HOW, meta_obj);
        
        /* Set name. */
        name_str = MVM_string_ascii_decode_nt(tc, tc->instance->VMString, name);
        MVM_ASSIGN_REF(tc, meta_obj, ((MVMKnowHOWREPR *)meta_obj)->body.name, name_str);
    });
Example #23
0
/* 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;
        }
    }
Example #24
0
MVMObject * Kiji_bootstrap_Pair(MVMCompUnit* cu, MVMThreadContext*tc) {
  MVMObject * type = MVM_6model_find_method(
    tc,
    STABLE(tc->instance->KnowHOW)->HOW,
    MVM_string_ascii_decode_nt(tc, tc->instance->VMString, (char*)"new_type")
  );
  MVMObject * how = STABLE(type)->HOW;

  CLASS_INIT();
  /* CLASS_ADD_METHOD("elems",   Hash_elems); */
  CLASS_REGISTER(type);

  return type;
}
Example #25
0
/* 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);
}
Example #26
0
/* Helper for finding a slot number. */
static INTVAL try_get_slot(PARROT_INTERP, P6opaqueREPRData *repr_data, PMC *class_key, STRING *name) {
    INTVAL slot = -1;
    if (repr_data->name_to_index_mapping) {
        P6opaqueNameMap *cur_map_entry = repr_data->name_to_index_mapping;
        while (cur_map_entry->class_key != NULL) {
            if (cur_map_entry->class_key == class_key) {
                if (!PMC_IS_NULL(cur_map_entry->name_map)) {
                    PMC *slot_pmc = VTABLE_get_pmc_keyed_str(interp, cur_map_entry->name_map, name);
                    if (!PMC_IS_NULL(slot_pmc))
                        slot = VTABLE_get_integer(interp, slot_pmc);
                    break;
                }
                else {
                    Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_INVALID_OPERATION,
                        "Null attribute map for P6opaque in class '%Ss'",
                        VTABLE_get_string(interp, introspection_call(interp,
                            class_key, STABLE(class_key)->HOW,
                            Parrot_str_new_constant(interp, "name"), 0)));
                }
            }
            cur_map_entry++;
        }
    }
    return slot;
}
Example #27
0
/* 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);
}
Example #28
0
MVMint32 MVM_6model_find_method_spesh(MVMThreadContext *tc, MVMObject *obj, MVMString *name,
                                      MVMint32 ss_idx, MVMRegister *res) {
    /* Missed mono-morph; try cache-only lookup. */
    MVMObject *meth = MVM_6model_find_method_cache_only(tc, obj, name);
    if (!MVM_is_null(tc, meth)) {
        /* Got it; cache. Must be careful due to threads
         * reading, races, etc. */
        MVMStaticFrame *sf = tc->cur_frame->static_info;
        uv_mutex_lock(&tc->instance->mutex_spesh_install);
        if (!tc->cur_frame->effective_spesh_slots[ss_idx + 1]) {
            MVM_ASSIGN_REF(tc, &(sf->common.header),
                           tc->cur_frame->effective_spesh_slots[ss_idx + 1],
                           (MVMCollectable *)meth);
            MVM_barrier();
            MVM_ASSIGN_REF(tc, &(sf->common.header),
                           tc->cur_frame->effective_spesh_slots[ss_idx],
                           (MVMCollectable *)STABLE(obj));
        }
        uv_mutex_unlock(&tc->instance->mutex_spesh_install);
        res->o = meth;
        return 0;
    }
    else {
        /* Fully late-bound. */
        MVM_6model_find_method(tc, obj, name, res);
        return 1;
    }
}
Example #29
0
/* 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;
}
Example #30
0
File: CStr.c Project: Arcterus/nqp
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);
}