From fca6f1720d44e5973e101d132bc4fcebd128320a Mon Sep 17 00:00:00 2001
From: "Tobias S. Josefowitz" <tobij@tobij.de>
Date: Sat, 22 Jun 2019 23:42:10 +0200
Subject: [PATCH] ADT.List: Do not put struct pike_list_structs into the GC

Backport from Pike master.

Fixes Pike.count_memory() getting stuck in a loop on ADT.List.

NB: The comments about inline markers below are not relevant
    to Pike 8.0.

Original commit message from Pike master follows:

Since the GC was changed to use inline markers, all items fed into the
GC must comply with a certain memory layout - containing
GC_MARKER_MEMBERS at the beginning of their region.

struct pike_list_struct does not, and cannot easily be made to because
struct List_struct (storage of ADT.List) and struct pike_list_struct
need to stay compatible because the former is used to store sentinels
being used as the latter type.

While we lose reporting from the GC about issues in ADT.List's inner
structure, GC checking of struct pike_list_structs seems to not be
functionally required. On the upside, the GC no longer writes beyond
or into struct pike_list_structs which did not reserve the memory areas
for use by the GC.
---
 src/builtin.cmod | 42 +++++++-----------------------------------
 1 file changed, 7 insertions(+), 35 deletions(-)

diff --git a/src/builtin.cmod b/src/builtin.cmod
index 3033f1ac49..73b6b130cc 100644
--- a/src/builtin.cmod
+++ b/src/builtin.cmod
@@ -5233,38 +5233,16 @@ PIKECLASS List
     }
   }
 
-  /* These two functions perform the same thing,
-   * but are optimized to minimize recursion.
-   */
-  static void gc_check_list_node_backward(struct pike_list_node *node,
-					  const char *msg);
-  static void gc_check_list_node_forward(struct pike_list_node *node,
-					 const char *msg)
-  {
-    while (node && !debug_gc_check(&node->refs, msg)) {
-      if (node->next)
-	debug_gc_check_svalues(&node->val, 1,  " as a list node value");
-      gc_check_list_node_backward(node->prev, msg);
-      node = node->next;
-    }
-  }
-
-  static void gc_check_list_node_backward(struct pike_list_node *node,
-					  const char *msg)
-  {
-    while (node && !debug_gc_check(&node->refs, msg)) {
-      if (node->prev)
-	debug_gc_check_svalues(&node->val, 1, " as a list node value");
-      gc_check_list_node_forward(node->next, msg);
-      node = node->prev;
-    }
-  }
-
   /* Called at gc_check time. */
   GC_CHECK
   {
-    gc_check_list_node_backward(HEAD_SENTINEL(THIS), " as a list node");
-    gc_check_list_node_forward(TAIL_SENTINEL(THIS), " as a list node");
+    struct pike_list_node *node = THIS->head;
+    struct pike_list_node *next;
+
+    while ((next = node->next)) {
+      debug_gc_check_svalues(&node->val, 1, "as a list node value");
+      node = next;
+    }
   }
 
   /* Called at gc_mark time */
@@ -5613,12 +5591,6 @@ PIKECLASS List
       }
     }
 
-    /* Called at gc_check time. */
-    GC_CHECK
-    {
-      gc_check_list_node_forward(THIS->cur, " held by an iterator");
-    }  
-
     /* These two functions perform the same thing,
      * but are optimized to minimize recursion.
      */
-- 
GitLab