Array.st
changeset 2185 790f4c380343
parent 2184 f25db3e10530
child 2202 a3432984bb95
--- a/Array.st	Fri Jan 17 00:57:14 1997 +0100
+++ b/Array.st	Fri Jan 17 15:41:40 1997 +0100
@@ -354,8 +354,7 @@
 	    RETURN ( __InstPtr(slf)->i_instvars[indx] );
 	}
     }
-%}
-.
+%}.
     ^ super basicAt:index
 !
 
@@ -388,8 +387,7 @@
             RETURN ( anObject );
         }
     }
-%}
-.
+%}.
     ^ super basicAt:index put:anObject
 
     "Modified: 19.4.1996 / 11:14:26 / cg"
@@ -501,8 +499,7 @@
 	    RETURN ( nObj );
 	}
     }
-%}
-.
+%}.
     ^ super copyWith:something
 ! !
 
@@ -545,64 +542,97 @@
         if (nIndex <= actualSize) {
 
             if (__isBlockLike(aBlock)
-             && ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
              && (__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
-	        for (; index < nIndex; index++) {
-	            if (InterruptPending != nil) __interruptL(@line);
-
-	            (*codeVal)(aBlock, __InstPtr(self)->i_instvars[index]);
-	        } 
+#		        define BLOCK_ARG        aBlock
 #else
-	        home = __BlockInstPtr(aBlock)->b_home;
-	        rHome = home;
-	        if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) {
-	            /*
-	             * home will not move - keep in a fast register
-	             */
-# if defined(UNROLL_LOOPS)
-	            {
-		        int i4;
+#		        define BLOCK_ARG	rHome
+                        REGISTER OBJ rHome;
+
+                        rHome = __BlockInstPtr(aBlock)->b_home;
+		        if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
+#endif
+		        {
+			    for (; index < nIndex; 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
+#               define IBLOCK_ARG       nil
+#else
+#               define BLOCK_ARG        (__BlockInstPtr(aBlock)->b_home)
+#               define IBLOCK_ARG       (__BlockInstPtr(aBlock)->b_home)
+#endif
+
+	        for (; index < nIndex; index++) {
+		    REGISTER OBJFUNC codeVal;
+
+		    if (InterruptPending != nil) __interruptL(@line);
 
-		        while ((i4 = index+4) < nIndex) {
-		            if (InterruptPending != nil) __interruptL(@line);
-		            (*codeVal)(rHome, __InstPtr(self)->i_instvars[index]);
-		            if (InterruptPending != nil) __interruptL(@line);
-		            (*codeVal)(rHome, __InstPtr(self)->i_instvars[index+1]);
-		            if (InterruptPending != nil) __interruptL(@line);
-		            (*codeVal)(rHome, __InstPtr(self)->i_instvars[index+2]);
-		            if (InterruptPending != nil) __interruptL(@line);
-		            (*codeVal)(rHome, __InstPtr(self)->i_instvars[index+3]);
-		            index = i4;
+		    if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
+		        (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+		    } else {
+		        if (__BlockInstPtr(aBlock)->b_bytecodes != nil) {
+			    /*
+			     * arg is a compiled block with bytecode -
+			     * directly call interpreter without going through Block>>value
+			     */
+#ifdef PASS_ARG_POINTER
+			    __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &(__InstPtr(self)->i_instvars[index]));
+#else
+			    __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, __InstPtr(self)->i_instvars[index]);
+#endif
+		        } else {
+	                    (*val.ilc_func)(aBlock, 
+			                    @symbol(value:), 
+			                    nil, &val, 
+			                    __InstPtr(self)->i_instvars[index]);
 		        }
-	            }
-# endif
-	            for (; index < nIndex; index++) {
-		        if (InterruptPending != nil) __interruptL(@line);
+		    }
+		}
 
-		        (*codeVal)(rHome, __InstPtr(self)->i_instvars[index]);
-	            } 
-	        } else {
-	            for (; index < nIndex; index++) {
-		        if (InterruptPending != nil) __interruptL(@line);
+#		undef BLOCK_ARG
+#		undef IBLOCK_ARG
+
+	        RETURN (self );
+            }
+
+            /*
+             * not a block - send it #value:
+             */
+            for (; index < nIndex; index++) {
+	        if (InterruptPending != nil) __interruptL(@line);
 
-		        (*codeVal)(home, __InstPtr(self)->i_instvars[index]);
-	            } 
-	        } 
-#endif
-            } else {
-	        for (; index < nIndex; index++) {
-	            if (InterruptPending != nil) __interruptL(@line);
-
-	            (*val.ilc_func)(aBlock, 
-			            @symbol(value:), 
-			            nil, &val, 
-			            __InstPtr(self)->i_instvars[index]);
-	        } 
+	        (*val.ilc_func)(aBlock, 
+			        @symbol(value:), 
+			        nil, &val, 
+			        __InstPtr(self)->i_instvars[index]);
             }
-	    RETURN (self );
-        }
+	    RETURN ( self );
+	}
     }
