Array.st
changeset 1903 30c98b3377c5
parent 1730 e668db8cbae0
child 2052 9fdab6cbecfa
--- a/Array.st	Tue Nov 05 23:24:57 1996 +0100
+++ b/Array.st	Wed Nov 06 13:17:58 1996 +0100
@@ -17,7 +17,7 @@
 	category:'Collections-Arrayed'
 !
 
-!Array  class methodsFor:'documentation'!
+!Array class methodsFor:'documentation'!
 
 copyright
 "
@@ -43,9 +43,10 @@
     Access to the individual elements is via an integer index,
     using the well-known access messages #at: and #at:put:.
 
-    Since Arrays are used very often in the system, some methods have been 
-    tuned by reimplementing them as primitives. Also, the compiler inline-codes
-    some operations (especially: the above accessing messages).
+    Since Arrays are used very often in the system (either directly or a data-container
+    of more complex collection classes), some methods have been tuned by reimplementing 
+    them as primitives. Also, the compiler inline-codes some operations 
+    (especially: the above accessing messages).
 
     Notice that Array is a built-in class 
     (i.e. the VM knows about its representation). 
@@ -82,7 +83,7 @@
 "
 ! !
 
-!Array  class methodsFor:'instance creation'!
+!Array class methodsFor:'instance creation'!
 
 basicNew:anInteger
     "return an instance of myself with anInteger indexed variables.
@@ -241,7 +242,7 @@
     "Modified: 23.4.1996 / 15:52:15 / cg"
 ! !
 
-!Array  class methodsFor:'queries'!
+!Array class methodsFor:'queries'!
 
 isBuiltInClass
     "return true if this class is known by the run-time-system.
@@ -467,6 +468,7 @@
 	    spc = __qSpace(nObj);
 	    srcP = __ArrayInstPtr(self)->a_element;
 	    dstP = __ArrayInstPtr(nObj)->a_element;
+
 #ifdef UNROLL_LOOPS
 	    while (nIndex >= 4) {
 		element = srcP[0];
@@ -978,10 +980,11 @@
     REGISTER int repStartIndex;
     REGISTER OBJ t;
     REGISTER int count;
-
+    OBJ myClass;
     
-    if ((__ClassInstPtr(__qClass(self))->c_ninstvars == __MKSMALLINT(0))
-     && (((t = __Class(aCollection)) == Array) || (t == __qClass(self)))
+    if ((__ClassInstPtr((myClass = __qClass(self)))->c_ninstvars == __MKSMALLINT(0))
+     && __isNonNilObject(aCollection)
+     && (((t = __qClass(aCollection)) == Array) || (t == myClass))
      && __bothSmallInteger(start, stop)
      && __isSmallInteger(repStart)) {
         startIndex = __intVal(start) - 1;
@@ -989,9 +992,7 @@
             nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
             stopIndex = __intVal(stop) - 1;
             count = stopIndex - startIndex + 1;
-            if (count == 0) {
-                RETURN ( self );
-            }
+
             if ((count > 0) && (stopIndex < nIndex)) {
                 repStartIndex = __intVal(repStart) - 1;
                 if (repStartIndex >= 0) {
@@ -1005,6 +1006,7 @@
                              * no need to check stores if copying
                              * from myself
                              */
+
                             /* 
                              * take care of overlapping copy
                              * do not depend on memset being smart enough
@@ -1033,15 +1035,54 @@
                                 }
                                 RETURN ( self );
                             }
-#ifdef bcopy4
-                            bcopy4(src, dst, count);
+#ifdef SOFTWARE_PIPELINE
+			    {
+				OBJ t1;
+
+			        /* 
+			         * the loop below fetches one longWord behind
+			         * this should not be a problem
+			         */
+			        t1 = src[0];
+			        count--;
+			        if (count) {
+			            dst++; src++;
+			            do {
+				        dst[-1] = t1;
+				        t1 = src[0];
+				        src++;
+				        dst++;
+			            } while (count--);
+			        } else {
+				    dst[0] = t1;
+			        }
+			    }
 #else
-# ifdef FAST_MEMCPY
+
+# ifdef bcopy4
+                            bcopy4(src, dst, count);
+# else
+#  ifdef FAST_MEMCPY
                             bcopy(src, dst, __OBJS2BYTES__(count));
-# else
+#  else
+#   if defined(UNROLL_LOOPS)
+			    while (count >= 8) {
+				dst[0] = src[0];
+				dst[1] = src[1];
+				dst[2] = src[2];
+				dst[3] = src[3];
+				dst[4] = src[4];
+				dst[5] = src[5];
+				dst[6] = src[6];
+				dst[7] = src[7];
+				dst += 8; src += 8;
+				count -= 8;
+			    }
+#   endif
                             while (count--) {
                                 *dst++ = *src++;
                             }
+#  endif
 # endif
 #endif
                         } else {
@@ -1067,6 +1108,10 @@
                     }
                 }
             }
+
+            if (count == 0) {
+                RETURN ( self );
+            }
         }
     }
 %}.
