Mercurial > hg > Members > anatofuz > MoarVM
view src/gc/allocation.c @ 11:e08e6dca633f
add switch code
author | Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 09 Oct 2018 16:17:01 +0900 |
parents | 2cf249471370 |
children |
line wrap: on
line source
/* Allocation of managed memory - that is, from the memory space that is * managed by the garbage collector. Memory that is in turn owned by a * GC-able object will be allocated separately and freed explicitly by * its REPR gc_free routine. */ #include "moar.h" /* Allocate the specified amount of memory from the nursery. Will * trigger a GC run if there is not enough. */ void * MVM_gc_allocate_nursery(MVMThreadContext *tc, size_t size) { void *allocated; /* Before an allocation is a GC safe-point and thus a good GC sync point * also; check if we've been signalled to collect. */ /* Don't use a MVM_load(&tc->gc_status) here for performance, it's okay * if the interrupt is delayed a bit. */ if (tc->gc_status) MVM_gc_enter_from_interrupt(tc); /* Guard against 0-byte allocation. */ if (size > 0) { /* Do a GC run if this allocation won't fit in what we have * left in the nursery. Note this is a loop to handle a * pathological case: all the objects in the nursery are very * young and thus survive in the nursery, meaning that no space * actually gets freed up. The next run will promote them to the * second generation. Note that this circumstance is exceptionally * unlikely in any non-contrived situation. */ while ((char *)tc->nursery_alloc + size >= (char *)tc->nursery_alloc_limit) { if (size > MVM_NURSERY_SIZE) MVM_panic(MVM_exitcode_gcalloc, "Attempt to allocate more than the maximum nursery size"); MVM_gc_enter_from_allocator(tc); } /* Allocate (just bump the pointer). */ allocated = tc->nursery_alloc; tc->nursery_alloc = (char *)tc->nursery_alloc + size; } else { MVM_panic(MVM_exitcode_gcalloc, "Cannot allocate 0 bytes of memory in the nursery"); } return allocated; } /* Same as MVM_gc_allocate, but promises that the memory will be zeroed. */ void * MVM_gc_allocate_zeroed(MVMThreadContext *tc, size_t size) { /* At present, MVM_gc_allocate always returns zeroed memory. */ return MVM_gc_allocate(tc, size); } /* Allocates a new STable, based on the specified thread context, REPR * and meta-object. */ MVMSTable * MVM_gc_allocate_stable(MVMThreadContext *tc, const MVMREPROps *repr, MVMObject *how) { MVMSTable *st; MVMROOT(tc, how, { st = MVM_gc_allocate_zeroed(tc, sizeof(MVMSTable)); st->header.flags |= MVM_CF_STABLE; st->header.size = sizeof(MVMSTable); st->header.owner = tc->thread_id; st->REPR = repr; st->invoke = MVM_6model_invoke_default; st->type_cache_id = MVM_6model_next_type_cache_id(tc); st->debug_name = NULL; MVM_ASSIGN_REF(tc, &(st->header), st->HOW, how); }); return st; } /* Allocates a new type object. */ MVMObject * MVM_gc_allocate_type_object(MVMThreadContext *tc, MVMSTable *st) { MVMObject *obj; MVMROOT(tc, st, { obj = MVM_gc_allocate_zeroed(tc, sizeof(MVMObject)); obj->header.flags |= MVM_CF_TYPE_OBJECT; obj->header.size = sizeof(MVMObject); obj->header.owner = tc->thread_id; MVM_ASSIGN_REF(tc, &(obj->header), obj->st, st); }); return obj; } /* Allocates a new object, and points it at the specified STable. */ MVMObject * MVM_gc_allocate_object(MVMThreadContext *tc, MVMSTable *st) { MVMObject *obj; MVMROOT(tc, st, { obj = MVM_gc_allocate_zeroed(tc, st->size); obj->header.size = (MVMuint16)st->size; obj->header.owner = tc->thread_id; MVM_ASSIGN_REF(tc, &(obj->header), obj->st, st); if (st->mode_flags & MVM_FINALIZE_TYPE) MVM_gc_finalize_add_to_queue(tc, obj); }); return obj; } /* Allocates a new heap frame. */ MVMFrame * MVM_gc_allocate_frame(MVMThreadContext *tc) { MVMFrame *f = MVM_gc_allocate_zeroed(tc, sizeof(MVMFrame)); f->header.flags |= MVM_CF_FRAME; f->header.size = sizeof(MVMFrame); f->header.owner = tc->thread_id; return f; } /* Sets allocate for this thread to be from the second generation by * default. */ void MVM_gc_allocate_gen2_default_set(MVMThreadContext *tc) { tc->allocate_in_gen2++; } /* Sets allocation for this thread to be from the nursery by default. */ void MVM_gc_allocate_gen2_default_clear(MVMThreadContext *tc) { if (tc->allocate_in_gen2 <= 0) MVM_oops(tc, "Cannot leave gen2 allocation without entering it"); tc->allocate_in_gen2--; }