Hi,

I've made a small change in OrderedCollection in growBy:shift:
I use the primitive VMpr_OrderedCollection_replaceFromToWithStartingAt.
I guess it should be possible to tweak again a bit the behavior:
In addLast or addFirst if we have any free rooms but first is <= 1 or last >= n we could move instead of allocating a new collection.

Gwen
>From f9c742d176e8f5c43d49acc5f2fb239ba8e871a3 Mon Sep 17 00:00:00 2001
From: Gwenael Casaccio <[email protected]>
Date: Fri, 24 Jun 2011 08:11:59 +0200
Subject: [PATCH] OrderedCollection

---
 kernel/OrderColl.st            |   11 ++++--
 libgst/prims.def               |   64 ++++++++++++++++++++++++++++++++++++++++
 snprintfv/snprintfv/filament.h |    4 +-
 snprintfv/snprintfv/printf.h   |    8 ++--
 snprintfv/snprintfv/stream.h   |    4 +-
 5 files changed, 79 insertions(+), 12 deletions(-)

diff --git a/kernel/OrderColl.st b/kernel/OrderColl.st
index 7d15dd4..0adfddc 100644
--- a/kernel/OrderColl.st
+++ b/kernel/OrderColl.st
@@ -508,13 +508,16 @@ on content (such as add:after:)'>
 	<category: 'private methods'>
 	| newOrderedCollection |
 	newOrderedCollection := self copyEmpty: self basicSize + delta.
-	firstIndex to: lastIndex
-	    do: 
-		[:index | 
-		newOrderedCollection basicAt: index + shiftCount put: (self basicAt: index)].
+	newOrderedCollection primReplaceFrom: firstIndex + shiftCount to: lastIndex + shiftCount with: self startingAt: firstIndex.
 	newOrderedCollection firstIndex: firstIndex + shiftCount
 	    lastIndex: lastIndex + shiftCount.
 	self become: newOrderedCollection
     ]
+
+    primReplaceFrom: aFromInteger to: aToInteger with: anOrderedCollection startingAt: aStartInteger [
+	<category: 'private methods'>
+
+	<primitive: VMpr_OrderedCollection_replaceFromToWithStartingAt>
+    ]
 ]
 
diff --git a/libgst/prims.def b/libgst/prims.def
index 5eff664..dbed9c8 100644
--- a/libgst/prims.def
+++ b/libgst/prims.def
@@ -3303,6 +3303,70 @@ primitive VMpr_ArrayedCollection_replaceFromToWithStartingAt [succeed,fail]
   UNPOP (4);
   PRIM_FAILED;
 }
+
+/* OrderedCollection primReplaceFrom:to:with:startingAt:*/
+primitive VMpr_OrderedCollection_replaceFromToWithStartingAt [succeed,fail]
+{
+  OOP srcIndexOOP, srcOOP, dstEndIndexOOP, dstStartIndexOOP, dstOOP;
+  int dstEndIndex, dstStartIndex, srcIndex, dstLen, srcLen, dstRangeLen;
+  gst_uchar *dstBase, *srcBase;
+  _gst_primitives_executed++;
+
+  srcIndexOOP = POP_OOP ();
+  srcOOP = POP_OOP ();
+  dstEndIndexOOP = POP_OOP ();
+  dstStartIndexOOP = POP_OOP ();
+  dstOOP = STACKTOP ();
+  if COMMON (IS_INT (srcIndexOOP) && IS_INT (dstStartIndexOOP)
+             && IS_INT (dstEndIndexOOP) && !IS_INT (srcOOP))
+    {
+      intptr_t srcSpec = OOP_INSTANCE_SPEC (srcOOP);
+      intptr_t dstSpec = OOP_INSTANCE_SPEC (dstOOP);
+      int srcOffset = srcSpec >> ISP_NUMFIXEDFIELDS;
+      int dstOffset = dstSpec >> ISP_NUMFIXEDFIELDS;
+      int size;
+
+      /* Check compatibility.  */
+      size = _gst_log2_sizes[srcSpec & ISP_SHAPE];
+      if (size != _gst_log2_sizes[dstSpec & ISP_SHAPE])
+	goto bad;
+      if (((srcSpec & ISP_INDEXEDVARS) == GST_ISP_POINTER)
+          != ((dstSpec & ISP_INDEXEDVARS) == GST_ISP_POINTER))
+	goto bad;
+
+      /* dstEnd is inclusive: (1 to: 1) has length 1 */
+      dstEndIndex = TO_INT (dstEndIndexOOP);
+      dstStartIndex = TO_INT (dstStartIndexOOP);
+      srcIndex = TO_INT (srcIndexOOP);
+      dstOOP = STACKTOP ();
+      dstLen = NUM_INDEXABLE_FIELDS (dstOOP);
+      srcLen = NUM_INDEXABLE_FIELDS (srcOOP);
+      dstRangeLen = dstEndIndex - dstStartIndex + 1;
+
+      if UNCOMMON (dstRangeLen < 0
+		   || dstEndIndex > dstLen || dstStartIndex <= 0
+	           || srcIndex + dstRangeLen - 1 > srcLen
+		   || (srcIndex <= 0 && dstRangeLen > 0))
+	goto bad;
+
+      /* don't do it unless there's something to copy */
+      if COMMON (dstRangeLen > 0)
+	{
+	  /* do the copy */
+          dstBase = (gst_uchar *) &(OOP_TO_OBJ (dstOOP)->data[dstOffset]);
+          srcBase = (gst_uchar *) &(OOP_TO_OBJ (srcOOP)->data[srcOffset]);
+	  dstStartIndex = (dstStartIndex - 1) << size;
+	  srcIndex = (srcIndex - 1) << size;
+	  dstRangeLen <<= size;
+	  memmove (&dstBase[dstStartIndex], &srcBase[srcIndex], dstRangeLen);
+	}
+      PRIM_SUCCEEDED;
+    }
+
+ bad:
+  UNPOP (4);
+  PRIM_FAILED;
+}
 
 /* Object == */
 
