2021 REGISTER OBJ *op; |
2021 REGISTER OBJ *op; |
2022 REGISTER unsigned INT nIndex; |
2022 REGISTER unsigned INT nIndex; |
2023 INT nInsts; |
2023 INT nInsts; |
2024 |
2024 |
2025 if (__isSmallInteger(start)) { |
2025 if (__isSmallInteger(start)) { |
2026 index = __intVal(start) - 1; |
2026 index = __intVal(start) - 1; |
2027 if (index >= 0) { |
2027 if (index >= 0) { |
2028 nInsts = __intVal(__ClassInstPtr(__qClass(self))->c_ninstvars); |
2028 nInsts = __intVal(__ClassInstPtr(__qClass(self))->c_ninstvars); |
2029 index += nInsts; |
2029 index += nInsts; |
2030 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
2030 nIndex = __BYTES2OBJS__(__qSize(self) - OHDR_SIZE); |
2031 el = anElement; |
2031 el = anElement; |
2032 op = & (__InstPtr(self)->i_instvars[index]); |
2032 op = & (__InstPtr(self)->i_instvars[index]); |
2033 |
2033 |
2034 #if defined(memsrch4) |
2034 #if defined(memsrch4) |
2035 if (index < nIndex) { |
2035 if (index < nIndex) { |
2036 OBJ *p; |
2036 OBJ *p; |
2037 |
2037 |
2038 p = memsrch4(op, (INT)el, (nIndex - index)); |
2038 p = memsrch4(op, (INT)el, (nIndex - index)); |
2039 if (p) { |
2039 if (p) { |
2040 index += (p - op + 1); |
2040 index += (p - op + 1); |
2041 RETURN ( __mkSmallInteger(index) ); |
2041 RETURN ( __mkSmallInteger(index) ); |
2042 } |
2042 } |
2043 } |
2043 } |
2044 #else |
2044 #else |
2045 |
2045 |
2046 # ifdef __UNROLL_LOOPS__ |
2046 # ifdef __UNROLL_LOOPS__ |
2047 { |
2047 { |
2048 /* |
2048 /* |
2049 * don't argue about those gotos below - they speed up that thing by 30%; |
2049 * don't argue about those gotos below - they speed up that thing by 30%; |
2050 * its better to exit the loops below with a goto, |
2050 * its better to exit the loops below with a goto, |
2051 * since the generated code will then be: |
2051 * since the generated code will then be: |
2052 * compare |
2052 * compare |
2053 * branch-on-equal found |
2053 * branch-on-equal found |
2054 * |
2054 * |
2055 * otherwise (with ret as if-statement), we get: |
2055 * otherwise (with ret as if-statement), we get: |
2056 * compare |
2056 * compare |
2057 * branch-on-not-equal skipLabel |
2057 * branch-on-not-equal skipLabel |
2058 * move-to-ret-register true |
2058 * move-to-ret-register true |
2059 * goto ret-label |
2059 * goto ret-label |
2060 * skipLabel |
2060 * skipLabel |
2061 * |
2061 * |
2062 * therefore, WITH the so-much-blamed goto, we only branch |
2062 * therefore, WITH the so-much-blamed goto, we only branch |
2063 * when found; without the goto, we branch always. |
2063 * when found; without the goto, we branch always. |
2064 * Pipelined CPUs do usually not like taken branches. |
2064 * Pipelined CPUs do usually not like taken branches. |
2065 */ |
2065 */ |
2066 |
2066 |
2067 unsigned INT i8; |
2067 unsigned INT i8; |
2068 |
2068 |
2069 while ((i8 = index + 8) < nIndex) { |
2069 while ((i8 = index + 8) < nIndex) { |
2070 if (op[0] == el) goto found1; |
2070 if (op[0] == el) goto found1; |
2071 if (op[1] == el) goto found2; |
2071 if (op[1] == el) goto found2; |
2072 if (op[2] == el) goto found3; |
2072 if (op[2] == el) goto found3; |
2073 if (op[3] == el) goto found4; |
2073 if (op[3] == el) goto found4; |
2074 if (op[4] == el) goto found5; |
2074 if (op[4] == el) goto found5; |
2075 if (op[5] == el) goto found6; |
2075 if (op[5] == el) goto found6; |
2076 if (op[6] == el) goto found7; |
2076 if (op[6] == el) goto found7; |
2077 if (op[7] == el) goto found8; |
2077 if (op[7] == el) goto found8; |
2078 index = i8; |
2078 index = i8; |
2079 op += 8; |
2079 op += 8; |
2080 } |
2080 } |
2081 if (0) { |
2081 if (0) { |
2082 found1: |
2082 found1: |
2083 RETURN ( __mkSmallInteger(index + 1 - nInsts) ); |
2083 RETURN ( __mkSmallInteger(index + 1 - nInsts) ); |
2084 found2: |
2084 found2: |
2085 RETURN ( __mkSmallInteger(index + 2 - nInsts) ); |
2085 RETURN ( __mkSmallInteger(index + 2 - nInsts) ); |
2086 found3: |
2086 found3: |
2087 RETURN ( __mkSmallInteger(index + 3 - nInsts) ); |
2087 RETURN ( __mkSmallInteger(index + 3 - nInsts) ); |
2088 found4: |
2088 found4: |
2089 RETURN ( __mkSmallInteger(index + 4 - nInsts) ); |
2089 RETURN ( __mkSmallInteger(index + 4 - nInsts) ); |
2090 found5: |
2090 found5: |
2091 RETURN ( __mkSmallInteger(index + 5 - nInsts) ); |
2091 RETURN ( __mkSmallInteger(index + 5 - nInsts) ); |
2092 found6: |
2092 found6: |
2093 RETURN ( __mkSmallInteger(index + 6 - nInsts) ); |
2093 RETURN ( __mkSmallInteger(index + 6 - nInsts) ); |
2094 found7: |
2094 found7: |
2095 RETURN ( __mkSmallInteger(index + 7 - nInsts) ); |
2095 RETURN ( __mkSmallInteger(index + 7 - nInsts) ); |
2096 found8: |
2096 found8: |
2097 RETURN ( __mkSmallInteger(index + 8 - nInsts) ); |
2097 RETURN ( __mkSmallInteger(index + 8 - nInsts) ); |
2098 } |
2098 } |
2099 } |
2099 } |
2100 # endif /* __UNROLLED_LOOPS__ */ |
2100 # endif /* __UNROLLED_LOOPS__ */ |
2101 |
2101 |
2102 while (index++ < nIndex) { |
2102 while (index++ < nIndex) { |
2103 if (*op++ == el) goto found0; |
2103 if (*op++ == el) goto found0; |
2104 } |
2104 } |
2105 |
2105 |
2106 if (0) { |
2106 if (0) { |
2107 found0: |
2107 found0: |
2108 RETURN ( __mkSmallInteger(index - nInsts) ); |
2108 RETURN ( __mkSmallInteger(index - nInsts) ); |
2109 } |
2109 } |
2110 #endif /* no memsrch */ |
2110 #endif /* no memsrch */ |
2111 } |
2111 } |
2112 RETURN ( __mkSmallInteger(0) ); |
2112 RETURN ( __mkSmallInteger(0) ); |
2113 } |
2113 } |
2114 %}. |
2114 %}. |
2115 ^ super identityIndexOf:anElement startingAt:start |
2115 ^ super identityIndexOf:anElement startingAt:start |
2116 ! |
2116 ! |
2117 |
2117 |
2554 * also, all branches are forward, which are usually predicted |
2554 * also, all branches are forward, which are usually predicted |
2555 * as not taken. |
2555 * as not taken. |
2556 */ |
2556 */ |
2557 # ifdef __UNROLL_LOOPS__ |
2557 # ifdef __UNROLL_LOOPS__ |
2558 { |
2558 { |
2559 unsigned INT i8; |
2559 unsigned INT i8; |
2560 REGISTER OBJ slf = self; |
2560 REGISTER OBJ slf = self; |
2561 |
2561 |
2562 while ((i8 = index + 8) < nIndex) { |
2562 while ((i8 = index + 8) < nIndex) { |
2563 if (__InstPtr(slf)->i_instvars[index] == o) goto found; |
2563 if (__InstPtr(slf)->i_instvars[index] == o) goto found; |
2564 if (__InstPtr(slf)->i_instvars[index+1] == o) goto found; |
2564 if (__InstPtr(slf)->i_instvars[index+1] == o) goto found; |
2565 if (__InstPtr(slf)->i_instvars[index+2] == o) goto found; |
2565 if (__InstPtr(slf)->i_instvars[index+2] == o) goto found; |
2566 if (__InstPtr(slf)->i_instvars[index+3] == o) goto found; |
2566 if (__InstPtr(slf)->i_instvars[index+3] == o) goto found; |
2567 if (__InstPtr(slf)->i_instvars[index+4] == o) goto found; |
2567 if (__InstPtr(slf)->i_instvars[index+4] == o) goto found; |
2568 if (__InstPtr(slf)->i_instvars[index+5] == o) goto found; |
2568 if (__InstPtr(slf)->i_instvars[index+5] == o) goto found; |
2569 if (__InstPtr(slf)->i_instvars[index+6] == o) goto found; |
2569 if (__InstPtr(slf)->i_instvars[index+6] == o) goto found; |
2570 if (__InstPtr(slf)->i_instvars[index+7] == o) goto found; |
2570 if (__InstPtr(slf)->i_instvars[index+7] == o) goto found; |
2571 index = i8; |
2571 index = i8; |
2572 } |
2572 } |
2573 } |
2573 } |
2574 # endif /* __UNROLL_LOOPS__ */ |
2574 # endif /* __UNROLL_LOOPS__ */ |
2575 |
2575 |
2576 while (index < nIndex) { |
2576 while (index < nIndex) { |
2577 if (__InstPtr(self)->i_instvars[index++] == o) goto found; |
2577 if (__InstPtr(self)->i_instvars[index++] == o) goto found; |
2578 } |
2578 } |
2579 if (0) { |
2579 if (0) { |
2580 found: |
2580 found: |
2581 RETURN (true); |
2581 RETURN (true); |
2582 } |
2582 } |
2583 |
2583 |
2584 # endif /* no memsrch */ |
2584 # endif /* no memsrch */ |
2585 |
2585 |
2586 if (o == nil) { |
2586 if (o == nil) { |
2587 RETURN ( false ); |
2587 RETURN ( false ); |
2588 } |
2588 } |
2589 %}. |
2589 %}. |
2590 |
2590 |
2591 %{ |
2591 %{ |
2592 REGISTER INT index; |
2592 REGISTER INT index; |