+    /* 
+     * I am something, not handle here
+     */
 %}.
     ^ super do:aBlock
 !
@@ -626,71 +656,106 @@
     slf = self;
     myClass = __qClass(slf);
     if (! ((INT)( __ClassInstPtr(myClass)->c_flags) & __MASKSMALLINT(WKPOINTERARRAY))
-     && __bothSmallInteger(start, stop)) {
-	indexLow = __intVal(start);
-	if (indexLow > 0) {
-	    indexHigh = __intVal(stop);
-	    nIndex = __BYTES2OBJS__(__qSize(slf) - OHDR_SIZE);
-	    if (myClass != @global(Array)) {
-		nInsts = __intVal(__ClassInstPtr(myClass)->c_ninstvars);
-		indexLow += nInsts;
-		indexHigh += nInsts;
-	    }
-	    if (indexHigh <= nIndex) {
-		indexLow--;
-		indexHigh--;
-		if (__isBlockLike(aBlock)
-		 && ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
-		 && (__BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) {
+     && __bothSmallInteger(start, stop)
+     && ((indexLow = __intVal(start)) > 0)) {
+	indexHigh = __intVal(stop);
+	nIndex = __BYTES2OBJS__(__qSize(slf) - OHDR_SIZE);
+	if (myClass != @global(Array)) {
+	    nInsts = __intVal(__ClassInstPtr(myClass)->c_ninstvars);
+	    indexLow += nInsts;
+	    indexHigh += nInsts;
+	}
+	if (indexHigh <= nIndex) {
+	    indexLow--;
+	    indexHigh--;
+
+	    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
-		    for (index=indexLow; index <= indexHigh; index++) {
-			if (InterruptPending != nil) __interruptL(@line);
-			(*codeVal)(aBlock, __InstPtr(self)->i_instvars[index]);
-		    } 
+#                       define BLOCK_ARG        aBlock
 #else
-		    home = __BlockInstPtr(aBlock)->b_home;
-		    rHome = home;
-		    if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) {
-			index = indexLow;
-# if defined(UNROLL_LOOPS)
-			{
-			    int i4;
+#                       define BLOCK_ARG        rHome
+                        REGISTER OBJ rHome;
+
+                        rHome = __BlockInstPtr(aBlock)->b_home;
+                        if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
+#endif
+                        {
+                            for (; index < nIndex; index++) {
+                                if (InterruptPending != nil) __interruptL(@line);
+
+                                (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+                            }
+                            RETURN (self);
+                        }
+                    }
+                }
 
-			    while ((i4 = index+4) <= indexHigh) {
-				if (InterruptPending != nil) __interruptL(@line);
-				(*codeVal)(rHome, __InstPtr(self)->i_instvars[index]);
-				if (InterruptPending != nil) __interruptL(@line);
-				(*codeVal)(rHome, __InstPtr(self)->i_instvars[index+1]);
-				if (InterruptPending != nil) __interruptL(@line);
-				(*codeVal)(rHome, __InstPtr(self)->i_instvars[index+2]);
-				if (InterruptPending != nil) __interruptL(@line);
-				(*codeVal)(rHome, __InstPtr(self)->i_instvars[index+3]);
-				index = i4;
-			    }
-			}
-# endif
-			for (; index <= indexHigh; index++) {
-			    if (InterruptPending != nil) __interruptL(@line);
-			    (*codeVal)(rHome, __InstPtr(self)->i_instvars[index]);
-			} 
-		    } else {
-			for (index=indexLow; index <= indexHigh; index++) {
-			    if (InterruptPending != nil) __interruptL(@line);
-			    (*codeVal)(home, __InstPtr(self)->i_instvars[index]);
-			} 
-		    }
+                /*
+                 * 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
+#               define IBLOCK_ARG       nil
+#else
+#               define BLOCK_ARG        (__BlockInstPtr(aBlock)->b_home)
+#               define IBLOCK_ARG       (__BlockInstPtr(aBlock)->b_home)
 #endif
-		} else {
-		    for (index=indexLow; index <= indexHigh; index++) {
-			if (InterruptPending != nil) __interruptL(@line);
-			(*val.ilc_func) (aBlock, 
-					 @symbol(value:), 
-					 nil, &val, 
-					 __InstPtr(self)->i_instvars[index]);
-		    } 
-		}
-	    }
-	    RETURN ( self );
+
+                for (; index < nIndex; index++) {
+                    REGISTER OBJFUNC codeVal;
+
+                    if (InterruptPending != nil) __interruptL(@line);
+
+                    if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
+                        (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+                    } else {
+                        if (__BlockInstPtr(aBlock)->b_bytecodes != nil) {
+                            /*
+                             * arg is a compiled block with bytecode -
+                             * directly call interpreter without going through Block>>value
+                             */
+#ifdef PASS_ARG_POINTER
+                            __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &(__InstPtr(self)->i_instvars[index]));
+#else
+                            __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, __InstPtr(self)->i_instvars[index]);
+#endif
+                        } else {
+                            (*val.ilc_func)(aBlock, 
+                                            @symbol(value:), 
+                                            nil, &val, 
+                                            __InstPtr(self)->i_instvars[index]);
+                        }
+                    }
+                }
+
+#		undef BLOCK_ARG
+#		undef IBLOCK_ARG
+
+                RETURN (self );
+            }
+
+            /*
+             * not a block - send it #value:
+             */
+            for (; index < nIndex; index++) {
+                if (InterruptPending != nil) __interruptL(@line);
+
+                (*val.ilc_func)(aBlock, 
+                                @symbol(value:), 
+                                nil, &val, 
+                                __InstPtr(self)->i_instvars[index]);
+            }
+            RETURN ( self );
 	}
     }
 %}.
