Coverage Report

Created: 2017-04-15 07:07

/home/travis/build/MoarVM/MoarVM/src/6model/sc.c
Line
Count
Source (jump to first uncovered line)
1
#include "moar.h"
2
3
/* Creates a new serialization context with the specified handle. If any
4
 * compilation units are waiting for an SC with this handle, removes it from
5
 * their to-resolve list after installing itself in the appropriate slot. */
6
2.88k
MVMObject * MVM_sc_create(MVMThreadContext *tc, MVMString *handle) {
7
2.88k
    MVMSerializationContext     *sc;
8
2.88k
    MVMSerializationContextBody *scb = NULL;
9
2.88k
10
2.88k
    /* Allocate. */
11
2.88k
    MVMROOT(tc, handle, {
12
2.88k
        sc = (MVMSerializationContext *)REPR(tc->instance->SCRef)->allocate(tc, STABLE(tc->instance->SCRef));
13
2.88k
        MVMROOT(tc, sc, {
14
2.88k
            /* Add to weak lookup hash. */
15
2.88k
            uv_mutex_lock(&tc->instance->mutex_sc_weakhash);
16
2.88k
            MVM_HASH_GET(tc, tc->instance->sc_weakhash, handle, scb);
17
2.88k
            if (!scb) {
18
2.88k
                sc->body = scb = MVM_calloc(1, sizeof(MVMSerializationContextBody));
19
2.88k
                MVM_ASSIGN_REF(tc, &(sc->common.header), scb->handle, handle);
20
2.88k
                MVM_HASH_BIND(tc, tc->instance->sc_weakhash, handle, scb);
21
2.88k
                /* Calling repr_init will allocate, BUT if it does so, and we
22
2.88k
                 * get unlucky, the GC will try to acquire mutex_sc_weakhash.
23
2.88k
                 * This deadlocks. Thus, we force allocation in gen2, which
24
2.88k
                 * can never trigger GC. Note that releasing the mutex early
25
2.88k
                 * is not a good way to fix this, as it leaves a race to
26
2.88k
                 * test/set scb->sc (between the line doing it in this block,
27
2.88k
                 * and in the else clauses beneath it). */
28
2.88k
                MVM_gc_allocate_gen2_default_set(tc);
29
2.88k
                MVM_repr_init(tc, (MVMObject *)sc);
30
2.88k
                MVM_gc_allocate_gen2_default_clear(tc);
31
2.88k
                scb->sc = sc;
32
2.88k
                MVM_sc_add_all_scs_entry(tc, scb);
33
2.88k
            }
34
2.88k
            else if (scb->sc) {
35
2.88k
                /* we lost a race to create it! */
36
2.88k
                sc = scb->sc;
37
2.88k
            }
38
2.88k
            else {
39
2.88k
                scb->sc = sc;
40
2.88k
                sc->body = scb;
41
2.88k
                MVM_ASSIGN_REF(tc, &(sc->common.header), scb->handle, handle);
42
2.88k
                MVM_gc_allocate_gen2_default_set(tc);
43
2.88k
                MVM_repr_init(tc, (MVMObject *)sc);
44
2.88k
                MVM_gc_allocate_gen2_default_clear(tc);
45
2.88k
            }
46
2.88k
            uv_mutex_unlock(&tc->instance->mutex_sc_weakhash);
47
2.88k
        });
48
2.88k
    });
49
2.88k
50
2.88k
    return (MVMObject *)sc;
51
2.88k
}
52
53
/* Makes an entry in all SCs list, the index of which is used to refer to
54
 * SCs in object headers. */
