diff gc/new_hblk.c @ 51488:5de98dce4bd1

*** empty log message ***
author Dave Love <fx@gnu.org>
date Thu, 05 Jun 2003 17:49:22 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gc/new_hblk.c	Thu Jun 05 17:49:22 2003 +0000
@@ -0,0 +1,263 @@
+/*
+ * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
+ * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
+ * Copyright (c) 2000 by Hewlett-Packard Company.  All rights reserved.
+ *
+ * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
+ * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
+ *
+ * Permission is hereby granted to use or copy this program
+ * for any purpose,  provided the above notices are retained on all copies.
+ * Permission to modify the code and to distribute modified code is granted,
+ * provided the above notices are retained, and a notice that the code was
+ * modified is included with the above copyright notice.
+ *
+ * This file contains the functions:
+ *	ptr_t GC_build_flXXX(h, old_fl)
+ *	void GC_new_hblk(n)
+ */
+/* Boehm, May 19, 1994 2:09 pm PDT */
+
+
+# include <stdio.h>
+# include "private/gc_priv.h"
+
+#ifndef SMALL_CONFIG
+/*
+ * Build a free list for size 1 objects inside hblk h.  Set the last link to
+ * be ofl.  Return a pointer tpo the first free list entry.
+ */
+ptr_t GC_build_fl1(h, ofl)
+struct hblk *h;
+ptr_t ofl;
+{
+    register word * p = h -> hb_body;
+    register word * lim = (word *)(h + 1);
+    
+    p[0] = (word)ofl;
+    p[1] = (word)(p);
+    p[2] = (word)(p+1);
+    p[3] = (word)(p+2);
+    p += 4;
+    for (; p < lim; p += 4) {
+        p[0] = (word)(p-1);
+        p[1] = (word)(p);
+        p[2] = (word)(p+1);
+        p[3] = (word)(p+2);
+    };
+    return((ptr_t)(p-1));
+}
+
+/* The same for size 2 cleared objects */
+ptr_t GC_build_fl_clear2(h, ofl)
+struct hblk *h;
+ptr_t ofl;
+{
+    register word * p = h -> hb_body;
+    register word * lim = (word *)(h + 1);
+    
+    p[0] = (word)ofl;
+    p[1] = 0;
+    p[2] = (word)p;
+    p[3] = 0;
+    p += 4;
+    for (; p < lim; p += 4) {
+        p[0] = (word)(p-2);
+        p[1] = 0;
+        p[2] = (word)p;
+        p[3] = 0;
+    };
+    return((ptr_t)(p-2));
+}
+
+/* The same for size 3 cleared objects */
+ptr_t GC_build_fl_clear3(h, ofl)
+struct hblk *h;
+ptr_t ofl;
+{
+    register word * p = h -> hb_body;
+    register word * lim = (word *)(h + 1) - 2;
+    
+    p[0] = (word)ofl;
+    p[1] = 0;
+    p[2] = 0;
+    p += 3;
+    for (; p < lim; p += 3) {
+        p[0] = (word)(p-3);
+        p[1] = 0;
+        p[2] = 0;
+    };
+    return((ptr_t)(p-3));
+}
+
+/* The same for size 4 cleared objects */
+ptr_t GC_build_fl_clear4(h, ofl)
+struct hblk *h;
+ptr_t ofl;
+{
+    register word * p = h -> hb_body;
+    register word * lim = (word *)(h + 1);
+    
+    p[0] = (word)ofl;
+    p[1] = 0;
+    p[2] = 0;
+    p[3] = 0;
+    p += 4;
+    for (; p < lim; p += 4) {
+	PREFETCH_FOR_WRITE(p+64);
+        p[0] = (word)(p-4);
+        p[1] = 0;
+	CLEAR_DOUBLE(p+2);
+    };
+    return((ptr_t)(p-4));
+}
+
+/* The same for size 2 uncleared objects */
+ptr_t GC_build_fl2(h, ofl)
+struct hblk *h;
+ptr_t ofl;
+{
+    register word * p = h -> hb_body;
+    register word * lim = (word *)(h + 1);
+    
+    p[0] = (word)ofl;
+    p[2] = (word)p;
+    p += 4;
+    for (; p < lim; p += 4) {
+        p[0] = (word)(p-2);
+        p[2] = (word)p;
+    };
+    return((ptr_t)(p-2));
+}
+
+/* The same for size 4 uncleared objects */
+ptr_t GC_build_fl4(h, ofl)
+struct hblk *h;
+ptr_t ofl;
+{
+    register word * p = h -> hb_body;
+    register word * lim = (word *)(h + 1);
+    
+    p[0] = (word)ofl;
+    p[4] = (word)p;
+    p += 8;
+    for (; p < lim; p += 8) {
+	PREFETCH_FOR_WRITE(p+64);
+        p[0] = (word)(p-4);
+        p[4] = (word)p;
+    };
+    return((ptr_t)(p-4));
+}
+
+#endif /* !SMALL_CONFIG */
+
+
+/* Build a free list for objects of size sz inside heap block h.	*/
+/* Clear objects inside h if clear is set.  Add list to the end of	*/
+/* the free list we build.  Return the new free list.			*/
+/* This could be called without the main GC lock, if we ensure that	*/
+/* there is no concurrent collection which might reclaim objects that	*/
+/* we have not yet allocated.						*/
+ptr_t GC_build_fl(h, sz, clear, list)
+struct hblk *h;
+word sz;
+GC_bool clear;
+ptr_t list;
+{
+  word *p, *prev;
+  word *last_object;		/* points to last object in new hblk	*/
+
+  /* Do a few prefetches here, just because its cheap.  	*/
+  /* If we were more serious about it, these should go inside	*/
+  /* the loops.  But write prefetches usually don't seem to	*/
+  /* matter much.						*/
+    PREFETCH_FOR_WRITE((char *)h);
+    PREFETCH_FOR_WRITE((char *)h + 128);
+    PREFETCH_FOR_WRITE((char *)h + 256);
+    PREFETCH_FOR_WRITE((char *)h + 378);
+  /* Handle small objects sizes more efficiently.  For larger objects 	*/
+  /* the difference is less significant.				*/
+#  ifndef SMALL_CONFIG
+    switch (sz) {
+        case 1: return GC_build_fl1(h, list);
+        case 2: if (clear) {
+        	    return GC_build_fl_clear2(h, list);
+        	} else {
+        	    return GC_build_fl2(h, list);
+        	}
+        case 3: if (clear) {
+         	    return GC_build_fl_clear3(h, list);
+        	} else {
+        	    /* It's messy to do better than the default here. */
+        	    break;
+        	}
+        case 4: if (clear) {
+        	    return GC_build_fl_clear4(h, list);
+        	} else {
+        	    return GC_build_fl4(h, list);
+        	}
+        default:
+        	break;
+    }
+#  endif /* !SMALL_CONFIG */
+    
+  /* Clear the page if necessary. */
+    if (clear) BZERO(h, HBLKSIZE);
+    
+  /* Add objects to free list */
+    p = &(h -> hb_body[sz]);	/* second object in *h	*/
+    prev = &(h -> hb_body[0]);       	/* One object behind p	*/
+    last_object = (word *)((char *)h + HBLKSIZE);
+    last_object -= sz;
+			    /* Last place for last object to start */
+
+  /* make a list of all objects in *h with head as last object */
+    while (p <= last_object) {
+      /* current object's link points to last object */
+        obj_link(p) = (ptr_t)prev;
+	prev = p;
+	p += sz;
+    }
+    p -= sz;			/* p now points to last object */
+
+  /*
+   * put p (which is now head of list of objects in *h) as first
+   * pointer in the appropriate free list for this size.
+   */
+      obj_link(h -> hb_body) = list;
+      return ((ptr_t)p);
+}
+
+/*
+ * Allocate a new heapblock for small objects of size n.
+ * Add all of the heapblock's objects to the free list for objects
+ * of that size.
+ * Set all mark bits if objects are uncollectable.
+ * Will fail to do anything if we are out of memory.
+ */
+void GC_new_hblk(sz, kind)
+register word sz;
+int kind;
+{
+    register struct hblk *h;	/* the new heap block			*/
+    register GC_bool clear = GC_obj_kinds[kind].ok_init;
+
+#   ifdef PRINTSTATS
+	if ((sizeof (struct hblk)) > HBLKSIZE) {
+	    ABORT("HBLK SZ inconsistency");
+        }
+#   endif
+  if (GC_debugging_started) clear = TRUE;
+
+  /* Allocate a new heap block */
+    h = GC_allochblk(sz, kind, 0);
+    if (h == 0) return;
+
+  /* Mark all objects if appropriate. */
+      if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h));
+
+  /* Build the free list */
+      GC_obj_kinds[kind].ok_freelist[sz] =
+	GC_build_fl(h, sz, clear, GC_obj_kinds[kind].ok_freelist[sz]);
+}
+