From 50ea68149a796c72a3e390b708c8830befd3c9c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20Grubbstr=C3=B6m=20=28Grubba=29?=
 <grubba@grubba.org>
Date: Fri, 14 Mar 2003 16:57:49 +0100
Subject: [PATCH] Improved dmalloc.

Rev: src/apply_low.h:1.16
Rev: src/array.c:1.138
Rev: src/backend.cmod:1.38
Rev: src/bignum.c:1.34
Rev: src/block_alloc.h:1.63
Rev: src/builtin_functions.c:1.479
Rev: src/code/ia32.c:1.25
Rev: src/cpp.c:1.115
Rev: src/encode.c:1.169
Rev: src/error.c:1.102
Rev: src/gc.c:1.209
Rev: src/interpret.c:1.295
Rev: src/interpret.h:1.131
Rev: src/interpret_functions.h:1.141
Rev: src/iterators.cmod:1.35
Rev: src/las.c:1.330
Rev: src/mapping.c:1.163
Rev: src/modules/Image/orient.c:1.24
Rev: src/modules/Image/phase.h:1.6
Rev: src/modules/Java/jvm.c:1.60
Rev: src/modules/SANE/sane.c:1.17
Rev: src/modules/_Roxen/roxen.c:1.33
Rev: src/multiset.c:1.69
Rev: src/object.c:1.228
Rev: src/opcodes.c:1.143
Rev: src/operators.c:1.172
Rev: src/pike_types.c:1.211
Rev: src/post_modules/Shuffler/Shuffler.cmod:1.23
Rev: src/post_modules/Shuffler/a_source_pikestring.c:1.8
Rev: src/post_modules/Shuffler/a_source_system_memory.c:1.9
Rev: src/post_modules/Shuffler/b_source_normal_file.c:1.8
Rev: src/post_modules/Shuffler/c_source_stream.c:1.7
Rev: src/post_modules/Shuffler/d_source_pikestream.c:1.6
Rev: src/post_modules/Shuffler/e_source_block_pikestream.c:1.2
Rev: src/preprocessor.h:1.58
Rev: src/program.c:1.486
Rev: src/signal_handler.c:1.249
Rev: src/stralloc.c:1.153
Rev: src/stralloc.h:1.73
Rev: src/svalue.c:1.161
Rev: src/threads.c:1.211
---
 src/apply_low.h                               |  11 +-
 src/array.c                                   |   9 +-
 src/backend.cmod                              |   5 +-
 src/bignum.c                                  |   8 +-
 src/block_alloc.h                             |  10 +-
 src/builtin_functions.c                       |  11 +-
 src/code/ia32.c                               |   8 +-
 src/cpp.c                                     |   3 +-
 src/encode.c                                  |  22 +++-
 src/error.c                                   |   6 +-
 src/gc.c                                      |   5 +-
 src/interpret.c                               |  15 ++-
 src/interpret.h                               |  51 +++++----
 src/interpret_functions.h                     |  13 ++-
 src/iterators.cmod                            |  12 ++-
 src/las.c                                     |  23 ++--
 src/mapping.c                                 |  18 ++--
 src/modules/Image/orient.c                    |   4 +-
 src/modules/Image/phase.h                     |   5 +-
 src/modules/Java/jvm.c                        |  53 ++++-----
 src/modules/SANE/sane.c                       |   6 +-
 src/modules/_Roxen/roxen.c                    |   8 +-
 src/multiset.c                                |  10 +-
 src/object.c                                  | 102 ++++++++++++++----
 src/opcodes.c                                 |   8 +-
 src/operators.c                               |  10 +-
 src/pike_types.c                              |   9 +-
 src/post_modules/Shuffler/Shuffler.cmod       |  13 +--
 .../Shuffler/a_source_pikestring.c            |   9 +-
 .../Shuffler/a_source_system_memory.c         |   8 +-
 .../Shuffler/b_source_normal_file.c           |   4 +-
 src/post_modules/Shuffler/c_source_stream.c   |   4 +-
 .../Shuffler/d_source_pikestream.c            |   4 +-
 .../Shuffler/e_source_block_pikestream.c      |   4 +-
 src/preprocessor.h                            |   3 +-
 src/program.c                                 |   9 +-
 src/signal_handler.c                          |   9 +-
 src/stralloc.c                                |   6 +-
 src/stralloc.h                                |  10 +-
 src/svalue.c                                  |  27 +++--
 src/threads.c                                 |   5 +-
 41 files changed, 353 insertions(+), 207 deletions(-)

diff --git a/src/apply_low.h b/src/apply_low.h
index 8e4e1ce5b7..9d45674137 100644
--- a/src/apply_low.h
+++ b/src/apply_low.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: apply_low.h,v 1.15 2003/02/24 21:50:46 mast Exp $
+|| $Id: apply_low.h,v 1.16 2003/03/14 15:50:43 grubba Exp $
 */
 
     {
@@ -227,6 +227,15 @@
 	  /* Create an extra svalue for tail recursion style call */
 	  Pike_sp++;
 	  MEMMOVE(Pike_sp-args,Pike_sp-args-1,sizeof(struct svalue)*args);
+#ifdef DEBUG_MALLOC
+	  {
+	    int i;
+	    /* Note: touch the dead svalue too. */
+	    for (i=args+2; i > 0; i--) {
+	      dmalloc_touch_svalue(Pike_sp-i);
+	    }
+	  }
+#endif /* DEBUG_MALLOC */	      
 	  Pike_sp[-args-1].type=T_INT;
 	}else{
 	  free_svalue(Pike_sp-args-1);
diff --git a/src/array.c b/src/array.c
index 701f2a960c..35baa4e5e6 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.137 2003/02/01 15:43:50 mast Exp $
+|| $Id: array.c,v 1.138 2003/03/14 15:50:43 grubba Exp $
 */
 
 #include "global.h"
@@ -25,7 +25,7 @@
 #include "bignum.h"
 #include "cyclic.h"
 
-RCSID("$Id: array.c,v 1.137 2003/02/01 15:43:50 mast Exp $");
+RCSID("$Id: array.c,v 1.138 2003/03/14 15:50:43 grubba Exp $");
 
 PMOD_EXPORT struct array empty_array=
 {
@@ -143,7 +143,7 @@ PMOD_EXPORT void really_free_array(struct array *v)
   add_ref(v);
   EXIT_PIKE_MEMOBJ(v);
   free_svalues(ITEM(v), v->size, v->type_field);
-  v->refs--;
+  sub_ref(v);
   array_free_no_free(v);
 }
 
@@ -217,8 +217,8 @@ PMOD_EXPORT void simple_array_index_no_free(struct svalue *s,
       ref_push_array(a);
       assign_svalue_no_free(Pike_sp++,ind);
       f_column(2);
-      s[0]=Pike_sp[-1];
       Pike_sp--;
+      *s = *Pike_sp;
       dmalloc_touch_svalue(Pike_sp);
       break;
     }
@@ -2390,6 +2390,7 @@ PMOD_EXPORT struct array *explode_array(struct array *a, struct array *b)
     } END_AGGREGATE_ARRAY;
   }
   tmp=(--Pike_sp)->u.array;
+  debug_malloc_touch(tmp);
   if(tmp->size) tmp->type_field=BIT_ARRAY;
   return tmp;
 }
diff --git a/src/backend.cmod b/src/backend.cmod
index a3dfe0e28d..91d2fd5a81 100644
--- a/src/backend.cmod
+++ b/src/backend.cmod
@@ -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: backend.cmod,v 1.37 2003/02/24 09:29:55 grubba Exp $
+|| $Id: backend.cmod,v 1.38 2003/03/14 15:53:09 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: backend.cmod,v 1.37 2003/02/24 09:29:55 grubba Exp $");
+RCSID("$Id: backend.cmod,v 1.38 2003/03/14 15:53:09 grubba Exp $");
 #include "fdlib.h"
 #include "backend.h"
 #include <errno.h>
@@ -1592,6 +1592,7 @@ PIKECLASS Backend
      
      new->args=args;
      Pike_sp--;
+     dmalloc_touch_svalue(Pike_sp);
      
      
      me->num_pending_calls++;
diff --git a/src/bignum.c b/src/bignum.c
index f026637a92..9e5d52298d 100644
--- a/src/bignum.c
+++ b/src/bignum.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: bignum.c,v 1.33 2003/02/14 19:19:57 mast Exp $
+|| $Id: bignum.c,v 1.34 2003/03/14 15:50:43 grubba Exp $
 */
 
 #include "global.h"
@@ -88,6 +88,7 @@ PMOD_EXPORT int is_bignum_object_in_svalue(struct svalue *sv)
 PMOD_EXPORT struct object *make_bignum_object(void)
 {
   convert_stack_top_to_bignum();
+  dmalloc_touch_svalue(sp-1);
   return (--sp)->u.object;
 }
 
@@ -95,6 +96,7 @@ PMOD_EXPORT struct object *bignum_from_svalue(struct svalue *s)
 {
   push_svalue(s);
   convert_stack_top_to_bignum();
+  dmalloc_touch_svalue(sp-1);
   return (--sp)->u.object;
 }
 
@@ -106,6 +108,7 @@ PMOD_EXPORT struct pike_string *string_from_bignum(struct object *o, int base)
   if(sp[-1].type != T_STRING)
     Pike_error("Gmp.mpz string conversion failed.\n");
   
+  dmalloc_touch_svalue(sp-1);
   return (--sp)->u.string;
 }
 
@@ -173,6 +176,7 @@ PMOD_EXPORT int int64_from_bignum(INT64 *i, struct object *bignum)
   apply_low(bignum, FIND_LFUN(bignum->prog, LFUN_LT), 1);
   if(sp[-1].type != T_INT)
     Pike_error("Result from Gmp.bignum->`< not an integer.\n");
+  dmalloc_touch_svalue(sp-1);
   neg = (--sp)->u.integer;
 
   if(neg)
@@ -189,6 +193,7 @@ PMOD_EXPORT int int64_from_bignum(INT64 *i, struct object *bignum)
     apply_low(sp[-2].u.object, andfun, 1);
     if(sp[-1].type != T_INT)
       Pike_error("Result from Gmp.bignum->`& not an integer.\n");
+    dmalloc_touch_svalue(sp-1);
     *i |= (INT64)(--sp)->u.integer << (INT64)pos;
     pos += BIGNUM_INT64_SHIFT;
     
@@ -198,6 +203,7 @@ PMOD_EXPORT int int64_from_bignum(INT64 *i, struct object *bignum)
     pop_stack();
   }
   
+  dmalloc_touch_svalue(sp-1);
   *i |= (INT64)(--sp)->u.integer << (INT64)pos;
 
   if(neg)
diff --git a/src/block_alloc.h b/src/block_alloc.h
index 59ab997898..53d554bfc3 100644
--- a/src/block_alloc.h
+++ b/src/block_alloc.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: block_alloc.h,v 1.62 2003/02/24 20:00:52 grubba Exp $
+|| $Id: block_alloc.h,v 1.63 2003/03/14 15:50:43 grubba Exp $
 */
 
 #undef PRE_INIT_BLOCK
@@ -23,7 +23,11 @@
 /* Note: The block_alloc mutex is held while PRE_INIT_BLOCK runs. */
 #define PRE_INIT_BLOCK(X)
 #define INIT_BLOCK(X)
+#ifdef DEBUG_MALLOC
+#define EXIT_BLOCK(X)	MEMSET((X), 0x55, sizeof(*(X)))
+#else
 #define EXIT_BLOCK(X)
+#endif /* DEBUG_MALLOC */
 #define COUNT_BLOCK(X)
 #define COUNT_OTHER()
 #define BLOCK_ALLOC_HSIZE_SHIFT 2
@@ -186,7 +190,7 @@ static void PIKE_CONCAT(check_free_,DATA)(struct DATA *d)               \
     return;                                                             \
   }                                                                     \
   Pike_fatal("really_free_%s called on non-block_alloc region (%p).\n",	\
-         #DATA, d);                                                     \
+	     #DATA, d);							\
 }                                                                       \
 )									\
 									\
@@ -248,10 +252,10 @@ void PIKE_CONCAT(really_free_,DATA)(struct DATA *d)			\
   }									\
 									\
   d->BLOCK_ALLOC_NEXT = (void *)blk->PIKE_CONCAT3(free_,DATA,s);	\
