mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 06:25:31 +00:00
Optimize rdataset_getownercase not to use bitshifts
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.
This commit is contained in:
162
lib/dns/rbtdb.c
162
lib/dns/rbtdb.c
@@ -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;
|
||||
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];
|
||||
}
|
||||
}
|
||||
while (bp < be) {
|
||||
c = *bp;
|
||||
*bp++ = maptolower[c];
|
||||
}
|
||||
goto unlock;
|
||||
}
|
||||
} else {
|
||||
for (size_t i = 0; i < name->length; i++) {
|
||||
uint8_t c = name->ndata[i];
|
||||
|
||||
i = 0;
|
||||
for (j = 0; j < (name->length >> 3); j++) {
|
||||
unsigned int k;
|
||||
if (mask == (1 << 7)) {
|
||||
bits = header->upper[i / 8];
|
||||
mask = 1;
|
||||
} else {
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
bits = ~(header->upper[j]);
|
||||
|
||||
for (k = 0; k < 8; k++) {
|
||||
c = name->ndata[i];
|
||||
flip = (bits & 1) << 5;
|
||||
flip ^= c;
|
||||
flip &= charmask[c];
|
||||
name->ndata[i] ^= flip;
|
||||
|
||||
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);
|
||||
|
Reference in New Issue
Block a user