diff options
author | drh <> | 2021-03-28 23:37:56 +0000 |
---|---|---|
committer | drh <> | 2021-03-28 23:37:56 +0000 |
commit | 1af3fd562fc26c0aaf2bc5c6b3b6097ae17d4abb (patch) | |
tree | 8f429c4e4ebec6b8ed5aa44fe0a84f8cd20838c6 /src | |
parent | 9cffb0ffb9b393e1231496d88a3d488e0f877183 (diff) | |
download | sqlite-1af3fd562fc26c0aaf2bc5c6b3b6097ae17d4abb.tar.gz sqlite-1af3fd562fc26c0aaf2bc5c6b3b6097ae17d4abb.zip |
Alternative implementation of the comparison opcode speed-up of
check-in [4a8805d9a66dc888] that should pass muster with UBSAN.
FossilOrigin-Name: afb18f64541effaeaada2d72c7c91adfe5ec3e2b1418c0bc281083125fb5badb
Diffstat (limited to 'src')
-rw-r--r-- | src/global.c | 30 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/vdbe.c | 11 |
3 files changed, 36 insertions, 8 deletions
diff --git a/src/global.c b/src/global.c index b5239ad81..10c368f72 100644 --- a/src/global.c +++ b/src/global.c @@ -37,7 +37,7 @@ const unsigned char sqlite3UpperToLower[] = { 198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215, 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,232,233, 234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251, - 252,253,254,255 + 252,253,254,255, #endif #ifdef SQLITE_EBCDIC 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 0x */ @@ -57,7 +57,35 @@ const unsigned char sqlite3UpperToLower[] = { 224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */ #endif +/* All of the upper-to-lower conversion data is above. The following +** 18 integers are completely unrelated. They are appended to the +** sqlite3UpperToLower[] array to avoid UBSAN warnings. Here's what is +** going on: +** +** The SQL comparison operators (<>, =, >, <=, <, and >=) are implemented +** by invoking sqlite3MemCompare(A,B) which compares values A and B and +** returns negative, zero, or positive if A is less then, equal to, or +** greater than B, respectively. Then the true false results is found by +** consulting sqlite3aLTb[opcode], sqlite3aEQb[opcode], or +** sqlite3aGTb[opcode] depending on whether the result of compare(A,B) +** is negative, zero, or positive, where opcode is the specific opcode. +** The only works because the comparison opcodes are consecutive and in +** this order: NE EQ GT LE LT GE. Various assert()s throughout the code +** ensure that is the case. +** +** These elements must be appended to another array. Otherwise the +** index (here shown as [256-OP_Ne]) would be out-of-bounds and thus +** be undefined behavior. That's goofy, but the C-standards people thought +** it was a good idea, so here we are. +*/ +/* NE EQ GT LE LT GE */ + 1, 0, 0, 1, 1, 0, /* aLTb[]: Use when compare(A,B) less than zero */ + 0, 1, 0, 1, 0, 1, /* aEQb[]: Use when compare(A,B) equals zero */ + 1, 0, 1, 0, 0, 1 /* aGTb[]: Use when compare(A,B) greater than zero*/ }; +const unsigned char *sqlite3aLTb = &sqlite3UpperToLower[256-OP_Ne]; +const unsigned char *sqlite3aEQb = &sqlite3UpperToLower[256+6-OP_Ne]; +const unsigned char *sqlite3aGTb = &sqlite3UpperToLower[256+12-OP_Ne]; /* ** The following 256 byte lookup table is used to support SQLites built-in diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0822a6c3c..cd2e9a2e2 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -4739,6 +4739,9 @@ void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); extern const unsigned char sqlite3OpcodeProperty[]; extern const char sqlite3StrBINARY[]; extern const unsigned char sqlite3UpperToLower[]; +extern const unsigned char *sqlite3aLTb; +extern const unsigned char *sqlite3aEQb; +extern const unsigned char *sqlite3aGTb; extern const unsigned char sqlite3CtypeMap[]; extern SQLITE_WSD struct Sqlite3Config sqlite3Config; extern FuncDefHash sqlite3BuiltinFunctions; diff --git a/src/vdbe.c b/src/vdbe.c index 080c7eaf8..0026ed377 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2111,15 +2111,12 @@ compare_op: ** order: NE, EQ, GT, LE, LT, GE */ assert( OP_Eq==OP_Ne+1 ); assert( OP_Gt==OP_Ne+2 ); assert( OP_Le==OP_Ne+3 ); assert( OP_Lt==OP_Ne+4 ); assert( OP_Ge==OP_Ne+5 ); - if( res<0 ){ /* ne, eq, gt, le, lt, ge */ - static const unsigned char aLTb[] = { 1, 0, 0, 1, 1, 0 }; - res2 = aLTb[pOp->opcode - OP_Ne]; + if( res<0 ){ + res2 = sqlite3aLTb[pOp->opcode]; }else if( res==0 ){ - static const unsigned char aEQb[] = { 0, 1, 0, 1, 0, 1 }; - res2 = aEQb[pOp->opcode - OP_Ne]; + res2 = sqlite3aEQb[pOp->opcode]; }else{ - static const unsigned char aGTb[] = { 1, 0, 1, 0, 0, 1 }; - res2 = aGTb[pOp->opcode - OP_Ne]; + res2 = sqlite3aGTb[pOp->opcode]; } /* Undo any changes made by applyAffinity() to the input registers. */ |