+  blk->PIKE_CONCAT3(free_,DATA,s)=d;					\
   PRE_INIT_BLOCK(d);							\
   /* Mark block as unavailable. */					\
   PIKE_MEM_NA(*d);							\
-  blk->PIKE_CONCAT3(free_,DATA,s)=d;					\
 									\
   if(!--blk->BLOCK_ALLOC_USED &&					\
      ++PIKE_CONCAT3(num_empty_,DATA,_blocks) > MAX_EMPTY_BLOCKS) {	\
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 29324dd843..666b2bc74c 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.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: builtin_functions.c,v 1.478 2003/03/02 14:28:41 grubba Exp $
+|| $Id: builtin_functions.c,v 1.479 2003/03/14 15:50:43 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.478 2003/03/02 14:28:41 grubba Exp $");
+RCSID("$Id: builtin_functions.c,v 1.479 2003/03/14 15:50:43 grubba Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -5935,7 +5935,7 @@ PMOD_EXPORT void f__leak(INT32 args)
 			 "array|mapping|multiset|object|"
 			 "function|program|string");
 
-  add_ref(Pike_sp[-args].u.array);
+  add_ref(Pike_sp[-args].u.dummy);
   i=Pike_sp[-args].u.refs[0];
   pop_n_elems(args);
   push_int(i);
@@ -6265,6 +6265,7 @@ PMOD_EXPORT void f_uniq_array(INT32 args)
       assign_svalue_no_free(ITEM(b)+ j++, ITEM(a)+i);
     }
   }
+  dmalloc_touch_svalue(Pike_sp-1);
   Pike_sp--; /* keep the ref to 'b' */
   b=resize_array(b,  j);
   pop_n_elems(args-1); /* pop args and the mapping */
@@ -6730,6 +6731,7 @@ PMOD_EXPORT void f_map(INT32 args)
 	 push_svalue(mysp-2); /* fun */
 	 *Pike_sp=mysp[-1];        /* extra */
 	 mysp[-1].type=T_INT;
+	 dmalloc_touch_svalue(Pike_sp);
 	 push_array_items(Pike_sp->u.array);
 	 f_map(splice+2);     /* ... arr fun extra -> ... retval */
 	 stack_pop_n_elems_keep_top(2); /* arr fun extra ret -> arr retval */
@@ -6754,6 +6756,7 @@ PMOD_EXPORT void f_map(INT32 args)
 	 /* FIXME: Handle multisets with values like mappings. */
 	 push_multiset (mkmultiset_2 (Pike_sp[-1].u.array, NULL, NULL));
 	 free_array (Pike_sp[-2].u.array);
+	 dmalloc_touch_svalue(Pike_sp-1);
 	 Pike_sp[-2] = Pike_sp[-1];
 	 Pike_sp--;
 #else
@@ -7146,6 +7149,7 @@ PMOD_EXPORT void f_filter(INT32 args)
 
 	 push_svalue(Pike_sp-args);
 	 f_indices(1);
+	 dmalloc_touch_svalue(Pike_sp-1);
 	 Pike_sp--;
 	 Pike_sp[-args-2]=*Pike_sp;
 	 dmalloc_touch_svalue(Pike_sp);
@@ -7189,6 +7193,7 @@ PMOD_EXPORT void f_filter(INT32 args)
 	 push_multiset (mkmultiset_2 (Pike_sp[-1].u.array, NULL, NULL));
 	 free_array (Pike_sp[-2].u.array);
 	 Pike_sp[-2] = Pike_sp[-1];
+	 dmalloc_touch_svalue(Pike_sp-1);
 	 Pike_sp--;
 #else
 	 Pike_sp--;                      /* allocate_multiset is destructive */
diff --git a/src/code/ia32.c b/src/code/ia32.c
index f32dc4956f..f434f618d9 100644
--- a/src/code/ia32.c
+++ b/src/code/ia32.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: ia32.c,v 1.24 2003/02/16 03:59:58 mast Exp $
+|| $Id: ia32.c,v 1.25 2003/03/14 15:51:14 grubba Exp $
 */
 
 /*
@@ -394,6 +394,7 @@ void ins_f_byte(unsigned int b)
   maybe_update_pc();
   addr=instrs[b].address;
 
+#ifndef DEBUG_MALLOC
 #ifdef PIKE_DEBUG
   if (d_flag < 3)
 #endif
@@ -435,6 +436,7 @@ void ins_f_byte(unsigned int b)
       }
       break;
   }
+#endif /* !DEBUG_MALLOC */
   ia32_call_c_function(addr);
 }
 
@@ -442,6 +444,7 @@ void ins_f_byte_with_arg(unsigned int a,unsigned INT32 b)
 {
   maybe_update_pc();
 
+#ifndef DEBUG_MALLOC
 #ifdef PIKE_DEBUG
   if (d_flag < 3)
 #endif
@@ -497,6 +500,7 @@ void ins_f_byte_with_arg(unsigned int a,unsigned INT32 b)
       ia32_call_c_function(Pike_compiler->new_program->constants[b].sval.u.efun->function);
       return;
   }
+#endif /* !DEBUG_MALLOC */
   update_arg1(b);
   ins_f_byte(a);
 }
@@ -507,6 +511,7 @@ void ins_f_byte_with_2_args(unsigned int a,
 {
   maybe_update_pc();
 
+#ifndef DEBUG_MALLOC
 #ifdef PIKE_DEBUG
   if (d_flag < 3)
 #endif
@@ -518,6 +523,7 @@ void ins_f_byte_with_2_args(unsigned int a,
       ia32_push_local(c);
       return;
   }
+#endif /* !DEBUG_MALLOC */
   update_arg1(b);
   update_arg2(c);
   ins_f_byte(a);
diff --git a/src/cpp.c b/src/cpp.c
index 95d721f6f4..7cf4dd14de 100644
--- a/src/cpp.c
+++ b/src/cpp.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: cpp.c,v 1.114 2003/01/05 00:56:13 nilsson Exp $
+|| $Id: cpp.c,v 1.115 2003/03/14 15:53:09 grubba Exp $
 */
 
 #include "global.h"
@@ -364,6 +364,7 @@ void cpp_change_compat(struct cpp *this, int major, int minor)
   if(sp[-1].type == T_OBJECT)
   {
     this->compat_handler=sp[-1].u.object;
+    dmalloc_touch_svalue(Pike_sp-1);
     sp--;
   }
   this->compat_major=major;
diff --git a/src/encode.c b/src/encode.c
index 4fa60903e0..2a7ff213bd 100644
--- a/src/encode.c
+++ b/src/encode.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: encode.c,v 1.168 2003/02/24 19:03:03 mast Exp $
+|| $Id: encode.c,v 1.169 2003/03/14 15:53:09 grubba Exp $
 */
 
 #include "global.h"
@@ -27,7 +27,7 @@
 #include "bignum.h"
 #include "pikecode.h"
 
-RCSID("$Id: encode.c,v 1.168 2003/02/24 19:03:03 mast Exp $");
+RCSID("$Id: encode.c,v 1.169 2003/03/14 15:53:09 grubba Exp $");
 
 /* #define ENCODE_DEBUG */
 
@@ -683,7 +683,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data)
 	    /* This doesn't let bignums through. That's necessary as
 	     * long as they aren't handled deterministically by the
 	     * sort function. */
-	    /* They should be hanled deterministically now - Hubbe */
+	    /* They should be handled deterministically now - Hubbe */
 	    Pike_error("Canonical encoding requires basic types in indices.\n");
 	}
 	order = get_switch_order(Pike_sp[-2].u.array);
@@ -1434,6 +1434,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data)
 	    } else {
 	      push_int(0);
 	      encode_value2(Pike_sp-1, data);
+	      dmalloc_touch_svalue(Pike_sp-1);
 	      Pike_sp--;
 	    }
 	  }
@@ -1637,6 +1638,7 @@ static void fallback_codec(void)
   push_constant_text(".");
   f_divide(2);
   f_reverse(1);
+  dmalloc_touch_svalue(Pike_sp-1);
   Pike_sp--;
   x=Pike_sp->u.array->size;
   push_array_items(Pike_sp->u.array);
@@ -1993,7 +1995,7 @@ static int init_placeholder(struct object *placeholder);
    * safely decrease this reference here. Thus it will be automatically	\
    * freed if something goes wrong.					\
    */									\
-    VAR->refs--;							\
+    sub_ref(VAR);							\
   }									\
   data->counter.u.integer++;						\
 }while(0)
@@ -2398,6 +2400,7 @@ static void decode_value2(struct decode_data *data)
 #endif
 	      pop_n_elems(2);
 	      *Pike_sp++ = func;
+	      dmalloc_touch_svalue(Pike_sp-1);
 	      break;
 	    }
 	  }
@@ -2503,6 +2506,7 @@ static void decode_value2(struct decode_data *data)
 		placeholder=Pike_sp[-1].u.object;
 		if(placeholder->prog != null_program)
 		  Pike_error("Placeholder object is not a null_program clone!\n");
+		dmalloc_touch_svalue(Pike_sp-1);
 		Pike_sp--;
 	      }else{
 		pop_stack();
@@ -2720,7 +2724,7 @@ static void decode_value2(struct decode_data *data)
 	      if(Pike_sp[-1].type != T_PROGRAM ||
 		 Pike_sp[-1].u.program != p)
 		Pike_error("Program decode failed!\n");
-	      p->refs--;
+	      sub_ref(p);
 	    }
 
 	    if(data->pass > 1)
@@ -2831,6 +2835,7 @@ static void decode_value2(struct decode_data *data)
 	      assign_svalue(& p->constants[d].sval , Pike_sp -1 );
 	      pop_stack();
 	    }else{
+	      dmalloc_touch_svalue(Pike_sp-1);
 	      p->constants[d].sval=*--Pike_sp;
 	    }
 	    dmalloc_touch_svalue(Pike_sp);
@@ -3104,6 +3109,7 @@ static void decode_value2(struct decode_data *data)
 	    Pike_error("Bad type for parent program (%s)\n",
 		       get_name_of_type(Pike_sp[-1].type));
 	  }
+	  dmalloc_touch_svalue(Pike_sp-1);
 	  Pike_sp--;
 
 	  /* Decode lengths. */
@@ -3162,6 +3168,7 @@ static void decode_value2(struct decode_data *data)
 	      Pike_error("Non strings in string table.\n");
 	    }
 	    add_to_strings(Pike_sp[-1].u.string);
+	    dmalloc_touch_svalue(Pike_sp-1);
 	    Pike_sp--;
 	  }
 
@@ -3417,6 +3424,8 @@ static void decode_value2(struct decode_data *data)
 		}
 
 		add_to_identifiers(id);
+		dmalloc_touch_svalue(Pike_sp-1);
+		dmalloc_touch_svalue(Pike_sp-2);
 		Pike_sp -= 2;
 	      }
 	      break;
@@ -3547,6 +3556,8 @@ static void decode_value2(struct decode_data *data)
 	      Pike_error("Name of constant is not a string.\n");
 	    }
 	    constant->sval = Pike_sp[-2];
+	    dmalloc_touch_svalue(Pike_sp-1);
+	    dmalloc_touch_svalue(Pike_sp-2);
 	    Pike_sp -= 2;
 	  }
 
