/* 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; }
/* Finishes heap profiling, getting the data. */ MVMObject * MVM_profile_heap_end(MVMThreadContext *tc) { MVMObject *dataset; /* Trigger a GC run, to ensure we get at least one heap snapshot. */ MVM_gc_enter_from_allocator(tc); /* Process and return the data. */ dataset = collection_to_mvm_objects(tc, tc->instance->heap_snapshots); destroy_heap_snapshot_collection(tc); return dataset; }