55
2.86k
void MVM_sc_add_all_scs_entry(MVMThreadContext *tc, MVMSerializationContextBody *scb) {
56
2.86k
    if (tc->instance->all_scs_next_idx == tc->instance->all_scs_alloc) {
57
167
        tc->instance->all_scs_alloc += 32;
58
167
        if (tc->instance->all_scs_next_idx == 0) {
59
130
            /* First time; allocate, and NULL first slot as it is
60
130
             * the "no SC" sentinel value. */
61
130
            tc->instance->all_scs    = MVM_malloc(tc->instance->all_scs_alloc * sizeof(MVMSerializationContextBody *));
62
130
            tc->instance->all_scs[0] = NULL;
63
130
            tc->instance->all_scs_next_idx++;
64
130
        }
65
37
        else {
66
37
            tc->instance->all_scs = MVM_realloc(tc->instance->all_scs,
67
37
                tc->instance->all_scs_alloc * sizeof(MVMSerializationContextBody *));
68
37
        }
69
167
    }
70
2.86k
    scb->sc_idx = tc->instance->all_scs_next_idx;
71
2.86k
    tc->instance->all_scs[tc->instance->all_scs_next_idx] = scb;
72
2.86k
    tc->instance->all_scs_next_idx++;
73
2.86k
}
74
75
/* Given an SC, returns its unique handle. */
76
8.28k
MVMString * MVM_sc_get_handle(MVMThreadContext *tc, MVMSerializationContext *sc) {
77
8.28k
    return sc->body->handle;
78
8.28k
}
79
80
/* Given an SC, returns its description. */
81
172
MVMString * MVM_sc_get_description(MVMThreadContext *tc, MVMSerializationContext *sc) {
82
172
    return sc->body->description;
83
172
}
84
85
/* Given an SC, sets its description. */
86
2.54k
void MVM_sc_set_description(MVMThreadContext *tc, MVMSerializationContext *sc, MVMString *desc) {
87
2.54k
    MVM_ASSIGN_REF(tc, &(sc->common.header), sc->body->description, desc);
88
2.54k
}
89
90
/* Given an SC, looks up the index of an object that is in its root set. */
91
8.50k
MVMint64 MVM_sc_find_object_idx(MVMThreadContext *tc, MVMSerializationContext *sc, MVMObject *obj) {
92
8.50k
    MVMObject **roots;
93
8.50k
    MVMint64    i, count;
94
8.50k
    MVMuint32   cached = MVM_sc_get_idx_in_sc(&obj->header);
95
8.50k
    if (cached != ~0 && MVM_sc_get_collectable_sc(tc, &obj->header) == sc)
96
4.93k
        return cached;
97
3.56k
    roots = sc->body->root_objects;
98
3.56k
    count = sc->body->num_objects;
99
197k
    for (i = 0; i < count; i++)
100
197k
        if (roots[i] == obj)
101
3.56k
            return i;
102
0
    MVM_exception_throw_adhoc(tc,
103
0
        "Object does not exist in serialization context");
104
0
}
105
106
/* Calls MVM_sc_find_object_idx, but first checks if the sc is actually an SCRef. */
107
3.57k
MVMint64 MVM_sc_find_object_idx_jit(MVMThreadContext *tc, MVMObject *sc, MVMObject *obj) {
108
3.57k
    if (REPR(sc)->ID != MVM_REPR_ID_SCRef)
109
0
        MVM_exception_throw_adhoc(tc,
110
0
            "Must provide an SCRef operand to scgetobjidx");
111
3.57k
    return MVM_sc_find_object_idx(tc, (MVMSerializationContext *)sc, obj);
112
3.57k
}
113
114
/* Given an SC, looks up the index of an STable that is in its root set. */
115
332
MVMint64 MVM_sc_find_stable_idx(MVMThreadContext *tc, MVMSerializationContext *sc, MVMSTable *st) {
116
332
    MVMuint64 i;
117
332
    MVMuint32 cached = MVM_sc_get_idx_in_sc(&st->header);
118
332
    if (cached != ~0 && MVM_sc_get_collectable_sc(tc, &st->header) == sc)
119
0
        return cached;
120
5.42k
    for (i = 0; i < sc->body->num_stables; i++)
121
5.42k
        if (sc->body->root_stables[i] == st)
122
332
            return i;
123
0
    MVM_exception_throw_adhoc(tc,
124
0
        "STable does not exist in serialization context");
125
0
}
126
127
/* Given an SC, looks up the index of a code ref that is in its root set. */
128
28
MVMint64 MVM_sc_find_code_idx(MVMThreadContext *tc, MVMSerializationContext *sc, MVMObject *obj) {
129
28
    MVMObject *roots;
130
28
    MVMint64   i, count;
131
28
    roots = sc->body->root_codes;
132
28
    count = MVM_repr_elems(tc, roots);
133
46
    for (i = 0; i < count; i++) {
134
46
        MVMObject *test = MVM_repr_at_pos_o(tc, roots, i);
135
46
        if (test == obj)
136
28
            return i;
137
46
    }
138
28
139
0
    if (REPR(obj)->ID == MVM_REPR_ID_MVMCode) {
140
0
        char *c_name = MVM_string_utf8_encode_C_string(tc, ((MVMCode *)obj)->body.name);
141
0
        char *waste[] = { c_name, NULL };
142
0
        MVM_exception_throw_adhoc_free(tc, waste,
143
0
            "Code ref '%s' does not exist in serialization context",
144
0
                c_name);
145
0
    }
146
0
    else {
147
0
        MVM_exception_throw_adhoc(tc,
148
0
            "Code ref '<NOT A CODE OBJECT>' does not exist in serialization context");
149
0
    }
150
0
}
151
152
/* Given a compilation unit and dependency index, returns that SC. */
153
14.8M
MVMSerializationContext * MVM_sc_get_sc(MVMThreadContext *tc, MVMCompUnit *cu, MVMint16 dep) {
154
14.8M
    MVMSerializationContext *sc = cu->body.scs[dep];
155
14.8M
    if (sc == NULL) {
156
2.46k
        MVMSerializationContextBody *scb = cu->body.scs_to_resolve[dep];
157
2.46k
        if (!scb)
158
0
            MVM_exception_throw_adhoc(tc,
159
0
                "SC resolution: internal error");
160
2.46k
        sc = scb->sc;
161
2.46k
        if (sc == NULL)
162
0
            return NULL;
163
2.46k
        MVM_ASSIGN_REF(tc, &(cu->common.header), cu->body.scs[dep], sc);
164
2.46k
        scb->claimed = 1;
165
2.46k
    }
166
14.8M
    return sc;
167
14.8M
}
168
169
/* Checks if an SC is currently in the process of doing deserialization work. */
170
17.1M
MVM_STATIC_INLINE MVMint64 sc_working(MVMSerializationContext *sc) {
171
17.1M
    MVMSerializationReader *sr = sc->body->sr;
172
17.0M
    return sr && sr->working;
173
17.1M
}
174
175
/* Given an SC and an index, fetch the object stored there. */
176
16.0M
MVMObject * MVM_sc_get_object(MVMThreadContext *tc, MVMSerializationContext *sc, MVMint64 idx) {
177
16.0M
    MVMObject **roots = sc->body->root_objects;
178
16.0M
    MVMint64    count = sc->body->num_objects;
179
16.0M
    if (idx >= 0 && idx < count)
180
16.0M
        return roots[idx] && !sc_working(sc)
181
14.9M
            ? roots[idx]
182
1.13M
            : MVM_serialization_demand_object(tc, sc, idx);
183
0
    else {
184
0
        char *c_description = MVM_string_utf8_encode_C_string(tc, sc->body->description);
185
0
        char *waste[] = { c_description, NULL };
186
0
        MVM_exception_throw_adhoc_free(tc, waste,
187
0
            "Probable version skew in pre-compiled '%s' (cause: no object at index %"PRId64")",
188
0
            c_description, idx);
189
0
    }
190
16.0M
}
191
192
MVMObject * MVM_sc_get_sc_object(MVMThreadContext *tc, MVMCompUnit *cu,
193
14.7M
                                 MVMint16 dep, MVMint64 idx) {
194
14.7M
    if (dep >= 0 && dep < cu->body.num_scs) {
195
14.7M
        MVMSerializationContext *sc = MVM_sc_get_sc(tc, cu, dep);
196
14.7M
        if (sc == NULL)
197
0
            MVM_exception_throw_adhoc(tc, "SC not yet resolved; lookup failed");
198
14.7M
        return MVM_sc_get_object(tc, sc, idx);
199
14.7M
    }
200
0
    else {
201
0
        MVM_exception_throw_adhoc(tc, "Invalid SC index in bytecode stream");
202
0
    }
203
14.7M
}
204
205
/* Given an SC and an index, fetch the object stored there, or return NULL if
206
 * there is none. Does not cause lazy deserialization. */