@@ -4012,6 +4023,7 @@ void f_decode_value(INT32 args)
 {
   struct pike_string *s;
   struct object *codec;
+  struct pike_frame *new_frame;
 
 #ifdef ENCODE_DEBUG
   int debug;
diff --git a/src/error.c b/src/error.c
index 7360d918fa..be439eba43 100644
--- a/src/error.c
+++ b/src/error.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: error.c,v 1.101 2003/01/09 15:21:26 grubba Exp $
+|| $Id: error.c,v 1.102 2003/03/14 15:50:44 grubba Exp $
 */
 
 #define NO_PIKE_SHORTHAND
@@ -23,7 +23,7 @@
 #include "threads.h"
 #include "gc.h"
 
-RCSID("$Id: error.c,v 1.101 2003/01/09 15:21:26 grubba Exp $");
+RCSID("$Id: error.c,v 1.102 2003/03/14 15:50:44 grubba Exp $");
 
 #undef ATTRIBUTE
 #define ATTRIBUTE(X)
@@ -181,6 +181,7 @@ PMOD_EXPORT DECLSPEC(noreturn) void low_error(const char *buf) ATTRIBUTE((noretu
 {
   push_error(buf);
   free_svalue(& throw_value);
+  dmalloc_touch_svalue(Pike_sp-1);
   throw_value = *--Pike_sp;
   throw_severity = THROW_ERROR;
   in_error=0;
@@ -284,6 +285,7 @@ PMOD_EXPORT DECLSPEC(noreturn) void new_error(const char *name, const char *text
   f_aggregate(2);
 
   free_svalue(& throw_value);
+  dmalloc_touch_svalue(Pike_sp-1);
   throw_value = *--Pike_sp;
   throw_severity=THROW_ERROR;
 
diff --git a/src/gc.c b/src/gc.c
index 13c0a9371f..63454a4dc1 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.208 2003/02/15 17:33:33 grubba Exp $
+|| $Id: gc.c,v 1.209 2003/03/14 15:50:44 grubba Exp $
 */
 
 #include "global.h"
@@ -33,7 +33,7 @@ struct callback *gc_evaluator_callback=0;
 
 #include "block_alloc.h"
 
-RCSID("$Id: gc.c,v 1.208 2003/02/15 17:33:33 grubba Exp $");
+RCSID("$Id: gc.c,v 1.209 2003/03/14 15:50:44 grubba Exp $");
 
 int gc_enabled = 1;
 
@@ -2440,6 +2440,7 @@ static void warn_bad_cycles()
     for (p = kill_list; p;) {
       if ((cycle = CYCLE(p))) {
 	push_object((struct object *) p->data);
+	dmalloc_touch_svalue(Pike_sp-1);
 	*obj_arr_ = append_array(*obj_arr_, --Pike_sp);
       }
       p = NEXT(p);
diff --git a/src/interpret.c b/src/interpret.c
index ca62f3486b..326f2c3939 100644
--- a/src/interpret.c
+++ b/src/interpret.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: interpret.c,v 1.294 2003/02/26 18:19:08 mast Exp $
+|| $Id: interpret.c,v 1.295 2003/03/14 15:50:44 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.294 2003/02/26 18:19:08 mast Exp $");
+RCSID("$Id: interpret.c,v 1.295 2003/03/14 15:50:44 grubba Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -316,6 +316,7 @@ void lvalue_to_svalue_no_free(struct svalue *to,struct svalue *lval)
     }
       
     case T_SVALUE_PTR:
+      dmalloc_touch_svalue(lval->u.lval);
       assign_svalue_no_free(to, lval->u.lval);
       break;
 
@@ -382,6 +383,8 @@ PMOD_EXPORT void assign_lvalue(struct svalue *lval,struct svalue *from)
     break;
 
   case T_SVALUE_PTR:
+    dmalloc_touch_svalue(from);
+    dmalloc_touch_svalue(lval->u.lval);
     assign_svalue(lval->u.lval,from);
     break;
 
@@ -429,6 +432,7 @@ union anything *get_pointer_if_this_type(struct svalue *lval, TYPE_T t)
       return 0;
       
     case T_SVALUE_PTR:
+      dmalloc_touch_svalue(lval->u.lval);
       if(lval->u.lval->type == t) return & ( lval->u.lval->u );
       return 0;
 
@@ -1115,7 +1119,8 @@ static void do_trace_call(INT32 args)
 
 #undef INIT_BLOCK
 #define INIT_BLOCK(X) do {			\
-  X->refs=1;					\
+  X->refs=0;					\
+  add_ref(X);	/* For DMALLOC... */		\
   X->flags=0; 					\
   X->scope=0;					\
   DO_IF_SECURITY( if(CURRENT_CREDS) {		\
@@ -1137,7 +1142,7 @@ static void do_trace_call(INT32 args)
   DO_IF_DEBUG(								\
   if(X->flags & PIKE_FRAME_MALLOCED_LOCALS)				\
   Pike_fatal("Pike frame is not supposed to have malloced locals here!\n"));	\
- 									\
+									\
   DO_IF_DMALLOC(							\
     X->context.prog=0;							\
     X->context.parent=0;						\
@@ -1555,6 +1560,7 @@ static int o_catch(PIKE_OPCODE_T *pc)
     *Pike_sp=throw_value;
     throw_value.type=T_INT;
     Pike_sp++;
+    dmalloc_touch_svalue(Pike_sp-1);
     UNSETJMP(tmp);
     Pike_fp->expendible=expendible;
     Pike_fp->flags=flags;
@@ -1618,6 +1624,7 @@ PMOD_EXPORT void call_handle_error(void)
     Pike_interpreter.c_stack_margin = 0;
     SET_ONERROR(tmp,exit_on_error,"Error in handle_error in master object!");
     *(Pike_sp++) = throw_value;
+    dmalloc_touch_svalue(Pike_sp-1);
     throw_value.type=T_INT;
     APPLY_MASTER("handle_error", 1);
     pop_stack();
diff --git a/src/interpret.h b/src/interpret.h
index 67be7feb9a..a325d320d5 100644
--- a/src/interpret.h
+++ b/src/interpret.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: interpret.h,v 1.130 2003/02/24 20:27:11 mast Exp $
+|| $Id: interpret.h,v 1.131 2003/03/14 15:50:44 grubba Exp $
 */
 
 #ifndef INTERPRET_H
@@ -215,14 +215,14 @@ PMOD_EXPORT extern const char msg_pop_neg[];
 #define push_constant_text(T) do{ Pike_sp->subtype=0; REF_MAKE_CONST_STRING(Pike_sp->u.string,T); Pike_sp++->type=PIKE_T_STRING; }while(0)
 #define push_function(OBJ, FUN) do {struct object *_=(OBJ); debug_malloc_touch(_); Pike_sp->u.object=_; Pike_sp->subtype=(FUN); Pike_sp++->type=PIKE_T_FUNCTION;} while (0)
 
-#define ref_push_program(P) do{ struct program *_=(P); debug_malloc_touch(_); _->refs++; Pike_sp->u.program=_; Pike_sp++->type=PIKE_T_PROGRAM; }while(0)
-#define ref_push_mapping(M) do{ struct mapping *_=(M); debug_malloc_touch(_); _->refs++; Pike_sp->u.mapping=_; Pike_sp++->type=PIKE_T_MAPPING; }while(0)
-#define ref_push_array(A) do{ struct array *_=(A); debug_malloc_touch(_); _->refs++; Pike_sp->u.array=_ ;Pike_sp++->type=PIKE_T_ARRAY; }while(0)
-#define ref_push_multiset(L) do{ struct multiset *_=(L); debug_malloc_touch(_); _->refs++; Pike_sp->u.multiset=_; Pike_sp++->type=PIKE_T_MULTISET; }while(0)
-#define ref_push_string(S) do{ struct pike_string *_=(S); debug_malloc_touch(_); _->refs++; Pike_sp->subtype=0; Pike_sp->u.string=_; Pike_sp++->type=PIKE_T_STRING; }while(0)
-#define ref_push_type_value(S) do{ struct pike_type *_=(S); debug_malloc_touch(_); _->refs++; Pike_sp->u.type=_; Pike_sp++->type=PIKE_T_TYPE; }while(0)
-#define ref_push_object(O) do{ struct object  *_=(O); debug_malloc_touch(_); _->refs++; Pike_sp->u.object=_; Pike_sp++->type=PIKE_T_OBJECT; }while(0)
-#define ref_push_function(OBJ, FUN) do {struct object *_=(OBJ); debug_malloc_touch(_); _->refs++; Pike_sp->u.object=_; Pike_sp->subtype=(FUN); Pike_sp++->type=PIKE_T_FUNCTION;} while (0)
+#define ref_push_program(P) do{ struct program *_=(P); add_ref(_); Pike_sp->u.program=_; Pike_sp++->type=PIKE_T_PROGRAM; }while(0)
+#define ref_push_mapping(M) do{ struct mapping *_=(M); add_ref(_); Pike_sp->u.mapping=_; Pike_sp++->type=PIKE_T_MAPPING; }while(0)
+#define ref_push_array(A) do{ struct array *_=(A); add_ref(_); Pike_sp->u.array=_ ;Pike_sp++->type=PIKE_T_ARRAY; }while(0)
+#define ref_push_multiset(L) do{ struct multiset *_=(L); add_ref(_); Pike_sp->u.multiset=_; Pike_sp++->type=PIKE_T_MULTISET; }while(0)
+#define ref_push_string(S) do{ struct pike_string *_=(S); add_ref(_); Pike_sp->subtype=0; Pike_sp->u.string=_; Pike_sp++->type=PIKE_T_STRING; }while(0)
+#define ref_push_type_value(S) do{ struct pike_type *_=(S); add_ref(_); Pike_sp->u.type=_; Pike_sp++->type=PIKE_T_TYPE; }while(0)
+#define ref_push_object(O) do{ struct object  *_=(O); add_ref(_); Pike_sp->u.object=_; Pike_sp++->type=PIKE_T_OBJECT; }while(0)
+#define ref_push_function(OBJ, FUN) do {struct object *_=(OBJ); add_ref(_); Pike_sp->u.object=_; Pike_sp->subtype=(FUN); Pike_sp++->type=PIKE_T_FUNCTION;} while (0)
 
 #define push_svalue(S) do { const struct svalue *_=(S); assign_svalue_no_free(Pike_sp,_); Pike_sp++; }while(0)
 
@@ -262,30 +262,37 @@ PMOD_EXPORT extern const char msg_pop_neg[];
  */
 #define stack_unlink(X) do { if(X) { free_svalue(Pike_sp-(X)-1); Pike_sp[-(X)-1]=Pike_sp[-1]; Pike_sp--; pop_n_elems(X-1); } }while(0)
 
-#define free_pike_frame(F) do{ struct pike_frame *f_=(F); debug_malloc_touch(f_); if(!--f_->refs) really_free_pike_frame(f_); }while(0)
+#define free_pike_frame(F) do{ struct pike_frame *f_=(F); if(!sub_ref(f_)) really_free_pike_frame(f_); }while(0)
 
 /* A scope is any frame which may have malloced locals */
-#define free_pike_scope(F) do{ struct pike_frame *f_=(F); debug_malloc_touch(f_); if(!--f_->refs) really_free_pike_scope(f_); }while(0)
+#define free_pike_scope(F) do{ struct pike_frame *f_=(F); if(!sub_ref(f_)) really_free_pike_scope(f_); }while(0)
 
 #define POP_PIKE_FRAME() do {						\
-  struct pike_frame *tmp_=Pike_fp->next;					\
+  struct pike_frame *tmp_=Pike_fp->next;				\
   if(!sub_ref(Pike_fp))							\
   {									\
-    really_free_pike_frame(Pike_fp);						\
+    really_free_pike_frame(Pike_fp);					\
   }else{								\
-    DO_IF_DEBUG(if( Pike_fp->locals + Pike_fp->num_locals > Pike_sp || Pike_sp < Pike_fp->expendible) Pike_fatal("Stack failure in POP_PIKE_FRAME %p+%d=%p %p %p!\n",Pike_fp->locals,Pike_fp->num_locals,Pike_fp->locals+Pike_fp->num_locals,Pike_sp,Pike_fp->expendible));                      \
-    debug_malloc_touch(Pike_fp); \
-    if(Pike_fp->num_locals)							\
+    DO_IF_DEBUG(							\
+      if( (Pike_fp->locals + Pike_fp->num_locals > Pike_sp) ||		\
+	  (Pike_sp < Pike_fp->expendible))				\
+	Pike_fatal("Stack failure in POP_PIKE_FRAME %p+%d=%p %p %p!\n",	\
+		   Pike_fp->locals, Pike_fp->num_locals,		\
+		   Pike_fp->locals+Pike_fp->num_locals,			\
+		   Pike_sp,Pike_fp->expendible));			\
+    debug_malloc_touch(Pike_fp);					\
+    if(Pike_fp->num_locals)						\
     {									\
       struct svalue *s=(struct svalue *)xalloc(sizeof(struct svalue)*	\
-					       Pike_fp->num_locals);		\
-      assign_svalues_no_free(s,Pike_fp->locals,Pike_fp->num_locals,BIT_MIXED);	\
-      Pike_fp->locals=s;							\
-      Pike_fp->flags|=PIKE_FRAME_MALLOCED_LOCALS;				\
+					       Pike_fp->num_locals);	\
+      assign_svalues_no_free(s, Pike_fp->locals, Pike_fp->num_locals,	\
+			     BIT_MIXED);				\
+      Pike_fp->locals=s;						\
+      Pike_fp->flags|=PIKE_FRAME_MALLOCED_LOCALS;			\
     }else{								\
-      Pike_fp->locals=0;							\
+      Pike_fp->locals=0;						\
     }									\
-    Pike_fp->next=0;								\
+    Pike_fp->next=0;							\
   }									\
   Pike_fp=tmp_;								\
  }while(0)
diff --git a/src/interpret_functions.h b/src/interpret_functions.h
index 2c08945f1d..c924b83b02 100644
--- a/src/interpret_functions.h
+++ b/src/interpret_functions.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: interpret_functions.h,v 1.140 2003/03/06 17:19:43 grubba Exp $
+|| $Id: interpret_functions.h,v 1.141 2003/03/14 15:50:44 grubba Exp $
 */
 
 /*
@@ -185,6 +185,7 @@
   pop_2_elems();				\
   *Pike_sp=s;					\
   Pike_sp++;					\
+  dmalloc_touch_svalue(Pike_sp-1);		\
   print_return_value();				\
 }while(0)
 
@@ -860,6 +861,8 @@ OPCODE0(F_ASSIGN, "assign", 0, {
   free_svalue(Pike_sp-3);
   free_svalue(Pike_sp-2);
   Pike_sp[-3]=Pike_sp[-1];
+  dmalloc_touch_svalue(Pike_sp-1);
+  dmalloc_touch_svalue(Pike_sp-2);
   Pike_sp-=2;
 });
 
@@ -868,6 +871,7 @@ OPCODE2(F_APPLY_ASSIGN_LOCAL_AND_POP, "apply, assign local and pop", 0, {
 	       DO_NOT_WARN((INT32)(Pike_sp - *--Pike_mark_sp)));
   free_svalue(Pike_fp->locals+arg2);
   Pike_fp->locals[arg2]=Pike_sp[-1];
+  dmalloc_touch_svalue(Pike_sp-1);
   Pike_sp--;
 });
 
@@ -885,6 +889,7 @@ OPCODE0(F_ASSIGN_AND_POP, "assign and pop", 0, {
 OPCODE1(F_ASSIGN_LOCAL_AND_POP, "assign local and pop", 0, {
   free_svalue(Pike_fp->locals + arg1);
   Pike_fp->locals[arg1] = Pike_sp[-1];
+  dmalloc_touch_svalue(Pike_sp-1);
   Pike_sp--;
 });
 
@@ -1425,6 +1430,7 @@ OPCODE0(F_ADD_INTS, "int+int", 0, {
     )
   {
     Pike_sp[-2].u.integer+=Pike_sp[-1].u.integer;
+    dmalloc_touch_svalue(Pike_sp-1);
     Pike_sp--;
   }else{
     f_add(2);
@@ -1435,6 +1441,7 @@ OPCODE0(F_ADD_FLOATS, "float+float", 0, {
   if(Pike_sp[-1].type == T_FLOAT && Pike_sp[-2].type == T_FLOAT)
   {
     Pike_sp[-2].u.float_number+=Pike_sp[-1].u.float_number;
+    dmalloc_touch_svalue(Pike_sp-1);
     Pike_sp--;
   }else{
     f_add(2);
@@ -1493,11 +1500,13 @@ OPCODE0(F_PUSH_ARRAY, "@", 0, {
       Pike_error("Bad return type from o->_values() in @\n");
     free_svalue(Pike_sp-2);
     Pike_sp[-2]=Pike_sp[-1];
+    dmalloc_touch_svalue(Pike_sp-1);
     Pike_sp--;
     break;
 
   case PIKE_T_ARRAY: break;
   }
+  dmalloc_touch_svalue(Pike_sp-1);
   Pike_sp--;
   push_array_items(Pike_sp->u.array);
 });
@@ -2052,7 +2061,7 @@ OPCODE1(F_CALL_BUILTIN1_AND_POP, "call builtin1 & pop", 0, {
 									   \
   new_frame=alloc_pike_frame();						   \
 									   \
-  new_frame->refs=1;							   \
+  new_frame->refs=1;	/* FIXME: Is this needed? */			   \
   new_frame->next=Pike_fp;						   \
 									   \
   Pike_fp->pc = (PIKE_OPCODE_T *)(((INT32 *)PROG_COUNTER) + 1);		   \
diff --git a/src/iterators.cmod b/src/iterators.cmod
index 193a39a2ca..4185d89766 100644
--- a/src/iterators.cmod
+++ b/src/iterators.cmod
@@ -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: iterators.cmod,v 1.34 2003/02/08 03:49:22 mast Exp $
+|| $Id: iterators.cmod,v 1.35 2003/03/14 15:53:09 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: iterators.cmod,v 1.34 2003/02/08 03:49:22 mast Exp $");
+RCSID("$Id: iterators.cmod,v 1.35 2003/03/14 15:53:09 grubba Exp $");
 #include "main.h"
 #include "object.h"
 #include "mapping.h"
@@ -690,6 +690,7 @@ PIKECLASS file_line_iterator
 	stack_swap();
 	f_add( 2 );
 	ssi->buffer = Pike_sp[-1].u.string;
+	dmalloc_touch_svalue(Pike_sp-1);
 	Pike_sp--;
 
 	if( !ssi->buffer->size_shift )
@@ -793,6 +794,7 @@ PIKECLASS file_line_iterator
       if( Pike_sp[-1].type != PIKE_T_STRING )
 	Pike_error("Feed function returned illegal value\n");
       THIS->buffer = Pike_sp[-1].u.string;
+      dmalloc_touch_svalue(Pike_sp-1);
       Pike_sp--;
       THIS->offset = 0;
       THIS->current = NULL;
@@ -990,6 +992,7 @@ PIKECLASS string_split_iterator
 	if ((Pike_sp[-1].type == T_STRING) &&			\
 	    (Pike_sp[-1].u.string->len)) {			\
 	  ssi->buffer = Pike_sp[-1].u.string;			\
+          dmalloc_touch_svalue(Pike_sp-1);			\
 	  Pike_sp--;						\
 	  goto reskip_empty;					\
 	}							\
@@ -1027,6 +1030,7 @@ PIKECLASS string_split_iterator
 	}							\
 	free_string(ssi->buffer);				\
 	ssi->buffer = Pike_sp[-1].u.string;			\
+        dmalloc_touch_svalue(Pike_sp-1);			\
 	Pike_sp--;						\
 	end -= offset;						\
 	offset = 0;						\
@@ -1041,6 +1045,7 @@ PIKECLASS string_split_iterator
     }								\
     ssi->offset = end+1;					\
     ssi->current = Pike_sp[-1].u.string;			\
+    dmalloc_touch_svalue(Pike_sp-1);				\
     Pike_sp--;							\
     if (ssi->offset > ssi->buffer->len) {			\
       free_string(ssi->buffer);					\
@@ -1173,6 +1178,7 @@ PIKECLASS string_split_iterator
       free_string(THIS->buffer);
       THIS->buffer = Pike_sp[-1].u.string;
       THIS->offset = 0;
+      dmalloc_touch_svalue(Pike_sp-1);
       Pike_sp--;
 
       /* Perform the scan. */
@@ -1567,6 +1573,7 @@ int foreach_iterate(struct object *o)
 	{
 	  /* Black Magic... */
 	  push_string(i->current);
+	  dmalloc_touch_svalue(Pike_sp-1);
 	  Pike_sp--;
 	  assign_lvalue(Pike_sp-2, Pike_sp);
 	}
@@ -1593,6 +1600,7 @@ int foreach_iterate(struct object *o)
 	{
 	  /* Black Magic... */
 	  push_string(i->current);
+	  dmalloc_touch_svalue(Pike_sp-1);
 	  Pike_sp--;
 	  assign_lvalue(Pike_sp-2, Pike_sp);
 	}
diff --git a/src/las.c b/src/las.c
index 4076182ab2..75b57134cf 100644
--- a/src/las.c
+++ b/src/las.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: las.c,v 1.329 2003/03/09 13:10:40 grubba Exp $
+|| $Id: las.c,v 1.330 2003/03/14 15:50:44 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: las.c,v 1.329 2003/03/09 13:10:40 grubba Exp $");
+RCSID("$Id: las.c,v 1.330 2003/03/14 15:50:44 grubba Exp $");
 
 #include "language.h"
 #include "interpret.h"
@@ -537,7 +537,7 @@ static node *freeze_node(node *orig)
 	orig->current_file = NULL;
       }
       free_node(dmalloc_touch(node *, orig));
-      n->refs++;
+      add_ref(n);
       return check_node_hash(dmalloc_touch(node *, n));
     }
     n = n->next;
@@ -661,7 +661,7 @@ void debug_free_node(node *n)
   if(!n) return;
 
 #ifdef SHARED_NODES
-  if (--n->refs) {
+  if (sub_ref(n)) {
 #ifdef PIKE_DEBUG
     if(l_flag>9)
       print_tree(n);
@@ -730,7 +730,7 @@ void debug_free_node(node *n)
       /* Free CAR */
 
 #ifdef SHARED_NODES
-      if (--_CAR(n)->refs) {
+      if (sub_ref(_CAR(n))) {
 	_CAR(n) = NULL;
       } else {
 #endif /* SHARED_NODES */
@@ -746,7 +746,7 @@ void debug_free_node(node *n)
       /* Free CDR */
 
 #ifdef SHARED_NODES
-      if (--_CDR(n)->refs) {
+      if (sub_ref(_CDR(n))) {
 	_CDR(n) = NULL;
       } else {
 #endif /* SHARED_NODES */
@@ -795,7 +795,7 @@ void debug_free_node(node *n)
       really_free_node_s(dead);
 
 #ifdef SHARED_NODES
-      if (--_CDR(n)->refs) {
+      if (sub_ref(_CDR(n))) {
 	_CDR(n) = NULL;
 	goto backtrack;
       } else {
@@ -852,7 +852,8 @@ static node *debug_mkemptynode(void)
   MEMSET(res, 0, sizeof(node));
 #ifdef SHARED_NODES
   res->hash = 0;  
-  res->refs = 1;
+  res->refs = 0;
+  add_ref(res);	/* For DMALLOC... */
 #endif /* SHARED_NODES */
 #endif /* SHARED_NODES || __CHECKER__ */
 
@@ -1211,7 +1212,8 @@ node *debug_mknewintnode(INT_TYPE nr)
   res->u.sval.u.integer = nr;
   res->type=get_type_of_svalue( & res->u.sval);
 #ifdef SHARED_NODES
-  res->refs = 1;
+  res->refs = 0;
+  add_ref(res);	/* For DMALLOC... */
   /* res->hash = hash_node(res); */
 #endif /* SHARED_NODES */
 
@@ -1933,6 +1935,7 @@ node *index_node(node *n, char *node_name, struct pike_string *id)
 	    
 	    if (thrown.type != PIKE_T_UNKNOWN) {
 	      *(Pike_sp++) = thrown;
+	      dmalloc_touch_svalue(Pike_sp-1);
 	      thrown.type = PIKE_T_INT;
 	      low_safe_apply_handler("compile_exception", error_handler, compat_handler, 1);
 	      if (SAFE_IS_ZERO(Pike_sp-1)) yy_describe_exception(&thrown);
@@ -2173,7 +2176,7 @@ node *copy_node(node *n)
 
   default:
 #ifdef SHARED_NODES
-    n->refs++;
+    add_ref(n);
     return n;
 #else /* !SHARED_NODES */
 
diff --git a/src/mapping.c b/src/mapping.c
index d700248126..331318cb18 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.162 2003/02/01 15:43:50 mast Exp $
+|| $Id: mapping.c,v 1.163 2003/03/14 15:50:44 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: mapping.c,v 1.162 2003/02/01 15:43:50 mast Exp $");
+RCSID("$Id: mapping.c,v 1.163 2003/03/14 15:50:44 grubba Exp $");
 #include "main.h"
 #include "object.h"
 #include "mapping.h"
@@ -228,7 +228,8 @@ PMOD_EXPORT struct mapping *debug_allocate_mapping(int size)
   INITIALIZE_PROT(m);
   init_mapping(m,size,0);
 
-  m->refs = 1;
+  m->refs = 0;
+  add_ref(m);	/* For DMALLOC... */
 
   DOUBLELINK(first_mapping, m);
 
@@ -445,7 +446,8 @@ struct mapping_data *copy_mapping_data(struct mapping_data *md)
   }
 #endif /* PIKE_MAPPING_KEYPAIR_LOOP */
 
-  nmd->refs=1;
+  nmd->refs=0;
+  add_ref(nmd);	/* For DMALLOC... */
   nmd->valrefs=0;
   nmd->hardlinks=0;
 
@@ -458,7 +460,7 @@ struct mapping_data *copy_mapping_data(struct mapping_data *md)
     md->hardlinks--;
     md->valrefs--;
   }
-  md->refs--;
+  sub_ref(md);
 
   return nmd;
 }
@@ -575,7 +577,7 @@ struct mapping_data *copy_mapping_data(struct mapping_data *md)
   LOW_RELOC(k);					\
   free_mapping_data(md);                        \
   md=m->data;                                   \
-  md->refs++;                                   \
+  add_ref(md);                                   \
 }while(0)
 
 #define PREPARE_FOR_DATA_CHANGE() \
@@ -1344,7 +1346,7 @@ PMOD_EXPORT struct mapping *copy_mapping(struct mapping *m)
 #ifdef MAPPING_SIZE_DEBUG
   n->debug_size=n->data->size;
 #endif
-  n->data->refs++;
+  add_ref(n->data);
   n->data->valrefs++;
   n->data->hardlinks++;
   debug_malloc_touch(n->data);
@@ -1871,8 +1873,10 @@ PMOD_EXPORT struct mapping *copy_mapping_recursively(struct mapping *m,
   {
     copy_svalues_recursively_no_free(Pike_sp,&k->ind, 1, &doing);
     Pike_sp++;
+    dmalloc_touch_svalue(Pike_sp-1);
     copy_svalues_recursively_no_free(Pike_sp,&k->val, 1, &doing);
     Pike_sp++;
+    dmalloc_touch_svalue(Pike_sp-1);
     
     mapping_insert(ret, Pike_sp-2, Pike_sp-1);
     pop_n_elems(2);
diff --git a/src/modules/Image/orient.c b/src/modules/Image/orient.c
index 226114c5ca..234017d4a2 100644
--- a/src/modules/Image/orient.c
+++ b/src/modules/Image/orient.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: orient.c,v 1.23 2002/10/21 17:06:14 marcus Exp $
+|| $Id: orient.c,v 1.24 2003/03/14 15:57:48 grubba Exp $
 */
 
 /*
@@ -272,7 +272,7 @@ THREADS_DISALLOW();
 
   if (!w)
   {
-    o[4]->refs++;
+    add_ref(o[4]);
     pop_n_elems(5);
     push_object(o[4]);
   }
diff --git a/src/modules/Image/phase.h b/src/modules/Image/phase.h
index 472f139e12..a7d07b8c91 100644
--- a/src/modules/Image/phase.h
+++ b/src/modules/Image/phase.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: phase.h,v 1.5 2002/10/11 01:39:43 nilsson Exp $
+|| $Id: phase.h,v 1.6 2003/03/14 15:57:48 grubba Exp $
 */
 
 /* This file is incuded in search.c with the following defines set:
@@ -91,6 +91,5 @@ THREADS_ALLOW();
 
 THREADS_DISALLOW();
 
-  o->refs++;
-  push_object(o);
+  ref_push_object(o);
 }
diff --git a/src/modules/Java/jvm.c b/src/modules/Java/jvm.c
index f29fe550ea..9191bf52f2 100644
--- a/src/modules/Java/jvm.c
+++ b/src/modules/Java/jvm.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: jvm.c,v 1.59 2003/03/13 22:06:01 marcus Exp $
+|| $Id: jvm.c,v 1.60 2003/03/14 15:57:48 grubba Exp $
 */
 
 /*
@@ -22,7 +22,7 @@
 #endif /* HAVE_CONFIG_H */
 
 #include "global.h"
-RCSID("$Id: jvm.c,v 1.59 2003/03/13 22:06:01 marcus Exp $");
+RCSID("$Id: jvm.c,v 1.60 2003/03/14 15:57:48 grubba Exp $");
 #include "program.h"
 #include "interpret.h"
 #include "stralloc.h"
@@ -225,7 +225,7 @@ static void push_java_class(jclass c, struct object *jvm, JNIEnv *env)
   jo = (struct jobj_storage *)(oo->storage);
   jo->jvm = jvm;
   jo->jobj = c2;
-  jvm->refs++;
+  add_ref(jvm);
 }
 
 static void push_java_throwable(jthrowable t, struct object *jvm, JNIEnv *env)
@@ -244,7 +244,7 @@ static void push_java_throwable(jthrowable t, struct object *jvm, JNIEnv *env)
   jo = (struct jobj_storage *)(oo->storage);
   jo->jvm = jvm;
   jo->jobj = t2;
-  jvm->refs++;
+  add_ref(jvm);
 }
 
 static void push_java_array(jarray t, struct object *jvm, JNIEnv *env, int ty)
@@ -266,7 +266,7 @@ static void push_java_array(jarray t, struct object *jvm, JNIEnv *env, int ty)
   jo->jobj = t2;
   a = (struct jarray_storage *)(oo->storage+jarray_stor_offs);
   a->ty = ty;
-  jvm->refs++;
+  add_ref(jvm);
 }
 
 static void push_java_anyobj(jobject o, struct object *jvm, JNIEnv *env)
@@ -303,7 +303,7 @@ static void push_java_anyobj(jobject o, struct object *jvm, JNIEnv *env)
   jo = (struct jobj_storage *)(oo->storage);
   jo->jvm = jvm;
   jo->jobj = o2;
-  jvm->refs++;
+  add_ref(jvm);
 }
 
 static void init_jobj_struct(struct object *o)
@@ -554,11 +554,9 @@ static void f_method_create(INT32 args)
   }
 
   m->class = class;
-  m->name = name;
-  m->sig = sig;
-  class->refs++;
-  name->refs++;
-  sig->refs++;
+  copy_shared_string(m->name, name);
+  copy_shared_string(m->sig, sig);
+  add_ref(class);
   pop_n_elems(args);
   push_int(0);
 
@@ -1167,7 +1165,7 @@ static void f_field_create(INT32 args)
 
   if(name == NULL || sig == NULL) {
     f->class = class;
-    class->refs++;
+    add_ref(class);
     pop_n_elems(args);
     f->type = 0;
     return;
@@ -1189,11 +1187,9 @@ static void f_field_create(INT32 args)
   }
 
   f->class = class;
-  f->name = name;
-  f->sig = sig;
-  class->refs++;
-  name->refs++;
-  sig->refs++;
+  copy_shared_string(f->name, name);
+  copy_shared_string(f->sig, sig);
+  add_ref(class);
   pop_n_elems(args);
   push_int(0);
 
@@ -2132,10 +2128,8 @@ static void build_native_entry(JNIEnv *env, jclass cls,
   int statc, args=0, wargs=0, flt_args=0, dbl_args=0;
   char *p = sig->str;
 
-  con->name = name;
-  con->sig = sig;
-  name->refs++;
-  sig->refs++;
+  copy_shared_string(con->name, name);
+  copy_shared_string(con->sig, sig);
 
   if((*env)->GetMethodID(env, cls, name->str, sig->str))
     statc = 0;
@@ -2296,8 +2290,8 @@ static void f_natives_create(INT32 args)
     
     n->jvm = c->jvm;
     n->cls = cls;
-    n->jvm->refs++;
-    n->cls->refs++;
+    add_ref(n->jvm);
+    add_ref(n->cls);
 
     rc = (*env)->RegisterNatives(env, c->jobj, n->jnms, n->num_methods);
     jvm_vacate_env(c->jvm, env);
@@ -2569,8 +2563,7 @@ static void javaarray_subarray(struct object *jvm, struct object *oo,
     if(e2==size) {
       /* Entire array selected */
       jvm_vacate_env(jvm, env);
-      oo->refs++;
-      push_object(oo);
+      ref_push_object(oo);
       return;
     }
 
@@ -3042,7 +3035,7 @@ static void f_monitor_create(INT32 args)
 #endif /* _REENTRANT */
 
   m->obj = obj;
-  obj->refs++;
+  add_ref(obj);
   pop_n_elems(args);
   return;
 }
@@ -3075,8 +3068,7 @@ static void f_create(INT32 args)
   /* Set classpath */
   if(args>0 && Pike_sp[-args].type == PIKE_T_STRING) {
     classpath = Pike_sp[-args].u.string->str;
-    Pike_sp[-args].u.string->refs++;
-    j->classpath_string = Pike_sp[-args].u.string;
+    copy_shared_string(j->classpath_string, Pike_sp[-args].u.string);
   } else {
     if(getenv("CLASSPATH"))
       classpath = getenv("CLASSPATH");
@@ -3098,8 +3090,7 @@ static void f_create(INT32 args)
     push_string(j->classpath_string);
     j->classpath_string = NULL;
     f_add(2);
-    Pike_sp[-1].u.string->refs++;
-    j->classpath_string = Pike_sp[-1].u.string;
+    copy_shared_string(j->classpath_string, Pike_sp[-1].u.string);
     pop_n_elems(1);
     j->vm_args.options[j->vm_args.nOptions].optionString =
       j->classpath_string->str;
@@ -3162,7 +3153,7 @@ static void f_create(INT32 args)
   f_thread_local(0);
   if(Pike_sp[-1].type == PIKE_T_OBJECT) {
     j->tl_env = Pike_sp[-1].u.object;
-    j->tl_env->refs ++;
+    add_ref(j->tl_env);
   }
   pop_n_elems(args+1);
 #else
diff --git a/src/modules/SANE/sane.c b/src/modules/SANE/sane.c
index 4084a9dffc..0a50ea3fa4 100644
--- a/src/modules/SANE/sane.c
+++ b/src/modules/SANE/sane.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: sane.c,v 1.16 2002/12/30 12:30:06 grubba Exp $
+|| $Id: sane.c,v 1.17 2003/03/14 15:57:49 grubba Exp $
 */
 
 #include "config.h"
@@ -39,7 +39,7 @@
 
 #define sp Pike_sp
 
-RCSID("$Id: sane.c,v 1.16 2002/12/30 12:30:06 grubba Exp $");
+RCSID("$Id: sane.c,v 1.17 2003/03/14 15:57:49 grubba Exp $");
 
 /*! @module SANE
  *!
@@ -722,7 +722,7 @@ static void f_scanner_nonblocking_row_scan( INT32 args )
   push_int( 1 );
   rsp->o = clone_object( image_program, 2 );
   rsp->t = Pike_fp->current_object;
-  Pike_fp->current_object->refs++;
+  add_ref(Pike_fp->current_object);
   rsp->r = ((struct image *)rsp->o->storage)->img;
   rsp->h = THIS->h;
   rsp->p = p;
diff --git a/src/modules/_Roxen/roxen.c b/src/modules/_Roxen/roxen.c
index 30d5a8ab0e..8df18ae403 100644
--- a/src/modules/_Roxen/roxen.c
+++ b/src/modules/_Roxen/roxen.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: roxen.c,v 1.32 2002/10/21 17:06:25 marcus Exp $
+|| $Id: roxen.c,v 1.33 2003/03/14 15:57:49 grubba Exp $
 */
 
 #define NO_PIKE_SHORTHAND
@@ -200,13 +200,11 @@ static void f_hp_feed( INT32 args )
 	f_aggregate( 1 );
 	if( tmp->type == PIKE_T_ARRAY )
 	{
-	  tmp->u.array->refs++;
-	  push_array(tmp->u.array);
+	  ref_push_array(tmp->u.array);
 	  map_delete(headers, Pike_sp-3);
 	  f_add(2);
 	} else {
-	  tmp->u.string->refs++;
-	  push_string(tmp->u.string);
+	  ref_push_string(tmp->u.string);
 	  f_aggregate(1);
 	  map_delete(headers, Pike_sp-3);
 	  f_add(2);
diff --git a/src/multiset.c b/src/multiset.c
index bf86e090d6..bbf65e128f 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.68 2003/02/01 15:43:51 mast Exp $
+|| $Id: multiset.c,v 1.69 2003/03/14 15:50:45 grubba Exp $
 */
 
 #include "global.h"
@@ -14,7 +14,7 @@
  * Created by Martin Stjernholm 2001-05-07
  */
 
-RCSID("$Id: multiset.c,v 1.68 2003/02/01 15:43:51 mast Exp $");
+RCSID("$Id: multiset.c,v 1.69 2003/03/14 15:50:45 grubba Exp $");
 
 #include "builtin_functions.h"
 #include "gc.h"
@@ -238,7 +238,8 @@ void free_multiset_data (struct multiset_data *msd);
 #define INIT_MULTISET(L) do {						\
     GC_ALLOC (L);							\
     INITIALIZE_PROT (L);						\
-    L->refs = 1;							\
+    L->refs = 0;							\
+    add_ref(L);	/* For DMALLOC... */					\
     L->node_refs = 0;							\
     DOUBLELINK (first_multiset, L);					\
   } while (0)
@@ -3603,6 +3604,7 @@ PMOD_EXPORT void f_aggregate_multiset (INT32 args)
   push_multiset (mkmultiset_2 (sp[-1].u.array, NULL, NULL));
   free_array (sp[-2].u.array);
   sp[-2] = sp[-1];
+  dmalloc_touch_svalue(Pike_sp-1);
   sp--;
 }
 
@@ -5279,7 +5281,7 @@ void test_multiset (void)
 #include "gc.h"
 #include "security.h"
 
-RCSID("$Id: multiset.c,v 1.68 2003/02/01 15:43:51 mast Exp $");
+RCSID("$Id: multiset.c,v 1.69 2003/03/14 15:50:45 grubba Exp $");
 
 struct multiset *first_multiset;
 
diff --git a/src/object.c b/src/object.c
index f79ecbea52..1240bffbb1 100644
--- a/src/object.c
+++ b/src/object.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: object.c,v 1.227 2003/03/09 13:10:40 grubba Exp $
+|| $Id: object.c,v 1.228 2003/03/14 15:50:45 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: object.c,v 1.227 2003/03/09 13:10:40 grubba Exp $");
+RCSID("$Id: object.c,v 1.228 2003/03/14 15:50:45 grubba Exp $");
 #include "object.h"
 #include "dynamic_buffer.h"
 #include "interpret.h"
@@ -242,6 +242,10 @@ PMOD_EXPORT void call_c_initializers(struct object *o)
       for(q=0;q<n;q++)
       {
 	int d=prog->variable_index[q];
+
+	if (IDENTIFIER_IS_ALIAS(prog->identifiers[d].identifier_flags))
+	  continue;
+
 	if(prog->identifiers[d].run_time_type == T_MIXED)
 	{
 	  struct svalue *s;
@@ -259,6 +263,7 @@ PMOD_EXPORT void call_c_initializers(struct object *o)
 	    default: u->refs=0; break;
 	  }
 	}
+	debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" clear_global"));
       }
     }
     if(prog->event_handler)
@@ -761,20 +766,28 @@ void destruct(struct object *o)
     {
       int d=prog->variable_index[q];
       struct identifier *id = prog->identifiers + d;
-      int id_flags = id->identifier_flags;
+      int identifier_flags = id->identifier_flags;
       int rtt = id->run_time_type;
 
-      if (IDENTIFIER_IS_ALIAS(id_flags))
+      if (IDENTIFIER_IS_ALIAS(identifier_flags))
 	continue;
-      
+
       if(rtt == T_MIXED)
       {
 	struct svalue *s;
 	s=(struct svalue *)(storage + id->func.offset);
 	dmalloc_touch_svalue(s);
-	if ((s->type != T_OBJECT && s->type != T_FUNCTION) || s->u.object != o ||
-	    !(id_flags & IDENTIFIER_NO_THIS_REF))
+	if ((s->type != T_OBJECT && s->type != T_FUNCTION) ||
+	    s->u.object != o ||
+	    !(identifier_flags & IDENTIFIER_NO_THIS_REF)) {
+	  debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" free_global"));
 	  free_svalue(s);
+#ifdef DEBUG_MALLOC
+	} else {
+	  debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" skip_global"));
+	  dmalloc_touch_svalue(s);
+#endif /* DEBUG_MALLOC */
+	}
       }else{
 	union anything *u;
 	u=(union anything *)(storage + id->func.offset);
@@ -782,8 +795,14 @@ void destruct(struct object *o)
 	if (rtt <= MAX_REF_TYPE) {debug_malloc_touch(u->refs);}
 #endif
 	if (rtt != T_OBJECT || u->object != o ||
-	    !(id_flags & IDENTIFIER_NO_THIS_REF))
+	    !(identifier_flags & IDENTIFIER_NO_THIS_REF)) {
+	  debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" free_global"));
 	  free_short_svalue(u, rtt);
