diff --git a/src/array.c b/src/array.c
index f3d61c5937ffabcbeae31b9f177cb13a30f594ff..1c11047baeadfeaf40184a20518e6cb77073c2b2 100644
--- a/src/array.c
+++ b/src/array.c
@@ -30,7 +30,7 @@
 /** The empty array. */
 PMOD_EXPORT struct array empty_array=
 {
-  PIKE_CONSTANT_MEMOBJ_INIT(1), /* Never free */
+  PIKE_CONSTANT_MEMOBJ_INIT(1, PIKE_T_ARRAY), /* Never free */
   &weak_empty_array,     /* Next */
   0,			 /* previous */
   0,                     /* Size = 0 */
@@ -44,7 +44,7 @@ PMOD_EXPORT struct array empty_array=
 /** The empty weak array. */
 PMOD_EXPORT struct array weak_empty_array=
 {
-  PIKE_CONSTANT_MEMOBJ_INIT(1),
+  PIKE_CONSTANT_MEMOBJ_INIT(1, PIKE_T_ARRAY),
   0, &empty_array, 0, 0, 0, ARRAY_WEAK_FLAG,
   weak_empty_array.real_item,
   {SVALUE_INIT_FREE},
@@ -112,7 +112,7 @@ PMOD_EXPORT struct array *real_allocate_array(ptrdiff_t size,
   v->malloced_size = DO_NOT_WARN((INT32)(size + extra_space));
   v->item=v->real_item;
   v->size = DO_NOT_WARN((INT32)size);
-  INIT_PIKE_MEMOBJ(v);
+  INIT_PIKE_MEMOBJ(v, T_ARRAY);
   DOUBLELINK (first_array, v);
   
   {
diff --git a/src/constants.c b/src/constants.c
index 23f93ce1b1b66f56ed1a58c12166b8029203f673..3b6490916090d02fc81e125bb627db4c6dfde116 100644
--- a/src/constants.c
+++ b/src/constants.c
@@ -100,7 +100,7 @@ PMOD_EXPORT struct callable *low_make_callable(c_fun fun,
 					       docode_fun docode)
 {
   struct callable *f=alloc_callable();
-  INIT_PIKE_MEMOBJ(f);
+  INIT_PIKE_MEMOBJ(f, T_STRUCT_CALLABLE);
   f->function=fun;
   f->name=name;
   f->type=type;
diff --git a/src/mapping.c b/src/mapping.c
index 5bed9c0cf06d40875db2b45da688526320647700..471fa0bf9c737b43fa5a16cb4e48757b958f15bd 100644
--- a/src/mapping.c
+++ b/src/mapping.c
@@ -149,16 +149,16 @@ static void check_mapping_type_fields(const struct mapping *m)
 #endif
 
 static struct mapping_data empty_data =
-  { PIKE_CONSTANT_MEMOBJ_INIT(1), 1, 0,0,0,0,0,0, 0,
+  { PIKE_CONSTANT_MEMOBJ_INIT(1, T_MAPPING_DATA), 1, 0,0,0,0,0,0, 0,
     IF_ELSE_KEYPAIR_LOOP((struct keypair *)&empty_data.hash, 0), {0}};
 static struct mapping_data weak_ind_empty_data =
-  { PIKE_CONSTANT_MEMOBJ_INIT(1), 1, 0,0,0,0,0,0, MAPPING_WEAK_INDICES,
+  { PIKE_CONSTANT_MEMOBJ_INIT(1, T_MAPPING_DATA), 1, 0,0,0,0,0,0, MAPPING_WEAK_INDICES,
     IF_ELSE_KEYPAIR_LOOP((struct keypair *)&weak_ind_empty_data.hash, 0), {0}};
 static struct mapping_data weak_val_empty_data =
-  { PIKE_CONSTANT_MEMOBJ_INIT(1), 1, 0,0,0,0,0,0, MAPPING_WEAK_VALUES,
+  { PIKE_CONSTANT_MEMOBJ_INIT(1, T_MAPPING_DATA), 1, 0,0,0,0,0,0, MAPPING_WEAK_VALUES,
     IF_ELSE_KEYPAIR_LOOP((struct keypair *)&weak_val_empty_data.hash, 0), {0}};
 static struct mapping_data weak_both_empty_data =
-  { PIKE_CONSTANT_MEMOBJ_INIT(1), 1, 0,0,0,0,0,0, MAPPING_WEAK,
+  { PIKE_CONSTANT_MEMOBJ_INIT(1, T_MAPPING_DATA), 1, 0,0,0,0,0,0, MAPPING_WEAK,
     IF_ELSE_KEYPAIR_LOOP((struct keypair *)&weak_both_empty_data.hash, 0), {0}};
 
 /** This function allocates the hash table and svalue space for a mapping
@@ -209,6 +209,9 @@ static void init_mapping(struct mapping *m,
     md->flags = flags;
     md->size = 0;
     md->refs=0;
+#ifdef ATOMIC_SVALUE
+    md->ref_type = T_MAPPING_DATA;
+#endif
     md->valrefs=0;
     md->hardlinks=0;
     md->num_keypairs=size;
@@ -246,6 +249,9 @@ PMOD_EXPORT struct mapping *debug_allocate_mapping(int size)
   INITIALIZE_PROT(m);
   init_mapping(m,size,0);
 
+#ifdef ATOMIC_SVALUE
+  m->ref_type = T_MAPPING;
+#endif
   m->refs = 0;
   add_ref(m);	/* For DMALLOC... */
 
diff --git a/src/multiset.c b/src/multiset.c
index 0f27c898e9c385882942dbff7fee0ca389a69db0..1119bb0dd4a1dcbb5b2f92801157f09c63489768 100644
--- a/src/multiset.c
+++ b/src/multiset.c
@@ -231,14 +231,26 @@ static struct multiset_data empty_indval_msd = {
 
 void free_multiset_data (struct multiset_data *msd);
 
+#ifdef ATOMIC_SVALUE
 #define INIT_MULTISET(L) do {						\
     GC_ALLOC (L);							\
     INITIALIZE_PROT (L);						\
+    L->ref_type = T_MULTISET;						\
     L->refs = 0;							\
     add_ref(L);	/* For DMALLOC... */					\
     L->node_refs = 0;							\
     DOUBLELINK (first_multiset, L);					\
   } while (0)
+#else /* !ATOMIC_SVALUE */
+#define INIT_MULTISET(L) do {						\
+    GC_ALLOC (L);							\
+    INITIALIZE_PROT (L);						\
+    L->refs = 0;							\
+    add_ref(L);	/* For DMALLOC... */					\
+    L->node_refs = 0;							\
+    DOUBLELINK (first_multiset, L);					\
+  } while (0)
+#endif
 
 #undef EXIT_BLOCK
 #define EXIT_BLOCK(L) do {						\
diff --git a/src/object.c b/src/object.c
index 3248028efd0dee1815adf321524a3bccda6108b9..158e7629fd0169925665f1ad773e1f223b193b91 100644
--- a/src/object.c
+++ b/src/object.c
@@ -151,7 +151,7 @@ PMOD_EXPORT struct object *low_clone(struct program *p)
 
   DOUBLELINK(first_object,o);
 
-  INIT_PIKE_MEMOBJ(o);
+  INIT_PIKE_MEMOBJ(o, T_OBJECT);
 
 #ifdef PIKE_DEBUG
   o->program_id=p->id;
diff --git a/src/pike_types.c b/src/pike_types.c
index fcf8b61e23e0f9d26057b1d806724817d65b6d34..c0a1546bd0881d9946745a41ba7be734aa407e28 100644
--- a/src/pike_types.c
+++ b/src/pike_types.c
@@ -554,6 +554,9 @@ static inline struct pike_type *debug_mk_type(unsigned INT32 type,
       
   debug_malloc_pass(t = alloc_pike_type());
 
+#ifdef ATOMIC_SVALUE
+  t->ref_type = PIKE_T_TYPE;
+#endif
   t->refs = 0;
   add_ref(t);	/* For DMALLOC... */
   t->type = type;
diff --git a/src/pike_types.h b/src/pike_types.h
index 1fca5d7c913ee3852249d6ff8d114a2e483791ae..31b7333224bed370dd71fe49f8edfe622bf0e7ad 100644
--- a/src/pike_types.h
+++ b/src/pike_types.h
@@ -24,6 +24,9 @@ void TYPE_STACK_DEBUG(const char *fun);
 struct pike_type
 {
   INT32 refs;
+#ifdef ATOMIC_SVALUE
+  INT32 ref_type;
+#endif
   unsigned INT32 hash;
   struct pike_type *next;
   unsigned INT32 flags;
diff --git a/src/program.c b/src/program.c
index 3ee9be937c0f8a9211b52d18cf62b78a5f5b5628..c0c5ae7be2a30754c40077559b78d55216dc1afe 100644
--- a/src/program.c
+++ b/src/program.c
@@ -2572,7 +2572,7 @@ struct program *low_allocate_program(void)
 
   GC_ALLOC(p);
   p->id=++current_program_id;
-  INIT_PIKE_MEMOBJ(p);
+  INIT_PIKE_MEMOBJ(p, T_PROGRAM);
 
   DOUBLELINK(first_program, p);
   GETTIMEOFDAY(& p->timestamp);
diff --git a/src/stralloc.c b/src/stralloc.c
index 92fdf19201bc6c60d0cc9719ee89707a7eae099b..f9e31020bc4eba87980734ffaa87b03dd6739d43 100644
--- a/src/stralloc.c
+++ b/src/stralloc.c
@@ -532,12 +532,22 @@ struct pike_string_hdr {
 /* Use the BLOCK_ALLOC() stuff for short strings */
 
 #undef INIT_BLOCK
+#ifdef ATOMIC_SVALUE
 #define INIT_BLOCK(NEW_STR) do {				\
+    (NEW_STR)->ref_type = T_STRING;				\
     (NEW_STR)->refs = 0;					\
     add_ref((NEW_STR));						\
     (NEW_STR)->flags =						\
       STRING_NOT_HASHED|STRING_NOT_SHARED|STRING_IS_SHORT;	\
   } while(0)
+#else /* !ATOMIC_SVALUE */
+#define INIT_BLOCK(NEW_STR) do {				\
+    (NEW_STR)->refs = 0;					\
+    add_ref((NEW_STR));						\
+    (NEW_STR)->flags =						\
+      STRING_NOT_HASHED|STRING_NOT_SHARED|STRING_IS_SHORT;	\
+  } while(0)
+#endif
 
 #define SHORT_STRING_BLOCK	256
 #define SHORT_STRING_THRESHOLD	15 /* % 4 === -1 */
@@ -603,6 +613,9 @@ PMOD_EXPORT struct pike_string *debug_begin_shared_string(size_t len)
     t=(struct pike_string *)xalloc(len + 1 + sizeof(struct pike_string_hdr));
     t->flags = STRING_NOT_HASHED | STRING_NOT_SHARED;
   }
+#ifdef ATOMIC_SVALUE
+  t->ref_type = T_STRING;
+#endif
   t->refs = 0;
   add_ref(t);	/* For DMALLOC */
   t->str[len]=0;
@@ -724,6 +737,9 @@ PMOD_EXPORT struct pike_string *debug_begin_wide_shared_string(size_t len, int s
 				   sizeof(struct pike_string_hdr));
     t->flags = STRING_NOT_HASHED|STRING_NOT_SHARED;
   }
+#ifdef ATOMIC_SVALUE
+  t->ref_type = T_STRING;
+#endif
   t->refs = 0;
   add_ref(t);	/* For DMALLOC */
   t->len=len;
diff --git a/src/stralloc.h b/src/stralloc.h
index 89a40b1cd739a2939ca0df7b8469dd7070056ea7..d31b043b5434e6ba38427e3489d28d121ee66660 100644
--- a/src/stralloc.h
+++ b/src/stralloc.h
@@ -18,13 +18,24 @@
 #define STRUCT_PIKE_STRING_DECLARED
 #endif
 
+#ifdef ATOMIC_SVALUE
 #define PIKE_STRING_CONTENTS						\
   INT32 refs;								\
+  INT32 ref_type;							\
   INT16 flags;								\
   INT16 size_shift; /* 14 bit waste, but good for alignment... */	\
   ptrdiff_t len; /* Not counting terminating NUL. */			\
   size_t hval;								\
   struct pike_string *next 
+#else /* !ATOMIC_SVALUE */
+#define PIKE_STRING_CONTENTS						\
+  INT32 refs;								\
+  INT16 flags;								\
+  INT16 size_shift; /* 14 bit waste, but good for alignment... */	\
+  ptrdiff_t len; /* Not counting terminating NUL. */			\
+  size_t hval;								\
+  struct pike_string *next 
+#endif
 
 struct pike_string
 {
diff --git a/src/svalue.h b/src/svalue.h
index a0801a51f097b828af71995931edeed0d631acbd..8c438c761942eb2930f1bfd7bb3cecc89dacf98f 100644
--- a/src/svalue.h
+++ b/src/svalue.h
@@ -980,32 +980,67 @@ static INLINE void assign_svalue(struct svalue *to, const struct svalue *from)
  * but it would cost a couple of cycles in every lock/unlock
  * operation instead.
  */
-#define PIKE_MEMORY_OBJECT_MEMBERS \
-  INT32 refs \
+#ifdef ATOMIC_SVALUE
+/* Atomic svalues: Store the type in the reference types,
+ * instead of on the stack. This allows for changing an
+ * svalue in a single atomic operation.
+ */
+#define PIKE_MEMORY_OBJECT_MEMBERS	\
+  INT32 refs;				\
+  INT32 ref_type			\
+  DO_IF_SECURITY(; struct object *prot) \
+  IF_LOCAL_MUTEX(; PIKE_MUTEX_T mutex)
+
+#ifdef PIKE_SECURITY
+#ifdef USE_LOCAL_MUTEX
+#define PIKE_CONSTANT_MEMOBJ_INIT(refs, type) refs, type, 0, PTHREAD_MUTEX_INITIALIZER
+#else
+#define PIKE_CONSTANT_MEMOBJ_INIT(refs, type) refs, type, 0
+#endif
+#else
+#ifdef USE_LOCAL_MUTEX
+#define PIKE_CONSTANT_MEMOBJ_INIT(refs, type) refs, type, PTHREAD_MUTEX_INITIALIZER
+#else
+#define PIKE_CONSTANT_MEMOBJ_INIT(refs, type) refs, type
+#endif
+#endif
+
+#define INIT_PIKE_MEMOBJ(X, TYPE) do {			\
+  struct ref_dummy *v_=(struct ref_dummy *)(X);		\
+  v_->ref_type = (TYPE);				\
+  v_->refs=0;						\
+  add_ref(v_); /* For DMALLOC... */			\
+  DO_IF_SECURITY( INITIALIZE_PROT(v_) );		\
+  IF_LOCAL_MUTEX(mt_init_recursive(&(v_->mutex)));	\
+}while(0)
+#else /* !ATOMIC_SVALUE */
+#define PIKE_MEMORY_OBJECT_MEMBERS	\
+  INT32 refs				\
   DO_IF_SECURITY(; struct object *prot) \
   IF_LOCAL_MUTEX(; PIKE_MUTEX_T mutex)
 
 #ifdef PIKE_SECURITY
 #ifdef USE_LOCAL_MUTEX
-#define PIKE_CONSTANT_MEMOBJ_INIT(refs) refs, 0, PTHREAD_MUTEX_INITIALIZER
+#define PIKE_CONSTANT_MEMOBJ_INIT(refs, type) refs, 0, PTHREAD_MUTEX_INITIALIZER
 #else
-#define PIKE_CONSTANT_MEMOBJ_INIT(refs) refs, 0
+#define PIKE_CONSTANT_MEMOBJ_INIT(refs, type) refs, 0
 #endif
 #else
 #ifdef USE_LOCAL_MUTEX
-#define PIKE_CONSTANT_MEMOBJ_INIT(refs) refs, PTHREAD_MUTEX_INITIALIZER
+#define PIKE_CONSTANT_MEMOBJ_INIT(refs, type) refs, PTHREAD_MUTEX_INITIALIZER
 #else
-#define PIKE_CONSTANT_MEMOBJ_INIT(refs) refs
+#define PIKE_CONSTANT_MEMOBJ_INIT(refs, type) refs
 #endif
 #endif
 
-#define INIT_PIKE_MEMOBJ(X) do {			\
+#define INIT_PIKE_MEMOBJ(X, TYPE) do {			\
   struct ref_dummy *v_=(struct ref_dummy *)(X);		\
   v_->refs=0;						\
   add_ref(v_); /* For DMALLOC... */			\
   DO_IF_SECURITY( INITIALIZE_PROT(v_) );		\
   IF_LOCAL_MUTEX(mt_init_recursive(&(v_->mutex)));	\
 }while(0)
+#endif /* ATOMIC_SVALUE */
 
 #define EXIT_PIKE_MEMOBJ(X) do {		\
   struct ref_dummy *v_=(struct ref_dummy *)(X);		\