/* FIXME: Worth optimizing! Pass more than one object to the scanner. */ void rs_enumerate( remset_t *rs, bool (*scanner)( word, void*, unsigned* ), void *data ) { pool_t *ps; word *p, *q; unsigned word_count = 0; unsigned removed_count=0; unsigned scanned = 0; unsigned scanned_all = 0; assert( WORDS_PER_POOL_ENTRY == 2 ); supremely_annoyingmsg( "REMSET @0x%p: scan", (void*)rs ); ps = DATA(rs)->first_pool; while (1) { p = ps->bot; q = ps->top; scanned_all += (q-p)/2; /* Zero entries also */ while (p < q) { if (*p != 0) { #if !GCLIB_LARGE_TABLE /* These attributes not defined then */ #ifndef NDEBUG2 if ( (attr_of(*p) & (MB_ALLOCATED|MB_HEAP_MEMORY)) != (MB_ALLOCATED|MB_HEAP_MEMORY) ) { assert2(attr_of(*p) & MB_ALLOCATED); assert2(attr_of(*p) & MB_HEAP_MEMORY); } #endif #endif if (!scanner( *p, data, &word_count )) { /* Clear the slot by setting the pointer to 0. */ *p = (word)(word*)0; removed_count++; } scanned++; /* Only nonzero entries */ } p += 2; } if (ps == DATA(rs)->curr_pool) break; ps = ps->next; } DATA(rs)->stats.objs_scanned += scanned; DATA(rs)->stats.max_objs_scanned = max( DATA(rs)->stats.max_objs_scanned, scanned ); DATA(rs)->stats.words_scanned += word_count; DATA(rs)->stats.max_words_scanned = max( DATA(rs)->stats.max_words_scanned, word_count ); DATA(rs)->stats.removed += removed_count; rs->live -= removed_count; DATA(rs)->stats.scanned++; supremely_annoyingmsg( "REMSET @0x%x: removed %d elements (total %d).", (word)rs, removed_count, DATA(rs)->stats.removed ); }
int stk_create( word *globals ) { word *stktop; assert( globals[G_STKP] - SCE_BUFFER >= globals[ G_ETOP ] && globals[G_STKP] <= globals[ G_ELIM ] ); stktop = (word*)globals[ G_STKP ]; stktop -= 4; if (stktop < (word*)globals[ G_ETOP ]) { supremely_annoyingmsg( "Failed to create stack."); return 0; } *(stktop+STK_CONTSIZE) = fixnum(3); /* header/size field */ *(stktop+STK_RETADDR) = 0xDEADBEEF; /* retaddr: uflow handler */ *(stktop+STK_DYNLINK) = 0xDEADBEEF; /* dynamic link field */ *(stktop+STK_PROC) = 0xDEADBEEF; /* saved procedure */ stk_initialize_underflow_frame( stktop ); /* In client space */ globals[ G_STKP ] = (word)stktop; globals[ G_STKBOT ] = (word)stktop; stack_state.stacks_created += 1; return 1; }
/* C_restore_frame: stack underflowed, restore a frame */ void C_restore_frame( void ) { supremely_annoyingmsg( "Stack underflow exception in millicode." ); in_noninterruptible_syscall = 1; gc_stack_underflow( the_gc( globals ) ); in_noninterruptible_syscall = 0; }
/* C_creg_set: reinstate a continuation */ void C_creg_set( void ) { supremely_annoyingmsg( "Throw exception in millicode." ); in_noninterruptible_syscall = 1; gc_creg_set( the_gc( globals ), globals[ G_RESULT ] ); in_noninterruptible_syscall = 0; }
/* C_creg_get: capture the current continuation. */ void C_creg_get( void ) { supremely_annoyingmsg( "Call/cc exception in millicode." ); in_noninterruptible_syscall = 1; globals[ G_RESULT ] = gc_creg_get( the_gc( globals ) ); in_noninterruptible_syscall = 0; }
/* C_stack_overflow: overflow handling depends on stack */ void C_stack_overflow( void ) { supremely_annoyingmsg( "Stack overflow exception in millicode." ); in_noninterruptible_syscall = 1; gc_stack_overflow( the_gc( globals ) ); in_noninterruptible_syscall = 0; }
static void rs_clear_opt( remset_t *rs, bool use_recycle_pool ) { remset_data_t *data = DATA(rs); word *p; int i; supremely_annoyingmsg( "REMSET @0x%p: clear", (void*)rs ); /* Clear hash table */ for ( p=data->tbl_bot, i=data->tbl_lim-data->tbl_bot ; i > 0 ; p++, i-- ) *p = (word)(word*)0; /* Clear pools */ data->first_pool->top = data->first_pool->bot; data->curr_pool = data->first_pool; if (use_recycle_pool) { assert( recycled_pool == NULL ); assert( recycled_pool_entries_per <= 0 ); recycled_pool = data->first_pool->next; recycled_pool_entries_per = data->pool_entries; } else { free_pool_segments( data->first_pool->next, data->pool_entries ); } data->first_pool->next = 0; rs->has_overflowed = FALSE; rs->live = 0; data->numpools = 1; data->stats.cleared++; }
/* Request is ignored -- doesn't make sense in nursery. */ static void collect( young_heap_t *heap, int nbytes, int request ) { young_data_t *data = DATA(heap); supremely_annoyingmsg( "nursery: promoting (free=%d; request=%d)%s", free_space( heap ), nbytes, (nbytes == 0 ? " [stack overflow]" : "" ) ); #if PROFILE_FOR_FAST_REMSET { word *p; word *globals = data->globals; for ( p=(word*)globals[G_EBOT]; p < (word*)globals[G_ETOP] ; p++ ) { nursery.words_scanned++; if ((((word)p ^ *p) & BLOCKMASK) == 0) nursery.fast_check_succeeds++; if (isptr(*p)) { nursery.ptrs_scanned++; if ((((word)p ^ *p) & BLOCKMASK) == 0) nursery.ptr_same_block++; } } } #endif /* Why did Lars pass 0 instead of nbytes below? */ gc_collect( heap->collector, data->gen_no, 0, GCTYPE_EVACUATE ); data->nbytes_wanted = nbytes; /* For use in after_collection() */ }
/* NOTE: A copy of this code exists in Sparc/memory.s; if you change * anything here, check that code as well. */ int stk_restore_frame( word *globals ) { word *stktop, *hframe, *p; word retoffs, proc, codeaddr, codeptr, header; unsigned size; assert2(globals[ G_STKP ] == globals[ G_STKBOT ]); hframe = ptrof( globals[ G_CONT ] ); size = roundup8( sizefield( *hframe ) + 4 ); /* bytes to copy */ stktop = (word*)globals[ G_STKP ]; stktop -= size / 4; if (stktop < (word*)globals[ G_ETOP ]) { supremely_annoyingmsg( "Failed to create stack." ); return 0; } globals[ G_STKP ] = (word)stktop; globals[ G_STKUFLOW ] += 1; #if 0 annoyingmsg("Restore: %d", size); #endif /* copy the frame onto the stack */ p = stktop; while (size) { *p++ = *hframe++; *p++ = *hframe++; size -= 8; } /* Follow continuation chain. */ globals[ G_CONT ] = *(stktop+STK_DYNLINK); header = *(stktop+HC_HEADER); retoffs = *(stktop+HC_RETOFFSET); proc = *(stktop+HC_PROC); /* convert the header back to a fixnum */ *(stktop+STK_CONTSIZE) = sizefield(header); /* convert the return address */ if (proc != 0) { codeptr = *(ptrof( proc )+PROC_CODEPTR); if (tagof( codeptr ) == BVEC_TAG) { codeaddr = (word)ptrof( codeptr ); *(stktop+STK_RETADDR) = (codeaddr+4)+retoffs; } else { *(stktop+STK_RETADDR) = retoffs; } } else { *(stktop+STK_RETADDR) = retoffs; } return 1; }
/* C_allocate: allocate heap memory */ void C_allocate( word request_words ) { supremely_annoyingmsg( "Allocation call-out from millicode." ); /* The assignment to G_RESULT violates the VM invariants because an untagged pointer to memory is being stored in a root. That's OK, because the millicode will fix the problem before anyone gets to see the pointer. */ in_noninterruptible_syscall = 1; globals[ G_RESULT ] = (word)alloc_from_heap( nativeint( request_words )*sizeof(word) ); in_noninterruptible_syscall = 0; }
void *must_realloc( void *ptr, unsigned bytes ) { void *p; again: p = realloc( ptr, bytes ); #if 0 supremely_annoyingmsg( "Re-allocating %u bytes", bytes); #endif if (p == 0) { memfail( MF_REALLOC, "Could not allocate RTS-internal data." ); goto again; } return p; }
word *los_allocate( los_t *los, int nbytes, int gen_no ) { word *w; int size; assert( 0 <= gen_no && gen_no < los->generations && nbytes > 0 ); size = roundup_page( nbytes + sizeof(word)*HEADER_WORDS ); w = gclib_alloc_heap( size, gen_no ); gclib_add_attribute( w, size, MB_LARGE_OBJECT ); w += HEADER_WORDS; set_size( w, size ); insert_at_end( w, los->object_lists[ gen_no ] ); supremely_annoyingmsg( "{LOS} Allocating large object size %d at 0x%p", size, w ); return w; }
void los_sweep( los_t *los, int gen_no ) { word *p, *n, *h; int nbytes; assert( 0 <= gen_no && gen_no < los->generations ); h = los->object_lists[gen_no]->header; p = next( h ); while ( p != h ) { n = next( p ); remove( p ); nbytes = size( p ); gclib_free( p - HEADER_WORDS, nbytes ); supremely_annoyingmsg( "{LOS} Freeing large object %d bytes at 0x%p", nbytes, (void*)p ); p = n; } clear_list( los->object_lists[ gen_no ] ); }
void *must_malloc( unsigned bytes ) { void *p; #ifdef __MWERKS__ /* Default CodeWarrior behavior is to return NULL if malloc is called with 0. (Not ANSI compliant; stupid; etc.) */ bytes = max( bytes, 1 ); #endif /* __MWERKS__ */ again: p = malloc( bytes ); bytes_allocated_by_malloc += bytes; #if 0 supremely_annoyingmsg( "Allocating %u bytes; total = %u bytes", bytes, bytes_allocated_by_malloc); #endif if (p == 0) { memfail( MF_MALLOC, "Could not allocate RTS-internal data." ); goto again; } return p; }