Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/spesh/osr.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
/* Locates deopt index matching OSR point. */
4
149
static MVMint32 get_osr_deopt_index(MVMThreadContext *tc, MVMSpeshCandidate *cand) {
5
149
    /* Calculate offset. */
6
149
    MVMint32 offset = (*(tc->interp_cur_op) - *(tc->interp_bytecode_start));
7
149
8
149
    /* Locate it in the deopt table. */
9
149
    MVMint32 i;
10
1.62k
    for (i = 0; i < cand->num_deopts; i++)
11
1.62k
        if (cand->deopts[2 * i] == offset)
12
149
            return i;
13
149
14
149
    /* If we couldn't locate it, something is really very wrong. */
15
0
    MVM_oops(tc, "Spesh: get_osr_deopt_index failed");
16
0
}
17
18
/* Locates deopt index matching OSR finalize point. */
19
148
static MVMint32 get_osr_deopt_finalize_index(MVMThreadContext *tc, MVMSpeshCandidate *cand) {
20
148
    /* Calculate offset. */
21
148
    MVMint32 offset = ((*(tc->interp_cur_op) - *(tc->interp_bytecode_start))) - 2;
22
148
23
148
    /* Locate it in the deopt table. */
24
148
    MVMint32 i;
25
1.49k
    for (i = 0; i < cand->num_deopts; i++)
26
1.49k
        if (cand->deopts[2 * i + 1] == offset)
27
148
            return i;
28
148
29
148
    /* If we couldn't locate it, something is really very wrong. */
30
0
    MVM_oops(tc, "Spesh: get_osr_deopt_finalize_index failed");
31
0
}
32
33
/* Called to start OSR. Switches us over to logging runs of spesh'd code, to
34
 * collect extra type info. */
35
161
void MVM_spesh_osr(MVMThreadContext *tc) {
36
161
    MVMSpeshCandidate *specialized;
37
161
    MVMint32 osr_index;
38
161
39
161
    /* Check OSR is enabled. */
40
161
    if (!tc->instance->spesh_osr_enabled)
41
0
        return;
42
161
43
161
    /* Ensure that we are in a position to specialize. */
44
161
    if (!tc->cur_frame->caller)
45
0
        return;
46
161
    if (!tc->cur_frame->params.callsite->is_interned)
47
10
        return;
48
151
    if (tc->cur_frame->static_info->body.num_spesh_candidates == MVM_SPESH_LIMIT)
49
2
        return;
50
151
51
151
    /* Produce logging spesh candidate. */
52
149
    specialized = MVM_spesh_candidate_setup(tc, tc->cur_frame->static_info,
53
149
        tc->cur_frame->params.callsite, tc->cur_frame->params.args, 1);
54
149
    if (specialized) {
55
149
        /* Set up frame to point to specialized logging code. */
56
149
        tc->cur_frame->effective_bytecode    = specialized->bytecode;
57
149
        tc->cur_frame->effective_handlers    = specialized->handlers;
58
149
        tc->cur_frame->effective_spesh_slots = specialized->spesh_slots;
59
149
        tc->cur_frame->spesh_log_slots       = specialized->log_slots;
60
149
        tc->cur_frame->spesh_cand            = specialized;
61
149
        tc->cur_frame->spesh_log_idx         = 0;
62
149
        specialized->log_enter_idx           = 1;
63
149
64
149
        /* Work out deopt index that applies, and move interpreter into the
65
149
         * logging version of the code. */
66
149
        osr_index = get_osr_deopt_index(tc, specialized);
67
149
        *(tc->interp_bytecode_start) = specialized->bytecode;
68
149
        *(tc->interp_cur_op)         = specialized->bytecode +
69
149
                                       specialized->deopts[2 * osr_index + 1] +
70
149
                                       2; /* Pass over sp_osrfianlize this first time */;
71
149
    }
72
149
}
73
74
/* Finalizes OSR. */
75
148
void MVM_spesh_osr_finalize(MVMThreadContext *tc) {
76
148
    /* Find deopt index using existing deopt table, for entering the updated
77
148
     * code later. */
78
148
    MVMSpeshCandidate *specialized = tc->cur_frame->spesh_cand;
79
148
    MVMint32 osr_index = get_osr_deopt_finalize_index(tc, specialized);
80
148
    MVMJitCode *jc;
81
148
    /* Finish up the specialization. */
82
148
    MVM_spesh_candidate_specialize(tc, tc->cur_frame->static_info, specialized);
83
148
84
148
    /* Resize work area if needed. */
85
148
    if (specialized->num_locals > tc->cur_frame->static_info->body.num_locals) {
86
136
        /* Resize work area. */
87
136
        MVMRegister *new_work = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa,
88
136
            specialized->work_size);
89
136
        memcpy(new_work, tc->cur_frame->work,
90
136
            tc->cur_frame->static_info->body.num_locals * sizeof(MVMRegister));
91
136
        MVM_fixed_size_free(tc, tc->instance->fsa, tc->cur_frame->allocd_work,
92
136
            tc->cur_frame->work);
93
136
        tc->cur_frame->work = new_work;
94
136
        tc->cur_frame->allocd_work = specialized->work_size;
95
136
        tc->cur_frame->args = tc->cur_frame->work + specialized->num_locals;
96
136
    }