@@ -712,49 +777,102 @@
     int indexLow, indexHigh;
 
     if (__bothSmallInteger(start, stop)
-     && (__qClass(self) == @global(Array))) {
-	indexLow = __intVal(start);
-	if (indexLow > 0) {
-	    indexHigh = __intVal(stop);
-	    nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
-	    if (indexHigh <= nIndex) {
-		indexLow--;
-		indexHigh--;
-		if (__isBlockLike(aBlock)
-		 && ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
-		 && (__BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(1))) {
+     && (__qClass(self) == @global(Array))
+     && ((indexLow = __intVal(start)) > 0)) {
+	indexHigh = __intVal(stop);
+	nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
+	if (indexHigh <= nIndex) {
+	    indexLow--;
+	    indexHigh--;
+
+	    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
-		    for (index=indexHigh; index >= indexLow; index--) {
-			if (InterruptPending != nil) __interruptL(@line);
-			(*codeVal)(aBlock, __InstPtr(self)->i_instvars[index]);
-		    } 
+#                       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
+#               define IBLOCK_ARG       nil
 #else
-		    home = __BlockInstPtr(aBlock)->b_home;
-		    rHome = home;
-		    if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) {
-			for (index=indexHigh; index >= indexLow; index--) {
-			    if (InterruptPending != nil) __interruptL(@line);
-			    (*codeVal)(rHome, __InstPtr(self)->i_instvars[index]);
-			} 
-		    } else {
-			for (index=indexHigh; index >= indexLow; index--) {
-			    if (InterruptPending != nil) __interruptL(@line);
-			    (*codeVal)(home, __InstPtr(self)->i_instvars[index]);
-			} 
-		    }
+#               define BLOCK_ARG        (__BlockInstPtr(aBlock)->b_home)
+#               define IBLOCK_ARG       (__BlockInstPtr(aBlock)->b_home)
+#endif
+
+		for (index=indexHigh; index >= indexLow; index--) {
+                    REGISTER OBJFUNC codeVal;
+
+                    if (InterruptPending != nil) __interruptL(@line);
+
+                    if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
+                        (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+                    } else {
+                        if (__BlockInstPtr(aBlock)->b_bytecodes != nil) {
+                            /*
+                             * arg is a compiled block with bytecode -
+                             * directly call interpreter without going through Block>>value
+                             */
+#ifdef PASS_ARG_POINTER
+                            __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &(__InstPtr(self)->i_instvars[index]));
+#else
+                            __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, __InstPtr(self)->i_instvars[index]);
 #endif
-		} else {
-		    for (index=indexHigh; index >= indexLow; index--) {
-			if (InterruptPending != nil) __interruptL(@line);
-			(*val.ilc_func) (aBlock, 
-					 @symbol(value:), 
-					 nil, &val, 
-					 __InstPtr(self)->i_instvars[index]);
-		    } 
-		}
-	    }
-	    RETURN ( self );
-	}
+                        } else {
+                            (*val.ilc_func)(aBlock, 
+                                            @symbol(value:), 
+                                            nil, &val, 
+                                            __InstPtr(self)->i_instvars[index]);
+                        }
+                    }
+                }
+
+#		undef BLOCK_ARG
+#		undef IBLOCK_ARG
+
+                RETURN (self );
+            }
+
+            /*
+             * not a block - send it #value:
+             */
+	    for (index=indexHigh; index >= indexLow; index--) {
+                if (InterruptPending != nil) __interruptL(@line);
+
+                (*val.ilc_func)(aBlock, 
+                                @symbol(value:), 
+                                nil, &val, 
+                                __InstPtr(self)->i_instvars[index]);
+            }
+            RETURN ( self );
+        }
     }
 %}.
     ^ super from:start to:stop reverseDo:aBlock