@@ -1256,31 +1301,69 @@
             nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
             el = anElement;
             op = & (__InstPtr(self)->i_instvars[index]);
+
+            /*
+             * dont argue about those gotos below - they speed up that thing by 30%;
+             * its better to exit the loops below with a goto,
+             * since the generated code will then be:
+             *   compare
+             *   branch-on-equal found
+             *
+             * otherwise, we get:
+             *   compare
+             *   branch-on-not-equal skipLabel
+             *   move-to-return-register true
+             *   goto return-label
+             * skipLabel
+             *
+             * therefore, WITH the so-much-blamed goto, we only branch
+             * when found; without the goto, we branch always.
+             * Pipelined CPUs do usually not like branches.
+             */
+
 #if defined(UNROLL_LOOPS)
             {
                 unsigned int i8;
 
                 while ((i8 = index + 8) < nIndex) {
-                    if (op[0] == el) { RETURN ( __MKSMALLINT(index + 1 - nInsts) ); }
-                    if (op[1] == el) { RETURN ( __MKSMALLINT(index + 2 - nInsts) ); }
-                    if (op[2] == el) { RETURN ( __MKSMALLINT(index + 3 - nInsts) ); }
-                    if (op[3] == el) { RETURN ( __MKSMALLINT(index + 4 - nInsts) ); }
-                    if (op[4] == el) { RETURN ( __MKSMALLINT(index + 5 - nInsts) ); }
-                    if (op[5] == el) { RETURN ( __MKSMALLINT(index + 6 - nInsts) ); }
-                    if (op[6] == el) { RETURN ( __MKSMALLINT(index + 7 - nInsts) ); }
-                    if (op[7] == el) { RETURN ( __MKSMALLINT(index + 8 - nInsts) ); }
+                    if (op[0] == el) goto found1;
+                    if (op[1] == el) goto found2;
+                    if (op[2] == el) goto found3;
+                    if (op[3] == el) goto found4;
+                    if (op[4] == el) goto found5;
+                    if (op[5] == el) goto found6;
+                    if (op[6] == el) goto found7;
+                    if (op[7] == el) goto found8;
                     index = i8;
                     op += 8;
                 }
             }
 #endif
             while (index++ < nIndex) {
-                if (*op++ == el) {
-                    RETURN ( __MKSMALLINT(index - nInsts) );
-                }
+                if (*op++ == el) goto found0;
             }
         }
         RETURN ( __MKSMALLINT(0) );
+
+    found0:
+	RETURN ( __MKSMALLINT(index - nInsts) );
+    found1:
+	RETURN ( __MKSMALLINT(index + 1 - nInsts) );
+    found2:
+	RETURN ( __MKSMALLINT(index + 2 - nInsts) );
+    found3:
+	RETURN ( __MKSMALLINT(index + 3 - nInsts) );
+    found4:
+	RETURN ( __MKSMALLINT(index + 4 - nInsts) );
+    found5:
+	RETURN ( __MKSMALLINT(index + 5 - nInsts) );
+    found6:
+	RETURN ( __MKSMALLINT(index + 6 - nInsts) );
+    found7:
+	RETURN ( __MKSMALLINT(index + 7 - nInsts) );
+    found8:
+	RETURN ( __MKSMALLINT(index + 8 - nInsts) );
+
     }
 %}.
     ^ self indexNotInteger
@@ -1319,26 +1402,44 @@
                 unsigned int i8;
 
                 while ((i8 = index + 8) < lastIndex) {
-                    if (op[0] == el) { RETURN ( __MKSMALLINT(index + 1 - nInsts) ); }
-                    if (op[1] == el) { RETURN ( __MKSMALLINT(index + 2 - nInsts) ); }
-                    if (op[2] == el) { RETURN ( __MKSMALLINT(index + 3 - nInsts) ); }
-                    if (op[3] == el) { RETURN ( __MKSMALLINT(index + 4 - nInsts) ); }
-                    if (op[4] == el) { RETURN ( __MKSMALLINT(index + 5 - nInsts) ); }
-                    if (op[5] == el) { RETURN ( __MKSMALLINT(index + 6 - nInsts) ); }
-                    if (op[6] == el) { RETURN ( __MKSMALLINT(index + 7 - nInsts) ); }
-                    if (op[7] == el) { RETURN ( __MKSMALLINT(index + 8 - nInsts) ); }
+                    if (op[0] == el) goto found1;
+                    if (op[1] == el) goto found2;
+                    if (op[2] == el) goto found3;
+                    if (op[3] == el) goto found4;
+                    if (op[4] == el) goto found5;
+                    if (op[5] == el) goto found6;
+                    if (op[6] == el) goto found7;
+                    if (op[7] == el) goto found8;
                     index = i8;
                     op += 8;
                 }
             }
 #endif
             while (index++ < lastIndex) {
-                if (*op++ == el) {
-                    RETURN ( __MKSMALLINT(index - nInsts) );
-                }
+                if (*op++ == el) goto found0;
             }
         }
         RETURN ( __MKSMALLINT(0) );
