Simplify the OPFLG processing logic in the VDBE for a speed boost in the
VDBE processing loop and a reduction in code size. FossilOrigin-Name: 3352b3eba545c3128efb7665ec91d4df3b16011d
This commit is contained in:
parent
c54055bd25
commit
93952eb8c5
20
manifest
20
manifest
@ -1,8 +1,8 @@
|
||||
-----BEGIN PGP SIGNED MESSAGE-----
|
||||
Hash: SHA1
|
||||
|
||||
C Force\s8-byte\smemory\salignment\son\smemory\sallocated\sfor\sVDBE\scursors.
|
||||
D 2009-11-13T17:05:54
|
||||
C Simplify\sthe\sOPFLG\sprocessing\slogic\sin\sthe\sVDBE\sfor\sa\sspeed\sboost\sin\sthe\nVDBE\sprocessing\sloop\sand\sa\sreduction\sin\scode\ssize.
|
||||
D 2009-11-13T19:43:44
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in 53f3dfa49f28ab5b80cb083fb7c9051e596bcfa1
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -94,7 +94,7 @@ F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
|
||||
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
|
||||
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
|
||||
F mkopcodec.awk 3fb9bf077053c968451f4dd03d11661ac373f9d1
|
||||
F mkopcodeh.awk 104fa333e4a7a689fac074437cbd51a31a803bd4
|
||||
F mkopcodeh.awk 29b84656502eee5f444c3147f331ee686956ab0e
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F publish.sh c74b6c2b6b63435aa1b4b43b1396dfebfae84095
|
||||
F publish_osx.sh 2ad2ee7d50632dff99949edc9c162dbb052f7534
|
||||
@ -210,7 +210,7 @@ F src/update.c 8efeb09822886e33c265dd96d29a3d865ea6dcf2
|
||||
F src/utf.c dad16adcc0c35ef2437dca125a4b07419d361052
|
||||
F src/util.c ad4f03079ba0fe83590d1cc9197e8e4844e38592
|
||||
F src/vacuum.c 03309a08d549f9389cc3a3589afd4fadbdaf0679
|
||||
F src/vdbe.c 3067cfcc86e61e1662f7322aa153f52857b61f8b
|
||||
F src/vdbe.c bc7fe6c752a86adb63ddfdefe41c2912f0dbb207
|
||||
F src/vdbe.h 65cd747e36ad444cb1a17e529030942c45a61fe3
|
||||
F src/vdbeInt.h 59c65e7b810836b9e946acee45c7b3c02b967d1b
|
||||
F src/vdbeapi.c 17680ab7a75ec938c5ba039a6c87489d01faf2cb
|
||||
@ -771,14 +771,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||
P f0599d28fabe9e67a7150a91c266cb7655a2002e
|
||||
R b787bcf50272d59401284264a4dcbb30
|
||||
P bdc45ba77fb77771c8ff46b8d6c2dd29e6d3b019
|
||||
R 5ea278d36772610aa788376c8fbcebe2
|
||||
U drh
|
||||
Z 255150de2174a2682813e546e8d990c7
|
||||
Z 259be306ad269f147c546ad8a52bafc1
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||
|
||||
iD8DBQFK/ZH1oxKgR168RlERAuF9AJ9hHIIG7PFtXPqnbvCge9luG/0VIACfc7kV
|
||||
v+sk467/hW51kXF6lY7carY=
|
||||
=mwCb
|
||||
iD8DBQFK/bbzoxKgR168RlERAnLoAKCIVxGvqT+6vMWYcfnTE0ON/9WBLwCfXEdv
|
||||
WTqwwhvX+GL8mTOt3BiR/h8=
|
||||
=9zc9
|
||||
-----END PGP SIGNATURE-----
|
||||
|
@ -1 +1 @@
|
||||
bdc45ba77fb77771c8ff46b8d6c2dd29e6d3b019
|
||||
3352b3eba545c3128efb7665ec91d4df3b16011d
|
@ -49,6 +49,7 @@
|
||||
in1[name] = 0
|
||||
in2[name] = 0
|
||||
in3[name] = 0
|
||||
out2[name] = 0
|
||||
out3[name] = 0
|
||||
for(i=3; i<NF; i++){
|
||||
if($i=="same" && $(i+1)=="as"){
|
||||
@ -70,6 +71,8 @@
|
||||
in2[name] = 1
|
||||
}else if(x=="in3"){
|
||||
in3[name] = 1
|
||||
}else if(x=="out2"){
|
||||
out2[name] = 1
|
||||
}else if(x=="out3"){
|
||||
out3[name] = 1
|
||||
}
|
||||
@ -125,13 +128,14 @@ END {
|
||||
name = order[i];
|
||||
x = op[name]
|
||||
a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0
|
||||
# a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0
|
||||
# a7 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0
|
||||
if( jump[name] ) a0 = 1;
|
||||
if( out2_prerelease[name] ) a1 = 2;
|
||||
if( in1[name] ) a2 = 4;
|
||||
if( in2[name] ) a3 = 8;
|
||||
if( in3[name] ) a4 = 16;
|
||||
if( out3[name] ) a5 = 32;
|
||||
if( out2[name] ) a5 = 32;
|
||||
if( out3[name] ) a6 = 64;
|
||||
# bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15;
|
||||
bv[x] = a0+a1+a2+a3+a4+a5+a6+a7;
|
||||
}
|
||||
@ -145,7 +149,8 @@ END {
|
||||
print "#define OPFLG_IN1 0x0004 /* in1: P1 is an input */"
|
||||
print "#define OPFLG_IN2 0x0008 /* in2: P2 is an input */"
|
||||
print "#define OPFLG_IN3 0x0010 /* in3: P3 is an input */"
|
||||
print "#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */"
|
||||
print "#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */"
|
||||
print "#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */"
|
||||
print "#define OPFLG_INITIALIZER {\\"
|
||||
for(i=0; i<=max; i++){
|
||||
if( i%8==0 ) printf("/* %3d */",i)
|
||||
|
108
src/vdbe.c
108
src/vdbe.c
@ -677,6 +677,9 @@ int sqlite3VdbeExec(
|
||||
** is initialized to a NULL.
|
||||
*/
|
||||
opProperty = opcodeProperty[pOp->opcode];
|
||||
if( opProperty & (OPFLG_OUT2_PRERELEASE | OPFLG_IN1 | OPFLG_IN2
|
||||
| OPFLG_IN3 | OPFLG_OUT2 | OPFLG_OUT3)
|
||||
){
|
||||
if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){
|
||||
assert( pOp->p2>0 );
|
||||
assert( pOp->p2<=p->nMem );
|
||||
@ -684,51 +687,29 @@ int sqlite3VdbeExec(
|
||||
sqlite3VdbeMemReleaseExternal(pOut);
|
||||
pOut->flags = MEM_Null;
|
||||
pOut->n = 0;
|
||||
}else
|
||||
|
||||
/* Do common setup for opcodes marked with one of the following
|
||||
** combinations of properties.
|
||||
**
|
||||
** in1
|
||||
** in1 in2
|
||||
** in1 in2 out3
|
||||
** in1 in3
|
||||
**
|
||||
** Variables pIn1, pIn2, and pIn3 are made to point to appropriate
|
||||
** registers for inputs. Variable pOut points to the output register.
|
||||
*/
|
||||
}else{
|
||||
if( (opProperty & OPFLG_IN1)!=0 ){
|
||||
assert( pOp->p1>0 );
|
||||
assert( pOp->p1<=p->nMem );
|
||||
pIn1 = &p->aMem[pOp->p1];
|
||||
REGISTER_TRACE(pOp->p1, pIn1);
|
||||
if( (opProperty & OPFLG_IN2)!=0 ){
|
||||
assert( pOp->p2>0 );
|
||||
assert( pOp->p2<=p->nMem );
|
||||
pIn2 = &p->aMem[pOp->p2];
|
||||
REGISTER_TRACE(pOp->p2, pIn2);
|
||||
/* As currently implemented, in2 implies out3. There is no reason
|
||||
** why this has to be, it just worked out that way. */
|
||||
assert( (opProperty & OPFLG_OUT3)!=0 );
|
||||
assert( pOp->p3>0 );
|
||||
assert( pOp->p3<=p->nMem );
|
||||
pOut = &p->aMem[pOp->p3];
|
||||
}else if( (opProperty & OPFLG_IN3)!=0 ){
|
||||
assert( pOp->p3>0 );
|
||||
assert( pOp->p3<=p->nMem );
|
||||
pIn3 = &p->aMem[pOp->p3];
|
||||
REGISTER_TRACE(pOp->p3, pIn3);
|
||||
}
|
||||
}else if( (opProperty & OPFLG_IN2)!=0 ){
|
||||
if( (opProperty & (OPFLG_IN2|OPFLG_OUT2))!=0 ){
|
||||
assert( pOp->p2>0 );
|
||||
assert( pOp->p2<=p->nMem );
|
||||
pIn2 = &p->aMem[pOp->p2];
|
||||
REGISTER_TRACE(pOp->p2, pIn2);
|
||||
}else if( (opProperty & OPFLG_IN3)!=0 ){
|
||||
assert( (opProperty & OPFLG_OUT2)==0 || (opProperty & OPFLG_IN3)==0 );
|
||||
pIn2 = pOut = &p->aMem[pOp->p2];
|
||||
}
|
||||
if( (opProperty & (OPFLG_IN3|OPFLG_OUT3))!=0 ){
|
||||
assert( pOp->p3>0 );
|
||||
assert( pOp->p3<=p->nMem );
|
||||
pIn3 = &p->aMem[pOp->p3];
|
||||
REGISTER_TRACE(pOp->p3, pIn3);
|
||||
pIn3 = pOut = &p->aMem[pOp->p3];
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( opProperty & OPFLG_IN2 ){ REGISTER_TRACE(pOp->p2, pIn2); }
|
||||
if( opProperty & OPFLG_IN3 ){ REGISTER_TRACE(pOp->p3, pIn3); }
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
switch( pOp->opcode ){
|
||||
@ -786,10 +767,7 @@ case OP_Goto: { /* jump */
|
||||
** Write the current address onto register P1
|
||||
** and then jump to address P2.
|
||||
*/
|
||||
case OP_Gosub: { /* jump */
|
||||
assert( pOp->p1>0 );
|
||||
assert( pOp->p1<=p->nMem );
|
||||
pIn1 = &p->aMem[pOp->p1];
|
||||
case OP_Gosub: { /* jump, in1 */
|
||||
assert( (pIn1->flags & MEM_Dyn)==0 );
|
||||
pIn1->flags = MEM_Int;
|
||||
pIn1->u.i = pc;
|
||||
@ -1075,10 +1053,7 @@ case OP_Move: {
|
||||
** This instruction makes a deep copy of the value. A duplicate
|
||||
** is made of any string or blob constant. See also OP_SCopy.
|
||||
*/
|
||||
case OP_Copy: { /* in1 */
|
||||
assert( pOp->p2>0 );
|
||||
assert( pOp->p2<=p->nMem );
|
||||
pOut = &p->aMem[pOp->p2];
|
||||
case OP_Copy: { /* in1, out2 */
|
||||
assert( pOut!=pIn1 );
|
||||
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
|
||||
Deephemeralize(pOut);
|
||||
@ -1098,11 +1073,7 @@ case OP_Copy: { /* in1 */
|
||||
** during the lifetime of the copy. Use OP_Copy to make a complete
|
||||
** copy.
|
||||
*/
|
||||
case OP_SCopy: { /* in1 */
|
||||
REGISTER_TRACE(pOp->p1, pIn1);
|
||||
assert( pOp->p2>0 );
|
||||
assert( pOp->p2<=p->nMem );
|
||||
pOut = &p->aMem[pOp->p2];
|
||||
case OP_SCopy: { /* in1, out2 */
|
||||
assert( pOut!=pIn1 );
|
||||
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
|
||||
REGISTER_TRACE(pOp->p2, pOut);
|
||||
@ -1945,8 +1916,7 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */
|
||||
** boolean complement in register P2. If the value in register P1 is
|
||||
** NULL, then a NULL is stored in P2.
|
||||
*/
|
||||
case OP_Not: { /* same as TK_NOT, in1 */
|
||||
pOut = &p->aMem[pOp->p2];
|
||||
case OP_Not: { /* same as TK_NOT, in1, out2 */
|
||||
if( pIn1->flags & MEM_Null ){
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
}else{
|
||||
@ -1961,8 +1931,7 @@ case OP_Not: { /* same as TK_NOT, in1 */
|
||||
** ones-complement of the P1 value into register P2. If P1 holds
|
||||
** a NULL then store a NULL in P2.
|
||||
*/
|
||||
case OP_BitNot: { /* same as TK_BITNOT, in1 */
|
||||
pOut = &p->aMem[pOp->p2];
|
||||
case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
|
||||
if( pIn1->flags & MEM_Null ){
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
}else{
|
||||
@ -4333,8 +4302,8 @@ case OP_IdxRowid: { /* out2-prerelease */
|
||||
** If P5 is non-zero then the key value is increased by an epsilon prior
|
||||
** to the comparison. This makes the opcode work like IdxLE.
|
||||
*/
|
||||
case OP_IdxLT: /* jump, in3 */
|
||||
case OP_IdxGE: { /* jump, in3 */
|
||||
case OP_IdxLT: /* jump */
|
||||
case OP_IdxGE: { /* jump */
|
||||
VdbeCursor *pC;
|
||||
int res;
|
||||
UnpackedRecord r;
|
||||
@ -4696,19 +4665,13 @@ case OP_IntegrityCk: {
|
||||
**
|
||||
** An assertion fails if P2 is not an integer.
|
||||
*/
|
||||
case OP_RowSetAdd: { /* in2 */
|
||||
Mem *pIdx;
|
||||
Mem *pVal;
|
||||
assert( pOp->p1>0 && pOp->p1<=p->nMem );
|
||||
pIdx = &p->aMem[pOp->p1];
|
||||
assert( pOp->p2>0 && pOp->p2<=p->nMem );
|
||||
pVal = &p->aMem[pOp->p2];
|
||||
assert( (pVal->flags & MEM_Int)!=0 );
|
||||
if( (pIdx->flags & MEM_RowSet)==0 ){
|
||||
sqlite3VdbeMemSetRowSet(pIdx);
|
||||
if( (pIdx->flags & MEM_RowSet)==0 ) goto no_mem;
|
||||
case OP_RowSetAdd: { /* in1, in2 */
|
||||
assert( (pIn2->flags & MEM_Int)!=0 );
|
||||
if( (pIn1->flags & MEM_RowSet)==0 ){
|
||||
sqlite3VdbeMemSetRowSet(pIn1);
|
||||
if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
|
||||
}
|
||||
sqlite3RowSetInsert(pIdx->u.pRowSet, pVal->u.i);
|
||||
sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -4718,22 +4681,17 @@ case OP_RowSetAdd: { /* in2 */
|
||||
** register P3. Or, if boolean index P1 is initially empty, leave P3
|
||||
** unchanged and jump to instruction P2.
|
||||
*/
|
||||
case OP_RowSetRead: { /* jump, out3 */
|
||||
Mem *pIdx;
|
||||
case OP_RowSetRead: { /* jump, in1, out3 */
|
||||
i64 val;
|
||||
assert( pOp->p1>0 && pOp->p1<=p->nMem );
|
||||
CHECK_FOR_INTERRUPT;
|
||||
pIdx = &p->aMem[pOp->p1];
|
||||
pOut = &p->aMem[pOp->p3];
|
||||
if( (pIdx->flags & MEM_RowSet)==0
|
||||
|| sqlite3RowSetNext(pIdx->u.pRowSet, &val)==0
|
||||
if( (pIn1->flags & MEM_RowSet)==0
|
||||
|| sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0
|
||||
){
|
||||
/* The boolean index is empty */
|
||||
sqlite3VdbeMemSetNull(pIdx);
|
||||
sqlite3VdbeMemSetNull(pIn1);
|
||||
pc = pOp->p2 - 1;
|
||||
}else{
|
||||
/* A value was pulled from the index */
|
||||
assert( pOp->p3>0 && pOp->p3<=p->nMem );
|
||||
sqlite3VdbeMemSetInt64(pOut, val);
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user