Example #1
0
static void invert_pointer_at (word *p)
{
    word q = *p;
    Assert (Ecolor ((intnat) p) == 0);

    /* Use Ecolor (q) == 0 instead of Is_block (q) because q could be an
       inverted pointer for an infix header (with Ecolor == 2). */
    if (Ecolor (q) == 0 && (Classify_addr (q) & In_heap)) {
        switch (Ecolor (Hd_val (q))) {
        case 0:
        case 3: /* Pointer or header: insert in inverted list. */
            *p = Hd_val (q);
            Hd_val (q) = (header_t) p;
            break;
        case 1: /* Infix header: make inverted infix list. */
            /* Double inversion: the last of the inverted infix list points to
               the next infix header in this block.  The last of the last list
               contains the original block header. */
        {
            /* This block as a value. */
            value val = (value) q - Infix_offset_val (q);
            /* Get the block header. */
            word *hp = (word *) Hp_val (val);

            while (Ecolor (*hp) == 0) hp = (word *) *hp;
            Assert (Ecolor (*hp) == 3);
            if (Tag_ehd (*hp) == Closure_tag) {
                /* This is the first infix found in this block. */
                /* Save original header. */
                *p = *hp;
                /* Link inverted infix list. */
                Hd_val (q) = (header_t) ((word) p | 2);
                /* Change block header's tag to Infix_tag, and change its size
                   to point to the infix list. */
                *hp = Make_ehd (Wosize_bhsize (q - val), Infix_tag, 3);
            } else {
                Assert (Tag_ehd (*hp) == Infix_tag);
                /* Point the last of this infix list to the current first infix
                   list of the block. */
                *p = (word) &Field (val, Wosize_ehd (*hp)) | 1;
                /* Point the head of this infix list to the above. */
                Hd_val (q) = (header_t) ((word) p | 2);
                /* Change block header's size to point to this infix list. */
                *hp = Make_ehd (Wosize_bhsize (q - val), Infix_tag, 3);
            }
        }
        break;
        case 2: /* Inverted infix list: insert. */
            *p = Hd_val (q);
            Hd_val (q) = (header_t) ((word) p | 2);
            break;
        }
    }
}
Example #2
0
static void do_compaction_r (CAML_R)
{
  char *ch, *chend;
                                          Assert (caml_gc_phase == Phase_idle);
  caml_gc_message (0x10, "Compacting heap...\n", 0);

#ifdef DEBUG
  caml_heap_check_r (ctx);
#endif

  /* First pass: encode all noninfix headers. */
  {
    ch = caml_heap_start;
    while (ch != NULL){
      header_t *p = (header_t *) ch;

      chend = ch + Chunk_size (ch);
      while ((char *) p < chend){
        header_t hd = Hd_hp (p);
        mlsize_t sz = Wosize_hd (hd);

        if (Is_blue_hd (hd)){
          /* Free object.  Give it a string tag. */
          Hd_hp (p) = Make_ehd (sz, String_tag, 3);
        }else{                                      Assert (Is_white_hd (hd));
          /* Live object.  Keep its tag. */
          Hd_hp (p) = Make_ehd (sz, Tag_hd (hd), 3);
        }
        p += Whsize_wosize (sz);
      }
      ch = Chunk_next (ch);
    }
  }


  /* Second pass: invert pointers.
     Link infix headers in each block in an inverted list of inverted lists.
     Don't forget roots and weak pointers. */
  {
    /* Invert roots first because the threads library needs some heap
       data structures to find its roots.  Fortunately, it doesn't need
       the headers (see above). */
    caml_do_roots_r (ctx, invert_root_r);
    caml_final_do_weak_roots_r (ctx, invert_root_r);

    ch = caml_heap_start;
    while (ch != NULL){
      word *p = (word *) ch;
      chend = ch + Chunk_size (ch);

      while ((char *) p < chend){
        word q = *p;
        size_t sz, i;
        tag_t t;
        word *infixes;

        while (Ecolor (q) == 0) q = * (word *) q;
        sz = Whsize_ehd (q);
        t = Tag_ehd (q);

        if (t == Infix_tag){
          /* Get the original header of this block. */
          infixes = p + sz;
          q = *infixes;
          while (Ecolor (q) != 3) q = * (word *) (q & ~(uintnat)3);
          sz = Whsize_ehd (q);
          t = Tag_ehd (q);
        }

        if (t < No_scan_tag){
          for (i = 1; i < sz; i++) invert_pointer_at_r (ctx, &(p[i]));
        }
        p += sz;
      }
      ch = Chunk_next (ch);
    }
    /* Invert weak pointers. */
    {
      value *pp = &caml_weak_list_head;
      value p;
      word q;
      size_t sz, i;

      while (1){
        p = *pp;
        if (p == (value) NULL) break;
        q = Hd_val (p);
        while (Ecolor (q) == 0) q = * (word *) q;
        sz = Wosize_ehd (q);
        for (i = 1; i < sz; i++){
          if (Field (p,i) != caml_weak_none){
            invert_pointer_at_r (ctx, (word *) &(Field (p,i)));
          }
        }
        invert_pointer_at_r (ctx, (word *) pp);
        pp = &Field (p, 0);
      }
    }
  }


  /* Third pass: reallocate virtually; revert pointers; decode headers.
     Rebuild infix headers. */
  {
    init_compact_allocate_r (ctx);
    ch = caml_heap_start;
    while (ch != NULL){
      word *p = (word *) ch;

      chend = ch + Chunk_size (ch);
      while ((char *) p < chend){
        word q = *p;

        if (Ecolor (q) == 0 || Tag_ehd (q) == Infix_tag){
          /* There were (normal or infix) pointers to this block. */
          size_t sz;
          tag_t t;
          char *newadr;
          word *infixes = NULL;

          while (Ecolor (q) == 0) q = * (word *) q;
          sz = Whsize_ehd (q);
          t = Tag_ehd (q);

          if (t == Infix_tag){
            /* Get the original header of this block. */
            infixes = p + sz;
            q = *infixes;                             Assert (Ecolor (q) == 2);
            while (Ecolor (q) != 3) q = * (word *) (q & ~(uintnat)3);
            sz = Whsize_ehd (q);
            t = Tag_ehd (q);
          }

          newadr = compact_allocate_r (ctx, Bsize_wsize (sz));
          q = *p;
          while (Ecolor (q) == 0){
            word next = * (word *) q;
            * (word *) q = (word) Val_hp (newadr);
            q = next;
          }
          *p = Make_header (Wosize_whsize (sz), t, Caml_white);

          if (infixes != NULL){
            /* Rebuild the infix headers and revert the infix pointers. */
            while (Ecolor ((word) infixes) != 3){
              infixes = (word *) ((word) infixes & ~(uintnat) 3);
              q = *infixes;
              while (Ecolor (q) == 2){
                word next;
                q = (word) q & ~(uintnat) 3;
                next = * (word *) q;
                * (word *) q = (word) Val_hp ((word *) newadr + (infixes - p));
                q = next;
              }                    Assert (Ecolor (q) == 1 || Ecolor (q) == 3);
              *infixes = Make_header (infixes - p, Infix_tag, Caml_white);
              infixes = (word *) q;
            }
          }
          p += sz;
        }else{                                        Assert (Ecolor (q) == 3);
          /* This is guaranteed only if caml_compact_heap was called after a
             nonincremental major GC:       Assert (Tag_ehd (q) == String_tag);
          */
          /* No pointers to the header and no infix header:
             the object was free. */
          *p = Make_header (Wosize_ehd (q), Tag_ehd (q), Caml_blue);
          p += Whsize_ehd (q);
        }
      }
      ch = Chunk_next (ch);
    }
  }


  /* Fourth pass: reallocate and move objects.
     Use the exact same allocation algorithm as pass 3. */
  {
    init_compact_allocate_r (ctx);
    ch = caml_heap_start;
    while (ch != NULL){
      word *p = (word *) ch;

      chend = ch + Chunk_size (ch);
      while ((char *) p < chend){
        word q = *p;
        if (Color_hd (q) == Caml_white){
          size_t sz = Bhsize_hd (q);
          char *newadr = compact_allocate_r (ctx, sz);
          memmove (newadr, p, sz);
          p += Wsize_bsize (sz);
        }else{
          Assert (Color_hd (q) == Caml_blue);
          p += Whsize_hd (q);
        }
      }
      ch = Chunk_next (ch);
    }
  }

  /* Shrink the heap if needed. */
  {
    /* Find the amount of live data and the unshrinkable free space. */
    asize_t live = 0;
    asize_t free = 0;
    asize_t wanted;

    ch = caml_heap_start;
    while (ch != NULL){
      if (Chunk_alloc (ch) != 0){
        live += Wsize_bsize (Chunk_alloc (ch));
        free += Wsize_bsize (Chunk_size (ch) - Chunk_alloc (ch));
      }
      ch = Chunk_next (ch);
    }

    /* Add up the empty chunks until there are enough, then remove the
       other empty chunks. */
    wanted = caml_percent_free * (live / 100 + 1);
    ch = caml_heap_start;
    while (ch != NULL){
      char *next_chunk = Chunk_next (ch);  /* Chunk_next (ch) will be erased */

      if (Chunk_alloc (ch) == 0){
        if (free < wanted){
          free += Wsize_bsize (Chunk_size (ch));
        }else{
          caml_shrink_heap_r (ctx, ch);
        }
      }
      ch = next_chunk;
    }
  }

  /* Rebuild the free list. */
  {
    ch = caml_heap_start;
    caml_fl_reset_r (ctx);
    while (ch != NULL){
      if (Chunk_size (ch) > Chunk_alloc (ch)){
        caml_make_free_blocks_r (ctx, (value *) (ch + Chunk_alloc (ch)),
                                 Wsize_bsize (Chunk_size(ch)-Chunk_alloc(ch)), 1,
                                 Caml_white);
      }
      ch = Chunk_next (ch);
    }
  }
  ++ caml_stat_compactions;
  caml_gc_message (0x10, "done.\n", 0);
}
int
PLP_rangesweep()
{
char attr[NAMEMAXLEN], *line, *lineval;
int lvp, first;

int i, j, stat, npoints, result, xfield, lofield, hifield;
double start, stop, xstart, f; double x, lo, hi, lastx, lastlo, lasthi;
char *color, *legendlabel, *selectex;
char oldcolor[COLORLEN];

TDH_errprog( "pl proc rangesweep" );

/* initialize */
xfield = -1; lofield = -1; hifield = -1;
start = EDXlo; stop = EDXhi; xstart = EDXlo;

color = "gray(0.9)";
legendlabel = "";
selectex = "";

/* get attributes.. */
first = 1;
while( 1 ) {
	line = getnextattr( first, attr, &lvp );
	if( line == NULL ) break;
	first = 0;
	lineval = &line[lvp];

	if( strcmp( attr, "xfield" )==0 ) xfield = fref( lineval ) - 1;
	else if( strcmp( attr, "lofield" )==0 ) lofield = fref( lineval ) - 1;
	else if( strcmp( attr, "hifield" )==0 ) hifield = fref( lineval ) - 1;
	else if( strcmp( attr, "legendlabel" )==0 ) legendlabel = lineval;
	else if( strcmp( attr, "sweeprange" )==0 ) getrange( lineval, &start, &stop, 'x', EDXlo, EDXhi );
	else if( strcmp( attr, "xstart" )==0 ) { xstart = Econv( X, lineval ); if( Econv_error() ) xstart = EDXlo; }
	else if( strcmp( attr, "select" )==0 ) selectex = lineval;
	else if( strcmp( attr, "color" )==0 ) color = lineval;
	else Eerr( 1, "attribute not recognized", attr );
	}

/* -------------------------- */
/* overrides and degenerate cases */
/* -------------------------- */
if( Nrecords < 1 ) return( Eerr( 17, "No data has been read yet w/ proc getdata", "" ) );
if( !scalebeenset() ) 
         return( Eerr( 51, "No scaled plotting area has been defined yet w/ proc areadef", "" ) );


if( (lofield < 0 || lofield >= Nfields )) return( Eerr( 601, "lofield out of range", "" ) );
if( (hifield < 0 || hifield >= Nfields )) return( Eerr( 601, "hifield out of range", "" ) );
if( xfield >= Nfields ) return( Eerr( 601, "xfield out of range", "" ) );
 
/* -------------------------- */
/* now do the plotting work.. */
/* -------------------------- */

/* put all values into PLV array.. */
j = 0;
f = xstart;
for( i = 0; i < Nrecords; i++ ) {

	if( selectex[0] != '\0' ) { /* process against selection condition if any.. */
                stat = do_select( selectex, i, &result );
                if( stat != 0 ) { Eerr( stat, "Select error", selectex ); continue; }
                if( result == 0 ) continue;
                }


	/* X */
	if( xfield < 0 ) {
		PLV[j] = f;
		f += 1.0;
		}
	else 	{
		PLV[j] = fda( i, xfield, X );
		if( Econv_error() ) { 
			conv_msg( i, xfield, "xfield" ); 
			PLV[j] = NEGHUGE;
			}
		}

	j++; 

	/* LO */
	PLV[j] = fda( i, lofield, Y );
	if( Econv_error() ) { 
		conv_msg( i, lofield, "yfield" ); 
		PLV[j] = NEGHUGE;
		/* continue; */
		}
	j++;


	/* HI */
	PLV[j] = fda( i, hifield, Y );
	if( Econv_error() ) { 
		conv_msg( i, hifield, "hifield" ); 
		PLV[j] = NEGHUGE;
		/* continue; */
		}
	j++;



	if( j >= PLVsize-3 ) {
		Eerr( 3579, "Too many points, sweep truncated (raise using -maxvector)", "" );
		break;
		}
	}

npoints = j / 3;



/* draw the sweep.. */
/* ---------------- */

first = 1;
lastlo = 0.0;
lasthi = 0.0;
lastx = 0.0;

strcpy( oldcolor, Ecurcolor );
Ecolor( color );

for( i = 0; i < npoints; i++ ) {
	if( !first && (hi > (NEGHUGE+1) && lo > (NEGHUGE+1) && 
	       x > (NEGHUGE+1) && x < (PLHUGE-1) ) )  { 
		lastlo = lo; 
		lasthi = hi; 
		lastx = x;
		}
	x = dat3d(i,0);
	lo = dat3d(i,1);
	hi = dat3d(i,2);

	/* fprintf( stderr, "[last: x=%g lo=%g hi=%g   current: x=%g lo=%g hi=%g]", lastx, lastlo, lasthi, x, lo, hi ); */

	/* skip bad values and places */
	if( x < (NEGHUGE+1) || lo < (NEGHUGE+1) || hi < (NEGHUGE+1) ) { 
		/* fprintf( stderr, "[skip]\n" );  */
		continue; 
		}

	/* if lo > hi reset so a new sweep can be started later.. */
	if( lo > hi || x > (PLHUGE-1) ) { 
		first = 1;
		/* fprintf( stderr, "[reset]\n" ); */
		continue;
		}

	if( x < start ) {
		/* fprintf( stderr, "[too lo]\n" ); */
		continue; /* out of range - lo */
		}
	if( x > stop ) {     /* out of range - hi */ 
		/* fprintf( stderr, "[too hi]\n" ); */
		break;
		}


	if( first ) {
		/* fprintf( stderr, "[First]\n" ); */
		first = 0;
		continue;
		}

	if( !first ) {
		/* fprintf( stderr, "[Draw]\n" ); */
		Emovu( x, lo ); Epathu( lastx, lastlo ); 
		Epathu( lastx, lasthi ); 
		Epathu( x, hi );
		/* Ecolorfill( color ); */ /* using Efill  scg 6/18/04 */
		Efill();
		continue;
		}
	}

Ecolor( oldcolor );

 
if( legendlabel[0] != '\0' ) {
	PL_add_legent( LEGEND_COLOR, legendlabel, "", color, "", "" );
	}

return( 0 );
}