Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/6model/reprs/MVMCallCapture.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
/* This representation's function pointer table. */
4
static const MVMREPROps MVMCallCapture_this_repr;
5
6
/* Creates a new type object of this representation, and associates it with
7
 * the given HOW. Also sets the invocation protocol handler in the STable. */
8
130
static MVMObject * type_object_for(MVMThreadContext *tc, MVMObject *HOW) {
9
130
    MVMSTable *st = MVM_gc_allocate_stable(tc, &MVMCallCapture_this_repr, HOW);
10
130
11
130
    MVMROOT(tc, st, {
12
130
        MVMObject *obj = MVM_gc_allocate_type_object(tc, st);
13
130
        MVM_ASSIGN_REF(tc, &(st->header), st->WHAT, obj);
14
130
        st->size = sizeof(MVMCallCapture);
15
130
    });
16
130
17
130
    return st->WHAT;
18
130
}
19
20
/* Copies the body of one object to another. */
21
1
static void copy_to(MVMThreadContext *tc, MVMSTable *st, void *src, MVMObject *dest_root, void *dest) {
22
1
    MVMCallCaptureBody *src_body  = (MVMCallCaptureBody *)src;
23
1
    MVMCallCaptureBody *dest_body = (MVMCallCaptureBody *)dest;
24
1
25
1
    MVMuint32 arg_size = src_body->apc->arg_count * sizeof(MVMRegister);
26
1
    MVMRegister *args = MVM_malloc(arg_size);
27
1
    memcpy(args, src_body->apc->args, arg_size);
28
1
29
1
    dest_body->apc = (MVMArgProcContext *)MVM_calloc(1, sizeof(MVMArgProcContext));
30
1
    dest_body->mode = MVM_CALL_CAPTURE_MODE_SAVE;
31
1
32
1
    if (src_body->owns_callsite) {
33
0
        dest_body->owns_callsite = 1;
34
0
        dest_body->effective_callsite = MVM_args_copy_callsite(tc, src_body->apc);
35
0
    }
36
1
    else {
37
1
        dest_body->owns_callsite = 0;
38
1
        dest_body->effective_callsite = src_body->effective_callsite;
39
1
    }
40
1
    MVM_args_proc_init(tc, dest_body->apc, dest_body->effective_callsite, args);
41
1
}
42
43
/* Adds held objects to the GC worklist. */
44
182
static void gc_mark(MVMThreadContext *tc, MVMSTable *st, void *data, MVMGCWorklist *worklist) {
45
182
    /* Only need to worry about the SAVE case, as the USE case will be marked by
46
182
     * the frame holding the args being marked. */
47
182
    MVMCallCaptureBody *body = (MVMCallCaptureBody *)data;
48
182
    if (body->mode == MVM_CALL_CAPTURE_MODE_SAVE) {
49
182
        MVMArgProcContext *ctx = body->apc;
50
182
        MVMuint8  *flag_map = ctx->arg_flags ? ctx->arg_flags : ctx->callsite->arg_flags;
51
182
        MVMuint16  count = ctx->arg_count;
52
182
        MVMuint16  i, flag;
53
564
        for (i = 0, flag = 0; i < count; i++, flag++) {
54
382
            if (flag_map[flag] & MVM_CALLSITE_ARG_NAMED) {
55
18
                /* Current position is name, then next is value. */
56
18
                MVM_gc_worklist_add(tc, worklist, &ctx->args[i].s);
57
18
                i++;
58
18
            }
59
382
            if (flag_map[flag] & MVM_CALLSITE_ARG_STR || flag_map[flag] & MVM_CALLSITE_ARG_OBJ)
60
382
                MVM_gc_worklist_add(tc, worklist, &ctx->args[i].o);
61
382
        }
62
182
    }
63
0
    else {
64
0
        MVM_gc_worklist_add(tc, worklist, &(body->use_mode_frame));
65
0
    }
66
182
}
67
68
/* Called by the VM in order to free memory associated with this object. */
69
2.96k
static void gc_free(MVMThreadContext *tc, MVMObject *obj) {
70
2.96k
    MVMCallCapture *ctx = (MVMCallCapture *)obj;
71
2.96k
    if (ctx->body.apc && ctx->body.effective_callsite != ctx->body.apc->callsite) {
72
0
        MVM_free(ctx->body.effective_callsite->arg_flags);
73
0
        MVM_free(ctx->body.effective_callsite);
74
0
    }
75
2.96k
    else if (ctx->body.owns_callsite) {
76
0
        MVM_free(ctx->body.effective_callsite->arg_flags);
77
0
        MVM_free(ctx->body.effective_callsite);
78
0
    }
79
2.96k
    if (ctx->body.mode == MVM_CALL_CAPTURE_MODE_SAVE) {
80
2.96k
        /* We made our own copy of the args buffer and processing context, so
81
2.96k
         * free them both. */
82
2.96k
        if (ctx->body.apc) {
83
2.96k
            if (ctx->body.apc->named_used) {
84
1.34k
                MVM_fixed_size_free(tc, tc->instance->fsa,
85
1.34k
                    ctx->body.apc->named_used_size,
86
1.34k
                    ctx->body.apc->named_used);
87
1.34k
                ctx->body.apc->named_used = NULL;
88
1.34k
            }
89
2.96k
            MVM_free(ctx->body.apc->args);
90
2.96k
            MVM_free(ctx->body.apc);
91
2.96k
        }
92
2.96k
    }
93
2.96k
}
94
95
96
static const MVMStorageSpec storage_spec = {
97
    MVM_STORAGE_SPEC_REFERENCE, /* inlineable */
98
    0,                          /* bits */
99
    0,                          /* align */
100
    MVM_STORAGE_SPEC_BP_NONE,   /* boxed_primitive */
101
    0,                          /* can_box */
102
    0,                          /* is_unsigned */
103
};
104
105
/* Gets the storage specification for this representation. */
106
0
static const MVMStorageSpec * get_storage_spec(MVMThreadContext *tc, MVMSTable *st) {
107
0
    return &storage_spec;
108
0
}
109
110
/* Compose the representation. */
111
0
static void compose(MVMThreadContext *tc, MVMSTable *st, MVMObject *info) {
112
0
    /* Nothing to do for this REPR. */
113
0
}
114
115
/* Initializes the representation. */
116
130
const MVMREPROps * MVMCallCapture_initialize(MVMThreadContext *tc) {
117
130
    return &MVMCallCapture_this_repr;
118
130
}
119
120
static const MVMREPROps MVMCallCapture_this_repr = {
121
    type_object_for,
122
    MVM_gc_allocate_object,
123
    NULL, /* initialize */
124
    copy_to,
125
    MVM_REPR_DEFAULT_ATTR_FUNCS,
126
    MVM_REPR_DEFAULT_BOX_FUNCS,
127
    MVM_REPR_DEFAULT_POS_FUNCS,
128
    MVM_REPR_DEFAULT_ASS_FUNCS,
129
    MVM_REPR_DEFAULT_ELEMS,
130
    get_storage_spec,
131
    NULL, /* change_type */
132
    NULL, /* serialize */
133
    NULL, /* deserialize */
134
    NULL, /* serialize_repr_data */
135
    NULL, /* deserialize_repr_data */
136
    NULL, /* deserialize_stable_size */
137
    gc_mark,
138
    gc_free,
139
    NULL, /* gc_cleanup */
140
    NULL, /* gc_mark_repr_data */
141
    NULL, /* gc_free_repr_data */
142
    compose,
143
    NULL, /* spesh */
144
    "MVMCallCapture", /* name */
145
    MVM_REPR_ID_MVMCallCapture,
146
    NULL, /* unmanaged_size */
147
    NULL, /* describe_refs */
148
};
149
150
/* This function was only introduced for the benefit of the JIT. */
151
0
MVMint64 MVM_capture_pos_primspec(MVMThreadContext *tc, MVMObject *obj, MVMint64 i) {
152
0
    if (IS_CONCRETE(obj) && REPR(obj)->ID == MVM_REPR_ID_MVMCallCapture) {
153
0
        MVMCallCapture *cc = (MVMCallCapture *)obj;
154
0
        if (i >= 0 && i < cc->body.apc->num_pos) {
155
0
            MVMCallsiteEntry *arg_flags = cc->body.apc->arg_flags
156
0
                ? cc->body.apc->arg_flags
157
0
                : cc->body.apc->callsite->arg_flags;
158
0
            switch (arg_flags[i] & MVM_CALLSITE_ARG_MASK) {
159
0
                case MVM_CALLSITE_ARG_INT:
160
0
                    return MVM_STORAGE_SPEC_BP_INT;
161
0
                case MVM_CALLSITE_ARG_NUM:
162
0
                    return MVM_STORAGE_SPEC_BP_NUM;
163
0
                case MVM_CALLSITE_ARG_STR:
164
0
                    return MVM_STORAGE_SPEC_BP_STR;
165
0
                default:
166
0
                    return MVM_STORAGE_SPEC_BP_NONE;
167
0
            }
168
0
        }
169
0
        else {
170
0
            MVM_exception_throw_adhoc(tc,
171
0
                "Bad argument index given to captureposprimspec");
172
0
        }
173
0
    }
174
0
    else {
175
0
        MVM_exception_throw_adhoc(tc, "captureposprimspec needs a MVMCallCapture");
176
0
    }
177
0
}