43
43
static int gc_ms_active_sized_buffers(ARGIN(const Memory_Pools *mem_pools))
44
44
__attribute__nonnull__(1);
46
static void gc_ms_add_free_object(SHIM_INTERP,
47
ARGMOD(Memory_Pools *mem_pools),
46
static void gc_ms_add_free_object(PARROT_INTERP,
47
SHIM(Memory_Pools *mem_pools),
48
48
ARGMOD(Fixed_Size_Pool *pool),
49
49
ARGIN(void *to_add))
50
__attribute__nonnull__(2)
50
__attribute__nonnull__(1)
51
51
__attribute__nonnull__(3)
52
52
__attribute__nonnull__(4)
53
FUNC_MODIFIES(*mem_pools)
54
53
FUNC_MODIFIES(*pool);
56
55
static void gc_ms_alloc_objects(PARROT_INTERP,
67
66
__attribute__nonnull__(1);
70
PARROT_CANNOT_RETURN_NULL
69
PARROT_CAN_RETURN_NULL
71
70
static void * gc_ms_allocate_memory_chunk(SHIM_INTERP, size_t size);
74
PARROT_CANNOT_RETURN_NULL
73
PARROT_CAN_RETURN_NULL
75
74
static void * gc_ms_allocate_memory_chunk_zeroed(SHIM_INTERP, size_t size);
77
76
PARROT_CANNOT_RETURN_NULL
84
83
static PMC* gc_ms_allocate_pmc_header(PARROT_INTERP, UINTVAL flags)
85
84
__attribute__nonnull__(1);
86
PARROT_WARN_UNUSED_RESULT
87
87
PARROT_CAN_RETURN_NULL
88
88
static STRING* gc_ms_allocate_string_header(PARROT_INTERP, UINTVAL flags)
89
89
__attribute__nonnull__(1);
155
155
static unsigned int gc_ms_is_blocked_GC_sweep(PARROT_INTERP)
156
156
__attribute__nonnull__(1);
158
PARROT_WARN_UNUSED_RESULT
159
static int gc_ms_is_pmc_ptr(PARROT_INTERP, ARGIN_NULLOK(void *ptr))
160
__attribute__nonnull__(1);
162
PARROT_WARN_UNUSED_RESULT
163
static int gc_ms_is_string_ptr(PARROT_INTERP, ARGIN_NULLOK(void *ptr))
164
__attribute__nonnull__(1);
158
166
static void gc_ms_iterate_live_strings(PARROT_INTERP,
159
167
string_iterator_callback callback,
160
168
ARGIN_NULLOK(void *data))
163
171
static void gc_ms_mark_and_sweep(PARROT_INTERP, UINTVAL flags)
164
172
__attribute__nonnull__(1);
174
static void gc_ms_mark_pobj_header(SHIM_INTERP, ARGMOD_NULLOK(PObj *obj))
166
177
static void gc_ms_mark_special(PARROT_INTERP, ARGIN(PMC *pmc))
167
178
__attribute__nonnull__(1)
168
179
__attribute__nonnull__(2);
170
181
static void gc_ms_more_traceable_objects(PARROT_INTERP,
171
ARGIN(Memory_Pools *mem_pools),
182
SHIM(Memory_Pools *mem_pools),
172
183
ARGMOD(Fixed_Size_Pool *pool))
173
184
__attribute__nonnull__(1)
174
__attribute__nonnull__(2)
175
185
__attribute__nonnull__(3)
176
186
FUNC_MODIFIES(*pool);
252
262
#define ASSERT_ARGS_gc_ms_active_sized_buffers __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
253
263
PARROT_ASSERT_ARG(mem_pools))
254
264
#define ASSERT_ARGS_gc_ms_add_free_object __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
255
PARROT_ASSERT_ARG(mem_pools) \
265
PARROT_ASSERT_ARG(interp) \
256
266
, PARROT_ASSERT_ARG(pool) \
257
267
, PARROT_ASSERT_ARG(to_add))
258
268
#define ASSERT_ARGS_gc_ms_alloc_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
308
318
PARROT_ASSERT_ARG(interp))
309
319
#define ASSERT_ARGS_gc_ms_is_blocked_GC_sweep __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
310
320
PARROT_ASSERT_ARG(interp))
321
#define ASSERT_ARGS_gc_ms_is_pmc_ptr __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
322
PARROT_ASSERT_ARG(interp))
323
#define ASSERT_ARGS_gc_ms_is_string_ptr __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
324
PARROT_ASSERT_ARG(interp))
311
325
#define ASSERT_ARGS_gc_ms_iterate_live_strings __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
312
326
PARROT_ASSERT_ARG(interp))
313
327
#define ASSERT_ARGS_gc_ms_mark_and_sweep __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
314
328
PARROT_ASSERT_ARG(interp))
329
#define ASSERT_ARGS_gc_ms_mark_pobj_header __attribute__unused__ int _ASSERT_ARGS_CHECK = (0)
315
330
#define ASSERT_ARGS_gc_ms_mark_special __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
316
331
PARROT_ASSERT_ARG(interp) \
317
332
, PARROT_ASSERT_ARG(pmc))
318
333
#define ASSERT_ARGS_gc_ms_more_traceable_objects __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
319
334
PARROT_ASSERT_ARG(interp) \
320
, PARROT_ASSERT_ARG(mem_pools) \
321
335
, PARROT_ASSERT_ARG(pool))
322
336
#define ASSERT_ARGS_gc_ms_pool_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
323
337
PARROT_ASSERT_ARG(pool))
400
414
interp->gc_sys->allocate_bufferlike_header = gc_ms_allocate_bufferlike_header;
401
415
interp->gc_sys->free_bufferlike_header = gc_ms_free_bufferlike_header;
417
interp->gc_sys->is_pmc_ptr = gc_ms_is_pmc_ptr;
418
interp->gc_sys->is_string_ptr = gc_ms_is_string_ptr;
419
interp->gc_sys->mark_pmc_header = gc_ms_mark_pmc_header;
420
interp->gc_sys->mark_pobj_header = gc_ms_mark_pobj_header;
403
422
interp->gc_sys->allocate_pmc_attributes = gc_ms_allocate_pmc_attributes;
404
423
interp->gc_sys->free_pmc_attributes = gc_ms_free_pmc_attributes;
434
453
interp->gc_sys->iterate_live_strings = gc_ms_iterate_live_strings;
455
/* gc_private is @objects */
456
interp->gc_sys->gc_private = Parrot_list_new(interp);
436
459
Parrot_gc_str_initialize(interp, &interp->mem_pools->string_gc);
437
460
initialize_fixed_size_pools(interp, interp->mem_pools);
438
461
Parrot_gc_initialize_fixed_size_pools(interp, interp->mem_pools,
530
PARROT_WARN_UNUSED_RESULT
508
533
Parrot_gc_ms_needed(PARROT_INTERP)
510
535
ASSERT_ARGS(Parrot_gc_ms_needed)
512
const Memory_Pools * const mem_pools = interp->mem_pools;
513
537
size_t dynamic_threshold;
515
539
/* new_mem is the additional amount of memory used since the last GC */
516
size_t new_mem = mem_pools->memory_used
517
- mem_pools->mem_used_last_collect;
540
size_t new_mem = interp->gc_sys->stats.memory_used
541
- interp->gc_sys->stats.mem_used_last_collect;
519
543
/* Never run a GC if new_mem is below static GC_SIZE_THRESHOLD */
520
544
if (new_mem <= GC_SIZE_THRESHOLD)
523
547
/* The dynamic threshold is a configurable percentage of the amount of
524
548
memory used after the last GC */
525
dynamic_threshold = (size_t)(mem_pools->mem_used_last_collect *
549
dynamic_threshold = (size_t)(interp->gc_sys->stats.mem_used_last_collect *
526
550
(0.01 * interp->gc_threshold));
528
552
return new_mem > dynamic_threshold;
592
616
pt_gc_stop_mark(interp);
595
++mem_pools->gc_mark_runs;
619
++interp->gc_sys->stats.gc_mark_runs;
620
interp->gc_sys->stats.header_allocs_since_last_collect = 0;
596
622
--mem_pools->gc_mark_block_level;
597
mem_pools->header_allocs_since_last_collect = 0;
598
mem_pools->mem_used_last_collect = mem_pools->memory_used;
623
interp->gc_sys->stats.header_allocs_since_last_collect = 0;
624
interp->gc_sys->stats.mem_used_last_collect = interp->gc_sys->stats.memory_used;
806
=item C<void gc_ms_mark_pmc_header(PARROT_INTERP, PMC *obj)>
808
Mark the PMC *obj as live and attach PMCs and/or buffers
815
gc_ms_mark_pmc_header(PARROT_INTERP, ARGMOD_NULLOK(PMC *obj))
817
ASSERT_ARGS(gc_ms_mark_pmc_header)
818
if (!PMC_IS_NULL(obj)) {
819
PARROT_ASSERT(PObj_is_PMC_TEST(obj));
821
if (PObj_is_live_or_free_TESTALL(obj))
827
/* if object is a PMC and contains buffers or PMCs, then attach the PMC
828
* to the chained mark list. */
829
if (PObj_is_special_PMC_TEST(obj)) {
830
if (PObj_custom_mark_TEST(obj))
831
VTABLE_mark(interp, obj);
834
if (PMC_metadata(obj))
835
Parrot_gc_mark_PMC_alive(interp, PMC_metadata(obj));
841
=item C<static int gc_ms_is_pmc_ptr(PARROT_INTERP, void *ptr)>
843
return True if *ptr is contained in the pool
849
PARROT_WARN_UNUSED_RESULT
851
gc_ms_is_pmc_ptr(PARROT_INTERP, ARGIN_NULLOK(void *ptr))
853
ASSERT_ARGS(gc_ms_is_pmc_ptr)
854
return contained_in_pool(interp->mem_pools->pmc_pool, ptr);
859
=item C<static int gc_ms_is_string_ptr(PARROT_INTERP, void *ptr)>
861
establish if string *ptr is owned
867
PARROT_WARN_UNUSED_RESULT
869
gc_ms_is_string_ptr(PARROT_INTERP, ARGIN_NULLOK(void *ptr))
871
ASSERT_ARGS(gc_ms_is_string_ptr)
874
for (i = 0; i < interp->mem_pools->num_sized; ++i) {
875
if (interp->mem_pools->sized_header_pools[i]
876
&& contained_in_pool(interp->mem_pools->sized_header_pools[i], ptr))
780
885
=item C<static STRING* gc_ms_allocate_string_header(PARROT_INTERP, UINTVAL
795
902
? interp->mem_pools->constant_string_header_pool
796
903
: interp->mem_pools->string_header_pool;
798
STRING *s = (STRING *)pool->get_free_object(interp, interp->mem_pools, pool);
905
STRING * const s = (STRING *)pool->get_free_object(interp, interp->mem_pools, pool);
799
906
memset(s, 0, sizeof (STRING));
934
=item C<static void gc_ms_mark_pobj_header(PARROT_INTERP, PObj *obj)>
943
gc_ms_mark_pobj_header(SHIM_INTERP, ARGMOD_NULLOK(PObj *obj))
945
ASSERT_ARGS(gc_ms_mark_pobj_header)
827
954
=item C<static Buffer * gc_ms_allocate_bufferlike_header(PARROT_INTERP, size_t
1218
1345
#ifdef DETAIL_MEMORY_DEBUG
1219
1346
fprintf(stderr, "Allocated %i at %p\n", size, ptr);
1222
1349
PANIC_OUT_OF_MEM(size);
1227
PARROT_CANNOT_RETURN_NULL
1354
PARROT_CAN_RETURN_NULL
1229
1356
gc_ms_reallocate_memory_chunk(SHIM_INTERP, ARGFREE(void *from), size_t size)
1240
1367
#ifdef DETAIL_MEMORY_DEBUG
1241
1368
fprintf(stderr, "Allocated %i at %p\n", size, ptr);
1244
1371
PANIC_OUT_OF_MEM(size);
1249
PARROT_CANNOT_RETURN_NULL
1376
PARROT_CAN_RETURN_NULL
1251
1378
gc_ms_allocate_memory_chunk_zeroed(SHIM_INTERP, size_t size)
1385
1512
gc_ms_more_traceable_objects(PARROT_INTERP,
1386
ARGIN(Memory_Pools *mem_pools),
1513
SHIM(Memory_Pools *mem_pools),
1387
1514
ARGMOD(Fixed_Size_Pool *pool))
1389
1516
ASSERT_ARGS(gc_ms_more_traceable_objects)
1418
gc_ms_add_free_object(SHIM_INTERP,
1419
ARGMOD(Memory_Pools *mem_pools),
1545
gc_ms_add_free_object(PARROT_INTERP,
1546
SHIM(Memory_Pools *mem_pools),
1420
1547
ARGMOD(Fixed_Size_Pool *pool),
1421
1548
ARGIN(void *to_add))
1633
1760
Memory_Pools * const mem_pools = interp->mem_pools;
1634
1761
switch (which) {
1635
case TOTAL_MEM_ALLOC:
1636
return mem_pools->memory_allocated;
1638
return mem_pools->gc_mark_runs;
1639
case GC_COLLECT_RUNS:
1640
return mem_pools->gc_collect_runs;
1641
1762
case ACTIVE_PMCS:
1642
1763
return mem_pools->pmc_pool->total_objects -
1643
1764
mem_pools->pmc_pool->num_free_objects;
1647
1768
return mem_pools->pmc_pool->total_objects;
1648
1769
case TOTAL_BUFFERS:
1649
1770
return gc_ms_total_sized_buffers(mem_pools);
1771
case IMPATIENT_PMCS:
1772
return mem_pools->num_early_gc_PMCs;
1774
return Parrot_gc_get_info(interp, which, &interp->gc_sys->stats);
1781
TODO Move it somewhere.
1786
=item C<size_t Parrot_gc_get_info(PARROT_INTERP, Interpinfo_enum which,
1787
GC_Statistics *stats)>
1789
returns stats as required by enum which
1795
PARROT_WARN_UNUSED_RESULT
1796
PARROT_PURE_FUNCTION
1798
Parrot_gc_get_info(SHIM_INTERP, Interpinfo_enum which, ARGIN(GC_Statistics *stats))
1800
ASSERT_ARGS(Parrot_gc_get_info)
1803
case TOTAL_MEM_ALLOC:
1804
return stats->memory_allocated;
1806
return stats->gc_mark_runs;
1807
case GC_COLLECT_RUNS:
1808
return stats->gc_collect_runs;
1650
1809
case HEADER_ALLOCS_SINCE_COLLECT:
1651
return mem_pools->header_allocs_since_last_collect;
1810
return stats->header_allocs_since_last_collect;
1652
1811
case MEM_ALLOCS_SINCE_COLLECT:
1653
return mem_pools->mem_allocs_since_last_collect;
1812
return stats->mem_allocs_since_last_collect;
1654
1813
case TOTAL_COPIED:
1655
return mem_pools->memory_collected;
1656
case IMPATIENT_PMCS:
1657
return mem_pools->num_early_gc_PMCs;
1814
return stats->memory_collected;
1658
1815
case GC_LAZY_MARK_RUNS:
1659
return mem_pools->gc_lazy_mark_runs;
1816
return stats->gc_lazy_mark_runs;