Coverage Report

Created: 2017-04-15 07:07

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