Array.st
changeset 2216 e4fed6c622de
parent 2213 2a4a3df451bf
child 2217 5c021c30fd01
--- a/Array.st	Tue Jan 21 11:20:33 1997 +0100
+++ b/Array.st	Tue Jan 21 13:54:25 1997 +0100
@@ -560,12 +560,78 @@
 			if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
 #endif
 			{
+
+# if defined(UNROLL_LOOPS2)
+			    {
+				int i8;
+
+				while ((i8 = index+8) < nIndex) {
+				    if (InterruptPending != nil) goto interrupt0;
+		continue0:
+				    (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+				    if (InterruptPending != nil) goto interrupt1;
+		continue1:
+				    (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index+1]);
+				    if (InterruptPending != nil) goto interrupt2;
+		continue2:
+				    (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index+2]);
+				    if (InterruptPending != nil) goto interrupt3;
+		continue3:
+				    (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index+3]);
+				    if (InterruptPending != nil) goto interrupt4;
+		continue4:
+				    (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index+4]);
+				    if (InterruptPending != nil) goto interrupt5;
+		continue5:
+				    (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index+5]);
+				    if (InterruptPending != nil) goto interrupt6;
+		continue6:
+				    (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index+6]);
+				    if (InterruptPending != nil) goto interrupt7;
+		continue7:
+				    (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index+7]);
+				    index = i8;
+				}
+			    }
+# endif /* UNROLL_LOOPS2 */
+
 			    for (; index < nIndex; index++) {
+# ifdef i386
 				if (InterruptPending != nil) __interruptL(@line);
+				(*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+# else
+				OBJ el;
 
-				(*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+				el = __InstPtr(self)->i_instvars[index]; */
+				if (InterruptPending == nil) {
+				    (*codeVal)(BLOCK_ARG, el);
+				} else {
+				    __interruptL(@line);
+				    (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+				}
+# endif
 			    }
 			    RETURN (self);
+
+# if defined(UNROLL_LOOPS2)
+		interrupt0:
+			    __interruptL(@line); goto continue0;
+		interrupt1:
+			    __interruptL(@line); goto continue1;
+		interrupt2:
+			    __interruptL(@line); goto continue2;
+		interrupt3:
+			    __interruptL(@line); goto continue3;
+		interrupt4:
+			    __interruptL(@line); goto continue4;
+		interrupt5:
+			    __interruptL(@line); goto continue5;
+		interrupt6:
+			    __interruptL(@line); goto continue6;
+		interrupt7:
+			    __interruptL(@line); goto continue7;
+
+# endif /* UNROLL_LOOPS2 */
 			}
 		    }
 		}
@@ -642,7 +708,6 @@
      up to (and including) stop in the collection.
      - reimplemented for speed"
 
