diff --git a/src/code/amd64.c b/src/code/amd64.c
index 0b961143eaf7877f9d8064928122509130ed1ca9..1077f9b6eb2b90420da3198dc3167cc3518a1207 100644
--- a/src/code/amd64.c
+++ b/src/code/amd64.c
@@ -1034,8 +1034,8 @@ static void amd64_push_svaluep_to(int reg, int spoff)
   mov_reg_mem(REG_RAX, sp_reg, spoff*sizeof(struct svalue)+OFFSETOF(svalue, type));
   and_reg_imm(REG_RAX, 0x1f);
   mov_reg_mem(REG_RCX, sp_reg, spoff*sizeof(struct svalue)+OFFSETOF(svalue, u.refs));
-  cmp_reg32_imm(REG_RAX, MAX_REF_TYPE);
-  jg(&label_A);
+  cmp_reg32_imm(REG_RAX, MIN_REF_TYPE);
+  jl(&label_A);
   add_imm_mem( 1, REG_RCX, OFFSETOF(pike_string, refs));
  LABEL_A;
 }
@@ -1096,9 +1096,9 @@ static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref )
     /* load type -> RAX */
   mov_sval_type( src, REG_RAX );
 
-  /* if RAX > MAX_REF_TYPE+1 */
-  cmp_reg32_imm( REG_RAX,MAX_REF_TYPE);
-  jg( &label_A );
+  /* if RAX < MIN_REF_TYPE+1 */
+  cmp_reg32_imm( REG_RAX,MIN_REF_TYPE);
+  jl( &label_A );
 
   /* Load pointer to refs -> RAX */
   mov_mem_reg( src, OFFSETOF(svalue, u.refs), REG_RAX);