+#ifdef DEBUG_MALLOC
+	} else {
+	  debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" skip_global"));
+#endif /* DEBUG_MALLOC */
+	}
 	DO_IF_DMALLOC(u->refs=(void *)-1);
       }
     }
@@ -898,7 +917,7 @@ PMOD_EXPORT void schedule_really_free_object(struct object *o)
   {
     add_ref(o);
     destruct(o);
-    if(--o->refs > 0) return;
+    if(sub_ref(o)) return;
   }
 
   debug_malloc_touch(o);
@@ -1199,14 +1218,37 @@ PMOD_EXPORT void object_low_set_index(struct object *o,
   {
     /* Don't count references to ourselves to help the gc. DDTAH. */
     struct svalue *to = (struct svalue *) LOW_GET_GLOBAL(o,f,i);
-    if ((to->type != T_OBJECT && to->type != T_FUNCTION) || to->u.object != o ||
-	!(id_flags & IDENTIFIER_NO_THIS_REF))
+    dmalloc_touch_svalue(to);
+    if ((to->type != T_OBJECT && to->type != T_FUNCTION) ||
+	to->u.object != o ||
+	!(id_flags & IDENTIFIER_NO_THIS_REF)) {
+      debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" free_global"));
       free_svalue(to);
+#ifdef DEBUG_MALLOC
+    } else {
+      debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" skip_global"));
+      dmalloc_touch_svalue (to);
+#endif /* DEBUG_MALLOC */
+    }
     *to = *from;
     dmalloc_touch_svalue (to);
