Exemple #1
0
static void init_named_used(MVMThreadContext *tc, MVMArgProcContext *ctx, MVMuint16 num) {
    ctx->named_used_size = num;
    if (num > 64)
        ctx->named_used.byte_array = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa, num);
    else
        ctx->named_used.bit_field = 0;
}
Exemple #2
0
/* Loads the extension op records. */
static MVMExtOpRecord * deserialize_extop_records(MVMThreadContext *tc, MVMCompUnit *cu, ReaderState *rs) {
    MVMExtOpRecord *extops;
    MVMuint32 num = rs->expected_extops;
    MVMuint8 *pos;
    MVMuint32 i;

    if (num == 0)
        return NULL;

    extops = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa,
        num * sizeof(MVMExtOpRecord));

    pos = rs->extop_seg;
    for (i = 0; i < num; i++) {
        MVMuint32 name_idx;
        MVMuint16 operand_bytes = 0;
        MVMuint8 *operand_descriptor = extops[i].operand_descriptor;

        /* Read name string index. */
        ensure_can_read(tc, cu, rs, pos, 4);
        name_idx = read_int32(pos, 0);
        pos += 4;

        /* Lookup name string. */
        if (name_idx >= cu->body.num_strings) {
            cleanup_all(tc, rs);
            MVM_exception_throw_adhoc(tc,
                    "String heap index beyond end of string heap");
        }
        extops[i].name = MVM_cu_string(tc, cu, name_idx);

        /* Read operand descriptor. */
        ensure_can_read(tc, cu, rs, pos, 8);
        memcpy(operand_descriptor, pos, 8);
        pos += 8;

        /* Validate operand descriptor.
         * TODO: Unify with validation in MVM_ext_register_extop? */
        {
            MVMuint8 j = 0;

            for(; j < 8; j++) {
                MVMuint8 flags = operand_descriptor[j];

                if (!flags)
                    break;

                switch (flags & MVM_operand_rw_mask) {
                    case MVM_operand_literal:
                        goto check_literal;

                    case MVM_operand_read_reg:
                    case MVM_operand_write_reg:
                        operand_bytes += 2;
                        goto check_reg;

                    case MVM_operand_read_lex:
                    case MVM_operand_write_lex:
                        operand_bytes += 4;
                        goto check_reg;

                    default:
                        goto fail;
                }

            check_literal:
                switch (flags & MVM_operand_type_mask) {
                    case MVM_operand_int8:
                        operand_bytes += 1;
                        continue;

                    case MVM_operand_int16:
                        operand_bytes += 2;
                        continue;

                    case MVM_operand_int32:
                        operand_bytes += 4;
                        continue;

                    case MVM_operand_int64:
                        operand_bytes += 8;
                        continue;

                    case MVM_operand_num32:
                        operand_bytes += 4;
                        continue;

                    case MVM_operand_num64:
                        operand_bytes += 8;
                        continue;

                    case MVM_operand_str:
                        operand_bytes += 2;
                        continue;

                    case MVM_operand_coderef:
                        operand_bytes += 2;
                        continue;

                    case MVM_operand_ins:
                    case MVM_operand_callsite:
                    default:
                        goto fail;
                }

            check_reg:
                switch (flags & MVM_operand_type_mask) {
                    case MVM_operand_int8:
                    case MVM_operand_int16:
                    case MVM_operand_int32:
                    case MVM_operand_int64:
                    case MVM_operand_num32:
                    case MVM_operand_num64:
                    case MVM_operand_str:
                    case MVM_operand_obj:
                    case MVM_operand_type_var:
                    case MVM_operand_uint8:
                    case MVM_operand_uint16:
                    case MVM_operand_uint32:
                    case MVM_operand_uint64:
                        continue;

                    default:
                        goto fail;
                }

            fail:
                cleanup_all(tc, rs);
                MVM_exception_throw_adhoc(tc, "Invalid operand descriptor");
            }
        }

        extops[i].operand_bytes = operand_bytes;
    }

    return extops;
}
Exemple #3
0
/* Does the jump into the optimized code. */
void perform_osr(MVMThreadContext *tc, MVMSpeshCandidate *specialized) {
    MVMJitCode *jit_code;
    MVMint32 num_locals;
    /* Work out the OSR deopt index, to locate the entry point. */
    MVMint32 osr_index = get_osr_deopt_index(tc, specialized);
#if MVM_LOG_OSR
    fprintf(stderr, "Performing OSR of frame '%s' (cuid: %s) at index %d\n",
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.name),
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.cuuid),
        osr_index);
