diff --git a/src/array.c b/src/array.c
index 26a2cf62e1020d7630fa8c313d48f37ded619a87..731a47202d54fd4eab6ca6a08016eb70997b1064 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.159 2004/05/13 23:28:49 nilsson Exp $
+|| $Id: array.c,v 1.160 2004/05/28 16:08:24 grubba Exp $
 */
 
 #include "global.h"
@@ -26,7 +26,7 @@
 #include "cyclic.h"
 #include "multiset.h"
 
-RCSID("$Id: array.c,v 1.159 2004/05/13 23:28:49 nilsson Exp $");
+RCSID("$Id: array.c,v 1.160 2004/05/28 16:08:24 grubba Exp $");
 
 PMOD_EXPORT struct array empty_array=
 {
@@ -2096,33 +2096,29 @@ PMOD_EXPORT struct pike_string *implode(struct array *a,struct pike_string *del)
   return low_end_shared_string(ret);
 }
 
-PMOD_EXPORT struct array *copy_array_recursively(struct array *a,struct processing *p)
+PMOD_EXPORT struct array *copy_array_recursively(struct array *a,
+						 struct mapping *m)
 {
-  struct processing doing;
   struct array *ret;
+  struct svalue aa, bb;
 
 #ifdef PIKE_DEBUG
   if(d_flag > 1)  array_check_type_field(a);
 #endif
 
-  doing.next=p;
-  doing.pointer_a=(void *)a;
-  for(;p;p=p->next)
-  {
-    if(p->pointer_a == (void *)a)
-    {
-      ret=(struct array *)p->pointer_b;
-      add_ref(ret);
-      return ret;
-    }
-  }
-
   ret=allocate_array_no_init(a->size,0);
-  doing.pointer_b=(void *)ret;
+
+  aa.type = T_ARRAY;
+  aa.subtype = 0;
+  aa.u.array = a;
+  bb.type = T_ARRAY;
+  bb.subtype = 0;
+  bb.u.array = ret;
+  low_mapping_insert(m, &aa, &bb);
 
   ret->flags = a->flags & ~ARRAY_LVALUE;
 
-  copy_svalues_recursively_no_free(ITEM(ret),ITEM(a),a->size,&doing);
+  copy_svalues_recursively_no_free(ITEM(ret),ITEM(a),a->size,m);
 
   ret->type_field=a->type_field;
   return ret;
diff --git a/src/array.h b/src/array.h
index c88cac80f554c2e95e1aeea839bae2a975aec2ba..e75bd270f89eba638dd9dd83eabf3e948593a7e4 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.60 2004/05/13 23:28:50 nilsson Exp $
+|| $Id: array.h,v 1.61 2004/05/28 16:08:24 grubba Exp $
 */
 
 #ifndef ARRAY_H
@@ -164,7 +164,8 @@ PMOD_EXPORT struct array *append_array(struct array *a, struct svalue *s);
 PMOD_EXPORT struct array *explode(struct pike_string *str,
 		       struct pike_string *del);
 PMOD_EXPORT struct pike_string *implode(struct array *a,struct pike_string *del);
-PMOD_EXPORT struct array *copy_array_recursively(struct array *a,struct processing *p);
+PMOD_EXPORT struct array *copy_array_recursively(struct array *a,
+						 struct mapping *p);
 PMOD_EXPORT void apply_array(struct array *a, INT32 args);
 PMOD_EXPORT struct array *reverse_array(struct array *a);
 void array_replace(struct array *a,
diff --git a/src/mapping.c b/src/mapping.c
index c122072dd1d0815bb7306b2dd0d01019604e1e19..ec9cb496aaca0f85582b0c792f2e120a4c606bef 100644
--- a/src/mapping.c
+++ b/src/mapping.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: mapping.c,v 1.180 2004/04/15 00:12:04 nilsson Exp $
+|| $Id: mapping.c,v 1.181 2004/05/28 16:08:24 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: mapping.c,v 1.180 2004/04/15 00:12:04 nilsson Exp $");
+RCSID("$Id: mapping.c,v 1.181 2004/05/28 16:08:24 grubba Exp $");
 #include "main.h"
 #include "object.h"
 #include "mapping.h"
@@ -648,9 +648,9 @@ PMOD_EXPORT void mapping_set_flags(struct mapping *m, int flags)
  *   2: Replace both the index and the value if the entry exists.
  */
 PMOD_EXPORT void low_mapping_insert(struct mapping *m,
-			struct svalue *key,
-			struct svalue *val,
-			int overwrite)
+				    const struct svalue *key,
+				    const struct svalue *val,
+				    int overwrite)
 {
   unsigned INT32 h,h2;
   struct keypair *k, **prev;
@@ -759,8 +759,8 @@ PMOD_EXPORT void low_mapping_insert(struct mapping *m,
 }
 
 PMOD_EXPORT void mapping_insert(struct mapping *m,
-		    struct svalue *key,
-		    struct svalue *val)
+				const struct svalue *key,
+				const struct svalue *val)
 {
   low_mapping_insert(m,key,val,1);
 }
@@ -1040,7 +1040,7 @@ PMOD_EXPORT void check_mapping_for_destruct(struct mapping *m)
 }
 
 PMOD_EXPORT struct svalue *low_mapping_lookup(struct mapping *m,
-				  struct svalue *key)
+					      const struct svalue *key)
 {
   unsigned INT32 h,h2;
   struct keypair *k=0, **prev=0;
@@ -2010,30 +2010,19 @@ PMOD_EXPORT void f_aggregate_mapping(INT32 args)
 }
 
 PMOD_EXPORT struct mapping *copy_mapping_recursively(struct mapping *m,
-						     struct processing *p)
+						     struct mapping *p)
 {
-  struct processing doing;
   struct mapping *ret;
   INT32 e;
   struct keypair *k;
   struct mapping_data  *md;
+  struct svalue aa, bb;
 
 #ifdef PIKE_DEBUG
   if(m->data->refs <=0)
     Pike_fatal("Zero refs in mapping->data\n");
 #endif
 
-  doing.next=p;
-  doing.pointer_a=(void *)m;
-  for(;p;p=p->next)
-  {
-    if(p->pointer_a == (void *)m)
-    {
-      add_ref(ret=(struct mapping *)p->pointer_b);
-      return ret;
-    }
-  }
-
 #ifdef PIKE_DEBUG
   if(d_flag > 1) check_mapping_type_fields(m);
 #endif
@@ -2042,7 +2031,14 @@ PMOD_EXPORT struct mapping *copy_mapping_recursively(struct mapping *m,
     return copy_mapping(m);
 
   ret=allocate_mapping(MAP_SLOTS(m->data->size));
-  doing.pointer_b=ret;
+
+  aa.type = T_MAPPING;
+  aa.subtype = 0;
+  aa.u.mapping = m;
+  bb.type = T_MAPPING;
+  bb.subtype = 0;
+  bb.u.mapping = ret;
+  mapping_insert(p, &aa, &bb);
 
   ret->data->flags = m->data->flags;
 
@@ -2053,10 +2049,10 @@ PMOD_EXPORT struct mapping *copy_mapping_recursively(struct mapping *m,
   add_ref(md);
   NEW_MAPPING_LOOP(md)
   {
-    copy_svalues_recursively_no_free(Pike_sp,&k->ind, 1, &doing);
+    copy_svalues_recursively_no_free(Pike_sp,&k->ind, 1, p);
     Pike_sp++;
     dmalloc_touch_svalue(Pike_sp-1);
-    copy_svalues_recursively_no_free(Pike_sp,&k->val, 1, &doing);
+    copy_svalues_recursively_no_free(Pike_sp,&k->val, 1, p);
     Pike_sp++;
     dmalloc_touch_svalue(Pike_sp-1);
     
diff --git a/src/mapping.h b/src/mapping.h
index 4b9f75c3f6488e0b3d5f63c4b293b70717a74e57..7dd54c638447a3f157a12f64b00d276f2f487e55 100644
--- a/src/mapping.h
+++ b/src/mapping.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: mapping.h,v 1.55 2004/04/29 23:56:21 nilsson Exp $
+|| $Id: mapping.h,v 1.56 2004/05/28 16:08:24 grubba Exp $
 */
 
 #ifndef MAPPING_H
@@ -121,12 +121,12 @@ struct mapping_data *copy_mapping_data(struct mapping_data *md);
 PMOD_EXPORT void mapping_fix_type_field(struct mapping *m);
 PMOD_EXPORT void mapping_set_flags(struct mapping *m, int flags);
 PMOD_EXPORT void low_mapping_insert(struct mapping *m,
-			struct svalue *key,
-			struct svalue *val,
-			int overwrite);
+				    const struct svalue *key,
+				    const struct svalue *val,
+				    int overwrite);
 PMOD_EXPORT void mapping_insert(struct mapping *m,
-		    struct svalue *key,
-		    struct svalue *val);
+				const struct svalue *key,
+				const struct svalue *val);
 PMOD_EXPORT union anything *mapping_get_item_ptr(struct mapping *m,
 				     struct svalue *key,
 				     TYPE_T t);
@@ -135,7 +135,7 @@ PMOD_EXPORT void map_delete_no_free(struct mapping *m,
 			struct svalue *to);
 PMOD_EXPORT void check_mapping_for_destruct(struct mapping *m);
 PMOD_EXPORT struct svalue *low_mapping_lookup(struct mapping *m,
-				  struct svalue *key);
+					      const struct svalue *key);
 PMOD_EXPORT struct svalue *low_mapping_string_lookup(struct mapping *m,
 					 struct pike_string *p);
 PMOD_EXPORT void mapping_string_insert(struct mapping *m,
@@ -175,7 +175,7 @@ void describe_mapping(struct mapping *m,struct processing *p,int indent);
 node *make_node_from_mapping(struct mapping *m);
 PMOD_EXPORT void f_aggregate_mapping(INT32 args);
 PMOD_EXPORT struct mapping *copy_mapping_recursively(struct mapping *m,
-						     struct processing *p);
+						     struct mapping *p);
 PMOD_EXPORT void mapping_search_no_free(struct svalue *to,
 			    struct mapping *m,
 			    struct svalue *look_for,
diff --git a/src/multiset.c b/src/multiset.c
index 4142c0f22c7aa40b2c94314fa5ed63b7412e9af1..54b89c7f2de271b9585fcc3251388c4e09948174 100644
--- a/src/multiset.c
+++ b/src/multiset.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: multiset.c,v 1.85 2004/05/19 19:02:08 mast Exp $
+|| $Id: multiset.c,v 1.86 2004/05/28 16:08:24 grubba Exp $
 */
 
 #include "global.h"
@@ -24,7 +24,7 @@
 #include "svalue.h"
 #include "block_alloc.h"
 
-RCSID("$Id: multiset.c,v 1.85 2004/05/19 19:02:08 mast Exp $");
+RCSID("$Id: multiset.c,v 1.86 2004/05/28 16:08:24 grubba Exp $");
 
 /* FIXME: Optimize finds and searches on type fields? (But not when
  * objects are involved!) Well.. Although cheap I suspect it pays off
@@ -3630,9 +3630,8 @@ PMOD_EXPORT void f_aggregate_multiset (INT32 args)
 }
 
 struct multiset *copy_multiset_recursively (struct multiset *l,
-					    struct processing *p)
+					    struct mapping *p)
 {
-  struct processing curr;
   struct tree_build_data new;
   struct multiset_data *msd = l->msd;
   union msnode *node;
@@ -3640,19 +3639,11 @@ struct multiset *copy_multiset_recursively (struct multiset *l,
   struct svalue ind;
   TYPE_FIELD ind_types, val_types;
   ONERROR uwp;
+  struct svalue aa, bb;
 
   debug_malloc_touch (l);
   debug_malloc_touch (msd);
 
-  curr.pointer_a = (void *) l;
-  curr.next = p;
-
-  for (; p; p = p->next)
-    if (p->pointer_a == (void *) l) {
-      add_ref ((struct multiset *) p->pointer_b);
-      return (struct multiset *) p->pointer_b;
-    }
-
 #ifdef PIKE_DEBUG
   if (d_flag > 1) check_multiset_type_fields (l);
 #endif
@@ -3672,11 +3663,18 @@ struct multiset *copy_multiset_recursively (struct multiset *l,
   assign_svalue_no_free (&new.msd->cmp_less, &msd->cmp_less);
   ind_types = 0;
   val_types = got_values ? 0 : BIT_INT;
-  curr.pointer_b = (void *) new.l;
   add_ref (new.msd2 = msd);
   node = low_multiset_first (msd);
   SET_ONERROR (uwp, free_tree_build_data, &new);
 
+  aa.type = T_MULTISET;
+  aa.subtype = 0;
+  aa.u.multiset = l;
+  bb.type = T_MULTISET;
+  bb.subtype = 0;
+  bb.u.multiset = new.l;
+  mapping_insert(p, &aa, &bb);
+
   node = low_multiset_first (msd);
   pos = 0;
   do {
@@ -3690,12 +3688,12 @@ struct multiset *copy_multiset_recursively (struct multiset *l,
 
     copy_svalues_recursively_no_free (&new.node->i.ind,
 				      low_use_multiset_index (node, ind),
-				      1, &curr);
+				      1, p);
     ind_types |= 1 << new.node->i.ind.type;
 
     if (got_values) {
       copy_svalues_recursively_no_free (&new.node->iv.val, &node->iv.val,
-					1, &curr);
+					1, p);
       val_types |= 1 << new.node->iv.val.type;
     }
 
diff --git a/src/multiset.h b/src/multiset.h
index 561f4e5a1b21b594be767abade68e3cf271df150..5de8b934d9008867047964affbaf5a7c6f279cfb 100644
--- a/src/multiset.h
+++ b/src/multiset.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: multiset.h,v 1.34 2004/04/18 02:16:06 mast Exp $
+|| $Id: multiset.h,v 1.35 2004/05/28 16:08:24 grubba Exp $
 */
 
 #ifndef MULTISET_H
@@ -412,7 +412,7 @@ int multiset_is_constant (struct multiset *l, struct processing *p);
 node *make_node_from_multiset (struct multiset *l);
 PMOD_EXPORT void f_aggregate_multiset (int args);
 struct multiset *copy_multiset_recursively (struct multiset *l,
-					    struct processing *p);
+					    struct mapping *p);
 PMOD_EXPORT ptrdiff_t multiset_get_nth (struct multiset *l, size_t n);
 
 unsigned gc_touch_all_multisets (void);
diff --git a/src/svalue.c b/src/svalue.c
index 001b22db7e053fa44e8b45ccb504645a35541985..85faa55b5d2e79273ff70a41eff7ad26cf506a57 100644
--- a/src/svalue.c
+++ b/src/svalue.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: svalue.c,v 1.193 2004/04/17 23:22:50 mast Exp $
+|| $Id: svalue.c,v 1.194 2004/05/28 16:08:24 grubba Exp $
 */
 
 #include "global.h"
@@ -30,7 +30,7 @@
 
 #define sp Pike_sp
 
-RCSID("$Id: svalue.c,v 1.193 2004/04/17 23:22:50 mast Exp $");
+RCSID("$Id: svalue.c,v 1.194 2004/05/28 16:08:24 grubba Exp $");
 
 struct svalue dest_ob_zero = {
   T_INT, 0,
@@ -1652,15 +1652,32 @@ PMOD_EXPORT void print_short_svalue_compact (FILE *out, const union anything *a,
 }
 
 PMOD_EXPORT void copy_svalues_recursively_no_free(struct svalue *to,
-				      const struct svalue *from,
-				      size_t num,
-				      struct processing *p)
+						  const struct svalue *from,
+						  size_t num,
+						  struct mapping *m)
 {
+  ONERROR err;
+  int allocated_here = 0;
+  if (!m) {
+    m = allocate_mapping(num);
+    allocated_here = 1;
+    SET_ONERROR(err, do_free_mapping, m);
+  }
   while(num--)
   {
+    struct svalue *tmp;
+
     check_type(from->type);
     check_refs(from);
 
+    if ((tmp = low_mapping_lookup(m, from))) {
+      *to = *tmp;
+      if (tmp->type <= MAX_REF_TYPE) add_ref(tmp->u.dummy);
+      to++;
+      from++;
+      continue;
+    }
+
     switch(from->type)
     {
     default:
@@ -1669,23 +1686,27 @@ PMOD_EXPORT void copy_svalues_recursively_no_free(struct svalue *to,
       break;
 
     case T_ARRAY:
-      to->u.array=copy_array_recursively(from->u.array,p);
+      to->u.array=copy_array_recursively(from->u.array,m);
       to->type=T_ARRAY;
       break;
 
     case T_MAPPING:
-      to->u.mapping=copy_mapping_recursively(from->u.mapping,p);
+      to->u.mapping=copy_mapping_recursively(from->u.mapping,m);
       to->type=T_MAPPING;
       break;
 
     case T_MULTISET:
-      to->u.multiset=copy_multiset_recursively(from->u.multiset,p);
+      to->u.multiset=copy_multiset_recursively(from->u.multiset,m);
       to->type=T_MULTISET;
       break;
     }
+    mapping_insert(m, from, to);
     to++;
     from++;
   }
+  if (allocated_here) {
+    CALL_AND_UNSET_ONERROR(err);
+  }
 }
 
 #ifdef PIKE_DEBUG
diff --git a/src/svalue.h b/src/svalue.h
index c11b4e060e6ff8f09c75655ed29cd6fd46ca2489..d8baae6700f4073161aa0d43cf300feafd12eb59 100644
--- a/src/svalue.h
+++ b/src/svalue.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: svalue.h,v 1.128 2004/04/03 18:24:39 mast Exp $
+|| $Id: svalue.h,v 1.129 2004/05/28 16:08:24 grubba Exp $
 */
 
 #ifndef SVALUE_H
@@ -591,9 +591,9 @@ PMOD_EXPORT void print_short_svalue (FILE *out, const union anything *a, TYPE_T
 PMOD_EXPORT void print_svalue_compact (FILE *out, const struct svalue *s);
 PMOD_EXPORT void print_short_svalue_compact (FILE *out, const union anything *a, TYPE_T type);
 PMOD_EXPORT void copy_svalues_recursively_no_free(struct svalue *to,
-				      const struct svalue *from,
-				      size_t num,
-				      struct processing *p);
+						  const struct svalue *from,
+						  size_t num,
+						  struct mapping *m);
 void check_short_svalue(const union anything *u, TYPE_T type);
 void debug_check_svalue(const struct svalue *s);
 void debug_check_type_hint (const struct svalue *svals, size_t num, TYPE_FIELD type_hint);