diff --git a/src/array.c b/src/array.c
index 4e6d8ffbc9c90375076d629bc9c633ba41b40793..0bcdf32aedd572ff5f544550b8b6239c3d13ea0f 100644
--- a/src/array.c
+++ b/src/array.c
@@ -23,7 +23,7 @@
 #include "stuff.h"
 #include "bignum.h"
 
-RCSID("$Id: array.c,v 1.106 2001/06/06 02:22:38 mast Exp $");
+RCSID("$Id: array.c,v 1.107 2001/06/07 08:26:46 hubbe Exp $");
 
 PMOD_EXPORT struct array empty_array=
 {
@@ -79,6 +79,7 @@ PMOD_EXPORT struct array *low_allocate_array(ptrdiff_t size, ptrdiff_t extra_spa
   v->flags=0;
 
   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);
   LINK_ARRAY(v);
@@ -515,11 +516,22 @@ PMOD_EXPORT struct array *slice_array(struct array *v, ptrdiff_t start,
   if(d_flag > 1)  array_check_type_field(v);
 #endif
 
-  if(start==0 && v->refs==1)	/* Can we use the same array? */
+#if 1
+  if(v->refs==1)	/* Can we use the same array? */
   {
-    add_ref(v);
-    return array_shrink(v,end);
+    if((end-start) &&
+       (end-start)*2 > v->malloced_size +4 ) /* don't waste too much memory */
+    {
+      add_ref(v);
+      free_svalues(ITEM(v) + end, v->size - end, v->type_field);
+      free_svalues(ITEM(v), start, v->type_field);
+      v->item+=start;
+      v->malloced_size+=start;
+      v->size=end-start;
+      return v;
+    }
   }
+#endif
 
   a=allocate_array_no_init(end-start,0);
   a->type_field = v->type_field;
diff --git a/src/array.h b/src/array.h
index aa8f74e5c20b8e0555d04f2db05a40451ab7e33b..5076cc9a71076dd626528866ebdb9783bab7e05d 100644
--- a/src/array.h
+++ b/src/array.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: array.h,v 1.35 2001/06/06 02:22:39 mast Exp $
+ * $Id: array.h,v 1.36 2001/06/07 08:26:46 hubbe Exp $
  */
 #ifndef ARRAY_H
 #define ARRAY_H
@@ -26,7 +26,8 @@ struct array
 			 * though.
 			 */
   INT16 flags;          /* ARRAY_* flags */
-  struct svalue item[1];
+  struct svalue *item;
+  struct svalue real_item[1];
 };
 
 #define ARRAY_WEAK_FLAG 1
diff --git a/src/docode.c b/src/docode.c
index 31430c8af625f5a7703330b6aee5ceb800229e6b..7bcd1c7f0036937431105c586536dcb6c67671d2 100644
--- a/src/docode.c
+++ b/src/docode.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: docode.c,v 1.112 2001/04/15 15:37:19 mast Exp $");
+RCSID("$Id: docode.c,v 1.113 2001/06/07 08:26:47 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "pike_types.h"
@@ -714,6 +714,7 @@ static int do_docode2(node *n, INT16 flags)
   case F_ASSIGN:
     switch(CAR(n)->token)
     {
+    case F_RANGE:
     case F_AND:
     case F_OR:
     case F_XOR:
@@ -730,11 +731,18 @@ static int do_docode2(node *n, INT16 flags)
 	if(match_types(CDR(n)->type, array_type_string) ||
 	   match_types(CDR(n)->type, string_type_string))
 	{
-	  code_expression(CDAR(n), 0, "binary operand");
-	  emit0(F_LTOSVAL2);
+	  switch(do_docode(check_node_hash(CDAR(n)), 0))
+	  {
+	    case 1: emit0(F_LTOSVAL2); break;
+	    case 2: emit0(F_LTOSVAL3); break;
+#ifdef PIKE_DEBUG
+	    default:
+	      fatal("Arglebargle glop-glyf?\n");
+#endif
+	  }
 	}else{
 	  emit0(F_LTOSVAL);
-	  code_expression(CDAR(n), 0, "binary operand");
+	  do_docode(check_node_hash(CDAR(n)), 0);
 	}
 
 	emit0(CAR(n)->token);
diff --git a/src/interpret_functions.h b/src/interpret_functions.h
index 51aa8f3ff6fa85bc6e43dd756b8c1ea063844dcc..2e157541b6466f276c01bdccea2a00b71342965a 100644
--- a/src/interpret_functions.h
+++ b/src/interpret_functions.h
@@ -1,5 +1,5 @@
 /*
- * $Id: interpret_functions.h,v 1.55 2001/05/24 22:39:00 hubbe Exp $
+ * $Id: interpret_functions.h,v 1.56 2001/06/07 08:26:48 hubbe Exp $
  *
  * Opcode definitions for the interpreter.
  */
@@ -445,6 +445,30 @@ OPCODE0(F_LTOSVAL2, "ltosval2")
   }
 BREAK;
 
+OPCODE0(F_LTOSVAL3, "ltosval3")
+  Pike_sp[0] = Pike_sp[-1];
+  Pike_sp[-1] = Pike_sp[-2];
+  Pike_sp[-2].type = PIKE_T_INT;
+  Pike_sp++;
+  lvalue_to_svalue_no_free(Pike_sp-3, Pike_sp-5);
+
+  /* this is so that foo+=bar (and similar things) will be faster, this
+   * is done by freeing the old reference to foo after it has been pushed
+   * on the stack. That way foo can have only 1 reference if we are lucky,
+   * and then the low array/multiset/mapping manipulation routines can be
+   * destructive if they like
+   */
+  if( (1 << Pike_sp[-3].type) &
+      (BIT_ARRAY | BIT_MULTISET | BIT_MAPPING | BIT_STRING) )
+  {
+    struct svalue s;
+    s.type = PIKE_T_INT;
+    s.subtype = 0;
+    s.u.integer = 0;
+    assign_lvalue(Pike_sp-5, &s);
+  }
+BREAK;
+
 OPCODE0(F_ADD_TO_AND_POP, "+= and pop")
   Pike_sp[0]=Pike_sp[-1];
   Pike_sp[-1].type=PIKE_T_INT;