Coverage Report

Created: 2018-07-03 15:31

/home/travis/build/MoarVM/MoarVM/src/spesh/osr.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
/* Writes to stderr about each OSR that we perform. */
4
#define MVM_LOG_OSR 0
5
6
/* Locates deopt index matching OSR point. */
7
17.7k
static MVMint32 get_osr_deopt_index(MVMThreadContext *tc, MVMSpeshCandidate *cand) {
8
17.7k
    /* Calculate offset. */
9
17.7k
    MVMint32 offset = (*(tc->interp_cur_op) - *(tc->interp_bytecode_start));
10
17.7k
11
17.7k
    /* Locate it in the deopt table. */
12
17.7k
    MVMint32 i;
13
174k
    for (i = 0; i < cand->num_deopts; i++)
14
174k
        if (cand->deopts[2 * i] == offset)
15
17.7k
            return i;
16
17.7k
17
17.7k
    /* If we couldn't locate it, something is really very wrong. */
18
0
    MVM_oops(tc, "Spesh: get_osr_deopt_index failed");
19
0
}
20
21
/* Does the jump into the optimized code. */
22
17.7k
void perform_osr(MVMThreadContext *tc, MVMSpeshCandidate *specialized) {
23
17.7k
    MVMJitCode *jit_code;
24
17.7k
    MVMint32 num_locals;
25
17.7k
    /* Work out the OSR deopt index, to locate the entry point. */
26
17.7k
    MVMint32 osr_index = get_osr_deopt_index(tc, specialized);
27
17.7k
#if MVM_LOG_OSR
28
    fprintf(stderr, "Performing OSR of frame '%s' (cuid: %s) at index %d\n",
29
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.name),
30
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.cuuid),
31
        osr_index);
32
#endif
33
17.7k
34
17.7k
    jit_code = specialized->jitcode;
35
17.7k
    num_locals = jit_code && jit_code->local_types ?
36
17.7k
        jit_code->num_locals : specialized->num_locals;
37
17.7k
38
17.7k
    /* Resize work area if needed. */
39
17.7k
    if (specialized->work_size > tc->cur_frame->allocd_work) {
40
16.9k
        /* Resize work area. */
41
16.9k
        MVMRegister *new_work = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa,
42
16.9k
            specialized->work_size);
43
16.9k
        MVMRegister *new_args = new_work + num_locals;
44
16.9k
        memcpy(new_work, tc->cur_frame->work,
45
16.9k
            tc->cur_frame->static_info->body.num_locals * sizeof(MVMRegister));
46
16.9k
        memcpy(new_args, tc->cur_frame->args,
47
16.9k
            tc->cur_frame->static_info->body.cu->body.max_callsite_size * sizeof(MVMRegister));
48
16.9k
49
16.9k
        MVM_fixed_size_free(tc, tc->instance->fsa, tc->cur_frame->allocd_work,
50
16.9k
            tc->cur_frame->work);
51
16.9k
        tc->cur_frame->work = new_work;
52
16.9k
        tc->cur_frame->allocd_work = specialized->work_size;
53
16.9k
        tc->cur_frame->args = new_args;
54
16.9k
#if MVM_LOG_OSR
55
    fprintf(stderr, "OSR resized work area of frame '%s' (cuid: %s)\n",
56
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.name),
57
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.cuuid));
58
#endif
59
16.9k
    }
60
811
    else if (specialized->work_size > tc->cur_frame->static_info->body.work_size) {
61
809
        size_t keep_bytes = tc->cur_frame->static_info->body.num_locals * sizeof(MVMRegister);
62
809
        size_t to_null = specialized->work_size - keep_bytes;
63
809
        memset((char *)tc->cur_frame->work + keep_bytes, 0, to_null);
64
809
    }
65
17.7k
66
17.7k
    /* Resize environment if needed. */
67
17.7k
    if (specialized->num_lexicals > tc->cur_frame->static_info->body.num_lexicals) {
68
18
        MVMRegister *new_env = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa,
69
18
            specialized->env_size);
70
18
        if (tc->cur_frame->allocd_env) {
71
16
            memcpy(new_env, tc->cur_frame->env,
72
16
                tc->cur_frame->static_info->body.num_lexicals * sizeof(MVMRegister));
73
16
            MVM_fixed_size_free(tc, tc->instance->fsa, tc->cur_frame->allocd_env,
74
16
                tc->cur_frame->env);
75
16
        }