#endif

    jit_code = specialized->jitcode;
    num_locals = jit_code && jit_code->local_types ?
        jit_code->num_locals : specialized->num_locals;

    /* Resize work area if needed. */
    if (specialized->work_size > tc->cur_frame->allocd_work) {
        /* Resize work area. */
        MVMRegister *new_work = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa,
            specialized->work_size);
        MVMRegister *new_args = new_work + num_locals;
        memcpy(new_work, tc->cur_frame->work,
            tc->cur_frame->static_info->body.num_locals * sizeof(MVMRegister));
        memcpy(new_args, tc->cur_frame->args,
            tc->cur_frame->static_info->body.cu->body.max_callsite_size * sizeof(MVMRegister));

        MVM_fixed_size_free(tc, tc->instance->fsa, tc->cur_frame->allocd_work,
            tc->cur_frame->work);
        tc->cur_frame->work = new_work;
        tc->cur_frame->allocd_work = specialized->work_size;
        tc->cur_frame->args = new_args;
#if MVM_LOG_OSR
    fprintf(stderr, "OSR resized work area of frame '%s' (cuid: %s)\n",
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.name),
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.cuuid));
#endif
    }
    else if (specialized->work_size > tc->cur_frame->static_info->body.work_size) {
        size_t keep_bytes = tc->cur_frame->static_info->body.num_locals * sizeof(MVMRegister);
        size_t to_null = specialized->work_size - keep_bytes;
        memset((char *)tc->cur_frame->work + keep_bytes, 0, to_null);
    }

    /* Resize environment if needed. */
    if (specialized->num_lexicals > tc->cur_frame->static_info->body.num_lexicals) {
        MVMRegister *new_env = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa,
            specialized->env_size);
        if (tc->cur_frame->allocd_env) {
            memcpy(new_env, tc->cur_frame->env,
                tc->cur_frame->static_info->body.num_lexicals * sizeof(MVMRegister));
            MVM_fixed_size_free(tc, tc->instance->fsa, tc->cur_frame->allocd_env,
                tc->cur_frame->env);
        }
        tc->cur_frame->env = new_env;
        tc->cur_frame->allocd_env = specialized->env_size;
