Пример #1
0
/* 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 );
}
Пример #2
0
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;
}
Пример #3
0
/* 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;
}
Пример #4
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;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
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++;
}
Пример #8
0
/* 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() */
}
Пример #9
0
/* 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;
}
Пример #10
0
/* 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;
}
Пример #11
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;
}
Пример #12
0
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;
}
Пример #13
0
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 ] );
}
Пример #14
0
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;
}