-    |home|
 %{
     REGISTER OBJFUNC codeVal;
     REGISTER int index;
@@ -690,12 +755,92 @@
 			if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
 #endif
 			{
-			    for (index=indexLow; index <= indexHigh; index++) {
+			    index = indexLow;
+
+#if defined(UNROLL_LOOPS2)
+			    OBJ el;
+			    /*
+			     * boy; what an ugly looking piece of code ...
+			     * however, this software pipelined thing has no taken conditional
+			     * branches in the normal case and is almost twice as fast to even
+			     * what an unrolling optimizing compiler produces from the loop below ...
+			     */
+			    {
+				int i8;
+
+				while ((i8 = index+8) <= indexHigh) {
+				    el = __InstPtr(self)->i_instvars[index];
+				    if (InterruptPending != nil) goto interrupt0;
+		continue0:
+				    (*codeVal)(BLOCK_ARG, el);
+				    el = __InstPtr(self)->i_instvars[index+1];
+				    if (InterruptPending != nil) goto interrupt1;
+		continue1:
+				    (*codeVal)(BLOCK_ARG, el);
+				    el = __InstPtr(self)->i_instvars[index+2];
+				    if (InterruptPending != nil) goto interrupt2;
+		continue2:
+				    (*codeVal)(BLOCK_ARG, el);
+				    el = __InstPtr(self)->i_instvars[index+3];
+				    if (InterruptPending != nil) goto interrupt3;
+		continue3:
+				    (*codeVal)(BLOCK_ARG, el);
+				    el = __InstPtr(self)->i_instvars[index+4];
+				    if (InterruptPending != nil) goto interrupt4;
+		continue4:
+				    (*codeVal)(BLOCK_ARG, el);
+				    el = __InstPtr(self)->i_instvars[index+5];
+				    if (InterruptPending != nil) goto interrupt5;
+		continue5:
+				    (*codeVal)(BLOCK_ARG, el);
+				    el = __InstPtr(self)->i_instvars[index+6];
+				    if (InterruptPending != nil) goto interrupt6;
+		continue6:
+				    (*codeVal)(BLOCK_ARG, el);
+				    el = __InstPtr(self)->i_instvars[index+7];
+				    if (InterruptPending != nil) goto interrupt7;
+		continue7:
+				    (*codeVal)(BLOCK_ARG, el);
+				    index = i8;
+				}
+			    }
+#endif /* UNROLL_LOOP2 */
+			    for (; index <= indexHigh; index++) {
+#ifdef i386
 				if (InterruptPending != nil) __interruptL(@line);
+				(*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+#else
+				OBJ el;
 
-				(*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+				el = __InstPtr(self)->i_instvars[index]; */
+				if (InterruptPending == nil) {
+				    (*codeVal)(BLOCK_ARG, el);
+				} else {
+				    __interruptL(@line);
+				    (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+				}
+#endif
 			    }
 			    RETURN (self);
+
+#if defined(UNROLL_LOOP2)
+		interrupt0:
+			    __interruptL(@line); el = __InstPtr(self)->i_instvars[index]; goto continue0;
+		interrupt1:
+			    __interruptL(@line); el = __InstPtr(self)->i_instvars[index+1]; goto continue1;
+		interrupt2:
+			    __interruptL(@line); el = __InstPtr(self)->i_instvars[index+2]; goto continue2;
+		interrupt3:
+			    __interruptL(@line); el = __InstPtr(self)->i_instvars[index+3]; goto continue3;
+		interrupt4:
+			    __interruptL(@line); el = __InstPtr(self)->i_instvars[index+4]; goto continue4;
+		interrupt5:
+			    __interruptL(@line); el = __InstPtr(self)->i_instvars[index+5]; goto continue5;
+		interrupt6:
+			    __interruptL(@line); el = __InstPtr(self)->i_instvars[index+6]; goto continue6;
+		interrupt7:
+			    __interruptL(@line); el = __InstPtr(self)->i_instvars[index+7]; goto continue7;
+#endif /* UNROLL_LOOP2 */
 			}
 		    }
 		}
@@ -769,7 +914,6 @@
      up to (and including) stop in the collection. Step in reverse order.
      - reimplemented for speed"
 
-    |home|
 %{
     REGISTER OBJFUNC codeVal;
     REGISTER int index;
@@ -789,37 +933,6 @@
 
 	    if (__isBlockLike(aBlock)
 	     && (__BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) {
-		{
-		    /*
-		     * the most common case: a static compiled block, with home on the stack ...
-		     */
-		    REGISTER OBJFUNC codeVal;
-
-		    if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
-#ifdef NEW_BLOCK_CALL
-#                       define BLOCK_ARG        aBlock
-#else
-#                       define BLOCK_ARG        rHome
-			REGISTER OBJ rHome;
-
-			rHome = __BlockInstPtr(aBlock)->b_home;
-			if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
-#endif
-			{
-			    for (index=indexHigh; index >= indexLow; index--) {
-				if (InterruptPending != nil) __interruptL(@line);
-
-				(*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
-			    }
-			    RETURN (self);
-			}
-		    }
-		}
-
-		/*
-		 * sorry, must check code-pointer in the loop
-		 * it could be recompiled or flushed
-		 */
 #               undef BLOCK_ARG
 #ifdef NEW_BLOCK_CALL
 #               define BLOCK_ARG        aBlock
@@ -885,7 +998,7 @@
      Pass both index and element to the block.
      - reimplemented for speed"
 
-    |home sz "{ Class: SmallInteger }" |
+    |sz "{ Class: SmallInteger }" |
 
     sz := self size.
 %{
@@ -1035,37 +1148,6 @@
 	if (nIndex <= actualSize) {
 	    if (__isBlockLike(aBlock)
 	     && (__BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) {
-		{
-		    /*
-		     * the most common case: a static compiled block, with home on the stack ...
-		     */
-		    REGISTER OBJFUNC codeVal;
-
-		    if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
-#ifdef NEW_BLOCK_CALL
-#                       define BLOCK_ARG        aBlock
-#else
-#                       define BLOCK_ARG        rHome
-			REGISTER OBJ rHome;
-
-			rHome = __BlockInstPtr(aBlock)->b_home;
-			if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
-#endif
-			{
-			    for (index=nIndex-1; index >= endIndex; index--) {
-				if (InterruptPending != nil) __interruptL(@line);
-
-				(*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
-			    }
-			    RETURN (self);
-			}
-		    }
-		}
-
-		/*
-		 * sorry, must check code-pointer in the loop
-		 * it could be recompiled or flushed
-		 */
 #               undef BLOCK_ARG
 #ifdef NEW_BLOCK_CALL
 #               define BLOCK_ARG        aBlock
@@ -1560,40 +1642,63 @@
 	    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 taken branches.
-	     */
-
 #if defined(memsrch4)
 	    if (index < nIndex) {
 		OBJ *p;
 
-	        p = memsrch4(op, (int)el, (nIndex - index));
-	        if (p) {
+		p = memsrch4(op, (int)el, (nIndex - index));
+		if (p) {
 		    index = p - op + 1;
 		    RETURN ( __MKSMALLINT(index) ); 
-	        }
+		}
 	    }
 #else
+	    if (0) {
+		found0:
+		    RETURN ( __MKSMALLINT(index - nInsts) );
+# if defined(UNROLL_LOOPS)
+		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) );
+# endif /* UNROLL_LOOPS */
+	    }
+
 # if defined(UNROLL_LOOPS)
 	    {
+		/*
+		 * 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 (with return as if-statement), 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 taken branches.
+		 */
+
 		unsigned int i8;
-
+                
 		while ((i8 = index + 8) < nIndex) {
 		    if (op[0] == el) goto found1;
 		    if (op[1] == el) goto found2;
@@ -1614,31 +1719,9 @@
 #endif
 	}
 	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
-
-
 !
 
 identityIndexOf:anElement startingAt:start endingAt:stop
@@ -1669,16 +1752,39 @@
 	    op = & (__InstPtr(self)->i_instvars[index]);
 
 #if defined(memsrch4)
-            if (index < lastIndex) {
-                OBJ *p;
+	    if (index < lastIndex) {
+		OBJ *p;
+
+		p = memsrch4(op, (int)el, (lastIndex - index));
+		if (p) {
+		    index = p - op + 1;
+		    RETURN ( __MKSMALLINT(index) ); 
+		}
+	    }
+#else
 
-                p = memsrch4(op, (int)el, (lastIndex - index));
-                if (p) {
-                    index = p - op + 1;
-                    RETURN ( __MKSMALLINT(index) ); 
-                }
-            }
-#else
+	    if (0) {
+		found0:
+		    RETURN ( __MKSMALLINT(index - nInsts) );
+# if defined(UNROLL_LOOPS)
+		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) );
+# endif /* UNROLL_LOOPS */
+	    }
 
 # if defined(UNROLL_LOOPS)
 	    {
@@ -1704,26 +1810,6 @@
 #endif
 	}
 	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
@@ -1787,14 +1873,13 @@
     }
 
 # ifdef memsrch4
-
     if (index < nIndex) {
-        OBJ *p;
+	OBJ *p;
 
-        p = memsrch4(&(__InstPtr(self)->i_instvars[index]), (int)o, (nIndex - index));
-        if (p) {
-            RETURN ( true );
-        }
+	p = memsrch4(&(__InstPtr(self)->i_instvars[index]), (int)o, (nIndex - index));
+	if (p) {
+	    RETURN ( true );
+	}
     }
 
 # else
@@ -2072,5 +2157,5 @@
 !Array class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Array.st,v 1.83 1997-01-20 21:35:59 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Array.st,v 1.84 1997-01-21 12:53:40 cg Exp $'
 ! !