Skip to content

Commit

Permalink
[gc] check -D1 in startup, add -D2xx MEM_DETAIL_DEBUG_FLAG
Browse files Browse the repository at this point in the history
Print GS and Memory info on -D1.
Add seperate GC_DEBUG_DETAIL_2 tracer to seperate it from
MEM_DETAIL_DEBUG_FLAG tracing for every single alloc/free.
Document the two new -D100 and -D200 flags with --ccflags=-DMEMORY_DEBUG
  • Loading branch information
Reini Urban committed Nov 8, 2014
1 parent c983e15 commit 9a75015
Show file tree
Hide file tree
Showing 13 changed files with 76 additions and 15 deletions.
2 changes: 1 addition & 1 deletion docs/binaries/parrot.pod
Expand Up @@ -197,7 +197,7 @@ removal of unused labels and dead code.

-Op applies -O2 to pasm files also.

The old options -Oc and -Oj are currently ineffective.
The old options -Oc (tailcall) and -Oj are currently ineffective.

-O defaults to -O1.

Expand Down
17 changes: 17 additions & 0 deletions docs/running.pod
Expand Up @@ -160,11 +160,28 @@ This turns off GC. This may be useful to find GC related bugs. Don't use this
option for longer running programs: as memory is no longer recycled, it may
quickly become exhausted.

=item --gc-nursery-size=percent

Default: 2

=item --gc-dynamic-threshold=percent

Default: 75

=item --gc-min-threshold=MB

Default: 4

=item --leak-test, --destroy-at-end

Free all memory of the last interpreter. This is useful when running leak
checkers.

=item --numthreads=number

Overrides the automatically detected number of CPU cores to set the
number of OS threads. Minimum number: 2

=back

