예제 #1
0
MVMint64 MVM_proc_shell(MVMThreadContext *tc, MVMString *cmd, MVMString *cwd, MVMObject *env) {
    MVMint64 result = 0, spawn_result = 0;
    uv_process_t *process = calloc(1, sizeof(uv_process_t));
    uv_process_options_t process_options = {0};
    uv_stdio_container_t process_stdio[3];
    int i;

    char * const cmdin = MVM_string_utf8_encode_C_string(tc, cmd);
    char * const _cwd = MVM_string_utf8_encode_C_string(tc, cwd);
    const MVMuint64 size = MVM_repr_elems(tc, env);
    MVMIter * const iter = (MVMIter *)MVM_iter(tc, env);
    char **_env = malloc((size + 1) * sizeof(char *));

#ifdef _WIN32
    const MVMuint16 acp = GetACP(); /* We should get ACP at runtime. */
    char * const _cmd = ANSIToUTF8(acp, getenv("ComSpec"));
    char *args[3];
    args[0] = "/c";
    {
        MVMint64 len = strlen(cmdin);
        MVMint64 i;
        for (i = 0; i < len; i++)
            if (cmdin[i] == '/')
                cmdin[i] = '\\';
    }
    args[1] = cmdin;
    args[2] = NULL;
#else
    char * const _cmd = "/bin/sh";
    char *args[4];
    args[0] = "/bin/sh";
    args[1] = "-c";
    args[2] = cmdin;
    args[3] = NULL;
#endif

    INIT_ENV();
    SPAWN(_cmd);
    FREE_ENV();

    free(_cwd);

#ifdef _WIN32
    free(_cmd);
#endif

    free(cmdin);
    return result;
}
예제 #2
0
MVMint64 MVM_proc_spawn(MVMThreadContext *tc, MVMObject *argv, MVMString *cwd, MVMObject *env) {
    MVMint64 result = 0, spawn_result = 0;
    uv_process_t *process = calloc(1, sizeof(uv_process_t));
    uv_process_options_t process_options = {0};
    uv_stdio_container_t process_stdio[3];
    int i;

    char   * const      _cwd = MVM_string_utf8_encode_C_string(tc, cwd);
    const MVMuint64     size = MVM_repr_elems(tc, env);
    MVMIter * const     iter = (MVMIter *)MVM_iter(tc, env);
    char              **_env = malloc((size + 1) * sizeof(char *));
    const MVMuint64  arg_size = MVM_repr_elems(tc, argv);
    char             **args = malloc((arg_size + 1) * sizeof(char *));
    MVMRegister        reg;

    i = 0;
    while(i < arg_size) {
        REPR(argv)->pos_funcs.at_pos(tc, STABLE(argv), argv, OBJECT_BODY(argv), i, &reg, MVM_reg_obj);
        args[i++] = MVM_string_utf8_encode_C_string(tc, MVM_repr_get_str(tc, reg.o));
    }
    args[arg_size] = NULL;

    INIT_ENV();
    SPAWN(arg_size ? args[0] : NULL);
    FREE_ENV();

    free(_cwd);

    i = 0;
    while(args[i])
        free(args[i++]);

    free(args);

    return result;
}
예제 #3
0
MVMint64 MVM_proc_spawn(MVMThreadContext *tc, MVMString *cmd, MVMString *cwd, MVMObject *env) {
    MVMint64 result, spawn_result;
    uv_process_t process = {0};
    uv_process_options_t process_options = {0};
    int i;

    char   * const     cmdin = MVM_string_utf8_encode_C_string(tc, cmd);
    char   * const      _cwd = MVM_string_utf8_encode_C_string(tc, cwd);
    const MVMuint64     size = MVM_repr_elems(tc, env);
    MVMIter * const     iter = (MVMIter *)MVM_iter(tc, env);
    char              **_env = malloc((size + 1) * sizeof(char *));

#ifdef _WIN32
    const MVMuint16      acp = GetACP(); /* We should get ACP at runtime. */
    char    * const     _cmd = ANSIToUTF8(acp, getenv("ComSpec"));
    char   *args[3];
    args[0] = "/c";
    args[1] = cmdin;
    args[2] = NULL;
#else
    char * const _cmd = "/bin/sh";
    char   *args[4];
    args[0] = "/bin/sh";
    args[1] = "-c";
    args[2] = cmdin;
    args[3] = NULL;
#endif

    MVMROOT(tc, iter, {
        MVMString * const equal = MVM_string_ascii_decode(tc, tc->instance->VMString, STR_WITH_LEN("="));
        MVMROOT(tc, equal, {
            MVMString *env_str;
            i = 0;
            while(MVM_iter_istrue(tc, iter)) {
                MVM_repr_shift_o(tc, (MVMObject *)iter);
                env_str = MVM_string_concatenate(tc, MVM_iterkey_s(tc, iter), equal);
                env_str = MVM_string_concatenate(tc, env_str, MVM_repr_get_str(tc, MVM_iterval(tc, iter)));
                _env[i++] = MVM_string_utf8_encode_C_string(tc, env_str);
            }
            _env[size] = NULL;
        });
    });
예제 #4
0
파일: procops.c 프로젝트: baby-gnu/MoarVM
MVMint64 MVM_proc_shell(MVMThreadContext *tc, MVMString *cmd, MVMString *cwd, MVMObject *env,
        MVMObject *in, MVMObject *out, MVMObject *err, MVMint64 flags) {
    MVMint64 result = 0, spawn_result;
    uv_process_t *process = MVM_calloc(1, sizeof(uv_process_t));
    uv_process_options_t process_options = {0};
    uv_stdio_container_t process_stdio[3];
    int i, process_still_running;

    char * const cmdin = MVM_string_utf8_c8_encode_C_string(tc, cmd);
    char * const _cwd = MVM_string_utf8_c8_encode_C_string(tc, cwd);
    const MVMuint64 size = MVM_repr_elems(tc, env);
    char **_env = MVM_malloc((size + 1) * sizeof(char *));
    MVMIter *iter;

#ifdef _WIN32
    const MVMuint16 acp = GetACP(); /* We should get ACP at runtime. */
    char * const _cmd = ANSIToUTF8(acp, getenv("ComSpec"));
    char *args[3];
    args[0] = "/c";
    args[1] = cmdin;
    args[2] = NULL;
#else
    char * const _cmd = "/bin/sh";
    char *args[4];
    args[0] = "/bin/sh";
    args[1] = "-c";
    args[2] = cmdin;
    args[3] = NULL;
#endif

    MVMROOT(tc, in, {
    MVMROOT(tc, out, {
    MVMROOT(tc, err, {
        iter = (MVMIter *)MVM_iter(tc, env);
        INIT_ENV();
    });
    });
예제 #5
0
파일: coerce.c 프로젝트: niner/MoarVM
void MVM_coerce_istrue(MVMThreadContext *tc, MVMObject *obj, MVMRegister *res_reg,
        MVMuint8 *true_addr, MVMuint8 *false_addr, MVMuint8 flip) {
    MVMint64 result = 0;
    if (!MVM_is_null(tc, obj)) {
        MVMBoolificationSpec *bs = obj->st->boolification_spec;
        switch (bs == NULL ? MVM_BOOL_MODE_NOT_TYPE_OBJECT : bs->mode) {
            case MVM_BOOL_MODE_CALL_METHOD: {
                MVMObject *code = MVM_frame_find_invokee(tc, bs->method, NULL);
                MVMCallsite *inv_arg_callsite = MVM_callsite_get_common(tc, MVM_CALLSITE_ID_INV_ARG);
                if (res_reg) {
                    /* We need to do the invocation, and set this register
                     * the result. Then we just do the call. For the flip
                     * case, just set up special return handler to flip
                     * the register. */
                    MVM_args_setup_thunk(tc, res_reg, MVM_RETURN_INT, inv_arg_callsite);
                    tc->cur_frame->args[0].o = obj;
                    if (flip) {
                        tc->cur_frame->special_return      = flip_return;
                        tc->cur_frame->special_return_data = res_reg;
                    }
                    STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
                }
                else {
                    /* Need to set up special return hook. */
                    BoolMethReturnData *data = MVM_malloc(sizeof(BoolMethReturnData));
                    data->true_addr  = true_addr;
                    data->false_addr = false_addr;
                    data->flip       = flip;
                    tc->cur_frame->special_return      = boolify_return;
                    tc->cur_frame->special_return_data = data;
                    MVM_args_setup_thunk(tc, &data->res_reg, MVM_RETURN_INT, inv_arg_callsite);
                    tc->cur_frame->args[0].o = obj;
                    STABLE(code)->invoke(tc, code, inv_arg_callsite, tc->cur_frame->args);
                }
                return;
            }
            case MVM_BOOL_MODE_UNBOX_INT:
                result = !IS_CONCRETE(obj) || REPR(obj)->box_funcs.get_int(tc, STABLE(obj), obj, OBJECT_BODY(obj)) == 0 ? 0 : 1;
                break;
            case MVM_BOOL_MODE_UNBOX_NUM:
                result = !IS_CONCRETE(obj) || REPR(obj)->box_funcs.get_num(tc, STABLE(obj), obj, OBJECT_BODY(obj)) == 0.0 ? 0 : 1;
                break;
            case MVM_BOOL_MODE_UNBOX_STR_NOT_EMPTY: {
                MVMString *str;
                if (!IS_CONCRETE(obj)) {
                    result = 0;
                    break;
                }
                str = REPR(obj)->box_funcs.get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj));
                result = MVM_coerce_istrue_s(tc, str);
                break;
            }
            case MVM_BOOL_MODE_UNBOX_STR_NOT_EMPTY_OR_ZERO: {
                MVMString *str;
                MVMint64 chars;
                if (!IS_CONCRETE(obj)) {
                    result = 0;
                    break;
                }
                str = REPR(obj)->box_funcs.get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj));

                if (str == NULL || !IS_CONCRETE(str)) {
                    result = 0;
                    break;
                }

                chars = MVM_string_graphs(tc, str);

                result = chars == 0 ||
                        (chars == 1 && MVM_string_get_grapheme_at_nocheck(tc, str, 0) == 48)
                        ? 0 : 1;
                break;
            }
            case MVM_BOOL_MODE_NOT_TYPE_OBJECT:
                result = !IS_CONCRETE(obj) ? 0 : 1;
                break;
            case MVM_BOOL_MODE_BIGINT:
                result = IS_CONCRETE(obj) ? MVM_bigint_bool(tc, obj) : 0;
                break;
            case MVM_BOOL_MODE_ITER:
                result = IS_CONCRETE(obj) ? MVM_iter_istrue(tc, (MVMIter *)obj) : 0;
                break;
            case MVM_BOOL_MODE_HAS_ELEMS:
                result = IS_CONCRETE(obj) ? MVM_repr_elems(tc, obj) != 0 : 0;
                break;
            default:
                MVM_exception_throw_adhoc(tc, "Invalid boolification spec mode used");
        }
    }

    if (flip)
        result = result ? 0 : 1;

    if (res_reg) {
        res_reg->i64 = result;
    }
    else {
        if (result)
            *(tc->interp_cur_op) = true_addr;
        else
            *(tc->interp_cur_op) = false_addr;
    }
}
예제 #6
0
/* 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 MVMObject * index_mapping_and_flat_list(MVMThreadContext *tc, MVMObject *mro, MVMCPPStructREPRData *repr_data) {
    MVMInstance *instance  = tc->instance;
    MVMObject *flat_list, *class_list, *attr_map_list;
    MVMint32  num_classes, i, current_slot = 0;
    MVMCPPStructNameMap *result;

    MVMint32 mro_idx = MVM_repr_elems(tc, mro);

    MVM_gc_root_temp_push(tc, (MVMCollectable **)&mro);

    flat_list = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_array_type);
    MVM_gc_root_temp_push(tc, (MVMCollectable **)&flat_list);

    class_list = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_array_type);
    MVM_gc_root_temp_push(tc, (MVMCollectable **)&class_list);

    attr_map_list = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_array_type);
    MVM_gc_root_temp_push(tc, (MVMCollectable **)&attr_map_list);

    /* Walk through the parents list. */
    while (mro_idx)
    {
        /* Get current class in MRO. */
        MVMObject *type_info     = MVM_repr_at_pos_o(tc, mro, --mro_idx);
        MVMObject *current_class = MVM_repr_at_pos_o(tc, type_info, 0);

        /* Get its local parents; make sure we're not doing MI. */
        MVMObject *parents     = MVM_repr_at_pos_o(tc, type_info, 2);
        MVMint32  num_parents = MVM_repr_elems(tc, parents);
        if (num_parents <= 1) {
            /* Get attributes and iterate over them. */
            MVMObject *attributes     = MVM_repr_at_pos_o(tc, type_info, 1);
            MVMIter * const attr_iter = (MVMIter *)MVM_iter(tc, attributes);
            MVMObject *attr_map = NULL;

            if (MVM_iter_istrue(tc, attr_iter)) {
                MVM_gc_root_temp_push(tc, (MVMCollectable **)&attr_iter);
                attr_map = MVM_repr_alloc_init(tc, MVM_hll_current(tc)->slurpy_hash_type);
                MVM_gc_root_temp_push(tc, (MVMCollectable **)&attr_map);
            }

            while (MVM_iter_istrue(tc, attr_iter)) {
                MVMObject *current_slot_obj = MVM_repr_box_int(tc, MVM_hll_current(tc)->int_box_type, current_slot);
                MVMObject *attr, *name_obj;
                MVMString *name;

                MVM_repr_shift_o(tc, (MVMObject *)attr_iter);

                /* Get attribute. */
                attr = MVM_iterval(tc, attr_iter);

                /* Get its name. */
                name_obj = MVM_repr_at_key_o(tc, attr, instance->str_consts.name);
                name     = MVM_repr_get_str(tc, name_obj);

                MVM_repr_bind_key_o(tc, attr_map, name, current_slot_obj);

                current_slot++;

                /* Push attr onto the flat list. */
                MVM_repr_push_o(tc, flat_list, attr);
            }

            if (attr_map) {
                MVM_gc_root_temp_pop_n(tc, 2);
            }

            /* Add to class list and map list. */
            MVM_repr_push_o(tc, class_list, current_class);
            MVM_repr_push_o(tc, attr_map_list, attr_map);
        }
        else {
            MVM_exception_throw_adhoc(tc,
                "CPPStruct representation does not support multiple inheritance");
        }
    }

    MVM_gc_root_temp_pop_n(tc, 4);

    /* We can now form the name map. */
    num_classes = MVM_repr_elems(tc, class_list);
    result = (MVMCPPStructNameMap *) MVM_malloc(sizeof(MVMCPPStructNameMap) * (1 + num_classes));

    for (i = 0; i < num_classes; i++) {
        result[i].class_key = MVM_repr_at_pos_o(tc, class_list, i);
        result[i].name_map  = MVM_repr_at_pos_o(tc, attr_map_list, i);
    }

    /* set the end to be NULL, it's useful for iteration. */
    result[i].class_key = NULL;

    repr_data->name_to_index_mapping = result;

    return flat_list;
}
예제 #7
0
static void * unmarshal_callback(MVMThreadContext *tc, MVMObject *callback, MVMObject *sig_info) {
    MVMNativeCallbackCacheHead *callback_data_head = NULL;
    MVMNativeCallback **callback_data_handle;
    MVMString          *cuid;

    if (!IS_CONCRETE(callback))
        return NULL;

    /* Try to locate existing cached callback info. */
    callback = MVM_frame_find_invokee(tc, callback, NULL);
    cuid     = ((MVMCode *)callback)->body.sf->body.cuuid;
    MVM_string_flatten(tc, cuid);
    MVM_HASH_GET(tc, tc->native_callback_cache, cuid, callback_data_head);

    if (!callback_data_head) {
        callback_data_head = MVM_malloc(sizeof(MVMNativeCallbackCacheHead));
        callback_data_head->head = NULL;

        MVM_HASH_BIND(tc, tc->native_callback_cache, cuid, callback_data_head);
    }

    callback_data_handle = &(callback_data_head->head);

    while (*callback_data_handle) {
        if ((*callback_data_handle)->target == callback) /* found it, break */
            break;

        callback_data_handle = &((*callback_data_handle)->next);
    }

    if (!*callback_data_handle) {
        /* First, build the MVMNativeCallback */
        MVMCallsite *cs;
        char        *signature;
        MVMObject   *typehash;
        MVMint64     num_info, i;
        MVMNativeCallback *callback_data;

        num_info                 = MVM_repr_elems(tc, sig_info);
        callback_data            = MVM_malloc(sizeof(MVMNativeCallback));
        callback_data->num_types = num_info;
        callback_data->typeinfos = MVM_malloc(num_info * sizeof(MVMint16));
        callback_data->types     = MVM_malloc(num_info * sizeof(MVMObject *));
        callback_data->next      = NULL;

        /* A dyncall signature looks like this: xxx)x
        * Argument types before the ) and return type after it. Thus,
        * num_info+1 must be NULL (zero-terminated string) and num_info-1
        * must be the ).
        */
        signature = MVM_malloc(num_info + 2);
        signature[num_info + 1] = '\0';
        signature[num_info - 1] = ')';

        /* We'll also build up a MoarVM callsite as we go. */
        cs                 = MVM_malloc(sizeof(MVMCallsite));
        cs->arg_flags      = MVM_malloc(num_info * sizeof(MVMCallsiteEntry));
        cs->arg_count      = num_info - 1;
        cs->num_pos        = num_info - 1;
        cs->has_flattening = 0;
        cs->is_interned    = 0;
        cs->with_invocant  = NULL;

        typehash = MVM_repr_at_pos_o(tc, sig_info, 0);
        callback_data->types[0] = MVM_repr_at_key_o(tc, typehash,
            tc->instance->str_consts.typeobj);
        callback_data->typeinfos[0] = MVM_nativecall_get_arg_type(tc, typehash, 1);
        signature[num_info] = get_signature_char(callback_data->typeinfos[0]);
        for (i = 1; i < num_info; i++) {
            typehash = MVM_repr_at_pos_o(tc, sig_info, i);
            callback_data->types[i] = MVM_repr_at_key_o(tc, typehash,
                tc->instance->str_consts.typeobj);
            callback_data->typeinfos[i] = MVM_nativecall_get_arg_type(tc, typehash, 0) & ~MVM_NATIVECALL_ARG_FREE_STR;
            signature[i - 1] = get_signature_char(callback_data->typeinfos[i]);
            switch (callback_data->typeinfos[i] & MVM_NATIVECALL_ARG_TYPE_MASK) {
                case MVM_NATIVECALL_ARG_CHAR:
                case MVM_NATIVECALL_ARG_SHORT:
                case MVM_NATIVECALL_ARG_INT:
                case MVM_NATIVECALL_ARG_LONG:
                case MVM_NATIVECALL_ARG_LONGLONG:
                    cs->arg_flags[i - 1] = MVM_CALLSITE_ARG_INT;
                    break;
                case MVM_NATIVECALL_ARG_UCHAR:
                case MVM_NATIVECALL_ARG_USHORT:
                case MVM_NATIVECALL_ARG_UINT:
                case MVM_NATIVECALL_ARG_ULONG:
                case MVM_NATIVECALL_ARG_ULONGLONG:
                    /* TODO: should probably be UINT, when we can support that. */
                    cs->arg_flags[i - 1] = MVM_CALLSITE_ARG_INT;
                    break;
                case MVM_NATIVECALL_ARG_FLOAT:
                case MVM_NATIVECALL_ARG_DOUBLE:
                    cs->arg_flags[i - 1] = MVM_CALLSITE_ARG_NUM;
                    break;
                default:
                    cs->arg_flags[i - 1] = MVM_CALLSITE_ARG_OBJ;
                    break;
            }
        }

        MVM_callsite_try_intern(tc, &cs);

        callback_data->tc        = tc;
        callback_data->cs        = cs;
        callback_data->target    = callback;
        callback_data->cb        = dcbNewCallback(signature, (DCCallbackHandler *)&callback_handler, callback_data);

        /* Now insert the MVMCallback into the linked list. */
        *callback_data_handle = callback_data;
        MVM_free(signature);
    }

    return (*callback_data_handle)->cb;
}
예제 #8
0
static void * unmarshal_callback(MVMThreadContext *tc, MVMObject *callback, MVMObject *sig_info) {
    MVMNativeCallbackCacheHead *callback_data_head = NULL;
    MVMNativeCallback **callback_data_handle;
    MVMString          *cuid;

    if (!IS_CONCRETE(callback))
        return NULL;

    /* Try to locate existing cached callback info. */
    callback = MVM_frame_find_invokee(tc, callback, NULL);
    cuid     = ((MVMCode *)callback)->body.sf->body.cuuid;
    MVM_HASH_GET(tc, tc->native_callback_cache, cuid, callback_data_head);

    if (!callback_data_head) {
        callback_data_head = MVM_malloc(sizeof(MVMNativeCallbackCacheHead));
        callback_data_head->head = NULL;

        MVM_HASH_BIND(tc, tc->native_callback_cache, cuid, callback_data_head);
    }

    callback_data_handle = &(callback_data_head->head);

    while (*callback_data_handle) {
        if ((*callback_data_handle)->target == callback) /* found it, break */
            break;

        callback_data_handle = &((*callback_data_handle)->next);
    }

    if (!*callback_data_handle) {
        /* First, build the MVMNativeCallback */
        MVMCallsite *cs;
        MVMObject   *typehash;
        MVMint64     num_info, i;
        MVMNativeCallback *callback_data;
        /* cb is a piece of executable memory we obtain from libffi. */
        void *cb;
        ffi_cif *cif;
        ffi_closure *closure;
        ffi_status status;

        num_info = MVM_repr_elems(tc, sig_info);

        /* We'll also build up a MoarVM callsite as we go. */
        cs                 = MVM_calloc(1, sizeof(MVMCallsite));
        cs->flag_count     = num_info - 1;
        cs->arg_flags      = MVM_malloc(cs->flag_count * sizeof(MVMCallsiteEntry));
        cs->arg_count      = num_info - 1;
        cs->num_pos        = num_info - 1;
        cs->has_flattening = 0;
        cs->is_interned    = 0;
        cs->with_invocant  = NULL;

        callback_data                = MVM_malloc(sizeof(MVMNativeCallback));
        callback_data->num_types     = num_info;
        callback_data->typeinfos     = MVM_malloc(num_info * sizeof(MVMint16));
        callback_data->types         = MVM_malloc(num_info * sizeof(MVMObject *));
        callback_data->next          = NULL;
        cif                          = (ffi_cif *)MVM_malloc(sizeof(ffi_cif));
        callback_data->convention    = FFI_DEFAULT_ABI;
        callback_data->ffi_arg_types = MVM_malloc(sizeof(ffi_type *) * (cs->arg_count ? cs->arg_count : 1));

        /* Collect information about the return type. */
        typehash                    = MVM_repr_at_pos_o(tc, sig_info, 0);
        callback_data->types[0]     = MVM_repr_at_key_o(tc, typehash, tc->instance->str_consts.typeobj);
        callback_data->typeinfos[0] = MVM_nativecall_get_arg_type(tc, typehash, 1);
        callback_data->ffi_ret_type = MVM_nativecall_get_ffi_type(tc, callback_data->typeinfos[0]);

        for (i = 1; i < num_info; i++) {
            typehash = MVM_repr_at_pos_o(tc, sig_info, i);
            callback_data->types[i]             = MVM_repr_at_key_o(tc, typehash, tc->instance->str_consts.typeobj);
            callback_data->typeinfos[i]         = MVM_nativecall_get_arg_type(tc, typehash, 0) & ~MVM_NATIVECALL_ARG_FREE_STR;
            callback_data->ffi_arg_types[i - 1] = MVM_nativecall_get_ffi_type(tc, callback_data->typeinfos[i]);
            switch (callback_data->typeinfos[i] & MVM_NATIVECALL_ARG_TYPE_MASK) {
                case MVM_NATIVECALL_ARG_CHAR:
                case MVM_NATIVECALL_ARG_SHORT:
                case MVM_NATIVECALL_ARG_INT:
                case MVM_NATIVECALL_ARG_LONG:
                case MVM_NATIVECALL_ARG_LONGLONG:
                    cs->arg_flags[i - 1] = MVM_CALLSITE_ARG_INT;
                    break;
                case MVM_NATIVECALL_ARG_UCHAR:
                case MVM_NATIVECALL_ARG_USHORT:
                case MVM_NATIVECALL_ARG_UINT:
                case MVM_NATIVECALL_ARG_ULONG:
                case MVM_NATIVECALL_ARG_ULONGLONG:
                    /* TODO: should probably be UINT, when we can support that. */
                    cs->arg_flags[i - 1] = MVM_CALLSITE_ARG_INT;
                    break;
                case MVM_NATIVECALL_ARG_FLOAT:
                case MVM_NATIVECALL_ARG_DOUBLE:
                    cs->arg_flags[i - 1] = MVM_CALLSITE_ARG_NUM;
                    break;
                default:
                    cs->arg_flags[i - 1] = MVM_CALLSITE_ARG_OBJ;
                    break;
            }
        }

        MVM_callsite_try_intern(tc, &cs);

        callback_data->instance  = tc->instance;
        callback_data->cs        = cs;
        callback_data->target    = callback;
        status                   = ffi_prep_cif(cif, callback_data->convention, (unsigned int)cs->arg_count,
            callback_data->ffi_ret_type, callback_data->ffi_arg_types);

        closure                  = ffi_closure_alloc(sizeof(ffi_closure), &cb);
        if (!closure)
            MVM_panic(1, "Unable to allocate memory for callback closure");
        ffi_prep_closure_loc(closure, cif, callback_handler, callback_data, cb);
        callback_data->cb        = cb;

        /* Now insert the MVMCallback into the linked list. */
        *callback_data_handle    = callback_data;
    }

    return (*callback_data_handle)->cb;
}
예제 #9
0
MVMint64 MVM_proc_spawn(MVMThreadContext *tc, MVMObject *argv, MVMString *cwd, MVMObject *env,
        MVMObject *in, MVMObject *out, MVMObject *err, MVMint64 flags) {
    MVMint64 result = 0, spawn_result;
    uv_process_t *process = MVM_calloc(1, sizeof(uv_process_t));
    uv_process_options_t process_options = {0};
    uv_stdio_container_t process_stdio[3];
    int i;

    char   * const      _cwd = MVM_string_utf8_c8_encode_C_string(tc, cwd);
    const MVMuint64     size = MVM_repr_elems(tc, env);
    MVMIter * const     iter = (MVMIter *)MVM_iter(tc, env);
    char              **_env = MVM_malloc((size + 1) * sizeof(char *));
    const MVMuint64  arg_size = MVM_repr_elems(tc, argv);
    char             **args = MVM_malloc((arg_size + 1) * sizeof(char *));
    MVMRegister        reg;

    i = 0;
    while(i < arg_size) {
        REPR(argv)->pos_funcs.at_pos(tc, STABLE(argv), argv, OBJECT_BODY(argv), i, &reg, MVM_reg_obj);
        args[i++] = MVM_string_utf8_c8_encode_C_string(tc, MVM_repr_get_str(tc, reg.o));
    }
    args[arg_size] = NULL;

    INIT_ENV();
    setup_process_stdio(tc, in,  process, &process_stdio[0], 0, flags,      "spawn");
    setup_process_stdio(tc, out, process, &process_stdio[1], 1, flags >> 3, "spawn");
    setup_process_stdio(tc, err, process, &process_stdio[2], 2, flags >> 6, "spawn");

    process_options.stdio       = process_stdio;
    process_options.file        = arg_size ? args[0] : NULL;
    process_options.args        = args;
    process_options.cwd         = _cwd;
    process_options.flags       = UV_PROCESS_WINDOWS_HIDE;
    process_options.env         = _env;
    process_options.stdio_count = 3;
    process_options.exit_cb     = spawn_on_exit;
    if (flags & (MVM_PIPE_CAPTURE_IN | MVM_PIPE_CAPTURE_OUT | MVM_PIPE_CAPTURE_ERR)) {
        process->data = MVM_calloc(1, sizeof(MVMint64));
        uv_ref((uv_handle_t *)process);
        spawn_result = uv_spawn(tc->loop, process, &process_options);
        if (spawn_result)
            result = spawn_result;
    }
    else {
        process->data = &result;
        uv_ref((uv_handle_t *)process);
        spawn_result = uv_spawn(tc->loop, process, &process_options);
        if (spawn_result)
            result = spawn_result;
        else
            uv_run(tc->loop, UV_RUN_DEFAULT);
    }

    FREE_ENV();
    MVM_free(_cwd);
    uv_unref((uv_handle_t *)process);

    i = 0;
    while(args[i])
        MVM_free(args[i++]);

    MVM_free(args);

    return result;
}
예제 #10
0
MVMint64 MVM_proc_shell(MVMThreadContext *tc, MVMString *cmd, MVMString *cwd, MVMObject *env,
        MVMObject *in, MVMObject *out, MVMObject *err, MVMint64 flags) {
    MVMint64 result = 0, spawn_result;
    uv_process_t *process = MVM_calloc(1, sizeof(uv_process_t));
    uv_process_options_t process_options = {0};
    uv_stdio_container_t process_stdio[3];
    int i;

    char * const cmdin = MVM_string_utf8_c8_encode_C_string(tc, cmd);
    char * const _cwd = MVM_string_utf8_c8_encode_C_string(tc, cwd);
    const MVMuint64 size = MVM_repr_elems(tc, env);
    MVMIter * const iter = (MVMIter *)MVM_iter(tc, env);
    char **_env = MVM_malloc((size + 1) * sizeof(char *));

#ifdef _WIN32
    const MVMuint16 acp = GetACP(); /* We should get ACP at runtime. */
    char * const _cmd = ANSIToUTF8(acp, getenv("ComSpec"));
    char *args[3];
    args[0] = "/c";
    args[1] = cmdin;
    args[2] = NULL;
#else
    char * const _cmd = "/bin/sh";
    char *args[4];
    args[0] = "/bin/sh";
    args[1] = "-c";
    args[2] = cmdin;
    args[3] = NULL;
#endif

    INIT_ENV();
    setup_process_stdio(tc, in,  process, &process_stdio[0], 0, flags,      "shell");
    setup_process_stdio(tc, out, process, &process_stdio[1], 1, flags >> 3, "shell");
    setup_process_stdio(tc, err, process, &process_stdio[2], 2, flags >> 6, "shell");

    process_options.stdio       = process_stdio;
    process_options.file        = _cmd;
    process_options.args        = args;
    process_options.cwd         = _cwd;
    process_options.flags       = UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS | UV_PROCESS_WINDOWS_HIDE;
    process_options.env         = _env;
    process_options.stdio_count = 3;
    process_options.exit_cb     = spawn_on_exit;
    if (flags & (MVM_PIPE_CAPTURE_IN | MVM_PIPE_CAPTURE_OUT | MVM_PIPE_CAPTURE_ERR)) {
        process->data = MVM_calloc(1, sizeof(MVMint64));
        uv_ref((uv_handle_t *)process);
        spawn_result = uv_spawn(tc->loop, process, &process_options);
        if (spawn_result)
            result = spawn_result;
    }
    else {
        process->data = &result;
        uv_ref((uv_handle_t *)process);
        spawn_result = uv_spawn(tc->loop, process, &process_options);
        if (spawn_result)
            result = spawn_result;
        else
            uv_run(tc->loop, UV_RUN_DEFAULT);
    }

    FREE_ENV();
    MVM_free(_cwd);
#ifdef _WIN32
    MVM_free(_cmd);
#endif
    MVM_free(cmdin);
    uv_unref((uv_handle_t *)process);

    return result;
}
예제 #11
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(MVMThreadContext *tc, MVMObject *repr_info, MVMCStructREPRData *repr_data) {
    /* Compute index mapping table and get flat list of attributes. */
    MVMObject *flat_list = index_mapping_and_flat_list(tc, 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. */
        MVMint32 cur_size    = 0;
        /* The structure itself will be the multiple of its biggest element in size.
         * So we keep track of that biggest element. */
        MVMint32 multiple_of = 1;

        /* Get number of attributes and set up various counters. */
        MVMint32 num_attrs        = MVM_repr_elems(tc, flat_list);
        MVMint32 info_alloc       = num_attrs == 0 ? 1 : num_attrs;
        MVMint32 cur_obj_attr     = 0;
        MVMint32 cur_init_slot    = 0;
        MVMint32 i;

        /* Allocate location/offset arrays and GC mark info arrays. */
        repr_data->num_attributes      = num_attrs;
        repr_data->attribute_locations = (MVMint32 *)   MVM_malloc(info_alloc * sizeof(MVMint32));
        repr_data->struct_offsets      = (MVMint32 *)   MVM_malloc(info_alloc * sizeof(MVMint32));
        repr_data->flattened_stables   = (MVMSTable **) MVM_calloc(info_alloc, sizeof(MVMObject *));
        repr_data->member_types        = (MVMObject **) MVM_calloc(info_alloc, sizeof(MVMObject *));

        /* 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. */
            MVMObject *attr  = MVM_repr_at_pos_o(tc, flat_list, i);
            MVMObject *type  = MVM_repr_at_key_o(tc, attr, tc->instance->str_consts.type);
            MVMObject *inlined_val = MVM_repr_at_key_o(tc, attr, tc->instance->str_consts.inlined);
            MVMint64 inlined = !MVM_is_null(tc, inlined_val) && MVM_repr_get_int(tc, inlined_val);
            MVMint32   bits  = sizeof(void *) * 8;
            MVMint32   align = ALIGNOF(void *);
            if (!MVM_is_null(tc, type)) {
                /* See if it's a type that we know how to handle in a C struct. */
                const MVMStorageSpec *spec = REPR(type)->get_storage_spec(tc, STABLE(type));
                MVMint32  type_id    = REPR(type)->ID;
                if (spec->inlineable == MVM_STORAGE_SPEC_INLINED &&
                        (spec->boxed_primitive == MVM_STORAGE_SPEC_BP_INT ||
                         spec->boxed_primitive == MVM_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;

                    repr_data->attribute_locations[i] = (bits << MVM_CSTRUCT_ATTR_SHIFT) | MVM_CSTRUCT_ATTR_IN_STRUCT;
                    repr_data->flattened_stables[i] = STABLE(type);
                    if (REPR(type)->initialize) {
                        if (!repr_data->initialize_slots)
                            repr_data->initialize_slots = (MVMint32 *) MVM_calloc(info_alloc + 1, sizeof(MVMint32));
                        repr_data->initialize_slots[cur_init_slot] = i;
                        cur_init_slot++;
                    }
                }
                else if (spec->can_box & MVM_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++ << MVM_CSTRUCT_ATTR_SHIFT) | MVM_CSTRUCT_ATTR_STRING;
                    repr_data->member_types[i] = type;
                    repr_data->flattened_stables[i] = STABLE(type);
                    if (REPR(type)->initialize) {
                        if (!repr_data->initialize_slots)
                            repr_data->initialize_slots = (MVMint32 *) MVM_calloc(info_alloc + 1, sizeof(MVMint32));
                        repr_data->initialize_slots[cur_init_slot] = i;
                        cur_init_slot++;
                    }
                }
                else if (type_id == MVM_REPR_ID_MVMCArray) {
                    /* It's a CArray of some kind.  */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CSTRUCT_ATTR_SHIFT) | MVM_CSTRUCT_ATTR_CARRAY;
                    repr_data->member_types[i] = type;
                }
                else if (type_id == MVM_REPR_ID_MVMCStruct) {
                    /* It's a CStruct. */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CSTRUCT_ATTR_SHIFT) | MVM_CSTRUCT_ATTR_CSTRUCT;
                    repr_data->member_types[i] = type;
                    if (inlined) {
                        MVMCStructREPRData *cstruct_repr_data = (MVMCStructREPRData *)STABLE(type)->REPR_data;
                        bits                                  = cstruct_repr_data->struct_size * 8;
                        align                                 = cstruct_repr_data->struct_size;
                        repr_data->attribute_locations[i]    |= MVM_CSTRUCT_ATTR_INLINED;
                    }
                }
                else if (type_id == MVM_REPR_ID_MVMCPPStruct) {
                    /* It's a CPPStruct. */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CSTRUCT_ATTR_SHIFT) | MVM_CSTRUCT_ATTR_CPPSTRUCT;
                    repr_data->member_types[i] = type;
                    if (inlined) {
                        MVMCPPStructREPRData *cppstruct_repr_data = (MVMCPPStructREPRData *)STABLE(type)->REPR_data;
                        bits                                      = cppstruct_repr_data->struct_size * 8;
                        align                                     = cppstruct_repr_data->struct_size;
                        repr_data->attribute_locations[i]        |= MVM_CSTRUCT_ATTR_INLINED;
                    }
                }
                else if (type_id == MVM_REPR_ID_MVMCUnion) {
                    /* It's a CUnion. */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CSTRUCT_ATTR_SHIFT) | MVM_CSTRUCT_ATTR_CUNION;
                    repr_data->member_types[i] = type;
                    if (inlined) {
                        MVMCUnionREPRData *cunion_repr_data = (MVMCUnionREPRData *)STABLE(type)->REPR_data;
                        bits                                = cunion_repr_data->struct_size * 8;
                        align                               = cunion_repr_data->struct_size;
                        repr_data->attribute_locations[i]  |= MVM_CSTRUCT_ATTR_INLINED;
                    }
                }
                else if (type_id == MVM_REPR_ID_MVMCPointer) {
                    /* It's a CPointer. */
                    repr_data->num_child_objs++;
                    repr_data->attribute_locations[i] = (cur_obj_attr++ << MVM_CSTRUCT_ATTR_SHIFT) | MVM_CSTRUCT_ATTR_CPTR;
                    repr_data->member_types[i] = type;
                }
                else {
                    MVM_exception_throw_adhoc(tc,
                        "CStruct representation only handles int, num, CArray, CPointer, CStruct, CPPStruct and CUnion");
                }
            }
            else {
                MVM_exception_throw_adhoc(tc,
                    "CStruct representation requires the types of all attributes to be specified");
            }

            if (bits % 8) {
                 MVM_exception_throw_adhoc(tc,
                    "CStruct only supports native types that are a multiple of 8 bits wide (was passed: %"PRId32")", bits);
            }

            /* 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;

            if (bits / 8 > multiple_of)
                multiple_of = bits / 8;
        }

        /* Finally, put computed allocation size in place; it's body size plus
         * header size. Also number of markables and sentinels. */
        if (multiple_of > sizeof(void *))
            multiple_of = sizeof(void *);
        repr_data->struct_size = ceil((double)cur_size / (double)multiple_of) * multiple_of;
        if (repr_data->initialize_slots)
            repr_data->initialize_slots[cur_init_slot] = -1;
    }
}
예제 #12
0
/* Enters the work loop. */
static void worker(MVMThreadContext *tc, MVMCallsite *callsite, MVMRegister *args) {
    MVMObject *updated_static_frames = MVM_repr_alloc_init(tc,
        tc->instance->boot_types.BOOTArray);
    MVMObject *previous_static_frames = MVM_repr_alloc_init(tc,
        tc->instance->boot_types.BOOTArray);

    tc->instance->speshworker_thread_id = tc->thread_obj->body.thread_id;

    MVMROOT2(tc, updated_static_frames, previous_static_frames, {
        while (1) {
            MVMObject *log_obj;
            MVMuint64 start_time;
            unsigned int interval_id;
            if (MVM_spesh_debug_enabled(tc))
                start_time = uv_hrtime();
            log_obj = MVM_repr_shift_o(tc, tc->instance->spesh_queue);
            if (MVM_spesh_debug_enabled(tc)) {
                MVM_spesh_debug_printf(tc,
                    "Received Logs\n"
                    "=============\n\n"
                    "Was waiting %dus for logs on the log queue.\n\n",
                    (int)((uv_hrtime() - start_time) / 1000));
            }

            if (tc->instance->main_thread->prof_data)
                MVM_profiler_log_spesh_start(tc);

            interval_id = MVM_telemetry_interval_start(tc, "spesh worker consuming a log");

            uv_mutex_lock(&(tc->instance->mutex_spesh_sync));
            tc->instance->spesh_working = 1;
            uv_mutex_unlock(&(tc->instance->mutex_spesh_sync));

            tc->instance->spesh_stats_version++;
            if (log_obj->st->REPR->ID == MVM_REPR_ID_MVMSpeshLog) {
                MVMSpeshLog *sl = (MVMSpeshLog *)log_obj;
                MVM_telemetry_interval_annotate((uintptr_t)sl->body.thread->body.tc, interval_id, "from this thread");
                MVMROOT(tc, sl, {
                    MVMThreadContext *stc;
                    MVMuint32 i;
                    MVMuint32 n;

                    /* Update stats, and if we're logging dump each of them. */
                    tc->instance->spesh_stats_version++;
                    if (MVM_spesh_debug_enabled(tc))
                        start_time = uv_hrtime();
                    MVM_spesh_stats_update(tc, sl, updated_static_frames);
                    n = MVM_repr_elems(tc, updated_static_frames);
                    if (MVM_spesh_debug_enabled(tc)) {
                        MVM_spesh_debug_printf(tc,
                            "Statistics Updated\n"
                            "==================\n"
                            "%d frames had their statistics updated in %dus.\n\n",
                            (int)n, (int)((uv_hrtime() - start_time) / 1000));
                        for (i = 0; i < n; i++) {
                            char *dump = MVM_spesh_dump_stats(tc, (MVMStaticFrame* )
                                MVM_repr_at_pos_o(tc, updated_static_frames, i));
                            MVM_spesh_debug_printf(tc, "%s==========\n\n", dump);
                            MVM_free(dump);
                        }
                    }
                    MVM_telemetry_interval_annotate((uintptr_t)n, interval_id, "stats for this many frames");
                    GC_SYNC_POINT(tc);

                    /* Form a specialization plan. */
                    if (MVM_spesh_debug_enabled(tc))
                        start_time = uv_hrtime();
                    tc->instance->spesh_plan = MVM_spesh_plan(tc, updated_static_frames);
                    if (MVM_spesh_debug_enabled(tc)) {
                        n = tc->instance->spesh_plan->num_planned;
                        MVM_spesh_debug_printf(tc,
                            "Specialization Plan\n"
                            "===================\n"
                            "%u specialization(s) will be produced (planned in %dus).\n\n",
                            n, (int)((uv_hrtime() - start_time) / 1000));
                        for (i = 0; i < n; i++) {
                            char *dump = MVM_spesh_dump_planned(tc,
                                &(tc->instance->spesh_plan->planned[i]));
                            MVM_spesh_debug_printf(tc, "%s==========\n\n", dump);
                            MVM_free(dump);
                        }
                    }
                    MVM_telemetry_interval_annotate((uintptr_t)tc->instance->spesh_plan->num_planned, interval_id,
                            "this many specializations planned");
                    GC_SYNC_POINT(tc);

                    /* Implement the plan and then discard it. */
                    n = tc->instance->spesh_plan->num_planned;
                    for (i = 0; i < n; i++) {
                        MVM_spesh_candidate_add(tc, &(tc->instance->spesh_plan->planned[i]));
                        GC_SYNC_POINT(tc);
                    }
                    MVM_spesh_plan_destroy(tc, tc->instance->spesh_plan);
                    tc->instance->spesh_plan = NULL;

                    /* Clear up stats that didn't get updated for a while,
                     * then add frames updated this time into the previously
                     * updated array. */
                    MVM_spesh_stats_cleanup(tc, previous_static_frames);
                    n = MVM_repr_elems(tc, updated_static_frames);
                    for (i = 0; i < n; i++)
                        MVM_repr_push_o(tc, previous_static_frames,
                            MVM_repr_at_pos_o(tc, updated_static_frames, i));

                    /* Clear updated static frames array. */
                    MVM_repr_pos_set_elems(tc, updated_static_frames, 0);

                    /* Allow the sending thread to produce more logs again,
                     * putting a new spesh log in place if needed. */
                    stc = sl->body.thread->body.tc;
                    if (stc && !sl->body.was_compunit_bumped)
                        if (MVM_incr(&(stc->spesh_log_quota)) == 0) {
                            stc->spesh_log = MVM_spesh_log_create(tc, sl->body.thread);
                            MVM_telemetry_timestamp(stc, "logging restored after quota had run out");
                        }

                    /* If needed, signal sending thread that it can continue. */
                    if (sl->body.block_mutex) {
                        uv_mutex_lock(sl->body.block_mutex);
                        MVM_store(&(sl->body.completed), 1);
                        uv_cond_signal(sl->body.block_condvar);
                        uv_mutex_unlock(sl->body.block_mutex);
                    }
                    {
                        MVMSpeshLogEntry *entries = sl->body.entries;
                        sl->body.entries = NULL;
                        MVM_free(entries);
                    }
                });
            }
            else if (MVM_is_null(tc, log_obj)) {
예제 #13
0
MVMObject * MVM_file_openpipe(MVMThreadContext *tc, MVMString *cmd, MVMString *cwd, MVMObject *env, MVMString *err_path) {
    MVMint64 spawn_result = 0;
    uv_process_t *process = calloc(1, sizeof(uv_process_t));
    uv_process_options_t process_options = {0};
    uv_stdio_container_t process_stdio[3];
    int i;
    int status;
    int readable = 1;
    uv_pipe_t *out, *in;

    char * const cmdin = MVM_string_utf8_encode_C_string(tc, cmd);
    char * const _cwd = MVM_string_utf8_encode_C_string(tc, cwd);
    const MVMuint64 size = MVM_repr_elems(tc, env);
    MVMIter * const iter = (MVMIter *)MVM_iter(tc, env);
    char **_env = malloc((size + 1) * sizeof(char *));

#ifdef _WIN32
    const MVMuint16 acp = GetACP(); /* We should get ACP at runtime. */
    char * const _cmd = ANSIToUTF8(acp, getenv("ComSpec"));
    char *args[3];
    args[0] = "/c";
    {
        MVMint64 len = strlen(cmdin);
        MVMint64 i;
        for (i = 0; i < len; i++)
            if (cmdin[i] == '/')
                cmdin[i] = '\\';
    }
    args[1] = cmdin;
    args[2] = NULL;
#else
    char * const _cmd = "/bin/sh";
    char *args[4];
    args[0] = "/bin/sh";
    args[1] = "-c";
    args[2] = cmdin;
    args[3] = NULL;
#endif

    INIT_ENV();
    /* Making openpipe distinguish between :rp and :wp and all other options
     * is left as an excercise for the reader. 
    readable = strncmp(cmdin, "/usr/bin/wc", 11) != 0; */

    if (readable) {
        /* We want to read from the child's stdout. */
        out = malloc(sizeof(uv_pipe_t));
        uv_pipe_init(tc->loop, out, 0);
        uv_pipe_open(out, 0);
        process_stdio[0].flags       = UV_INHERIT_FD; // child's stdin
        process_stdio[0].data.fd     = 0;
        process_stdio[1].flags       = UV_CREATE_PIPE | UV_WRITABLE_PIPE; // child's stdout
        process_stdio[1].data.stream = (uv_stream_t*)out;
    }
    else {
        /* We want to print to the child's stdin. */
        in  = malloc(sizeof(uv_pipe_t));
        uv_pipe_init(tc->loop, in, 0);
        uv_pipe_open(in, 1);
        process_stdio[0].flags       = UV_CREATE_PIPE | UV_READABLE_PIPE; // child's stdin
        process_stdio[0].data.stream = (uv_stream_t*)in;
        process_stdio[1].flags       = UV_INHERIT_FD; // child's stdout
        process_stdio[1].data.fd     = 1;
    }
    process_stdio[2].flags      = UV_INHERIT_FD; // child's stderr
    process_stdio[2].data.fd    = 2;
    process_options.stdio       = process_stdio;
    process_options.file        = _cmd;
    process_options.args        = args;
    process_options.cwd         = _cwd;
    process_options.flags       = UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS | UV_PROCESS_WINDOWS_HIDE;
    process_options.env         = _env;
    process_options.stdio_count = 3;
    process_options.exit_cb     = spawn_on_exit;
    uv_ref((uv_handle_t *)process);
    spawn_result = uv_spawn(tc->loop, process, &process_options);
    if (spawn_result) {
        FREE_ENV();
        free(_cwd);
        free(cmdin);
        uv_unref((uv_handle_t *)process);
        MVM_exception_throw_adhoc(tc, "Failed to open pipe: %d", errno);
    }

    FREE_ENV();
    free(_cwd);
    free(cmdin);
    uv_unref((uv_handle_t *)process);

    return MVM_io_syncpipe(tc, (uv_stream_t *)(readable ? out : in), process);
}
예제 #14
0
void MVM_coerce_istrue(MVMThreadContext *tc, MVMObject *obj, MVMRegister *res_reg,
                       MVMuint8 *true_addr, MVMuint8 *false_addr, MVMuint8 flip) {
    MVMint64 result;
    if (obj == NULL) {
        result = 0;
    }
    else {
        MVMBoolificationSpec *bs = obj->st->boolification_spec;
        switch (bs == NULL ? MVM_BOOL_MODE_NOT_TYPE_OBJECT : bs->mode) {
        case MVM_BOOL_MODE_CALL_METHOD:
            if (res_reg) {
                /* We need to do the invocation, and set this register
                 * the result. Then we just do the call. For the flip
                 * case, just set up special return handler to flip
                 * the register. */
                MVMObject *code = MVM_frame_find_invokee(tc, bs->method);
                tc->cur_frame->return_value   = res_reg;
                tc->cur_frame->return_type    = MVM_RETURN_INT;
                tc->cur_frame->return_address = *(tc->interp_cur_op);
                tc->cur_frame->args[0].o = obj;
                if (flip) {
                    tc->cur_frame->special_return      = flip_return;
                    tc->cur_frame->special_return_data = res_reg;
                }
                STABLE(code)->invoke(tc, code, get_inv_callsite(), tc->cur_frame->args);
            }
            else {
                /* Need to set up special return hook. */
                MVMObject *code = MVM_frame_find_invokee(tc, bs->method);
                BoolMethReturnData *data = malloc(sizeof(BoolMethReturnData));
                data->true_addr  = true_addr;
                data->false_addr = false_addr;
                data->flip       = flip;
                tc->cur_frame->special_return      = boolify_return;
                tc->cur_frame->special_return_data = data;
                tc->cur_frame->return_value        = &data->res_reg;
                tc->cur_frame->return_type         = MVM_RETURN_INT;
                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;
            }
            break;
        case MVM_BOOL_MODE_UNBOX_INT:
            result = !IS_CONCRETE(obj) || REPR(obj)->box_funcs->get_int(tc, STABLE(obj), obj, OBJECT_BODY(obj)) == 0 ? 0 : 1;
            break;
        case MVM_BOOL_MODE_UNBOX_NUM:
            result = !IS_CONCRETE(obj) || REPR(obj)->box_funcs->get_num(tc, STABLE(obj), obj, OBJECT_BODY(obj)) == 0.0 ? 0 : 1;
            break;
        case MVM_BOOL_MODE_UNBOX_STR_NOT_EMPTY:
            result = !IS_CONCRETE(obj) || NUM_GRAPHS(REPR(obj)->box_funcs->get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj))) == 0 ? 0 : 1;
            break;
        case MVM_BOOL_MODE_UNBOX_STR_NOT_EMPTY_OR_ZERO: {
            MVMString *str;
            if (!IS_CONCRETE(obj)) {
                result = 0;
                break;
            }
            str = REPR(obj)->box_funcs->get_str(tc, STABLE(obj), obj, OBJECT_BODY(obj));
            result = MVM_coerce_istrue_s(tc, str);
            break;
        }
        case MVM_BOOL_MODE_NOT_TYPE_OBJECT:
            result = !IS_CONCRETE(obj) ? 0 : 1;
            break;
        case MVM_BOOL_MODE_ITER:
            result = IS_CONCRETE(obj) ? MVM_iter_istrue(tc, (MVMIter *)obj) : 0;
            break;
        case MVM_BOOL_MODE_HAS_ELEMS:
            result = IS_CONCRETE(obj) ? MVM_repr_elems(tc, obj) != 0 : 0;
            break;
        default:
            MVM_exception_throw_adhoc(tc, "Invalid boolification spec mode used");
        }
    }

    if (flip)
        result = result ? 0 : 1;

    if (res_reg) {
        res_reg->i64 = result;
    }
    else {
        if (result)
            *(tc->interp_cur_op) = true_addr;
        else
            *(tc->interp_cur_op) = false_addr;
    }
}