From: drh Date: Tue, 2 Jun 2009 15:21:42 +0000 (+0000) Subject: Add the vdbe-compress.tcl script which automatically refactors the X-Git-Tag: version-3.6.15~56 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=856c10375d75ae867c824421d385f0cb69242a13;p=thirdparty%2Fsqlite.git Add the vdbe-compress.tcl script which automatically refactors the sqlite3VdbeExec() routine to use less stack space. Use this script when constructing the amalgamation. (CVS 6704) FossilOrigin-Name: 7f43391831b03e53d967acee6ae02089740aaedb --- diff --git a/Makefile.in b/Makefile.in index debe2f16dc..f38f16b16c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -488,6 +488,8 @@ sqlite3$(TEXE): $(TOP)/src/shell.c libsqlite3.la sqlite3.h mkdir -p tsrc cp $(SRC) tsrc rm tsrc/sqlite.h.in tsrc/parse.y + $(TCLSH_CMD) $(TOP)/tool/vdbe-compress.tcl vdbe.new + mv vdbe.new tsrc/vdbe.c touch .target_source sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl diff --git a/main.mk b/main.mk index 8ae0ba79d5..069a0091bf 100644 --- a/main.mk +++ b/main.mk @@ -323,11 +323,13 @@ objects: $(LIBOBJ_ORIG) # files are automatically generated. This target takes care of # all that automatic generation. # -target_source: $(SRC) +target_source: $(SRC) $(TOP)/tool/vdbe-compress.tcl rm -rf tsrc mkdir tsrc cp -f $(SRC) tsrc rm tsrc/sqlite.h.in tsrc/parse.y + tclsh $(TOP)/tool/vdbe-compress.tcl vdbe.new + mv vdbe.new tsrc/vdbe.c touch target_source sqlite3.c: target_source $(TOP)/tool/mksqlite3c.tcl diff --git a/manifest b/manifest index 9e549fb457..92583df72f 100644 --- a/manifest +++ b/manifest @@ -1,7 +1,7 @@ -C Avoid\sallocating\slarge\sobjects\son\sthe\sstack\sin\sthe\sincremental\sBLOB\sI/O\ninterface.\s(CVS\s6703) -D 2009-06-01T19:53:31 +C Add\sthe\svdbe-compress.tcl\sscript\swhich\sautomatically\srefactors\sthe\nsqlite3VdbeExec()\sroutine\sto\suse\sless\sstack\sspace.\s\sUse\sthis\sscript\nwhen\sconstructing\sthe\samalgamation.\s(CVS\s6704) +D 2009-06-02T15:21:42 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 -F Makefile.in 583e87706abc3026960ed759aff6371faf84c211 +F Makefile.in 8b8fb7823264331210cddf103831816c286ba446 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.vxworks 51698ac39a2d114c1586b7694838f2f321c43f64 F README b974cdc3f9f12b87e851b04e75996d720ebf81ac @@ -86,7 +86,7 @@ F ext/rtree/tkt3363.test 6662237ea75bb431cd5d262dfc9535e1023315fc F ext/rtree/viewrtree.tcl 09526398dae87a5a87c5aac2b3854dbaf8376869 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 -F main.mk 8388687358db061fa98f062f8b417b986d8ff3fe +F main.mk 4a9e8f062833f7ef6fc926f2701f3ce1c83a3373 F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 4123480947681d9b434a5e7b1ee08135abe409ac @@ -203,7 +203,7 @@ F src/update.c 6ae6c26adff8dc34532d578f66e6cfde04b5d177 F src/utf.c 9541d28f40441812c0b40f00334372a0542c00ff F src/util.c a9719d309f6c65b3b79fa3ca8512fa8e3947a391 F src/vacuum.c 981686c910b2ff9fe3db814e01da31cf9dbd48c7 -F src/vdbe.c b859cb274024e5755aa03625251ff859e3e95158 +F src/vdbe.c 2f2c4b5a1b92cdbae31f5c5d5a380c697fa3dcc4 F src/vdbe.h 35a648bc3279a120da24f34d9a25213ec15daf8a F src/vdbeInt.h 43183a2a18654fa570219ab65e53a608057c48ae F src/vdbeapi.c 86aa27a5f3493aaffb8ac051782aa3b22670d7ed @@ -731,7 +731,8 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P c7c0c58e472cd8277b2ad58bb60834190bace4fa -R 01d40d71e1b5c8cea7b1b21c881c4bd8 +F tool/vdbe-compress.tcl 383f4be3ceb8cec24f31f27480232fbb866fd83a +P ea7dfde700fb57ed0ecb5000a55abbf45aa1e09d +R f304b4ea19d83f978fafc25600629030 U drh -Z f0ffd7a898768d77c536a218a2488cbe +Z 613f8e55a41fae0a6bf73d1968f3449f diff --git a/manifest.uuid b/manifest.uuid index 49fe44b9f4..b877754896 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -ea7dfde700fb57ed0ecb5000a55abbf45aa1e09d \ No newline at end of file +7f43391831b03e53d967acee6ae02089740aaedb \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 51a5e5b3e4..326efc91b5 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.843 2009/05/07 12:17:34 drh Exp $ +** $Id: vdbe.c,v 1.844 2009/06/02 15:21:42 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -564,9 +564,7 @@ int sqlite3VdbeExec( #ifndef SQLITE_OMIT_PROGRESS_CALLBACK int nProgressOps = 0; /* Opcodes executed since progress callback. */ #endif - - /* Temporary space into which to unpack a record. */ - char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; + /*** INSERT STACK UNION HERE ***/ assert( p->magic==VDBE_MAGIC_RUN ); /* sqlite3_step() verifies this */ assert( db->magic==SQLITE_MAGIC_BUSY ); @@ -982,20 +980,24 @@ case OP_Blob: { /* out2-prerelease */ ** The P4 value is used by sqlite3_bind_parameter_name(). */ case OP_Variable: { - int j = pOp->p1 - 1; - int k = pOp->p2; - Mem *pVar; - int n = pOp->p3; - assert( j>=0 && j+n<=p->nVar ); - assert( k>=1 && k+n-1<=p->nMem ); + int p1; /* Variable to copy from */ + int p2; /* Register to copy to */ + int n; /* Number of values left to copy */ + Mem *pVar; /* Value being transferred */ + + p1 = pOp->p1 - 1; + p2 = pOp->p2; + n = pOp->p3; + assert( p1>=0 && p1+n<=p->nVar ); + assert( p2>=1 && p2+n-1<=p->nMem ); assert( pOp->p4.z==0 || pOp->p3==1 ); while( n-- > 0 ){ - pVar = &p->aVar[j++]; + pVar = &p->aVar[p1++]; if( sqlite3VdbeMemTooBig(pVar) ){ goto too_big; } - pOut = &p->aMem[k++]; + pOut = &p->aMem[p2++]; sqlite3VdbeMemReleaseExternal(pOut); pOut->flags = MEM_Null; sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static); @@ -1012,10 +1014,14 @@ case OP_Variable: { ** P1..P1+P3-1 and P2..P2+P3-1 to overlap. */ case OP_Move: { - char *zMalloc; - int n = pOp->p3; - int p1 = pOp->p1; - int p2 = pOp->p2; + char *zMalloc; /* Holding variable for allocated memory */ + int n; /* Number of registers left to copy */ + int p1; /* Register to copy from */ + int p2; /* Register to copy to */ + + n = pOp->p3; + p1 = pOp->p1; + p2 = pOp->p2; assert( n>0 && p1>0 && p2>0 ); assert( p1+n<=p2 || p2+n<=p1 ); @@ -1213,21 +1219,25 @@ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ - int flags; + int flags; /* Combined MEM_* flags from both inputs */ + i64 iA; /* Integer value of left operand */ + i64 iB; /* Integer value of right operand */ + double rA; /* Real value of left operand */ + double rB; /* Real value of right operand */ + applyNumericAffinity(pIn1); applyNumericAffinity(pIn2); flags = pIn1->flags | pIn2->flags; if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ - i64 a, b; - a = pIn1->u.i; - b = pIn2->u.i; + iA = pIn1->u.i; + iB = pIn2->u.i; switch( pOp->opcode ){ - case OP_Add: b += a; break; - case OP_Subtract: b -= a; break; - case OP_Multiply: b *= a; break; + case OP_Add: iB += iA; break; + case OP_Subtract: iB -= iA; break; + case OP_Multiply: iB *= iA; break; case OP_Divide: { - if( a==0 ) goto arithmetic_result_is_null; + if( iA==0 ) goto arithmetic_result_is_null; /* Dividing the largest possible negative 64-bit integer (1<<63) by ** -1 returns an integer too large to store in a 64-bit data-type. On ** some architectures, the value overflows to (1<<63). On others, @@ -1235,46 +1245,45 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ ** behavior so that all architectures behave as if integer ** overflow occurred. */ - if( a==-1 && b==SMALLEST_INT64 ) a = 1; - b /= a; + if( iA==-1 && iB==SMALLEST_INT64 ) iA = 1; + iB /= iA; break; } default: { - if( a==0 ) goto arithmetic_result_is_null; - if( a==-1 ) a = 1; - b %= a; + if( iA==0 ) goto arithmetic_result_is_null; + if( iA==-1 ) iA = 1; + iB %= iA; break; } } - pOut->u.i = b; + pOut->u.i = iB; MemSetTypeFlag(pOut, MEM_Int); }else{ - double a, b; - a = sqlite3VdbeRealValue(pIn1); - b = sqlite3VdbeRealValue(pIn2); + rA = sqlite3VdbeRealValue(pIn1); + rB = sqlite3VdbeRealValue(pIn2); switch( pOp->opcode ){ - case OP_Add: b += a; break; - case OP_Subtract: b -= a; break; - case OP_Multiply: b *= a; break; + case OP_Add: rB += rA; break; + case OP_Subtract: rB -= rA; break; + case OP_Multiply: rB *= rA; break; case OP_Divide: { /* (double)0 In case of SQLITE_OMIT_FLOATING_POINT... */ - if( a==(double)0 ) goto arithmetic_result_is_null; - b /= a; + if( rA==(double)0 ) goto arithmetic_result_is_null; + rB /= rA; break; } default: { - i64 ia = (i64)a; - i64 ib = (i64)b; - if( ia==0 ) goto arithmetic_result_is_null; - if( ia==-1 ) ia = 1; - b = (double)(ib % ia); + iA = rA; + iB = rB; + if( iA==0 ) goto arithmetic_result_is_null; + if( iA==-1 ) iA = 1; + rB = (double)(iB % iA); break; } } - if( sqlite3IsNaN(b) ){ + if( sqlite3IsNaN(rB) ){ goto arithmetic_result_is_null; } - pOut->r = b; + pOut->r = rB; MemSetTypeFlag(pOut, MEM_Real); if( (flags & MEM_Real)==0 ){ sqlite3VdbeIntegerAffinity(pOut); @@ -1324,8 +1333,9 @@ case OP_Function: { Mem *pArg; sqlite3_context ctx; sqlite3_value **apVal; - int n = pOp->p5; + int n; + n = pOp->p5; apVal = p->apArg; assert( apVal || n==0 ); @@ -1444,7 +1454,8 @@ case OP_BitAnd: /* same as TK_BITAND, in1, in2, out3 */ case OP_BitOr: /* same as TK_BITOR, in1, in2, out3 */ case OP_ShiftLeft: /* same as TK_LSHIFT, in1, in2, out3 */ case OP_ShiftRight: { /* same as TK_RSHIFT, in1, in2, out3 */ - i64 a, b; + i64 a; + i64 b; if( (pIn1->flags | pIn2->flags) & MEM_Null ){ sqlite3VdbeMemSetNull(pOut); @@ -1759,9 +1770,17 @@ case OP_Permutation: { ** and strings are less than blobs. */ case OP_Compare: { - int n = pOp->p3; - int i, p1, p2; - const KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; + int n; + int i; + int p1; + int p2; + const KeyInfo *pKeyInfo; + int idx; + CollSeq *pColl; /* Collating sequence to use on this term */ + int bRev; /* True for DESCENDING sort order */ + + n = pOp->p3; + pKeyInfo = pOp->p4.pKeyInfo; assert( n>0 ); assert( pKeyInfo!=0 ); p1 = pOp->p1; @@ -1769,9 +1788,7 @@ case OP_Compare: { p2 = pOp->p2; assert( p2>0 && p2+n<=p->nMem+1 ); for(i=0; iaMem[p1+idx]); REGISTER_TRACE(p2+idx, &p->aMem[p2+idx]); assert( inField ); @@ -1824,7 +1841,8 @@ case OP_Jump: { /* jump */ */ case OP_And: /* same as TK_AND, in1, in2, out3 */ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ - int v1, v2; /* 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ + int v1; /* Left operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ + int v2; /* Right operand: 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */ if( pIn1->flags & MEM_Null ){ v1 = 2; @@ -1983,9 +2001,10 @@ case OP_SetNumColumns: { */ case OP_Column: { int payloadSize; /* Number of bytes in the record */ - int p1 = pOp->p1; /* P1 value of the opcode */ - int p2 = pOp->p2; /* column number to retrieve */ - VdbeCursor *pC = 0;/* The VDBE cursor */ + i64 payloadSize64; /* Number of bytes in the record */ + int p1; /* P1 value of the opcode */ + int p2; /* column number to retrieve */ + VdbeCursor *pC; /* The VDBE cursor */ char *zRec; /* Pointer to complete record-data */ BtCursor *pCrsr; /* The BTree cursor */ u32 *aType; /* aType[i] holds the numeric type of the i-th column */ @@ -1996,7 +2015,16 @@ case OP_Column: { char *zData; /* Part of the record being decoded */ Mem *pDest; /* Where to write the extracted value */ Mem sMem; /* For storing the record being decoded */ + u8 *zIdx; /* Index into header */ + u8 *zEndHdr; /* Pointer to first byte after the header */ + int offset; /* Offset into the data */ + int szHdrSz; /* Size of the header size field at start of record */ + int avail; /* Number of bytes of available data */ + + p1 = pOp->p1; + p2 = pOp->p2; + pC = 0; memset(&sMem, 0, sizeof(sMem)); assert( p1nCursor ); assert( pOp->p3>0 && pOp->p3<=p->nMem ); @@ -2032,7 +2060,6 @@ case OP_Column: { payloadSize = pC->payloadSize; zRec = (char*)pC->aRow; }else if( pC->isIndex ){ - i64 payloadSize64; sqlite3BtreeKeySize(pCrsr, &payloadSize64); payloadSize = (int)payloadSize64; }else{ @@ -2068,13 +2095,8 @@ case OP_Column: { if( pC->cacheStatus==p->cacheCtr ){ aOffset = pC->aOffset; }else{ - u8 *zIdx; /* Index into header */ - u8 *zEndHdr; /* Pointer to first byte after the header */ - int offset; /* Offset into the data */ - int szHdrSz; /* Size of the header size field at start of record */ - int avail = 0; /* Number of bytes of available data */ - assert(aType); + avail = 0; pC->aOffset = aOffset = &aType[nField]; pC->payloadSize = payloadSize; pC->cacheStatus = p->cacheCtr; @@ -2152,7 +2174,7 @@ case OP_Column: { ** of the record (when all fields present), then we must be dealing ** with a corrupt database. */ - if( zIdx>zEndHdr || offset>payloadSize + if( (zIdx > zEndHdr)|| (offset > payloadSize) || (zIdx==zEndHdr && offset!=payloadSize) ){ rc = SQLITE_CORRUPT_BKPT; goto op_column_out; @@ -2221,11 +2243,14 @@ op_column_out: ** memory cell in the range. */ case OP_Affinity: { - char *zAffinity = pOp->p4.z; - Mem *pData0 = &p->aMem[pOp->p1]; - Mem *pLast = &pData0[pOp->p2-1]; - Mem *pRec; + char *zAffinity; /* The affinity to be applied */ + Mem *pData0; /* First register to which to apply affinity */ + Mem *pLast; /* Last register to which to apply affinity */ + Mem *pRec; /* Current register */ + zAffinity = pOp->p4.z; + pData0 = &p->aMem[pOp->p1]; + pLast = &pData0[pOp->p2-1]; for(pRec=pData0; pRec<=pLast; pRec++){ ExpandBlob(pRec); applyAffinity(pRec, zAffinity[pRec-pData0], encoding); @@ -2252,6 +2277,22 @@ case OP_Affinity: { ** If P4 is NULL then all index fields have the affinity NONE. */ case OP_MakeRecord: { + u8 *zNewRecord; /* A buffer to hold the data for the new record */ + Mem *pRec; /* The new record */ + u64 nData; /* Number of bytes of data space */ + int nHdr; /* Number of bytes of header space */ + i64 nByte; /* Data space required for this record */ + int nZero; /* Number of zero bytes at the end of the record */ + int nVarint; /* Number of bytes in a varint */ + u32 serial_type; /* Type field */ + Mem *pData0; /* First field to be combined into the record */ + Mem *pLast; /* Last field of the record */ + int nField; /* Number of fields in the record */ + char *zAffinity; /* The affinity string for the record */ + int file_format; /* File format to use for encoding */ + int i; /* Space used in zNewRecord[] */ + int len; /* Length of a field */ + /* Assuming the record contains N fields, the record format looks ** like this: ** @@ -2267,21 +2308,10 @@ case OP_MakeRecord: { ** hdr-size field is also a varint which is the offset from the beginning ** of the record to data0. */ - u8 *zNewRecord; /* A buffer to hold the data for the new record */ - Mem *pRec; /* The new record */ - u64 nData = 0; /* Number of bytes of data space */ - int nHdr = 0; /* Number of bytes of header space */ - i64 nByte = 0; /* Data space required for this record */ - int nZero = 0; /* Number of zero bytes at the end of the record */ - int nVarint; /* Number of bytes in a varint */ - u32 serial_type; /* Type field */ - Mem *pData0; /* First field to be combined into the record */ - Mem *pLast; /* Last field of the record */ - int nField; /* Number of fields in the record */ - char *zAffinity; /* The affinity string for the record */ - int file_format; /* File format to use for encoding */ - int i; /* Space used in zNewRecord[] */ - + nData = 0; /* Number of bytes of data space */ + nHdr = 0; /* Number of bytes of header space */ + nByte = 0; /* Data space required for this record */ + nZero = 0; /* Number of zero bytes at the end of the record */ nField = pOp->p1; zAffinity = pOp->p4.z; assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem+1 ); @@ -2294,7 +2324,6 @@ case OP_MakeRecord: { ** out how much space is required for the new record. */ for(pRec=pData0; pRec<=pLast; pRec++){ - int len; if( zAffinity ){ applyAffinity(pRec, zAffinity[pRec-pData0], encoding); } @@ -2404,9 +2433,10 @@ case OP_Count: { /* out2-prerelease */ ** has an index of 1. */ case OP_Statement: { + int i; + Btree *pBt; if( db->autoCommit==0 || db->activeVdbeCnt>1 ){ - int i = pOp->p1; - Btree *pBt; + i = pOp->p1; assert( i>=0 && inDb ); assert( db->aDb[i].pBt!=0 ); pBt = db->aDb[i].pBt; @@ -2429,8 +2459,17 @@ case OP_Statement: { ** existing savepoint, P1==1, or to rollback an existing savepoint P1==2. */ case OP_Savepoint: { - int p1 = pOp->p1; - char *zName = pOp->p4.z; /* Name of savepoint */ + int p1; /* Value of P1 operand */ + char *zName; /* Name of savepoint */ + int nName; + Savepoint *pNew; + Savepoint *pSavepoint; + Savepoint *pTmp; + int iSavepoint; + int ii; + + p1 = pOp->p1; + zName = pOp->p4.z; /* Assert that the p1 parameter is valid. Also that if there is no open ** transaction, then there cannot be any savepoints. @@ -2449,8 +2488,7 @@ case OP_Savepoint: { "SQL statements in progress"); rc = SQLITE_BUSY; }else{ - int nName = sqlite3Strlen30(zName); - Savepoint *pNew; + nName = sqlite3Strlen30(zName); /* Create a new savepoint structure. */ pNew = sqlite3DbMallocRaw(db, sizeof(Savepoint)+nName+1); @@ -2473,15 +2511,14 @@ case OP_Savepoint: { } } }else{ - Savepoint *pSavepoint; - int iSavepoint = 0; + iSavepoint = 0; /* Find the named savepoint. If there is no such savepoint, then an ** an error is returned to the user. */ for( - pSavepoint=db->pSavepoint; + pSavepoint = db->pSavepoint; pSavepoint && sqlite3StrICmp(pSavepoint->zName, zName); - pSavepoint=pSavepoint->pNext + pSavepoint = pSavepoint->pNext ){ iSavepoint++; } @@ -2518,7 +2555,6 @@ case OP_Savepoint: { db->isTransactionSavepoint = 0; rc = p->rc; }else{ - int ii; iSavepoint = db->nSavepoint - iSavepoint - 1; for(ii=0; iinDb; ii++){ rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint); @@ -2535,7 +2571,7 @@ case OP_Savepoint: { /* Regardless of whether this is a RELEASE or ROLLBACK, destroy all ** savepoints nested inside of the savepoint being operated on. */ while( db->pSavepoint!=pSavepoint ){ - Savepoint *pTmp = db->pSavepoint; + pTmp = db->pSavepoint; db->pSavepoint = pTmp->pNext; sqlite3DbFree(db, pTmp); db->nSavepoint--; @@ -2566,13 +2602,15 @@ case OP_Savepoint: { ** This instruction causes the VM to halt. */ case OP_AutoCommit: { - int desiredAutoCommit = pOp->p1; - int rollback = pOp->p2; - int turnOnAC = desiredAutoCommit && !db->autoCommit; + int desiredAutoCommit; + int rollback; + int turnOnAC; + desiredAutoCommit = pOp->p1; + rollback = pOp->p2; + turnOnAC = desiredAutoCommit && !db->autoCommit; assert( desiredAutoCommit==1 || desiredAutoCommit==0 ); assert( desiredAutoCommit==1 || rollback==0 ); - assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ if( turnOnAC && rollback && db->activeVdbeCnt>1 ){ @@ -2645,9 +2683,10 @@ case OP_AutoCommit: { ** If P2 is zero, then a read-lock is obtained on the database file. */ case OP_Transaction: { - int i = pOp->p1; + int i; Btree *pBt; + i = pOp->p1; assert( i>=0 && inDb ); assert( (p->btreeMask & (1<aDb[i].pBt; @@ -2685,9 +2724,11 @@ case OP_Transaction: { */ case OP_ReadCookie: { /* out2-prerelease */ int iMeta; - int iDb = pOp->p1; - int iCookie = pOp->p3; + int iDb; + int iCookie; + iDb = pOp->p1; + iCookie = pOp->p3; assert( pOp->p3p1; - int p2 = pOp->p2; - int iDb = pOp->p3; + int nField; + KeyInfo *pKeyInfo; + int i; + int p2; + int iDb; int wrFlag; Btree *pX; VdbeCursor *pCur; Db *pDb; - + int flags; + + nField = 0; + pKeyInfo = 0; + i = pOp->p1; + p2 = pOp->p2; + iDb = pOp->p3; assert( iDb>=0 && iDbnDb ); assert( (p->btreeMask & (1<aDb[iDb]; @@ -2905,7 +2952,7 @@ case OP_OpenWrite: { goto vdbe_return; } case SQLITE_OK: { - int flags = sqlite3BtreeFlags(pCur->pCursor); + flags = sqlite3BtreeFlags(pCur->pCursor); /* Sanity checking. Only the lower four bits of the flags byte should ** be used. Bit 3 (mask 0x08) is unpredictable. The lower 3 bits ** (mask 0x07) should be either 5 (intkey+leafdata for tables) or @@ -2962,7 +3009,7 @@ case OP_OpenWrite: { ** that created confusion with the whole virtual-table idea. */ case OP_OpenEphemeral: { - int i = pOp->p1; + int i; VdbeCursor *pCx; static const int openFlags = SQLITE_OPEN_READWRITE | @@ -2971,6 +3018,7 @@ case OP_OpenEphemeral: { SQLITE_OPEN_DELETEONCLOSE | SQLITE_OPEN_TRANSIENT_DB; + i = pOp->p1; assert( i>=0 ); pCx = allocateCursor(p, i, pOp->p2, -1, 1); if( pCx==0 ) goto no_mem; @@ -3031,8 +3079,10 @@ case OP_OpenEphemeral: { ** the pseudo-table. */ case OP_OpenPseudo: { - int i = pOp->p1; + int i; VdbeCursor *pCx; + + i = pOp->p1; assert( i>=0 ); pCx = allocateCursor(p, i, pOp->p3, -1, 0); if( pCx==0 ) goto no_mem; @@ -3113,20 +3163,23 @@ case OP_SeekLt: /* jump, in3 */ case OP_SeekLe: /* jump, in3 */ case OP_SeekGe: /* jump, in3 */ case OP_SeekGt: { /* jump, in3 */ - int i = pOp->p1; + int i; + int res; + int oc; VdbeCursor *pC; + UnpackedRecord r; + int nField; + i64 iKey; /* The rowid we are to seek to */ + i = pOp->p1; assert( i>=0 && inCursor ); assert( pOp->p2!=0 ); pC = p->apCsr[i]; assert( pC!=0 ); if( pC->pCursor!=0 ){ - int res, oc; oc = pOp->opcode; pC->nullRow = 0; if( pC->isTable ){ - i64 iKey; /* The rowid we are to seek to */ - /* The input value in P3 might be of any type: integer, real, string, ** blob, or NULL. But it needs to be an integer before we can do ** the seek, so covert it. */ @@ -3184,8 +3237,7 @@ case OP_SeekGt: { /* jump, in3 */ pC->lastRowid = iKey; } }else{ - UnpackedRecord r; - int nField = pOp->p4.i; + nField = pOp->p4.i; assert( pOp->p4type==P4_INT32 ); assert( nField>0 ); r.pKeyInfo = pC->pKeyInfo; @@ -3252,9 +3304,10 @@ case OP_SeekGt: { /* jump, in3 */ ** occur, no unnecessary I/O happens. */ case OP_Seek: { /* in2 */ - int i = pOp->p1; + int i; VdbeCursor *pC; + i = pOp->p1; assert( i>=0 && inCursor ); pC = p->apCsr[i]; assert( pC!=0 ); @@ -3301,14 +3354,18 @@ case OP_Seek: { /* in2 */ */ case OP_NotFound: /* jump, in3 */ case OP_Found: { /* jump, in3 */ - int i = pOp->p1; - int alreadyExists = 0; + int i; + int alreadyExists; VdbeCursor *pC; + int res; + UnpackedRecord *pIdxKey; + char aTempRec[ROUND8(sizeof(UnpackedRecord)) + sizeof(Mem)*3 + 7]; + + i = pOp->p1; + alreadyExists = 0; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor!=0 ){ - int res; - UnpackedRecord *pIdxKey; assert( pC->isTable==0 ); assert( pIn3->flags & MEM_Blob ); @@ -3367,8 +3424,11 @@ case OP_IsUnique: { /* jump, in3 */ VdbeCursor *pCx; BtCursor *pCrsr; u16 nField; - Mem *aMem = &p->aMem[pOp->p4.i]; + Mem *aMem; + UnpackedRecord r; /* B-Tree index search key */ + i64 R; /* Rowid stored in register P3 */ + aMem = &p->aMem[pOp->p4.i]; /* Assert that the values of parameters P1 and P4 are in range. */ assert( pOp->p4type==P4_INT32 ); assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem ); @@ -3393,9 +3453,6 @@ case OP_IsUnique: { /* jump, in3 */ assert( (aMem[nField].flags & MEM_Null)==0 ); if( pCrsr!=0 ){ - UnpackedRecord r; /* B-Tree index search key */ - i64 R; /* Rowid stored in register P3 */ - /* Populate the index search key. */ r.pKeyInfo = pCx->pKeyInfo; r.nField = nField + 1; @@ -3434,14 +3491,17 @@ case OP_IsUnique: { /* jump, in3 */ ** See also: Found, NotFound, IsUnique */ case OP_NotExists: { /* jump, in3 */ - int i = pOp->p1; + int i; VdbeCursor *pC; BtCursor *pCrsr; + int res; + u64 iKey; + + i = pOp->p1; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ - int res = 0; - u64 iKey; + res = 0; assert( pIn3->flags & MEM_Int ); assert( p->apCsr[i]->isTable ); iKey = intToKey(pIn3->u.i); @@ -3500,9 +3560,19 @@ case OP_Sequence: { /* out2-prerelease */ ** AUTOINCREMENT feature. */ case OP_NewRowid: { /* out2-prerelease */ - int i = pOp->p1; - i64 v = 0; + int i; + i64 v; VdbeCursor *pC; + int res; + int rx; + int cnt; + i64 x; + Mem *pMem; + + i = pOp->p1; + v = 0; + res = 0; + rx = SQLITE_OK; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor==0 ){ @@ -3539,8 +3609,6 @@ case OP_NewRowid: { /* out2-prerelease */ ** larger than the previous rowid. This has been shown experimentally ** to double the speed of the COPY operation. */ - int res=0, rx=SQLITE_OK, cnt; - i64 x; cnt = 0; if( (sqlite3BtreeFlags(pC->pCursor)&(BTREE_INTKEY|BTREE_ZERODATA)) != BTREE_INTKEY ){ @@ -3582,7 +3650,6 @@ case OP_NewRowid: { /* out2-prerelease */ #ifndef SQLITE_OMIT_AUTOINCREMENT if( pOp->p3 ){ - Mem *pMem; assert( pOp->p3>0 && pOp->p3<=p->nMem ); /* P3 is a valid memory cell */ pMem = &p->aMem[pOp->p3]; REGISTER_TRACE(pOp->p3, pMem); @@ -3659,12 +3726,20 @@ case OP_NewRowid: { /* out2-prerelease */ ** for indices is OP_IdxInsert. */ case OP_Insert: { - Mem *pData = &p->aMem[pOp->p2]; - Mem *pKey = &p->aMem[pOp->p3]; - + Mem *pData; + Mem *pKey; i64 iKey; /* The integer ROWID or key for the record to be inserted */ - int i = pOp->p1; + int i; VdbeCursor *pC; + int nZero; + int seekResult; + const char *zDb; + const char *zTbl; + int op; + + pData = &p->aMem[pOp->p2]; + pKey = &p->aMem[pOp->p3]; + i = pOp->p1; assert( i>=0 && inCursor ); pC = p->apCsr[i]; assert( pC!=0 ); @@ -3705,8 +3780,7 @@ case OP_Insert: { } pC->nullRow = 0; }else{ - int nZero; - int seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0); + seekResult = ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0); if( pData->flags & MEM_Zero ){ nZero = pData->u.nZero; }else{ @@ -3725,9 +3799,9 @@ case OP_Insert: { /* Invoke the update-hook if required. */ if( rc==SQLITE_OK && db->xUpdateCallback && pOp->p4.z ){ - const char *zDb = db->aDb[pC->iDb].zName; - const char *zTbl = pOp->p4.z; - int op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); + zDb = db->aDb[pC->iDb].zName; + zTbl = pOp->p4.z; + op = ((pOp->p5 & OPFLAG_ISUPDATE) ? SQLITE_UPDATE : SQLITE_INSERT); assert( pC->isTable ); db->xUpdateCallback(db->pUpdateArg, op, zDb, zTbl, iKey); assert( pC->iDb>=0 ); @@ -3756,10 +3830,12 @@ case OP_Insert: { ** using OP_NotFound prior to invoking this opcode. */ case OP_Delete: { - int i = pOp->p1; - i64 iKey = 0; + int i; + i64 iKey; VdbeCursor *pC; + i = pOp->p1; + iKey = 0; assert( i>=0 && inCursor ); pC = p->apCsr[i]; assert( pC!=0 ); @@ -3828,11 +3904,13 @@ case OP_ResetCount: { */ case OP_RowKey: case OP_RowData: { - int i = pOp->p1; + int i; VdbeCursor *pC; BtCursor *pCrsr; u32 n; + i64 n64; + i = pOp->p1; pOut = &p->aMem[pOp->p2]; /* Note that RowKey and RowData are really exactly the same instruction */ @@ -3848,7 +3926,6 @@ case OP_RowData: { rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; if( pC->isIndex ){ - i64 n64; assert( !pC->isTable ); sqlite3BtreeKeySize(pCrsr, &n64); if( n64>db->aLimit[SQLITE_LIMIT_LENGTH] ){ @@ -3886,10 +3963,13 @@ case OP_RowData: { ** one opcode now works for both table types. */ case OP_Rowid: { /* out2-prerelease */ - int i = pOp->p1; + int i; VdbeCursor *pC; i64 v; + sqlite3_vtab *pVtab; + const sqlite3_module *pModule; + i = pOp->p1; assert( i>=0 && inCursor ); pC = p->apCsr[i]; assert( pC!=0 ); @@ -3902,8 +3982,6 @@ case OP_Rowid: { /* out2-prerelease */ v = keyToInt(pC->iKey); #ifndef SQLITE_OMIT_VIRTUALTABLE }else if( pC->pVtabCursor ){ - sqlite3_vtab *pVtab; - const sqlite3_module *pModule; pVtab = pC->pVtabCursor->pVtab; pModule = pVtab->pModule; assert( pModule->xRowid ); @@ -3937,9 +4015,10 @@ case OP_Rowid: { /* out2-prerelease */ ** write a NULL. */ case OP_NullRow: { - int i = pOp->p1; + int i; VdbeCursor *pC; + i = pOp->p1; assert( i>=0 && inCursor ); pC = p->apCsr[i]; assert( pC!=0 ); @@ -3960,11 +4039,12 @@ case OP_NullRow: { ** to the following instruction. */ case OP_Last: { /* jump */ - int i = pOp->p1; + int i; VdbeCursor *pC; BtCursor *pCrsr; int res; + i = pOp->p1; assert( i>=0 && inCursor ); pC = p->apCsr[i]; assert( pC!=0 ); @@ -4011,11 +4091,12 @@ case OP_Sort: { /* jump */ ** to the following instruction. */ case OP_Rewind: { /* jump */ - int i = pOp->p1; + int i; VdbeCursor *pC; BtCursor *pCrsr; int res; + i = pOp->p1; assert( i>=0 && inCursor ); pC = p->apCsr[i]; assert( pC!=0 ); @@ -4100,9 +4181,13 @@ case OP_Next: { /* jump */ ** for tables is OP_Insert. */ case OP_IdxInsert: { /* in2 */ - int i = pOp->p1; + int i; VdbeCursor *pC; BtCursor *pCrsr; + int nKey; + const char *zKey; + + i = pOp->p1; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); assert( pIn2->flags & MEM_Blob ); @@ -4110,8 +4195,8 @@ case OP_IdxInsert: { /* in2 */ assert( pC->isTable==0 ); rc = ExpandBlob(pIn2); if( rc==SQLITE_OK ){ - int nKey = pIn2->n; - const char *zKey = pIn2->z; + nKey = pIn2->n; + zKey = pIn2->z; rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3, ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0) ); @@ -4129,9 +4214,11 @@ case OP_IdxInsert: { /* in2 */ ** index opened by cursor P1. */ case OP_IdxDelete: { - int i = pOp->p1; + int i; VdbeCursor *pC; BtCursor *pCrsr; + + i = pOp->p1; assert( pOp->p3>0 ); assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem+1 ); assert( i>=0 && inCursor ); @@ -4162,15 +4249,15 @@ case OP_IdxDelete: { ** See also: Rowid, MakeRecord. */ case OP_IdxRowid: { /* out2-prerelease */ - int i = pOp->p1; + int i; BtCursor *pCrsr; VdbeCursor *pC; + i64 rowid; - + i = pOp->p1; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ - i64 rowid; rc = sqlite3VdbeCursorMoveto(pC); if( rc ) goto abort_due_to_error; assert( pC->deferredMoveto==0 ); @@ -4215,14 +4302,15 @@ case OP_IdxRowid: { /* out2-prerelease */ */ case OP_IdxLT: /* jump, in3 */ case OP_IdxGE: { /* jump, in3 */ - int i= pOp->p1; + int i; VdbeCursor *pC; + int res; + UnpackedRecord r; + i = pOp->p1; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); if( (pC = p->apCsr[i])->pCursor!=0 ){ - int res; - UnpackedRecord r; assert( pC->deferredMoveto==0 ); assert( pOp->p5==0 || pOp->p5==1 ); assert( pOp->p4type==P4_INT32 ); @@ -4271,10 +4359,11 @@ case OP_IdxGE: { /* jump, in3 */ case OP_Destroy: { /* out2-prerelease */ int iMoved; int iCnt; -#ifndef SQLITE_OMIT_VIRTUALTABLE Vdbe *pVdbe; + int iDb; +#ifndef SQLITE_OMIT_VIRTUALTABLE iCnt = 0; - for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ + for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){ if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->inVtabMethod<2 && pVdbe->pc>=0 ){ iCnt++; } @@ -4286,7 +4375,7 @@ case OP_Destroy: { /* out2-prerelease */ rc = SQLITE_LOCKED; p->errorAction = OE_Abort; }else{ - int iDb = pOp->p3; + iDb = pOp->p3; assert( iCnt==1 ); assert( (p->btreeMask & (1<aDb[iDb].pBt, pOp->p1, &iMoved); @@ -4320,7 +4409,9 @@ case OP_Destroy: { /* out2-prerelease */ ** See also: Destroy */ case OP_Clear: { - int nChange = 0; + int nChange; + + nChange = 0; assert( (p->btreeMask & (1<p2))!=0 ); rc = sqlite3BtreeClearTable( db->aDb[pOp->p2].pBt, pOp->p1, (pOp->p3 ? &nChange : 0) @@ -4358,9 +4449,11 @@ case OP_Clear: { */ case OP_CreateIndex: /* out2-prerelease */ case OP_CreateTable: { /* out2-prerelease */ - int pgno = 0; + int pgno; int flags; Db *pDb; + + pgno = 0; assert( pOp->p1>=0 && pOp->p1nDb ); assert( (p->btreeMask & (1<p1))!=0 ); pDb = &db->aDb[pOp->p1]; @@ -4390,7 +4483,12 @@ case OP_CreateTable: { /* out2-prerelease */ ** then runs the new virtual machine. It is thus a re-entrant opcode. */ case OP_ParseSchema: { - int iDb = pOp->p1; + int iDb; + const char *zMaster; + char *zSql; + InitData initData; + + iDb = pOp->p1; assert( iDb>=0 && iDbnDb ); /* If pOp->p2 is 0, then this opcode is being executed to read a @@ -4417,9 +4515,7 @@ case OP_ParseSchema: { assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) ); sqlite3BtreeEnterAll(db); if( pOp->p2 || DbHasProperty(db, iDb, DB_SchemaLoaded) ){ - const char *zMaster = SCHEMA_TABLE(iDb); - char *zSql; - InitData initData; + zMaster = SCHEMA_TABLE(iDb); initData.db = db; initData.iDb = pOp->p1; initData.pzErrMsg = &p->zErrMsg; @@ -4456,9 +4552,8 @@ case OP_ParseSchema: { ** the analysis to be used when preparing all subsequent queries. */ case OP_LoadAnalysis: { - int iDb = pOp->p1; - assert( iDb>=0 && iDbnDb ); - rc = sqlite3AnalysisLoad(db, iDb); + assert( pOp->p1>=0 && pOp->p1nDb ); + rc = sqlite3AnalysisLoad(db, pOp->p1); break; } #endif /* !defined(SQLITE_OMIT_ANALYZE) && !defined(SQLITE_OMIT_PARSER) */ @@ -4636,7 +4731,10 @@ case OP_RowSetRead: { /* jump, out3 */ ** inserted as part of some other set). */ case OP_RowSetTest: { /* jump, in1, in3 */ - int iSet = pOp->p4.i; + int iSet; + int exists; + + iSet = pOp->p4.i; assert( pIn3->flags&MEM_Int ); /* If there is anything other than a rowset object in memory cell P1, @@ -4650,7 +4748,6 @@ case OP_RowSetTest: { /* jump, in1, in3 */ assert( pOp->p4type==P4_INT32 ); assert( iSet==-1 || iSet>=0 ); if( iSet ){ - int exists; exists = sqlite3RowSetTest(pIn1->u.pRowSet, (u8)(iSet>=0 ? iSet & 0xf : 0xff), pIn3->u.i); @@ -4674,9 +4771,10 @@ case OP_RowSetTest: { /* jump, in1, in3 */ ** count, and the current statement change count. */ case OP_ContextPush: { - int i = p->contextStackTop++; + int i; Context *pContext; + i = p->contextStackTop++; assert( i>=0 ); /* FIX ME: This should be allocated as part of the vdbe at compile-time */ if( i>=p->contextStackDepth ){ @@ -4698,7 +4796,8 @@ case OP_ContextPush: { ** change count, and the current statement change count. */ case OP_ContextPop: { - Context *pContext = &p->contextStack[--p->contextStackTop]; + Context *pContext; + pContext = &p->contextStack[--p->contextStackTop]; assert( p->contextStackTop>=0 ); db->lastRowid = pContext->lastRowid; p->nChange = pContext->nChange; @@ -4781,12 +4880,13 @@ case OP_IfZero: { /* jump, in1 */ ** successors. */ case OP_AggStep: { - int n = pOp->p5; + int n; int i; Mem *pMem, *pRec; sqlite3_context ctx; sqlite3_value **apVal; + n = pOp->p5; assert( n>=0 ); pRec = &p->aMem[pOp->p2]; apVal = p->apArg; @@ -4922,8 +5022,11 @@ case OP_Expire: { ** used to generate an error message if the lock cannot be obtained. */ case OP_TableLock: { - int p1 = pOp->p1; - u8 isWriteLock = (u8)pOp->p3; + int p1; + u8 isWriteLock; + + p1 = pOp->p1; + isWriteLock = (u8)pOp->p3; assert( p1>=0 && p1nDb ); assert( (p->btreeMask & (1<p4.pVtab; + sqlite3_vtab *pVtab; + pVtab = pOp->p4.pVtab; rc = sqlite3VtabBegin(db, pVtab); if( pVtab ){ sqlite3DbFree(db, p->zErrMsg); @@ -4992,12 +5096,15 @@ case OP_VDestroy: { ** table and stores that cursor in P1. */ case OP_VOpen: { - VdbeCursor *pCur = 0; - sqlite3_vtab_cursor *pVtabCursor = 0; - - sqlite3_vtab *pVtab = pOp->p4.pVtab; - sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; + VdbeCursor *pCur; + sqlite3_vtab_cursor *pVtabCursor; + sqlite3_vtab *pVtab; + sqlite3_module *pModule; + pCur = 0; + pVtabCursor = 0; + pVtab = pOp->p4.pVtab; + pModule = (sqlite3_module *)pVtab->pModule; assert(pVtab && pModule); if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; rc = pModule->xOpen(pVtab, &pVtabCursor); @@ -5046,13 +5153,18 @@ case OP_VFilter: { /* jump */ int nArg; int iQuery; const sqlite3_module *pModule; - Mem *pQuery = &p->aMem[pOp->p3]; - Mem *pArgc = &pQuery[1]; + Mem *pQuery; + Mem *pArgc; sqlite3_vtab_cursor *pVtabCursor; sqlite3_vtab *pVtab; + VdbeCursor *pCur; + int res; + int i; + Mem **apArg; - VdbeCursor *pCur = p->apCsr[pOp->p1]; - + pQuery = &p->aMem[pOp->p3]; + pArgc = &pQuery[1]; + pCur = p->apCsr[pOp->p1]; REGISTER_TRACE(pOp->p3, pQuery); assert( pCur->pVtabCursor ); pVtabCursor = pCur->pVtabCursor; @@ -5066,9 +5178,8 @@ case OP_VFilter: { /* jump */ /* Invoke the xFilter method */ { - int res = 0; - int i; - Mem **apArg = p->apArg; + res = 0; + apArg = p->apArg; for(i = 0; iapCsr[pOp->p1]; + pCur = p->apCsr[pOp->p1]; assert( pCur->pVtabCursor ); if( pCur->nullRow ){ break; @@ -5214,8 +5326,11 @@ case OP_VNext: { /* jump */ ** in register P1 is passed as the zName argument to the xRename method. */ case OP_VRename: { - sqlite3_vtab *pVtab = pOp->p4.pVtab; - Mem *pName = &p->aMem[pOp->p1]; + sqlite3_vtab *pVtab; + Mem *pName; + + pVtab = pOp->p4.pVtab; + pName = &p->aMem[pOp->p1]; assert( pVtab->pModule->xRename ); REGISTER_TRACE(pOp->p1, pName); @@ -5259,18 +5374,24 @@ case OP_VRename: { ** is set to the value of the rowid for the row just inserted. */ case OP_VUpdate: { - sqlite3_vtab *pVtab = pOp->p4.pVtab; - sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; - int nArg = pOp->p2; + sqlite3_vtab *pVtab; + sqlite3_module *pModule; + int nArg; + int i; + sqlite_int64 rowid; + Mem **apArg; + Mem *pX; + + pVtab = pOp->p4.pVtab; + pModule = (sqlite3_module *)pVtab->pModule; + nArg = pOp->p2; assert( pOp->p4type==P4_VTAB ); if( pModule->xUpdate==0 ){ sqlite3SetString(&p->zErrMsg, db, "read-only table"); rc = SQLITE_ERROR; }else{ - int i; - sqlite_int64 rowid; - Mem **apArg = p->apArg; - Mem *pX = &p->aMem[pOp->p3]; + apArg = p->apArg; + pX = &p->aMem[pOp->p3]; for(i=0; ip1; + int p1; int nPage; - Pager *pPager = sqlite3BtreePager(db->aDb[p1].pBt); + Pager *pPager; + p1 = pOp->p1; + pPager = sqlite3BtreePager(db->aDb[p1].pBt); rc = sqlite3PagerPagecount(pPager, &nPage); if( rc==SQLITE_OK ){ pOut->flags = MEM_Int; @@ -5320,7 +5443,9 @@ case OP_Pagecount: { /* out2-prerelease */ ** the UTF-8 string contained in P4 is emitted on the trace callback. */ case OP_Trace: { - char *zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); + char *zTrace; + + zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql); if( zTrace ){ if( db->xTrace ){ db->xTrace(db->pTraceArg, zTrace); diff --git a/tool/vdbe-compress.tcl b/tool/vdbe-compress.tcl new file mode 100644 index 0000000000..81f2da06d5 --- /dev/null +++ b/tool/vdbe-compress.tcl @@ -0,0 +1,124 @@ +#!/usr/bin/tcl +# +# This script makes modifications to the vdbe.c source file which reduce +# the amount of stack space required by the sqlite3VdbeExec() routine. +# +# The modifications performed by this script are optional. The vdbe.c +# source file will compile correctly with and without the modifications +# performed by this script. And all routines within vdbe.c will compute +# the same result. The modifications made by this script merely help +# the C compiler to generate code for sqlite3VdbeExec() that uses less +# stack space. +# +# Script usage: +# +# mv vdbe.c vdbe.c.template +# tclsh vdbe-compress.tcl vdbe.c +# +# Modifications made: +# +# All modifications are within the sqlite3VdbeExec() function. The +# modifications seek to reduce the amount of stack space allocated by +# this routine by moving local variable declarations out of individual +# opcode implementations and into a single large union. The union contains +# a separate structure for each opcode and that structure contains the +# local variables used by that opcode. In this way, the total amount +# of stack space required by sqlite3VdbeExec() is reduced from the +# sum of all local variables to the maximum of the local variable space +# required for any single opcode. +# +# In order to be recognized by this script, local variables must appear +# on the first line after the open curly-brace that begins a new opcode +# implementation. Local variables must not have initializers, though they +# may be commented. +# +# The union definition is inserted in place of a special marker comment +# in the preamble to the sqlite3VdbeExec() implementation. +# +############################################################################# +# +set beforeUnion {} ;# C code before union +set unionDef {} ;# C code of the union +set afterUnion {} ;# C code after the union +set sCtr 0 ;# Context counter + +# Read program text up to the spot where the union should be +# inserted. +# +while {![eof stdin]} { + set line [gets stdin] + if {[regexp {INSERT STACK UNION HERE} $line]} break + append beforeUnion $line\n +} + +# Process the remaining text. Build up the union definition as we go. +# +set vlist {} +set seenDecl 0 +set namechars {abcdefghijklmnopqrstuvwxyz} +set nnc [string length $namechars] +while {![eof stdin]} { + set line [gets stdin] + if {[regexp "^case (OP_\\w+): \173" $line all operator]} { + append afterUnion $line\n + set vlist {} + while {![eof stdin]} { + set line [gets stdin] + if {[regexp {^ +(const )?\w+ \*?(\w+)(\[.*\])?;} $line \ + all constKeyword vname notused1]} { + if {!$seenDecl} { + set sname {} + append sname [string index $namechars [expr {$sCtr/$nnc}]] + append sname [string index $namechars [expr {$sCtr%$nnc}]] + incr sCtr + append unionDef " struct ${operator}_stack_vars \173\n" + append afterUnion \ + "#if 0 /* local variables moved into u.$sname */\n" + set seenDecl 1 + } + append unionDef " $line\n" + append afterUnion $line\n + lappend vlist $vname + } else { + break + } + } + if {$seenDecl} { + append unionDef " \175 $sname;\n" + append afterUnion "#endif /* local variables moved into u.$sname */\n" + } + set seenDecl 0 + } + if {[regexp "^\175" $line]} { + append afterUnion $line\n + set vlist {} + } elseif {[llength $vlist]>0} { + append line " " + foreach v $vlist { + regsub -all "(\[^a-zA-Z0-9>.\])${v}(\\W)" $line "\\1u.$sname.$v\\2" line + } + append afterUnion [string trimright $line]\n + } elseif {$line=="" && [eof stdin]} { + # no-op + } else { + append afterUnion $line\n + } +} + +# Output the resulting text. +# +puts -nonewline $beforeUnion +puts " /********************************************************************" +puts " ** Automatically generated code" +puts " **" +puts " ** The following union is automatically generated by the" +puts " ** vdbe-compress.tcl script. The purpose of this union is to" +puts " ** reduce the amount of stack space required by this function." +puts " ** See comments in the vdbe-compress.tcl script for details." +puts " */" +puts " union vdbeExecUnion \173" +puts -nonewline $unionDef +puts " \175 u;" +puts " /* End automatically generated code" +puts " ********************************************************************/" +puts -nonewline $afterUnion