Coverage Report

Created: 2017-04-15 07:07

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