-    if ((to->type != T_OBJECT && to->type != T_FUNCTION) || to->u.object != o ||
-	!(id_flags & IDENTIFIER_NO_THIS_REF))
-      if(to->type <= MAX_REF_TYPE) add_ref(to->u.dummy);
+    if ((to->type != T_OBJECT && to->type != T_FUNCTION) ||
+	(to->u.object != o) ||
+	!(id_flags & IDENTIFIER_NO_THIS_REF)) {
+      if(to->type <= MAX_REF_TYPE) {
+	debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" store_global"));
+	add_ref(to->u.dummy);
+#ifdef DEBUG_MALLOC
+      } else {
+	debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" store_global"));
+#endif /* DEBUG_MALLOC */
+      }
+#ifdef DEBUG_MALLOC
+    } else {
+      debug_malloc_update_location(o, DMALLOC_NAMED_LOCATION(" self_global"));
+      dmalloc_touch_svalue (to);
+#endif /* DEBUG_MALLOC */
+    }
   }
   else
   {
@@ -1222,24 +1264,40 @@ PMOD_EXPORT void object_low_set_index(struct object *o,
 	  if (id_flags & IDENTIFIER_NO_THIS_REF) {
 	    /* Don't count references to ourselves to help the gc. */
 	    debug_malloc_touch(u->object);
-	    if ((u->object != o) && u->refs && --*(u->refs) <= 0)
+	    if ((u->object != o) && u->refs && !sub_ref(u->dummy)) {
+	      debug_malloc_touch(o);
 	      really_free_short_svalue(u,rtt);
+#ifdef DEBUG_MALLOC
+	    } else {
+	      debug_malloc_touch(o);
+#endif /* DEBUG_MALLOC */
+	    }
 	    u->refs = from->u.refs;
-	    if (u->object != o) add_ref(u->dummy);
+	    debug_malloc_touch(u->refs);
+	    if (u->object != o) {
+	      debug_malloc_touch(o);
+	      add_ref(u->dummy);
+#ifdef DEBUG_MALLOC
+	    } else {
+	      debug_malloc_touch(o);
+#endif /* DEBUG_MALLOC */
+	    }
 	    break;
 	  }
 	  /* FALL THROUGH */
 	default:
 	  debug_malloc_touch(u->refs);
-	  if(u->refs && --*(u->refs) <= 0)
+	  if(u->refs && !sub_ref(u->dummy))
 	    really_free_short_svalue(u,rtt);
 	  u->refs = from->u.refs;
 	  add_ref(u->dummy);
       }
     }else if(rtt<=MAX_REF_TYPE && UNSAFE_IS_ZERO(from)){
       if((rtt != T_OBJECT || u->object != o || !(id_flags & IDENTIFIER_NO_THIS_REF)) &&
-	 u->refs && --*(u->refs) <= 0)
+	 u->refs && !sub_ref(u->dummy)) {
+	debug_malloc_touch(u->ptr);
 	really_free_short_svalue(u,rtt);
+      }
       debug_malloc_touch(u->ptr);
       u->refs=0;
     }else{
@@ -1337,12 +1395,16 @@ static union anything *object_low_get_item_ptr(struct object *o,
   struct identifier *i;
   struct program *p;
 
+  debug_malloc_touch(o);
+
   if(!o || !(p=o->prog))
   {
     Pike_error("Lookup in destructed object.\n");
     return 0; /* make gcc happy */
   }
 
+  debug_malloc_touch(p);
+
   i=ID_FROM_INT(p, f);
 
 #ifdef PIKE_DEBUG
@@ -1378,6 +1440,9 @@ union anything *object_get_item_ptr(struct object *o,
   struct program *p;
   int f;
 
+  debug_malloc_touch(o);
+  dmalloc_touch_svalue(index);
+
   if(!o || !(p=o->prog))
   {
     Pike_error("Lookup in destructed object.\n");
@@ -1991,6 +2056,7 @@ static void f_magic_index(INT32 args)
 			     inherit->identifier_level);
     *sp=sval;
     sp++;
+    dmalloc_touch_svalue(Pike_sp-1);
   }
 }
 
diff --git a/src/opcodes.c b/src/opcodes.c
index 90c9898049..133c6f34ff 100644
--- a/src/opcodes.c
+++ b/src/opcodes.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: opcodes.c,v 1.142 2003/03/06 15:29:56 grubba Exp $
+|| $Id: opcodes.c,v 1.143 2003/03/14 15:50:45 grubba Exp $
 */
 
 #include "global.h"
@@ -30,7 +30,7 @@
 
 #define sp Pike_sp
 
-RCSID("$Id: opcodes.c,v 1.142 2003/03/06 15:29:56 grubba Exp $");
+RCSID("$Id: opcodes.c,v 1.143 2003/03/14 15:50:45 grubba Exp $");
 
 void index_no_free(struct svalue *to,struct svalue *what,struct svalue *ind)
 {
@@ -139,6 +139,7 @@ void o_index(void)
   *sp=s;
   dmalloc_touch_svalue(sp);
   sp++;
+  dmalloc_touch_svalue(Pike_sp-1);
 }
 
 /*! @class MasterObject
@@ -1647,6 +1648,7 @@ CHAROPT2(								 \
 		   pos+=8;						 \
 		   eye++;						 \
 		 }							 \
+                 dmalloc_touch_svalue(Pike_sp-1);			 \
 		 sval=*--sp;						 \
 		 break;							 \
 	       }							 \
@@ -1674,6 +1676,7 @@ CHAROPT2(								 \
 		   o_or();						 \
 		   eye++;						 \
 		 }							 \
+                 dmalloc_touch_svalue(Pike_sp-1);			 \
 		 sval=*--sp;						 \
 		 break;							 \
 	       }							 \
@@ -2048,6 +2051,7 @@ CHAROPT2(								 \
     }else{								 \
       check_stack(1);							 \
       *sp++=sval;							 \
+      dmalloc_touch_svalue(Pike_sp-1);					 \
       DO_IF_DEBUG(sval.type=99);					 \
     }									 \
   }									 \
diff --git a/src/operators.c b/src/operators.c
index f77084a748..969a6db425 100644
--- a/src/operators.c
+++ b/src/operators.c
@@ -2,12 +2,12 @@
 || 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: operators.c,v 1.171 2003/01/26 17:04:03 nilsson Exp $
+|| $Id: operators.c,v 1.172 2003/03/14 15:50:46 grubba Exp $
 */
 
 #include "global.h"
 #include <math.h>
-RCSID("$Id: operators.c,v 1.171 2003/01/26 17:04:03 nilsson Exp $");
+RCSID("$Id: operators.c,v 1.172 2003/03/14 15:50:46 grubba Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "multiset.h"
@@ -357,9 +357,11 @@ PMOD_EXPORT void f_add(INT32 args)
 	if (save_sp[e].type == T_STRING)
 	  break;
 	*(sp++) = save_sp[e];
+	dmalloc_touch_svalue(Pike_sp-1);
       }
       /* Perform the addition. */
       f_add(args+e);
+      dmalloc_touch_svalue(Pike_sp-1);
       save_sp[--e] = *(--sp);
 #ifdef PIKE_DEBUG
       if (sp != save_sp) {
@@ -1379,6 +1381,7 @@ static void r_speedup(INT32 args, void (*func)(void))
 
     default:
       r_speedup((args+1)>>1,func);
+      dmalloc_touch_svalue(Pike_sp-1);
       tmp=*--sp;
       SET_ONERROR(err,do_free_svalue,&tmp);
       r_speedup(args>>1,func);
@@ -3114,6 +3117,8 @@ PMOD_EXPORT void o_range(void)
   if(from<0) from = 0;
   to = sp[-1].u.integer;
   if(to<from-1) to = from-1;
+  dmalloc_touch_svalue(Pike_sp-1);
+  dmalloc_touch_svalue(Pike_sp-2);
   sp-=2;
 
   switch(sp[-1].type)
@@ -3558,6 +3563,7 @@ static void f_string_assignment_assign_index(INT32 args)
   }else{
     lvalue_to_svalue_no_free(sp,THIS->lval);
     sp++;
+    dmalloc_touch_svalue(Pike_sp-1);
     if(sp[-1].type != T_STRING) Pike_error("string[]= failed.\n");
     if(i<0) i+=sp[-1].u.string->len;
     if(i<0 || i>=sp[-1].u.string->len)
diff --git a/src/pike_types.c b/src/pike_types.c
index 36f78c2f50..8c2f7394a8 100644
--- a/src/pike_types.c
+++ b/src/pike_types.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: pike_types.c,v 1.210 2003/03/08 20:38:02 grubba Exp $
+|| $Id: pike_types.c,v 1.211 2003/03/14 15:50:46 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: pike_types.c,v 1.210 2003/03/08 20:38:02 grubba Exp $");
+RCSID("$Id: pike_types.c,v 1.211 2003/03/14 15:50:46 grubba Exp $");
 #include <ctype.h>
 #include "svalue.h"
 #include "pike_types.h"
@@ -220,7 +220,7 @@ static size_t pike_type_hash_size = 0;
 void debug_free_type(struct pike_type *t)
 {
  loop:
-  if (!(--(((struct pike_type *)debug_malloc_pass(t))->refs))) {
+  if (!sub_ref(t)) {
     unsigned INT32 hash = t->hash % pike_type_hash_size;
     struct pike_type **t2 = pike_type_hash + hash;
     struct pike_type *car, *cdr;
@@ -391,7 +391,8 @@ static inline struct pike_type *debug_mk_type(unsigned INT32 type,
       
   debug_malloc_pass(t = alloc_pike_type());
 
-  t->refs = 1;
+  t->refs = 0;
+  add_ref(t);	/* For DMALLOC... */
   t->type = type;
   t->flags = 0;
   t->car = car;
diff --git a/src/post_modules/Shuffler/Shuffler.cmod b/src/post_modules/Shuffler/Shuffler.cmod
index 80ceb8a660..8c22981010 100644
--- a/src/post_modules/Shuffler/Shuffler.cmod
+++ b/src/post_modules/Shuffler/Shuffler.cmod
@@ -2,12 +2,12 @@
 || 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: Shuffler.cmod,v 1.22 2002/11/26 21:15:21 grubba Exp $
+|| $Id: Shuffler.cmod,v 1.23 2003/03/14 15:57:49 grubba Exp $
 */
 
 #include "global.h"
 #include "stralloc.h"
-RCSID("$Id: Shuffler.cmod,v 1.22 2002/11/26 21:15:21 grubba Exp $");
+RCSID("$Id: Shuffler.cmod,v 1.23 2003/03/14 15:57:49 grubba Exp $");
 #include "pike_macros.h"
 #include "interpret.h"
 #include "threads.h"
@@ -526,18 +526,15 @@ PIKECLASS Shuffle
       Pike_error("This class cannot be instantiated directly\n");
 
     THIS->file_obj = fd;
-    THIS->file_obj->refs++;
-    debug_malloc_touch( THIS->file_obj );
+    add_ref(THIS->file_obj);
 
     THIS->shuffler = shuffler;
-    THIS->shuffler->refs++;
-    debug_malloc_touch( THIS->shuffler );
+    add_ref(THIS->shuffler);
 
     if( throttler->type == PIKE_T_OBJECT )
     {
       THIS->throttler = throttler->u.object;
-      THIS->throttler->refs++;
-      debug_malloc_touch( THIS->throttler );
+      add_ref(THIS->throttler);
     }
 
     safe_apply( fd, "query_fd", 0 );
diff --git a/src/post_modules/Shuffler/a_source_pikestring.c b/src/post_modules/Shuffler/a_source_pikestring.c
index 90566f18f4..0f85f6e114 100644
--- a/src/post_modules/Shuffler/a_source_pikestring.c
+++ b/src/post_modules/Shuffler/a_source_pikestring.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: a_source_pikestring.c,v 1.7 2002/10/11 01:39:59 nilsson Exp $
+|| $Id: a_source_pikestring.c,v 1.8 2003/03/14 15:57:49 grubba Exp $
 */
 
 #include "global.h"
@@ -69,15 +69,14 @@ struct source *source_pikestring_make( struct svalue *s,
   res->s.free_source = free_source;
   res->s.get_data = get_data;
 
-  res->str = s->u.string;
-  res->str->refs++;
+  copy_shared_string(res->str, s->u.string);
   res->offset = start;
 
   if( len != -1 )
   {
     if( len > res->str->len-start )
     {
-      res->str->refs--;
+      sub_ref(res->str);
       free(res);
       return 0;
     }
@@ -89,7 +88,7 @@ struct source *source_pikestring_make( struct svalue *s,
 
   if( res->len <= 0 )
   {
-    res->str->refs--;
+    sub_ref(res->str);
     free(res);
   }
   return (struct source *)res;
diff --git a/src/post_modules/Shuffler/a_source_system_memory.c b/src/post_modules/Shuffler/a_source_system_memory.c
index 077573b1a8..537074d160 100644
--- a/src/post_modules/Shuffler/a_source_system_memory.c
+++ b/src/post_modules/Shuffler/a_source_system_memory.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: a_source_system_memory.c,v 1.8 2002/10/17 16:59:21 manual Exp $
+|| $Id: a_source_system_memory.c,v 1.9 2003/03/14 15:57:49 grubba Exp $
 */
 
 #include "global.h"
@@ -98,13 +98,13 @@ struct source *source_system_memory_make( struct svalue *s,
   res->s.free_source = free_source;
   res->s.get_data = get_data;
   res->obj = s->u.object;
-  res->obj->refs++;
+  add_ref(res->obj);
   res->offset = start;
 
   if( len != -1 )
     if( len > res->mem->len-start )
     {
-      res->obj->refs--;
+      sub_ref(res->obj);
       free(res);
       return 0;
     }
@@ -115,7 +115,7 @@ struct source *source_system_memory_make( struct svalue *s,
 
   if( res->len <= 0 )
   {
-    res->obj->refs--;
+    sub_ref(res->obj);
     free(res);
     return 0;
   }
diff --git a/src/post_modules/Shuffler/b_source_normal_file.c b/src/post_modules/Shuffler/b_source_normal_file.c
index 6efb950d9b..6bc66de364 100644
--- a/src/post_modules/Shuffler/b_source_normal_file.c
+++ b/src/post_modules/Shuffler/b_source_normal_file.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: b_source_normal_file.c,v 1.7 2002/10/11 01:39:59 nilsson Exp $
+|| $Id: b_source_normal_file.c,v 1.8 2003/03/14 15:57:49 grubba Exp $
 */
 
 #include "global.h"
@@ -113,7 +113,7 @@ struct source *source_normal_file_make( struct svalue *s,
   res->s.get_data = get_data;
   res->s.free_source = free_source;
   res->obj = s->u.object;
-  res->obj->refs++;
+  add_ref(res->obj);
 
   if( fd_fstat( res->fd, &st ) < 0 )
   {
diff --git a/src/post_modules/Shuffler/c_source_stream.c b/src/post_modules/Shuffler/c_source_stream.c
index 66b740240f..ec2d5124e4 100644
--- a/src/post_modules/Shuffler/c_source_stream.c
+++ b/src/post_modules/Shuffler/c_source_stream.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: c_source_stream.c,v 1.6 2002/10/11 01:39:59 nilsson Exp $
+|| $Id: c_source_stream.c,v 1.7 2003/03/14 15:57:49 grubba Exp $
 */
 
 #include "global.h"
@@ -181,7 +181,7 @@ struct source *source_stream_make( struct svalue *s,
   res->s.setup_callbacks = setup_callbacks;
   res->s.remove_callbacks = remove_callbacks;
   res->obj = s->u.object;
-  res->obj->refs++;
+  add_ref(res->obj);
   return (struct source *)res;
 }
 
diff --git a/src/post_modules/Shuffler/d_source_pikestream.c b/src/post_modules/Shuffler/d_source_pikestream.c
index 206f3a5f0c..60fc960c79 100644
--- a/src/post_modules/Shuffler/d_source_pikestream.c
+++ b/src/post_modules/Shuffler/d_source_pikestream.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: d_source_pikestream.c,v 1.5 2002/11/06 23:08:19 nilsson Exp $
+|| $Id: d_source_pikestream.c,v 1.6 2003/03/14 15:57:49 grubba Exp $
 */
 
 #include "global.h"
@@ -187,7 +187,7 @@ struct source *source_pikestream_make( struct svalue *s,
   res->s.setup_callbacks = setup_callbacks;
   res->s.remove_callbacks = remove_callbacks;
   res->obj = s->u.object;
-  res->obj->refs++;
+  add_ref(res->obj);
 
   res->cb_obj = clone_object( callback_program, 0 );
   ((struct callback_prog *)res->cb_obj->storage)->s = res;
diff --git a/src/post_modules/Shuffler/e_source_block_pikestream.c b/src/post_modules/Shuffler/e_source_block_pikestream.c
index 0d71031e58..7f3716de6e 100644
--- a/src/post_modules/Shuffler/e_source_block_pikestream.c
+++ b/src/post_modules/Shuffler/e_source_block_pikestream.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: e_source_block_pikestream.c,v 1.1 2003/01/14 22:40:25 per Exp $
+|| $Id: e_source_block_pikestream.c,v 1.2 2003/03/14 15:57:49 grubba Exp $
 */
 
 #include "global.h"
@@ -119,7 +119,7 @@ struct source *source_block_pikestream_make( struct svalue *s,
   res->s.get_data = get_data;
   res->s.free_source = free_source;
   res->obj = s->u.object;
-  res->obj->refs++;
+  add_ref(res->obj);
   return (struct source *)res;
 }
 
diff --git a/src/preprocessor.h b/src/preprocessor.h
index 7ca49783f7..86a7848f84 100644
--- a/src/preprocessor.h
+++ b/src/preprocessor.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: preprocessor.h,v 1.57 2002/12/08 15:26:01 grubba Exp $
+|| $Id: preprocessor.h,v 1.58 2003/03/14 15:50:46 grubba Exp $
 */
 
 /*
@@ -1440,6 +1440,7 @@ static ptrdiff_t lower_cpp(struct cpp *this,
 	    /* Why not just use ref_push_string(new_file)? */
 	    assign_svalue_no_free(Pike_sp,Pike_sp-1);
 	    Pike_sp++;
+	    dmalloc_touch_svalue(Pike_sp-1);
 	    
 	    /* FIXME: Ought to use safe_apply_handler()... */
 	    if(this->compat_handler)
diff --git a/src/program.c b/src/program.c
index b2d82cf672..e9ce814612 100644
--- a/src/program.c
+++ b/src/program.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: program.c,v 1.485 2003/03/09 13:10:40 grubba Exp $
+|| $Id: program.c,v 1.486 2003/03/14 15:50:46 grubba Exp $
 */
 
 #include "global.h"
-RCSID("$Id: program.c,v 1.485 2003/03/09 13:10:40 grubba Exp $");
+RCSID("$Id: program.c,v 1.486 2003/03/14 15:50:46 grubba Exp $");
 #include "program.h"
 #include "object.h"
 #include "dynamic_buffer.h"
@@ -1840,7 +1840,8 @@ void low_start_new_program(struct program *p,
 
   Pike_compiler->fake_object->next=Pike_compiler->fake_object;
   Pike_compiler->fake_object->prev=Pike_compiler->fake_object;
-  Pike_compiler->fake_object->refs=1;
+  Pike_compiler->fake_object->refs=0;
+  add_ref(Pike_compiler->fake_object);	/* For DMALLOC... */
   Pike_compiler->fake_object->prog=p;
   add_ref(p);
 
@@ -6051,6 +6052,7 @@ struct program *compile(struct pike_string *aprog,
   }
   free_svalue(& c->default_module);
   c->default_module=Pike_sp[-1];
+  dmalloc_touch_svalue(Pike_sp-1);
   Pike_sp--;
 
 #ifdef PIKE_DEBUG
@@ -7266,6 +7268,7 @@ PMOD_EXPORT void change_compiler_compatibility(int major, int minor)
   if((Pike_sp[-1].type == T_OBJECT) && (Pike_sp[-1].u.object->prog))
   {
     compat_handler = dmalloc_touch(struct object *, Pike_sp[-1].u.object);
+    dmalloc_touch_svalue(Pike_sp-1);
     Pike_sp--;
   } else {
     pop_stack();
diff --git a/src/signal_handler.c b/src/signal_handler.c
index 1b4145c8cb..5838b307b0 100644
--- a/src/signal_handler.c
+++ b/src/signal_handler.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: signal_handler.c,v 1.248 2003/03/13 22:12:59 nilsson Exp $
+|| $Id: signal_handler.c,v 1.249 2003/03/14 15:50:47 grubba Exp $
 */
 
 #include "global.h"
@@ -26,7 +26,7 @@
 #include "main.h"
 #include <signal.h>
 
-RCSID("$Id: signal_handler.c,v 1.248 2003/03/13 22:12:59 nilsson Exp $");
+RCSID("$Id: signal_handler.c,v 1.249 2003/03/14 15:50:47 grubba Exp $");
 
 #ifdef HAVE_PASSWD_H
 # include <passwd.h>
@@ -336,11 +336,6 @@ RCSID("$Id: signal_handler.c,v 1.248 2003/03/13 22:12:59 nilsson Exp $");
 #define SAFE_FIFO_DEBUG_END()  }while(0)
 #endif
 
-/* Added so we are able to patch older versions of Pike. */
-#ifndef add_ref
-#define add_ref(X)	((X)->refs++)
-#endif /* add_ref */
-
 extern int fd_from_object(struct object *o);
 static int set_priority( int pid, char *to );
 
diff --git a/src/stralloc.c b/src/stralloc.c
index d2a9acfb0f..56c1819563 100644
--- a/src/stralloc.c
+++ b/src/stralloc.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: stralloc.c,v 1.152 2003/02/26 22:42:29 mast Exp $
+|| $Id: stralloc.c,v 1.153 2003/03/14 15:50:47 grubba Exp $
 */
 
 #include "global.h"
@@ -24,7 +24,7 @@
 #include <ctype.h>
 #include <math.h>
 
-RCSID("$Id: stralloc.c,v 1.152 2003/02/26 22:42:29 mast Exp $");
+RCSID("$Id: stralloc.c,v 1.153 2003/03/14 15:50:47 grubba Exp $");
 
 /* #define STRALLOC_USE_PRIMES */
 
@@ -956,7 +956,7 @@ PMOD_EXPORT void really_free_string(struct pike_string *s)
 
 PMOD_EXPORT void debug_free_string(struct pike_string *s)
 {
-  if(--s->refs<=0)
+  if(!sub_ref(s))
     really_free_string(s);
 }
 
diff --git a/src/stralloc.h b/src/stralloc.h
index ed9ba68f7f..ec370f17ab 100644
--- a/src/stralloc.h
+++ b/src/stralloc.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: stralloc.h,v 1.72 2003/02/08 03:44:32 mast Exp $
+|| $Id: stralloc.h,v 1.73 2003/03/14 15:50:47 grubba Exp $
 */
 
 #ifndef STRALLOC_H
@@ -106,8 +106,8 @@ static INLINE PCHARP MKPCHARP(void *ptr, int shift)
 
 
 #ifdef DEBUG_MALLOC
-#define reference_shared_string(s) do { struct pike_string *S_=(s); debug_malloc_touch(S_); S_->refs++; }while(0)
-#define copy_shared_string(to,s) do { struct pike_string *S_=(to)=(s); debug_malloc_touch(S_); S_->refs++; }while(0)
+#define reference_shared_string(s) do { struct pike_string *S_=(s); add_ref(S_); }while(0)
+#define copy_shared_string(to,s) do { struct pike_string *S_=(to)=(s); add_ref(S_); }while(0)
 
 struct shared_string_location
 {
@@ -129,8 +129,8 @@ extern struct shared_string_location *all_shared_string_locations;
 
 #else
 
-#define reference_shared_string(s) (s)->refs++
-#define copy_shared_string(to,s) ((to)=(s))->refs++
+#define reference_shared_string(s) add_ref(s)
+#define copy_shared_string(to,s) add_ref((to)=(s))
 
 #define MAKE_CONST_STRING(var, text)						\
  do { static struct pike_string *str_;                                          \
diff --git a/src/svalue.c b/src/svalue.c
index 37c1dcd1cf..6643d5fdf3 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.160 2003/02/24 21:09:46 mast Exp $
+|| $Id: svalue.c,v 1.161 2003/03/14 15:50:47 grubba Exp $
 */
 
 #include "global.h"
@@ -66,7 +66,7 @@ static int pike_isnan(double x)
 #endif /* HAVE__ISNAN */
 #endif /* HAVE_ISNAN */
 
-RCSID("$Id: svalue.c,v 1.160 2003/02/24 21:09:46 mast Exp $");
+RCSID("$Id: svalue.c,v 1.161 2003/03/14 15:50:47 grubba Exp $");
 
 struct svalue dest_ob_zero = {
   T_INT, 0,
@@ -277,7 +277,7 @@ PMOD_EXPORT void debug_free_svalues(struct svalue *s, size_t num, INT32 type_hin
 #ifdef DEBUG_MALLOC
       debug_malloc_update_location(s->u.refs  DMALLOC_PROXY_ARGS);
 #endif
-      if(--s->u.refs[0]<=0)
+      if(!sub_ref(s->u.dummy))
       {
 	really_free_svalue(s);
 	DO_IF_DMALLOC(s->u.refs=0);
@@ -293,7 +293,7 @@ PMOD_EXPORT void debug_free_svalues(struct svalue *s, size_t num, INT32 type_hin
 #ifdef DEBUG_MALLOC
       debug_malloc_update_location(s->u.refs  DMALLOC_PROXY_ARGS);
 #endif
-      if(--s->u.refs[0] <= 0)
+      if(!sub_ref(s->u.dummy))
       {
 	if(s->subtype == FUNCTION_BUILTIN)
 	  really_free_callable(s->u.efun);
@@ -395,12 +395,12 @@ PMOD_EXPORT void assign_to_short_svalue(union anything *u,
       case T_INT: u->integer=s->u.integer; break;
       case T_FLOAT: u->float_number=s->u.float_number; break;
       default:
-	if(u->refs && --*(u->refs) <= 0) really_free_short_svalue(u,type);
+	if(u->refs && !sub_ref(u->dummy)) really_free_short_svalue(u,type);
 	u->refs = s->u.refs;
 	add_ref(u->dummy);
     }
   }else if(type<=MAX_REF_TYPE && UNSAFE_IS_ZERO(s)){
-    if(u->refs && --*(u->refs) <= 0) really_free_short_svalue(u,type);
+    if(u->refs && !sub_ref(u->dummy)) really_free_short_svalue(u,type);
     u->refs=0;
   }else{
     Pike_error("Wrong type in assignment, expected %s, got %s.\n",
@@ -493,7 +493,7 @@ PMOD_EXPORT void assign_short_svalue(union anything *to,
     case T_INT: to->integer=from->integer; break;
     case T_FLOAT: to->float_number=from->float_number; break;
     default:
-      if(to->refs && --*(to->refs) <= 0) really_free_short_svalue(to,type);
+      if(to->refs && !sub_ref(to->dummy)) really_free_short_svalue(to,type);
       to->refs = tmp = from->refs;
       if(tmp) tmp[0]++;
   }
@@ -729,8 +729,7 @@ PMOD_EXPORT int is_eq(const struct svalue *a, const struct svalue *b)
       if(FIND_LFUN(a->u.object->prog,LFUN_EQ) != -1)
       {
       a_is_obj:
-	assign_svalue_no_free(sp, b);
-	sp++;
+	push_svalue(b);
 	apply_lfun(a->u.object, LFUN_EQ, 1);
 	if(UNSAFE_IS_ZERO(sp-1))
 	{
@@ -754,8 +753,7 @@ PMOD_EXPORT int is_eq(const struct svalue *a, const struct svalue *b)
       if(FIND_LFUN(b->u.object->prog,LFUN_EQ) != -1)
       {
       b_is_obj:
-	assign_svalue_no_free(sp, a);
-	sp++;
+	push_svalue(a);
 	apply_lfun(b->u.object, LFUN_EQ, 1);
 	if(UNSAFE_IS_ZERO(sp-1))
 	{
@@ -983,8 +981,7 @@ PMOD_EXPORT int is_lt(const struct svalue *a, const struct svalue *b)
 	Pike_error("Comparison on destructed object.\n");
       if(FIND_LFUN(a->u.object->prog,LFUN_LT) != -1)
       {
-	assign_svalue_no_free(sp, b);
-	sp++;
+	push_svalue(b);
 	apply_lfun(a->u.object, LFUN_LT, 1);
 	if(UNSAFE_IS_ZERO(sp-1))
 	{
@@ -1008,8 +1005,7 @@ PMOD_EXPORT int is_lt(const struct svalue *a, const struct svalue *b)
 	Pike_error("Comparison on destructed object.\n");
       if(FIND_LFUN(b->u.object->prog,LFUN_GT) == -1)
 	Pike_error("Object lacks `>\n");
-      assign_svalue_no_free(sp, a);
-      sp++;
+      push_svalue(a);
       apply_lfun(b->u.object, LFUN_GT, 1);
       if(UNSAFE_IS_ZERO(sp-1))
       {
@@ -2117,6 +2113,7 @@ PMOD_EXPORT INT32 pike_sizeof(const struct svalue *s)
       apply_lfun(s->u.object, LFUN__SIZEOF, 0);
       if(sp[-1].type != T_INT)
 	Pike_error("Bad return type from o->_sizeof() (not int)\n");
+      dmalloc_touch_svalue(Pike_sp-1);
       sp--;
       return sp->u.integer;
     }
diff --git a/src/threads.c b/src/threads.c
index 7b01693c52..224626da54 100644
--- a/src/threads.c
+++ b/src/threads.c
@@ -2,12 +2,12 @@
 || 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: threads.c,v 1.210 2003/03/05 16:18:30 mast Exp $
+|| $Id: threads.c,v 1.211 2003/03/14 15:50:47 grubba Exp $
 */
 
 #ifndef CONFIGURE_TEST
 #include "global.h"
-RCSID("$Id: threads.c,v 1.210 2003/03/05 16:18:30 mast Exp $");
+RCSID("$Id: threads.c,v 1.211 2003/03/14 15:50:47 grubba Exp $");
 
 PMOD_EXPORT int num_threads = 1;
 PMOD_EXPORT int threads_disabled = 0;
@@ -1497,6 +1497,7 @@ static void f_thread_id_result(INT32 args)
 
   assign_svalue_no_free(Pike_sp, &th->result);
   Pike_sp++;
+  dmalloc_touch_svalue(Pike_sp-1);
 }
 
 void init_thread_obj(struct object *o)
-- 
GitLab