From eeaea16330fa93776fac38b3bbeb4fcca9a993aa Mon Sep 17 00:00:00 2001
From: Per Hedbor <ph@opera.com>
Date: Thu, 2 Oct 2014 19:53:59 +0200
Subject: [PATCH] Optimized case for array += ({..}) when refs==2.

This was sort of done before, but it first assigned the lvalue
to 0, then assigned it back to the array once done.

This new version is about 2x faster, improving the "append array"
benchmark by about 60%.
---
 src/array.c | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/src/array.c b/src/array.c
index e3650b9a43..067d5658eb 100644
--- a/src/array.c
+++ b/src/array.c
@@ -460,6 +460,26 @@ void o_append_array(INT32 args)
   if (TYPEOF(*val) == T_ARRAY) {
     struct svalue tmp;
     struct array *v = val->u.array;
+    /* simple case: if refs == 2 and there is space, just add the
+       element and do not do the assign.  This can be done because the
+       lvalue already has the array as it's value.
+    */
+    if( v->refs == 2 )
+    {
+      if( v->real_item+v->malloced_size >= v->item+v->size+args )
+      {
+        struct svalue *from = val+1;
+        int i;
+        for( i = 0; i<args; i++,from++ )
+        {
+          v->item[v->size++] = *from;
+          v->type_field |= 1<<TYPEOF(*from);
+        }
+        Pike_sp -= args;
+        stack_pop_2_elems_keep_top();
+        return;
+      }
+    }
     /* This is so that we can minimize the number of references
      * to the array, and be able to use destructive operations.
      * It's done by freeing the old reference to foo after it has been
-- 
GitLab