diff --git a/snprintfv/snprintfv/filament.h b/snprintfv/snprintfv/filament.h
index 4a91eb6..8a7ce6c 100644
--- a/snprintfv/snprintfv/filament.h
+++ b/snprintfv/snprintfv/filament.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/filament.in"
+#line 1 "./filament.in"
 /*  -*- Mode: C -*-  */
 
 /* filament.h --- a bit like a string but different =)O|
@@ -118,7 +118,7 @@ extern char * fildelete (Filament *fil);
 extern void _fil_extend (Filament *fil, size_t len, boolean copy);
 
 
-#line 61 "../../../snprintfv/snprintfv/filament.in"
+#line 61 "./filament.in"
 
 /* Save the overhead of a function call in the great majority of cases. */
 #define fil_maybe_extend(fil, len, copy)  \
diff --git a/snprintfv/snprintfv/printf.h b/snprintfv/snprintfv/printf.h
index 49a2e9f..1437dd5 100644
--- a/snprintfv/snprintfv/printf.h
+++ b/snprintfv/snprintfv/printf.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/printf.in"
+#line 1 "./printf.in"
 /*  -*- Mode: C -*-  */
 
 /* printf.in --- printf clone for argv arrays
@@ -266,7 +266,7 @@ enum
       } \
   } SNV_STMT_END
 
-#line 269 "../../../snprintfv/snprintfv/printf.in"
+#line 269 "./printf.in"
 /**
  * printf_generic_info:   
  * @pinfo: the current state information for the format
@@ -302,7 +302,7 @@ extern int printf_generic_info (struct printf_info *const pinfo, size_t n, int *
 extern int printf_generic (STREAM *stream, struct printf_info *const pinfo, union printf_arg const *args);
 
 
-#line 270 "../../../snprintfv/snprintfv/printf.in"
+#line 270 "./printf.in"
 /**
  * register_printf_function:  
  * @spec: the character which will trigger @func, cast to an unsigned int.
@@ -789,7 +789,7 @@ extern int snv_vasprintf (char **result, const char *format, va_list ap);
 extern int snv_asprintfv (char **result, const char *format, snv_constpointer const args[]);
 
 
-#line 271 "../../../snprintfv/snprintfv/printf.in"
+#line 271 "./printf.in"
 
 /* If you don't want to use snprintfv functions for *all* of your string
    formatting API, then define COMPILING_SNPRINTFV_C and use the snv_
diff --git a/snprintfv/snprintfv/stream.h b/snprintfv/snprintfv/stream.h
index 496bd33..0bebce1 100644
--- a/snprintfv/snprintfv/stream.h
+++ b/snprintfv/snprintfv/stream.h
@@ -1,4 +1,4 @@
-#line 1 "../../../snprintfv/snprintfv/stream.in"
+#line 1 "./stream.in"
 /*  -*- Mode: C -*-  */
 
 /* stream.h --- customizable stream routines
@@ -180,7 +180,7 @@ extern int stream_puts (char *s, STREAM *stream);
 extern int stream_get (STREAM *stream);
 
 
-#line 88 "../../../snprintfv/snprintfv/stream.in"
+#line 88 "./stream.in"
 #ifdef __cplusplus
 #if 0
 /* This brace is so that emacs can still indent properly: */
-- 
1.7.4.1

_______________________________________________
help-smalltalk mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/help-smalltalk

Reply via email to