@@ -786,52 +904,104 @@
 
         if (nIndex <= actualSize) {
             if (__isBlockLike(aBlock)
-             && ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
              && (__BlockInstPtr(aBlock)->b_nargs == __MKSMALLINT(2))) {
+                {
+                    /*
+                     * 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
-	        for (; index < nIndex; index++) {
-	            if (InterruptPending != nil) __interruptL(@line);
+#                       define BLOCK_ARG        aBlock
+#else
+#                       define BLOCK_ARG        rHome
+                        REGISTER OBJ rHome;
+
+                        rHome = __BlockInstPtr(aBlock)->b_home;
+                        if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE))
+#endif
+                        {
+                            while (index < nIndex) {
+				index++;
+                                if (InterruptPending != nil) __interruptL(@line);
 
-	            (*codeVal)(aBlock, __MKSMALLINT(index+1),
-					          __InstPtr(self)->i_instvars[index]);
-	        } 
+                                (*codeVal)(BLOCK_ARG, __MKSMALLINT(index), __InstPtr(self)->i_instvars[index-1]);
+                            }
+                            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
+#               define IBLOCK_ARG       nil
 #else
-	        home = __BlockInstPtr(aBlock)->b_home;
-	        rHome = home;
-	        if ((rHome == nil) || (__qSpace(rHome) >= STACKSPACE)) {
-	            /*
-	             * home will not move - keep in a fast register
-	             */
-	            while (index < nIndex) {
-		        if (InterruptPending != nil) __interruptL(@line);
+#               define BLOCK_ARG        (__BlockInstPtr(aBlock)->b_home)
+#               define IBLOCK_ARG       (__BlockInstPtr(aBlock)->b_home)
+#endif
+
+                while (index < nIndex) {
+                    REGISTER OBJFUNC codeVal;
+
+                    if (InterruptPending != nil) __interruptL(@line);
 
-		        index++;
-		        (*codeVal)(rHome, __MKSMALLINT(index),
-					             __InstPtr(self)->i_instvars[index-1]);
-	            } 
-	        } else {
-	            while (index < nIndex) {
-		        if (InterruptPending != nil) __interruptL(@line);
+		    index++;
+                    if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
+                        (*codeVal)(BLOCK_ARG, __MKSMALLINT(index), __InstPtr(self)->i_instvars[index-1]);
+                    } else {
+                        if (__BlockInstPtr(aBlock)->b_bytecodes != nil) {
+                            /*
+                             * arg is a compiled block with bytecode -
+                             * directly call interpreter without going through Block>>value
+                             */
+#ifdef PASS_ARG_POINTER
+			    {
+				OBJ t[2];
 
-		        index++;
-		        (*codeVal)(home, __MKSMALLINT(index),
-					            __InstPtr(self)->i_instvars[index-1]);
-	            } 
-	        } 
+				t[0] = __MKSMALLINT(index);
+				t[1] = __InstPtr(self)->i_instvars[index-1];
+
+                                __interpret(aBlock, 2, nil, IBLOCK_ARG, nil, nil, t);
+			    }
+#else
+                            __interpret(aBlock, 2, nil, IBLOCK_ARG, nil, nil, __MKSMALLINT(index), __InstPtr(self)->i_instvars[index-1]);
 #endif
-            } else {
-	        while (index < nIndex) {
-	            if (InterruptPending != nil) __interruptL(@line);
+                        } else {
+                            (*val2.ilc_func)(aBlock, 
+                                            @symbol(value:value:), 
+                                            nil, &val2, 
+					    __MKSMALLINT(index),
+                                            __InstPtr(self)->i_instvars[index-1]);
+                        }
+                    }
+                }
+
+#		undef BLOCK_ARG
+#		undef IBLOCK_ARG
 
-	            index++;
-	            (*val2.ilc_func)(aBlock, 
-			            @symbol(value:value:), 
-			            nil, &val2,
-			            __MKSMALLINT(index),
-			            __InstPtr(self)->i_instvars[index-1]);
-	        } 
+                RETURN (self );
             }
