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:
drh 2009-11-13 19:43:43 +00:00
parent c54055bd25
commit 93952eb8c5
4 changed files with 67 additions and 104 deletions

View File

@ -1,8 +1,8 @@
-----BEGIN PGP SIGNED MESSAGE----- -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 Hash: SHA1
C Force\s8-byte\smemory\salignment\son\smemory\sallocated\sfor\sVDBE\scursors. 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-13T17:05:54 D 2009-11-13T19:43:44
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 53f3dfa49f28ab5b80cb083fb7c9051e596bcfa1 F Makefile.in 53f3dfa49f28ab5b80cb083fb7c9051e596bcfa1
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -94,7 +94,7 @@ F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac
F mkopcodec.awk 3fb9bf077053c968451f4dd03d11661ac373f9d1 F mkopcodec.awk 3fb9bf077053c968451f4dd03d11661ac373f9d1
F mkopcodeh.awk 104fa333e4a7a689fac074437cbd51a31a803bd4 F mkopcodeh.awk 29b84656502eee5f444c3147f331ee686956ab0e
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F publish.sh c74b6c2b6b63435aa1b4b43b1396dfebfae84095 F publish.sh c74b6c2b6b63435aa1b4b43b1396dfebfae84095
F publish_osx.sh 2ad2ee7d50632dff99949edc9c162dbb052f7534 F publish_osx.sh 2ad2ee7d50632dff99949edc9c162dbb052f7534
@ -210,7 +210,7 @@ F src/update.c 8efeb09822886e33c265dd96d29a3d865ea6dcf2
F src/utf.c dad16adcc0c35ef2437dca125a4b07419d361052 F src/utf.c dad16adcc0c35ef2437dca125a4b07419d361052
F src/util.c ad4f03079ba0fe83590d1cc9197e8e4844e38592 F src/util.c ad4f03079ba0fe83590d1cc9197e8e4844e38592
F src/vacuum.c 03309a08d549f9389cc3a3589afd4fadbdaf0679 F src/vacuum.c 03309a08d549f9389cc3a3589afd4fadbdaf0679
F src/vdbe.c 3067cfcc86e61e1662f7322aa153f52857b61f8b F src/vdbe.c bc7fe6c752a86adb63ddfdefe41c2912f0dbb207
F src/vdbe.h 65cd747e36ad444cb1a17e529030942c45a61fe3 F src/vdbe.h 65cd747e36ad444cb1a17e529030942c45a61fe3
F src/vdbeInt.h 59c65e7b810836b9e946acee45c7b3c02b967d1b F src/vdbeInt.h 59c65e7b810836b9e946acee45c7b3c02b967d1b
F src/vdbeapi.c 17680ab7a75ec938c5ba039a6c87489d01faf2cb F src/vdbeapi.c 17680ab7a75ec938c5ba039a6c87489d01faf2cb
@ -771,14 +771,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P f0599d28fabe9e67a7150a91c266cb7655a2002e P bdc45ba77fb77771c8ff46b8d6c2dd29e6d3b019
R b787bcf50272d59401284264a4dcbb30 R 5ea278d36772610aa788376c8fbcebe2
U drh U drh
Z 255150de2174a2682813e546e8d990c7 Z 259be306ad269f147c546ad8a52bafc1
-----BEGIN PGP SIGNATURE----- -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux) Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFK/ZH1oxKgR168RlERAuF9AJ9hHIIG7PFtXPqnbvCge9luG/0VIACfc7kV iD8DBQFK/bbzoxKgR168RlERAnLoAKCIVxGvqT+6vMWYcfnTE0ON/9WBLwCfXEdv
v+sk467/hW51kXF6lY7carY= WTqwwhvX+GL8mTOt3BiR/h8=
=mwCb =9zc9
-----END PGP SIGNATURE----- -----END PGP SIGNATURE-----

View File

@ -1 +1 @@
bdc45ba77fb77771c8ff46b8d6c2dd29e6d3b019 3352b3eba545c3128efb7665ec91d4df3b16011d

View File

