Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/core/callsite.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
/* Checks if two callsiates are equal. */
4
static MVMint32 callsites_equal(MVMThreadContext *tc, MVMCallsite *cs1, MVMCallsite *cs2,
5
1.17M
                                MVMint32 num_flags, MVMint32 num_nameds) {
6
1.17M
    MVMint32 i;
7
1.17M
8
1.17M
    if (num_flags && memcmp(cs1->arg_flags, cs2->arg_flags, num_flags))
9
1.10M
        return 0;
10
1.17M
11
85.3k
    for (i = 0; i < num_nameds; i++)
12
59.1k
        if (!MVM_string_equal(tc, cs1->arg_names[i], cs2->arg_names[i]))
13
43.5k
            return 0;
14
69.8k
15
26.2k
    return 1;
16
69.8k
}
17
18
static MVMCallsite   null_args_callsite = { NULL, 0, 0, 0, 0, 0, 0, 0 };
19
20
static MVMCallsiteEntry obj_arg_flags[] = { MVM_CALLSITE_ARG_OBJ };
21
static MVMCallsite     inv_arg_callsite = { obj_arg_flags, 1, 1, 1, 0, 0, 0, 0 };
22
23
static MVMCallsiteEntry two_obj_arg_flags[] = { MVM_CALLSITE_ARG_OBJ,
24
                                                MVM_CALLSITE_ARG_OBJ };
25
static MVMCallsite    two_args_callsite = { two_obj_arg_flags, 2, 2, 2, 0, 0, 0 };
26
27
static MVMCallsiteEntry mnfe_flags[] = { MVM_CALLSITE_ARG_OBJ,
28
                                         MVM_CALLSITE_ARG_STR };
29
static MVMCallsite     methnotfound_callsite = { mnfe_flags, 2, 2, 2, 0 };
30
31
static MVMCallsiteEntry fm_flags[] = { MVM_CALLSITE_ARG_OBJ,
32
                                       MVM_CALLSITE_ARG_OBJ,
33
                                       MVM_CALLSITE_ARG_STR };
34
static MVMCallsite     findmeth_callsite = { fm_flags, 3, 3, 3, 0 };
35
36
static MVMCallsiteEntry tc_flags[] = { MVM_CALLSITE_ARG_OBJ,
37
                                       MVM_CALLSITE_ARG_OBJ,
38
                                       MVM_CALLSITE_ARG_OBJ };
39
static MVMCallsite     typecheck_callsite = { tc_flags, 3, 3, 3, 0 };
40
41
static MVMCallsiteEntry obj_int_flags[] = { MVM_CALLSITE_ARG_OBJ,
42
                                            MVM_CALLSITE_ARG_INT };
43
static MVMCallsite    obj_int_callsite = { obj_int_flags, 2, 2, 2, 0, 0, 0 };
44
45
static MVMCallsiteEntry obj_num_flags[] = { MVM_CALLSITE_ARG_OBJ,
46
                                            MVM_CALLSITE_ARG_NUM };
47
static MVMCallsite    obj_num_callsite = { obj_num_flags, 2, 2, 2, 0, 0, 0 };
48
49
static MVMCallsiteEntry obj_str_flags[] = { MVM_CALLSITE_ARG_OBJ,
50
                                            MVM_CALLSITE_ARG_STR };
