Coverage Report

Created: 2018-07-03 15:31

/home/travis/build/MoarVM/MoarVM/src/gc/allocation.c
Line
Count
Source (jump to first uncovered line)
1
/* Allocation of managed memory - that is, from the memory space that is
2
 * managed by the garbage collector. Memory that is in turn owned by a
3
 * GC-able object will be allocated separately and freed explicitly by
4
 * its REPR gc_free routine. */
5
6
#include "moar.h"
7
8
/* Allocate the specified amount of memory from the nursery. Will
9
 * trigger a GC run if there is not enough. */
10
32.6M
void * MVM_gc_allocate_nursery(MVMThreadContext *tc, size_t size) {
11
32.6M
    void *allocated;
12
32.6M
13
32.6M
    /* Before an allocation is a GC safe-point and thus a good GC sync point
14
32.6M
     * also; check if we've been signalled to collect. */
15
32.6M
    /* Don't use a MVM_load(&tc->gc_status) here for performance, it's okay
16
32.6M
     * if the interrupt is delayed a bit. */
17
32.6M
    if (tc->gc_status)
18
2
        MVM_gc_enter_from_interrupt(tc);
19
32.6M
20
32.6M
    /* Guard against 0-byte allocation. */
21
32.6M
    if (size > 0) {
22
32.6M
        /* Do a GC run if this allocation won't fit in what we have
23
32.6M
         * left in the nursery. Note this is a loop to handle a
24
32.6M
         * pathological case: all the objects in the nursery are very
25
32.6M
         * young and thus survive in the nursery, meaning that no space
26
32.6M
         * actually gets freed up. The next run will promote them to the
27
32.6M
         * second generation. Note that this circumstance is exceptionally
28
32.6M
         * unlikely in any non-contrived situation. */
29
32.6M
        while ((char *)tc->nursery_alloc + size >= (char *)tc->nursery_alloc_limit) {
30
313
            if (size > MVM_NURSERY_SIZE)
31
0
                MVM_panic(MVM_exitcode_gcalloc, "Attempt to allocate more than the maximum nursery size");
32
313
            MVM_gc_enter_from_allocator(tc);
33
313
        }
34
32.6M
35
32.6M
        /* Allocate (just bump the pointer). */
36
32.6M
        allocated = tc->nursery_alloc;
37
32.6M
        tc->nursery_alloc = (char *)tc->nursery_alloc + size;
38
32.6M
    }
39
0
    else {
40
0
        MVM_panic(MVM_exitcode_gcalloc, "Cannot allocate 0 bytes of memory in the nursery");
41
0
    }
42
32.6M
43
32.6M
    return allocated;
44
32.6M
}
45
46
/* Same as MVM_gc_allocate, but promises that the memory will be zeroed. */
47
36.8M
void * MVM_gc_allocate_zeroed(MVMThreadContext *tc, size_t size) {
48
36.8M
    /* At present, MVM_gc_allocate always returns zeroed memory. */
49
36.8M
    return MVM_gc_allocate(tc, size);
50
36.8M
}
51
52
/* Allocates a new STable, based on the specified thread context, REPR
53
 * and meta-object. */
54
32.3k
MVMSTable * MVM_gc_allocate_stable(MVMThreadContext *tc, const MVMREPROps *repr, MVMObject *how) {
55
32.3k
    MVMSTable *st;
56
32.3k
    MVMROOT(tc, how, {
57
32.3k
        st                = MVM_gc_allocate_zeroed(tc, sizeof(MVMSTable));
58
32.3k
        st->header.flags |= MVM_CF_STABLE;
59
32.3k
        st->header.size   = sizeof(MVMSTable);
60
32.3k
        st->header.owner  = tc->thread_id;
61
32.3k
        st->REPR          = repr;
62
32.3k
        st->invoke        = MVM_6model_invoke_default;
63
32.3k
        st->type_cache_id = MVM_6model_next_type_cache_id(tc);
64
32.3k
        st->debug_name    = NULL;
65
32.3k
        MVM_ASSIGN_REF(tc, &(st->header), st->HOW, how);
66
32.3k
    });
67
32.3k
    return st;
68
32.3k
}
69
70
/* Allocates a new type object. */
71
32.2k
MVMObject * MVM_gc_allocate_type_object(MVMThreadContext *tc, MVMSTable *st) {
72
32.2k
    MVMObject *obj;
73
32.2k
    MVMROOT(tc, st, {
74
32.2k
        obj                = MVM_gc_allocate_zeroed(tc, sizeof(MVMObject));
75
32.2k
        obj->header.flags |= MVM_CF_TYPE_OBJECT;
76
32.2k
        obj->header.size   = sizeof(MVMObject);
77
32.2k
        obj->header.owner  = tc->thread_id;
78
32.2k
        MVM_ASSIGN_REF(tc, &(obj->header), obj->st, st);
79
32.2k
    });
80
32.2k
    return obj;
81
32.2k
}
82
83
/* Allocates a new object, and points it at the specified STable. */
84
29.5M
MVMObject * MVM_gc_allocate_object(MVMThreadContext *tc, MVMSTable *st) {
85
29.5M
    MVMObject *obj;
86
29.5M
    MVMROOT(tc, st, {
87
29.5M
        obj               = MVM_gc_allocate_zeroed(tc, st->size);
88
29.5M
        obj->header.size  = (MVMuint16)st->size;
89
29.5M
        obj->header.owner = tc->thread_id;
90
29.5M
        MVM_ASSIGN_REF(tc, &(obj->header), obj->st, st);
91
29.5M
        if (st->mode_flags & MVM_FINALIZE_TYPE)
92
29.5M
            MVM_gc_finalize_add_to_queue(tc, obj);
93
29.5M
    });
94
29.5M
    return obj;
95
29.5M
}
96
97
/* Allocates a new heap frame. */
98
960k
MVMFrame * MVM_gc_allocate_frame(MVMThreadContext *tc) {
99
960k
    MVMFrame *f = MVM_gc_allocate_zeroed(tc, sizeof(MVMFrame));
100
960k
    f->header.flags |= MVM_CF_FRAME;
101
960k
    f->header.size   = sizeof(MVMFrame);
102
960k
    f->header.owner  = tc->thread_id;
103
960k
    return f;
104
960k
}
105
106
/* Sets allocate for this thread to be from the second generation by
107
 * default. */
108
2.28M
void MVM_gc_allocate_gen2_default_set(MVMThreadContext *tc) {
109
2.28M
    tc->allocate_in_gen2++;
110
2.28M
}
111
112
/* Sets allocation for this thread to be from the nursery by default. */
113
2.28M
void MVM_gc_allocate_gen2_default_clear(MVMThreadContext *tc) {
114
2.28M
    if (tc->allocate_in_gen2 <= 0)
115
0
        MVM_oops(tc, "Cannot leave gen2 allocation without entering it");
116
2.28M
    tc->allocate_in_gen2--;
117
2.28M
}