-	    RETURN (self);
+
+            /*
+             * not a block - send it #value:
+             */
+            while (index < nIndex) {
+                if (InterruptPending != nil) __interruptL(@line);
+
+		index++;
+                (*val2.ilc_func)(aBlock, 
+                                @symbol(value:value:), 
+                                nil, &val2, 
+				__MKSMALLINT(index),
+                                __InstPtr(self)->i_instvars[index-1]);
+            }
+            RETURN ( self );
 	}
     }
 %}.
@@ -862,30 +1032,92 @@
 
         if (nIndex <= actualSize) {
             if (__isBlockLike(aBlock)
-             && ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil)
              && (__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
-	        for (index=nIndex-1; index >= endIndex; index--) {
-	            if (InterruptPending != nil) __interruptL(@line);
-	            (*codeVal)(aBlock, __InstPtr(self)->i_instvars[index]);
-	        } 
+#                       define BLOCK_ARG        aBlock
 #else
-	        home = __BlockInstPtr(aBlock)->b_home;
+#                       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
+#               define IBLOCK_ARG       nil
+#else
+#               define BLOCK_ARG        (__BlockInstPtr(aBlock)->b_home)
+#               define IBLOCK_ARG       (__BlockInstPtr(aBlock)->b_home)
+#endif
+
 	        for (index=nIndex-1; index >= endIndex; index--) {
-	            if (InterruptPending != nil) __interruptL(@line);
-	            (*codeVal)(home, __InstPtr(self)->i_instvars[index]);
-	        } 
+                    REGISTER OBJFUNC codeVal;
+
+                    if (InterruptPending != nil) __interruptL(@line);
+
+                    if ((codeVal = __BlockInstPtr(aBlock)->b_code) != (OBJFUNC)nil) {
+                        (*codeVal)(BLOCK_ARG, __InstPtr(self)->i_instvars[index]);
+                    } else {
+                        if (__BlockInstPtr(aBlock)->b_bytecodes != nil) {
+                            /*
+                             * arg is a compiled block with bytecode -
+                             * directly call interpreter without going through Block>>value
+                             */
+#ifdef PASS_ARG_POINTER
+                            __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, &(__InstPtr(self)->i_instvars[index]));
+#else
+                            __interpret(aBlock, 1, nil, IBLOCK_ARG, nil, nil, __InstPtr(self)->i_instvars[index]);
 #endif
-            } else {
-	        for (index=nIndex-1; index >= endIndex; index--) {
-	            if (InterruptPending != nil) __interruptL(@line);
-	            (*val.ilc_func)(aBlock, 
-			            @symbol(value:), 
-			            nil, &val, 
-			            __InstPtr(self)->i_instvars[index]);
-	        } 
-	    }
-	    RETURN (self);
+                        } else {
+                            (*val.ilc_func)(aBlock, 
+                                            @symbol(value:), 
+                                            nil, &val, 
+                                            __InstPtr(self)->i_instvars[index]);
+                        }
+                    }
+                }
+
+#		undef BLOCK_ARG
+#		undef IBLOCK_ARG
+
+                RETURN (self );
+            }
+
+            /*
+             * not a block - send it #value:
+             */
+	    for (index=nIndex-1; index >= endIndex; index--) {
+                if (InterruptPending != nil) __interruptL(@line);
+
+                (*val.ilc_func)(aBlock, 
+                                @symbol(value:), 
+                                nil, &val, 
+                                __InstPtr(self)->i_instvars[index]);
+            }
+            RETURN ( self );
 	}
     }
 %}.
@@ -943,6 +1175,7 @@
 	if (index >= 0) {
 	    nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE);
 	    endIndex = __intVal(index2) - 1;
+
 	    if ((endIndex >= index) && (endIndex < nIndex)) {
 		dst = &(__InstPtr(self)->i_instvars[index]);
 #ifdef memset4
@@ -1339,7 +1572,7 @@
              *
              * 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.
+             * Pipelined CPUs do usually not like taken branches.
              */
 
 #if defined(UNROLL_LOOPS)
@@ -1793,5 +2026,5 @@
 !Array class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic/Array.st,v 1.78 1997-01-16 23:57:14 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic/Array.st,v 1.79 1997-01-17 14:41:40 cg Exp $'
 ! !