207
875k
MVMObject * MVM_sc_try_get_object(MVMThreadContext *tc, MVMSerializationContext *sc, MVMint64 idx) {
208
875k
    MVMObject **roots = sc->body->root_objects;
209
875k
    MVMint64    count = sc->body->num_objects;
210
875k
    if (idx > 0 && idx < count && !sc_working(sc))
211
49.7k
        return roots[idx];
212
875k
    else
213
825k
        return NULL;
214
875k
}
215
216
/* Given an SC, an index, and an object, store the object at that index. */
217
827k
void MVM_sc_set_object(MVMThreadContext *tc, MVMSerializationContext *sc, MVMint64 idx, MVMObject *obj) {
218
827k
    if (idx < 0)
219
0
        MVM_exception_throw_adhoc(tc, "Invalid (negative) object root index %"PRId64"", idx);
220
827k
    if (idx < sc->body->num_objects) {
221
822k
        /* Just updating an existing one. */
222
822k
        MVM_ASSIGN_REF(tc, &(sc->common.header), sc->body->root_objects[idx], obj);
223
822k
    }
224
5.11k
    else {
225
5.11k
        if (idx >= sc->body->alloc_objects) {
226
2.64k
            MVMint64 orig_size = sc->body->alloc_objects;
227
2.64k
            sc->body->alloc_objects *= 2;
228
2.64k
            if (sc->body->alloc_objects < idx + 1)
229
1.31k
                sc->body->alloc_objects = idx + 1;
230
2.64k
            sc->body->root_objects = MVM_realloc(sc->body->root_objects,
231
2.64k
                sc->body->alloc_objects * sizeof(MVMObject *));
232
2.64k
            memset(sc->body->root_objects + orig_size, 0,
233
2.64k
                (sc->body->alloc_objects - orig_size) * sizeof(MVMObject *));
234
2.64k
        }
235
5.11k
        MVM_ASSIGN_REF(tc, &(sc->common.header), sc->body->root_objects[idx], obj);
236
5.11k
        sc->body->num_objects = idx + 1;
237
5.11k
    }
238
827k
    MVM_sc_set_idx_in_sc(&obj->header, idx);
239
827k
}
240
241
/* Given an SC and an index, fetch the STable stored there. */
242
848k
MVMSTable * MVM_sc_get_stable(MVMThreadContext *tc, MVMSerializationContext *sc, MVMint64 idx) {
243
848k
    if (idx >= 0 && idx < sc->body->num_stables) {
244
848k
        MVMSTable *got = sc->body->root_stables[idx];
245
825k
        return got && !sc_working(sc) ? got : MVM_serialization_demand_stable(tc, sc, idx);
246
848k
    }
247
0
    else {
248
0
        char *c_description = MVM_string_utf8_encode_C_string(tc, sc->body->description);
249
0
        char *waste[] = { c_description, NULL };
250
0
        MVM_exception_throw_adhoc_free(tc, waste,
251
0
            "Probable version skew in pre-compiled '%s' (cause: no STable at index %"PRId64")",
252
0
            c_description, idx);
253
0
    }
254
848k
}
255
256
/* Given an SC and an index, fetch the STable stored there, or return NULL if there
257
 * is none. Does not cause lazy deserialization. */