51
static MVMCallsite    obj_str_callsite = { obj_str_flags, 2, 2, 2, 0, 0, 0 };
52
53
static MVMCallsiteEntry int_int_arg_flags[] = { MVM_CALLSITE_ARG_INT, MVM_CALLSITE_ARG_INT };
54
static MVMCallsite     int_int_arg_callsite = { int_int_arg_flags, 2, 2, 2, 0, 0, 0, 0 };
55
56
216k
MVM_PUBLIC MVMCallsite *MVM_callsite_get_common(MVMThreadContext *tc, MVMCommonCallsiteID id) {
57
216k
    switch (id) {
58
4.26k
        case MVM_CALLSITE_ID_NULL_ARGS:
59
4.26k
            return &null_args_callsite;
60
212k
        case MVM_CALLSITE_ID_INV_ARG:
61
212k
            return &inv_arg_callsite;
62
24
        case MVM_CALLSITE_ID_TWO_OBJ:
63
24
            return &two_args_callsite;
64
0
        case MVM_CALLSITE_ID_METH_NOT_FOUND:
65
0
            return &methnotfound_callsite;
66
6
        case MVM_CALLSITE_ID_FIND_METHOD:
67
6
            return &findmeth_callsite;
68
10
        case MVM_CALLSITE_ID_TYPECHECK:
69
10
            return &typecheck_callsite;
70
0
        case MVM_CALLSITE_ID_OBJ_INT:
71
0
            return &obj_int_callsite;
72
0
        case MVM_CALLSITE_ID_OBJ_NUM:
73
0
            return &obj_num_callsite;
74
0
        case MVM_CALLSITE_ID_OBJ_STR:
75
0
            return &obj_str_callsite;
76
0
        case MVM_CALLSITE_ID_INT_INT:
77
0
            return &int_int_arg_callsite;
78
0
        default:
79
0
            MVM_exception_throw_adhoc(tc, "get_common_callsite: id %d unknown", id);
80
216k
    }
81
216k
}
82
83
0
int MVM_callsite_is_common(MVMCallsite *cs) {
84
0
    return cs == &null_args_callsite    ||
85
0
           cs == &inv_arg_callsite      ||
86
0
           cs == &two_args_callsite     ||
87
0
           cs == &methnotfound_callsite ||
88
0
           cs == &findmeth_callsite     ||
89
0
           cs == &typecheck_callsite    ||
90
0
           cs == &obj_int_callsite      ||
91
0
           cs == &obj_num_callsite      ||
92
0
           cs == &obj_str_callsite;
93
0
}
94
95
0
void MVM_callsite_destroy(MVMCallsite *cs) {
96
0
    if (cs->flag_count) {
97
0
        MVM_free(cs->arg_flags);
98
0
    }
99
0
100
0
    if (cs->arg_names) {
101
0
        MVM_free(cs->arg_names);
102
0
    }
103
0
104
0
    if (cs->with_invocant) {
105
0
        MVM_callsite_destroy(cs->with_invocant);
106
0
    }
107
0
108
0
    MVM_free(cs);
109
0
}
110
111
12
MVMCallsite *MVM_callsite_copy(MVMThreadContext *tc, const MVMCallsite *cs) {
112
12
    MVMCallsite *copy = MVM_malloc(sizeof(MVMCallsite));
113
12
114
12
    if (cs->flag_count) {
115
12
        copy->arg_flags =  MVM_malloc(cs->flag_count);
116
12
        memcpy(copy->arg_flags, cs->arg_flags, cs->flag_count);
117
12
    }
118
12
119
12
    if (cs->arg_names) {
120
9
        MVMint32 num_named = MVM_callsite_num_nameds(tc, cs);
121
9
122
9
        copy->arg_names = MVM_malloc(num_named * sizeof(MVMString *));
123
9
        memcpy(copy->arg_names, cs->arg_names, num_named * sizeof(MVMString *));
124
9
    }
125
3
    else {
126
3
        copy->arg_names = NULL;
127
3
    }
128
12
129
12
    if (cs->with_invocant) {
130
0
        copy->with_invocant = MVM_callsite_copy(tc, cs->with_invocant);
131
0
    }
132
12
    else {
133
12
        copy->with_invocant = NULL;
134
12
    }
135
12
136
12
    copy->flag_count = cs->flag_count;
137
12
    copy->arg_count = cs->arg_count;
138
12
    copy->num_pos = cs->num_pos;
139
12
    copy->has_flattening = cs->has_flattening;
140
12
    copy->is_interned = cs->is_interned;
141
12
142
12
    return copy;
143
12
}
144
145
130
void MVM_callsite_initialize_common(MVMThreadContext *tc) {
146
130
    MVMCallsite *ptr;
147
130
148
130
    ptr = &inv_arg_callsite;
149
130
    MVM_callsite_try_intern(tc, &ptr);
150
130
    ptr = &null_args_callsite;
151
130
    MVM_callsite_try_intern(tc, &ptr);
152
130
    ptr = &methnotfound_callsite;
153
130
    MVM_callsite_try_intern(tc, &ptr);
154
130
    ptr = &two_args_callsite;
155
130
    MVM_callsite_try_intern(tc, &ptr);
156
130
    ptr = &findmeth_callsite;
157
130
    MVM_callsite_try_intern(tc, &ptr);
158
130
    ptr = &typecheck_callsite;
159
130
    MVM_callsite_try_intern(tc, &ptr);
160
130
}
161
162
/* Tries to intern the callsite, freeing and updating the one passed in and
163
 * replacing it with an already interned one if we find it. */
