Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/core/loadbytecode.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
/* Handles loading of bytecode, including triggering the deserialize and load
4
 * special frames. Takes place in two steps, with a callback between them which
5
 * is triggered by the special_return mechanism. */
6
static void run_load(MVMThreadContext *tc, void *sr_data);
7
0
static void mark_sr_data(MVMThreadContext *tc, MVMFrame *frame, MVMGCWorklist *worklist) {
8
0
    MVM_gc_worklist_add(tc, worklist, &frame->special_return_data);
9
0
}
10
1.30k
static void run_comp_unit(MVMThreadContext *tc, MVMCompUnit *cu) {
11
1.30k
    /* If there's a deserialization frame, need to run that. */
12
1.30k
    if (cu->body.deserialize_frame) {
13
1.30k
        /* Set up special return to delegate to running the load frame,
14
1.30k
         * if any. */
15
1.30k
        tc->cur_frame->return_value             = NULL;
16
1.30k
        tc->cur_frame->return_type              = MVM_RETURN_VOID;
17
1.30k
        tc->cur_frame->special_return           = run_load;
18
1.30k
        tc->cur_frame->special_return_data      = cu;
19
1.30k
        tc->cur_frame->mark_special_return_data = mark_sr_data;
20
1.30k
21
1.30k
        /* Invoke the deserialization frame and return to the runloop. */
22
1.30k
        MVM_frame_invoke(tc, cu->body.deserialize_frame, MVM_callsite_get_common(tc, MVM_CALLSITE_ID_NULL_ARGS),
23
1.30k
            NULL, NULL, NULL, -1);
24
1.30k
    }
25
0
    else {
26
0
        /* No deserialize frame, so do load frame instead. */
27
0
        run_load(tc, cu);
28
0
    }
29
1.30k
}
30
0
void MVM_load_bytecode_buffer(MVMThreadContext *tc, MVMObject *buf) {
31
0
    MVMCompUnit *cu;
32
0
    MVMuint8    *data_start;
33
0
    MVMuint32    data_size;
34
0
35
0
    /* Ensure the source is in the correct form. */
36
0
    if (
37
0
        !IS_CONCRETE(buf)
38
0
        || REPR(buf)->ID != MVM_REPR_ID_VMArray
39
0
        || (
40
0
               ((MVMArrayREPRData *)STABLE(buf)->REPR_data)->slot_type != MVM_ARRAY_U8
41
0
            && ((MVMArrayREPRData *)STABLE(buf)->REPR_data)->slot_type != MVM_ARRAY_I8
42
0
        )
43
0
    )
44
0
        MVM_exception_throw_adhoc(tc, "loadbytecodebuffer requires a native int8 or uint8 array to read from");
45
0
46
0
    /* MVMCompUnit expects the data to be non-GC managed as it usually comes straight from a file */
47
0
    data_size = ((MVMArray *)buf)->body.elems;
48
0
    data_start = MVM_malloc(data_size);
49
0
    memcpy(data_start, (MVMuint8 *)(((MVMArray *)buf)->body.slots.i8 + ((MVMArray *)buf)->body.start), data_size);
50
0
51
0
    cu = MVM_cu_from_bytes(tc, data_start, data_size);
52
0
    run_comp_unit(tc, cu);
53
0
}
54
4.29k
void MVM_load_bytecode(MVMThreadContext *tc, MVMString *filename) {
55
4.29k
    MVMCompUnit *cu;
56
4.29k
    MVMLoadedCompUnitName *loaded_name;
57
4.29k
58
4.29k
    /* Work out actual filename to use, taking --libpath into account. */
59
4.29k
    filename = MVM_file_in_libpath(tc, filename);
60
4.29k
61
4.29k
    /* See if we already loaded this. */
62
4.29k
    uv_mutex_lock(&tc->instance->mutex_loaded_compunits);
63
4.29k
    MVM_tc_set_ex_release_mutex(tc, &tc->instance->mutex_loaded_compunits);
64
4.29k
    MVM_HASH_GET(tc, tc->instance->loaded_compunits, filename, loaded_name);
65
4.29k
    if (loaded_name) {
66
2.99k
        /* already loaded */
67
2.99k
        goto LEAVE;
68
2.99k
    }
69
4.29k
70
4.29k
    /* Otherwise, load from disk. */
71
1.30k
    MVMROOT(tc, filename, {
72
1.30k
        char *c_filename = MVM_string_utf8_c8_encode_C_string(tc, filename);
73
1.30k
        /* XXX any exception from MVM_cu_map_from_file needs to be handled
74
1.30k
         *     and c_filename needs to be freed */
75
1.30k
        cu = MVM_cu_map_from_file(tc, c_filename);
76
1.30k
        MVM_free(c_filename);
77
1.30k
        cu->body.filename = filename;
78
1.30k
79
1.30k
        run_comp_unit(tc, cu);
80
1.30k
81
1.30k
        loaded_name = MVM_calloc(1, sizeof(MVMLoadedCompUnitName));
82
1.30k
        loaded_name->filename = filename;
83
1.30k
        MVM_HASH_BIND(tc, tc->instance->loaded_compunits, filename, loaded_name);
84
1.30k
    });
85
1.30k
86
4.29k
LEAVE:
87
4.29k
    MVM_tc_clear_ex_release_mutex(tc);
88
4.29k
    uv_mutex_unlock(&tc->instance->mutex_loaded_compunits);
89
4.29k
}
90
0
void MVM_load_bytecode_fh(MVMThreadContext *tc, MVMObject *oshandle, MVMString *filename) {
91
0
    MVMCompUnit *cu;
92
0
93
0
    if (REPR(oshandle)->ID != MVM_REPR_ID_MVMOSHandle)
94
0
        MVM_exception_throw_adhoc(tc, "loadbytecodefh requires an object with REPR MVMOSHandle");
95
0
96
0
    MVMROOT(tc, filename, {
97
0
        MVMuint64 pos = MVM_io_tell(tc, oshandle);
98
0
        cu = MVM_cu_map_from_file_handle(tc, MVM_io_fileno(tc, oshandle), pos);
99
0
        cu->body.filename = filename;
100
0
101
0
        run_comp_unit(tc, cu);
102
0
    });
103
0
}
104
105
/* Callback after running deserialize code to run the load code. */
106
1.30k
static void run_load(MVMThreadContext *tc, void *sr_data) {
107
1.30k
    MVMCompUnit *cu = (MVMCompUnit *)sr_data;
108
1.30k
109
1.30k
    /* If there's a load frame, need to run that. If not, we're done. */
110
1.30k
    if (cu->body.load_frame) {
111
1.30k
        /* Make sure the call happens in void context. No special return
112
1.30k
         * handler here; we want to go back to the place that used the
113
1.30k
         * loadbytecode op in the first place. */
114
1.30k
        tc->cur_frame->return_value = NULL;
115
1.30k
        tc->cur_frame->return_type  = MVM_RETURN_VOID;
116
1.30k
117
1.30k
        /* Invoke the load frame and return to the runloop. */
118
1.30k
        MVM_frame_invoke(tc, cu->body.load_frame, MVM_callsite_get_common(tc, MVM_CALLSITE_ID_NULL_ARGS),
119
1.30k
            NULL, NULL, NULL, -1);
120
1.30k
    }
121
1.30k
}