@@ -1121,12 +1121,12 @@ static void amd64_free_svalue_type(enum amd64_reg src, enum amd64_reg type,
                                    int guaranteed_ref )
 {
   LABELS();
-  /* if type > MAX_REF_TYPE+1 */
+  /* if type < MIN_REF_TYPE+1 */
   if( src == REG_RAX )
     Pike_fatal("Clobbering RAX for free-svalue\n");
 
-  cmp_reg32_imm(type,MAX_REF_TYPE);
-  jg( &label_A );
+  cmp_reg32_imm(type,MIN_REF_TYPE);
+  jl( &label_A );
 
   /* Load pointer to refs -> RAX */
   mov_mem_reg( src, OFFSETOF(svalue, u.refs), REG_RAX);
@@ -1153,9 +1153,9 @@ void amd64_ref_svalue( enum amd64_reg src, int already_have_type )
   else
       and_reg_imm( REG_RAX, 0x1f );
 
-  /* if RAX > MAX_REF_TYPE+1 */
-  cmp_reg32_imm(REG_RAX, MAX_REF_TYPE );
-  jg( &label_A );
+  /* if RAX > MIN_REF_TYPE+1 */
+  cmp_reg32_imm(REG_RAX, MIN_REF_TYPE );
+  jl( &label_A );
   /* Load pointer to refs -> RAX */
   mov_mem_reg( src, OFFSETOF(svalue, u.refs), REG_RAX);
    /* *RAX++ */
@@ -2121,8 +2121,8 @@ int amd64_ins_f_jump(unsigned int op, int backward_jump)
 
       /* inc refs? */
       and_reg_imm( REG_RAX, 0x1f );
-      cmp_reg32_imm(REG_RAX, MAX_REF_TYPE);
-      jg( &label_B );
+      cmp_reg32_imm(REG_RAX, MIN_REF_TYPE);
+      jl( &label_B );
       add_imm_mem( 1, REG_RCX, OFFSETOF(pike_string, refs));
       jmp( &label_B );
 
@@ -2206,8 +2206,8 @@ int amd64_ins_f_jump(unsigned int op, int backward_jump)
 
       /* Optimization: The types are equal, pop_stack can be greatly
        * simplified if they are <= max_ref_type */
-      cmp_reg32_imm( REG_RCX,MAX_REF_TYPE+1);
-      jl( &label_B );
+      cmp_reg32_imm( REG_RCX,MIN_REF_TYPE);
+      jge( &label_B );
       /* cheap pop. We know that both are > max_ref_type */
       amd64_add_sp( -2 );
       jmp( &label_D );
diff --git a/src/code/ia32.c b/src/code/ia32.c
index 860ca516c31e77763fd748993ee1ddabd208e779..f97956aeed0faf154ff8a2ccd00942dee0fb805b 100644
--- a/src/code/ia32.c
+++ b/src/code/ia32.c
@@ -584,10 +584,10 @@ static void ia32_push_svalue (enum ia32_reg svalue_ptr_reg)
   add_to_program(0x66);		/* Switch to 16 bit operand mode. */
   add_to_program(0x83);		/* cmp $xx,svalue_ptr_reg */
   add_to_program(0xf8 | svalue_ptr_reg);
-  add_to_program(MAX_REF_TYPE);
+  add_to_program(MIN_REF_TYPE);
   DEALLOC_REG (svalue_ptr_reg);
 
-  add_to_program(0x77); /* ja bork */
+  add_to_program(0x7c); /* jl bork */
   add_to_program(0x02);
 
   CHECK_VALID_REG (tmp_reg);
diff --git a/src/encode.c b/src/encode.c
index 48c9212540469a0a552fa5bc247c321fdf4505d3..e49514878c6c01e4d5a71b07b3563d3f676b78c4 100644
--- a/src/encode.c
+++ b/src/encode.c
@@ -74,21 +74,27 @@
 
 
 /* Tags used by encode value.
- * Currently they only differ from the PIKE_T variants by
- *   TAG_FLOAT == PIKE_T_TYPE == 7
+ *
+ * Currently they differ from the old PIKE_T variants by
+ *   TAG_FLOAT == OLD_PIKE_T_TYPE == 7
  * and
- *   TAG_TYPE == PIKE_T_FLOAT == 9
+ *   TAG_TYPE == OLD_PIKE_T_FLOAT == 9
+ *
+ * The old PIKE_T variants in turn differ from the current for values
+ * less than 16 (aka MAX_TYPE) by bit 3 (mask 0x0008 (aka MIN_REF_TYPE))
+ * being inverted.
+ *
  * These are NOT to be renumbered unless the file-format version is changed!
  */
 /* Current encoding: �ke0
  *
  * +---+-+-+-------+
- * |s z|s|n|t y p e|
+ * |s z|s|n| t a g |
  * +---+-+-+-------+
  *  	sz	size/small int
  *  	s	small int indicator
  *  	n	negative (or rather inverted)
- *  	type	TAG_type
+ *  	tag	TAG_type (4 bits)
  */
 #define TAG_ARRAY 0
 #define TAG_MAPPING 1
@@ -235,9 +241,16 @@ static int type_to_tag(int type)
 {
   if (type == T_FLOAT) return TAG_FLOAT;
   if (type == T_TYPE) return TAG_TYPE;
+  if (type <= MAX_TYPE) return type ^ MIN_REF_TYPE;
   return type;
 }
-static int (*tag_to_type)(int) = type_to_tag;
+static int tag_to_type(int tag)
+{
+  if (tag == TAG_FLOAT) return T_FLOAT;
+  if (tag == TAG_TYPE) return T_TYPE;
+  if (tag <= MAX_TYPE) return tag ^ MIN_REF_TYPE;
+  return tag;
+}
 
 /* Let's cram those bits... */
 static void code_entry(int tag, INT64 num, struct encode_data *data)
@@ -313,17 +326,19 @@ static void encode_type(struct pike_type *t, struct encode_data *data)
 {
  one_more_type:
   if (t->type == T_MANY) {
-    addchar(T_FUNCTION);
+    addchar(T_FUNCTION ^ MIN_REF_TYPE);
     addchar(T_MANY);
   } else if (t->type == T_STRING) {
     if (t->car == int_type_string) {
-      addchar(T_STRING);
+      addchar(T_STRING ^ MIN_REF_TYPE);
     } else {
       /* Narrow string */
       addchar(PIKE_T_NSTRING);
       encode_type(t->car, data);
     }
     return;
+  } else if (t->type <= MAX_TYPE) {
+    addchar(t->type ^ MIN_REF_TYPE);
   } else {
     addchar(t->type);
   }
@@ -2323,6 +2338,7 @@ static void low_decode_type(struct decode_data *data)
   SET_ONERROR(err2, restore_type_mark, Pike_compiler->pike_type_mark_stackp);
 
   tmp = GETC();
+  if (tmp <= MAX_TYPE) tmp ^= MIN_REF_TYPE;
   switch(tmp)
   {
     default:
diff --git a/src/gc.c b/src/gc.c
index 80127be575eb40b52767b09582f22086135cc95d..d8cc7c206749d73a4def428bb36440cf2a85268d 100644
--- a/src/gc.c
+++ b/src/gc.c
@@ -4355,7 +4355,15 @@ PMOD_EXPORT visit_ref_cb *visit_ref = NULL;
 /* Be careful if extending this with internal types like
  * T_MAPPING_DATA and T_MULTISET_DATA; there's code that assumes
  * type_from_visit_fn only returns types that fit in a TYPE_FIELD. */
-PMOD_EXPORT visit_thing_fn *const visit_fn_from_type[MAX_REF_TYPE + 1] = {
+PMOD_EXPORT visit_thing_fn *const visit_fn_from_type[MAX_TYPE + 1] = {
+  (visit_thing_fn *) (ptrdiff_t) -1,
+  (visit_thing_fn *) (ptrdiff_t) -1,
+  (visit_thing_fn *) (ptrdiff_t) -1,
+  (visit_thing_fn *) (ptrdiff_t) -1,
+  (visit_thing_fn *) (ptrdiff_t) -1,
+  (visit_thing_fn *) (ptrdiff_t) -1,
+  (visit_thing_fn *) (ptrdiff_t) -1,
+  (visit_thing_fn *) (ptrdiff_t) -1,
   (visit_thing_fn *) &visit_array,
   (visit_thing_fn *) &visit_mapping,
   (visit_thing_fn *) &visit_multiset,
diff --git a/src/gc.h b/src/gc.h
index 9695e63304306e14f190d23e38bf4909c582470d..99873d228453d59824121b7c7833e901df58d4fe 100644
--- a/src/gc.h
+++ b/src/gc.h
@@ -659,7 +659,7 @@ PMOD_EXPORT extern visit_ref_cb *visit_ref;
  * VISIT_COMPLEX_ONLY. */
 
 /* Map between type and visit function for the standard ref types. */
-PMOD_EXPORT extern visit_thing_fn *const visit_fn_from_type[MAX_REF_TYPE + 1];
+PMOD_EXPORT extern visit_thing_fn *const visit_fn_from_type[MAX_TYPE + 1];
 PMOD_EXPORT TYPE_T type_from_visit_fn (visit_thing_fn *fn);
 
 PMOD_EXPORT TYPE_FIELD real_visit_svalues (struct svalue *s, size_t num,
diff --git a/src/pike_types.c b/src/pike_types.c
index e06090385daa4f5d8f700ee96802c92705124a53..67d24d33d65079c74882ef852d11d3b9d1f4a8c1 100644
--- a/src/pike_types.c
+++ b/src/pike_types.c
@@ -8137,9 +8137,16 @@ static void low_make_function_type(unsigned char *type_string,
 static void low_make_pike_type(unsigned char *type_string,
 			       unsigned char **cont)
 {
-  unsigned INT32 type;
+  unsigned INT32 type = *type_string;
 
-  switch(type = *type_string) {
+  if (type <= MAX_TYPE) {
+    /* Remap from old type enumeration to
+     * keep compat with output from __parse_pike_type().
+     */
+    type ^= MIN_REF_TYPE;
+  }
+
+  switch(type) {
 #ifdef PIKE_DEBUG
   case T_SCOPE:
     Pike_fatal("Not supported yet.\n");
@@ -8410,16 +8417,24 @@ static void low_type_to_string(struct pike_type *t)
   case T_ARRAY:
   case T_MULTISET:
   case T_TYPE:
-  case T_NOT:
   case T_PROGRAM:
+    my_putchar(t->type ^ MIN_REF_TYPE);
+    t = t->car;
+    goto recurse;
+
+  case T_NOT:
     my_putchar(t->type);
-    /* FALL_THROUGH */
     t = t->car;
     goto recurse;
 
+  case T_MAPPING:
+    my_putchar(t->type ^ MIN_REF_TYPE);
+    low_type_to_string(t->car);
+    t = t->cdr;
+    goto recurse;
+
   case PIKE_T_RING:
   case T_TUPLE:
-  case T_MAPPING:
   case T_OR:
   case T_AND:
     my_putchar(t->type);
@@ -8427,6 +8442,11 @@ static void low_type_to_string(struct pike_type *t)
     t = t->cdr;
     goto recurse;
 
+  case T_FLOAT:
+  case T_ZERO:
+    my_putchar(t->type ^ MIN_REF_TYPE);
+    break;
+
   case '0':
   case '1':
   case '2':
@@ -8437,8 +8457,6 @@ static void low_type_to_string(struct pike_type *t)
   case '7':
   case '8':
   case '9':
-  case T_FLOAT:
-  case T_ZERO:
   case T_VOID:
   case T_MIXED:
     my_putchar(t->type);
@@ -8447,7 +8465,7 @@ static void low_type_to_string(struct pike_type *t)
   case T_OBJECT:
     {
       INT32 i;
-      my_putchar(T_OBJECT);
+      my_putchar(T_OBJECT ^ MIN_REF_TYPE);
       i = (INT32)CAR_TO_INT(t);
       my_putchar( i );
       i = (INT32)CDR_TO_INT(t);
@@ -8464,7 +8482,7 @@ static void low_type_to_string(struct pike_type *t)
   case T_STRING:
     {
       if (t->car == int_type_string) {
-	my_putchar(T_STRING);
+	my_putchar(T_STRING ^ MIN_REF_TYPE);
       } else {
 	my_putchar(PIKE_T_NSTRING);
 	low_type_to_string(t->car);
@@ -8475,7 +8493,7 @@ static void low_type_to_string(struct pike_type *t)
   case T_INT:
     {
       INT32 i;
-      my_putchar(T_INT);
+      my_putchar(T_INT ^ MIN_REF_TYPE);
       i = (INT32)CAR_TO_INT(t);
       my_putchar((i >> 24) & 0xff);
       my_putchar((i >> 16) & 0xff);
@@ -8491,7 +8509,7 @@ static void low_type_to_string(struct pike_type *t)
 
   case T_FUNCTION:
   case T_MANY:
-    my_putchar(T_FUNCTION);
+    my_putchar(T_FUNCTION ^ MIN_REF_TYPE);
     while(t->type == T_FUNCTION) {
       low_type_to_string(t->car);
       t = t->cdr;
diff --git a/src/svalue.c b/src/svalue.c
index 9e2fcf228555e2ba8ef8c3e3034b69159f49af72..39b1a8cc8f15452e3bd2b95c2eff60af74ef9c79 100644
--- a/src/svalue.c
+++ b/src/svalue.c
@@ -137,10 +137,13 @@ PMOD_EXPORT void really_free_svalue(struct svalue *s)
   case T_STRING:
     really_free_string(tmp.u.string);
     break;
+
+  case PIKE_T_FREE:
+    break;
     
 #ifdef PIKE_DEBUG
   default:
-    Pike_fatal("Bad type in really_free_svalue.\n");
+    Pike_fatal("Bad type in really_free_svalue: %d.\n", TYPEOF(tmp));
 #endif
   }
 
@@ -181,56 +184,6 @@ PMOD_EXPORT void debug_free_svalues(struct svalue *s, size_t num, INT32 type_hin
     DOTYPE(BIT_OBJECT, free_object, object);
     DOTYPE(BIT_PROGRAM, free_program, program);
 
-   case   3: case   5: case   6: case   7: case   9: case  10: case  11:
-   case  12: case  13: case  14: case  15: case  17: case  18: case  19:
-   case  20: case  21: case  22: case  23: case  24: case  25: case  26:
-   case  27: case  28: case  29: case  30: case  31: case  33: case  34:
-   case  35: case  36: case  37: case  38: case  39: case  40: case  41:
-   case  42: case  43: case  44: case  45: case  46: case  47: case  48:
-   case  49: case  50: case  51: case  52: case  53: case  54: case  55:
-   case  56: case  57: case  58: case  59: case  60: case  61: case  62:
-   case  63: case  65: case  66: case  67: case  68: case  69: case  70:
-   case  71: case  72: case  73: case  74: case  75: case  76: case  77:
-   case  78: case  79: case  80: case  81: case  82: case  83: case  84:
-   case  85: case  86: case  87: case  88: case  89: case  90: case  91:
-   case  92: case  93: case  94: case  95: case  96: case  97: case  98:
-   case  99: case 100: case 101: case 102: case 103: case 104: case 105:
-   case 106: case 107: case 108: case 109: case 110: case 111: case 112:
-   case 113: case 114: case 115: case 116: case 117: case 118: case 119:
-   case 120: case 121: case 122: case 123: case 124: case 125: case 126:
-   case 127: case 129: case 130: case 131: case 132: case 133: case 134:
-   case 135: case 136: case 137: case 138: case 139: case 140: case 141:
-   case 142: case 143: case 144: case 145: case 146: case 147: case 148:
-   case 149: case 150: case 151: case 152: case 153: case 154: case 155:
-   case 156: case 157: case 158: case 159: case 160: case 161: case 162:
-   case 163: case 164: case 165: case 166: case 167: case 168: case 169:
-   case 170: case 171: case 172: case 173: case 174: case 175: case 176:
-   case 177: case 178: case 179: case 180: case 181: case 182: case 183:
-   case 184: case 185: case 186: case 187: case 188: case 189: case 190:
-   case 191: case 192: case 193: case 194: case 195: case 196: case 197:
-   case 198: case 199: case 200: case 201: case 202: case 203: case 204:
-   case 205: case 206: case 207: case 208: case 209: case 210: case 211:
-   case 212: case 213: case 214: case 215: case 216: case 217: case 218:
-   case 219: case 220: case 221: case 222: case 223: case 224: case 225:
-   case 226: case 227: case 228: case 229: case 230: case 231: case 232:
-   case 233: case 234: case 235: case 236: case 237: case 238: case 239:
-   case 240: case 241: case 242: case 243: case 244: case 245: case 246:
-   case 247: case 248: case 249: case 250: case 251: case 252: case 253:
-   case 254: case 255:
-
-    while(num--)
-    {
-#ifdef DEBUG_MALLOC
-      debug_malloc_update_location(s->u.refs  DMALLOC_PROXY_ARGS);
-#endif
-      if(!sub_ref(s->u.dummy))
-      {
-	really_free_svalue(s);
-      }
-      s++;
-    }
-    break;
-
   case BIT_FUNCTION:
     while(num--)
     {
@@ -251,7 +204,8 @@ PMOD_EXPORT void debug_free_svalues(struct svalue *s, size_t num, INT32 type_hin
 
 #undef DOTYPE
   default:
-    while(num--)
+    if (type_hint & (BIT_FLOAT | BIT_INT)) {
+      while(num--)
       {
 #ifdef DEBUG_MALLOC
 	if(REFCOUNTED_TYPE(TYPEOF(*s)))
@@ -259,6 +213,20 @@ PMOD_EXPORT void debug_free_svalues(struct svalue *s, size_t num, INT32 type_hin
 #endif
 	free_svalue(s++);
       }
+    } else {
+      while(num--)
+      {
+#ifdef DEBUG_MALLOC
+	debug_malloc_update_location(s->u.refs  DMALLOC_PROXY_ARGS);
+#endif
+	if(!sub_ref(s->u.dummy))
+	{
+	  really_free_svalue(s);
+	}
+	s++;
+      }
+    }
+    break;
   }
 }
 
@@ -2528,7 +2496,8 @@ void real_gc_free_svalue(struct svalue *s)
 	Pike_in_gc != GC_PASS_ZAP_WEAK)
       Pike_fatal("gc_free_svalue() called in invalid gc pass.\n");
 #endif
-    if (TYPEOF(*s) <= MAX_COMPLEX && *(s->u.refs) == 1)
+    if (REFCOUNTED_TYPE(TYPEOF(*s)) && TYPEOF(*s) <= MAX_COMPLEX &&
+	*(s->u.refs) == 1)
       gc_delayed_free(s->u.refs, TYPEOF(*s));
   }
   free_svalue(s);
@@ -2542,7 +2511,7 @@ void real_gc_free_short_svalue(union anything *u, TYPE_T type)
 	Pike_in_gc != GC_PASS_ZAP_WEAK)
       Pike_fatal("gc_free_short_svalue() called in invalid gc pass.\n");
 #endif
-    if (type <= MAX_COMPLEX && *u->refs == 1)
+    if (REFCOUNTED_TYPE(type) && type <= MAX_COMPLEX && *u->refs == 1)
       gc_delayed_free(u->refs, type);
   }
   free_short_svalue(u, type);
diff --git a/src/svalue.h b/src/svalue.h
index 3a64a0e2702f47e9d24e6458cd017b861e5fe44e..b704b3860bf515c24ed6102f464c7baf70c47197 100644
--- a/src/svalue.h
+++ b/src/svalue.h
@@ -116,25 +116,33 @@ struct svalue
 */
 #define INVALIDATE_SVAL(SVAL) SET_SVAL_TYPE(SVAL, 99) /* an invalid type */
 
-#define PIKE_T_ARRAY 0
-#define PIKE_T_MAPPING 1
-#define PIKE_T_MULTISET 2
-#define PIKE_T_OBJECT 3
-#define PIKE_T_FUNCTION 4
-#define PIKE_T_PROGRAM 5
-#define PIKE_T_STRING 6
-#define PIKE_T_TYPE 7
-#define PIKE_T_INT 8
-#define PIKE_T_FLOAT 9
+/* The native types.
+ *
+ * Note that PIKE_T_INT is zero so that cleared memory
+ * is filled with zeroes.
+ */
+#define PIKE_T_INT 0
+#define PIKE_T_FLOAT 1
+
+/* NB: The reference counted types all have bit 4 set. */
+#define PIKE_T_ARRAY 8
+#define PIKE_T_MAPPING 9
+#define PIKE_T_MULTISET 10
+#define PIKE_T_OBJECT 11
+#define PIKE_T_FUNCTION 12
+#define PIKE_T_PROGRAM 13
+#define PIKE_T_STRING 14
+#define PIKE_T_TYPE 15
 
 /* The types above are valid types in svalues.
  * The following are only used by the internal systems.
  */
 
-#define PIKE_T_ZERO  14	/**< Can return 0, but nothing else */
+/* NB: 6 & 7 below are selected for easy backward compat with Pike 7.8. */
+#define PIKE_T_ZERO  6	/**< Can return 0, but nothing else */
 
 
-#define T_UNFINISHED 15
+#define T_UNFINISHED 7
 
 #define T_VOID       16 /**< Can't return any value. Also used on stack to fill out the second
  * svalue on an lvalue when it isn't used. */
@@ -200,6 +208,10 @@ struct svalue
 #define T_MULTISET_DATA 10003
 #define T_STRUCT_CALLABLE 10004
 
+/* NOTE: The t* macros below currently use the old type encoding
+ *       to be compatible with __parse_pike_type() in older
+ *       versions of Pike.
+ */
 #define tArr(VAL) "\000" VAL
 #define tArray tArr(tMix)
 #define tMap(IND,VAL) "\001" IND VAL
@@ -325,7 +337,7 @@ struct svalue
 #define BIT_VOID (1 << T_VOID)
 
 /** This is used in typechecking to signify that the rest of the
- * arguments has to be of this type.
+ * arguments have to be of this type.
  */
 #define BIT_MANY (1 << T_MANY)
 
@@ -338,12 +350,12 @@ struct svalue
 
 /* Max type which contains svalues */
 #define MAX_COMPLEX PIKE_T_PROGRAM
-/* Max type with ref count */
-#define MAX_REF_TYPE PIKE_T_TYPE
+/* Min type with ref count */
+#define MIN_REF_TYPE PIKE_T_ARRAY
 /* Max type handled by svalue primitives */
-#define MAX_TYPE PIKE_T_FLOAT
+#define MAX_TYPE PIKE_T_TYPE
 
-#define REFCOUNTED_TYPE(T)	((T) <= MAX_REF_TYPE)
+#define REFCOUNTED_TYPE(T)	(((T) & ~(MIN_REF_TYPE - 1)) == MIN_REF_TYPE)
 
 #define NUMBER_NUMBER 0
 #define NUMBER_UNDEFINED 1