shithub: MicroHs

Download patch

ref: 638bdf75dc7aa79e1e97982afe43e8a5dab42a7b
parent: 8f1795d9bb6bd984b346f70d23ee408010f5dd1d
parent: 206c195ff111f01385283bdc82759aa78235451a
author: Lennart Augustsson <lennart@augustsson.net>
date: Sat Aug 31 10:25:07 EDT 2024

Merge branch 'master' into bytestring

--- a/src/runtime/eval.c
+++ b/src/runtime/eval.c
@@ -315,6 +315,8 @@
   struct final  *next;      /* the next finalizer */
   HsFunPtr       final;     /* function to call to release resource */
   void          *arg;       /* argument to final when called */
+  size_t         size;      /* size of memory, if known, otherwise NOSIZE */
+#define NOSIZE ~0           /* used as the size in payload for actual foreign pointers */
   struct forptr *back;      /* back pointer to the first forptr */
   int            marked;    /* mark bit for GC */
 };
@@ -326,8 +328,8 @@
  * The size field is non-zero only for bytestrings.
  */
 struct forptr {
-  struct forptr *next;      /* the next ForeignPtr that shares the same finilizer */
-  struct final  *finalizer; /* the finalizer for this ForeignPtr */
+  struct forptr *next;       /* the next ForeignPtr that shares the same finilizer */
+  struct final  *finalizer;  /* the finalizer for this ForeignPtr */
   struct bytestring payload; /* the actual pointer to allocated data, and maybe a size */
 };
 struct final *final_root = 0;   /* root of all allocated foreign pointers, linked by next */
@@ -374,6 +376,11 @@
 counter_t num_arr_free;
 counter_t num_fin_alloc;
 counter_t num_fin_free;
+counter_t num_bs_alloc;
+counter_t num_bs_free;
+counter_t num_bs_bytes;
+counter_t num_bs_inuse;
+counter_t num_bs_inuse_max;
 
 #define BITS_PER_WORD (sizeof(bits_t) * 8)
 bits_t *free_map;             /* 1 bit per node, 0=free, 1=used */
@@ -1100,6 +1107,12 @@
       finp = &fin->next;
     } else {
       /* Unused, run finalizer and free all associated memory */
+      if (fin->size == NOSIZE) {
+        num_fin_free++;
+      } else {
+        num_bs_free++;
+        num_bs_inuse -= fin->size;
+      }
       void (*f)(void *) = (void (*)(void *))fin->final;
       if (f) {
         //printf("finalizer fin=%p final=%p\n", fin, f);
@@ -1112,7 +1125,6 @@
         p = q;
       }
       *finp = fin->next;
-      num_fin_free++;
       //printf("free fin=%p\n", fin);
       FREE(fin);
     }
@@ -2263,12 +2275,21 @@
   struct forptr *fp = malloc(sizeof(struct forptr));
   if (!fin || !fp)
     memerr();
-  num_fin_alloc++;
+  if (bs.size == NOSIZE) {
+    num_fin_alloc++;
+  } else {
+    num_bs_alloc++;
+    num_bs_inuse += bs.size;
+    num_bs_bytes += bs.size;
+    if (num_bs_inuse > num_bs_inuse_max)
+      num_bs_inuse_max = num_bs_inuse;
+  }
   //printf("mkForPtr p=%p fin=%p fp=%p\n", p, fin, fp);
   fin->next = final_root;
   final_root = fin;
   fin->final = 0;
   fin->arg = bs.string;
+  fin->size = bs.size;
   fin->back = fp;
   fin->marked = 0;
   fp->next = 0;
@@ -2280,7 +2301,7 @@
 struct forptr*
 mkForPtrP(void *p)
 {
-  struct bytestring bs = { 0, p };
+  struct bytestring bs = { NOSIZE, p };
   return mkForPtr(bs);
 }
 
@@ -2293,7 +2314,8 @@
     memerr();
   fp->next = ofp;
   fin->back = fp;
-  fp->payload.size = ofp->payload.size - s;
+  if (fp->payload.size != NOSIZE)
+    fp->payload.size = ofp->payload.size - s;
   fp->payload.string = (uint8_t*)ofp->payload.string + s;
   fp->finalizer = fin;
   return fp;
@@ -3896,8 +3918,11 @@
     PRINT("%"PCOMMA"15"PRIcounter" reductions (%"PCOMMA".1f Mred/s)\n", num_reductions, num_reductions / ((double)run_time / 1000) / 1000000);
     PRINT("%"PCOMMA"15"PRIcounter" array alloc\n", num_arr_alloc);
     PRINT("%"PCOMMA"15"PRIcounter" array free\n", num_arr_free);
-    PRINT("%"PCOMMA"15"PRIcounter" foreign/bytestring alloc\n", num_fin_alloc);
-    PRINT("%"PCOMMA"15"PRIcounter" foreign/bytestring free\n", num_fin_free);
+    PRINT("%"PCOMMA"15"PRIcounter" foreign alloc\n", num_fin_alloc);
+    PRINT("%"PCOMMA"15"PRIcounter" foreign free\n", num_fin_free);
+    PRINT("%"PCOMMA"15"PRIcounter" bytestring alloc\n", num_bs_alloc);
+    PRINT("%"PCOMMA"15"PRIcounter" bytestring alloc'd bytes (max %"PCOMMA""PRIcounter")\n", num_bs_bytes, num_bs_inuse_max);
+    PRINT("%"PCOMMA"15"PRIcounter" bytestring free\n", num_bs_free);
 #if MAXSTACKDEPTH
     PRINT("%"PCOMMA"15d max stack depth\n", (int)max_stack_depth);
     PRINT("%"PCOMMA"15d max C stack depth\n", (int)max_c_stack);
--