Coverage Report

Created: 2018-07-03 15:31

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