On 05/11/2011 11:45 AM, Paolo Bonzini wrote:

Here is the patch, all the tests are green ;-)

Nice patch!

I have a few comments.

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

Spurious change.

@@ -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;

Can you try representing large objects with F_FIXED but not F_OLD? At
the same time, makeFixed would not cause objects to become old, which is
useful for objects passed to C.

Apparently, I even had some code to handle this in _gst_tenure_oop:

if (oop->flags & F_OLD)
return;

if (!(oop->flags & F_FIXED))
{
int size = SIZE_TO_BYTES (TO_INT(oop->object->objSize));
newObj = (gst_object) _gst_mem_alloc (_gst_mem.old, size);
if (!newObj)
abort ();

memcpy (newObj, oop->object, size);
_gst_mem.numOldOOPs++;

oop->object = newObj;
}

where the increment of numOldOOPs should be moved outside the if.

@@ -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);

Compacting is not going to be helpful, for fixed objects.

@@ -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--;

This makes stats wrong. With the idea above, the code would be like:

if ((oop->flags & F_LOADED) == 0)
{
if UNCOMMON (oop->flags & F_FIXED)
_gst_mem_free (_gst_mem.fixed, oop->object);
else if UNCOMMON (oop->flags & F_OLD)
_gst_mem_free (_gst_mem.old, oop->object);
}

if UNCOMMON (oop->flags & F_OLD)
{
_gst_mem.numOldOOPs--;
stats.reclaimedOldSpaceBytesSinceLastGlobalGC +=
SIZE_TO_BYTES (TO_INT (OOP_TO_OBJ (oop)->objSize));
}

It is a very good start though, thanks!

Paolo

Here is the new patch, I've removed like you've said the F_LARGE and make the F_FIXED working with both new and old generation the spurious change is removed ;-). I've included your idea just swap the two if because the memory can be freed before the size is accessed.

Gwen

diff --git a/libgst/gstpriv.h b/libgst/gstpriv.h
index 68c34b9..1ad17e7 100644
--- a/libgst/gstpriv.h
+++ b/libgst/gstpriv.h
@@ -336,7 +336,7 @@ enum {
   /* Set for objects that live in oldspace.  */
   F_OLD = 0x100U,
 
-  /* Set together with F_OLD for objects that live in fixedspace.  */
+  /* Set for objects that live in fixedspace.  */
   F_FIXED = 0x200U,
 
   /* Set for untrusted classes, instances of untrusted classes,
diff --git a/libgst/oop.c b/libgst/oop.c
index ad264d9..fe8b4d2 100644
--- a/libgst/oop.c
+++ b/libgst/oop.c
@@ -720,8 +720,7 @@ _gst_make_oop_fixed (OOP oop)
       oop->object = newObj;
     }
 
-  oop->flags &= ~(F_SPACES | F_POOLED);
-  oop->flags |= F_OLD | F_FIXED;
+  oop->flags |= F_FIXED;
 }
 
 void
@@ -763,7 +762,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 +779,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_FIXED);
+  p_instance->objSize = FROM_INT (BYTES_TO_SIZE (size));
+  return p_instance;
+}
+
+gst_object
 _gst_alloc_old_obj (size_t size,
 		    OOP *p_oop)
 {
@@ -1452,20 +1483,18 @@ _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_OLD)
     {
       _gst_mem.numOldOOPs--;
       stats.reclaimedOldSpaceBytesSinceLastGlobalGC +=
-	SIZE_TO_BYTES (TO_INT (OOP_TO_OBJ (oop)->objSize));
-      if ((oop->flags & F_LOADED) == 0)
-        _gst_mem_free (_gst_mem.fixed, oop->object);
+        SIZE_TO_BYTES (TO_INT (OOP_TO_OBJ (oop)->objSize));
     }
-  else if UNCOMMON (oop->flags & F_OLD)
+
+  if ((oop->flags & F_LOADED) == 0)
     {
-      _gst_mem.numOldOOPs--;
-      stats.reclaimedOldSpaceBytesSinceLastGlobalGC +=
-	SIZE_TO_BYTES (TO_INT (OOP_TO_OBJ (oop)->objSize));
-      if ((oop->flags & F_LOADED) == 0)
+      if UNCOMMON (oop->flags & F_FIXED)
+        _gst_mem_free (_gst_mem.fixed, oop->object);
+      else if UNCOMMON (oop->flags & F_OLD)
         _gst_mem_free (_gst_mem.old, oop->object);
     }
 
@@ -1617,7 +1646,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_FIXED))
+    queue_get (_gst_mem.active_half, TO_INT (oop->object->objSize));
 }
 
 void
@@ -2061,8 +2092,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_FIXED))
+        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/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