--- 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 $'
! !