From 991e5aabd4e9a57713a9fb58fdef803c8ff7b587 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Tue, 28 Apr 1998 19:45:22 -0700
Subject: [PATCH] garbage collector now uses a queue instead of recursion

Rev: src/Makefile.in:1.85
Rev: src/gc.c:1.37
Rev: src/gc.h:1.18
Rev: src/queue.c:1.1
Rev: src/queue.h:1.1
Rev: src/svalue.c:1.31
---
 src/Makefile.in |  3 ++-
 src/gc.c        |  8 +++++++-
 src/gc.h        |  4 +++-
 src/queue.c     | 53 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/queue.h     | 20 +++++++++++++++++++
 src/svalue.c    | 31 +++++++++++++++++++++++------
 6 files changed, 110 insertions(+), 9 deletions(-)
 create mode 100644 src/queue.c
 create mode 100644 src/queue.h

diff --git a/src/Makefile.in b/src/Makefile.in
index b4af76d5ff..c1839d2067 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -1,5 +1,5 @@
 #
-# $Id: Makefile.in,v 1.84 1998/04/27 15:18:09 grubba Exp $
+# $Id: Makefile.in,v 1.85 1998/04/29 02:45:21 hubbe Exp $
 #
 
 # This line is needed on some machines.
@@ -121,6 +121,7 @@ OBJ= \
  stuff.o \
  threads.o \
  version.o \
+ queue.o \
  svalue.o @EXTRA_OBJS@
 
 #
diff --git a/src/gc.c b/src/gc.c
index c2fcd93845..056dbb1a49 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -25,7 +25,7 @@ struct callback *gc_evaluator_callback=0;
 #include "main.h"
 #include <math.h>
 
-RCSID("$Id: gc.c,v 1.36 1998/04/24 00:32:08 hubbe Exp $");
+RCSID("$Id: gc.c,v 1.37 1998/04/29 02:45:21 hubbe Exp $");
 
 /* Run garbage collect approximate every time we have
  * 20 percent of all arrays, objects and programs is
@@ -42,6 +42,7 @@ INT32 num_objects =0;
 INT32 num_allocs =0;
 INT32 alloc_threshold = MIN_ALLOC_THRESHOLD;
 static int in_gc = 0;
+struct queue gc_mark_queue;
 
 static double objects_alloced = 0.0;
 static double objects_freed = 0.0;
@@ -609,10 +610,15 @@ void do_gc(void)
 
   /* Next we mark anything with external references */
   gc_mark_all_arrays();
+  run_queue(&gc_mark_queue);
   gc_mark_all_multisets();
+  run_queue(&gc_mark_queue);
   gc_mark_all_mappings();
+  run_queue(&gc_mark_queue);
   gc_mark_all_programs();
+  run_queue(&gc_mark_queue);
   gc_mark_all_objects();
+  run_queue(&gc_mark_queue);
 
   if(d_flag)
     gc_mark_all_strings();
diff --git a/src/gc.h b/src/gc.h
index 4e72c2f0bf..4a0400fed1 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -1,12 +1,14 @@
 /*
- * $Id: gc.h,v 1.17 1998/04/06 04:25:27 hubbe Exp $
+ * $Id: gc.h,v 1.18 1998/04/29 02:45:22 hubbe Exp $
  */
 #ifndef GC_H
 #define GC_H
 
 #include "global.h"
 #include "callback.h"
+#include "queue.h"
 
+extern struct queue gc_mark_queue;
 extern INT32 num_objects;
 extern INT32 num_allocs;
 extern INT32 alloc_threshold;
