diff --git a/src/array.c b/src/array.c
index cdcf6481e340f1f8492b78b1ad923ff5cdeb9c37..88bf09f4b28c9b358918ba0e894c6f3cd269c387 100644
--- a/src/array.c
+++ b/src/array.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: array.c,v 1.153 2004/03/09 15:48:51 nilsson Exp $
+|| $Id: array.c,v 1.154 2004/03/15 22:23:14 mast Exp $
 */
 
 #include "global.h"
@@ -26,13 +26,13 @@
 #include "cyclic.h"
 #include "multiset.h"
 
-RCSID("$Id: array.c,v 1.153 2004/03/09 15:48:51 nilsson Exp $");
+RCSID("$Id: array.c,v 1.154 2004/03/15 22:23:14 mast Exp $");
 
 PMOD_EXPORT struct array empty_array=
 {
   PIKE_CONSTANT_MEMOBJ_INIT(1), /* Never free */
   &weak_empty_array,     /* Next */
-  &weak_shrink_empty_array, /* previous (circular) */
+  0,			 /* previous */
   0,                     /* Size = 0 */
   0,                     /* malloced Size = 0 */
   0,                     /* no types */
@@ -54,14 +54,15 @@ PMOD_EXPORT struct array weak_empty_array=
 PMOD_EXPORT struct array weak_shrink_empty_array=
 {
   PIKE_CONSTANT_MEMOBJ_INIT(1),
-  &empty_array, &weak_empty_array, 0, 0, 0, ARRAY_WEAK_FLAG|ARRAY_WEAK_SHRINK,
+  0, &weak_empty_array, 0, 0, 0, ARRAY_WEAK_FLAG|ARRAY_WEAK_SHRINK,
   weak_shrink_empty_array.real_item,
 #ifdef HAVE_UNION_INIT
   {{0, 0, {0}}}, /* Only to avoid warnings. */
 #endif
 };
 
-struct array *gc_internal_array = &empty_array;
+struct array *first_array = &empty_array;
+struct array *gc_internal_array = 0;
 static struct array *gc_mark_array_pos = 0;
 
 #ifdef TRACE_UNFINISHED_TYPE_FIELDS
@@ -108,7 +109,7 @@ PMOD_EXPORT struct array *low_allocate_array(ptrdiff_t size, ptrdiff_t extra_spa
   v->item=v->real_item;
   v->size = DO_NOT_WARN((INT32)size);
   INIT_PIKE_MEMOBJ(v);
-  LINK_ARRAY(v);
+  DOUBLELINK (first_array, v);
 
   for(e=0;e<v->size;e++)
   {
@@ -125,7 +126,7 @@ PMOD_EXPORT struct array *low_allocate_array(ptrdiff_t size, ptrdiff_t extra_spa
  */
 static void array_free_no_free(struct array *v)
 {
-  UNLINK_ARRAY(v);
+  DOUBLEUNLINK (first_array, v);
 
   free((char *)v);
 
@@ -2216,8 +2217,17 @@ PMOD_EXPORT void check_array(struct array *a)
 {
   INT32 e;
 
-  if(a->next->prev != a)
-    Pike_fatal("Array check: a->next->prev != a\n");
+  if(a->next && a->next->prev != a)
+    Pike_fatal("array->next->prev != array.\n");
+
+  if(a->prev)
+  {
+    if(a->prev->next != a)
+      Pike_fatal("array->prev->next != array.\n");
+  }else{
+    if(first_array != a)
+      Pike_fatal("array->prev == 0 but first_array != array.\n");
+  }
 
   if(a->size > a->malloced_size)
     Pike_fatal("Array is larger than malloced block!\n");
@@ -2252,16 +2262,8 @@ PMOD_EXPORT void check_array(struct array *a)
 void check_all_arrays(void)
 {
   struct array *a;
-
-  a=&empty_array;
-  do
-  {
+  for (a = first_array; a; a = a->next)
     check_array(a);
-
-    a=a->next;
-    if(!a)
-      Pike_fatal("Null pointer in array list.\n");
-  } while (a != & empty_array);
 }
 #endif /* PIKE_DEBUG */
 
@@ -2285,18 +2287,13 @@ void gc_mark_array_as_referenced(struct array *a)
 {
   if(gc_mark(a))
     GC_ENTER (a, T_ARRAY) {
-#ifdef PIKE_DEBUG
-      if (a == &empty_array || a == &weak_empty_array || a == &weak_shrink_empty_array)
-	Pike_fatal("Trying to gc mark some *_empty_array.\n");
-#endif
-
       if (a == gc_mark_array_pos)
 	gc_mark_array_pos = a->next;
       if (a == gc_internal_array)
 	gc_internal_array = a->next;
       else {
-	UNLINK_ARRAY(a);
-	LINK_ARRAY(a);		/* Linked in first. */
+	DOUBLEUNLINK (first_array, a);
+	DOUBLELINK (first_array, a); /* Linked in first. */
       }
 
       if (a->type_field & BIT_COMPLEX)
@@ -2383,43 +2380,35 @@ void real_gc_cycle_check_array(struct array *a, int weak)
 unsigned gc_touch_all_arrays(void)
 {
   unsigned n = 0;
-  struct array *a = &empty_array;
-  do {
+  struct array *a;
+  if (!first_array || first_array->prev)
+    Pike_fatal ("error in array link list.\n");
+  for (a = first_array; a; a = a->next) {
     debug_gc_touch(a);
     n++;
-    if (!a->next || a->next->prev != a)
+    if (a->next && a->next->prev != a)
       Pike_fatal("Error in array link list.\n");
-    a=a->next;
-  } while (a != &empty_array);
+  }
   return n;
 }
 
 void gc_check_all_arrays(void)
 {
   struct array *a;
-  a=&empty_array;
-  do
-  {
+  for (a = first_array; a; a = a->next) {
 #ifdef PIKE_DEBUG
     if(d_flag > 1)  array_check_type_field(a);
 #endif
     gc_check_array(a);
-    a=a->next;
-  } while (a != & empty_array);
+  }
 }
 
 
 void gc_mark_all_arrays(void)
 {
   gc_mark_array_pos = gc_internal_array;
-  gc_mark(&empty_array);
-  gc_mark(&weak_empty_array);
-  gc_mark(&weak_shrink_empty_array);
-  while (gc_mark_array_pos != &empty_array) {
+  while (gc_mark_array_pos) {
     struct array *a = gc_mark_array_pos;
-#ifdef PIKE_DEBUG
-    if (!a) Pike_fatal("Null pointer in array list.\n");
-#endif
     gc_mark_array_pos = a->next;
     if(gc_is_referenced(a))
       gc_mark_array_as_referenced(a);
@@ -2429,7 +2418,7 @@ void gc_mark_all_arrays(void)
 void gc_cycle_check_all_arrays(void)
 {
   struct array *a;
-  for (a = gc_internal_array; a != &empty_array; a = a->next) {
+  for (a = gc_internal_array; a; a = a->next) {
     real_gc_cycle_check_array(a, 0);
     gc_cycle_run_queue();
   }
@@ -2437,7 +2426,7 @@ void gc_cycle_check_all_arrays(void)
 
 void gc_zap_ext_weak_refs_in_arrays(void)
 {
-  gc_mark_array_pos = empty_array.next;
+  gc_mark_array_pos = first_array;
   while (gc_mark_array_pos != gc_internal_array && gc_ext_weak_refs) {
     struct array *a = gc_mark_array_pos;
     gc_mark_array_pos = a->next;
@@ -2451,7 +2440,7 @@ size_t gc_free_all_unreferenced_arrays(void)
   struct array *a,*next;
   size_t unreferenced = 0;
 
-  for (a = gc_internal_array; a != &weak_empty_array; a = next)
+  for (a = gc_internal_array; a; a = next)
   {
 #ifdef PIKE_DEBUG
     if (!a)
@@ -2518,7 +2507,7 @@ void count_memory_in_arrays(INT32 *num_, INT32 *size_)
 {
   INT32 num=0, size=0;
   struct array *m;
-  for(m=empty_array.next;m!=&weak_empty_array;m=m->next)
+  for(m=first_array;m;m=m->next)
   {
     num++;
     size+=sizeof(struct array)+
diff --git a/src/array.h b/src/array.h
index 51e059e2ce1fbcaab6376ffc3451db8483cda76f..84d6fe8c5ddd76e129cce1b4528b8b27e12167ec 100644
--- a/src/array.h
+++ b/src/array.h
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: array.h,v 1.54 2004/03/09 15:49:04 nilsson Exp $
+|| $Id: array.h,v 1.55 2004/03/15 22:23:14 mast Exp $
 */
 
 #ifndef ARRAY_H
@@ -39,6 +39,7 @@ struct array
 #define ARRAY_WEAK_SHRINK 8
 
 PMOD_EXPORT extern struct array empty_array, weak_empty_array, weak_shrink_empty_array;
+extern struct array *first_array;
 extern struct array *gc_internal_array;
 
 #if defined(DEBUG_MALLOC) && defined(PIKE_DEBUG)
@@ -47,19 +48,6 @@ extern struct array *gc_internal_array;
 #define ITEM(X) ((X)->item)
 #endif
 
-#define LINK_ARRAY(a) do {						\
-  (a)->prev = &empty_array;						\
-  (a)->next = empty_array.next;						\
-  empty_array.next = (a);						\
-  (a)->next->prev = (a);						\
-} while (0)
-
-#define UNLINK_ARRAY(a) do {						\
-  struct array *next = (a)->next, *prev = (a)->prev;			\
-  prev->next = next;							\
-  next->prev = prev;							\
-} while (0)
-
 /* These are arguments for the function 'merge' which merges two sorted
  * set stored in arrays in the way you specify
  */
diff --git a/src/gc.c b/src/gc.c
index 4461bae5d03b16c91eccede818f84e6fea750a55..b0d9aaaf8ae296a606dec1737d9eb9ca1cd95495 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -2,7 +2,7 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: gc.c,v 1.240 2004/03/15 19:03:48 mast Exp $
+|| $Id: gc.c,v 1.241 2004/03/15 22:23:14 mast Exp $
 */
 
 #include "global.h"
@@ -33,7 +33,7 @@ struct callback *gc_evaluator_callback=0;
 
 #include "block_alloc.h"
 
-RCSID("$Id: gc.c,v 1.240 2004/03/15 19:03:48 mast Exp $");
+RCSID("$Id: gc.c,v 1.241 2004/03/15 22:23:14 mast Exp $");
 
 int gc_enabled = 1;
 
@@ -284,12 +284,9 @@ int attempt_to_identify(void *something, void **inblock)
 
   if (inblock) *inblock = 0;
 
-  a=&empty_array;
-  do
-  {
+  for (a = first_array; a; a = a->next) {
     if(a==(struct array *)something) return T_ARRAY;
-    a=a->next;
-  }while(a!=&empty_array);
+  }
 
   for(o=first_object;o;o=o->next) {
     if(o==(struct object *)something)
@@ -2196,7 +2193,7 @@ int gc_cycle_push(void *x, struct marker *m, int weak)
     struct program *p;
     struct mapping *m;
     struct multiset *l;
-    for(a = gc_internal_array; a != &empty_array; a = a->next)
+    for(a = gc_internal_array; a; a = a->next)
       if(a == (struct array *) x) goto on_gc_internal_lists;
     for(o = gc_internal_object; o; o = o->next)
       if(o == (struct object *) x) goto on_gc_internal_lists;
@@ -2794,7 +2791,7 @@ size_t do_gc(void *ignored, int explicit_call)
   /* Anything after and including gc_internal_* in the linked lists
    * are considered to lack external references. The mark pass move
    * externally referenced things in front of these pointers. */
-  gc_internal_array = empty_array.next;
+  gc_internal_array = first_array;
   gc_internal_multiset = first_multiset;
   gc_internal_mapping = first_mapping;
   gc_internal_program = first_program;
@@ -2946,7 +2943,7 @@ size_t do_gc(void *ignored, int explicit_call)
    * added above are removed just before the calls so we'll get the
    * correct relative positions in them. */
   unreferenced = 0;
-  if (gc_internal_array != &weak_empty_array)
+  if (gc_internal_array)
     unreferenced += gc_free_all_unreferenced_arrays();
   if (gc_internal_multiset)
     unreferenced += gc_free_all_unreferenced_multisets();
diff --git a/src/main.c b/src/main.c
index 4b4c470f85f35a3b2bfac20a617b892a20725744..23375d98d9440d5bbff778b9a3cd28c5ec49f33b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,11 +2,11 @@
 || This file is part of Pike. For copyright information see COPYRIGHT.
 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
 || for more information.
-|| $Id: main.c,v 1.190 2004/03/10 09:40:00 grubba Exp $
+|| $Id: main.c,v 1.191 2004/03/15 22:23:14 mast Exp $
 */
 
 #include "global.h"
-RCSID("$Id: main.c,v 1.190 2004/03/10 09:40:00 grubba Exp $");
+RCSID("$Id: main.c,v 1.191 2004/03/15 22:23:14 mast Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include "module.h"
@@ -984,10 +984,10 @@ void low_exit_main(void)
 
     search_all_memheaders_for_references();
 
-#define REPORT_LINKED_LIST_LEAKS(TYPE, START, END, T_TYPE, NAME) do {	\
+#define REPORT_LINKED_LIST_LEAKS(TYPE, START, T_TYPE, NAME) do {	\
       size_t num = 0;							\
       struct TYPE *x;							\
-      for (x = START; x != END; x = x->next) {				\
+      for (x = START; x; x = x->next) {					\
 	struct marker *m = find_marker (x);				\
 	num++;								\
 	if (!m) {							\
@@ -1004,11 +1004,11 @@ void low_exit_main(void)
 	fprintf (stderr, NAME "s left: %"PRINTSIZET"d\n", num);		\
     } while (0)
 
-    REPORT_LINKED_LIST_LEAKS (array, empty_array.next, &weak_empty_array, T_ARRAY, "Array");
-    REPORT_LINKED_LIST_LEAKS (multiset, first_multiset, NULL, T_MULTISET, "Multiset");
-    REPORT_LINKED_LIST_LEAKS (mapping, first_mapping, NULL, T_MAPPING, "Mapping");
-    REPORT_LINKED_LIST_LEAKS (program, first_program, NULL, T_PROGRAM, "Program");
-    REPORT_LINKED_LIST_LEAKS (object, first_object, NULL, T_OBJECT, "Object");
+    REPORT_LINKED_LIST_LEAKS (array, first_array, T_ARRAY, "Array");
+    REPORT_LINKED_LIST_LEAKS (multiset, first_multiset, T_MULTISET, "Multiset");
+    REPORT_LINKED_LIST_LEAKS (mapping, first_mapping, T_MAPPING, "Mapping");
+    REPORT_LINKED_LIST_LEAKS (program, first_program, T_PROGRAM, "Program");
+    REPORT_LINKED_LIST_LEAKS (object, first_object, T_OBJECT, "Object");
 
 #undef REPORT_LINKED_LIST_LEAKS
 
@@ -1016,9 +1016,9 @@ void low_exit_main(void)
      * another gc so that we don't report the blocks again in the low
      * level dmalloc reports. */
 
-#define ZAP_LINKED_LIST_LEAKS(TYPE, START, END) do {			\
+#define ZAP_LINKED_LIST_LEAKS(TYPE, START) do {				\
       struct TYPE *x;							\
-      for (x = START; x != END; x = x->next) {				\
+      for (x = START; x; x = x->next) {					\
 	struct marker *m = find_marker (x);				\
 	if (m)								\
 	  while (x->refs > m->refs)					\
@@ -1026,11 +1026,11 @@ void low_exit_main(void)
       }									\
     } while (0)
 
-    ZAP_LINKED_LIST_LEAKS (array, empty_array.next, &weak_empty_array);
-    ZAP_LINKED_LIST_LEAKS (multiset, first_multiset, NULL);
-    ZAP_LINKED_LIST_LEAKS (mapping, first_mapping, NULL);
-    ZAP_LINKED_LIST_LEAKS (program, first_program, NULL);
-    ZAP_LINKED_LIST_LEAKS (object, first_object, NULL);
+    ZAP_LINKED_LIST_LEAKS (array, first_array);
+    ZAP_LINKED_LIST_LEAKS (multiset, first_multiset);
+    ZAP_LINKED_LIST_LEAKS (mapping, first_mapping);
+    ZAP_LINKED_LIST_LEAKS (program, first_program);
+    ZAP_LINKED_LIST_LEAKS (object, first_object);
 
 #undef ZAP_LINKED_LIST_LEAKS