On 05/10/2011 11:59 AM, Gwenael Casaccio wrote:
Hi,

Currently in GST big objects are allocated in the old space
and won't move during the GC. The non-moving property is nice
but putting big objects in the old space is not good since we
need to do a full GC to free them.

I've made a small patch not yet finished (there is one last bug when
I do a make check) which creates a new kind of object:

F_LARGE that can be in young space and after tenured to the old space.
The difference is that the object won't move during the copy gc and the
tenure step.

git://github.com/MrGwen/GNU-Smalltalk.git in the branch LargeOOP.

Cheers,
Gwen

Hi,

Here is the patch, all the tests are green ;-)
Basically I've added a new flag F_LARGE, and a new method for allocating
large object: gst_alloc_large_obj. The object is fixed and won't move during the GC, so that implies that when tenuring an object I check if the object is F_LARGE. Also a special care is taken when the object is sweep, I use the correct heap. The image loading is updated to take care
of the F_LARGE field.

Cheers,
Gwen
diff --git a/libgst/gstpriv.h b/libgst/gstpriv.h
index 68c34b9..277cb06 100644
--- a/libgst/gstpriv.h
+++ b/libgst/gstpriv.h
@@ -347,6 +347,9 @@ enum {
      garbage collect their contents, only the OOPs.  */
   F_LOADED = 0x800U,
 
+  /* Set for large OOP */
+  F_LARGE = 0x1000U,
+
   /* Set to the number of bytes unused in an object with byte-sized
      instance variables.  Note that this field and the following one
      should be initialized only by INIT_UNALIGNED_OBJECT (not really 
diff --git a/libgst/oop.c b/libgst/oop.c
index ad264d9..018ec95 100644
--- a/libgst/oop.c
+++ b/libgst/oop.c
@@ -66,6 +66,7 @@
 
 /* Define this flag to turn on debugging code for OOP table management */
 /* #define GC_DEBUGGING */
+#define GC_DEBUGGING
 
 /* Define this flag to disable incremental garbage collection */
 /* #define NO_INCREMENTAL_GC */
@@ -701,7 +702,7 @@ _gst_make_oop_fixed (OOP oop)
 {
   gst_object newObj;
   int size;
-  if (oop->flags & F_FIXED)
+  if ((oop->flags & F_FIXED) || (oop->flags & F_LARGE))
     return;
 
   if ((oop->flags & F_LOADED) == 0)
@@ -731,7 +732,7 @@ _gst_tenure_oop (OOP oop)
   if (oop->flags & F_OLD)
     return;
 
-  if (!(oop->flags & F_FIXED))
+  if (!(oop->flags & F_FIXED) && !(oop->flags & F_LARGE))
     {
       int size = SIZE_TO_BYTES (TO_INT(oop->object->objSize));
       newObj = (gst_object) _gst_mem_alloc (_gst_mem.old, size);
@@ -763,7 +764,7 @@ _gst_alloc_obj (size_t size,
   newAllocPtr = _gst_mem.eden.allocPtr + BYTES_TO_SIZE (size);
 
   if UNCOMMON (size >= _gst_mem.big_object_threshold)
-    return _gst_alloc_old_obj (size, p_oop);
+    return _gst_alloc_large_obj (size, p_oop);
 
   if UNCOMMON (newAllocPtr >= _gst_mem.eden.maxPtr)
     {
@@ -780,6 +781,38 @@ _gst_alloc_obj (size_t size,
 }
 
 gst_object
+_gst_alloc_large_obj (size_t size,
+                      OOP *p_oop)
+{
+  gst_object p_instance;
+
+  size = ROUNDED_BYTES (size);
+
+  /* If the object is big enough, we put it directly in fixedspace.  */
+  p_instance = (gst_object) _gst_mem_alloc (_gst_mem.fixed, size);
+  if COMMON (p_instance)
+    goto ok;
+
+  _gst_global_gc (size);
+  p_instance = (gst_object) _gst_mem_alloc (_gst_mem.fixed, size);
+  if COMMON (p_instance)
+    goto ok;
+
+  _gst_compact (0);
+  p_instance = (gst_object) _gst_mem_alloc (_gst_mem.fixed, size);
+  if UNCOMMON (!p_instance)
+    {
+      _gst_errorf ("Cannot recover, exiting...");
+      exit (1);
+    }
+
+ok:
+  *p_oop = alloc_oop (p_instance, _gst_mem.active_flag | F_LARGE);
+  p_instance->objSize = FROM_INT (BYTES_TO_SIZE (size));
+  return p_instance;
+}
+
+gst_object
 _gst_alloc_old_obj (size_t size,
 		    OOP *p_oop)
 {
@@ -1037,7 +1070,7 @@ _gst_compact (size_t new_heap_limit)
        oop < &_gst_mem.ot[_gst_mem.ot_size]; oop++)
     {
       PREFETCH_LOOP (oop, PREF_READ | PREF_NTA);
-      if ((oop->flags & (F_OLD | F_FIXED | F_LOADED)) == F_OLD)
+      if ((oop->flags & (F_OLD | F_FIXED | F_LOADED | F_LARGE)) == F_OLD)
         {
           gst_object new;
           size_t size = SIZE_TO_BYTES (TO_INT (oop->object->objSize));
@@ -1452,7 +1485,7 @@ _gst_sweep_oop (OOP oop)
     _gst_make_oop_non_weak (oop);
 
   /* Free unreachable oldspace objects.  */
-  if UNCOMMON (oop->flags & F_FIXED)
+  if UNCOMMON ((oop->flags & F_FIXED) || (oop->flags & F_LARGE))
     {
       _gst_mem.numOldOOPs--;
       stats.reclaimedOldSpaceBytesSinceLastGlobalGC +=
@@ -1617,7 +1650,9 @@ tenure_one_object ()
     _gst_tenure_oop (oop);
 
   queue_get (&_gst_mem.tenuring_queue, 1);
-  queue_get (_gst_mem.active_half, TO_INT (oop->object->objSize));
+
+  if (!(oop->flags & F_LARGE))
+    queue_get (_gst_mem.active_half, TO_INT (oop->object->objSize));
 }
 
 void
@@ -2061,8 +2096,10 @@ _gst_copy_an_oop (OOP oop)
 #endif
 
       queue_put (&_gst_mem.tenuring_queue, &oop, 1);
-      obj = oop->object = (gst_object)
-	queue_put (_gst_mem.active_half, pData, TO_INT (obj->objSize));
+
+      if (!(oop->flags & F_LARGE))
+        obj = oop->object = (gst_object)
+	  queue_put (_gst_mem.active_half, pData, TO_INT (obj->objSize));
 
       oop->flags &= ~(F_SPACES | F_POOLED);
       oop->flags |= _gst_mem.active_flag;
diff --git a/libgst/oop.h b/libgst/oop.h
index 6816b3f..4e99e76 100644
--- a/libgst/oop.h
+++ b/libgst/oop.h
@@ -409,6 +409,11 @@ extern gst_object _gst_alloc_obj (size_t size,
 				  OOP *p_oop) 
   ATTRIBUTE_HIDDEN;
 
+/* The same, but for a large object */
+extern gst_object _gst_alloc_large_obj (size_t size,
+                                        OOP *p_oop)
+  ATTRIBUTE_HIDDEN;
+
 /* The same, but for an oldspace object */
 extern gst_object _gst_alloc_old_obj (size_t size,
 				      OOP *p_oop) 
diff --git a/libgst/print.c b/libgst/print.c
index 6ac7358..5ae9dbb 100644
--- a/libgst/print.c
+++ b/libgst/print.c
@@ -324,7 +324,7 @@ _gst_display_oop_short (OOP oop)
     printf ("%-10p   Free\n", oop);
   else
     {
-      printf ("%-10p   %-10p  %-10s %-10s %-10s\n", oop, oop->object,
+      printf ("%-10p   %-10p  %-10s %-10s %-10s %-10s\n", oop, oop->object,
             oop->flags & F_CONTEXT ? "Context" :
             oop->flags & F_WEAK ? "Weak" :
             oop->flags & F_EPHEMERON ? "Ephemeron" : "",
@@ -338,7 +338,9 @@ _gst_display_oop_short (OOP oop)
 	    IS_SURVIVOR_ADDR (oop->object, 0) ? "Surv (Even)" :
 	    IS_SURVIVOR_ADDR (oop->object, 1) ? "Surv (Odd)" :
             oop->flags & F_POOLED ? "Pooled" :
-	    oop->flags & F_REACHABLE ? "Old/marked" : "Old");
+	    oop->flags & F_REACHABLE ? "Old/marked" : "Old",
+
+            oop->flags & F_LARGE ? "Large" : "");
     }
 }
 
@@ -355,7 +357,7 @@ _gst_display_oop (OOP oop)
     printf ("%-10p   Free\n", oop);
   else
     {
-      printf ("%-10p   %-10p  %-10s %-10s %-10s", oop, oop->object,
+      printf ("%-10p   %-10p  %-10s %-10s %-10s %-10s", oop, oop->object,
             oop->flags & F_CONTEXT ? "Context" :
             oop->flags & F_WEAK ? "Weak" :
             oop->flags & F_EPHEMERON ? "Ephemeron" : "",
@@ -369,7 +371,9 @@ _gst_display_oop (OOP oop)
 	    IS_SURVIVOR_ADDR (oop->object, 0) ? "Surv (Even)" :
 	    IS_SURVIVOR_ADDR (oop->object, 1) ? "Surv (Odd)" :
             oop->flags & F_POOLED ? "Pooled" :
-	    oop->flags & F_REACHABLE ? "Old/marked" : "Old");
+	    oop->flags & F_REACHABLE ? "Old/marked" : "Old",
+
+            oop->flags & F_LARGE ? "Large" : "");
 
       if (IS_OOP_ADDR (oop->object->objClass))
         printf ("   %O (%O)\n", oop->object->objClass, oop->object->objSize);
diff --git a/libgst/save.c b/libgst/save.c
index 77cc8b9..a45cc8a 100644
--- a/libgst/save.c
+++ b/libgst/save.c
@@ -646,7 +646,7 @@ load_normal_oops (int imageFd)
 
       else
 	{
-	  if (flags & F_FIXED)
+	  if ((flags & F_FIXED) || (flags & F_LARGE))
 	    {
 	      _gst_mem.numFixedOOPs++;
               object = (gst_object) _gst_mem_alloc (_gst_mem.fixed, size);
diff --git a/snprintfv/snprintfv/filament.h b/snprintfv/snprintfv/filament.h
index 4a91eb6..8a7ce6c 100644
--- a/snprintfv/snprintfv/filament.h
+++ b/snprintfv/snprintfv/filament.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/filament.in"
+#line 1 "./filament.in"
 /*  -*- Mode: C -*-  */
 
 /* filament.h --- a bit like a string but different =)O|
@@ -118,7 +118,7 @@ extern char * fildelete (Filament *fil);
 extern void _fil_extend (Filament *fil, size_t len, boolean copy);
 
 
-#line 61 "../../../snprintfv/snprintfv/filament.in"
+#line 61 "./filament.in"
 
 /* Save the overhead of a function call in the great majority of cases. */
 #define fil_maybe_extend(fil, len, copy)  \
diff --git a/snprintfv/snprintfv/printf.h b/snprintfv/snprintfv/printf.h
index 49a2e9f..1437dd5 100644
--- a/snprintfv/snprintfv/printf.h
+++ b/snprintfv/snprintfv/printf.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/printf.in"
+#line 1 "./printf.in"
 /*  -*- Mode: C -*-  */
 
 /* printf.in --- printf clone for argv arrays
@@ -266,7 +266,7 @@ enum
       } \
   } SNV_STMT_END
 
-#line 269 "../../../snprintfv/snprintfv/printf.in"
+#line 269 "./printf.in"
 /**
  * printf_generic_info:   
  * @pinfo: the current state information for the format
@@ -302,7 +302,7 @@ extern int printf_generic_info (struct printf_info *const pinfo, size_t n, int *
 extern int printf_generic (STREAM *stream, struct printf_info *const pinfo, union printf_arg const *args);
 
 
-#line 270 "../../../snprintfv/snprintfv/printf.in"
+#line 270 "./printf.in"
 /**
  * register_printf_function:  
  * @spec: the character which will trigger @func, cast to an unsigned int.
@@ -789,7 +789,7 @@ extern int snv_vasprintf (char **result, const char *format, va_list ap);
 extern int snv_asprintfv (char **result, const char *format, snv_constpointer const args[]);
 
 
-#line 271 "../../../snprintfv/snprintfv/printf.in"
+#line 271 "./printf.in"
 
 /* If you don't want to use snprintfv functions for *all* of your string
    formatting API, then define COMPILING_SNPRINTFV_C and use the snv_
diff --git a/snprintfv/snprintfv/stream.h b/snprintfv/snprintfv/stream.h
index 496bd33..0bebce1 100644
--- a/snprintfv/snprintfv/stream.h
+++ b/snprintfv/snprintfv/stream.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/stream.in"
+#line 1 "./stream.in"
 /*  -*- Mode: C -*-  */
 
 /* stream.h --- customizable stream routines
@@ -180,7 +180,7 @@ extern int stream_puts (char *s, STREAM *stream);
 extern int stream_get (STREAM *stream);
 
 
-#line 88 "../../../snprintfv/snprintfv/stream.in"
+#line 88 "./stream.in"
 #ifdef __cplusplus
 #if 0
 /* This brace is so that emacs can still indent properly: */
_______________________________________________
help-smalltalk mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/help-smalltalk

Reply via email to