diff --git a/src/queue.c b/src/queue.c
new file mode 100644
index 0000000000..f2dc7fca66
--- /dev/null
+++ b/src/queue.c
@@ -0,0 +1,53 @@
+#include "global.h"
+#include "pike_macros.h"
+#include "queue.h"
+
+struct queue_entry
+{
+  queue_call call;
+  void *data;
+};
+
+#define QUEUE_ENTRIES 8192
+
+struct queue_block
+{
+  struct queue_block *next;
+  int used;
+  struct queue_entry entries[QUEUE_ENTRIES];
+};
+
+void run_queue(struct queue *q)
+{
+  struct queue_block *b;
+  while((b=q->first))
+  {
+    int e;
+    for(e=0;e<b->used;e++)
+      b->entries[e].call(b->entries[e].data);
+
+    q->first=b->next;
+    free((char *)b);
+  }
+  q->last=0;
+}
+
+void enqueue(struct queue *q, queue_call call, void *data)
+{
+  struct queue_block *b=q->last;
+  if(!b || b->used >= QUEUE_ENTRIES)
+  {
+    b=ALLOC_STRUCT(queue_block);
+    b->used=0;
+    b->next=0;
+    if(q->first)
+      q->last->next=b;
+    else
+      q->first=b;
+    q->last=b;
+  }
+
+  b->entries[b->used].call=call;
+  b->entries[b->used].data=data;
+  b->used++;
+}
diff --git a/src/queue.h b/src/queue.h
new file mode 100644
index 0000000000..2dc43f261b
--- /dev/null
+++ b/src/queue.h
@@ -0,0 +1,20 @@
+#ifndef QUEUE_H
+#define QUEUE_H
+
+struct queue;
+typedef void (*queue_call)(void *data);
+
+/* Prototypes begin here */
+struct queue_entry;
+struct queue_block;
+void run_queue(struct queue *q);
+void enqueue(struct queue *q, queue_call call, void *data);
+/* Prototypes end here */
+
+struct queue
+{
+  struct queue_block *first, *last;
+};
+
+
+#endif /* QUEUE_H */
diff --git a/src/svalue.c b/src/svalue.c
index cd18e902dd..4fe027eb39 100644
--- a/src/svalue.c
+++ b/src/svalue.c
@@ -19,8 +19,9 @@
 #include "gc.h"
 #include "pike_macros.h"
 #include <ctype.h>
+#include "queue.h"
 
-RCSID("$Id: svalue.c,v 1.30 1998/04/28 22:34:18 hubbe Exp $");
+RCSID("$Id: svalue.c,v 1.31 1998/04/29 02:45:22 hubbe Exp $");
 
 struct svalue dest_ob_zero = { T_INT, 0 };
 
@@ -1066,10 +1067,26 @@ void gc_mark_svalues(struct svalue *s, int num)
   {
     switch(s->type)
     {
-    case T_ARRAY:   gc_mark_array_as_referenced(s->u.array);     break;
-    case T_MULTISET:    gc_mark_multiset_as_referenced(s->u.multiset);       break;
-    case T_MAPPING: gc_mark_mapping_as_referenced(s->u.mapping); break;
-    case T_PROGRAM: gc_mark_program_as_referenced(s->u.program); break;
+    case T_ARRAY: 
+      enqueue(&gc_mark_queue,
+	      (queue_call)gc_mark_array_as_referenced,
+	      s->u.array);
+      break;
+    case T_MULTISET:
+      enqueue(&gc_mark_queue,
+	      (queue_call)gc_mark_multiset_as_referenced,
+	      s->u.multiset);
+      break;
+    case T_MAPPING:
+      enqueue(&gc_mark_queue,
+	      (queue_call)gc_mark_mapping_as_referenced,
+	      s->u.mapping);
+      break;
+    case T_PROGRAM:
+      enqueue(&gc_mark_queue,
+	      (queue_call)gc_mark_program_as_referenced,
+	      s->u.program);
+      break;
 
     case T_FUNCTION:
       if(s->subtype == FUNCTION_BUILTIN) break;
@@ -1077,7 +1094,9 @@ void gc_mark_svalues(struct svalue *s, int num)
     case T_OBJECT:
       if(s->u.object->prog)
       {
-	gc_mark_object_as_referenced(s->u.object);
+	enqueue(&gc_mark_queue,
+		(queue_call)gc_mark_object_as_referenced,
+		s->u.object);
       }else{
 	free_svalue(s);
 	s->type=T_INT;
-- 
GitLab