164
67.9k
MVM_PUBLIC void MVM_callsite_try_intern(MVMThreadContext *tc, MVMCallsite **cs_ptr) {
165
67.9k
    MVMCallsiteInterns *interns    = tc->instance->callsite_interns;
166
67.9k
    MVMCallsite        *cs         = *cs_ptr;
167
67.9k
    MVMint32            num_flags  = cs->flag_count;
168
67.9k
    MVMint32            num_nameds = MVM_callsite_num_nameds(tc, cs);
169
67.9k
    MVMint32 i, found;
170
67.9k
171
67.9k
    /* Can't intern anything with flattening. */
172
67.9k
    if (cs->has_flattening)
173
6.64k
        return;
174
67.9k
175
67.9k
    /* Also can't intern past the max arity. */
176
61.2k
    if (num_flags >= MVM_INTERN_ARITY_LIMIT)
177
399
        return;
178
61.2k
179
61.2k
    /* Can intern things with nameds, provided we know the names. */
180
60.8k
    if (num_nameds > 0 && !cs->arg_names)
181
0
        return;
182
60.8k
183
60.8k
    /* Obtain mutex protecting interns store. */
184
60.8k
    uv_mutex_lock(&tc->instance->mutex_callsite_interns);
185
60.8k
186
60.8k
    /* Search for a match. */
187
60.8k
    found = 0;
188
1.20M
    for (i = 0; i < interns->num_by_arity[num_flags]; i++) {
189
1.17M
        if (callsites_equal(tc, interns->by_arity[num_flags][i], cs, num_flags, num_nameds)) {
190
26.2k
            /* Got a match! Free the one we were passed and replace it with
191
26.2k
             * the interned one. */
192
26.2k
            if (num_flags)
193
24.6k
                MVM_free(cs->arg_flags);
194
26.2k
            MVM_free(cs->arg_names);
195
26.2k
            MVM_free(cs);
196
26.2k
            *cs_ptr = interns->by_arity[num_flags][i];
197
26.2k
            found = 1;
198
26.2k
            break;
199
26.2k
        }
200
1.17M
    }
201
60.8k
202
60.8k
    /* If it wasn't found, store it for the future. */
203
60.8k
    if (!found) {
204
34.6k
        if (interns->num_by_arity[num_flags] % 8 == 0) {
205
4.82k
            if (interns->num_by_arity[num_flags])
206
3.78k
                interns->by_arity[num_flags] = MVM_realloc(
207
3.78k
                    interns->by_arity[num_flags],
208
3.78k
                    sizeof(MVMCallsite *) * (interns->num_by_arity[num_flags] + 8));
209
4.82k
            else
210
1.04k
                interns->by_arity[num_flags] = MVM_malloc(sizeof(MVMCallsite *) * 8);
211
4.82k
        }
212
34.6k
        interns->by_arity[num_flags][interns->num_by_arity[num_flags]++] = cs;
213
34.6k
        cs->is_interned = 1;
214
34.6k
    }
215
60.8k
216
60.8k
    /* Finally, release mutex. */
217
60.8k
    uv_mutex_unlock(&tc->instance->mutex_callsite_interns);
218
60.8k
}