/home/travis/build/MoarVM/MoarVM/src/jit/compile.c
Line | Count | Source (jump to first uncovered line) |
1 | | #include "moar.h" |
2 | | #include "dasm_proto.h" |
3 | | #include "platform/mmap.h" |
4 | | #include "emit.h" |
5 | | |
6 | 20.4k | #define COPY_ARRAY(a, n, t) memcpy(MVM_malloc(n * sizeof(t)), a, n * sizeof(t)) |
7 | | |
8 | | |
9 | | static const MVMuint16 MAGIC_BYTECODE[] = { MVM_OP_sp_jit_enter, 0 }; |
10 | | |
11 | 12.3k | MVMJitCode * MVM_jit_compile_graph(MVMThreadContext *tc, MVMJitGraph *jg) { |
12 | 12.3k | dasm_State *state; |
13 | 12.3k | char * memory; |
14 | 12.3k | size_t codesize; |
15 | 12.3k | /* Space for globals */ |
16 | 12.3k | MVMint32 num_globals = MVM_jit_num_globals(); |
17 | 12.3k | void ** dasm_globals = MVM_malloc(num_globals * sizeof(void*)); |
18 | 12.3k | MVMJitNode * node = jg->first_node; |
19 | 12.3k | MVMJitCode * code; |
20 | 12.3k | MVMint32 i; |
21 | 12.3k | |
22 | 12.3k | MVM_jit_log(tc, "Starting compilation\n"); |
23 | 12.3k | |
24 | 12.3k | /* setup dasm (data and code section) */ |
25 | 12.3k | dasm_init(&state, 2); |
26 | 12.3k | dasm_setupglobal(&state, dasm_globals, num_globals); |
27 | 12.3k | dasm_setup(&state, MVM_jit_actions()); |
28 | 12.3k | dasm_growpc(&state, jg->num_labels); |
29 | 12.3k | |
30 | 12.3k | /* generate code */ |
31 | 12.3k | MVM_jit_emit_prologue(tc, jg, &state); |
32 | 1.00M | while (node) { |
33 | 991k | switch(node->type) { |
34 | 171k | case MVM_JIT_NODE_LABEL: |
35 | 171k | MVM_jit_emit_label(tc, jg, &node->u.label, &state); |
36 | 171k | break; |
37 | 350k | case MVM_JIT_NODE_PRIMITIVE: |
38 | 350k | MVM_jit_emit_primitive(tc, jg, &node->u.prim, &state); |
39 | 350k | break; |
40 | 91.8k | case MVM_JIT_NODE_BRANCH: |
41 | 91.8k | MVM_jit_emit_branch(tc, jg, &node->u.branch, &state); |
42 | 91.8k | break; |
43 | 117k | case MVM_JIT_NODE_CALL_C: |
44 | 117k | MVM_jit_emit_call_c(tc, jg, &node->u.call, &state); |
45 | 117k | break; |
46 | 15.0k | case MVM_JIT_NODE_GUARD: |
47 | 15.0k | MVM_jit_emit_guard(tc, jg, &node->u.guard, &state); |
48 | 15.0k | break; |
49 | 16.3k | case MVM_JIT_NODE_INVOKE: |
50 | 16.3k | MVM_jit_emit_invoke(tc, jg, &node->u.invoke, &state); |
51 | 16.3k | break; |
52 | 406 | case MVM_JIT_NODE_JUMPLIST: |
53 | 406 | MVM_jit_emit_jumplist(tc, jg, &node->u.jumplist, &state); |
54 | 406 | break; |
55 | 228k | case MVM_JIT_NODE_CONTROL: |
56 | 228k | MVM_jit_emit_control(tc, jg, &node->u.control, &state); |
57 | 228k | break; |
58 | 0 | case MVM_JIT_NODE_DATA: |
59 | 0 | MVM_jit_emit_data(tc, jg, &node->u.data, &state); |
60 | 0 | break; |
61 | 991k | } |
62 | 991k | node = node->next; |
63 | 991k | } |
64 | 12.3k | MVM_jit_emit_epilogue(tc, jg, &state); |
65 | 12.3k | |
66 | 12.3k | /* compile the function */ |
67 | 12.3k | dasm_link(&state, &codesize); |
68 | 12.3k | memory = MVM_platform_alloc_pages(codesize, MVM_PAGE_READ|MVM_PAGE_WRITE); |
69 | 12.3k | dasm_encode(&state, memory); |
70 | 12.3k | /* set memory readable + executable */ |
71 | 12.3k | MVM_platform_set_page_mode(memory, codesize, MVM_PAGE_READ|MVM_PAGE_EXEC); |
72 | 12.3k | |
73 | 12.3k | |
74 | 12.3k | MVM_jit_log(tc, "Bytecode size: %"MVM_PRSz"\n", codesize); |
75 | 12.3k | /* Create code segment */ |
76 | 12.3k | code = MVM_malloc(sizeof(MVMJitCode)); |
77 | 12.3k | code->func_ptr = (MVMJitFunc)memory; |
78 | 12.3k | code->size = codesize; |
79 | 12.3k | code->bytecode = (MVMuint8*)MAGIC_BYTECODE; |
80 | 12.3k | code->sf = jg->sg->sf; |
81 | 12.3k | |
82 | 12.3k | /* Get the basic block labels */ |
83 | 12.3k | code->num_labels = jg->num_labels; |
84 | 12.3k | code->labels = MVM_malloc(sizeof(void*) * code->num_labels); |
85 | 177k | for (i = 0; i < code->num_labels; i++) { |
86 | 164k | MVMint32 offset = dasm_getpclabel(&state, i); |
87 | 164k | if (offset < 0) |
88 | 0 | MVM_jit_log(tc, "Got negative offset for dynamic label %d\n", i); |
89 | 164k | code->labels[i] = memory + offset; |
90 | 164k | } |
91 | 12.3k | |
92 | 12.3k | /* Copy the deopts, inlines, and handlers. Because these use the label index |
93 | 12.3k | * rather than the direct pointer, no fixup is necessary */ |
94 | 12.3k | code->num_bbs = jg->num_bbs; |
95 | 12.3k | code->bb_labels = COPY_ARRAY(jg->bb_labels, jg->num_bbs, MVMint32); |
96 | 12.3k | |
97 | 12.3k | code->num_deopts = jg->num_deopts; |
98 | 5.16k | code->deopts = code->num_deopts ? COPY_ARRAY(jg->deopts, jg->num_deopts, MVMJitDeopt) : NULL; |
99 | 12.3k | code->num_handlers = jg->num_handlers; |
100 | 788 | code->handlers = code->num_handlers ? COPY_ARRAY(jg->handlers, jg->num_handlers, MVMJitHandler) : NULL; |
101 | 12.3k | code->num_inlines = jg->num_inlines; |
102 | 2.16k | code->inlines = code->num_inlines ? COPY_ARRAY(jg->inlines, jg->num_inlines, MVMJitInline) : NULL; |
103 | 12.3k | |
104 | 12.3k | /* clear up the assembler */ |
105 | 12.3k | dasm_free(&state); |
106 | 12.3k | MVM_free(dasm_globals); |
107 | 12.3k | |
108 | 12.3k | code->seq_nr = MVM_incr(&tc->instance->jit_seq_nr); |
109 | 12.3k | |
110 | 12.3k | if (tc->instance->jit_bytecode_dir) { |
111 | 0 | MVM_jit_log_bytecode(tc, code); |
112 | 0 | } |
113 | 12.3k | if (tc->instance->jit_log_fh) |
114 | 0 | fflush(tc->instance->jit_log_fh); |
115 | 12.3k | return code; |
116 | 12.3k | } |
117 | | |
118 | 0 | void MVM_jit_destroy_code(MVMThreadContext *tc, MVMJitCode *code) { |
119 | 0 | MVM_platform_free_pages(code->func_ptr, code->size); |
120 | 0 | MVM_free(code->labels); |
121 | 0 | MVM_free(code->bb_labels); |
122 | 0 | MVM_free(code->deopts); |
123 | 0 | MVM_free(code->handlers); |
124 | 0 | MVM_free(code->inlines); |
125 | 0 | MVM_free(code); |
126 | 0 | } |
127 | | |
128 | | /* Returns 1 if we should return from the frame, the function, 0 otherwise */ |
129 | | MVMint32 MVM_jit_enter_code(MVMThreadContext *tc, MVMCompUnit *cu, |
130 | 10.0M | MVMJitCode *code) { |
131 | 10.0M | /* The actual JIT code returns 0 if it went through to the exit */ |
132 | 10.0M | MVMint32 ctrl; |
133 | 10.0M | void *label = tc->cur_frame->jit_entry_label; |
134 | 10.0M | if (label < (void*)code->func_ptr || (char*)label > (((char*)code->func_ptr) + code->size)) |
135 | 0 | MVM_oops(tc, "JIT entry label out of range for code!\n" |
136 | 0 | "(label %p, func_ptr %p, code size %lui, offset %li, frame_nr %i, seq nr %i)", |
137 | 0 | label, code->func_ptr, code->size, ((char*)label) - ((char*)code->func_ptr), |
138 | 0 | tc->cur_frame->sequence_nr, code->seq_nr); |
139 | 10.0M | ctrl = code->func_ptr(tc, cu, label); |
140 | 6.58M | return ctrl ? 0 : 1; |
141 | 10.0M | } |