Coverage Report

Created: 2018-07-03 15:31

/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.38M
                                MVMint32 num_flags, MVMint32 num_nameds) {
6
1.38M
    MVMint32 i;
7
1.38M
8
1.38M
    if (num_flags && memcmp(cs1->arg_flags, cs2->arg_flags, num_flags))
9
1.30M
        return 0;
10
1.38M
11
99.1k
    for (i = 0; i < num_nameds; i++)
12
70.3k
        if (!MVM_string_equal(tc, cs1->arg_names[i], cs2->arg_names[i]))
13
53.5k
            return 0;
14
82.3k
15
28.8k
    return 1;
16
82.3k
}
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
310k
MVM_PUBLIC MVMCallsite *MVM_callsite_get_common(MVMThreadContext *tc, MVMCommonCallsiteID id) {
57
310k
    switch (id) {
58
4.92k
        case MVM_CALLSITE_ID_NULL_ARGS:
59
4.92k
            return &null_args_callsite;
60
305k
        case MVM_CALLSITE_ID_INV_ARG:
61
305k
            return &inv_arg_callsite;
62
29
        case MVM_CALLSITE_ID_TWO_OBJ:
63
29
            return &two_args_callsite;
64
2
        case MVM_CALLSITE_ID_METH_NOT_FOUND:
65
2
            return &methnotfound_callsite;
66
8
        case MVM_CALLSITE_ID_FIND_METHOD:
67
8
            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
2
        case MVM_CALLSITE_ID_INT_INT:
77
2
            return &int_int_arg_callsite;
78
0
        default:
79
0
            MVM_exception_throw_adhoc(tc, "get_common_callsite: id %d unknown", id);
80
310k
    }
81
310k
}
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
50
MVMCallsite *MVM_callsite_copy(MVMThreadContext *tc, const MVMCallsite *cs) {
112
50
    MVMCallsite *copy = MVM_malloc(sizeof(MVMCallsite));
113
50
114
50
    if (cs->flag_count) {
115
50
        copy->arg_flags =  MVM_malloc(cs->flag_count);
116
50
        memcpy(copy->arg_flags, cs->arg_flags, cs->flag_count);
117
50
    }
118
50
119
50
    if (cs->arg_names) {
120
28
        MVMint32 num_named = MVM_callsite_num_nameds(tc, cs);
121
28
122
28
        copy->arg_names = MVM_malloc(num_named * sizeof(MVMString *));
123
28
        memcpy(copy->arg_names, cs->arg_names, num_named * sizeof(MVMString *));
124
28
    }
125
22
    else {
126
22
        copy->arg_names = NULL;
127
22
    }
128
50
129
50
    if (cs->with_invocant) {
130
0
        copy->with_invocant = MVM_callsite_copy(tc, cs->with_invocant);
131
0
    }
132
50
    else {
133
50
        copy->with_invocant = NULL;
134
50
    }
135
50
136
50
    copy->flag_count = cs->flag_count;
137
50
    copy->arg_count = cs->arg_count;
138
50
    copy->num_pos = cs->num_pos;
139
50
    copy->has_flattening = cs->has_flattening;
140
50
    copy->is_interned = cs->is_interned;
141
50
142
50
    return copy;
143
50
}
144
145
144
void MVM_callsite_initialize_common(MVMThreadContext *tc) {
146
144
    MVMCallsite *ptr;
147
144
148
144
    ptr = &inv_arg_callsite;
149
144
    MVM_callsite_try_intern(tc, &ptr);
150
144
    ptr = &null_args_callsite;
151
144
    MVM_callsite_try_intern(tc, &ptr);
152
144
    ptr = &methnotfound_callsite;
153
144
    MVM_callsite_try_intern(tc, &ptr);
154
144
    ptr = &two_args_callsite;
155
144
    MVM_callsite_try_intern(tc, &ptr);
156
144
    ptr = &findmeth_callsite;
157
144
    MVM_callsite_try_intern(tc, &ptr);
158
144
    ptr = &typecheck_callsite;
159
144
    MVM_callsite_try_intern(tc, &ptr);
160
144
}
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
76.8k
MVM_PUBLIC void MVM_callsite_try_intern(MVMThreadContext *tc, MVMCallsite **cs_ptr) {
165
76.8k
    MVMCallsiteInterns *interns    = tc->instance->callsite_interns;
166
76.8k
    MVMCallsite        *cs         = *cs_ptr;
167
76.8k
    MVMint32            num_flags  = cs->flag_count;
168
76.8k
    MVMint32            num_nameds = MVM_callsite_num_nameds(tc, cs);
169
76.8k
    MVMint32 i, found;
170
76.8k
171
76.8k
    /* Can't intern anything with flattening. */
172
76.8k
    if (cs->has_flattening)
173
7.64k
        return;
174
76.8k
175
76.8k
    /* Also can't intern past the max arity. */
176
69.1k
    if (num_flags >= MVM_INTERN_ARITY_LIMIT)
177
443
        return;
178
69.1k
179
69.1k
    /* Can intern things with nameds, provided we know the names. */
180
68.7k
    if (num_nameds > 0 && !cs->arg_names)
181
0
        return;
182
68.7k
183
68.7k
    /* Obtain mutex protecting interns store. */
184
68.7k
    uv_mutex_lock(&tc->instance->mutex_callsite_interns);
185
68.7k
186
68.7k
    /* Search for a match. */
187
68.7k
    found = 0;
188
1.42M
    for (i = 0; i < interns->num_by_arity[num_flags]; i++) {
189
1.38M
        if (callsites_equal(tc, interns->by_arity[num_flags][i], cs, num_flags, num_nameds)) {
190
28.8k
            /* Got a match! Free the one we were passed and replace it with
191
28.8k
             * the interned one. */
192
28.8k
            if (num_flags)
193
27.1k
                MVM_free(cs->arg_flags);
194
28.8k
            MVM_free(cs->arg_names);
195
28.8k
            MVM_free(cs);
196
28.8k
            *cs_ptr = interns->by_arity[num_flags][i];
197
28.8k
            found = 1;
198
28.8k
            break;
199
28.8k
        }
200
1.38M
    }
201
68.7k
202
68.7k
    /* If it wasn't found, store it for the future. */
203
68.7k
    if (!found) {
204
39.8k
        if (interns->num_by_arity[num_flags] % 8 == 0) {
205
5.58k
            if (interns->num_by_arity[num_flags])
206
4.43k
                interns->by_arity[num_flags] = MVM_realloc(
207
4.43k
                    interns->by_arity[num_flags],
208
4.43k
                    sizeof(MVMCallsite *) * (interns->num_by_arity[num_flags] + 8));
209
5.58k
            else
210
1.15k
                interns->by_arity[num_flags] = MVM_malloc(sizeof(MVMCallsite *) * 8);
211
5.58k
        }
212
39.8k
        interns->by_arity[num_flags][interns->num_by_arity[num_flags]++] = cs;
213
39.8k
        cs->is_interned = 1;
214
39.8k
    }
215
68.7k
216
68.7k
    /* Finally, release mutex. */
217
68.7k
    uv_mutex_unlock(&tc->instance->mutex_callsite_interns);
218
68.7k
}