/
interface.c
95 lines (83 loc) · 3.58 KB
/
interface.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "moar.h"
#include "internal.h"
static void assert_within_region(MVMThreadContext *tc, MVMJitCode *code, void *address) {
#if MVM_JIT_DEBUG
MVMint32 ofs = (char*)address - (char*)code->func_ptr;
if ((0 <= ofs) && (ofs < code->size))
return;
MVM_panic(1, "JIT: address out of range for code!\n"
"(label %p, func_ptr %p, code size %lui, offset %li, frame_nr %i, seq nr %i)",
address, code->func_ptr, code->size, ofs,
tc->cur_frame->sequence_nr, code->seq_nr);
#endif
}
/* Enter the JIT code segment. The label is a continuation point where control
* is resumed after the frame is properly setup. */
void MVM_jit_code_enter(MVMThreadContext *tc, MVMJitCode *code, MVMCompUnit *cu) {
void *label = tc->cur_frame->jit_entry_label;
assert_within_region(tc, code, label);
code->func_ptr(tc, cu, label);
}
void * MVM_jit_code_get_current_position(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame) {
if (tc->cur_frame == frame && tc->jit_return_address != NULL) {
/* currently on C stack */
void *return_address = *tc->jit_return_address;
assert_within_region(tc, code, return_address);
return return_address;
} else {
/* trampolined-out of this frame, so jit_entry_label is correct */
return frame->jit_entry_label;
}
}
void MVM_jit_code_set_current_position(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame, void *position) {
assert_within_region(tc, code, position);
if (tc->cur_frame == frame && tc->jit_return_address != NULL) {
*tc->jit_return_address = position;
} else {
frame->jit_entry_label = position;
}
}
void MVM_jit_code_trampoline(MVMThreadContext *tc) {
if (tc->jit_return_address != NULL) {
MVMJitCode *code = tc->cur_frame->spesh_cand->jitcode;
void *reentry_label = *tc->jit_return_address;
assert_within_region(tc, code, reentry_label);
/* Store our current position */
tc->cur_frame->jit_entry_label = *tc->jit_return_address;
/* Tell currently-active JIT code that we're leaving this frame */
assert_within_region(tc, code, code->exit_label);
*tc->jit_return_address = code->exit_label;
/* And tell further frame handlers that as far as they are concerned,
we're not on the stack anymore */
tc->jit_return_address = NULL;
}
}
MVMuint32 MVM_jit_code_get_active_deopt_idx(MVMThreadContext *tc, MVMJitCode *code, MVMFrame *frame) {
MVMuint32 i;
void *current_position = MVM_jit_code_get_current_position(tc, code, frame);
for (i = 0; i < code->num_deopts; i++) {
if (code->labels[code->deopts[i].label] == current_position) {
break;
}
}
return i;
}
MVMint32 MVM_jit_code_get_active_handlers(MVMThreadContext *tc, MVMJitCode *code, void *current_position, MVMint32 i) {
for (; i < code->num_handlers; i++) {
void *start_label = code->labels[code->handlers[i].start_label];
void *end_label = code->labels[code->handlers[i].end_label];
if (start_label <= current_position && current_position <= end_label) {
break;
}
}
return i;
}
MVMint32 MVM_jit_code_get_active_inlines(MVMThreadContext *tc, MVMJitCode *code, void *current_position, MVMint32 i) {
for (;i < code->num_inlines; i++) {
void *inline_start = code->labels[code->inlines[i].start_label];
void *inline_end = code->labels[code->inlines[i].end_label];
if (inline_start <= current_position && current_position <= inline_end)
break;
}
return i;
}