97
148
98
148
    /* Resize environment if needed. */
99
148
    if (specialized->num_lexicals > tc->cur_frame->static_info->body.num_lexicals) {
100
0
        MVMRegister *new_env = MVM_fixed_size_alloc_zeroed(tc, tc->instance->fsa,
101
0
            specialized->env_size);
102
0
        if (tc->cur_frame->allocd_env) {
103
0
            memcpy(new_env, tc->cur_frame->env,
104
0
                tc->cur_frame->static_info->body.num_lexicals * sizeof(MVMRegister));
105
0
            MVM_fixed_size_free(tc, tc->instance->fsa, tc->cur_frame->allocd_env,
106
0
                tc->cur_frame->env);
107
0
        }
108
0
        tc->cur_frame->env = new_env;
109
0
        tc->cur_frame->allocd_env = specialized->env_size;
110
0
    }
111
148
112
148
    /* Sync frame with updates. */
113
148
    tc->cur_frame->effective_bytecode    = specialized->bytecode;
114
148
    tc->cur_frame->effective_handlers    = specialized->handlers;
115
148
    tc->cur_frame->effective_spesh_slots = specialized->spesh_slots;
116
148
    tc->cur_frame->spesh_log_slots       = NULL;
117
148
    tc->cur_frame->spesh_log_idx         = -1;
118
148
119
148
    /* Sync interpreter with updates. */
120
148
    jc = specialized->jitcode;
121
148
    if (jc && jc->num_deopts) {
122
15
        MVMint32 i;
123
15
        *(tc->interp_bytecode_start)   = specialized->jitcode->bytecode;
124
15
        *(tc->interp_cur_op)           = specialized->jitcode->bytecode;
125
17
        for (i = 0; i < jc->num_deopts; i++) {
126
17
            if (jc->deopts[i].idx == osr_index) {
127
15
                tc->cur_frame->jit_entry_label = jc->labels[jc->deopts[i].label];
128
15
                break;
129
15
            }
130
17
        }
131
15
        if (i == jc->num_deopts)
132
0
            MVM_oops(tc, "JIT: Could not find OSR label");
133
15
        if (tc->instance->profiling)
134
0
            MVM_profiler_log_osr(tc, 1);
135
133
    } else {
136
133
        *(tc->interp_bytecode_start) = specialized->bytecode;
137
133
        *(tc->interp_cur_op)         = specialized->bytecode +
138
133
            specialized->deopts[2 * osr_index + 1];
139
133
        if (tc->instance->profiling)
140
0
            MVM_profiler_log_osr(tc, 0);
141
133
    }
142
148
    *(tc->interp_reg_base) = tc->cur_frame->work;
143
148
144
148
    /* Tweak frame invocation count so future invocations will use the code
145
148
     * produced by OSR. */
146
148
    tc->cur_frame->static_info->body.invocations +=
147
148
        tc->cur_frame->static_info->body.spesh_threshold;
148
148
}
149