76
18
        tc->cur_frame->env = new_env;
77
18
        tc->cur_frame->allocd_env = specialized->env_size;
78
18
#if MVM_LOG_OSR
79
    fprintf(stderr, "OSR resized environment of frame '%s' (cuid: %s)\n",
80
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.name),
81
        MVM_string_utf8_encode_C_string(tc, tc->cur_frame->static_info->body.cuuid));
82
#endif
83
18
    }
84
17.7k
    else if (specialized->env_size > tc->cur_frame->static_info->body.env_size) {
85
0
        size_t keep_bytes = tc->cur_frame->static_info->body.num_lexicals * sizeof(MVMRegister);
86
0
        size_t to_null = specialized->env_size - keep_bytes;
87
0
        memset((char *)tc->cur_frame->env + keep_bytes, 0, to_null);
88
0
    }
89
17.7k
90
17.7k
    /* Set up frame to point to spesh candidate/slots. */
91
17.7k
    tc->cur_frame->effective_spesh_slots = specialized->spesh_slots;
92
17.7k
    tc->cur_frame->spesh_cand            = specialized;
93
17.7k
94
17.7k
    /* Move into the optimized (and maybe JIT-compiled) code. */
95
17.7k
96
17.7k
    if (jit_code && jit_code->num_deopts) {
97
17.7k
        MVMint32 i;
98
17.7k
        *(tc->interp_bytecode_start)   = jit_code->bytecode;
99
17.7k
        *(tc->interp_cur_op)           = jit_code->bytecode;
100
40.9k
        for (i = 0; i < jit_code->num_deopts; i++) {
101
40.9k
            if (jit_code->deopts[i].idx == osr_index) {
102
17.7k
                tc->cur_frame->jit_entry_label = jit_code->labels[jit_code->deopts[i].label];
103
17.7k
                break;
104
17.7k
            }
105
40.9k
        }
106
17.7k
107
17.7k
        if (i == jit_code->num_deopts)
108
0
            MVM_oops(tc, "JIT: Could not find OSR label");
109
17.7k
        if (tc->instance->profiling)
110
0
            MVM_profiler_log_osr(tc, 1);
111
3
    } else {
112
3
        *(tc->interp_bytecode_start) = specialized->bytecode;
113
3
        *(tc->interp_cur_op)         = specialized->bytecode +
114
3
            specialized->deopts[2 * osr_index + 1];
115
3
        if (tc->instance->profiling)
116
0
            MVM_profiler_log_osr(tc, 0);
117
3
    }
118
17.7k
    *(tc->interp_reg_base) = tc->cur_frame->work;
119
17.7k
}
120
121
/* Polls for an optimization and, when one is produced, jumps into it. */
122
1.09M
void MVM_spesh_osr_poll_for_result(MVMThreadContext *tc) {
123
1.09M
    MVMStaticFrameSpesh *spesh = tc->cur_frame->static_info->body.spesh;
124
1.09M
    MVMint32 num_cands = spesh->body.num_spesh_candidates;
125
1.09M
    MVMint32 seq_nr = tc->cur_frame->sequence_nr;
126
1.09M
    if (seq_nr != tc->osr_hunt_frame_nr || num_cands != tc->osr_hunt_num_spesh_candidates) {
127
416k
        /* Provided OSR is enabled... */
128
416k
        if (tc->instance->spesh_osr_enabled) {
129
416k
            /* Check if there's a candidate available and install it if so. */
130
416k
            MVMFrame *caller = tc->cur_frame->caller;
131
416k
            MVMCallsite *cs = caller
132
416k
                ? caller->cur_args_callsite
133
3
                : MVM_callsite_get_common(tc, MVM_CALLSITE_ID_NULL_ARGS);
134
416k
            MVMint32 ag_result = MVM_spesh_arg_guard_run(tc,
135
416k
                spesh->body.spesh_arg_guard,
136
416k
                (cs && cs->is_interned ? cs : NULL),
137
416k
                (caller ? caller->args : NULL),
138
416k
                NULL);
139
416k
            if (ag_result >= 0)
140
17.7k
                perform_osr(tc, spesh->body.spesh_candidates[ag_result]);
141
416k
        }
142
416k
143
416k
        /* Update state for avoiding checks in the common case. */
144
416k
        tc->osr_hunt_frame_nr = seq_nr;
145
416k
        tc->osr_hunt_num_spesh_candidates = num_cands;
146
416k
    }
147
1.09M
}