1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Optimizations to the main loop inside sqlite3VdbeExec() to help VDBE byte code

run a few percent faster.

FossilOrigin-Name: d622ac6ac7a297754494d3a33dbaeea02836272e
This commit is contained in:
drh
2009-11-14 23:22:23 +00:00
parent bbe879d516
commit a6c2ed91ca
8 changed files with 95 additions and 96 deletions

View File

@@ -1,8 +1,8 @@
-----BEGIN PGP SIGNED MESSAGE----- -----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1 Hash: SHA1
C Make\sthe\ssqlite3VdbeExec()\sfunction\sabout\s2%\sfaster\sby\sstoring\sthe\sopcode\narray\sin\sa\slocal\svariable. C Optimizations\sto\sthe\smain\sloop\sinside\ssqlite3VdbeExec()\sto\shelp\sVDBE\sbyte\scode\nrun\sa\sfew\spercent\sfaster.
D 2009-11-14T18:04:36 D 2009-11-14T23:22:23
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
@@ -121,7 +121,7 @@ F src/expr.c 94f3086a342a1d151fb9d17ef1c33bff4cc768f0
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0 F src/fkey.c e2116672a6bd610dc888e27df292ebc7999c9bb0
F src/func.c bf54e1202cbfb28bf4b1fd9b58899009ae76716f F src/func.c bf54e1202cbfb28bf4b1fd9b58899009ae76716f
F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32 F src/global.c 9481e307caf01c59792f2bc32396061386591124
F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af F src/hash.c 458488dcc159c301b8e7686280ab209f1fb915af
F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970 F src/hash.h 2894c932d84d9f892d4b4023a75e501f83050970
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08 F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
@@ -167,7 +167,7 @@ F src/select.c a727f61f3267bfa20ce1c3e85d38dc2132db1060
F src/shell.c f4948cb6d30665d755a6b5e0ec313d1094aab828 F src/shell.c f4948cb6d30665d755a6b5e0ec313d1094aab828
F src/sqlite.h.in 4464e9772122f0447305d425e04d122b6f1bffec F src/sqlite.h.in 4464e9772122f0447305d425e04d122b6f1bffec
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
F src/sqliteInt.h ee54fe752ba5672b7ca52bdd0e300c3902103d93 F src/sqliteInt.h 961a7a3c1428fdc9c18df63ee34c91c7425c47af
F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6 F src/sqliteLimit.h 3afab2291762b5d09ae20c18feb8e9fa935a60a6
F src/status.c e651be6b30d397d86384c6867bc016e4913bcac7 F src/status.c e651be6b30d397d86384c6867bc016e4913bcac7
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@@ -210,11 +210,11 @@ 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 0abb88a10fb243cc753c3ab468d6aab7c3ee5211 F src/vdbe.c 0bc1c3aaa0c5c13240c2e39ce3b9ae92586fc30b
F src/vdbe.h 65cd747e36ad444cb1a17e529030942c45a61fe3 F src/vdbe.h 5f35750615163d1064052785b4a9f0eb004a720d
F src/vdbeInt.h 59c65e7b810836b9e946acee45c7b3c02b967d1b F src/vdbeInt.h d7ea821ac7813c9bea0fe87558c35e07b2c7c44d
F src/vdbeapi.c 17680ab7a75ec938c5ba039a6c87489d01faf2cb F src/vdbeapi.c 17680ab7a75ec938c5ba039a6c87489d01faf2cb
F src/vdbeaux.c ee52010d2517eae2ef1c6766a372d79bfaea6e2e F src/vdbeaux.c 45d1e150d811da2bafe820136b1c21616b2e5fd4
F src/vdbeblob.c 84f924700a7a889152aeebef77ca5f4e3875ffb4 F src/vdbeblob.c 84f924700a7a889152aeebef77ca5f4e3875ffb4
F src/vdbemem.c 1e16e3a16e55f4c3452834f0e041726021aa66e0 F src/vdbemem.c 1e16e3a16e55f4c3452834f0e041726021aa66e0
F src/vtab.c 456fc226614569f0e46f216e33265bea268bd917 F src/vtab.c 456fc226614569f0e46f216e33265bea268bd917
@@ -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 ed820f45cf4354b1e1db64049c47a07221a7ff6d P 8bd3cc82720ac7e8a9d4a03a882b6f8226867b0d
R 03060ba235b0950aa9146609f8d8a31d R cb3a1da29955733378e76881557b866a
U drh U drh
Z ce5be4ec1d2dd720600d2c9af2d32994 Z afa90cd668940f60ced698df17c38b7b
-----BEGIN PGP SIGNATURE----- -----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux) Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFK/vE5oxKgR168RlERAor4AJ4s/kWdVBsQ2tAlXF4Ix+CSbm+a5wCfWYrX iD8DBQFK/zu0oxKgR168RlERAk/iAKCEVk6/+bUzTWEw8F/wvHvw0zgqfgCcC5l5
75gfXpBzWcUcFFhH7YbfTXU= k8ZGSZvLtvYXVF3tlPQ2ip8=
=IpIH =cEZ3
-----END PGP SIGNATURE----- -----END PGP SIGNATURE-----