=head1 ABOUT RUNCORES
Expand Down
10 changes: 10 additions & 0 deletions frontend/parrot/main.c
Expand Up @@ -485,6 +485,10 @@ help_debug(void)
" 0020 eval/compile\n"
" 0040 fill I, N registers with garbage\n"
" 0080 show when a context is destroyed\n"
#ifdef MEMORY_DEBUG
" 0100 GC traces\n"
" 0200 every single alloc/free\n"
#endif
"\n"
"--trace -t [Flags] ...\n"
" 0001 opcodes\n"
Expand Down Expand Up @@ -681,6 +685,12 @@ parseflags_minimal(ARGMOD(Parrot_Init_Args * initargs), int argc, ARGIN(const ch
case 'g':
initargs->gc_system = opt.opt_arg;
break;
case 'D':
if (opt.opt_arg && is_all_hex_digits(opt.opt_arg))
initargs->debug_flags = strtoul(opt.opt_arg, NULL, 16);
else
initargs->debug_flags = PARROT_MEM_STAT_DEBUG_FLAG;
break;
case OPT_GC_DYNAMIC_THRESHOLD:
if (opt.opt_arg && is_all_digits(opt.opt_arg)) {
initargs->gc_dynamic_threshold = strtoul(opt.opt_arg, NULL, 10);
Expand Down
10 changes: 10 additions & 0 deletions frontend/parrot2/main.c
Expand Up @@ -397,6 +397,10 @@ help_debug(void)
" 0020 eval/compile\n"
" 0040 fill I, N registers with garbage\n"
" 0080 show when a context is destroyed\n"
#ifdef MEMORY_DEBUG
" 0100 GC traces\n"
" 0200 every single alloc/free\n"
#endif
"\n"
"--trace -t [Flags] ...\n"
" 0001 opcodes\n"
Expand Down Expand Up @@ -507,6 +511,12 @@ parseflags_minimal(ARGMOD(Parrot_Init_Args * initargs), int argc, ARGIN(const ch
case 'g':
initargs->gc_system = opt.opt_arg;
break;
case 'D':
if (opt.opt_arg && is_all_hex_digits(opt.opt_arg))
initargs->debug_flags = strtoul(opt.opt_arg, NULL, 16);
else
initargs->debug_flags = PARROT_MEM_STAT_DEBUG_FLAG;
break;
case OPT_GC_DYNAMIC_THRESHOLD:
if (opt.opt_arg && is_all_digits(opt.opt_arg)) {
initargs->gc_dynamic_threshold = strtoul(opt.opt_arg, NULL, 10);
Expand Down
1 change: 1 addition & 0 deletions include/parrot/api.h
Expand Up @@ -78,6 +78,7 @@ typedef struct _Parrot_Init_Args {
Parrot_Int gc_min_threshold;
Parrot_UInt hash_seed;
Parrot_UInt numthreads;
Parrot_UInt debug_flags;
} Parrot_Init_Args;

#define GET_INIT_STRUCT(i) do {\
Expand Down
1 change: 1 addition & 0 deletions include/parrot/gc_api.h
Expand Up @@ -41,6 +41,7 @@ typedef struct _Parrot_GC_Init_Args {
Parrot_Int dynamic_threshold;
Parrot_Int min_threshold;
Parrot_UInt numthreads;
Parrot_UInt debug_flags;
} Parrot_GC_Init_Args;

typedef enum _gc_sys_type_enum {
Expand Down
5 changes: 3 additions & 2 deletions include/parrot/interpreter.h
Expand Up @@ -30,15 +30,16 @@ typedef enum {
/* &gen_from_enum(interpdebug.pasm) */
typedef enum {
PARROT_NO_DEBUG = 0x00,
PARROT_MEM_STAT_DEBUG_FLAG = 0x01, /* memory usage summary */
PARROT_MEM_STAT_DEBUG_FLAG = 0x01, /* memory/gc usage summary */
PARROT_BACKTRACE_DEBUG_FLAG = 0x02, /* print bt in exception */
PARROT_JIT_DEBUG_FLAG = 0x04, /* create jit stabs file (unused) */
PARROT_START_DEBUG_FLAG = 0x08,
PARROT_THREAD_DEBUG_FLAG = 0x10,
PARROT_EVAL_DEBUG_FLAG = 0x20, /* create EVAL_n file */
PARROT_REG_DEBUG_FLAG = 0x40, /* fill I,N with garbage */
PARROT_CTX_DESTROY_DEBUG_FLAG = 0x80, /* ctx of a sub is gone */
PARROT_GC_DETAIL_DEBUG_FLAG = 0x100,
PARROT_GC_DETAIL_DEBUG_FLAG = 0x100, /* formerly DETAIL_MEMORY_DEBUG */
PARROT_MEM_DETAIL_DEBUG_FLAG = 0x200, /* every single malloc/free */
PARROT_ALL_DEBUG_FLAGS = 0xffff
} Parrot_debug_flags;
/* &end_gen */
Expand Down
1 change: 1 addition & 0 deletions src/embed/api.c
Expand Up @@ -143,6 +143,7 @@ Parrot_api_make_interpreter(Parrot_PMC parent, Parrot_Int flags,
gc_args.nursery_size = args->gc_nursery_size;
gc_args.dynamic_threshold = args->gc_dynamic_threshold;
gc_args.min_threshold = args->gc_min_threshold;
gc_args.debug_flags = args->debug_flags;
gc_args.numthreads = args->numthreads;

if (args->hash_seed)
Expand Down
4 changes: 4 additions & 0 deletions src/gc/api.c
Expand Up @@ -205,6 +205,10 @@ Parrot_gc_initialize(PARROT_INTERP, ARGIN(Parrot_GC_Init_Args *args))
fprintf(stderr, "Unknown GC type '%s'\n", args->system);
PANIC(interp, "Cannot activate GC");
}
#ifndef NDEBUG
if (Interp_debug_TEST(interp, PARROT_MEM_STAT_DEBUG_FLAG))
fprintf(stderr, "GC type '%s'\n", args->system);
#endif
}

switch (interp->gc_sys->sys_type) {
Expand Down
28 changes: 19 additions & 9 deletions src/gc/gc_gms.c
Expand Up @@ -766,9 +766,16 @@ Parrot_gc_gms_init(PARROT_INTERP, ARGIN(Parrot_GC_Init_Args *args))
/*
* Collect every nursery_size/100 of system memory.
*
* Configured by runtime parameter (default 2%).
* Configured by runtime parameter, default 2%.
* or --gc-nursery-size=2 [default]
*/
self->gc_threshold = Parrot_sysmem_amount(interp) * nursery_size / 100;
#ifndef NDEBUG
if (Interp_debug_TEST(interp, PARROT_MEM_STAT_DEBUG_FLAG)) {
fprintf(stderr, "GC nursery size: %f\n", nursery_size);
fprintf(stderr, "GMS GC threshold: %ld\n", self->gc_threshold);
}
#endif

Parrot_gc_str_initialize(interp, &self->string_gc);
}
Expand Down Expand Up @@ -1438,7 +1445,7 @@ gc_gms_finalize(PARROT_INTERP)
{
ASSERT_ARGS(gc_gms_finalize)
MarkSweep_GC * const self = (MarkSweep_GC *)interp->gc_sys->gc_private;
size_t i;
size_t i;

Parrot_gc_str_finalize(interp, &self->string_gc);

Expand All @@ -1456,8 +1463,7 @@ gc_gms_finalize(PARROT_INTERP)
=item C<gc_gms_maybe_mark_and_sweep(PARROT_INTERP)>
Maybe M&S. Depends on total allocated memory, memory allocated since last alloc
and phase of the Moon.
Maybe M&S. Depends on total allocated memory, memory allocated since last alloc.
=cut
Expand Down Expand Up @@ -1800,7 +1806,7 @@ gc_gms_iterate_live_strings(PARROT_INTERP,
ASSERT_ARGS(gc_gms_iterate_live_strings)

MarkSweep_GC * const self = (MarkSweep_GC *)interp->gc_sys->gc_private;
size_t i;
size_t i;
for (i = 0; i < MAX_GENERATIONS; i++) {
POINTER_ARRAY_ITER(self->strings[i],
STRING *s = &((string_alloc_struct *)ptr)->str;
Expand Down Expand Up @@ -2251,15 +2257,19 @@ gc_gms_check_sanity(PARROT_INTERP)
UNUSED(interp)
#else
MarkSweep_GC * const self = (MarkSweep_GC *)interp->gc_sys->gc_private;
size_t i;
size_t i;

for (i = 0; i < MAX_GENERATIONS; i++) {
POINTER_ARRAY_ITER(self->objects[i],
PMC *pmc = &(((pmc_alloc_struct*)ptr)->pmc);
const size_t gen = POBJ2GEN(pmc);
PARROT_GC_ASSERT_INTERP(pmc, interp);
MEMORY_DEBUG_DETAIL_3("GC live pmc %-21s gen %ld at %p\n",
if (i < 3) /* too many objects in gen3 */
GC_DEBUG_DETAIL_3("GC live pmc %-21s gen %ld at %p\n",
pmc->vtable->whoami->strstart, gen, pmc);
if (gen != i)
fprintf(stderr, "GC live pmc %-21s gen %ld != %ld at %p\n",
pmc->vtable->whoami->strstart, gen, i, pmc);
PARROT_ASSERT((gen == i)
|| !"Object from wrong generation");

Expand All @@ -2276,15 +2286,15 @@ gc_gms_check_sanity(PARROT_INTERP)
POINTER_ARRAY_ITER(self->dirty_list,
PMC *pmc = &(((pmc_alloc_struct*)ptr)->pmc);
PARROT_GC_ASSERT_INTERP(pmc, interp);
MEMORY_DEBUG_DETAIL_2("GC dirty pmc %-21s at %p\n",
GC_DEBUG_DETAIL_2("GC dirty pmc %-21s at %p\n",
pmc->vtable->whoami->strstart, pmc);
PARROT_ASSERT(PObj_GC_on_dirty_list_TEST(pmc)
|| !"Object in dirty_list without dirty_flag"););

POINTER_ARRAY_ITER(self->work_list,
PMC *pmc = &(((pmc_alloc_struct*)ptr)->pmc);
PARROT_GC_ASSERT_INTERP(pmc, interp);
MEMORY_DEBUG_DETAIL_2("GC work pmc %-21s at %p\n",
GC_DEBUG_DETAIL_2("GC work pmc %-21s at %p\n",
pmc->vtable->whoami->strstart, pmc);
PARROT_ASSERT(!PObj_GC_on_dirty_list_TEST(pmc)
|| !"Dirty object in work_list"););
Expand Down
2 changes: 1 addition & 1 deletion src/gc/gc_ms2.c
Expand Up @@ -1448,7 +1448,7 @@ gc_ms2_free_memory_chunk(PARROT_INTERP, ARGFREE(void *data))
=item C<static void gc_ms2_pmc_needs_early_collection(PARROT_INTERP, PMC *pmc)>
Marks a PMC as needing timely destruction.
Helper function to count how many PMCs need timely destruction.
=cut
Expand Down
9 changes: 7 additions & 2 deletions src/gc/gc_private.h
Expand Up @@ -32,13 +32,18 @@ extern int CONSERVATIVE_POINTER_CHASING;

#ifndef MEMORY_DEBUG
# define MEMORY_DEBUG_DETAIL_2(s, a1, a2)
# define MEMORY_DEBUG_DETAIL_3(s, a1, a2, a3)
# define GC_DEBUG_DETAIL_2(s, a1, a2)
# define GC_DEBUG_DETAIL_3(s, a1, a2, a3)
#else
# define MEMORY_DEBUG_DETAIL_2(s, a1, a2) \
if (Interp_debug_TEST(interp, \
PARROT_MEM_STAT_DEBUG_FLAG | PARROT_MEM_DETAIL_DEBUG_FLAG)) \
fprintf(stderr, (s), (a1), (a2))
# define GC_DEBUG_DETAIL_2(s, a1, a2) \
if (Interp_debug_TEST(interp, \
PARROT_MEM_STAT_DEBUG_FLAG | PARROT_GC_DETAIL_DEBUG_FLAG)) \
fprintf(stderr, (s), (a1), (a2))
# define MEMORY_DEBUG_DETAIL_3(s, a1, a2, a3) \
# define GC_DEBUG_DETAIL_3(s, a1, a2, a3) \
if (Interp_debug_TEST(interp, \
PARROT_MEM_STAT_DEBUG_FLAG | PARROT_GC_DETAIL_DEBUG_FLAG)) \
fprintf(stderr, (s), (a1), (a2), (a3))
Expand Down
1 change: 1 addition & 0 deletions src/interp/api.c
Expand Up @@ -251,6 +251,7 @@ Parrot_interp_initialize_interpreter(PARROT_INTERP, ARGIN(Parrot_GC_Init_Args *a
int numthr;

/* Set up the memory allocation system */
interp->debug_flags = args->debug_flags;
Parrot_gc_initialize(interp, args);
Parrot_block_GC_mark(interp);
Parrot_block_GC_sweep(interp);
Expand Down

0 comments on commit 9a75015

Please sign in to comment.