static void gc_mark(void) { // mark all roots // active tasks gc_push_root(jl_root_task); gc_push_root(jl_current_task); // modules gc_push_root(jl_main_module); gc_push_root(jl_current_module); // invisible builtin values if (jl_an_empty_cell) gc_push_root(jl_an_empty_cell); gc_push_root(jl_exception_in_transit); gc_push_root(jl_task_arg_in_transit); gc_push_root(jl_unprotect_stack_func); gc_push_root(jl_bottom_func); gc_push_root(jl_typetype_type); gc_push_root(jl_tupletype_type); // constants gc_push_root(jl_null); gc_push_root(jl_true); gc_push_root(jl_false); // libuv loops gc_mark_uv_state(jl_global_event_loop()); jl_mark_box_caches(); size_t i; // stuff randomly preserved for(i=0; i < preserved_values.len; i++) { gc_push_root((jl_value_t*)preserved_values.items[i]); } // objects currently being finalized for(i=0; i < to_finalize.len; i++) { gc_push_root(to_finalize.items[i]); } gc_mark_all(); // find unmarked objects that need to be finalized. // this must happen last. for(i=0; i < finalizer_table.size; i+=2) { if (finalizer_table.table[i+1] != HT_NOTFOUND) { jl_value_t *v = finalizer_table.table[i]; if (!gc_marked(v)) { gc_push_root(v); schedule_finalization(v); } gc_push_root(finalizer_table.table[i+1]); } } gc_mark_all(); }
ats_void_type gc_collect () { int overflow, nchunk, nmarkstackpage ; jmp_buf reg_save ; // register contents are roots #ifdef _ATS_MULTITHREAD threadinfolst infolst ; int nother ; #endif /* fprintf( stderr , "GC begs: the_chunk_count = %i and the_chunk_count_limit = %i\n" , the_chunk_count , the_chunk_count_limit ) ; */ setjmp (reg_save) ; // push registers onto the stack asm volatile ("": : :"memory") ; // stop potential optimization nmarkstackpage = (the_chunk_count << CHUNK_WORDSIZE_LOG) ; nmarkstackpage /= (MARKSTACK_PAGESIZE * NCHUNK_PER_MARKSTACKPAGE) ; nmarkstackpage += 1 ; nmarkstackpage -= the_markstackpagecnt ; /* fprintf (stderr, "gc_collect: nmarkstackpage = %i\n", nmarkstackpage) ; */ the_markstack_extend (nmarkstackpage) ; #ifdef _ATS_MULTITHREAD // put all of the other threads into sleep infolst = the_threadinfolst_fst ; nother = 0 ; while (infolst) { if (infolst != the_threadinfolst_self) { fprintf (stderr, "gc_collect: SIGUSR1: infolst->pid = %i\n", (int)(infolst->pid)) ; pthread_kill (infolst->pid, SIGUSR1) ; nother += 1 ; } infolst = infolst->next ; } while (nother) { // ordering is irrelevant fprintf (stderr, "gc_collect: sem_wait: bef: nother = %i\n", nother) ; sem_wait (&the_sleep_semaphore) ; nother -= 1 ; fprintf (stderr, "gc_collect: sem_wait: aft: nother = %i\n", nother) ; } fprintf (stderr, "gc_collect: nother = %i\n", nother) ; #endif // end of [_ATS_MULTITHREAD] gc_markbits_clear_the_topsegtbl () ; // clear all mark bits /* fprintf ( stderr, "gc_collect: gc_markbits_clear_topsegtbl: done\n", nmarkstackpage ) ; // end of [fprintf] */ overflow = gc_mark_all () ; // marking phase /* fprintf (stderr, "gc_collect: gc_mark_all: done\n") ; */ #ifdef _ATS_MULTITHREAD // wake up all of the sleeping threads infolst = the_threadinfolst_fst ; while (infolst) { if (infolst != the_threadinfolst_self) { fprintf (stderr, "gc_collect: SIGUSR2: infolst->pid = %i\n", (int)(infolst->pid)) ; pthread_kill (infolst->pid, SIGUSR2) ; } infolst = infolst->next ; } #endif // end of [_ATS_MULTITHREAD] the_freeitmlst_array_mark_unset () ; /* is this really needed? */ // [gc_mark_threadinfolst_one] is not called on [the_threadinfolst_self] // Therefore [the_freeitmlst_array_clear_all] must be called! the_freeitmlst_array_clear_all () ; /* clear the freeitmlst array */ gc_sweeplst_build_the_topsegtbl () ; // sweep chunks into [the_sweeplst_array] if (overflow > 0) { /* fprintf (stderr, "gc_collect: markstack overflow happend.\n") ; */ the_markstack_extend (MARKSTACK_EXTEND_INCREMENT) ; } /* fprintf( stderr , "GC ends: the_chunk_count = %i and the_chunk_count_limit = %i\n" , the_chunk_count , the_chunk_count_limit ) ; */ if (the_chunk_count_limit_max >= 0) { // [the_chunk_count_limit_max] is finite if (the_chunk_count_limit >= the_chunk_count_limit_max) { // fprintf(stderr, "GC: the_chunk_count_limit = %i\n", the_chunk_count_limit) ; // fprintf(stderr, "GC: the_chunk_count_limit_max = %i\n", the_chunk_count_limit_max) ; fprintf(stderr, "GC: Warning: the maximal chunk count limit is reached!\n") ; return ; } } /* end of [if] */ if (the_chunk_count >= the_chunk_count_limit * CHUNK_LIMIT_EXTEND_CUTOFF) the_chunk_count_limit *= 2 ; /* fprintf( stderr , "GC ends: update: the_chunk_count_limit = %i\n", the_chunk_count_limit ) ; */ return ; } /* end of [gc_collect] */