#if MVM_LOG_OSR
    fprintf(stderr, "OSR resized environment of frame '%s' (cuid: %s)\n",
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.name),
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.cuuid));
#endif
    }
    else if (specialized->env_size > tc->cur_frame->static_info->body.env_size) {
        size_t keep_bytes = tc->cur_frame->static_info->body.num_lexicals * sizeof(MVMRegister);
        size_t to_null = specialized->env_size - keep_bytes;
        memset((char *)tc->cur_frame->env + keep_bytes, 0, to_null);
    }

    /* Set up frame to point to spesh candidate/slots. */
    tc->cur_frame->effective_spesh_slots = specialized->spesh_slots;
    tc->cur_frame->spesh_cand            = specialized;

    /* Move into the optimized (and maybe JIT-compiled) code. */

    if (jit_code && jit_code->num_deopts) {
        MVMint32 i;
        *(tc->interp_bytecode_start)   = jit_code->bytecode;
        *(tc->interp_cur_op)           = jit_code->bytecode;
        for (i = 0; i < jit_code->num_deopts; i++) {
            if (jit_code->deopts[i].idx == osr_index) {
                tc->cur_frame->jit_entry_label = jit_code->labels[jit_code->deopts[i].label];
                break;
            }
        }

        if (i == jit_code->num_deopts)
            MVM_oops(tc, "JIT: Could not find OSR label");
        if (tc->instance->profiling)
            MVM_profiler_log_osr(tc, 1);
    } else {
        *(tc->interp_bytecode_start) = specialized->bytecode;
        *(tc->interp_cur_op)         = specialized->bytecode +
            specialized->deopts[2 * osr_index + 1];
        if (tc->instance->profiling)
            MVM_profiler_log_osr(tc, 0);
    }
    *(tc->interp_reg_base) = tc->cur_frame->work;
}
Exemple #4
0
/* Finalizes OSR. */
void MVM_spesh_osr_finalize(MVMThreadContext *tc) {
    /* Find deopt index using existing deopt table, for entering the updated
     * code later. */
    MVMSpeshCandidate *specialized = tc->cur_frame->spesh_cand;
    MVMint32 osr_index = get_osr_deopt_finalize_index(tc, specialized);
    MVMJitCode *jc;
    /* Finish up the specialization. */
    MVM_spesh_candidate_specialize(tc, tc->cur_frame->static_info, specialized);

    /* Resize work area if needed. */
    if (specialized->num_locals > tc->cur_frame->static_info->body.num_locals) {
        /* Resize work area. */
        MVMRegister *new_work = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa,
            specialized->work_size);
        memcpy(new_work, tc->cur_frame->work,
            tc->cur_frame->static_info->body.num_locals * sizeof(MVMRegister));
        MVM_fixed_size_free(tc, tc->instance->fsa, tc->cur_frame->allocd_work,
            tc->cur_frame->work);
        tc->cur_frame->work = new_work;
        tc->cur_frame->allocd_work = specialized->work_size;
        tc->cur_frame->args = tc->cur_frame->work + specialized->num_locals;
    }

    /* Resize environment if needed. */
    if (specialized->num_lexicals > tc->cur_frame->static_info->body.num_lexicals) {
        MVMRegister *new_env = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa,
            specialized->env_size);
        if (tc->cur_frame->allocd_env) {
            memcpy(new_env, tc->cur_frame->env,
                tc->cur_frame->static_info->body.num_lexicals * sizeof(MVMRegister));
            MVM_fixed_size_free(tc, tc->instance->fsa, tc->cur_frame->allocd_env,
                tc->cur_frame->env);
        }
        tc->cur_frame->env = new_env;
        tc->cur_frame->allocd_env = specialized->env_size;
    }

    /* Sync frame with updates. */
    tc->cur_frame->effective_bytecode    = specialized->bytecode;
    tc->cur_frame->effective_handlers    = specialized->handlers;
    tc->cur_frame->effective_spesh_slots = specialized->spesh_slots;
    tc->cur_frame->spesh_log_slots       = NULL;
    tc->cur_frame->spesh_log_idx         = -1;

    /* Sync interpreter with updates. */
    jc = specialized->jitcode;
    if (jc && jc->num_deopts) {
        MVMint32 i;
        *(tc->interp_bytecode_start)   = specialized->jitcode->bytecode;
        *(tc->interp_cur_op)           = specialized->jitcode->bytecode;
        for (i = 0; i < jc->num_deopts; i++) {
            if (jc->deopts[i].idx == osr_index) {
                tc->cur_frame->jit_entry_label = jc->labels[jc->deopts[i].label];
                break;
            }
        }
        if (i == jc->num_deopts)
            MVM_oops(tc, "JIT: Could not find OSR label");
        if (tc->instance->profiling)
            MVM_profiler_log_osr(tc, 1);
    } else {
        *(tc->interp_bytecode_start) = specialized->bytecode;
        *(tc->interp_cur_op)         = specialized->bytecode +
            specialized->deopts[2 * osr_index + 1];
        if (tc->instance->profiling)
            MVM_profiler_log_osr(tc, 0);
    }
    *(tc->interp_reg_base) = tc->cur_frame->work;

    /* Tweak frame invocation count so future invocations will use the code
     * produced by OSR. */
    tc->cur_frame->static_info->body.invocations +=
        tc->cur_frame->static_info->body.spesh_threshold;
}