]> granicus.if.org Git - php/commitdiff
Move builtin_ctzl portability into zend_bitset.h
authorNikita Popov <nikic@php.net>
Tue, 17 May 2016 20:17:22 +0000 (22:17 +0200)
committerNikita Popov <nikic@php.net>
Tue, 17 May 2016 20:23:43 +0000 (22:23 +0200)
Use this function in both zend_mm_bitset_find_one and
zend_bitset_first.

Maybe zend_bitset.h is not quite the right place for it, but I did
not want to include this in a globally included header like
zend_long.h or zend_portability.h.

Zend/zend_alloc.c
Zend/zend_bitset.h

index e7a8e0d2a5121476d2e8b73f2659db96cbbc33fd..a7e3808e7cab0e0122a94436dbb6dac6d91b29c6 100644 (file)
@@ -58,6 +58,7 @@
 #include "zend_globals.h"
 #include "zend_operators.h"
 #include "zend_multiply.h"
+#include "zend_bitset.h"
 
 #ifdef HAVE_SIGNAL_H
 # include <signal.h>
@@ -546,45 +547,6 @@ static zend_always_inline int zend_mm_bitset_nts(zend_mm_bitset bitset)
 #endif
 }
 
-/* number of trailing zero bits (0x01 -> 1; 0x40 -> 6; 0x00 -> LEN) */
-static zend_always_inline int zend_mm_bitset_ntz(zend_mm_bitset bitset)
-{
-#if (defined(__GNUC__) || __has_builtin(__builtin_ctzl)) && SIZEOF_ZEND_LONG == SIZEOF_LONG && defined(PHP_HAVE_BUILTIN_CTZL)
-       return __builtin_ctzl(bitset);
-#elif (defined(__GNUC__) || __has_builtin(__builtin_ctzll)) && defined(PHP_HAVE_BUILTIN_CTZLL)
-       return __builtin_ctzll(bitset);
-#elif defined(_WIN32)
-       unsigned long index;
-
-#if defined(_WIN64)
-       if (!BitScanForward64(&index, bitset)) {
-#else
-       if (!BitScanForward(&index, bitset)) {
-#endif
-               /* undefined behavior */
-               return 32;
-       }
-
-       return (int)index;
-#else
-       int n;
-
-       if (bitset == (zend_mm_bitset)0) return ZEND_MM_BITSET_LEN;
-
-       n = 1;
-#if SIZEOF_ZEND_LONG == 8
-       if (sizeof(zend_mm_bitset) == 8) {
-               if ((bitset & 0xffffffff) == 0) {n += 32; bitset = bitset >> Z_UL(32);}
-       }
-#endif
-       if ((bitset & 0x0000ffff) == 0) {n += 16; bitset = bitset >> 16;}
-       if ((bitset & 0x000000ff) == 0) {n +=  8; bitset = bitset >>  8;}
-       if ((bitset & 0x0000000f) == 0) {n +=  4; bitset = bitset >>  4;}
-       if ((bitset & 0x00000003) == 0) {n +=  2; bitset = bitset >>  2;}
-       return n - (bitset & 1);
-#endif
-}
-
 static zend_always_inline int zend_mm_bitset_find_zero(zend_mm_bitset *bitset, int size)
 {
        int i = 0;
@@ -606,7 +568,7 @@ static zend_always_inline int zend_mm_bitset_find_one(zend_mm_bitset *bitset, in
        do {
                zend_mm_bitset tmp = bitset[i];
                if (tmp != 0) {
-                       return i * ZEND_MM_BITSET_LEN + zend_mm_bitset_ntz(tmp);
+                       return i * ZEND_MM_BITSET_LEN + zend_ulong_ntz(tmp);
                }
                i++;
        } while (i < size);
@@ -941,7 +903,7 @@ static void *zend_mm_alloc_pages(zend_mm_heap *heap, int pages_count ZEND_FILE_L
                                        tmp = *(bitset++);
                                }
                                /* find first 1 bit */
-                               len = (i + zend_mm_bitset_ntz(tmp)) - page_num;
+                               len = (i + zend_ulong_ntz(tmp)) - page_num;
                                if (len >= pages_count) {
                                        goto found;
                                }
@@ -998,7 +960,7 @@ static void *zend_mm_alloc_pages(zend_mm_heap *heap, int pages_count ZEND_FILE_L
                                        tmp = *(bitset++);
                                }
                                /* find first 1 bit */
-                               len = i + zend_mm_bitset_ntz(tmp) - page_num;
+                               len = i + zend_ulong_ntz(tmp) - page_num;
                                if (len >= pages_count) {
                                        if (len == pages_count) {
                                                goto found;
index e1a95466b882e12c1ec589a7e9b797e43a4ff2b1..1b42201a7a25c36fdd5eafd809b36f74eca2da24 100644 (file)
@@ -36,6 +36,47 @@ typedef zend_ulong *zend_bitset;
 # define ZEND_BITSET_BIT_NUM(n)                ((n) % (sizeof(zend_long) * 8))
 #endif
 
+#define ZEND_BITSET_ALLOCA(n, use_heap) \
+       (zend_bitset)do_alloca((n) * ZEND_BITSET_ELM_SIZE, use_heap)
+
+/* Number of trailing zero bits (0x01 -> 0; 0x40 -> 6; 0x00 -> LEN) */
+static zend_always_inline int zend_ulong_ntz(zend_ulong num)
+{
+#if (defined(__GNUC__) || __has_builtin(__builtin_ctzl)) \
+       && SIZEOF_ZEND_LONG == SIZEOF_LONG && defined(PHP_HAVE_BUILTIN_CTZL)
+       return __builtin_ctzl(num);
+#elif (defined(__GNUC__) || __has_builtin(__builtin_ctzll)) && defined(PHP_HAVE_BUILTIN_CTZLL)
+       return __builtin_ctzll(num);
+#elif defined(_WIN32)
+       unsigned long index;
+
+#if defined(_WIN64)
+       if (!BitScanForward64(&index, num)) {
+#else
+       if (!BitScanForward(&index, num)) {
+#endif
+               /* undefined behavior */
+               return 32;
+       }
+
+       return (int) index;
+#else
+       int n;
+
+       if (num == Z_UL(0)) return ZEND_MM_BITSET_LEN;
+
+       n = 1;
+#if SIZEOF_ZEND_LONG == 8
+       if ((num & 0xffffffff) == 0) {n += 32; num = num >> Z_UL(32);}
+#endif
+       if ((num & 0x0000ffff) == 0) {n += 16; num = num >> 16;}
+       if ((num & 0x000000ff) == 0) {n +=  8; num = num >>  8;}
+       if ((num & 0x0000000f) == 0) {n +=  4; num = num >>  4;}
+       if ((num & 0x00000003) == 0) {n +=  2; num = num >>  2;}
+       return n - (num & 1);
+#endif
+}
+
 /* Returns the number of zend_ulong words needed to store a bitset that is N
    bits long.  */
 static inline uint32_t zend_bitset_len(uint32_t n)
@@ -43,9 +84,6 @@ static inline uint32_t zend_bitset_len(uint32_t n)
        return (n + ((sizeof(zend_long) * 8) - 1)) / (sizeof(zend_long) * 8);
 }
 
-#define ZEND_BITSET_ALLOCA(n, use_heap) \
-       (zend_bitset)do_alloca((n) * ZEND_BITSET_ELM_SIZE, use_heap)
-
 static inline zend_bool zend_bitset_in(zend_bitset set, uint32_t n)
 {
        return (set[ZEND_BITSET_ELM_NUM(n)] & (Z_UL(1) << ZEND_BITSET_BIT_NUM(n))) != Z_UL(0);
@@ -155,13 +193,7 @@ static inline int zend_bitset_first(zend_bitset set, uint32_t len)
 
        for (i = 0; i < len; i++) {
                if (set[i]) {
-                       int j = ZEND_BITSET_ELM_SIZE * 8 * i;
-                       zend_ulong x = set[i];
-                       while ((x & Z_UL(1)) == 0) {
-                               x = x >> Z_UL(1);
-                               j++;
-                       }
-                       return j;
+                       return ZEND_BITSET_ELM_SIZE * 8 * i + zend_ulong_ntz(set[i]);
                }
        }
        return -1; /* empty set */