View File

@@ -1 +1 @@
8bd3cc82720ac7e8a9d4a03a882b6f8226867b0d d622ac6ac7a297754494d3a33dbaeea02836272e

View File

@@ -14,7 +14,6 @@
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
/* An array to map all upper-case characters into their corresponding /* An array to map all upper-case characters into their corresponding
** lower-case character. ** lower-case character.
** **
@@ -188,3 +187,12 @@ SQLITE_WSD FuncDefHash sqlite3GlobalFunctions;
** and dileterious behavior. ** and dileterious behavior.
*/ */
int sqlite3PendingByte = 0x40000000; int sqlite3PendingByte = 0x40000000;
#include "opcodes.h"
/*
** Properties of opcodes. The OPFLG_INITIALIZER macro is
** created by mkopcodeh.awk during compilation. Data is obtained
** from the comments following the "case OP_xxxx:" statements in
** the vdbe.c file.
*/
const unsigned char sqlite3OpcodeProperty[] = OPFLG_INITIALIZER;

View File

@@ -2845,6 +2845,7 @@ char *sqlite3Utf8to16(sqlite3 *, u8, char *, int, int *);
int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **); int sqlite3ValueFromExpr(sqlite3 *, Expr *, u8, u8, sqlite3_value **);
void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8); void sqlite3ValueApplyAffinity(sqlite3_value *, u8, u8);
#ifndef SQLITE_AMALGAMATION #ifndef SQLITE_AMALGAMATION
extern const unsigned char sqlite3OpcodeProperty[];
extern const unsigned char sqlite3UpperToLower[]; extern const unsigned char sqlite3UpperToLower[];
extern const unsigned char sqlite3CtypeMap[]; extern const unsigned char sqlite3CtypeMap[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config; extern SQLITE_WSD struct Sqlite3Config sqlite3Config;

View File

@@ -170,23 +170,6 @@ void sqlite3VdbeMemStoreType(Mem *pMem){
} }
} }
/*
** Properties of opcodes. The OPFLG_INITIALIZER macro is
** created by mkopcodeh.awk during compilation. Data is obtained
** from the comments following the "case OP_xxxx:" statements in
** this file.
*/
static const unsigned char opcodeProperty[] = OPFLG_INITIALIZER;
/*
** Return true if an opcode has any of the OPFLG_xxx properties
** specified by mask.
*/
int sqlite3VdbeOpcodeHasProperty(int opcode, int mask){
assert( opcode>0 && opcode<(int)sizeof(opcodeProperty) );
return (opcodeProperty[opcode]&mask)!=0;
}
/* /*
** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL ** Allocate VdbeCursor number iCur. Return a pointer to it. Return NULL
** if we run out of memory. ** if we run out of memory.
@@ -560,19 +543,21 @@ int sqlite3VdbeExec(
int rc = SQLITE_OK; /* Value to return */ int rc = SQLITE_OK; /* Value to return */
sqlite3 *db = p->db; /* The database */ sqlite3 *db = p->db; /* The database */
u8 encoding = ENC(db); /* The database encoding */ u8 encoding = ENC(db); /* The database encoding */
u8 opProperty;
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
u8 checkProgress; /* True if progress callbacks are enabled */
int nProgressOps = 0; /* Opcodes executed since progress callback. */
#endif
Mem *aMem = p->aMem; /* Copy of p->aMem */
Mem *pIn1 = 0; /* 1st input operand */ Mem *pIn1 = 0; /* 1st input operand */
Mem *pIn2 = 0; /* 2nd input operand */ Mem *pIn2 = 0; /* 2nd input operand */
Mem *pIn3 = 0; /* 3rd input operand */ Mem *pIn3 = 0; /* 3rd input operand */
Mem *pOut = 0; /* Output operand */ Mem *pOut = 0; /* Output operand */
u8 opProperty;
int iCompare = 0; /* Result of last OP_Compare operation */ int iCompare = 0; /* Result of last OP_Compare operation */
int *aPermute = 0; /* Permutation of columns for OP_Compare */ int *aPermute = 0; /* Permutation of columns for OP_Compare */
#ifdef VDBE_PROFILE #ifdef VDBE_PROFILE
u64 start; /* CPU clock count at start of opcode */ u64 start; /* CPU clock count at start of opcode */
int origPc; /* Program counter at start of opcode */ int origPc; /* Program counter at start of opcode */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
int nProgressOps = 0; /* Opcodes executed since progress callback. */
#endif #endif
/*** INSERT STACK UNION HERE ***/ /*** INSERT STACK UNION HERE ***/
@@ -591,6 +576,9 @@ int sqlite3VdbeExec(
db->busyHandler.nBusy = 0; db->busyHandler.nBusy = 0;
CHECK_FOR_INTERRUPT; CHECK_FOR_INTERRUPT;
sqlite3VdbeIOTraceSql(p); sqlite3VdbeIOTraceSql(p);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
checkProgress = db->xProgress!=0;
#endif
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
sqlite3BeginBenignMalloc(); sqlite3BeginBenignMalloc();
if( p->pc==0 if( p->pc==0
@@ -656,7 +644,7 @@ int sqlite3VdbeExec(
** If the progress callback returns non-zero, exit the virtual machine with ** If the progress callback returns non-zero, exit the virtual machine with
** a return code SQLITE_ABORT. ** a return code SQLITE_ABORT.
*/ */
if( db->xProgress ){ if( checkProgress ){
if( db->nProgressOps==nProgressOps ){ if( db->nProgressOps==nProgressOps ){
int prc; int prc;
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
@@ -677,14 +665,15 @@ int sqlite3VdbeExec(
** output which is specified by the P2 parameter. The P2 register ** output which is specified by the P2 parameter. The P2 register
** is initialized to a NULL. ** is initialized to a NULL.
*/ */
opProperty = opcodeProperty[pOp->opcode]; assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
opProperty = pOp->opflags;
if( opProperty & (OPFLG_OUT2_PRERELEASE | OPFLG_IN1 | OPFLG_IN2 if( opProperty & (OPFLG_OUT2_PRERELEASE | OPFLG_IN1 | OPFLG_IN2
| OPFLG_IN3 | OPFLG_OUT2 | OPFLG_OUT3) | OPFLG_IN3 | OPFLG_OUT2 | OPFLG_OUT3)
){ ){
if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){ if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){
assert( pOp->p2>0 ); assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem ); assert( pOp->p2<=p->nMem );
pOut = &p->aMem[pOp->p2]; pOut = &aMem[pOp->p2];
sqlite3VdbeMemReleaseExternal(pOut); sqlite3VdbeMemReleaseExternal(pOut);
pOut->flags = MEM_Null; pOut->flags = MEM_Null;
pOut->n = 0; pOut->n = 0;
@@ -692,19 +681,19 @@ int sqlite3VdbeExec(
if( (opProperty & OPFLG_IN1)!=0 ){ if( (opProperty & OPFLG_IN1)!=0 ){
assert( pOp->p1>0 ); assert( pOp->p1>0 );
assert( pOp->p1<=p->nMem ); assert( pOp->p1<=p->nMem );
pIn1 = &p->aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
REGISTER_TRACE(pOp->p1, pIn1); REGISTER_TRACE(pOp->p1, pIn1);
} }
if( (opProperty & (OPFLG_IN2|OPFLG_OUT2))!=0 ){ if( (opProperty & (OPFLG_IN2|OPFLG_OUT2))!=0 ){
assert( pOp->p2>0 ); assert( pOp->p2>0 );
assert( pOp->p2<=p->nMem ); assert( pOp->p2<=p->nMem );
assert( (opProperty & OPFLG_OUT2)==0 || (opProperty & OPFLG_IN3)==0 ); assert( (opProperty & OPFLG_OUT2)==0 || (opProperty & OPFLG_IN3)==0 );
pIn2 = pOut = &p->aMem[pOp->p2]; pIn2 = pOut = &aMem[pOp->p2];
} }
if( (opProperty & (OPFLG_IN3|OPFLG_OUT3))!=0 ){ if( (opProperty & (OPFLG_IN3|OPFLG_OUT3))!=0 ){
assert( pOp->p3>0 ); assert( pOp->p3>0 );
assert( pOp->p3<=p->nMem ); assert( pOp->p3<=p->nMem );
pIn3 = pOut = &p->aMem[pOp->p3]; pIn3 = pOut = &aMem[pOp->p3];
} }
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
if( opProperty & OPFLG_IN2 ){ REGISTER_TRACE(pOp->p2, pIn2); } if( opProperty & OPFLG_IN2 ){ REGISTER_TRACE(pOp->p2, pIn2); }
@@ -849,6 +838,7 @@ case OP_Halt: {
pc = p->aOp[pc].p2-1; pc = p->aOp[pc].p2-1;
} }
aOp = p->aOp; aOp = p->aOp;
aMem = p->aMem;
break; break;
} }
@@ -1004,7 +994,7 @@ case OP_Variable: {
if( sqlite3VdbeMemTooBig(pVar) ){ if( sqlite3VdbeMemTooBig(pVar) ){
goto too_big; goto too_big;
} }
pOut = &p->aMem[p2++]; pOut = &aMem[p2++];
sqlite3VdbeMemReleaseExternal(pOut); sqlite3VdbeMemReleaseExternal(pOut);
pOut->flags = MEM_Null; pOut->flags = MEM_Null;
sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
@@ -1032,11 +1022,11 @@ case OP_Move: {
assert( n>0 && p1>0 && p2>0 ); assert( n>0 && p1>0 && p2>0 );
assert( p1+n<=p2 || p2+n<=p1 ); assert( p1+n<=p2 || p2+n<=p1 );
pIn1 = &p->aMem[p1]; pIn1 = &aMem[p1];
pOut = &p->aMem[p2]; pOut = &aMem[p2];
while( n-- ){ while( n-- ){
assert( pOut<=&p->aMem[p->nMem] ); assert( pOut<=&aMem[p->nMem] );
assert( pIn1<=&p->aMem[p->nMem] ); assert( pIn1<=&aMem[p->nMem] );
zMalloc = pOut->zMalloc; zMalloc = pOut->zMalloc;
pOut->zMalloc = 0; pOut->zMalloc = 0;
sqlite3VdbeMemMove(pOut, pIn1); sqlite3VdbeMemMove(pOut, pIn1);
@@ -1134,7 +1124,7 @@ case OP_ResultRow: {
** and have an assigned type. The results are de-ephemeralized as ** and have an assigned type. The results are de-ephemeralized as
** as side effect. ** as side effect.
*/ */
pMem = p->pResultSet = &p->aMem[pOp->p1]; pMem = p->pResultSet = &aMem[pOp->p1];
for(i=0; i<pOp->p2; i++){ for(i=0; i<pOp->p2; i++){
sqlite3VdbeMemNulTerminate(&pMem[i]); sqlite3VdbeMemNulTerminate(&pMem[i]);
sqlite3VdbeMemStoreType(&pMem[i]); sqlite3VdbeMemStoreType(&pMem[i]);
@@ -1353,7 +1343,7 @@ case OP_Function: {
assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem+1) ); assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem+1) );
assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n ); assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
pArg = &p->aMem[pOp->p2]; pArg = &aMem[pOp->p2];
for(i=0; i<n; i++, pArg++){ for(i=0; i<n; i++, pArg++){
apVal[i] = pArg; apVal[i] = pArg;
sqlite3VdbeMemStoreType(pArg); sqlite3VdbeMemStoreType(pArg);
@@ -1370,7 +1360,7 @@ case OP_Function: {
} }
assert( pOp->p3>0 && pOp->p3<=p->nMem ); assert( pOp->p3>0 && pOp->p3<=p->nMem );
pOut = &p->aMem[pOp->p3]; pOut = &aMem[pOp->p3];
ctx.s.flags = MEM_Null; ctx.s.flags = MEM_Null;
ctx.s.db = db; ctx.s.db = db;
ctx.s.xDel = 0; ctx.s.xDel = 0;
@@ -1730,7 +1720,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
** The jump is taken if the SQLITE_JUMPIFNULL bit is set. ** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
*/ */
if( pOp->p5 & SQLITE_STOREP2 ){ if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &p->aMem[pOp->p2]; pOut = &aMem[pOp->p2];
MemSetTypeFlag(pOut, MEM_Null); MemSetTypeFlag(pOut, MEM_Null);
REGISTER_TRACE(pOp->p2, pOut); REGISTER_TRACE(pOp->p2, pOut);
}else if( pOp->p5 & SQLITE_JUMPIFNULL ){ }else if( pOp->p5 & SQLITE_JUMPIFNULL ){
@@ -1762,7 +1752,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
} }
if( pOp->p5 & SQLITE_STOREP2 ){ if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &p->aMem[pOp->p2]; pOut = &aMem[pOp->p2];
MemSetTypeFlag(pOut, MEM_Int); MemSetTypeFlag(pOut, MEM_Int);
pOut->u.i = res; pOut->u.i = res;
REGISTER_TRACE(pOp->p2, pOut); REGISTER_TRACE(pOp->p2, pOut);
@@ -1831,12 +1821,12 @@ case OP_Compare: {
#endif /* SQLITE_DEBUG */ #endif /* SQLITE_DEBUG */
for(i=0; i<n; i++){ for(i=0; i<n; i++){
idx = aPermute ? aPermute[i] : i; idx = aPermute ? aPermute[i] : i;
REGISTER_TRACE(p1+idx, &p->aMem[p1+idx]); REGISTER_TRACE(p1+idx, &aMem[p1+idx]);
REGISTER_TRACE(p2+idx, &p->aMem[p2+idx]); REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
assert( i<pKeyInfo->nField ); assert( i<pKeyInfo->nField );
pColl = pKeyInfo->aColl[i]; pColl = pKeyInfo->aColl[i];
bRev = pKeyInfo->aSortOrder[i]; bRev = pKeyInfo->aSortOrder[i];
iCompare = sqlite3MemCompare(&p->aMem[p1+idx], &p->aMem[p2+idx], pColl); iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
if( iCompare ){ if( iCompare ){
if( bRev ) iCompare = -iCompare; if( bRev ) iCompare = -iCompare;
break; break;
@@ -2045,7 +2035,7 @@ case OP_Column: {
memset(&sMem, 0, sizeof(sMem)); memset(&sMem, 0, sizeof(sMem));
assert( p1<p->nCursor ); assert( p1<p->nCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem ); assert( pOp->p3>0 && pOp->p3<=p->nMem );
pDest = &p->aMem[pOp->p3]; pDest = &aMem[pOp->p3];
MemSetTypeFlag(pDest, MEM_Null); MemSetTypeFlag(pDest, MEM_Null);
zRec = 0; zRec = 0;
@@ -2091,7 +2081,7 @@ case OP_Column: {
assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ assert( rc==SQLITE_OK ); /* DataSize() cannot fail */
} }
}else if( pC->pseudoTableReg>0 ){ }else if( pC->pseudoTableReg>0 ){
pReg = &p->aMem[pC->pseudoTableReg]; pReg = &aMem[pC->pseudoTableReg];
assert( pReg->flags & MEM_Blob ); assert( pReg->flags & MEM_Blob );
payloadSize = pReg->n; payloadSize = pReg->n;
zRec = pReg->z; zRec = pReg->z;
@@ -2308,7 +2298,7 @@ case OP_Affinity: {
Mem *pRec; /* Current register */ Mem *pRec; /* Current register */
zAffinity = pOp->p4.z; zAffinity = pOp->p4.z;
pData0 = &p->aMem[pOp->p1]; pData0 = &aMem[pOp->p1];
pLast = &pData0[pOp->p2-1]; pLast = &pData0[pOp->p2-1];
for(pRec=pData0; pRec<=pLast; pRec++){ for(pRec=pData0; pRec<=pLast; pRec++){
ExpandBlob(pRec); ExpandBlob(pRec);
@@ -2374,7 +2364,7 @@ case OP_MakeRecord: {
nField = pOp->p1; nField = pOp->p1;
zAffinity = pOp->p4.z; zAffinity = pOp->p4.z;
assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem+1 ); assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem+1 );
pData0 = &p->aMem[nField]; pData0 = &aMem[nField];
nField = pOp->p2; nField = pOp->p2;
pLast = &pData0[nField-1]; pLast = &pData0[nField-1];
file_format = p->minWriteFileFormat; file_format = p->minWriteFileFormat;
@@ -2418,7 +2408,7 @@ case OP_MakeRecord: {
** sqlite3VdbeMemGrow() could clobber the value before it is used). ** sqlite3VdbeMemGrow() could clobber the value before it is used).
*/ */
assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 ); assert( pOp->p3<pOp->p1 || pOp->p3>=pOp->p1+pOp->p2 );
pOut = &p->aMem[pOp->p3]; pOut = &aMem[pOp->p3];
if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){ if( sqlite3VdbeMemGrow(pOut, (int)nByte, 0) ){
goto no_mem; goto no_mem;
} }
@@ -2965,7 +2955,7 @@ case OP_OpenWrite: {
if( pOp->p5 ){ if( pOp->p5 ){
assert( p2>0 ); assert( p2>0 );
assert( p2<=p->nMem ); assert( p2<=p->nMem );
pIn2 = &p->aMem[p2]; pIn2 = &aMem[p2];
sqlite3VdbeMemIntegerify(pIn2); sqlite3VdbeMemIntegerify(pIn2);
p2 = (int)pIn2->u.i; p2 = (int)pIn2->u.i;
/* The p2 value always comes from a prior OP_CreateTable opcode and /* The p2 value always comes from a prior OP_CreateTable opcode and
@@ -3264,7 +3254,7 @@ case OP_SeekGt: { /* jump, in3 */
assert( oc!=OP_SeekGe || r.flags==0 ); assert( oc!=OP_SeekGe || r.flags==0 );
assert( oc!=OP_SeekLt || r.flags==0 ); assert( oc!=OP_SeekLt || r.flags==0 );
r.aMem = &p->aMem[pOp->p3]; r.aMem = &aMem[pOp->p3];
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res); rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, &r, 0, 0, &res);
if( rc!=SQLITE_OK ){ if( rc!=SQLITE_OK ){
goto abort_due_to_error; goto abort_due_to_error;
@@ -3448,11 +3438,11 @@ case OP_IsUnique: { /* jump, in3 */
VdbeCursor *pCx; VdbeCursor *pCx;
BtCursor *pCrsr; BtCursor *pCrsr;
u16 nField; u16 nField;
Mem *aMem; Mem *aMx;
UnpackedRecord r; /* B-Tree index search key */ UnpackedRecord r; /* B-Tree index search key */
i64 R; /* Rowid stored in register P3 */ i64 R; /* Rowid stored in register P3 */
aMem = &p->aMem[pOp->p4.i]; aMx = &aMem[pOp->p4.i];
/* Assert that the values of parameters P1 and P4 are in range. */ /* Assert that the values of parameters P1 and P4 are in range. */
assert( pOp->p4type==P4_INT32 ); assert( pOp->p4type==P4_INT32 );
assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem ); assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
@@ -3468,20 +3458,20 @@ case OP_IsUnique: { /* jump, in3 */
/* If any of the values are NULL, take the jump. */ /* If any of the values are NULL, take the jump. */
nField = pCx->pKeyInfo->nField; nField = pCx->pKeyInfo->nField;
for(ii=0; ii<nField; ii++){ for(ii=0; ii<nField; ii++){
if( aMem[ii].flags & MEM_Null ){ if( aMx[ii].flags & MEM_Null ){
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
pCrsr = 0; pCrsr = 0;
break; break;
} }
} }
assert( (aMem[nField].flags & MEM_Null)==0 ); assert( (aMx[nField].flags & MEM_Null)==0 );
if( pCrsr!=0 ){ if( pCrsr!=0 ){
/* Populate the index search key. */ /* Populate the index search key. */
r.pKeyInfo = pCx->pKeyInfo; r.pKeyInfo = pCx->pKeyInfo;
r.nField = nField + 1; r.nField = nField + 1;
r.flags = UNPACKED_PREFIX_SEARCH; r.flags = UNPACKED_PREFIX_SEARCH;
r.aMem = aMem; r.aMem = aMx;
/* Extract the value of R from register P3. */ /* Extract the value of R from register P3. */
sqlite3VdbeMemIntegerify(pIn3); sqlite3VdbeMemIntegerify(pIn3);
@@ -3657,7 +3647,7 @@ case OP_NewRowid: { /* out2-prerelease */
}else{ }else{
/* Assert that P3 is a valid memory cell. */ /* Assert that P3 is a valid memory cell. */
assert( pOp->p3<=p->nMem ); assert( pOp->p3<=p->nMem );
pMem = &p->aMem[pOp->p3]; pMem = &aMem[pOp->p3];
} }
REGISTER_TRACE(pOp->p3, pMem); REGISTER_TRACE(pOp->p3, pMem);
@@ -3761,7 +3751,7 @@ case OP_InsertInt: {
const char *zTbl; /* Table name - used by the opdate hook */ const char *zTbl; /* Table name - used by the opdate hook */
int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */ int op; /* Opcode for update hook: SQLITE_UPDATE or SQLITE_INSERT */
pData = &p->aMem[pOp->p2]; pData = &aMem[pOp->p2];
assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1]; pC = p->apCsr[pOp->p1];
assert( pC!=0 ); assert( pC!=0 );
@@ -3771,7 +3761,7 @@ case OP_InsertInt: {
REGISTER_TRACE(pOp->p2, pData); REGISTER_TRACE(pOp->p2, pData);
if( pOp->opcode==OP_Insert ){ if( pOp->opcode==OP_Insert ){
pKey = &p->aMem[pOp->p3]; pKey = &aMem[pOp->p3];
assert( pKey->flags & MEM_Int ); assert( pKey->flags & MEM_Int );
REGISTER_TRACE(pOp->p3, pKey); REGISTER_TRACE(pOp->p3, pKey);
iKey = pKey->u.i; iKey = pKey->u.i;
@@ -3919,7 +3909,7 @@ case OP_RowData: {
u32 n; u32 n;
i64 n64; i64 n64;
pOut = &p->aMem[pOp->p2]; pOut = &aMem[pOp->p2];
/* Note that RowKey and RowData are really exactly the same instruction */ /* Note that RowKey and RowData are really exactly the same instruction */
assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p1>=0 && pOp->p1<p->nCursor );
@@ -4245,7 +4235,7 @@ case OP_IdxDelete: {
r.pKeyInfo = pC->pKeyInfo; r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p3; r.nField = (u16)pOp->p3;
r.flags = 0; r.flags = 0;
r.aMem = &p->aMem[pOp->p2]; r.aMem = &aMem[pOp->p2];
rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res); rc = sqlite3BtreeMovetoUnpacked(pCrsr, &r, 0, 0, &res);
if( rc==SQLITE_OK && res==0 ){ if( rc==SQLITE_OK && res==0 ){
rc = sqlite3BtreeDelete(pCrsr); rc = sqlite3BtreeDelete(pCrsr);
@@ -4336,7 +4326,7 @@ case OP_IdxGE: { /* jump */
}else{ }else{
r.flags = UNPACKED_IGNORE_ROWID; r.flags = UNPACKED_IGNORE_ROWID;
} }
r.aMem = &p->aMem[pOp->p3]; r.aMem = &aMem[pOp->p3];
rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res); rc = sqlite3VdbeIdxKeyCompare(pC, &r, &res);
if( pOp->opcode==OP_IdxLT ){ if( pOp->opcode==OP_IdxLT ){
res = -res; res = -res;
@@ -4434,7 +4424,7 @@ case OP_Clear: {
if( pOp->p3 ){ if( pOp->p3 ){
p->nChange += nChange; p->nChange += nChange;
if( pOp->p3>0 ){ if( pOp->p3>0 ){
p->aMem[pOp->p3].u.i += nChange; aMem[pOp->p3].u.i += nChange;
} }
} }
break; break;
@@ -4644,10 +4634,10 @@ case OP_IntegrityCk: {
aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) ); aRoot = sqlite3DbMallocRaw(db, sizeof(int)*(nRoot+1) );
if( aRoot==0 ) goto no_mem; if( aRoot==0 ) goto no_mem;
assert( pOp->p3>0 && pOp->p3<=p->nMem ); assert( pOp->p3>0 && pOp->p3<=p->nMem );
pnErr = &p->aMem[pOp->p3]; pnErr = &aMem[pOp->p3];
assert( (pnErr->flags & MEM_Int)!=0 ); assert( (pnErr->flags & MEM_Int)!=0 );
assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 ); assert( (pnErr->flags & (MEM_Str|MEM_Blob))==0 );
pIn1 = &p->aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
for(j=0; j<nRoot; j++){ for(j=0; j<nRoot; j++){
aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]); aRoot[j] = (int)sqlite3VdbeIntValue(&pIn1[j]);
} }
@@ -4793,7 +4783,7 @@ case OP_Program: { /* jump */
void *t; /* Token identifying trigger */ void *t; /* Token identifying trigger */
pProgram = pOp->p4.pProgram; pProgram = pOp->p4.pProgram;
pRt = &p->aMem[pOp->p3]; pRt = &aMem[pOp->p3];
assert( pProgram->nOp>0 ); assert( pProgram->nOp>0 );
/* If the p5 flag is clear, then recursive invocation of triggers is /* If the p5 flag is clear, then recursive invocation of triggers is
@@ -4871,10 +4861,10 @@ case OP_Program: { /* jump */
pFrame->nChange = p->nChange; pFrame->nChange = p->nChange;
p->nChange = 0; p->nChange = 0;
p->pFrame = pFrame; p->pFrame = pFrame;
p->aMem = &VdbeFrameMem(pFrame)[-1]; p->aMem = aMem = &VdbeFrameMem(pFrame)[-1];
p->nMem = pFrame->nChildMem; p->nMem = pFrame->nChildMem;
p->nCursor = (u16)pFrame->nChildCsr; p->nCursor = (u16)pFrame->nChildCsr;
p->apCsr = (VdbeCursor **)&p->aMem[p->nMem+1]; p->apCsr = (VdbeCursor **)&aMem[p->nMem+1];
p->aOp = aOp = pProgram->aOp; p->aOp = aOp = pProgram->aOp;
p->nOp = pProgram->nOp; p->nOp = pProgram->nOp;
pc = -1; pc = -1;
@@ -4961,7 +4951,7 @@ case OP_MemMax: { /* in2 */
for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent); for(pFrame=p->pFrame; pFrame->pParent; pFrame=pFrame->pParent);
pIn1 = &pFrame->aMem[pOp->p1]; pIn1 = &pFrame->aMem[pOp->p1];
}else{ }else{
pIn1 = &p->aMem[pOp->p1]; pIn1 = &aMem[pOp->p1];
} }
sqlite3VdbeMemIntegerify(pIn1); sqlite3VdbeMemIntegerify(pIn1);
sqlite3VdbeMemIntegerify(pIn2); sqlite3VdbeMemIntegerify(pIn2);
@@ -5039,7 +5029,7 @@ case OP_AggStep: {
n = pOp->p5; n = pOp->p5;
assert( n>=0 ); assert( n>=0 );
pRec = &p->aMem[pOp->p2]; pRec = &aMem[pOp->p2];
apVal = p->apArg; apVal = p->apArg;
assert( apVal || n==0 ); assert( apVal || n==0 );
for(i=0; i<n; i++, pRec++){ for(i=0; i<n; i++, pRec++){
@@ -5048,7 +5038,7 @@ case OP_AggStep: {
} }
ctx.pFunc = pOp->p4.pFunc; ctx.pFunc = pOp->p4.pFunc;
assert( pOp->p3>0 && pOp->p3<=p->nMem ); assert( pOp->p3>0 && pOp->p3<=p->nMem );
ctx.pMem = pMem = &p->aMem[pOp->p3]; ctx.pMem = pMem = &aMem[pOp->p3];
pMem->n++; pMem->n++;
ctx.s.flags = MEM_Null; ctx.s.flags = MEM_Null;
ctx.s.z = 0; ctx.s.z = 0;
@@ -5087,7 +5077,7 @@ case OP_AggStep: {
case OP_AggFinal: { case OP_AggFinal: {
Mem *pMem; Mem *pMem;
assert( pOp->p1>0 && pOp->p1<=p->nMem ); assert( pOp->p1>0 && pOp->p1<=p->nMem );
pMem = &p->aMem[pOp->p1]; pMem = &aMem[pOp->p1];
assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 ); assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc); rc = sqlite3VdbeMemFinalize(pMem, pOp->p4.pFunc);
if( rc ){ if( rc ){
@@ -5312,7 +5302,7 @@ case OP_VFilter: { /* jump */
int i; int i;
Mem **apArg; Mem **apArg;
pQuery = &p->aMem[pOp->p3]; pQuery = &aMem[pOp->p3];
pArgc = &pQuery[1]; pArgc = &pQuery[1];
pCur = p->apCsr[pOp->p1]; pCur = p->apCsr[pOp->p1];
REGISTER_TRACE(pOp->p3, pQuery); REGISTER_TRACE(pOp->p3, pQuery);
@@ -5373,7 +5363,7 @@ case OP_VColumn: {
VdbeCursor *pCur = p->apCsr[pOp->p1]; VdbeCursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor ); assert( pCur->pVtabCursor );
assert( pOp->p3>0 && pOp->p3<=p->nMem ); assert( pOp->p3>0 && pOp->p3<=p->nMem );
pDest = &p->aMem[pOp->p3]; pDest = &aMem[pOp->p3];
if( pCur->nullRow ){ if( pCur->nullRow ){
sqlite3VdbeMemSetNull(pDest); sqlite3VdbeMemSetNull(pDest);
break; break;
@@ -5480,7 +5470,7 @@ case OP_VRename: {
Mem *pName; Mem *pName;
pVtab = pOp->p4.pVtab->pVtab; pVtab = pOp->p4.pVtab->pVtab;
pName = &p->aMem[pOp->p1]; pName = &aMem[pOp->p1];
assert( pVtab->pModule->xRename ); assert( pVtab->pModule->xRename );
REGISTER_TRACE(pOp->p1, pName); REGISTER_TRACE(pOp->p1, pName);
assert( pName->flags & MEM_Str ); assert( pName->flags & MEM_Str );
@@ -5534,7 +5524,7 @@ case OP_VUpdate: {
assert( pOp->p4type==P4_VTAB ); assert( pOp->p4type==P4_VTAB );
if( ALWAYS(pModule->xUpdate) ){ if( ALWAYS(pModule->xUpdate) ){
apArg = p->apArg; apArg = p->apArg;
pX = &p->aMem[pOp->p3]; pX = &aMem[pOp->p3];
for(i=0; i<nArg; i++){ for(i=0; i<nArg; i++){
sqlite3VdbeMemStoreType(pX); sqlite3VdbeMemStoreType(pX);
apArg[i] = pX; apArg[i] = pX;

View File

@@ -42,7 +42,7 @@ typedef struct SubProgram SubProgram;
struct VdbeOp { struct VdbeOp {
u8 opcode; /* What operation to perform */ u8 opcode; /* What operation to perform */
signed char p4type; /* One of the P4_xxx constants for p4 */ signed char p4type; /* One of the P4_xxx constants for p4 */
u8 opflags; /* Not currently used */ u8 opflags; /* Mask of the OPFLG_* flags in opcodes.h */
u8 p5; /* Fifth parameter is an unsigned character */ u8 p5; /* Fifth parameter is an unsigned character */
int p1; /* First operand */ int p1; /* First operand */
int p2; /* Second parameter (often the jump destination) */ int p2; /* Second parameter (often the jump destination) */

View File

@@ -379,7 +379,6 @@ void sqlite3VdbeMemRelease(Mem *p);
void sqlite3VdbeMemReleaseExternal(Mem *p); void sqlite3VdbeMemReleaseExternal(Mem *p);
int sqlite3VdbeMemFinalize(Mem*, FuncDef*); int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
const char *sqlite3OpcodeName(int); const char *sqlite3OpcodeName(int);
int sqlite3VdbeOpcodeHasProperty(int, int);
int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve); int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
int sqlite3VdbeCloseStatement(Vdbe *, int); int sqlite3VdbeCloseStatement(Vdbe *, int);
void sqlite3VdbeFrameDelete(VdbeFrame*); void sqlite3VdbeFrameDelete(VdbeFrame*);

View File

@@ -386,6 +386,8 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument ** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument
** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by ** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by
** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array. ** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
**
** The Op.opflags field is set on all opcodes.
*/ */
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
int i; int i;
@@ -396,15 +398,14 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){ for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
u8 opcode = pOp->opcode; u8 opcode = pOp->opcode;
pOp->opflags = sqlite3OpcodeProperty[opcode];
if( opcode==OP_Function || opcode==OP_AggStep ){ if( opcode==OP_Function || opcode==OP_AggStep ){
if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5; if( pOp->p5>nMaxArgs ) nMaxArgs = pOp->p5;
#ifndef SQLITE_OMIT_VIRTUALTABLE
}else if( opcode==OP_VUpdate ){
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
#endif
}else if( opcode==OP_Transaction && pOp->p2!=0 ){ }else if( opcode==OP_Transaction && pOp->p2!=0 ){
p->readOnly = 0; p->readOnly = 0;
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
}else if( opcode==OP_VUpdate ){
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
}else if( opcode==OP_VFilter ){ }else if( opcode==OP_VFilter ){
int n; int n;
assert( p->nOp - i >= 3 ); assert( p->nOp - i >= 3 );
@@ -414,7 +415,7 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
#endif #endif
} }
if( sqlite3VdbeOpcodeHasProperty(opcode, OPFLG_JUMP) && pOp->p2<0 ){ if( (pOp->opflags & OPFLG_JUMP)!=0 && pOp->p2<0 ){
assert( -1-pOp->p2<p->nLabel ); assert( -1-pOp->p2<p->nLabel );
pOp->p2 = aLabel[-1-pOp->p2]; pOp->p2 = aLabel[-1-pOp->p2];
} }
@@ -476,7 +477,7 @@ int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
VdbeOp *pOut = &p->aOp[i+addr]; VdbeOp *pOut = &p->aOp[i+addr];
pOut->opcode = pIn->opcode; pOut->opcode = pIn->opcode;
pOut->p1 = pIn->p1; pOut->p1 = pIn->p1;
if( p2<0 && sqlite3VdbeOpcodeHasProperty(pOut->opcode, OPFLG_JUMP) ){ if( p2<0 && (sqlite3OpcodeProperty[pOut->opcode] & OPFLG_JUMP)!=0 ){
pOut->p2 = addr + ADDR(p2); pOut->p2 = addr + ADDR(p2);
}else{ }else{
pOut->p2 = p2; pOut->p2 = p2;