]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Optimize rdataset_getownercase not to use bitshifts
authorOndřej Surý <ondrej@sury.org>
Thu, 20 May 2021 11:01:41 +0000 (13:01 +0200)
committerOndřej Surý <ondrej@sury.org>
Thu, 20 May 2021 18:41:29 +0000 (20:41 +0200)
The last rdataset_getownercase() left it in a state where the code was
mix of microoptimizations (manual loop unrolling, complicated bitshifts)
with a code that would always rewrite the character even if it stayed
the same after transformation.

This commit makes sure that we modify only the characters that actually
need to change, removes the manual loop unrolling, and replaces the
weird bit arithmetics with a simple shift and bit-and.

lib/dns/rbtdb.c

index 6eed090f668918dd7057e6e26a62904b062034ce..4efa16beadcb314190c7615716e633225b2cca39 100644 (file)
@@ -9848,7 +9848,7 @@ setownercase(rdatasetheader_t *header, const dns_name_t *name) {
        memset(header->upper, 0, sizeof(header->upper));
        fully_lower = true;
        for (i = 0; i < name->length; i++) {
-               if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a) {
+               if (name->ndata[i] >= 'A' && name->ndata[i] <= 'Z') {
                        {
                                header->upper[i / 8] |= 1 << (i % 8);
                                fully_lower = false;
@@ -9877,54 +9877,20 @@ rdataset_setownercase(dns_rdataset_t *rdataset, const dns_name_t *name) {
                    isc_rwlocktype_write);
 }
 
-static const unsigned char charmask[] = {
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-       0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
-       0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00
+static const unsigned char maptolower[256] = {
+       ['A'] = 'a', ['B'] = 'b', ['C'] = 'c', ['D'] = 'd', ['E'] = 'e',
+       ['F'] = 'f', ['G'] = 'g', ['H'] = 'h', ['I'] = 'i', ['J'] = 'j',
+       ['K'] = 'k', ['L'] = 'l', ['M'] = 'm', ['N'] = 'n', ['O'] = 'o',
+       ['P'] = 'p', ['Q'] = 'q', ['R'] = 'r', ['S'] = 's', ['T'] = 't',
+       ['U'] = 'u', ['V'] = 'v', ['X'] = 'x', ['Y'] = 'y', ['Z'] = 'z',
 };
 
-static const unsigned char maptolower[] = {
-       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
-       0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
-       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
-       0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
-       0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
-       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73,
-       0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b,
-       0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
-       0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83,
-       0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-       0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
-       0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
-       0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
-       0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-       0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
-       0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
-       0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
-       0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
-       0xfc, 0xfd, 0xfe, 0xff
+static const unsigned char maptoupper[256] = {
+       ['a'] = 'A', ['b'] = 'B', ['c'] = 'C', ['d'] = 'D', ['e'] = 'E',
+       ['f'] = 'F', ['g'] = 'G', ['h'] = 'H', ['i'] = 'I', ['j'] = 'J',
+       ['k'] = 'K', ['l'] = 'L', ['m'] = 'M', ['n'] = 'N', ['o'] = 'O',
+       ['p'] = 'P', ['q'] = 'Q', ['r'] = 'R', ['s'] = 'S', ['t'] = 'T',
+       ['u'] = 'U', ['v'] = 'V', ['x'] = 'X', ['y'] = 'Y', ['z'] = 'Z',
 };
 
 static void
@@ -9932,10 +9898,9 @@ rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
        dns_rbtdb_t *rbtdb = rdataset->private1;
        dns_rbtnode_t *rbtnode = rdataset->private2;
        unsigned char *raw = rdataset->private3; /* RDATASLAB */
-       rdatasetheader_t *header;
-       unsigned int i, j;
-       unsigned char bits;
-       unsigned char c, flip;
+       rdatasetheader_t *header = NULL;
+       uint8_t mask = (1 << 7);
+       uint8_t bits = 0;
 
        header = (struct rdatasetheader *)(raw - sizeof(*header));
 
@@ -9946,85 +9911,36 @@ rdataset_getownercase(const dns_rdataset_t *rdataset, dns_name_t *name) {
                goto unlock;
        }
 
-#if 0
-       /*
-        * This was the original code, and is implemented differently in
-        * the #else block that follows.
-        */
-       for (i = 0; i < name->length; i++) {
-               /*
-                * Set the case bit if it does not match the recorded bit.
-                */
-               if (name->ndata[i] >= 0x61 && name->ndata[i] <= 0x7a &&
-                   (header->upper[i / 8] & (1 << (i % 8))) != 0)
-               {
-                       name->ndata[i] &= ~0x20; /* clear the lower case bit */
-               } else if (name->ndata[i] >= 0x41 && name->ndata[i] <= 0x5a &&
-                          (header->upper[i / 8] & (1 << (i % 8))) == 0)
-               {
-                       name->ndata[i] |= 0x20; /* set the lower case bit */
-               }
-       }
-#else  /* if 0 */
-
        if (ISC_LIKELY(CASEFULLYLOWER(header))) {
-               unsigned char *bp, *be;
-               bp = name->ndata;
-               be = bp + name->length;
-
-               while (bp <= be - 4) {
-                       c = bp[0];
-                       bp[0] = maptolower[c];
-                       c = bp[1];
-                       bp[1] = maptolower[c];
-                       c = bp[2];
-                       bp[2] = maptolower[c];
-                       c = bp[3];
-                       bp[3] = maptolower[c];
-                       bp += 4;
-               }
-               while (bp < be) {
-                       c = *bp;
-                       *bp++ = maptolower[c];
+               for (size_t i = 0; i < name->length; i++) {
+                       uint8_t c = name->ndata[i];
+                       if (c >= 'A' && c <= 'Z') {
+                               name->ndata[i] = maptolower[c];
+                       }
                }
-               goto unlock;
-       }
-
-       i = 0;
-       for (j = 0; j < (name->length >> 3); j++) {
-               unsigned int k;
-
-               bits = ~(header->upper[j]);
+       } else {
+               for (size_t i = 0; i < name->length; i++) {
+                       uint8_t c = name->ndata[i];
 
-               for (k = 0; k < 8; k++) {
-                       c = name->ndata[i];
-                       flip = (bits & 1) << 5;
-                       flip ^= c;
-                       flip &= charmask[c];
-                       name->ndata[i] ^= flip;
+                       if (mask == (1 << 7)) {
+                               bits = header->upper[i / 8];
+                               mask = 1;
+                       } else {
+                               mask <<= 1;
+                       }
 
-                       i++;
-                       bits >>= 1;
+                       if (c >= 'a' && c <= 'z') {
+                               if ((bits & mask) != 0) {
+                                       name->ndata[i] = maptoupper[c];
+                               }
+                       } else if (c >= 'A' && c <= 'Z') {
+                               if ((bits & mask) == 0) {
+                                       name->ndata[i] = maptolower[c];
+                               }
+                       }
                }
        }
 
-       if (ISC_UNLIKELY(i == name->length)) {
-               goto unlock;
-       }
-
-       bits = ~(header->upper[j]);
-
-       for (; i < name->length; i++) {
-               c = name->ndata[i];
-               flip = (bits & 1) << 5;
-               flip ^= c;
-               flip &= charmask[c];
-               name->ndata[i] ^= flip;
-
-               bits >>= 1;
-       }
-#endif /* if 0 */
-
 unlock:
        NODE_UNLOCK(&rbtdb->node_locks[rbtnode->locknum].lock,
                    isc_rwlocktype_read);