+
+    found0:
+        RETURN ( __MKSMALLINT(index - nInsts) );
+    found1:
+        RETURN ( __MKSMALLINT(index + 1 - nInsts) );
+    found2:
+        RETURN ( __MKSMALLINT(index + 2 - nInsts) );
+    found3:
+        RETURN ( __MKSMALLINT(index + 3 - nInsts) );
+    found4:
+        RETURN ( __MKSMALLINT(index + 4 - nInsts) );
+    found5:
+        RETURN ( __MKSMALLINT(index + 5 - nInsts) );
+    found6:
+        RETURN ( __MKSMALLINT(index + 6 - nInsts) );
+    found7:
+        RETURN ( __MKSMALLINT(index + 7 - nInsts) );
+    found8:
+        RETURN ( __MKSMALLINT(index + 8 - nInsts) );
+
     }
 %}.
     ^ self indexNotInteger
@@ -1377,28 +1478,52 @@
     }
 
     o = anObject;
-#if defined(UNROLL_LOOPS)
+
+    /*
+     * dont argue those gotos below - they speed up that thing by 30%
+     * its better to exit the loops below with a goto,
+     * since the generated code will then be:
+     *   compare
+     *   branch-on-equal found
+     *
+     * otherwise, we get:
+     *   compare
+     *   branch-on-not-equal skipLabel
+     *   move-to-return-register true
+     *   goto return-label
+     * skipLabel
+     *
+     * therefore, WITH the so-much-blamed goto, we only branch
+     * when found; without the goto, we branch always.
+     * Pipelined CPUs do usually not like branches.
+     */
+    if (0) {
+	found:
+	    RETURN (true);
+    }
+
+# if defined(UNROLL_LOOPS)
     {
 	unsigned int i8;
+	OBJ slf = self;
 
 	while ((i8 = index + 8) < nIndex) {
-	    if (__InstPtr(self)->i_instvars[index] == o) { RETURN ( true ); }
-	    if (__InstPtr(self)->i_instvars[index+1] == o) { RETURN ( true ); }
-	    if (__InstPtr(self)->i_instvars[index+2] == o) { RETURN ( true ); }
-	    if (__InstPtr(self)->i_instvars[index+3] == o) { RETURN ( true ); }
-	    if (__InstPtr(self)->i_instvars[index+4] == o) { RETURN ( true ); }
-	    if (__InstPtr(self)->i_instvars[index+5] == o) { RETURN ( true ); }
-	    if (__InstPtr(self)->i_instvars[index+6] == o) { RETURN ( true ); }
-	    if (__InstPtr(self)->i_instvars[index+7] == o) { RETURN ( true ); }
+	    if (__InstPtr(slf)->i_instvars[index] == o) goto found;
+	    if (__InstPtr(slf)->i_instvars[index+1] == o) goto found;
+	    if (__InstPtr(slf)->i_instvars[index+2] == o) goto found;
+	    if (__InstPtr(slf)->i_instvars[index+3] == o) goto found;
+	    if (__InstPtr(slf)->i_instvars[index+4] == o) goto found;
+	    if (__InstPtr(slf)->i_instvars[index+5] == o) goto found;
+	    if (__InstPtr(slf)->i_instvars[index+6] == o) goto found;
+	    if (__InstPtr(slf)->i_instvars[index+7] == o) goto found;
 	    index = i8;
 	}
     }
-#endif
+# endif
     while (index < nIndex) {
-	if (__InstPtr(self)->i_instvars[index++] == o) {
-	    RETURN ( true );
-	}
+	if (__InstPtr(self)->i_instvars[index++] == o) goto found;
     }
+
     if (o == nil) {
 	RETURN ( false );
     }
@@ -1450,6 +1575,10 @@
             index += nInsts;
             nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
             if (anElement != nil) {
+		/*
+		 * special kludge to search for a string;
+		 * this is so common, that its worth a special case
+		 */
 #define SPECIAL_STRING_OPT
 #ifdef SPECIAL_STRING_OPT
                 if (__isString(anElement)) {
@@ -1486,7 +1615,9 @@
                     }
                 }
             } else {
-                /* search for nil */
+                /* 
+		 * search for nil - do an identity-search
+		 */
 #if defined(UNROLL_LOOPS)
                 {
                     unsigned int i8;
@@ -1543,6 +1674,10 @@
             }
 
             if (anElement != nil) {
+		/*
+		 * special kludge to search for a string;
+		 * this is so common, that its worth a special case
+		 */
 #ifdef SPECIAL_STRING_OPT
                 if (__isString(anElement)) {
                     while (index < lastIndex) {
@@ -1595,7 +1730,9 @@
                         }
                     }
                 } else {
-                    /* search for nil */
+                    /* 
+		     * search for nil - do an identity-search
+		     */
 #if defined(UNROLL_LOOPS)
                     {
                         unsigned int i8;
@@ -1628,8 +1765,8 @@
     ^ self indexNotInteger
 ! !
 
-!Array  class methodsFor:'documentation'!
+!Array class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Array.st,v 1.74 1996-10-14 15:32:09 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Array.st,v 1.75 1996-11-06 12:17:47 cg Exp $'
 ! !