@ -49,6 +49,7 @@
in1[name] = 0 in1[name] = 0
in2[name] = 0 in2[name] = 0
in3[name] = 0 in3[name] = 0
out2[name] = 0
out3[name] = 0 out3[name] = 0
for(i=3; i<NF; i++){ for(i=3; i<NF; i++){
if($i=="same" && $(i+1)=="as"){ if($i=="same" && $(i+1)=="as"){
@ -70,6 +71,8 @@
in2[name] = 1 in2[name] = 1
}else if(x=="in3"){ }else if(x=="in3"){
in3[name] = 1 in3[name] = 1
}else if(x=="out2"){
out2[name] = 1
}else if(x=="out3"){ }else if(x=="out3"){
out3[name] = 1 out3[name] = 1
} }
@ -125,13 +128,14 @@ END {
name = order[i]; name = order[i];
x = op[name] x = op[name]
a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0 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( jump[name] ) a0 = 1;
if( out2_prerelease[name] ) a1 = 2; if( out2_prerelease[name] ) a1 = 2;
if( in1[name] ) a2 = 4; if( in1[name] ) a2 = 4;
if( in2[name] ) a3 = 8; if( in2[name] ) a3 = 8;
if( in3[name] ) a4 = 16; 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+a8+a9+a10+a11+a12+a13+a14+a15;
bv[x] = a0+a1+a2+a3+a4+a5+a6+a7; 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_IN1 0x0004 /* in1: P1 is an input */"
print "#define OPFLG_IN2 0x0008 /* in2: P2 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_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 {\\" print "#define OPFLG_INITIALIZER {\\"
for(i=0; i<=max; i++){ for(i=0; i<=max; i++){
if( i%8==0 ) printf("/* %3d */",i) if( i%8==0 ) printf("/* %3d */",i)

View File

@ -677,60 +677,41 @@ int sqlite3VdbeExec(
** is initialized to a NULL. ** is initialized to a NULL.
*/ */
opProperty = opcodeProperty[pOp->opcode]; opProperty = opcodeProperty[pOp->opcode];
if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){ if( opProperty & (OPFLG_OUT2_PRERELEASE | OPFLG_IN1 | OPFLG_IN2
assert( pOp->p2>0 ); | OPFLG_IN3 | OPFLG_OUT2 | OPFLG_OUT3)
assert( pOp->p2<=p->nMem ); ){
pOut = &p->aMem[pOp->p2]; if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){
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.
*/
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>0 );
assert( pOp->p2<=p->nMem ); assert( pOp->p2<=p->nMem );
pIn2 = &p->aMem[pOp->p2]; pOut = &p->aMem[pOp->p2];
REGISTER_TRACE(pOp->p2, pIn2); sqlite3VdbeMemReleaseExternal(pOut);
/* As currently implemented, in2 implies out3. There is no reason pOut->flags = MEM_Null;
** why this has to be, it just worked out that way. */ pOut->n = 0;
assert( (opProperty & OPFLG_OUT3)!=0 ); }else{
assert( pOp->p3>0 ); if( (opProperty & OPFLG_IN1)!=0 ){
assert( pOp->p3<=p->nMem ); assert( pOp->p1>0 );
pOut = &p->aMem[pOp->p3]; assert( pOp->p1<=p->nMem );
}else if( (opProperty & OPFLG_IN3)!=0 ){ pIn1 = &p->aMem[pOp->p1];
assert( pOp->p3>0 ); REGISTER_TRACE(pOp->p1, pIn1);
assert( pOp->p3<=p->nMem ); }
pIn3 = &p->aMem[pOp->p3]; if( (opProperty & (OPFLG_IN2|OPFLG_OUT2))!=0 ){
REGISTER_TRACE(pOp->p3, pIn3); assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem );
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 = 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
} }
}else if( (opProperty & OPFLG_IN2)!=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( pOp->p3>0 );
assert( pOp->p3<=p->nMem );
pIn3 = &p->aMem[pOp->p3];
REGISTER_TRACE(pOp->p3, pIn3);
} }
switch( pOp->opcode ){ switch( pOp->opcode ){
/***************************************************************************** /*****************************************************************************
@ -786,10 +767,7 @@ case OP_Goto: { /* jump */
** Write the current address onto register P1 ** Write the current address onto register P1
** and then jump to address P2. ** and then jump to address P2.
*/ */
case OP_Gosub: { /* jump */ case OP_Gosub: { /* jump, in1 */
assert( pOp->p1>0 );
assert( pOp->p1<=p->nMem );
pIn1 = &p->aMem[pOp->p1];
assert( (pIn1->flags & MEM_Dyn)==0 ); assert( (pIn1->flags & MEM_Dyn)==0 );
pIn1->flags = MEM_Int; pIn1->flags = MEM_Int;
pIn1->u.i = pc; pIn1->u.i = pc;
@ -1075,10 +1053,7 @@ case OP_Move: {
** This instruction makes a deep copy of the value. A duplicate ** This instruction makes a deep copy of the value. A duplicate
** is made of any string or blob constant. See also OP_SCopy. ** is made of any string or blob constant. See also OP_SCopy.
*/ */
case OP_Copy: { /* in1 */ case OP_Copy: { /* in1, out2 */
assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem );
pOut = &p->aMem[pOp->p2];
assert( pOut!=pIn1 ); assert( pOut!=pIn1 );
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
Deephemeralize(pOut); Deephemeralize(pOut);
@ -1098,11 +1073,7 @@ case OP_Copy: { /* in1 */
** during the lifetime of the copy. Use OP_Copy to make a complete ** during the lifetime of the copy. Use OP_Copy to make a complete
** copy. ** copy.
*/ */
case OP_SCopy: { /* in1 */ case OP_SCopy: { /* in1, out2 */
REGISTER_TRACE(pOp->p1, pIn1);
assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem );
pOut = &p->aMem[pOp->p2];
assert( pOut!=pIn1 ); assert( pOut!=pIn1 );
sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
REGISTER_TRACE(pOp->p2, pOut); 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 ** boolean complement in register P2. If the value in register P1 is
** NULL, then a NULL is stored in P2. ** NULL, then a NULL is stored in P2.
*/ */
case OP_Not: { /* same as TK_NOT, in1 */ case OP_Not: { /* same as TK_NOT, in1, out2 */
pOut = &p->aMem[pOp->p2];
if( pIn1->flags & MEM_Null ){ if( pIn1->flags & MEM_Null ){
sqlite3VdbeMemSetNull(pOut); sqlite3VdbeMemSetNull(pOut);
}else{ }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 ** ones-complement of the P1 value into register P2. If P1 holds
** a NULL then store a NULL in P2. ** a NULL then store a NULL in P2.
*/ */
case OP_BitNot: { /* same as TK_BITNOT, in1 */ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
pOut = &p->aMem[pOp->p2];
if( pIn1->flags & MEM_Null ){ if( pIn1->flags & MEM_Null ){
sqlite3VdbeMemSetNull(pOut); sqlite3VdbeMemSetNull(pOut);
}else{ }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 ** 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. ** to the comparison. This makes the opcode work like IdxLE.
*/ */
case OP_IdxLT: /* jump, in3 */ case OP_IdxLT: /* jump */
case OP_IdxGE: { /* jump, in3 */ case OP_IdxGE: { /* jump */
VdbeCursor *pC; VdbeCursor *pC;
int res; int res;
UnpackedRecord r; UnpackedRecord r;
@ -4696,19 +4665,13 @@ case OP_IntegrityCk: {
** **
** An assertion fails if P2 is not an integer. ** An assertion fails if P2 is not an integer.
*/ */
case OP_RowSetAdd: { /* in2 */ case OP_RowSetAdd: { /* in1, in2 */
Mem *pIdx; assert( (pIn2->flags & MEM_Int)!=0 );
Mem *pVal; if( (pIn1->flags & MEM_RowSet)==0 ){
assert( pOp->p1>0 && pOp->p1<=p->nMem ); sqlite3VdbeMemSetRowSet(pIn1);
pIdx = &p->aMem[pOp->p1]; if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
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;
} }
sqlite3RowSetInsert(pIdx->u.pRowSet, pVal->u.i); sqlite3RowSetInsert(pIn1->u.pRowSet, pIn2->u.i);
break; break;
} }
@ -4718,22 +4681,17 @@ case OP_RowSetAdd: { /* in2 */
** register P3. Or, if boolean index P1 is initially empty, leave P3 ** register P3. Or, if boolean index P1 is initially empty, leave P3
** unchanged and jump to instruction P2. ** unchanged and jump to instruction P2.
*/ */
case OP_RowSetRead: { /* jump, out3 */ case OP_RowSetRead: { /* jump, in1, out3 */
Mem *pIdx;
i64 val; i64 val;
assert( pOp->p1>0 && pOp->p1<=p->nMem );
CHECK_FOR_INTERRUPT; CHECK_FOR_INTERRUPT;
pIdx = &p->aMem[pOp->p1]; if( (pIn1->flags & MEM_RowSet)==0
pOut = &p->aMem[pOp->p3]; || sqlite3RowSetNext(pIn1->u.pRowSet, &val)==0
if( (pIdx->flags & MEM_RowSet)==0
|| sqlite3RowSetNext(pIdx->u.pRowSet, &val)==0
){ ){
/* The boolean index is empty */ /* The boolean index is empty */
sqlite3VdbeMemSetNull(pIdx); sqlite3VdbeMemSetNull(pIn1);
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
}else{ }else{
/* A value was pulled from the index */ /* A value was pulled from the index */
assert( pOp->p3>0 && pOp->p3<=p->nMem );
sqlite3VdbeMemSetInt64(pOut, val); sqlite3VdbeMemSetInt64(pOut, val);
} }
break; break;