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