[Gc] Proposed solution (was: Determine the requested size of a memory block)

Christian Gudrian christian at gudrian.org
Mon Aug 16 06:58:30 PDT 2010


Hello!

I've implemented a new function called GC_ex_size which returns the 
requested size of a memory block.  A new field has been added to the 
struct hblkhdr which stores this information which otherwise would be lost.

A patch has been attached.

Christian
-------------- next part --------------
From: Christian Gudrian <christian at gudrian.org>
Date: Mon, 16 Aug 2010 15:40:23 +0200
Subject: [PATCH] New function: GC_ex_size()

GC_ex_size() returns the explicit size of a memory block (i.e. the size
that was originally requested by the program).  To accomplish that an
additional field (hb_ex_sz) has been added to the struct hblkhdr.
---
 src/bdwgc/gc/include/gc.h              |    7 +++++++
 src/bdwgc/gc/include/private/gc_priv.h |    1 +
 src/bdwgc/gc/malloc.c                  |   28 +++++++++++++++++++++++++---
 src/bdwgc/gc/misc.c                    |    7 +++++++
 4 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/src/bdwgc/gc/include/gc.h b/src/bdwgc/gc/include/gc.h
index 197b6b1..e1d04d7 100644
--- a/src/bdwgc/gc/include/gc.h
+++ b/src/bdwgc/gc/include/gc.h
@@ -407,6 +407,13 @@ GC_API void * GC_CALL GC_base(void * /* displaced_pointer */);
 /* requested.                                                           */
 GC_API size_t GC_CALL GC_size(const void * /* object_addr */);

+/* Given a pointer to the base of an object, return its explicit size   */
+/* in bytes (i.e. the size that has originally been requested by the    */
+/* program as opposed to the size that got eventuallyallocated.         */
+/* For implementation reasons this function returns 1 for uncollectable */
+/* blocks of size 0.                                                    */
+GC_API size_t GC_CALL GC_ex_size(const void * /* object_addr */);
+
 /* For compatibility with C library.  This is occasionally faster than  */
 /* a malloc followed by a bcopy.  But if you rely on that, either here  */
 /* or with the standard C library, your code is broken.  In my          */
diff --git a/src/bdwgc/gc/include/private/gc_priv.h b/src/bdwgc/gc/include/private/gc_priv.h
index c93aac9..89e2457 100644
--- a/src/bdwgc/gc/include/private/gc_priv.h
+++ b/src/bdwgc/gc/include/private/gc_priv.h
@@ -811,6 +811,7 @@ struct hblkhdr {
                    /* We assume that this is convertible to signed_word  */
                    /* without generating a negative result.  We avoid    */
                    /* generating free blocks larger than that.           */
+    size_t hb_ex_sz;            /* explicit size in bytes of the block  */
     word hb_descr;              /* object descriptor for marking.  See  */
                                 /* mark.h.                              */
 #   ifdef MARK_BIT_PER_OBJ
diff --git a/src/bdwgc/gc/malloc.c b/src/bdwgc/gc/malloc.c
index f6a3f3f..33ab0a0 100644
--- a/src/bdwgc/gc/malloc.c
+++ b/src/bdwgc/gc/malloc.c
@@ -154,6 +154,28 @@ GC_INNER void * GC_generic_malloc_inner_ignore_off_page(size_t lb, int k)
     return op;
 }

+/* Set the explicit size lb of the memory block pointed to by p.            */
+/* This size can later be retrieved by GC_ex_size().                        */
+GC_INNER void * GC_set_explicit_size(void * p, size_t lb)
+{
+    hdr * hhdr;
+
+    hhdr = HDR(p);
+    hhdr -> hb_ex_sz = lb;
+
+    /* When dealing with small uncollectable blocks, lb may actually be one */
+    /* byte less than the requested size (cf. GC_malloc_uncollectable()).   */
+    /* We try our best to account for that, however uncollectable blocks of */
+    /* size 0 will still get a size of 1.                                   */
+    if (IS_UNCOLLECTABLE(hhdr -> hb_obj_kind)
+            && !hhdr -> hb_large_block
+            && EXTRA_BYTES != 0) {
+        hhdr -> hb_ex_sz++;
+    }
+
+    return p;
+}
+
 GC_API void * GC_CALL GC_generic_malloc(size_t lb, int k)
 {
     void * result;
@@ -197,10 +219,10 @@ GC_API void * GC_CALL GC_generic_malloc(size_t lb, int k)
         }
     }
     if (0 == result) {
-        return((*GC_get_oom_fn())(lb));
-    } else {
-        return(result);
+        result = (*GC_get_oom_fn())(lb);
     }
+
+    return(GC_set_explicit_size(result, lb));
 }

 /* Allocate lb bytes of atomic (pointerfree) data */
diff --git a/src/bdwgc/gc/misc.c b/src/bdwgc/gc/misc.c
index f3efd3f..0f5dd63 100644
--- a/src/bdwgc/gc/misc.c
+++ b/src/bdwgc/gc/misc.c
@@ -386,6 +386,13 @@ GC_API size_t GC_CALL GC_size(const void * p)
     return hhdr -> hb_sz;
 }

+GC_API size_t GC_CALL GC_ex_size(const void * p)
+{
+    hdr * hhdr = HDR(p);
+
+    return hhdr -> hb_ex_sz;
+}
+
 GC_API size_t GC_CALL GC_get_heap_size(void)
 {
     size_t value;
--
1.7.1.msysgit.0.387.g185df



More information about the Gc mailing list