Commit 5ee9edc4 authored by Ondřej Surý's avatar Ondřej Surý
Browse files

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.
parent e31cc1ee
Pipeline #72209 failed with stages
in 37 minutes and 40 seconds
......@@ -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);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment