diff --git a/src/gc/alloc_resources.c b/src/gc/alloc_resources.c
index cd96ffb..6930bb8 100644
a
|
b
|
|
321 | 321 | * TODO pass required allocation size to the GC system, |
322 | 322 | * so that collection can be skipped if needed |
323 | 323 | */ |
| 324 | size_t new_mem = mem_pools->memory_used - |
| 325 | mem_pools->mem_used_last_collect; |
324 | 326 | if (!mem_pools->gc_mark_block_level |
325 | | && mem_pools->mem_allocs_since_last_collect) { |
| 327 | && new_mem > (mem_pools->mem_used_last_collect >> 1) |
| 328 | && new_mem > GC_SIZE_THRESHOLD) { |
326 | 329 | Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG); |
327 | 330 | |
328 | 331 | if (interp->gc_sys->sys_type != INF) { |
… |
… |
|
360 | 363 | return_val = pool->top_block->top; |
361 | 364 | pool->top_block->top += size; |
362 | 365 | pool->top_block->free -= size; |
| 366 | mem_pools->memory_used += size; |
363 | 367 | |
364 | 368 | return return_val; |
365 | 369 | } |
… |
… |
|
512 | 516 | /* How much is free. That's the total size minus the amount we used */ |
513 | 517 | new_block->free = new_block->size - (cur_spot - new_block->start); |
514 | 518 | mem_pools->memory_collected += (cur_spot - new_block->start); |
| 519 | mem_pools->memory_used += (cur_spot - new_block->start); |
515 | 520 | |
516 | 521 | free_old_mem_blocks(mem_pools, pool, new_block, total_size); |
517 | 522 | |
… |
… |
|
719 | 724 | else { |
720 | 725 | /* Note that we don't have it any more */ |
721 | 726 | mem_pools->memory_allocated -= cur_block->size; |
| 727 | mem_pools->memory_used -= |
| 728 | cur_block->size - cur_block->free - cur_block->freed; |
722 | 729 | |
723 | 730 | /* We know the pool body and pool header are a single chunk, so |
724 | 731 | * this is enough to get rid of 'em both */ |
diff --git a/src/gc/gc_ms.c b/src/gc/gc_ms.c
index 523a5ca..9dc50f1 100644
a
|
b
|
|
35 | 35 | __attribute__nonnull__(1); |
36 | 36 | |
37 | 37 | static void gc_ms_add_free_object(SHIM_INTERP, |
38 | | SHIM(Memory_Pools *mem_pools), |
| 38 | ARGMOD(Memory_Pools *mem_pools), |
39 | 39 | ARGMOD(Fixed_Size_Pool *pool), |
40 | 40 | ARGIN(void *to_add)) |
| 41 | __attribute__nonnull__(2) |
41 | 42 | __attribute__nonnull__(3) |
42 | 43 | __attribute__nonnull__(4) |
| 44 | FUNC_MODIFIES(*mem_pools) |
43 | 45 | FUNC_MODIFIES(*pool); |
44 | 46 | |
45 | 47 | static void gc_ms_alloc_objects(PARROT_INTERP, |
… |
… |
|
134 | 136 | PARROT_CANNOT_RETURN_NULL |
135 | 137 | PARROT_WARN_UNUSED_RESULT |
136 | 138 | static void * gc_ms_get_free_object(PARROT_INTERP, |
137 | | ARGIN(Memory_Pools *mem_pools), |
| 139 | ARGMOD(Memory_Pools *mem_pools), |
138 | 140 | ARGMOD(Fixed_Size_Pool *pool)) |
139 | 141 | __attribute__nonnull__(1) |
140 | 142 | __attribute__nonnull__(2) |
141 | 143 | __attribute__nonnull__(3) |
| 144 | FUNC_MODIFIES(*mem_pools) |
142 | 145 | FUNC_MODIFIES(*pool); |
143 | 146 | |
144 | 147 | static size_t gc_ms_get_gc_info(PARROT_INTERP, Interpinfo_enum which) |
… |
… |
|
253 | 256 | #define ASSERT_ARGS_gc_ms_active_sized_buffers __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ |
254 | 257 | PARROT_ASSERT_ARG(mem_pools)) |
255 | 258 | #define ASSERT_ARGS_gc_ms_add_free_object __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ |
256 | | PARROT_ASSERT_ARG(pool) \ |
| 259 | PARROT_ASSERT_ARG(mem_pools) \ |
| 260 | , PARROT_ASSERT_ARG(pool) \ |
257 | 261 | , PARROT_ASSERT_ARG(to_add)) |
258 | 262 | #define ASSERT_ARGS_gc_ms_alloc_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ |
259 | 263 | PARROT_ASSERT_ARG(interp) \ |
… |
… |
|
560 | 564 | ++mem_pools->gc_mark_runs; |
561 | 565 | --mem_pools->gc_mark_block_level; |
562 | 566 | mem_pools->header_allocs_since_last_collect = 0; |
| 567 | mem_pools->mem_used_last_collect = mem_pools->memory_used; |
563 | 568 | |
564 | 569 | return; |
565 | 570 | } |
… |
… |
|
1127 | 1132 | && (pool->top_block->top == (char *)Buffer_bufstart(buffer) + old_size)) { |
1128 | 1133 | pool->top_block->free -= needed; |
1129 | 1134 | pool->top_block->top += needed; |
| 1135 | interp->mem_pools->memory_used += needed; |
1130 | 1136 | Buffer_buflen(buffer) = newsize; |
1131 | 1137 | return; |
1132 | 1138 | } |
… |
… |
|
1239 | 1245 | && pool->top_block->top == (char *)Buffer_bufstart(str) + old_size) { |
1240 | 1246 | pool->top_block->free -= needed; |
1241 | 1247 | pool->top_block->top += needed; |
| 1248 | interp->mem_pools->memory_used += needed; |
1242 | 1249 | Buffer_buflen(str) = new_size - sizeof (void *); |
1243 | 1250 | return; |
1244 | 1251 | } |
… |
… |
|
1260 | 1267 | |
1261 | 1268 | /* Decrease usage */ |
1262 | 1269 | PARROT_ASSERT(Buffer_pool(str)); |
1263 | | Buffer_pool(str)->freed += ALIGNED_STRING_SIZE(Buffer_buflen(str)); |
| 1270 | Buffer_pool(str)->freed += old_size; |
| 1271 | interp->mem_pools->memory_used -= old_size; |
1264 | 1272 | |
1265 | 1273 | /* copy mem from strstart, *not* bufstart */ |
1266 | 1274 | oldmem = str->strstart; |
… |
… |
|
1523 | 1531 | ARGMOD(Fixed_Size_Pool *pool)) |
1524 | 1532 | { |
1525 | 1533 | ASSERT_ARGS(gc_ms_more_traceable_objects) |
| 1534 | size_t new_mem = mem_pools->memory_used - |
| 1535 | mem_pools->mem_used_last_collect; |
1526 | 1536 | |
1527 | | if (pool->skip == GC_ONE_SKIP) |
1528 | | pool->skip = GC_NO_SKIP; |
1529 | | else if (pool->skip == GC_NEVER_SKIP |
1530 | | || (pool->skip == GC_NO_SKIP |
1531 | | && mem_pools->header_allocs_since_last_collect >= GC_SIZE_THRESHOLD)) |
1532 | | Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG); |
| 1537 | if (new_mem > (mem_pools->mem_used_last_collect >> 1) |
| 1538 | && new_mem > GC_SIZE_THRESHOLD) { |
| 1539 | Parrot_gc_mark_and_sweep(interp, GC_trace_stack_FLAG); |
| 1540 | } |
1533 | 1541 | |
1534 | 1542 | /* requires that num_free_objects be updated in Parrot_gc_mark_and_sweep. |
1535 | 1543 | If gc is disabled, then we must check the free list directly. */ |
… |
… |
|
1557 | 1565 | |
1558 | 1566 | static void |
1559 | 1567 | gc_ms_add_free_object(SHIM_INTERP, |
1560 | | SHIM(Memory_Pools *mem_pools), |
| 1568 | ARGMOD(Memory_Pools *mem_pools), |
1561 | 1569 | ARGMOD(Fixed_Size_Pool *pool), |
1562 | 1570 | ARGIN(void *to_add)) |
1563 | 1571 | { |
… |
… |
|
1568 | 1576 | |
1569 | 1577 | object->next_ptr = pool->free_list; |
1570 | 1578 | pool->free_list = object; |
| 1579 | mem_pools->memory_used -= pool->object_size; |
1571 | 1580 | } |
1572 | 1581 | |
1573 | 1582 | /* |
… |
… |
|
1588 | 1597 | PARROT_WARN_UNUSED_RESULT |
1589 | 1598 | static void * |
1590 | 1599 | gc_ms_get_free_object(PARROT_INTERP, |
1591 | | ARGIN(Memory_Pools *mem_pools), |
| 1600 | ARGMOD(Memory_Pools *mem_pools), |
1592 | 1601 | ARGMOD(Fixed_Size_Pool *pool)) |
1593 | 1602 | { |
1594 | 1603 | ASSERT_ARGS(gc_ms_get_free_object) |
… |
… |
|
1630 | 1639 | #endif |
1631 | 1640 | |
1632 | 1641 | --pool->num_free_objects; |
| 1642 | mem_pools->memory_used += pool->object_size; |
1633 | 1643 | |
1634 | 1644 | return ptr; |
1635 | 1645 | } |
… |
… |
|
1682 | 1692 | |
1683 | 1693 | if (alloc_size > POOL_MAX_BYTES) |
1684 | 1694 | pool->objects_per_alloc = POOL_MAX_BYTES / pool->object_size; |
1685 | | |
1686 | | if (alloc_size > GC_SIZE_THRESHOLD) |
1687 | | pool->skip = GC_NEVER_SKIP; |
1688 | 1695 | } |
1689 | 1696 | |
1690 | 1697 | |
diff --git a/src/gc/gc_private.h b/src/gc/gc_private.h
index 66ffdb7..02ea617 100644
a
|
b
|
|
88 | 88 | INF /*infinite memory core*/ |
89 | 89 | } gc_sys_type_enum; |
90 | 90 | |
91 | | /* how often to skip a full GC when this pool has nothing free */ |
92 | | typedef enum _gc_skip_type_enum { |
93 | | GC_NO_SKIP = 0, |
94 | | GC_ONE_SKIP, |
95 | | GC_ALWAYS_SKIP, |
96 | | GC_NEVER_SKIP |
97 | | } gc_skip_type_enum; |
98 | | |
99 | 91 | typedef struct GC_Subsystem { |
100 | 92 | /* Which GC subsystem are we using? See PARROT_GC_DEFAULT_TYPE in |
101 | 93 | * include/parrot/settings.h for possible values */ |
… |
… |
|
237 | 229 | |
238 | 230 | size_t objects_per_alloc; |
239 | 231 | |
240 | | int skip; |
241 | 232 | size_t replenish_level; |
242 | 233 | |
243 | 234 | add_free_object_fn_type add_free_object; /* adds a free object to |
… |
… |
|
294 | 285 | * memory for headers or |
295 | 286 | * internal structures or |
296 | 287 | * anything */ |
| 288 | size_t memory_used; /* The total amount of |
| 289 | * memory used for |
| 290 | * buffers and headers */ |
| 291 | size_t mem_used_last_collect; /* The total amount of |
| 292 | * memory used after |
| 293 | * the last GC run */ |
297 | 294 | UINTVAL memory_collected; /* Total amount of memory copied |
298 | 295 | during collection */ |
299 | 296 | 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 b6baba6..dfa3ae5 100644
a
|
b
|
|
32 | 32 | /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ |
33 | 33 | |
34 | 34 | static void free_buffer(SHIM_INTERP, |
35 | | SHIM(Memory_Pools *mem_pools), |
| 35 | ARGMOD(Memory_Pools *mem_pools), |
36 | 36 | ARGMOD(Fixed_Size_Pool *pool), |
37 | 37 | ARGMOD(Buffer *b)) |
| 38 | __attribute__nonnull__(2) |
38 | 39 | __attribute__nonnull__(3) |
39 | 40 | __attribute__nonnull__(4) |
| 41 | FUNC_MODIFIES(*mem_pools) |
40 | 42 | FUNC_MODIFIES(*pool) |
41 | 43 | FUNC_MODIFIES(*b); |
42 | 44 | |
… |
… |
|
78 | 80 | FUNC_MODIFIES(*mem_pools); |
79 | 81 | |
80 | 82 | #define ASSERT_ARGS_free_buffer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ |
81 | | PARROT_ASSERT_ARG(pool) \ |
| 83 | PARROT_ASSERT_ARG(mem_pools) \ |
| 84 | , PARROT_ASSERT_ARG(pool) \ |
82 | 85 | , PARROT_ASSERT_ARG(b)) |
83 | 86 | #define ASSERT_ARGS_free_pmc_in_pool __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ |
84 | 87 | PARROT_ASSERT_ARG(interp) \ |
… |
… |
|
665 | 668 | |
666 | 669 | static void |
667 | 670 | free_buffer(SHIM_INTERP, |
668 | | SHIM(Memory_Pools *mem_pools), |
| 671 | ARGMOD(Memory_Pools *mem_pools), |
669 | 672 | ARGMOD(Fixed_Size_Pool *pool), |
670 | 673 | ARGMOD(Buffer *b)) |
671 | 674 | { |
… |
… |
|
690 | 693 | |
691 | 694 | /* We can have shared buffers. Don't count them (yet) */ |
692 | 695 | if (!(*buffer_flags & Buffer_shared_FLAG)) { |
693 | | block->freed += ALIGNED_STRING_SIZE(Buffer_buflen(b)); |
| 696 | size_t size = ALIGNED_STRING_SIZE(Buffer_buflen(b)); |
| 697 | block->freed += size; |
| 698 | mem_pools->memory_used -= size; |
694 | 699 | } |
695 | 700 | |
696 | 701 | } |
… |
… |
|
770 | 775 | /* Init the constant string header pool */ |
771 | 776 | mem_pools->constant_string_header_pool = new_string_pool(interp, mem_pools, 1); |
772 | 777 | mem_pools->constant_string_header_pool->name = "constant_string_header"; |
773 | | mem_pools->constant_string_header_pool->skip = GC_ALWAYS_SKIP; |
774 | 778 | |
775 | 779 | /* Init the buffer header pool |
776 | 780 | * |
… |
… |
|
789 | 793 | /* constant PMCs */ |
790 | 794 | mem_pools->constant_pmc_pool = new_pmc_pool(interp); |
791 | 795 | mem_pools->constant_pmc_pool->name = "constant_pmc"; |
792 | | mem_pools->constant_pmc_pool->skip = GC_ALWAYS_SKIP; |
793 | 796 | mem_pools->constant_pmc_pool->objects_per_alloc = |
794 | 797 | CONSTANT_PMC_HEADERS_PER_ALLOC; |
795 | 798 | } |