258
22.6k
MVMSTable * MVM_sc_try_get_stable(MVMThreadContext *tc, MVMSerializationContext *sc, MVMint64 idx) {
259
22.6k
    if (idx >= 0 && idx < sc->body->num_stables)
260
22.6k
        return sc->body->root_stables[idx];
261
22.6k
    else
262
0
        return NULL;
263
22.6k
}
264
265
/* Given an SC, an index, and an STable, store the STable at the index. */
266
23.9k
void MVM_sc_set_stable(MVMThreadContext *tc, MVMSerializationContext *sc, MVMint64 idx, MVMSTable *st) {
267
23.9k
    if (idx < 0)
268
0
        MVM_exception_throw_adhoc(tc,
269
0
            "Invalid (negative) STable index %"PRId64, idx);
270
23.9k
    if (idx < sc->body->num_stables) {
271
22.6k
        /* Just updating an existing one. */
272
22.6k
        MVM_ASSIGN_REF(tc, &(sc->common.header), sc->body->root_stables[idx], st);
273
22.6k
    }
274
1.30k
    else {
275
1.30k
        if (idx >= sc->body->alloc_stables) {
276
130
            MVMint64 orig_size = sc->body->alloc_stables;
277
130
            sc->body->alloc_stables += 32;
278
130
            if (sc->body->alloc_stables < idx + 1)
279
0
                sc->body->alloc_stables = idx + 1;
280
130
            sc->body->root_stables = MVM_realloc(sc->body->root_stables,
281
130
                sc->body->alloc_stables * sizeof(MVMSTable *));
282
130
            memset(sc->body->root_stables + orig_size, 0,
283
130
                (sc->body->alloc_stables - orig_size) * sizeof(MVMSTable *));
284
130
        }
285
1.30k
        MVM_ASSIGN_REF(tc, &(sc->common.header), sc->body->root_stables[idx], st);
286
1.30k
        sc->body->num_stables = idx + 1;
287
1.30k
    }
288
23.9k
}
289
290
291
/* Given an SC and an STable, pushes the STable to the end of the root list. */
292
587
void MVM_sc_push_stable(MVMThreadContext *tc, MVMSerializationContext *sc, MVMSTable *st) {
293
587
    MVMint64 idx = sc->body->num_stables;
294
587
    if (idx == sc->body->alloc_stables) {
295
151
        sc->body->alloc_stables += 16;
296
151
        sc->body->root_stables = MVM_realloc(sc->body->root_stables,
297
151
            sc->body->alloc_stables * sizeof(MVMSTable *));
298
151
    }
299
587
    MVM_ASSIGN_REF(tc, &(sc->common.header), sc->body->root_stables[idx], st);
300
587
    sc->body->num_stables++;
301
587
}
302
303
/* Given an SC and an index, fetch the code ref stored there. */
304
210k
MVMObject * MVM_sc_get_code(MVMThreadContext *tc, MVMSerializationContext *sc, MVMint64 idx) {
305
210k
    MVMObject *roots = sc->body->root_codes;
306
210k
    MVMuint64   count = MVM_repr_elems(tc, roots);
307
210k
    if (idx < count) {
308
210k
        MVMObject *found = MVM_repr_at_pos_o(tc, roots, idx);
309
189k
        return MVM_is_null(tc, found) || sc_working(sc)
310
210k
            ? MVM_serialization_demand_code(tc, sc, idx)
311
260
            : found;
312
210k
    }
313
0
    else {
314
0
        char *c_description = MVM_string_utf8_encode_C_string(tc, sc->body->description);
315
0
        char *waste[] = { c_description, NULL };
316
0
        MVM_exception_throw_adhoc_free(tc, waste,
317
0
            "Probable version skew in pre-compiled '%s' (cause: no code ref at index %"PRId64")",
318
0
            c_description, idx);
319
0
    }
320
210k
}
321
322
/* Resolves an SC handle using the SC weakhash. */
323
6.68k
MVMSerializationContext * MVM_sc_find_by_handle(MVMThreadContext *tc, MVMString *handle) {
324
6.68k
    MVMSerializationContextBody *scb;
325
6.68k
    uv_mutex_lock(&tc->instance->mutex_sc_weakhash);
326
6.68k
    MVM_HASH_GET(tc, tc->instance->sc_weakhash, handle, scb);
327
6.68k
    uv_mutex_unlock(&tc->instance->mutex_sc_weakhash);
328
6.68k
    return scb && scb->sc ? scb->sc : NULL;
329
6.68k
}
330
331
/* Marks all objects, stables and codes that belong to this SC as free to be taken by another. */
332
0
void MVM_sc_disclaim(MVMThreadContext *tc, MVMSerializationContext *sc) {
333
0
    MVMObject **root_objects, *root_codes, *obj;
334
0
    MVMSTable **root_stables, *stable;
335
0
    MVMint64 i, count;
336
0
    MVMCollectable *col;
337
0
    if (REPR(sc)->ID != MVM_REPR_ID_SCRef)
338
0
        MVM_exception_throw_adhoc(tc,
339
0
            "Must provide an SCRef operand to scdisclaim");
340
0
341
0
    root_objects = sc->body->root_objects;
342
0
    count        = sc->body->num_objects;
343
0
    for (i = 0; i < count; i++) {
344
0
        obj = root_objects[i];
345
0
        col = &obj->header;
346
0
#ifdef MVM_USE_OVERFLOW_SERIALIZATION_INDEX
347
        if (col->flags & MVM_CF_SERIALZATION_INDEX_ALLOCATED) {
348
            struct MVMSerializationIndex *const sci = col->sc_forward_u.sci;
349
            col->sc_forward_u.sci = NULL;
350
            MVM_free(sci);
351
        }
352
        col->sc_forward_u.sc.sc_idx = 0;
353
        col->sc_forward_u.sc.idx = 0;
354
#else
355
0
        col->sc_forward_u.sc.sc_idx = 0;
356
0
        col->sc_forward_u.sc.idx = 0;
357
0
#endif
358
0
    }
359
0
    sc->body->num_objects = 0;
360
0
361
0
    root_stables = sc->body->root_stables;
362
0
    count        = sc->body->num_stables;
363
0
    for (i = 0; i < count; i++) {
364
0
        stable                      = root_stables[i];
365
0
        col                         = &stable->header;
366
0
        col->sc_forward_u.sc.sc_idx = 0;
367
0
    }
368
0
    sc->body->num_stables = 0;
369
0
370
0
    root_codes = sc->body->root_codes;
371
0
    count      = MVM_repr_elems(tc, root_codes);
372
0
    for (i = 0; i < count; i++) {
373
0
        obj = MVM_repr_at_pos_o(tc, root_codes, i);
374
0
        if (MVM_is_null(tc, obj))
375
0
            obj = MVM_serialization_demand_code(tc, sc, i);
376
0
        col                         = &obj->header;
377
0
        col->sc_forward_u.sc.sc_idx = 0;
378
0
    }
379
0
    sc->body->root_codes = NULL;
380
0
}
381
382
/* Called when an object triggers the SC repossession write barrier. */
383
18.8k
void MVM_sc_wb_hit_obj(MVMThreadContext *tc, MVMObject *obj) {
384
18.8k
    MVMSerializationContext *comp_sc;
385
18.8k
386
18.8k
    /* If the WB is disabled or we're not compiling, can exit quickly. */
387
18.8k
    if (tc->sc_wb_disable_depth)
388
11.1k
        return;
389
7.71k
    if (!tc->compiling_scs || !MVM_repr_elems(tc, tc->compiling_scs))
390
5.06k
        return;
391
7.71k
392
7.71k
    /* Same if the object is flagged as one to never repossess. */
393
2.65k
    if (obj->header.flags & MVM_CF_NEVER_REPOSSESS)
394
1
        return;
395
2.65k
396
2.65k
    /* Otherwise, check that the object's SC is different from the SC
397
2.65k
     * of the compilation we're currently in. Repossess if so. */
398
2.65k
    comp_sc = (MVMSerializationContext *)MVM_repr_at_pos_o(tc, tc->compiling_scs, 0);
399
2.65k
    if (MVM_sc_get_obj_sc(tc, obj) != comp_sc) {
400
597
        /* Get new slot ID. */
401
597
        MVMint64 new_slot = comp_sc->body->num_objects;
402
597
403
597
        /* See if the object is actually owned by another, and it's the
404
597
         * owner we need to repossess. */
405
597
        if (obj->st->WHAT == tc->instance->boot_types.BOOTArray ||
406
597
            obj->st->WHAT == tc->instance->boot_types.BOOTHash) {
407
130
            MVMObject *owned_objects = MVM_sc_get_obj_sc(tc, obj)->body->owned_objects;
408
130
            MVMint64 n = MVM_repr_elems(tc, owned_objects);
409
130
            MVMint64 found = 0;
410
130
            MVMint64 i;
411
8.34k
            for (i = 0; i < n; i += 2) {
412
8.21k
                if (MVM_repr_at_pos_o(tc, owned_objects, i) == obj) {
413
0
                    MVMSerializationContext *real_sc;
414
0
                    obj = MVM_repr_at_pos_o(tc, owned_objects, i + 1);
415
0
                    real_sc = MVM_sc_get_obj_sc(tc, obj);
416
0
                    if (!real_sc)
417
0
                        return; /* Probably disclaimed. */
418
0
                    if (real_sc == comp_sc)
419
0
                        return;
420
0
                    found = 1;
421
0
                    break;
422
0
                }
423
8.21k
            }
424
130
            if (!found)
425
130
                return;
426
130
        }
427
597
428
597
        /* Add to root set. */
429
467
        MVM_sc_set_object(tc, comp_sc, new_slot, obj);
430
467
431
467
        /* Add repossession entry. */
432
467
        MVM_repr_push_i(tc, comp_sc->body->rep_indexes, new_slot << 1);
433
467
        MVM_repr_push_o(tc, comp_sc->body->rep_scs, (MVMObject *)MVM_sc_get_obj_sc(tc, obj));
434
467
435
467
        /* Update SC of the object, claiming it, and update index too. */
436
467
        MVM_sc_set_obj_sc(tc, obj, comp_sc);
437
467
        MVM_sc_set_idx_in_sc(&(obj->header), new_slot);
438
467
    }
439
2.65k
}
440
441
/* Called when an STable triggers the SC repossession write barrier. */
442
765
void MVM_sc_wb_hit_st(MVMThreadContext *tc, MVMSTable *st) {
443
765
    MVMSerializationContext *comp_sc;
444
765
445
765
    /* If the WB is disabled or we're not compiling, can exit quickly. */
446
765
    if (tc->sc_wb_disable_depth)
447
0
        return;
448
765
    if (!tc->compiling_scs || !MVM_repr_elems(tc, tc->compiling_scs))
449
3
        return;
450
765
451
765
    /* Otherwise, check that the STable's SC is different from the SC
452
765
     * of the compilation we're currently in. Repossess if so. */
453
762
    comp_sc = (MVMSerializationContext *)MVM_repr_at_pos_o(tc, tc->compiling_scs, 0);
454
762
    if (MVM_sc_get_stable_sc(tc, st) != comp_sc) {
455
1
        /* Add to root set. */
456
1
        MVMint64 new_slot = comp_sc->body->num_stables;
457
1
        MVM_sc_push_stable(tc, comp_sc, st);
458
1
459
1
        /* Add repossession entry. */
460
1
        MVM_repr_push_i(tc, comp_sc->body->rep_indexes, (new_slot << 1) | 1);
461
1
        MVM_repr_push_o(tc, comp_sc->body->rep_scs, (MVMObject *)MVM_sc_get_stable_sc(tc, st));
462
1
463
1
        /* Update SC of the STable, claiming it. */
464
1
        MVM_sc_set_stable_sc(tc, st, comp_sc);
465
1
        MVM_sc_set_idx_in_sc(&(st->header), new_slot);
466
1
    }
467
762
}