diff --git a/src/gc/alloc_resources.c b/src/gc/alloc_resources.c index cd96ffb..6930bb8 100644 --- a/src/gc/alloc_resources.c +++ b/src/gc/alloc_resources.c @@ -321,8 +321,11 @@ mem_allocate(PARROT_INTERP, * TODO pass required allocation size to the GC system, * so that collection can be skipped if needed */ + size_t new_mem = mem_pools->memory_used - + mem_pools->mem_used_last_collect; if (!mem_pools->gc_mark_block_level - && mem_pools->mem_allocs_since_last_collect) { + && new_mem > (mem_pools->mem_used_last_collect >> 1) + && new_mem > GC_SIZE_THRESHOLD) { Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG); if (interp->gc_sys->sys_type != INF) { @@ -360,6 +363,7 @@ mem_allocate(PARROT_INTERP, return_val = pool->top_block->top; pool->top_block->top += size; pool->top_block->free -= size; + mem_pools->memory_used += size; return return_val; } @@ -512,6 +516,7 @@ compact_pool(PARROT_INTERP, /* How much is free. That's the total size minus the amount we used */ new_block->free = new_block->size - (cur_spot - new_block->start); mem_pools->memory_collected += (cur_spot - new_block->start); + mem_pools->memory_used += (cur_spot - new_block->start); free_old_mem_blocks(mem_pools, pool, new_block, total_size); @@ -719,6 +724,8 @@ free_old_mem_blocks( else { /* Note that we don't have it any more */ mem_pools->memory_allocated -= cur_block->size; + mem_pools->memory_used -= + cur_block->size - cur_block->free - cur_block->freed; /* We know the pool body and pool header are a single chunk, so * this is enough to get rid of 'em both */ diff --git a/src/gc/gc_ms.c b/src/gc/gc_ms.c index c244730..e67d6f2 100644 --- a/src/gc/gc_ms.c +++ b/src/gc/gc_ms.c @@ -35,11 +35,13 @@ static int gc_ms_active_sized_buffers(ARGIN(const Memory_Pools *mem_pools)) __attribute__nonnull__(1); static void gc_ms_add_free_object(SHIM_INTERP, - SHIM(Memory_Pools *mem_pools), + ARGMOD(Memory_Pools *mem_pools), ARGMOD(Fixed_Size_Pool *pool), ARGIN(void *to_add)) + __attribute__nonnull__(2) __attribute__nonnull__(3) __attribute__nonnull__(4) + FUNC_MODIFIES(*mem_pools) FUNC_MODIFIES(*pool); static void gc_ms_alloc_objects(PARROT_INTERP, @@ -134,11 +136,12 @@ static void gc_ms_free_string_header(PARROT_INTERP, ARGMOD(STRING *s)) PARROT_CANNOT_RETURN_NULL PARROT_WARN_UNUSED_RESULT static void * gc_ms_get_free_object(PARROT_INTERP, - ARGIN(Memory_Pools *mem_pools), + ARGMOD(Memory_Pools *mem_pools), ARGMOD(Fixed_Size_Pool *pool)) __attribute__nonnull__(1) __attribute__nonnull__(2) __attribute__nonnull__(3) + FUNC_MODIFIES(*mem_pools) FUNC_MODIFIES(*pool); static size_t gc_ms_get_gc_info(PARROT_INTERP, Interpinfo_enum which) @@ -253,7 +256,8 @@ static void Parrot_gc_initialize_fixed_size_pools(SHIM_INTERP, #define ASSERT_ARGS_gc_ms_active_sized_buffers __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(mem_pools)) #define ASSERT_ARGS_gc_ms_add_free_object __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(pool) \ + PARROT_ASSERT_ARG(mem_pools) \ + , PARROT_ASSERT_ARG(pool) \ , PARROT_ASSERT_ARG(to_add)) #define ASSERT_ARGS_gc_ms_alloc_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(interp) \ @@ -560,6 +564,7 @@ gc_ms_mark_and_sweep(PARROT_INTERP, UINTVAL flags) ++mem_pools->gc_mark_runs; --mem_pools->gc_mark_block_level; mem_pools->header_allocs_since_last_collect = 0; + mem_pools->mem_used_last_collect = mem_pools->memory_used; return; } @@ -1098,6 +1103,7 @@ gc_ms_reallocate_buffer_storage(PARROT_INTERP, ARGMOD(Buffer *buffer), && (pool->top_block->top == (char *)Buffer_bufstart(buffer) + old_size)) { pool->top_block->free -= needed; pool->top_block->top += needed; + interp->mem_pools->memory_used += needed; Buffer_buflen(buffer) = newsize; return; } @@ -1210,6 +1216,7 @@ gc_ms_reallocate_string_storage(PARROT_INTERP, ARGMOD(STRING *str), && pool->top_block->top == (char *)Buffer_bufstart(str) + old_size) { pool->top_block->free -= needed; pool->top_block->top += needed; + interp->mem_pools->memory_used += needed; Buffer_buflen(str) = new_size - sizeof (void *); return; } @@ -1231,7 +1238,8 @@ gc_ms_reallocate_string_storage(PARROT_INTERP, ARGMOD(STRING *str), /* Decrease usage */ PARROT_ASSERT(Buffer_pool(str)); - Buffer_pool(str)->freed += ALIGNED_STRING_SIZE(Buffer_buflen(str)); + Buffer_pool(str)->freed += old_size; + interp->mem_pools->memory_used -= old_size; /* copy mem from strstart, *not* bufstart */ oldmem = str->strstart; @@ -1494,12 +1502,15 @@ gc_ms_more_traceable_objects(PARROT_INTERP, ARGMOD(Fixed_Size_Pool *pool)) { ASSERT_ARGS(gc_ms_more_traceable_objects) + size_t new_mem = mem_pools->memory_used + - mem_pools->mem_used_last_collect; if (pool->skip == GC_ONE_SKIP) pool->skip = GC_NO_SKIP; else if (pool->skip == GC_NEVER_SKIP || (pool->skip == GC_NO_SKIP - && mem_pools->header_allocs_since_last_collect >= GC_SIZE_THRESHOLD)) + && (new_mem > (mem_pools->mem_used_last_collect >> 1) + && mem_pools->header_allocs_since_last_collect >= GC_SIZE_THRESHOLD))) Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG); /* requires that num_free_objects be updated in Parrot_gc_mark_and_sweep. @@ -1523,7 +1534,7 @@ the PObj flags to indicate that the item is free. static void gc_ms_add_free_object(SHIM_INTERP, - SHIM(Memory_Pools *mem_pools), + ARGMOD(Memory_Pools *mem_pools), ARGMOD(Fixed_Size_Pool *pool), ARGIN(void *to_add)) { @@ -1534,6 +1545,7 @@ gc_ms_add_free_object(SHIM_INTERP, object->next_ptr = pool->free_list; pool->free_list = object; + mem_pools->memory_used -= pool->object_size; } /* @@ -1554,7 +1566,7 @@ PARROT_CANNOT_RETURN_NULL PARROT_WARN_UNUSED_RESULT static void * gc_ms_get_free_object(PARROT_INTERP, - ARGIN(Memory_Pools *mem_pools), + ARGMOD(Memory_Pools *mem_pools), ARGMOD(Fixed_Size_Pool *pool)) { ASSERT_ARGS(gc_ms_get_free_object) @@ -1584,6 +1596,7 @@ gc_ms_get_free_object(PARROT_INTERP, } --pool->num_free_objects; + mem_pools->memory_used += pool->object_size; return ptr; } diff --git a/src/gc/gc_private.h b/src/gc/gc_private.h index ad62b42..46bce80 100644 --- a/src/gc/gc_private.h +++ b/src/gc/gc_private.h @@ -283,6 +283,12 @@ typedef struct Memory_Pools { * memory for headers or * internal structures or * anything */ + size_t memory_used; /* The total amount of + * memory used for + * buffers and headers */ + size_t mem_used_last_collect; /* The total amount of + * memory used after + * the last GC run */ UINTVAL memory_collected; /* Total amount of memory copied during collection */ UINTVAL num_early_gc_PMCs; /* how many PMCs want immediate destruction */ diff --git a/src/gc/mark_sweep.c b/src/gc/mark_sweep.c index 757a060..ea76511 100644 --- a/src/gc/mark_sweep.c +++ b/src/gc/mark_sweep.c @@ -32,11 +32,13 @@ throughout the rest of Parrot. /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ static void free_buffer(SHIM_INTERP, - SHIM(Memory_Pools *mem_pools), + ARGMOD(Memory_Pools *mem_pools), ARGMOD(Fixed_Size_Pool *pool), ARGMOD(Buffer *b)) + __attribute__nonnull__(2) __attribute__nonnull__(3) __attribute__nonnull__(4) + FUNC_MODIFIES(*mem_pools) FUNC_MODIFIES(*pool) FUNC_MODIFIES(*b); @@ -78,7 +80,8 @@ static Fixed_Size_Pool * new_string_pool(PARROT_INTERP, FUNC_MODIFIES(*mem_pools); #define ASSERT_ARGS_free_buffer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ - PARROT_ASSERT_ARG(pool) \ + PARROT_ASSERT_ARG(mem_pools) \ + , PARROT_ASSERT_ARG(pool) \ , PARROT_ASSERT_ARG(b)) #define ASSERT_ARGS_free_pmc_in_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(interp) \ @@ -655,7 +658,7 @@ reuse later. static void free_buffer(SHIM_INTERP, - SHIM(Memory_Pools *mem_pools), + ARGMOD(Memory_Pools *mem_pools), ARGMOD(Fixed_Size_Pool *pool), ARGMOD(Buffer *b)) { @@ -680,7 +683,9 @@ free_buffer(SHIM_INTERP, /* We can have shared buffers. Don't count them (yet) */ if (!(*buffer_flags & Buffer_shared_FLAG)) { - block->freed += ALIGNED_STRING_SIZE(Buffer_buflen(b)); + size_t size = ALIGNED_STRING_SIZE(Buffer_buflen(b)); + block->freed += size; + mem_pools->memory_used -= size; } }