diff --git a/manifest b/manifest index a0d0ce4cf1..d7418dfe8f 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Rework\sthe\sVDBE\sdata\sstructures\sto\scombine\sstring\srepresentations\sinto\sthe\nsame\sstructure\swith\sinteger\sand\sfloating\spoint.\s\sThis\sopens\sthe\sdoor\sto\nsignificant\soptimizations.\s(CVS\s1202) -D 2004-01-30T14:49:17 +C Rework\sinternal\sdata\sstructures\sto\smake\sthe\sVDBE\sabout\s15%\ssmaller.\s(CVS\s1203) +D 2004-01-31T19:22:56 F Makefile.in 0515ff9218ad8d5a8f6220f0494b8ef94c67013b F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -61,10 +61,10 @@ F src/trigger.c ce83e017b407d046e909d05373d7f8ee70f9f7f9 F src/update.c 24260b4fda00c9726d27699a0561d53c0dccc397 F src/util.c 64995b5949a5d377629ffd2598747bc771cade1e F src/vacuum.c 77485a64a6e4e358170f150fff681c1624a092b0 -F src/vdbe.c fcd5b6f27b3041ef022cf04ecaf63bbdccf88950 +F src/vdbe.c 36a93b5e213100b4c25ca614e69b74a5056154d6 F src/vdbe.h 3957844e46fea71fd030e78f6a3bd2f7e320fb43 -F src/vdbeInt.h 6f12f5b9344cbb0e5cc2277458d84f7b951122bf -F src/vdbeaux.c 358d955a23d29e268a3b45c428e49292b89dfcf5 +F src/vdbeInt.h 8a3baf749115cba81a810b7a52208aef055eda7b +F src/vdbeaux.c c55d87d6658487e87ef09ca80c1aa2f314024fed F src/where.c 1302d728bd338c237e6a8282e4e3eadbbdf11e45 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 F test/attach.test c26848402e7ac829e043e1fa5e0eb87032e5d81d @@ -147,7 +147,7 @@ F test/where.test cb3a2ed062ce4b5f08aff2d08027c6a46d68c47b F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/lemon.c e37dcb5b8cdb16f4ac98338134bf8d8cd28e399f F tool/lempar.c 0b5e7a58634e0d448929b8e85f7981c2aa708d57 -F tool/memleak.awk 16ef9493dcd36146f806e75148f4bb0201a123ec +F tool/memleak.awk b744b6109566206c746d826f6ecdba34662216bc F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8 F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c @@ -182,7 +182,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P af73fbca839f8cbe39c21f1f9e439fe9b79005c8 -R 498fe1480c9c56c03607a7a6c9f9b96c +P c0faa1c67a967f028cd018e58988fb08bc814d3d +R ee0cff331d148b843c9a28e532dc12e0 U drh -Z 222ac74ccb7f92ccb269c2c94a8bca52 +Z 9c3d28234884b5bb6cce05f45417ae61 diff --git a/manifest.uuid b/manifest.uuid index c18d5a8d3c..4f458f6a65 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c0faa1c67a967f028cd018e58988fb08bc814d3d \ No newline at end of file +8273c74bd09d1a044cb5154498b0a39939f6e3ed \ No newline at end of file diff --git a/src/vdbe.c b/src/vdbe.c index 86499f9080..5bac6745e7 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.252 2004/01/30 14:49:17 drh Exp $ +** $Id: vdbe.c,v 1.253 2004/01/31 19:22:56 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -182,9 +182,8 @@ static AggElem *_AggInFocus(Agg *p){ ** Convert the given stack entity into a string if it isn't one ** already. */ -#define Stringify(P,I) if((aStack[I].flags & MEM_Str)==0){hardStringify(P,I);} -static int hardStringify(Vdbe *p, int i){ - Mem *pStack = &p->aStack[i]; +#define Stringify(P) if(((P)->flags & MEM_Str)==0){hardStringify(P);} +static int hardStringify(Mem *pStack){ int fg = pStack->flags; if( fg & MEM_Real ){ sqlite_snprintf(sizeof(pStack->zShort),pStack->zShort,"%.15g",pStack->r); @@ -193,9 +192,9 @@ static int hardStringify(Vdbe *p, int i){ }else{ pStack->zShort[0] = 0; } - p->aStack[i].z = pStack->zShort; + pStack->z = pStack->zShort; pStack->n = strlen(pStack->zShort)+1; - pStack->flags = MEM_Str; + pStack->flags = MEM_Str | MEM_Short; return 0; } @@ -206,19 +205,18 @@ static int hardStringify(Vdbe *p, int i){ ** will fit but this routine always mallocs for space. ** Return non-zero if we run out of memory. */ -#define Dynamicify(P,I) ((aStack[I].flags & MEM_Dyn)==0 ? hardDynamicify(P,I):0) -static int hardDynamicify(Vdbe *p, int i){ - Mem *pStack = &p->aStack[i]; +#define Dynamicify(P) (((P)->flags & MEM_Dyn)==0 ? hardDynamicify(P):0) +static int hardDynamicify(Mem *pStack){ int fg = pStack->flags; char *z; if( (fg & MEM_Str)==0 ){ - hardStringify(p, i); + hardStringify(pStack); } assert( (fg & MEM_Dyn)==0 ); z = sqliteMallocRaw( pStack->n ); if( z==0 ) return 1; - memcpy(z, p->aStack[i].z, pStack->n); - p->aStack[i].z = z; + memcpy(z, pStack->z, pStack->n); + pStack->z = z; pStack->flags |= MEM_Dyn; return 0; } @@ -234,10 +232,9 @@ static int hardDynamicify(Vdbe *p, int i){ ** string that the stack entry itself controls. In other words, it ** converts an MEM_Ephem string into an MEM_Dyn string. */ -#define Deephemeralize(P,I) \ - if( ((P)->aStack[I].flags&MEM_Ephem)!=0 && hardDeephem(P,I) ){ goto no_mem;} -static int hardDeephem(Vdbe *p, int i){ - Mem *pStack = &p->aStack[i]; +#define Deephemeralize(P) \ + if( ((P)->flags&MEM_Ephem)!=0 && hardDeephem(P) ){ goto no_mem;} +static int hardDeephem(Mem *pStack){ char *z; assert( (pStack->flags & MEM_Ephem)!=0 ); z = sqliteMallocRaw( pStack->n ); @@ -250,13 +247,22 @@ static int hardDeephem(Vdbe *p, int i){ } /* -** Release the memory associated with the given stack level +** Release the memory associated with the given stack level. This +** leaves the Mem.flags field in an inconsistent state. */ -#define Release(P,I) if((P)->aStack[I].flags&MEM_Dyn){ hardRelease(P,I); } -static void hardRelease(Vdbe *p, int i){ - sqliteFree(p->aStack[i].z); - p->aStack[i].z = 0; - p->aStack[i].flags &= ~(MEM_Str|MEM_Dyn|MEM_Static|MEM_Ephem); +#define Release(P) if((P)->flags&MEM_Dyn){ sqliteFree((P)->z); } + +/* +** Pop the stack N times. +*/ +static void popStack(Mem **ppTos, int N){ + Mem *pTos = *ppTos; + while( N>0 ){ + N--; + Release(pTos); + pTos--; + } + *ppTos = pTos; } /* @@ -295,19 +301,18 @@ static int toInt(const char *zNum, int *pNum){ ** Any prior string or real representation is invalidated. ** NULLs are converted into 0. */ -#define Integerify(P,I) \ - if(((P)->aStack[(I)].flags&MEM_Int)==0){ hardIntegerify(P,I); } -static void hardIntegerify(Vdbe *p, int i){ - if( p->aStack[i].flags & MEM_Real ){ - p->aStack[i].i = (int)p->aStack[i].r; - Release(p, i); - }else if( p->aStack[i].flags & MEM_Str ){ - toInt(p->aStack[i].z, &p->aStack[i].i); - Release(p, i); +#define Integerify(P) if(((P)->flags&MEM_Int)==0){ hardIntegerify(P); } +static void hardIntegerify(Mem *pStack){ + if( pStack->flags & MEM_Real ){ + pStack->i = (int)pStack->r; + Release(pStack); + }else if( pStack->flags & MEM_Str ){ + toInt(pStack->z, &pStack->i); + Release(pStack); }else{ - p->aStack[i].i = 0; + pStack->i = 0; } - p->aStack[i].flags = MEM_Int; + pStack->flags = MEM_Int; } /* @@ -316,17 +321,16 @@ static void hardIntegerify(Vdbe *p, int i){ ** Any prior string or integer representation is retained. ** NULLs are converted into 0.0. */ -#define Realify(P,I) \ - if(((P)->aStack[(I)].flags&MEM_Real)==0){ hardRealify(P,I); } -static void hardRealify(Vdbe *p, int i){ - if( p->aStack[i].flags & MEM_Str ){ - p->aStack[i].r = sqliteAtoF(p->aStack[i].z); - }else if( p->aStack[i].flags & MEM_Int ){ - p->aStack[i].r = p->aStack[i].i; +#define Realify(P) if(((P)->flags&MEM_Real)==0){ hardRealify(P); } +static void hardRealify(Mem *pStack){ + if( pStack->flags & MEM_Str ){ + pStack->r = sqliteAtoF(pStack->z); + }else if( pStack->flags & MEM_Int ){ + pStack->r = pStack->i; }else{ - p->aStack[i].r = 0.0; + pStack->r = 0.0; } - p->aStack[i].flags |= MEM_Real; + pStack->flags |= MEM_Real; } /* @@ -361,17 +365,6 @@ static Sorter *Merge(Sorter *pLeft, Sorter *pRight){ return sHead.pNext; } -/* -** Code contained within the VERIFY() macro is not needed for correct -** execution. It is there only to catch errors. So when we compile -** with NDEBUG=1, the VERIFY() code is omitted. -*/ -#ifdef NDEBUG -# define VERIFY(X) -#else -# define VERIFY(X) X -#endif - /* ** The following routine works like a replacement for the standard ** library routine fgets(). The difference is in how end-of-line (EOL) @@ -485,7 +478,7 @@ int sqliteVdbeExec( Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ sqlite *db = p->db; /* The database */ - Mem *aStack = p->aStack; /* The operand stack */ + Mem *pTos; /* Top entry in the operand stack */ char zBuf[100]; /* Space to sprintf() an integer */ #ifdef VDBE_PROFILE unsigned long long start; /* CPU clock count at start of opcode */ @@ -501,13 +494,14 @@ int sqliteVdbeExec( p->rc = SQLITE_OK; assert( p->explain==0 ); if( sqlite_malloc_failed ) goto no_mem; + pTos = p->pTos; if( p->popStack ){ - sqliteVdbePopStack(p, p->popStack); + popStack(&pTos, p->popStack); p->popStack = 0; } for(pc=p->pc; rc==SQLITE_OK; pc++){ assert( pc>=0 && pcnOp ); - assert( p->tos<=pc ); + assert( pTos<=&p->aStack[pc] ); #ifdef VDBE_PROFILE origPc = pc; start = hwtime(); @@ -639,6 +633,7 @@ case OP_Return: { */ case OP_Halt: { p->magic = VDBE_MAGIC_HALT; + p->pTos = pTos; if( pOp->p1!=SQLITE_OK ){ p->rc = pOp->p1; p->errorAction = pOp->p2; @@ -658,13 +653,13 @@ case OP_Halt: { ** then it is assumed to be a string representation of the same integer. */ case OP_Integer: { - int i = ++p->tos; - aStack[i].i = pOp->p1; - aStack[i].flags = MEM_Int; + pTos++; + pTos->i = pOp->p1; + pTos->flags = MEM_Int; if( pOp->p3 ){ - aStack[i].z = pOp->p3; - aStack[i].flags |= MEM_Str | MEM_Static; - aStack[i].n = strlen(pOp->p3)+1; + pTos->z = pOp->p3; + pTos->flags |= MEM_Str | MEM_Static; + pTos->n = strlen(pOp->p3)+1; } break; } @@ -675,17 +670,14 @@ case OP_Integer: { ** NULL is pushed onto the stack. */ case OP_String: { - int i = ++p->tos; - char *z; - z = pOp->p3; + char *z = pOp->p3; + pTos++; if( z==0 ){ - aStack[i].z = 0; - aStack[i].n = 0; - aStack[i].flags = MEM_Null; + pTos->flags = MEM_Null; }else{ - aStack[i].z = z; - aStack[i].n = strlen(z) + 1; - aStack[i].flags = MEM_Str | MEM_Static; + pTos->z = z; + pTos->n = strlen(z) + 1; + pTos->flags = MEM_Str | MEM_Static; } break; } @@ -700,16 +692,14 @@ case OP_String: { ** sqlite_bind() API. */ case OP_Variable: { - int i = ++p->tos; int j = pOp->p1 - 1; + pTos++; if( j>=0 && jnVar && p->azVar[j]!=0 ){ - aStack[i].z = p->azVar[j]; - aStack[i].n = p->anVar[j]; - aStack[i].flags = MEM_Str | MEM_Static; + pTos->z = p->azVar[j]; + pTos->n = p->anVar[j]; + pTos->flags = MEM_Str | MEM_Static; }else{ - aStack[i].z = 0; - aStack[i].n = 0; - aStack[i].flags = MEM_Null; + pTos->flags = MEM_Null; } break; } @@ -719,8 +709,9 @@ case OP_Variable: { ** P1 elements are popped off of the top of stack and discarded. */ case OP_Pop: { - assert( p->tos+1>=pOp->p1 ); - sqliteVdbePopStack(p, pOp->p1); + assert( pOp->p1>=0 ); + popStack(&pTos, pOp->p1); + assert( pTos>=&p->aStack[-1] ); break; } @@ -740,26 +731,23 @@ case OP_Pop: { ** Also see the Pull instruction. */ case OP_Dup: { - int i = p->tos - pOp->p1; - int j = ++p->tos; - VERIFY( if( i<0 ) goto not_enough_stack; ) - memcpy(&aStack[j], &aStack[i], sizeof(aStack[i])-NBFS); - if( aStack[j].flags & MEM_Str ){ - int isStatic = (aStack[j].flags & MEM_Static)!=0; - if( pOp->p2 || isStatic ){ - aStack[j].z = aStack[i].z; - aStack[j].flags &= ~MEM_Dyn; - if( !isStatic ) aStack[j].flags |= MEM_Ephem; - }else if( aStack[i].n<=NBFS ){ - memcpy(aStack[j].zShort, aStack[i].z, aStack[j].n); - aStack[j].z = aStack[j].zShort; - aStack[j].flags &= ~(MEM_Static|MEM_Dyn|MEM_Ephem); - }else{ - aStack[j].z = sqliteMallocRaw( aStack[j].n ); - if( aStack[j].z==0 ) goto no_mem; - memcpy(aStack[j].z, aStack[i].z, aStack[j].n); - aStack[j].flags &= ~(MEM_Static|MEM_Ephem); - aStack[j].flags |= MEM_Dyn; + Mem *pFrom = &pTos[-pOp->p1]; + assert( pFrom<=pTos && pFrom>=p->aStack ); + pTos++; + memcpy(pTos, pFrom, sizeof(*pFrom)-NBFS); + if( pTos->flags & MEM_Str ){ + if( pOp->p2 && (pTos->flags & (MEM_Dyn|MEM_Ephem)) ){ + pTos->flags &= ~MEM_Dyn; + pTos->flags |= MEM_Ephem; + }else if( pTos->flags & MEM_Short ){ + memcpy(pTos->zShort, pFrom->zShort, pTos->n); + pTos->z = pTos->zShort; + }else if( (pTos->flags & MEM_Static)==0 ){ + pTos->z = sqliteMallocRaw(pFrom->n); + if( sqlite_malloc_failed ) goto no_mem; + memcpy(pTos->z, pFrom->z, pFrom->n); + pTos->flags &= ~(MEM_Static|MEM_Ephem|MEM_Short); + pTos->flags |= MEM_Dyn; } } break; @@ -776,28 +764,31 @@ case OP_Dup: { ** See also the Dup instruction. */ case OP_Pull: { - int from = p->tos - pOp->p1; - int to = p->tos; + Mem *pFrom = &pTos[-pOp->p1]; int i; Mem ts; - VERIFY( if( from<0 ) goto not_enough_stack; ) - Deephemeralize(p, from); - ts = aStack[from]; - Deephemeralize(p, to); - for(i=from; ip1; i++, pFrom++){ + Deephemeralize(&pFrom[1]); + *pFrom = pFrom[1]; + assert( (pFrom->flags & MEM_Ephem)==0 ); + if( pFrom->flags & MEM_Short ){ + assert( pFrom->flags & MEM_Str ); + assert( pFrom->z==pFrom[1].zShort ); + assert( (pTos->flags & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 ); + pFrom->z = pFrom->zShort; } } - aStack[to] = ts; - assert( (aStack[to].flags & MEM_Ephem)==0 ); - if( (aStack[to].flags & (MEM_Dyn|MEM_Static))==0 ){ - aStack[to].z = aStack[to].zShort; + *pTos = ts; + /* assert( (pTos->flags & MEM_Ephem)==0 ); *** not needed */ + if( pTos->flags & MEM_Short ){ + assert( pTos->flags & MEM_Str ); + assert( pTos->z==pTos[-pOp->p1].zShort ); + assert( (pTos->flags & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 ); + pTos->z = pTos->zShort; } break; } @@ -809,25 +800,21 @@ case OP_Pull: { ** of the top of the stack. Then pop the top of the stack. */ case OP_Push: { - int from = p->tos; - int to = p->tos - pOp->p1; + Mem *pTo = &pTos[-pOp->p1]; - VERIFY( if( to<0 ) goto not_enough_stack; ) - if( aStack[to].flags & MEM_Dyn ){ - sqliteFree(aStack[to].z); + assert( pTo>=p->aStack ); + Deephemeralize(pTos); + Release(pTo); + *pTo = *pTos; + if( pTo->flags & MEM_Short ){ + assert( pTo->z==pTos->zShort ); + pTo->z = pTo->zShort; } - Deephemeralize(p, from); - aStack[to] = aStack[from]; - if( aStack[to].flags & (MEM_Dyn|MEM_Static|MEM_Ephem) ){ - aStack[to].z = aStack[from].z; - }else{ - aStack[to].z = aStack[to].zShort; - } - aStack[from].flags = 0; - p->tos--; + pTos--; break; } + /* Opcode: ColumnName P1 * P3 ** ** P3 becomes the P1-th column name (first is 0). An array of pointers @@ -847,32 +834,37 @@ case OP_ColumnName: { ** 3rd parameter. */ case OP_Callback: { - int i = p->tos - pOp->p1 + 1; - int j; - VERIFY( if( i<0 ) goto not_enough_stack; ) - for(j=i; j<=p->tos; j++){ - if( aStack[j].flags & MEM_Null ){ - aStack[j].z = 0; + int i; + char **azArgv = p->zArgv; + Mem *pCol; + + pCol = &pTos[1-pOp->p1]; + assert( pCol>=p->aStack ); + for(i=0; ip1; i++, pCol++){ + if( pCol->flags & MEM_Null ){ + azArgv[i] = 0; }else{ - Stringify(p, j); + Stringify(pCol); + azArgv[i] = pCol->z; } - p->zArgv[j] = aStack[j].z; } - p->zArgv[p->tos+1] = 0; + azArgv[i] = 0; if( p->xCallback==0 ){ - p->azResColumn = &p->zArgv[i]; + p->azResColumn = azArgv; p->nResColumn = pOp->p1; p->popStack = pOp->p1; p->pc = pc + 1; + p->pTos = pTos; return SQLITE_ROW; } if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; - if( p->xCallback(p->pCbArg, pOp->p1, &p->zArgv[i], p->azColName)!=0 ){ + if( p->xCallback(p->pCbArg, pOp->p1, azArgv, p->azColName)!=0 ){ rc = SQLITE_ABORT; } if( sqliteSafetyOn(db) ) goto abort_due_to_misuse; p->nCallback++; - sqliteVdbePopStack(p, pOp->p1); + popStack(&pTos, pOp->p1); + assert( pTos>=&p->aStack[-1] ); if( sqlite_malloc_failed ) goto no_mem; break; } @@ -926,48 +918,53 @@ case OP_Concat: { int i, j; char *zSep; int nSep; + Mem *pTerm; nField = pOp->p1; zSep = pOp->p3; if( zSep==0 ) zSep = ""; nSep = strlen(zSep); - VERIFY( if( p->tos+1= p->aStack ); nByte = 1 - nSep; - for(i=p->tos-nField+1; i<=p->tos; i++){ - if( aStack[i].flags & MEM_Null ){ + pTerm = &pTos[1-nField]; + for(i=0; iflags & MEM_Null ){ nByte = -1; break; }else{ - Stringify(p, i); - nByte += aStack[i].n - 1 + nSep; + Stringify(pTerm); + nByte += pTerm->n - 1 + nSep; } } if( nByte<0 ){ - if( pOp->p2==0 ) sqliteVdbePopStack(p, nField); - p->tos++; - aStack[p->tos].flags = MEM_Null; - aStack[p->tos].z = 0; + if( pOp->p2==0 ){ + popStack(&pTos, nField); + } + pTos++; + pTos->flags = MEM_Null; break; } zNew = sqliteMallocRaw( nByte ); if( zNew==0 ) goto no_mem; j = 0; - for(i=p->tos-nField+1; i<=p->tos; i++){ - if( (aStack[i].flags & MEM_Null)==0 ){ - memcpy(&zNew[j], aStack[i].z, aStack[i].n-1); - j += aStack[i].n-1; - } - if( nSep>0 && itos ){ + pTerm = &pTos[1-nField]; + for(i=j=0; iflags & MEM_Str ); + memcpy(&zNew[j], pTerm->z, pTerm->n-1); + j += pTerm->n-1; + if( nSep>0 && ip2==0 ) sqliteVdbePopStack(p, nField); - p->tos++; - aStack[p->tos].n = nByte; - aStack[p->tos].flags = MEM_Str|MEM_Dyn; - aStack[p->tos].z = zNew; + if( pOp->p2==0 ){ + popStack(&pTos, nField); + } + pTos++; + pTos->n = nByte; + pTos->flags = MEM_Str|MEM_Dyn; + pTos->z = zNew; break; } @@ -1022,17 +1019,17 @@ case OP_Subtract: case OP_Multiply: case OP_Divide: case OP_Remainder: { - int tos = p->tos; - int nos = tos - 1; - VERIFY( if( nos<0 ) goto not_enough_stack; ) - if( ((aStack[tos].flags | aStack[nos].flags) & MEM_Null)!=0 ){ - POPSTACK; - Release(p, nos); - aStack[nos].flags = MEM_Null; - }else if( (aStack[tos].flags & aStack[nos].flags & MEM_Int)==MEM_Int ){ + Mem *pNos = &pTos[-1]; + assert( pNos>=p->aStack ); + if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){ + Release(pTos); + pTos--; + Release(pTos); + pTos->flags = MEM_Null; + }else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){ int a, b; - a = aStack[tos].i; - b = aStack[nos].i; + a = pTos->i; + b = pNos->i; switch( pOp->opcode ){ case OP_Add: b += a; break; case OP_Subtract: b -= a; break; @@ -1048,16 +1045,17 @@ case OP_Remainder: { break; } } - POPSTACK; - Release(p, nos); - aStack[nos].i = b; - aStack[nos].flags = MEM_Int; + Release(pTos); + pTos--; + Release(pTos); + pTos->i = b; + pTos->flags = MEM_Int; }else{ double a, b; - Realify(p, tos); - Realify(p, nos); - a = aStack[tos].r; - b = aStack[nos].r; + Realify(pTos); + Realify(pNos); + a = pTos->r; + b = pNos->r; switch( pOp->opcode ){ case OP_Add: b += a; break; case OP_Subtract: b -= a; break; @@ -1075,17 +1073,19 @@ case OP_Remainder: { break; } } - POPSTACK; - Release(p, nos); - aStack[nos].r = b; - aStack[nos].flags = MEM_Real; + Release(pTos); + pTos--; + Release(pTos); + pTos->r = b; + pTos->flags = MEM_Real; } break; divide_by_zero: - sqliteVdbePopStack(p, 2); - p->tos = nos; - aStack[nos].flags = MEM_Null; + Release(pTos); + pTos--; + Release(pTos); + pTos->flags = MEM_Null; break; } @@ -1099,18 +1099,20 @@ divide_by_zero: */ case OP_Function: { int n, i; + Mem *pArg; + char **azArgv; sqlite_func ctx; n = pOp->p1; - VERIFY( if( n<0 ) goto bad_instruction; ) - VERIFY( if( p->tos+1tos-n+1; i<=p->tos; i++){ - if( aStack[i].flags & MEM_Null ){ - aStack[i].z = 0; + pArg = &pTos[1-n]; + azArgv = p->zArgv; + for(i=0; iflags & MEM_Null ){ + azArgv[i] = 0; }else{ - Stringify(p, i); + Stringify(pArg); + azArgv[i] = pArg->z; } - p->zArgv[i] = aStack[i].z; } ctx.pFunc = (FuncDef*)pOp->p3; ctx.s.flags = MEM_Null; @@ -1118,21 +1120,17 @@ case OP_Function: { ctx.isError = 0; ctx.isStep = 0; if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; - (*ctx.pFunc->xFunc)(&ctx, n, (const char**)&p->zArgv[p->tos-n+1]); + (*ctx.pFunc->xFunc)(&ctx, n, (const char**)azArgv); if( sqliteSafetyOn(db) ) goto abort_due_to_misuse; - sqliteVdbePopStack(p, n); - p->tos++; - aStack[p->tos] = ctx.s; - if( ctx.s.flags & MEM_Dyn ){ - aStack[p->tos].z = ctx.s.z; - }else if( ctx.s.flags & MEM_Str ){ - aStack[p->tos].z = aStack[p->tos].zShort; - }else{ - aStack[p->tos].z = 0; + popStack(&pTos, n); + pTos++; + *pTos = ctx.s; + if( pTos->flags & MEM_Short ){ + pTos->z = pTos->zShort; } if( ctx.isError ){ sqliteSetString(&p->zErrMsg, - aStack[p->tos].z ? aStack[p->tos].z : "user function error", (char*)0); + (pTos->flags & MEM_Str)!=0 ? pTos->z : "user function error", (char*)0); rc = SQLITE_ERROR; } break; @@ -1170,20 +1168,20 @@ case OP_BitAnd: case OP_BitOr: case OP_ShiftLeft: case OP_ShiftRight: { - int tos = p->tos; - int nos = tos - 1; + Mem *pNos = &pTos[-1]; int a, b; - VERIFY( if( nos<0 ) goto not_enough_stack; ) - if( (aStack[tos].flags | aStack[nos].flags) & MEM_Null ){ - POPSTACK; - Release(p,nos); - aStack[nos].flags = MEM_Null; + + assert( pNos>=p->aStack ); + if( (pTos->flags | pNos->flags) & MEM_Null ){ + popStack(&pTos, 2); + pTos++; + pTos->flags = MEM_Null; break; } - Integerify(p, tos); - Integerify(p, nos); - a = aStack[tos].i; - b = aStack[nos].i; + Integerify(pTos); + Integerify(pNos); + a = pTos->i; + b = pNos->i; switch( pOp->opcode ){ case OP_BitAnd: a &= b; break; case OP_BitOr: a |= b; break; @@ -1191,10 +1189,11 @@ case OP_ShiftRight: { case OP_ShiftRight: a >>= b; break; default: /* CANT HAPPEN */ break; } - POPSTACK; - Release(p, nos); - aStack[nos].i = a; - aStack[nos].flags = MEM_Int; + assert( (pTos->flags & MEM_Dyn)==0 ); + assert( (pNos->flags & MEM_Dyn)==0 ); + pTos--; + pTos->i = a; + assert( pTos->flags==MEM_Int ); break; } @@ -1206,10 +1205,9 @@ case OP_ShiftRight: { ** To force the top of the stack to be an integer, just add 0. */ case OP_AddImm: { - int tos = p->tos; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - Integerify(p, tos); - aStack[tos].i += pOp->p1; + assert( pTos>=p->aStack ); + Integerify(pTos); + pTos->i += pOp->p1; break; } @@ -1224,27 +1222,26 @@ case OP_AddImm: { ** greater than its current value if P1==1. */ case OP_ForceInt: { - int tos = p->tos; int v; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - if( (aStack[tos].flags & (MEM_Int|MEM_Real))==0 - && (aStack[tos].z==0 || sqliteIsNumber(aStack[tos].z)==0) ){ - POPSTACK; + assert( pTos>=p->aStack ); + if( (pTos->flags & (MEM_Int|MEM_Real))==0 + && ((pTos->flags & MEM_Str)==0 || sqliteIsNumber(pTos->z)==0) ){ + Release(pTos); + pTos--; pc = pOp->p2 - 1; break; } - if( aStack[tos].flags & MEM_Int ){ - v = aStack[tos].i + (pOp->p1!=0); + if( pTos->flags & MEM_Int ){ + v = pTos->i + (pOp->p1!=0); }else{ - Realify(p, tos); - v = (int)aStack[tos].r; - if( aStack[tos].r>(double)v ) v++; - if( pOp->p1 && aStack[tos].r==(double)v ) v++; + Realify(pTos); + v = (int)pTos->r; + if( pTos->r>(double)v ) v++; + if( pOp->p1 && pTos->r==(double)v ) v++; } - if( aStack[tos].flags & MEM_Dyn ) sqliteFree(aStack[tos].z); - aStack[tos].z = 0; - aStack[tos].i = v; - aStack[tos].flags = MEM_Int; + Release(pTos); + pTos->i = v; + pTos->flags = MEM_Int; break; } @@ -1260,38 +1257,36 @@ case OP_ForceInt: { ** of the stack is unchanged. */ case OP_MustBeInt: { - int tos = p->tos; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - if( aStack[tos].flags & MEM_Int ){ + assert( pTos>=p->aStack ); + if( pTos->flags & MEM_Int ){ /* Do nothing */ - }else if( aStack[tos].flags & MEM_Real ){ - int i = aStack[tos].r; + }else if( pTos->flags & MEM_Real ){ + int i = (int)pTos->r; double r = (double)i; - if( r!=aStack[tos].r ){ + if( r!=pTos->r ){ goto mismatch; } - aStack[tos].i = i; - }else if( aStack[tos].flags & MEM_Str ){ + pTos->i = i; + }else if( pTos->flags & MEM_Str ){ int v; - if( !toInt(aStack[tos].z, &v) ){ + if( !toInt(pTos->z, &v) ){ double r; - if( !sqliteIsNumber(aStack[tos].z) ){ + if( !sqliteIsNumber(pTos->z) ){ goto mismatch; } - Realify(p, tos); - assert( (aStack[tos].flags & MEM_Real)!=0 ); - v = aStack[tos].r; + Realify(pTos); + v = (int)pTos->r; r = (double)v; - if( r!=aStack[tos].r ){ + if( r!=pTos->r ){ goto mismatch; } } - aStack[tos].i = v; + pTos->i = v; }else{ goto mismatch; } - Release(p, tos); - aStack[tos].flags = MEM_Int; + Release(pTos); + pTos->flags = MEM_Int; break; mismatch: @@ -1299,7 +1294,7 @@ mismatch: rc = SQLITE_MISMATCH; goto abort_due_to_error; }else{ - if( pOp->p1 ) POPSTACK; + if( pOp->p1 ) popStack(&pTos, 1); pc = pOp->p2 - 1; } break; @@ -1422,39 +1417,31 @@ case OP_Lt: case OP_Le: case OP_Gt: case OP_Ge: { - int tos = p->tos; - int nos = tos - 1; + Mem *pNos = &pTos[-1]; int c, v; int ft, fn; - VERIFY( if( nos<0 ) goto not_enough_stack; ) - ft = aStack[tos].flags; - fn = aStack[nos].flags; + assert( pNos>=p->aStack ); + ft = pTos->flags; + fn = pNos->flags; if( (ft | fn) & MEM_Null ){ - POPSTACK; - POPSTACK; + popStack(&pTos, 2); if( pOp->p2 ){ if( pOp->p1 ) pc = pOp->p2-1; }else{ - p->tos++; - aStack[nos].flags = MEM_Null; + pTos++; + pTos->flags = MEM_Null; } break; }else if( (ft & fn & MEM_Int)==MEM_Int ){ - c = aStack[nos].i - aStack[tos].i; - }else if( (ft & MEM_Int)!=0 && (fn & MEM_Str)!=0 && toInt(aStack[nos].z,&v) ){ - Release(p, nos); - aStack[nos].i = v; - aStack[nos].flags = MEM_Int; - c = aStack[nos].i - aStack[tos].i; - }else if( (fn & MEM_Int)!=0 && (ft & MEM_Str)!=0 && toInt(aStack[tos].z,&v) ){ - Release(p, tos); - aStack[tos].i = v; - aStack[tos].flags = MEM_Int; - c = aStack[nos].i - aStack[tos].i; + c = pNos->i - pTos->i; + }else if( (ft & MEM_Int)!=0 && (fn & MEM_Str)!=0 && toInt(pNos->z,&v) ){ + c = v - pTos->i; + }else if( (fn & MEM_Int)!=0 && (ft & MEM_Str)!=0 && toInt(pTos->z,&v) ){ + c = pNos->i - v; }else{ - Stringify(p, tos); - Stringify(p, nos); - c = sqliteCompare(aStack[nos].z, aStack[tos].z); + Stringify(pTos); + Stringify(pNos); + c = sqliteCompare(pNos->z, pTos->z); } switch( pOp->opcode ){ case OP_Eq: c = c==0; break; @@ -1464,14 +1451,13 @@ case OP_Ge: { case OP_Gt: c = c>0; break; default: c = c>=0; break; } - POPSTACK; - POPSTACK; + popStack(&pTos, 2); if( pOp->p2 ){ if( c ) pc = pOp->p2-1; }else{ - p->tos++; - aStack[nos].flags = MEM_Int; - aStack[nos].i = c; + pTos++; + pTos->i = c; + pTos->flags = MEM_Int; } break; } @@ -1588,24 +1574,22 @@ case OP_StrLt: case OP_StrLe: case OP_StrGt: case OP_StrGe: { - int tos = p->tos; - int nos = tos - 1; + Mem *pNos = &pTos[-1]; int c; - VERIFY( if( nos<0 ) goto not_enough_stack; ) - if( (aStack[nos].flags | aStack[tos].flags) & MEM_Null ){ - POPSTACK; - POPSTACK; + assert( pNos>=p->aStack ); + if( (pNos->flags | pTos->flags) & MEM_Null ){ + popStack(&pTos, 2); if( pOp->p2 ){ if( pOp->p1 ) pc = pOp->p2-1; }else{ - p->tos++; - aStack[nos].flags = MEM_Null; + pTos++; + pTos->flags = MEM_Null; } break; }else{ - Stringify(p, tos); - Stringify(p, nos); - c = strcmp(aStack[nos].z, aStack[tos].z); + Stringify(pTos); + Stringify(pNos); + c = strcmp(pNos->z, pTos->z); } /* The asserts on each case of the following switch are there to verify ** that string comparison opcodes are always exactly 6 greater than the @@ -1620,14 +1604,13 @@ case OP_StrGe: { case OP_StrGt: c = c>0; assert( pOp->opcode-6==OP_Gt ); break; default: c = c>=0; assert( pOp->opcode-6==OP_Ge ); break; } - POPSTACK; - POPSTACK; + popStack(&pTos, 2); if( pOp->p2 ){ if( c ) pc = pOp->p2-1; }else{ - p->tos++; - aStack[nos].flags = MEM_Int; - aStack[nos].i = c; + pTos++; + pTos->flags = MEM_Int; + pTos->i = c; } break; } @@ -1646,22 +1629,21 @@ case OP_StrGe: { */ case OP_And: case OP_Or: { - int tos = p->tos; - int nos = tos - 1; + Mem *pNos = &pTos[-1]; int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */ - VERIFY( if( nos<0 ) goto not_enough_stack; ) - if( aStack[tos].flags & MEM_Null ){ + assert( pNos>=p->aStack ); + if( pTos->flags & MEM_Null ){ v1 = 2; }else{ - Integerify(p, tos); - v1 = aStack[tos].i==0; + Integerify(pTos); + v1 = pTos->i==0; } - if( aStack[nos].flags & MEM_Null ){ + if( pNos->flags & MEM_Null ){ v2 = 2; }else{ - Integerify(p, nos); - v2 = aStack[nos].i==0; + Integerify(pNos); + v2 = pNos->i==0; } if( pOp->opcode==OP_And ){ static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; @@ -1670,13 +1652,13 @@ case OP_Or: { static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; v1 = or_logic[v1*3+v2]; } - POPSTACK; - Release(p, nos); + popStack(&pTos, 2); + pTos++; if( v1==2 ){ - aStack[nos].flags = MEM_Null; + pTos->flags = MEM_Null; }else{ - aStack[nos].i = v1==0; - aStack[nos].flags = MEM_Int; + pTos->i = v1==0; + pTos->flags = MEM_Int; } break; } @@ -1695,29 +1677,28 @@ case OP_Or: { */ case OP_Negative: case OP_AbsValue: { - int tos = p->tos; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - if( aStack[tos].flags & MEM_Real ){ - Release(p, tos); - if( pOp->opcode==OP_Negative || aStack[tos].r<0.0 ){ - aStack[tos].r = -aStack[tos].r; + assert( pTos>=p->aStack ); + if( pTos->flags & MEM_Real ){ + Release(pTos); + if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ + pTos->r = -pTos->r; } - aStack[tos].flags = MEM_Real; - }else if( aStack[tos].flags & MEM_Int ){ - Release(p, tos); - if( pOp->opcode==OP_Negative || aStack[tos].i<0 ){ - aStack[tos].i = -aStack[tos].i; + pTos->flags = MEM_Real; + }else if( pTos->flags & MEM_Int ){ + Release(pTos); + if( pOp->opcode==OP_Negative || pTos->i<0 ){ + pTos->i = -pTos->i; } - aStack[tos].flags = MEM_Int; - }else if( aStack[tos].flags & MEM_Null ){ + pTos->flags = MEM_Int; + }else if( pTos->flags & MEM_Null ){ /* Do nothing */ }else{ - Realify(p, tos); - Release(p, tos); - if( pOp->opcode==OP_Negative || aStack[tos].r<0.0 ){ - aStack[tos].r = -aStack[tos].r; + Realify(pTos); + Release(pTos); + if( pOp->opcode==OP_Negative || pTos->r<0.0 ){ + pTos->r = -pTos->r; } - aStack[tos].flags = MEM_Real; + pTos->flags = MEM_Real; } break; } @@ -1729,13 +1710,11 @@ case OP_AbsValue: { ** is unchanged. */ case OP_Not: { - int tos = p->tos; - VERIFY( if( p->tos<0 ) goto not_enough_stack; ) - if( aStack[tos].flags & MEM_Null ) break; /* Do nothing to NULLs */ - Integerify(p, tos); - Release(p, tos); - aStack[tos].i = !aStack[tos].i; - aStack[tos].flags = MEM_Int; + assert( pTos>=p->aStack ); + if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ + Integerify(pTos); + assert( pTos->flags==MEM_Int ); + pTos->i = !pTos->i; break; } @@ -1746,13 +1725,11 @@ case OP_Not: { ** value is unchanged. */ case OP_BitNot: { - int tos = p->tos; - VERIFY( if( p->tos<0 ) goto not_enough_stack; ) - if( aStack[tos].flags & MEM_Null ) break; /* Do nothing to NULLs */ - Integerify(p, tos); - Release(p, tos); - aStack[tos].i = ~aStack[tos].i; - aStack[tos].flags = MEM_Int; + assert( pTos>=p->aStack ); + if( pTos->flags & MEM_Null ) break; /* Do nothing to NULLs */ + Integerify(pTos); + assert( pTos->flags==MEM_Int ); + pTos->i = ~pTos->i; break; } @@ -1788,15 +1765,16 @@ case OP_Noop: { case OP_If: case OP_IfNot: { int c; - VERIFY( if( p->tos<0 ) goto not_enough_stack; ) - if( aStack[p->tos].flags & MEM_Null ){ + assert( pTos>=p->aStack ); + if( pTos->flags & MEM_Null ){ c = pOp->p1; }else{ - Integerify(p, p->tos); - c = aStack[p->tos].i; + Integerify(pTos); + c = pTos->i; if( pOp->opcode==OP_IfNot ) c = !c; } - POPSTACK; + assert( (pTos->flags & MEM_Dyn)==0 ); + pTos--; if( c ) pc = pOp->p2-1; break; } @@ -1809,16 +1787,18 @@ case OP_IfNot: { */ case OP_IsNull: { int i, cnt; + Mem *pTerm; cnt = pOp->p1; if( cnt<0 ) cnt = -cnt; - VERIFY( if( p->tos+1-cnt<0 ) goto not_enough_stack; ) - for(i=0; itos-i].flags & MEM_Null ){ + pTerm = &pTos[1-cnt]; + assert( pTerm>=p->aStack ); + for(i=0; iflags & MEM_Null ){ pc = pOp->p2-1; break; } } - if( pOp->p1>0 ) sqliteVdbePopStack(p, cnt); + if( pOp->p1>0 ) popStack(&pTos, cnt); break; } @@ -1832,10 +1812,10 @@ case OP_NotNull: { int i, cnt; cnt = pOp->p1; if( cnt<0 ) cnt = -cnt; - VERIFY( if( p->tos+1-cnt<0 ) goto not_enough_stack; ) - for(i=0; itos-i].flags & MEM_Null)==0; i++){} + assert( &pTos[1-cnt] >= p->aStack ); + for(i=0; i=cnt ) pc = pOp->p2-1; - if( pOp->p1>0 ) sqliteVdbePopStack(p, cnt); + if( pOp->p1>0 ) popStack(&pTos, cnt); break; } @@ -1867,6 +1847,7 @@ case OP_MakeRecord: { int i, j; int idxWidth; u32 addr; + Mem *pRec; int addUnique = 0; /* True to cause bytes to be added to make the ** generated record distinct */ char zTemp[NBFS]; /* Temp space for small records */ @@ -1890,14 +1871,15 @@ case OP_MakeRecord: { ** Idx(N) contains the total number of bytes in the record. */ nField = pOp->p1; - VERIFY( if( p->tos+1=p->aStack ); nByte = 0; - for(i=p->tos-nField+1; i<=p->tos; i++){ - if( (aStack[i].flags & MEM_Null) ){ + for(i=0; iflags & MEM_Null ){ addUnique = pOp->p2; }else{ - Stringify(p, i); - nByte += aStack[i].n; + Stringify(pRec); + nByte += pRec->n; } } if( addUnique ) nByte += sizeof(p->uniqueCnt); @@ -1921,7 +1903,7 @@ case OP_MakeRecord: { } j = 0; addr = idxWidth*(nField+1) + addUnique*sizeof(p->uniqueCnt); - for(i=p->tos-nField+1; i<=p->tos; i++){ + for(i=0, pRec=&pTos[1-nField]; i1 ){ zNewRecord[j++] = (addr>>8)&0xff; @@ -1929,8 +1911,8 @@ case OP_MakeRecord: { zNewRecord[j++] = (addr>>16)&0xff; } } - if( (aStack[i].flags & MEM_Null)==0 ){ - addr += aStack[i].n; + if( (pRec->flags & MEM_Null)==0 ){ + addr += pRec->n; } } zNewRecord[j++] = addr & 0xff; @@ -1945,24 +1927,24 @@ case OP_MakeRecord: { p->uniqueCnt++; j += sizeof(p->uniqueCnt); } - for(i=p->tos-nField+1; i<=p->tos; i++){ - if( (aStack[i].flags & MEM_Null)==0 ){ - memcpy(&zNewRecord[j], aStack[i].z, aStack[i].n); - j += aStack[i].n; + for(i=0, pRec=&pTos[1-nField]; iflags & MEM_Null)==0 ){ + memcpy(&zNewRecord[j], pRec->z, pRec->n); + j += pRec->n; } } - sqliteVdbePopStack(p, nField); - p->tos++; - aStack[p->tos].n = nByte; + popStack(&pTos, nField); + pTos++; + pTos->n = nByte; if( nByte<=NBFS ){ assert( zNewRecord==zTemp ); - memcpy(aStack[p->tos].zShort, zTemp, nByte); - aStack[p->tos].z = aStack[p->tos].zShort; - aStack[p->tos].flags = MEM_Str; + memcpy(pTos->zShort, zTemp, nByte); + pTos->z = pTos->zShort; + pTos->flags = MEM_Str | MEM_Short; }else{ assert( zNewRecord!=zTemp ); - aStack[p->tos].flags = MEM_Str | MEM_Dyn; - aStack[p->tos].z = zNewRecord; + pTos->z = zNewRecord; + pTos->flags = MEM_Str | MEM_Dyn; } break; } @@ -2047,39 +2029,41 @@ case OP_MakeKey: { int addRowid; int i, j; int containsNull = 0; + Mem *pRec; char zTemp[NBFS]; addRowid = pOp->opcode==OP_MakeIdxKey; nField = pOp->p1; - VERIFY( if( p->tos+1+addRowid=p->aStack ); nByte = 0; - for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){ - int flags = aStack[i].flags; + for(j=0, i=0; iflags; int len; char *z; if( flags & MEM_Null ){ nByte += 2; containsNull = 1; }else if( pOp->p3 && pOp->p3[j]=='t' ){ - Stringify(p, i); - aStack[i].flags &= ~(MEM_Int|MEM_Real); - nByte += aStack[i].n+1; - }else if( (flags & (MEM_Real|MEM_Int))!=0 || sqliteIsNumber(aStack[i].z) ){ + Stringify(pRec); + pRec->flags &= ~(MEM_Int|MEM_Real); + nByte += pRec->n+1; + }else if( (flags & (MEM_Real|MEM_Int))!=0 || sqliteIsNumber(pRec->z) ){ if( (flags & (MEM_Real|MEM_Int))==MEM_Int ){ - aStack[i].r = aStack[i].i; + pRec->r = pRec->i; }else if( (flags & (MEM_Real|MEM_Int))==0 ){ - aStack[i].r = sqliteAtoF(aStack[i].z); + pRec->r = sqliteAtoF(pRec->z); } - Release(p, i); - z = aStack[i].zShort; - sqliteRealToSortable(aStack[i].r, z); + Release(pRec); + z = pRec->zShort; + sqliteRealToSortable(pRec->r, z); len = strlen(z); - aStack[i].z = 0; - aStack[i].flags = MEM_Real; - aStack[i].n = len+1; - nByte += aStack[i].n+1; + pRec->z = 0; + pRec->flags = MEM_Real; + pRec->n = len+1; + nByte += pRec->n+1; }else{ - nByte += aStack[i].n+1; + nByte += pRec->n+1; } } if( nByte+sizeof(u32)>MAX_BYTES_PER_ROW ){ @@ -2094,41 +2078,44 @@ case OP_MakeKey: { if( zNewKey==0 ) goto no_mem; } j = 0; - for(i=p->tos-nField+1; i<=p->tos; i++){ - if( aStack[i].flags & MEM_Null ){ + pRec = &pTos[1-nField]; + for(i=0; iflags & MEM_Null ){ zNewKey[j++] = 'a'; zNewKey[j++] = 0; + }else if( pRec->flags==MEM_Real ){ + zNewKey[j++] = 'b'; + memcpy(&zNewKey[j], pRec->zShort, pRec->n); + j += pRec->n; }else{ - if( aStack[i].flags & (MEM_Int|MEM_Real) ){ - zNewKey[j++] = 'b'; - }else{ - zNewKey[j++] = 'c'; - } - /*** Is this right? ****/ - memcpy(&zNewKey[j],aStack[i].z?aStack[i].z:aStack[i].zShort,aStack[i].n); - j += aStack[i].n; + assert( pRec->flags & MEM_Str ); + zNewKey[j++] = 'c'; + memcpy(&zNewKey[j], pRec->z, pRec->n); + j += pRec->n; } } if( addRowid ){ u32 iKey; - Integerify(p, p->tos-nField); - iKey = intToKey(aStack[p->tos-nField].i); + pRec = &pTos[-nField]; + assert( pRec>=p->aStack ); + Integerify(pRec); + iKey = intToKey(pRec->i); memcpy(&zNewKey[j], &iKey, sizeof(u32)); - sqliteVdbePopStack(p, nField+1); + popStack(&pTos, nField+1); if( pOp->p2 && containsNull ) pc = pOp->p2 - 1; }else{ - if( pOp->p2==0 ) sqliteVdbePopStack(p, nField+addRowid); + if( pOp->p2==0 ) popStack(&pTos, nField); } - p->tos++; - aStack[p->tos].n = nByte; + pTos++; + pTos->n = nByte; if( nByte<=NBFS ){ assert( zNewKey==zTemp ); - aStack[p->tos].z = aStack[p->tos].zShort; - memcpy(aStack[p->tos].z, zTemp, nByte); - aStack[p->tos].flags = MEM_Str; + pTos->z = pTos->zShort; + memcpy(pTos->zShort, zTemp, nByte); + pTos->flags = MEM_Str | MEM_Short; }else{ - aStack[p->tos].flags = MEM_Str|MEM_Dyn; - aStack[p->tos].z = zNewKey; + pTos->z = zNewKey; + pTos->flags = MEM_Str | MEM_Dyn; } break; } @@ -2142,18 +2129,14 @@ case OP_MakeKey: { ** the key itself. */ case OP_IncrKey: { - int tos = p->tos; - - VERIFY( if( tos<0 ) goto bad_instruction ); - Stringify(p, tos); - if( aStack[tos].flags & (MEM_Static|MEM_Ephem) ){ - /* CANT HAPPEN. The IncrKey opcode is only applied to keys - ** generated by MakeKey or MakeIdxKey and the results of those - ** operands are always dynamic strings. - */ - goto abort_due_to_error; - } - aStack[tos].z[aStack[tos].n-1]++; + assert( pTos>=p->aStack ); + /* The IncrKey opcode is only applied to keys generated by + ** MakeKey or MakeIdxKey and the results of those operands + ** are always dynamic strings or zShort[] strings. So we + ** are always free to modify the string in place. + */ + assert( pTos->flags & (MEM_Dyn|MEM_Short) ); + pTos->z[pTos->n-1]++; break; } @@ -2206,6 +2189,7 @@ case OP_Transaction: { p->pc = pc; p->undoTransOnError = 1; p->rc = SQLITE_BUSY; + p->pTos = pTos; return SQLITE_BUSY; }else if( (*db->xBusyCallback)(db->pBusyArg, "", busy++)==0 ){ sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0); @@ -2295,14 +2279,14 @@ case OP_Rollback: { ** executing this instruction. */ case OP_ReadCookie: { - int i = ++p->tos; int aMeta[SQLITE_N_BTREE_META]; assert( pOp->p2p1>=0 && pOp->p1nDb ); assert( db->aDb[pOp->p1].pBt!=0 ); rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta); - aStack[i].i = aMeta[1+pOp->p2]; - aStack[i].flags = MEM_Int; + pTos++; + pTos->i = aMeta[1+pOp->p2]; + pTos->flags = MEM_Int; break; } @@ -2321,14 +2305,15 @@ case OP_SetCookie: { assert( pOp->p2p1>=0 && pOp->p1nDb ); assert( db->aDb[pOp->p1].pBt!=0 ); - VERIFY( if( p->tos<0 ) goto not_enough_stack; ) - Integerify(p, p->tos) + assert( pTos>=p->aStack ); + Integerify(pTos) rc = sqliteBtreeGetMeta(db->aDb[pOp->p1].pBt, aMeta); if( rc==SQLITE_OK ){ - aMeta[1+pOp->p2] = aStack[p->tos].i; + aMeta[1+pOp->p2] = pTos->i; rc = sqliteBtreeUpdateMeta(db->aDb[pOp->p1].pBt, aMeta); } - POPSTACK; + assert( pTos->flags==MEM_Int ); + pTos--; break; } @@ -2407,32 +2392,31 @@ case OP_OpenRead: case OP_OpenWrite: { int busy = 0; int i = pOp->p1; - int tos = p->tos; int p2 = pOp->p2; int wrFlag; Btree *pX; int iDb; - VERIFY( if( tos<0 ) goto not_enough_stack; ); - Integerify(p, tos); - iDb = p->aStack[tos].i; - tos--; - VERIFY( if( iDb<0 || iDb>=db->nDb ) goto bad_instruction; ); - VERIFY( if( db->aDb[iDb].pBt==0 ) goto bad_instruction; ); + assert( pTos>=p->aStack ); + Integerify(pTos); + iDb = pTos->i; + pTos--; + assert( iDb>=0 && iDbnDb ); pX = db->aDb[iDb].pBt; + assert( pX!=0 ); wrFlag = pOp->opcode==OP_OpenWrite; if( p2<=0 ){ - VERIFY( if( tos<0 ) goto not_enough_stack; ); - Integerify(p, tos); - p2 = p->aStack[tos].i; - POPSTACK; + assert( pTos>=p->aStack ); + Integerify(pTos); + p2 = pTos->i; + pTos--; if( p2<2 ){ sqliteSetString(&p->zErrMsg, "root page number less than 2", (char*)0); rc = SQLITE_INTERNAL; break; } } - VERIFY( if( i<0 ) goto bad_instruction; ) + assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; sqliteVdbeCleanupCursor(&p->aCsr[i]); memset(&p->aCsr[i], 0, sizeof(Cursor)); @@ -2445,6 +2429,7 @@ case OP_OpenWrite: { if( db->xBusyCallback==0 ){ p->pc = pc; p->rc = SQLITE_BUSY; + p->pTos = &pTos[1 + (pOp->p2<=0)]; /* Operands must remain on stack */ return SQLITE_BUSY; }else if( (*db->xBusyCallback)(db->pBusyArg, pOp->p3, ++busy)==0 ){ sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0); @@ -2461,10 +2446,6 @@ case OP_OpenWrite: { } } }while( busy ); - if( p2<=0 ){ - POPSTACK; - } - POPSTACK; break; } @@ -2489,7 +2470,7 @@ case OP_OpenWrite: { case OP_OpenTemp: { int i = pOp->p1; Cursor *pCx; - VERIFY( if( i<0 ) goto bad_instruction; ) + assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; pCx = &p->aCsr[i]; sqliteVdbeCleanupCursor(pCx); @@ -2527,7 +2508,7 @@ case OP_OpenTemp: { case OP_OpenPseudo: { int i = pOp->p1; Cursor *pCx; - VERIFY( if( i<0 ) goto bad_instruction; ) + assert( i>=0 ); if( expandCursorArraySize(p, i) ) goto no_mem; pCx = &p->aCsr[i]; sqliteVdbeCleanupCursor(pCx); @@ -2574,29 +2555,29 @@ case OP_Close: { case OP_MoveLt: case OP_MoveTo: { int i = pOp->p1; - int tos = p->tos; Cursor *pC; - VERIFY( if( tos<0 ) goto not_enough_stack; ) + assert( pTos>=p->aStack ); assert( i>=0 && inCursor ); pC = &p->aCsr[i]; if( pC->pCursor!=0 ){ int res, oc; pC->nullRow = 0; - if( aStack[tos].flags & MEM_Int ){ - int iKey = intToKey(aStack[tos].i); + if( pTos->flags & MEM_Int ){ + int iKey = intToKey(pTos->i); if( pOp->p2==0 && pOp->opcode==OP_MoveTo ){ pC->movetoTarget = iKey; pC->deferredMoveto = 1; - POPSTACK; + Release(pTos); + pTos--; break; } sqliteBtreeMoveto(pC->pCursor, (char*)&iKey, sizeof(int), &res); - pC->lastRecno = aStack[tos].i; + pC->lastRecno = pTos->i; pC->recnoIsValid = res==0; }else{ - Stringify(p, tos); - sqliteBtreeMoveto(pC->pCursor, aStack[tos].z, aStack[tos].n, &res); + Stringify(pTos); + sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); pC->recnoIsValid = 0; } pC->deferredMoveto = 0; @@ -2624,7 +2605,8 @@ case OP_MoveTo: { } } } - POPSTACK; + Release(pTos); + pTos--; break; } @@ -2665,14 +2647,14 @@ case OP_Distinct: case OP_NotFound: case OP_Found: { int i = pOp->p1; - int tos = p->tos; int alreadyExists = 0; Cursor *pC; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - if( VERIFY( i>=0 && inCursor && ) (pC = &p->aCsr[i])->pCursor!=0 ){ + assert( pTos>=p->aStack ); + assert( i>=0 && inCursor ); + if( (pC = &p->aCsr[i])->pCursor!=0 ){ int res, rx; - Stringify(p, tos); - rx = sqliteBtreeMoveto(pC->pCursor, aStack[tos].z, aStack[tos].n, &res); + Stringify(pTos); + rx = sqliteBtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); alreadyExists = rx==SQLITE_OK && res==0; pC->deferredMoveto = 0; } @@ -2682,7 +2664,8 @@ case OP_Found: { if( !alreadyExists ) pc = pOp->p2 - 1; } if( pOp->opcode!=OP_Distinct ){ - POPSTACK; + Release(pTos); + pTos--; } break; } @@ -2709,18 +2692,18 @@ case OP_Found: { */ case OP_IsUnique: { int i = pOp->p1; - int tos = p->tos; - int nos = tos-1; + Mem *pNos = &pTos[-1]; BtCursor *pCrsr; int R; /* Pop the value R off the top of the stack */ - VERIFY( if( nos<0 ) goto not_enough_stack; ) - Integerify(p, tos); - R = aStack[tos].i; - POPSTACK; - if( VERIFY( i>=0 && inCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ + assert( pNos>=p->aStack ); + Integerify(pTos); + R = pTos->i; + pTos--; + assert( i>=0 && i<=p->nCursor ); + if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ int res, rc; int v; /* The record number on the P1 entry that matches K */ char *zKey; /* The value of K */ @@ -2728,9 +2711,9 @@ case OP_IsUnique: { /* Make sure K is a string and make zKey point to K */ - Stringify(p, nos); - zKey = aStack[nos].z; - nKey = aStack[nos].n; + Stringify(pNos); + zKey = pNos->z; + nKey = pNos->n; assert( nKey >= 4 ); /* Search for an entry in P1 where all but the last four bytes match K. @@ -2770,9 +2753,9 @@ case OP_IsUnique: { ** stack. (These bytes are the record number of an entry that ** violates a UNIQUE constraint.) */ - p->tos++; - aStack[tos].i = v; - aStack[tos].flags = MEM_Int; + pTos++; + pTos->i = v; + pTos->flags = MEM_Int; } break; } @@ -2792,15 +2775,15 @@ case OP_IsUnique: { */ case OP_NotExists: { int i = pOp->p1; - int tos = p->tos; BtCursor *pCrsr; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - if( VERIFY( i>=0 && inCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ + assert( pTos>=p->aStack ); + assert( i>=0 && inCursor ); + if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ int res, rx, iKey; - assert( aStack[tos].flags & MEM_Int ); - iKey = intToKey(aStack[tos].i); + assert( pTos->flags & MEM_Int ); + iKey = intToKey(pTos->i); rx = sqliteBtreeMoveto(pCrsr, (char*)&iKey, sizeof(int), &res); - p->aCsr[i].lastRecno = aStack[tos].i; + p->aCsr[i].lastRecno = pTos->i; p->aCsr[i].recnoIsValid = res==0; p->aCsr[i].nullRow = 0; if( rx!=SQLITE_OK || res!=0 ){ @@ -2808,7 +2791,8 @@ case OP_NotExists: { p->aCsr[i].recnoIsValid = 0; } } - POPSTACK; + Release(pTos); + pTos--; break; } @@ -2823,7 +2807,8 @@ case OP_NewRecno: { int i = pOp->p1; int v = 0; Cursor *pC; - if( VERIFY( i<0 || i>=p->nCursor || ) (pC = &p->aCsr[i])->pCursor==0 ){ + assert( i>=0 && inCursor ); + if( (pC = &p->aCsr[i])->pCursor==0 ){ v = 0; }else{ /* The next rowid or record number (different terms for the same @@ -2907,9 +2892,9 @@ case OP_NewRecno: { pC->recnoIsValid = 0; pC->deferredMoveto = 0; } - p->tos++; - aStack[p->tos].i = v; - aStack[p->tos].flags = MEM_Int; + pTos++; + pTos->i = v; + pTos->flags = MEM_Int; break; } @@ -2937,29 +2922,28 @@ case OP_NewRecno: { */ case OP_PutIntKey: case OP_PutStrKey: { - int tos = p->tos; - int nos = p->tos-1; + Mem *pNos = &pTos[-1]; int i = pOp->p1; Cursor *pC; - VERIFY( if( nos<0 ) goto not_enough_stack; ) - if( VERIFY( i>=0 && inCursor && ) - ((pC = &p->aCsr[i])->pCursor!=0 || pC->pseudoTable) ){ + assert( pNos>=p->aStack ); + assert( i>=0 && inCursor ); + if( ((pC = &p->aCsr[i])->pCursor!=0 || pC->pseudoTable) ){ char *zKey; int nKey, iKey; if( pOp->opcode==OP_PutStrKey ){ - Stringify(p, nos); - nKey = aStack[nos].n; - zKey = aStack[nos].z; + Stringify(pNos); + nKey = pNos->n; + zKey = pNos->z; }else{ - assert( aStack[nos].flags & MEM_Int ); + assert( pNos->flags & MEM_Int ); nKey = sizeof(int); - iKey = intToKey(aStack[nos].i); + iKey = intToKey(pNos->i); zKey = (char*)&iKey; if( pOp->p2 ){ db->nChange++; - db->lastRowid = aStack[nos].i; + db->lastRowid = pNos->i; } - if( pC->nextRowidValid && aStack[nos].i>=pC->nextRowid ){ + if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){ pC->nextRowidValid = 0; } } @@ -2971,27 +2955,24 @@ case OP_PutStrKey: { assert( pOp->opcode==OP_PutIntKey ); sqliteFree(pC->pData); pC->iKey = iKey; - pC->nData = aStack[tos].n; - if( aStack[tos].flags & MEM_Dyn ){ - pC->pData = aStack[tos].z; - aStack[tos].z = 0; - aStack[tos].flags = MEM_Null; + pC->nData = pTos->n; + if( pTos->flags & MEM_Dyn ){ + pC->pData = pTos->z; + pTos->flags = MEM_Null; }else{ pC->pData = sqliteMallocRaw( pC->nData ); if( pC->pData ){ - memcpy(pC->pData, aStack[tos].z, pC->nData); + memcpy(pC->pData, pTos->z, pC->nData); } } pC->nullRow = 0; }else{ - rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey, - aStack[tos].z, aStack[tos].n); + rc = sqliteBtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n); } pC->recnoIsValid = 0; pC->deferredMoveto = 0; } - POPSTACK; - POPSTACK; + popStack(&pTos, 2); break; } @@ -3058,46 +3039,46 @@ case OP_KeyAsData: { case OP_RowKey: case OP_RowData: { int i = pOp->p1; - int tos = ++p->tos; Cursor *pC; int n; + pTos++; assert( i>=0 && inCursor ); pC = &p->aCsr[i]; if( pC->nullRow ){ - aStack[tos].flags = MEM_Null; + pTos->flags = MEM_Null; }else if( pC->pCursor!=0 ){ BtCursor *pCrsr = pC->pCursor; sqliteVdbeCursorMoveto(pC); if( pC->nullRow ){ - aStack[tos].flags = MEM_Null; + pTos->flags = MEM_Null; break; }else if( pC->keyAsData || pOp->opcode==OP_RowKey ){ sqliteBtreeKeySize(pCrsr, &n); }else{ sqliteBtreeDataSize(pCrsr, &n); } - aStack[tos].n = n; + pTos->n = n; if( n<=NBFS ){ - aStack[tos].flags = MEM_Str; - aStack[tos].z = aStack[tos].zShort; + pTos->flags = MEM_Str | MEM_Short; + pTos->z = pTos->zShort; }else{ char *z = sqliteMallocRaw( n ); if( z==0 ) goto no_mem; - aStack[tos].flags = MEM_Str | MEM_Dyn; - aStack[tos].z = z; + pTos->flags = MEM_Str | MEM_Dyn; + pTos->z = z; } if( pC->keyAsData || pOp->opcode==OP_RowKey ){ - sqliteBtreeKey(pCrsr, 0, n, aStack[tos].z); + sqliteBtreeKey(pCrsr, 0, n, pTos->z); }else{ - sqliteBtreeData(pCrsr, 0, n, aStack[tos].z); + sqliteBtreeData(pCrsr, 0, n, pTos->z); } }else if( pC->pseudoTable ){ - aStack[tos].n = pC->nData; - aStack[tos].z = pC->pData; - aStack[tos].flags = MEM_Str|MEM_Ephem; + pTos->n = pC->nData; + pTos->z = pC->pData; + pTos->flags = MEM_Str|MEM_Ephem; }else{ - aStack[tos].flags = MEM_Null; + pTos->flags = MEM_Null; } break; } @@ -3125,7 +3106,6 @@ case OP_Column: { int amt, offset, end, payloadSize; int i = pOp->p1; int p2 = pOp->p2; - int tos = p->tos+1; Cursor *pC; char *zRec; BtCursor *pCrsr; @@ -3133,11 +3113,12 @@ case OP_Column: { unsigned char aHdr[10]; assert( inCursor ); + pTos++; if( i<0 ){ - VERIFY( if( tos+i<0 ) goto bad_instruction; ) - VERIFY( if( (aStack[tos+i].flags & MEM_Str)==0 ) goto bad_instruction; ) - zRec = aStack[tos+i].z; - payloadSize = aStack[tos+i].n; + assert( &pTos[i]>=p->aStack ); + assert( pTos[i].flags & MEM_Str ); + zRec = pTos[i].z; + payloadSize = pTos[i].n; }else if( (pC = &p->aCsr[i])->pCursor!=0 ){ sqliteVdbeCursorMoveto(pC); zRec = 0; @@ -3161,8 +3142,7 @@ case OP_Column: { ** data begins. */ if( payloadSize==0 ){ - aStack[tos].flags = MEM_Null; - p->tos = tos; + pTos->flags = MEM_Null; break; }else if( payloadSize<256 ){ idxWidth = 1; @@ -3204,31 +3184,28 @@ case OP_Column: { /* amt and offset now hold the offset to the start of data and the ** amount of data. Go get the data and put it on the stack. */ + pTos->n = amt; if( amt==0 ){ - aStack[tos].flags = MEM_Null; + pTos->flags = MEM_Null; }else if( zRec ){ - aStack[tos].flags = MEM_Str | MEM_Ephem; - aStack[tos].n = amt; - aStack[tos].z = &zRec[offset]; + pTos->flags = MEM_Str | MEM_Ephem; + pTos->z = &zRec[offset]; }else{ if( amt<=NBFS ){ - aStack[tos].flags = MEM_Str; - aStack[tos].z = aStack[tos].zShort; - aStack[tos].n = amt; + pTos->flags = MEM_Str | MEM_Short; + pTos->z = pTos->zShort; }else{ char *z = sqliteMallocRaw( amt ); if( z==0 ) goto no_mem; - aStack[tos].flags = MEM_Str | MEM_Dyn; - aStack[tos].z = z; - aStack[tos].n = amt; + pTos->flags = MEM_Str | MEM_Dyn; + pTos->z = z; } if( pC->keyAsData ){ - sqliteBtreeKey(pCrsr, offset, amt, aStack[tos].z); + sqliteBtreeKey(pCrsr, offset, amt, pTos->z); }else{ - sqliteBtreeData(pCrsr, offset, amt, aStack[tos].z); + sqliteBtreeData(pCrsr, offset, amt, pTos->z); } } - p->tos = tos; break; } @@ -3241,27 +3218,27 @@ case OP_Column: { */ case OP_Recno: { int i = pOp->p1; - int tos = ++p->tos; Cursor *pC; int v; assert( i>=0 && inCursor ); pC = &p->aCsr[i]; sqliteVdbeCursorMoveto(pC); + pTos++; if( pC->recnoIsValid ){ v = pC->lastRecno; }else if( pC->pseudoTable ){ v = keyToInt(pC->iKey); }else if( pC->nullRow || pC->pCursor==0 ){ - aStack[tos].flags = MEM_Null; + pTos->flags = MEM_Null; break; }else{ assert( pC->pCursor!=0 ); sqliteBtreeKey(pC->pCursor, 0, sizeof(u32), (char*)&v); v = keyToInt(v); } - aStack[tos].i = v; - aStack[tos].flags = MEM_Int; + pTos->i = v; + pTos->flags = MEM_Int; break; } @@ -3278,12 +3255,13 @@ case OP_Recno: { */ case OP_FullKey: { int i = pOp->p1; - int tos = ++p->tos; BtCursor *pCrsr; - VERIFY( if( !p->aCsr[i].keyAsData ) goto bad_instruction; ) - VERIFY( if( p->aCsr[i].pseudoTable ) goto bad_instruction; ) - if( VERIFY( i>=0 && inCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ + assert( p->aCsr[i].keyAsData ); + assert( !p->aCsr[i].pseudoTable ); + assert( i>=0 && inCursor ); + pTos++; + if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ int amt; char *z; @@ -3296,14 +3274,14 @@ case OP_FullKey: { if( amt>NBFS ){ z = sqliteMallocRaw( amt ); if( z==0 ) goto no_mem; - aStack[tos].flags = MEM_Str | MEM_Dyn; + pTos->flags = MEM_Str | MEM_Dyn; }else{ - z = aStack[tos].zShort; - aStack[tos].flags = MEM_Str; + z = pTos->zShort; + pTos->flags = MEM_Str | MEM_Short; } sqliteBtreeKey(pCrsr, 0, amt, z); - aStack[tos].z = z; - aStack[tos].n = amt; + pTos->z = z; + pTos->n = amt; } break; } @@ -3440,15 +3418,16 @@ case OP_Next: { */ case OP_IdxPut: { int i = pOp->p1; - int tos = p->tos; BtCursor *pCrsr; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - if( VERIFY( i>=0 && inCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ - int nKey = aStack[tos].n; - const char *zKey = aStack[tos].z; + assert( pTos>=p->aStack ); + assert( i>=0 && inCursor ); + assert( pTos->flags & MEM_Str ); + if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ + int nKey = pTos->n; + const char *zKey = pTos->z; if( pOp->p2 ){ int res, n; - assert( aStack[tos].n >= 4 ); + assert( nKey >= 4 ); rc = sqliteBtreeMoveto(pCrsr, zKey, nKey-4, &res); if( rc!=SQLITE_OK ) goto abort_due_to_error; while( res!=0 ){ @@ -3475,7 +3454,8 @@ case OP_IdxPut: { rc = sqliteBtreeInsert(pCrsr, zKey, nKey, "", 0); assert( p->aCsr[i].deferredMoveto==0 ); } - POPSTACK; + Release(pTos); + pTos--; break; } @@ -3486,18 +3466,20 @@ case OP_IdxPut: { */ case OP_IdxDelete: { int i = pOp->p1; - int tos = p->tos; BtCursor *pCrsr; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - if( VERIFY( i>=0 && inCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ + assert( pTos>=p->aStack ); + assert( pTos->flags & MEM_Str ); + assert( i>=0 && inCursor ); + if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ int rx, res; - rx = sqliteBtreeMoveto(pCrsr, aStack[tos].z, aStack[tos].n, &res); + rx = sqliteBtreeMoveto(pCrsr, pTos->z, pTos->n, &res); if( rx==SQLITE_OK && res==0 ){ rc = sqliteBtreeDelete(pCrsr); } assert( p->aCsr[i].deferredMoveto==0 ); } - POPSTACK; + Release(pTos); + pTos--; break; } @@ -3512,22 +3494,25 @@ case OP_IdxDelete: { */ case OP_IdxRecno: { int i = pOp->p1; - int tos = ++p->tos; BtCursor *pCrsr; - if( VERIFY( i>=0 && inCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ + assert( i>=0 && inCursor ); + pTos++; + if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ int v; int sz; assert( p->aCsr[i].deferredMoveto==0 ); sqliteBtreeKeySize(pCrsr, &sz); if( szflags = MEM_Null; }else{ sqliteBtreeKey(pCrsr, sz - sizeof(u32), sizeof(u32), (char*)&v); v = keyToInt(v); - aStack[tos].i = v; - aStack[tos].flags = MEM_Int; + pTos->i = v; + pTos->flags = MEM_Int; } + }else{ + pTos->flags = MEM_Null; } break; } @@ -3561,15 +3546,16 @@ case OP_IdxLT: case OP_IdxGT: case OP_IdxGE: { int i= pOp->p1; - int tos = p->tos; BtCursor *pCrsr; - if( VERIFY( i>=0 && inCursor && ) (pCrsr = p->aCsr[i].pCursor)!=0 ){ + assert( i>=0 && inCursor ); + assert( pTos>=p->aStack ); + if( (pCrsr = p->aCsr[i].pCursor)!=0 ){ int res, rc; - Stringify(p, tos); + Stringify(pTos); assert( p->aCsr[i].deferredMoveto==0 ); - rc = sqliteBtreeKeyCompare(pCrsr, aStack[tos].z, aStack[tos].n, 4, &res); + rc = sqliteBtreeKeyCompare(pCrsr, pTos->z, pTos->n, 4, &res); if( rc!=SQLITE_OK ){ break; } @@ -3582,7 +3568,8 @@ case OP_IdxGE: { pc = pOp->p2 - 1 ; } } - POPSTACK; + Release(pTos); + pTos--; break; } @@ -3597,14 +3584,13 @@ case OP_IdxGE: { */ case OP_IdxIsNull: { int i = pOp->p1; - int tos = p->tos; int k, n; const char *z; - assert( tos>=0 ); - assert( aStack[tos].flags & MEM_Str ); - z = aStack[tos].z; - n = aStack[tos].n; + assert( pTos>=p->aStack ); + assert( pTos->flags & MEM_Str ); + z = pTos->z; + n = pTos->n; for(k=0; k0; i--){ if( z[k]=='a' ){ pc = pOp->p2-1; @@ -3613,7 +3599,8 @@ case OP_IdxIsNull: { while( ktos; int pgno; assert( pOp->p3!=0 && pOp->p3type==P3_POINTER ); assert( pOp->p2>=0 && pOp->p2nDb ); @@ -3687,9 +3673,10 @@ case OP_CreateTable: { }else{ rc = sqliteBtreeCreateIndex(db->aDb[pOp->p2].pBt, &pgno); } + pTos++; if( rc==SQLITE_OK ){ - aStack[i].i = pgno; - aStack[i].flags = MEM_Int; + pTos->i = pgno; + pTos->flags = MEM_Int; *(u32*)pOp->p3 = pgno; pOp->p3 = 0; } @@ -3715,14 +3702,14 @@ case OP_CreateTable: { case OP_IntegrityCk: { int nRoot; int *aRoot; - int tos = ++p->tos; int iSet = pOp->p1; Set *pSet; int j; HashElem *i; char *z; - VERIFY( if( iSet<0 || iSet>=p->nSet ) goto bad_instruction; ) + assert( iSet>=0 && iSetnSet ); + pTos++; pSet = &p->aSet[iSet]; nRoot = sqliteHashCount(&pSet->hash); aRoot = sqliteMallocRaw( sizeof(int)*(nRoot+1) ); @@ -3736,13 +3723,13 @@ case OP_IntegrityCk: { z = sqliteBtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot); if( z==0 || z[0]==0 ){ if( z ) sqliteFree(z); - aStack[tos].z = "ok"; - aStack[tos].n = 3; - aStack[tos].flags = MEM_Str | MEM_Static; + pTos->z = "ok"; + pTos->n = 3; + pTos->flags = MEM_Str | MEM_Static; }else{ - aStack[tos].z = z; - aStack[tos].n = strlen(z) + 1; - aStack[tos].flags = MEM_Str | MEM_Dyn; + pTos->z = z; + pTos->n = strlen(z) + 1; + pTos->flags = MEM_Str | MEM_Dyn; } sqliteFree(aRoot); break; @@ -3755,7 +3742,7 @@ case OP_IntegrityCk: { */ case OP_ListWrite: { Keylist *pKeylist; - VERIFY( if( p->tos<0 ) goto not_enough_stack; ) + assert( pTos>=p->aStack ); pKeylist = p->pList; if( pKeylist==0 || pKeylist->nUsed>=pKeylist->nKey ){ pKeylist = sqliteMallocRaw( sizeof(Keylist)+999*sizeof(pKeylist->aKey[0]) ); @@ -3766,9 +3753,10 @@ case OP_ListWrite: { pKeylist->pNext = p->pList; p->pList = pKeylist; } - Integerify(p, p->tos); - pKeylist->aKey[pKeylist->nUsed++] = aStack[p->tos].i; - POPSTACK; + Integerify(pTos); + pKeylist->aKey[pKeylist->nUsed++] = pTos->i; + assert( pTos->flags==MEM_Int ); + pTos--; break; } @@ -3793,15 +3781,12 @@ case OP_ListRead: { CHECK_FOR_INTERRUPT; pKeylist = p->pList; if( pKeylist!=0 ){ - VERIFY( - if( pKeylist->nRead<0 - || pKeylist->nRead>=pKeylist->nUsed - || pKeylist->nRead>=pKeylist->nKey ) goto bad_instruction; - ) - p->tos++; - aStack[p->tos].i = pKeylist->aKey[pKeylist->nRead++]; - aStack[p->tos].flags = MEM_Int; - aStack[p->tos].z = 0; + assert( pKeylist->nRead>=0 ); + assert( pKeylist->nReadnUsed ); + assert( pKeylist->nReadnKey ); + pTos++; + pTos->i = pKeylist->aKey[pKeylist->nRead++]; + pTos->flags = MEM_Int; if( pKeylist->nRead>=pKeylist->nUsed ){ p->pList = pKeylist->pNext; sqliteFree(pKeylist); @@ -3865,29 +3850,21 @@ case OP_ListPop: { ** made using SortMakeKey and SortMakeRec, respectively. */ case OP_SortPut: { - int tos = p->tos; - int nos = tos - 1; + Mem *pNos = &pTos[-1]; Sorter *pSorter; - VERIFY( if( tos<1 ) goto not_enough_stack; ) - if( Dynamicify(p, tos) || Dynamicify(p, nos) ) goto no_mem; + assert( pNos>=p->aStack ); + if( Dynamicify(pTos) || Dynamicify(pNos) ) goto no_mem; pSorter = sqliteMallocRaw( sizeof(Sorter) ); if( pSorter==0 ) goto no_mem; pSorter->pNext = p->pSort; p->pSort = pSorter; - assert( aStack[tos].flags & MEM_Dyn ); - pSorter->nKey = aStack[tos].n; - pSorter->zKey = aStack[tos].z; - pSorter->nData = aStack[nos].n; - if( aStack[nos].flags & MEM_Dyn ){ - pSorter->pData = aStack[nos].z; - }else{ - pSorter->pData = sqliteStrDup(aStack[nos].z); - } - aStack[tos].flags = 0; - aStack[nos].flags = 0; - aStack[tos].z = 0; - aStack[nos].z = 0; - p->tos -= 2; + assert( pTos->flags & MEM_Dyn ); + pSorter->nKey = pTos->n; + pSorter->zKey = pTos->z; + assert( pNos->flags & MEM_Dyn ); + pSorter->nData = pNos->n; + pSorter->pData = pNos->z; + pTos -= 2; break; } @@ -3902,35 +3879,37 @@ case OP_SortMakeRec: { char **azArg; int nByte; int nField; - int i, j; + int i; + Mem *pRec; nField = pOp->p1; - VERIFY( if( p->tos+1=p->aStack ); nByte = 0; - for(i=p->tos-nField+1; i<=p->tos; i++){ - if( (aStack[i].flags & MEM_Null)==0 ){ - Stringify(p, i); - nByte += aStack[i].n; + for(i=0; iflags & MEM_Null)==0 ){ + Stringify(pRec); + nByte += pRec->n; } } nByte += sizeof(char*)*(nField+1); azArg = sqliteMallocRaw( nByte ); if( azArg==0 ) goto no_mem; z = (char*)&azArg[nField+1]; - for(j=0, i=p->tos-nField+1; i<=p->tos; i++, j++){ - if( aStack[i].flags & MEM_Null ){ - azArg[j] = 0; + for(pRec=&pTos[1-nField], i=0; iflags & MEM_Null ){ + azArg[i] = 0; }else{ - azArg[j] = z; - strcpy(z, aStack[i].z); - z += aStack[i].n; + azArg[i] = z; + memcpy(z, pRec->z, pRec->n); + z += pRec->n; } } - sqliteVdbePopStack(p, nField); - p->tos++; - aStack[p->tos].n = nByte; - aStack[p->tos].z = (char*)azArg; - aStack[p->tos].flags = MEM_Str|MEM_Dyn; + popStack(&pTos, nField); + pTos++; + pTos->n = nByte; + pTos->z = (char*)azArg; + pTos->flags = MEM_Str | MEM_Dyn; break; } @@ -3954,41 +3933,42 @@ case OP_SortMakeKey: { int nByte; int nField; int i, j, k; + Mem *pRec; nField = strlen(pOp->p3); - VERIFY( if( p->tos+1tos-nField+1; i<=p->tos; i++){ - if( (aStack[i].flags & MEM_Null)!=0 ){ + for(i=0; iflags & MEM_Null ){ nByte += 2; }else{ - Stringify(p, i); - nByte += aStack[i].n+2; + Stringify(pRec); + nByte += pRec->n+2; } } zNewKey = sqliteMallocRaw( nByte ); if( zNewKey==0 ) goto no_mem; j = 0; k = 0; - for(i=p->tos-nField+1; i<=p->tos; i++){ - if( (aStack[i].flags & MEM_Null)!=0 ){ + for(pRec=&pTos[1-nField], i=0; iflags & MEM_Null ){ zNewKey[j++] = 'N'; zNewKey[j++] = 0; k++; }else{ zNewKey[j++] = pOp->p3[k++]; - memcpy(&zNewKey[j], aStack[i].z, aStack[i].n-1); - j += aStack[i].n-1; + memcpy(&zNewKey[j], pRec->z, pRec->n-1); + j += pRec->n-1; zNewKey[j++] = 0; } } zNewKey[j] = 0; assert( jtos++; - aStack[p->tos].n = nByte; - aStack[p->tos].flags = MEM_Str|MEM_Dyn; - aStack[p->tos].z = zNewKey; + popStack(&pTos, nField); + pTos++; + pTos->n = nByte; + pTos->flags = MEM_Str|MEM_Dyn; + pTos->z = zNewKey; break; } @@ -4041,10 +4021,10 @@ case OP_SortNext: { CHECK_FOR_INTERRUPT; if( pSorter!=0 ){ p->pSort = pSorter->pNext; - p->tos++; - aStack[p->tos].z = pSorter->pData; - aStack[p->tos].n = pSorter->nData; - aStack[p->tos].flags = MEM_Str|MEM_Dyn; + pTos++; + pTos->z = pSorter->pData; + pTos->n = pSorter->nData; + pTos->flags = MEM_Str|MEM_Dyn; sqliteFree(pSorter->zKey); sqliteFree(pSorter); }else{ @@ -4061,23 +4041,25 @@ case OP_SortNext: { ** callback on it. */ case OP_SortCallback: { - int i = p->tos; - VERIFY( if( i<0 ) goto not_enough_stack; ) + assert( pTos>=p->aStack ); + assert( pTos->flags & MEM_Str ); if( p->xCallback==0 ){ p->pc = pc+1; - p->azResColumn = (char**)aStack[i].z; + p->azResColumn = (char**)pTos->z; p->nResColumn = pOp->p1; p->popStack = 1; + p->pTos = pTos; return SQLITE_ROW; }else{ if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; - if( p->xCallback(p->pCbArg, pOp->p1, (char**)aStack[i].z, p->azColName)!=0){ + if( p->xCallback(p->pCbArg, pOp->p1, (char**)pTos->z, p->azColName)!=0){ rc = SQLITE_ABORT; } if( sqliteSafetyOn(db) ) goto abort_due_to_misuse; p->nCallback++; } - POPSTACK; + Release(pTos); + pTos--; if( sqlite_malloc_failed ) goto no_mem; break; } @@ -4097,7 +4079,7 @@ case OP_SortReset: { ** If P3 is "stdin" then open standard input for reading. */ case OP_FileOpen: { - VERIFY( if( pOp->p3==0 ) goto bad_instruction; ) + assert( pOp->p3!=0 ); if( p->pFile ){ if( p->pFile!=stdin ) fclose(p->pFile); p->pFile = 0; @@ -4242,20 +4224,19 @@ fileread_jump: case OP_FileColumn: { int i = pOp->p1; char *z; - if( VERIFY( i>=0 && inField && ) p->azField ){ + assert( i>=0 && inField ); + if( p->azField ){ z = p->azField[i]; }else{ z = 0; } - p->tos++; + pTos++; if( z ){ - aStack[p->tos].n = strlen(z) + 1; - aStack[p->tos].z = z; - aStack[p->tos].flags = MEM_Str; + pTos->n = strlen(z) + 1; + pTos->z = z; + pTos->flags = MEM_Str | MEM_Ephem; }else{ - aStack[p->tos].n = 0; - aStack[p->tos].z = 0; - aStack[p->tos].flags = MEM_Null; + pTos->flags = MEM_Null; } break; } @@ -4272,11 +4253,10 @@ case OP_FileColumn: { */ case OP_MemStore: { int i = pOp->p1; - int tos = p->tos; char *zOld; Mem *pMem; int flags; - VERIFY( if( tos<0 ) goto not_enough_stack; ) + assert( pTos>=p->aStack ); if( i>=p->nMem ){ int nOld = p->nMem; Mem *aMem; @@ -4286,7 +4266,7 @@ case OP_MemStore: { if( aMem!=p->aMem ){ int j; for(j=0; jaMem[j].zShort ){ + if( aMem[j].flags & MEM_Short ){ aMem[j].z = aMem[j].zShort; } } @@ -4303,26 +4283,24 @@ case OP_MemStore: { }else{ zOld = 0; } - *pMem = aStack[tos]; + *pMem = *pTos; flags = pMem->flags; - if( flags & (MEM_Static|MEM_Dyn|MEM_Ephem) ){ - if( (flags & MEM_Static)!=0 || (pOp->p2 && (flags & MEM_Dyn)!=0) ){ - /* pMem->z = zStack[tos]; *** do nothing */ - }else if( flags & MEM_Str ){ + if( flags & MEM_Dyn ){ + if( pOp->p2 ){ + pTos->flags = MEM_Null; + }else{ + /* OR: perhaps just make the stack ephermeral */ pMem->z = sqliteMallocRaw( pMem->n ); if( pMem->z==0 ) goto no_mem; - memcpy(pMem->z, aStack[tos].z, pMem->n); - pMem->flags |= MEM_Dyn; - pMem->flags &= ~(MEM_Static|MEM_Ephem); + memcpy(pMem->z, pTos->z, pMem->n); } - }else{ + }else if( flags & MEM_Short ){ pMem->z = pMem->zShort; } if( zOld ) sqliteFree(zOld); if( pOp->p2 ){ - aStack[tos].z = 0; - aStack[tos].flags = 0; - POPSTACK; + Release(pTos); + pTos--; } break; } @@ -4337,14 +4315,13 @@ case OP_MemStore: { ** value pushed onto the stack will change too. */ case OP_MemLoad: { - int tos = ++p->tos; int i = pOp->p1; - VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; ) - memcpy(&aStack[tos], &p->aMem[i], sizeof(aStack[tos])-NBFS);; - if( aStack[tos].flags & MEM_Str ){ - /* aStack[tos].z = p->aMem[i].z; */ - aStack[tos].flags |= MEM_Ephem; - aStack[tos].flags &= ~(MEM_Dyn|MEM_Static); + assert( i>=0 && inMem ); + pTos++; + memcpy(pTos, &p->aMem[i], sizeof(pTos[0])-NBFS);; + if( pTos->flags & MEM_Str ){ + pTos->flags |= MEM_Ephem; + pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short); } break; } @@ -4361,9 +4338,9 @@ case OP_MemLoad: { case OP_MemIncr: { int i = pOp->p1; Mem *pMem; - VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; ) + assert( i>=0 && inMem ); pMem = &p->aMem[i]; - VERIFY( if( pMem->flags != MEM_Int ) goto bad_instruction; ) + assert( pMem->flags==MEM_Int ); pMem->i++; if( pOp->p2>0 && pMem->i>0 ){ pc = pOp->p2 - 1; @@ -4392,7 +4369,7 @@ case OP_AggReset: { */ case OP_AggInit: { int i = pOp->p2; - VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; ) + assert( i>=0 && iagg.nMem ); p->agg.apFunc[i] = (FuncDef*)pOp->p3; break; } @@ -4411,22 +4388,24 @@ case OP_AggInit: { case OP_AggFunc: { int n = pOp->p2; int i; - Mem *pMem; + Mem *pMem, *pRec; + char **azArgv = p->zArgv; sqlite_func ctx; - VERIFY( if( n<0 ) goto bad_instruction; ) - VERIFY( if( p->tos+1tos].flags!=MEM_Int ) goto bad_instruction; ) - for(i=p->tos-n; itos; i++){ - if( aStack[i].flags & MEM_Null ){ - aStack[i].z = 0; + assert( n>=0 ); + assert( pTos->flags==MEM_Int ); + pRec = &pTos[-n]; + assert( pRec>=p->aStack ); + for(i=0; iflags & MEM_Null ){ + azArgv[i] = 0; }else{ - Stringify(p, i); + Stringify(pRec); + azArgv[i] = pRec->z; } - p->zArgv[i] = aStack[i].z; } - i = aStack[p->tos].i; - VERIFY( if( i<0 || i>=p->agg.nMem ) goto bad_instruction; ) + i = pTos->i; + assert( i>=0 && iagg.nMem ); ctx.pFunc = (FuncDef*)pOp->p3; pMem = &p->agg.pCurrent->aMem[i]; ctx.s.z = pMem->zShort; /* Space used for small aggregate contexts */ @@ -4434,10 +4413,10 @@ case OP_AggFunc: { ctx.cnt = ++pMem->i; ctx.isError = 0; ctx.isStep = 1; - (ctx.pFunc->xStep)(&ctx, n, (const char**)&p->zArgv[p->tos-n]); + (ctx.pFunc->xStep)(&ctx, n, (const char**)azArgv); pMem->z = ctx.pAgg; pMem->flags = MEM_AggCtx; - sqliteVdbePopStack(p, n+1); + popStack(&pTos, n+1); if( ctx.isError ){ rc = SQLITE_ERROR; } @@ -4459,15 +4438,14 @@ case OP_AggFunc: { ** in between an AggNext and an AggReset. */ case OP_AggFocus: { - int tos = p->tos; AggElem *pElem; char *zKey; int nKey; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - Stringify(p, tos); - zKey = aStack[tos].z; - nKey = aStack[tos].n; + assert( pTos>=p->aStack ); + Stringify(pTos); + zKey = pTos->z; + nKey = pTos->n; pElem = sqliteHashFind(&p->agg.hash, zKey, nKey); if( pElem ){ p->agg.pCurrent = pElem; @@ -4476,7 +4454,8 @@ case OP_AggFocus: { AggInsert(&p->agg, zKey, nKey); if( sqlite_malloc_failed ) goto no_mem; } - POPSTACK; + Release(pTos); + pTos--; break; } @@ -4488,10 +4467,11 @@ case OP_AggFocus: { case OP_AggSet: { AggElem *pFocus = AggInFocus(p->agg); int i = pOp->p2; - int tos = p->tos; - VERIFY( if( tos<0 ) goto not_enough_stack; ) + assert( pTos>=p->aStack ); if( pFocus==0 ) goto no_mem; - if( VERIFY( i>=0 && ) iagg.nMem ){ + assert( i>=0 ); + assert( iagg.nMem ); + if( iagg.nMem ){ Mem *pMem = &pFocus->aMem[i]; char *zOld; if( pMem->flags & MEM_Dyn ){ @@ -4499,19 +4479,17 @@ case OP_AggSet: { }else{ zOld = 0; } - Deephemeralize(p, tos); - *pMem = aStack[tos]; + Deephemeralize(pTos); + *pMem = *pTos; if( pMem->flags & MEM_Dyn ){ - aStack[tos].z = 0; - aStack[tos].flags = 0; - }else if( pMem->flags & (MEM_Static|MEM_AggCtx) ){ - /* pMem->z = zStack[tos]; *** do nothing */ - }else if( pMem->flags & MEM_Str ){ + pTos->flags = MEM_Null; + }else if( pMem->flags & MEM_Short ){ pMem->z = pMem->zShort; } if( zOld ) sqliteFree(zOld); } - POPSTACK; + Release(pTos); + pTos--; break; } @@ -4524,13 +4502,15 @@ case OP_AggSet: { case OP_AggGet: { AggElem *pFocus = AggInFocus(p->agg); int i = pOp->p2; - int tos = ++p->tos; if( pFocus==0 ) goto no_mem; - if( VERIFY( i>=0 && ) iagg.nMem ){ + assert( i>=0 ); + pTos++; + assert( iagg.nMem ); + if( iagg.nMem ){ Mem *pMem = &pFocus->aMem[i]; - aStack[tos] = *pMem; - aStack[tos].flags &= ~MEM_Dyn; - aStack[tos].flags |= MEM_Ephem; + *pTos = *pMem; + pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short); + pTos->flags |= MEM_Ephem; } break; } @@ -4578,8 +4558,7 @@ case OP_AggNext: { sqliteFree( aMem[i].z ); } aMem[i] = ctx.s; - if( (aMem[i].flags & MEM_Str) && - (aMem[i].flags & (MEM_Dyn|MEM_Static|MEM_Ephem))==0 ){ + if( aMem[i].flags & MEM_Short ){ aMem[i].z = aMem[i].zShort; } } @@ -4608,11 +4587,11 @@ case OP_SetInsert: { if( pOp->p3 ){ sqliteHashInsert(&p->aSet[i].hash, pOp->p3, strlen(pOp->p3)+1, p); }else{ - int tos = p->tos; - if( tos<0 ) goto not_enough_stack; - Stringify(p, tos); - sqliteHashInsert(&p->aSet[i].hash, aStack[tos].z, aStack[tos].n, p); - POPSTACK; + assert( pTos>=p->aStack ); + Stringify(pTos); + sqliteHashInsert(&p->aSet[i].hash, pTos->z, pTos->n, p); + Release(pTos); + pTos--; } if( sqlite_malloc_failed ) goto no_mem; break; @@ -4626,14 +4605,13 @@ case OP_SetInsert: { */ case OP_SetFound: { int i = pOp->p1; - int tos = p->tos; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - Stringify(p, tos); - if( i>=0 && inSet && - sqliteHashFind(&p->aSet[i].hash, aStack[tos].z, aStack[tos].n)){ + assert( pTos>=p->aStack ); + Stringify(pTos); + if( i>=0 && inSet && sqliteHashFind(&p->aSet[i].hash, pTos->z, pTos->n)){ pc = pOp->p2 - 1; } - POPSTACK; + Release(pTos); + pTos--; break; } @@ -4645,14 +4623,14 @@ case OP_SetFound: { */ case OP_SetNotFound: { int i = pOp->p1; - int tos = p->tos; - VERIFY( if( tos<0 ) goto not_enough_stack; ) - Stringify(p, tos); + assert( pTos>=p->aStack ); + Stringify(pTos); if( i<0 || i>=p->nSet || - sqliteHashFind(&p->aSet[i].hash, aStack[tos].z, aStack[tos].n)==0 ){ + sqliteHashFind(&p->aSet[i].hash, pTos->z, pTos->n)==0 ){ pc = pOp->p2 - 1; } - POPSTACK; + Release(pTos); + pTos--; break; } @@ -4671,7 +4649,6 @@ case OP_SetNotFound: { case OP_SetFirst: case OP_SetNext: { Set *pSet; - int tos; CHECK_FOR_INTERRUPT; if( pOp->p1<0 || pOp->p1>=p->nSet ){ if( pOp->opcode==OP_SetFirst ) pc = pOp->p2 - 1; @@ -4685,7 +4662,7 @@ case OP_SetNext: { break; } }else{ - VERIFY( if( pSet->prev==0 ) goto bad_instruction; ) + assert( pSet->prev ); pSet->prev = sqliteHashNext(pSet->prev); if( pSet->prev==0 ){ break; @@ -4693,10 +4670,10 @@ case OP_SetNext: { pc = pOp->p2 - 1; } } - tos = ++p->tos; - aStack[tos].z = sqliteHashKey(pSet->prev); - aStack[tos].n = sqliteHashKeysize(pSet->prev); - aStack[tos].flags = MEM_Str | MEM_Ephem; + pTos++; + pTos->z = sqliteHashKey(pSet->prev); + pTos->n = sqliteHashKeysize(pSet->prev); + pTos->flags = MEM_Str | MEM_Ephem; break; } @@ -4752,39 +4729,39 @@ default: { sqliteSetString(&p->zErrMsg, "jump destination out of range", (char*)0); rc = SQLITE_INTERNAL; } - if( p->trace && p->tos>=0 ){ + if( p->trace && pTos>=p->aStack ){ int i; fprintf(p->trace, "Stack:"); - for(i=p->tos; i>=0 && i>p->tos-5; i--){ - if( aStack[i].flags & MEM_Null ){ + for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){ + if( pTos[i].flags & MEM_Null ){ fprintf(p->trace, " NULL"); - }else if( (aStack[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ - fprintf(p->trace, " si:%d", aStack[i].i); - }else if( aStack[i].flags & MEM_Int ){ - fprintf(p->trace, " i:%d", aStack[i].i); - }else if( aStack[i].flags & MEM_Real ){ - fprintf(p->trace, " r:%g", aStack[i].r); - }else if( aStack[i].flags & MEM_Str ){ + }else if( (pTos[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ + fprintf(p->trace, " si:%d", pTos[i].i); + }else if( pTos[i].flags & MEM_Int ){ + fprintf(p->trace, " i:%d", pTos[i].i); + }else if( pTos[i].flags & MEM_Real ){ + fprintf(p->trace, " r:%g", pTos[i].r); + }else if( pTos[i].flags & MEM_Str ){ int j, k; char zBuf[100]; zBuf[0] = ' '; - if( aStack[i].flags & MEM_Dyn ){ + if( pTos[i].flags & MEM_Dyn ){ zBuf[1] = 'z'; - assert( (aStack[i].flags & (MEM_Static|MEM_Ephem))==0 ); - }else if( aStack[i].flags & MEM_Static ){ + assert( (pTos[i].flags & (MEM_Static|MEM_Ephem))==0 ); + }else if( pTos[i].flags & MEM_Static ){ zBuf[1] = 't'; - assert( (aStack[i].flags & (MEM_Dyn|MEM_Ephem))==0 ); - }else if( aStack[i].flags & MEM_Ephem ){ + assert( (pTos[i].flags & (MEM_Dyn|MEM_Ephem))==0 ); + }else if( pTos[i].flags & MEM_Ephem ){ zBuf[1] = 'e'; - assert( (aStack[i].flags & (MEM_Static|MEM_Dyn))==0 ); + assert( (pTos[i].flags & (MEM_Static|MEM_Dyn))==0 ); }else{ zBuf[1] = 's'; } zBuf[2] = '['; k = 3; - for(j=0; j<20 && jmagic = VDBE_MAGIC_HALT; + p->pTos = pTos; return rc; /* Jump to here if a malloc() fails. It's hard to get a malloc() @@ -4852,23 +4830,4 @@ abort_due_to_interrupt: } sqliteSetString(&p->zErrMsg, sqlite_error_string(rc), (char*)0); goto vdbe_halt; - - /* Jump to here if a operator is encountered that requires more stack - ** operands than are currently available on the stack. - */ -not_enough_stack: - sqlite_snprintf(sizeof(zBuf),zBuf,"%d",pc); - sqliteSetString(&p->zErrMsg, "too few operands on stack at ", zBuf, (char*)0); - rc = SQLITE_INTERNAL; - goto vdbe_halt; - - /* Jump here if an illegal or illformed instruction is executed. - */ -VERIFY( -bad_instruction: - sqlite_snprintf(sizeof(zBuf),zBuf,"%d",pc); - sqliteSetString(&p->zErrMsg, "illegal operation at ", zBuf, (char*)0); - rc = SQLITE_INTERNAL; - goto vdbe_halt; -) } diff --git a/src/vdbeInt.h b/src/vdbeInt.h index daa25052d4..28f658a7ef 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -129,12 +129,13 @@ typedef struct Mem Mem; #define MEM_Dyn 0x0010 /* Need to call sqliteFree() on Mem.z */ #define MEM_Static 0x0020 /* Mem.z points to a static string */ #define MEM_Ephem 0x0040 /* Mem.z points to an ephemeral string */ +#define MEM_Short 0x0080 /* Mem.z points to Mem.zShort */ /* The following MEM_ value appears only in AggElem.aMem.s.flag fields. ** It indicates that the corresponding AggElem.aMem.z points to a ** aggregate function context that needs to be finalized. */ -#define MEM_AggCtx 0x0040 /* Mem.z points to an agg function context */ +#define MEM_AggCtx 0x0100 /* Mem.z points to an agg function context */ /* ** The "context" argument for a installable function. A pointer to an @@ -223,8 +224,8 @@ struct Vdbe { int nLabel; /* Number of labels used */ int nLabelAlloc; /* Number of slots allocated in aLabel[] */ int *aLabel; /* Space to hold the labels */ - int tos; /* Index of top of stack */ Mem *aStack; /* The operand stack, except string values */ + Mem *pTos; /* Top entry in the operand stack */ char **zArgv; /* Text values used by the callback */ char **azColName; /* Becomes the 4th parameter to callbacks */ int nCursor; /* Number of slots in aCsr[] */ @@ -274,16 +275,6 @@ struct Vdbe { #define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */ #define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */ -/* -** Here is a macro to handle the common case of popping the stack -** once. This macro only works from within the sqliteVdbeExec() -** function. -*/ -#define POPSTACK \ - assert(p->tos>=0); \ - if( aStack[p->tos].flags & MEM_Dyn ) sqliteFree(aStack[p->tos].z); \ - p->tos--; - /* ** Function prototypes */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 3648062e0b..f3f73cad00 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -388,7 +388,7 @@ char *sqlite_set_result_string(sqlite_func *p, const char *zResult, int n){ if( ns.zShort, zResult, n); p->s.zShort[n] = 0; - p->s.flags = MEM_Str; + p->s.flags = MEM_Str | MEM_Short; p->s.z = p->s.zShort; }else{ p->s.z = sqliteMallocRaw( n+1 ); @@ -597,8 +597,8 @@ void sqliteVdbeMakeReady( assert( nVar>=0 ); n = isExplain ? 10 : p->nOp; p->aStack = sqliteMalloc( - n*(sizeof(p->aStack[0]) + 2*sizeof(char*)) /* aStack and zArgv */ - + p->nVar*(sizeof(char*)+sizeof(int)+1) /* azVar, anVar, abVar */ + n*(sizeof(p->aStack[0]) + 2*sizeof(char*)) /* aStack and zArgv */ + + p->nVar*(sizeof(char*)+sizeof(int)+1) /* azVar, anVar, abVar */ ); p->zArgv = (char**)&p->aStack[n]; p->azColName = (char**)&p->zArgv[n]; @@ -614,7 +614,7 @@ void sqliteVdbeMakeReady( p->trace = stdout; } #endif - p->tos = -1; + p->pTos = &p->aStack[-1]; p->pc = 0; p->rc = SQLITE_OK; p->uniqueCnt = 0; @@ -651,22 +651,6 @@ void sqliteVdbeSorterReset(Vdbe *p){ } } -/* -** Pop the stack N times. Free any memory associated with the -** popped stack elements. -*/ -void sqliteVdbePopStack(Vdbe *p, int N){ - assert( N>=0 ); - if( p->aStack==0 ) return; - while( N-- > 0 ){ - if( p->aStack[p->tos].flags & MEM_Dyn ){ - sqliteFree(p->aStack[p->tos].z); - } - p->aStack[p->tos].flags = 0; - p->tos--; - } -} - /* ** Reset an Agg structure. Delete all its contents. ** @@ -758,7 +742,16 @@ static void closeAllCursors(Vdbe *p){ */ static void Cleanup(Vdbe *p){ int i; - sqliteVdbePopStack(p, p->tos+1); + if( p->aStack ){ + Mem *pTos = p->pTos; + while( pTos>=p->aStack ){ + if( pTos->flags & MEM_Dyn ){ + sqliteFree(pTos->z); + } + pTos--; + } + p->pTos = pTos; + } closeAllCursors(p); if( p->aMem ){ for(i=0; inMem; i++){ @@ -871,7 +864,7 @@ int sqliteVdbeReset(Vdbe *p, char **pzErrMsg){ db->aDb[i].inTrans = 1; } } - assert( p->tospc || sqlite_malloc_failed==1 ); + assert( p->pTos<&p->aStack[p->pc] || sqlite_malloc_failed==1 ); #ifdef VDBE_PROFILE { FILE *out = fopen("vdbe_profile.out", "a"); diff --git a/tool/memleak.awk b/tool/memleak.awk index bf12cb406b..185f174897 100644 --- a/tool/memleak.awk +++ b/tool/memleak.awk @@ -10,6 +10,9 @@ mem[$10] = $0 } /[0-9]+ free / { + if (mem[$6]=="") { + print "*** free without a malloc at",$6 + } mem[$6] = ""; str[$6] = "" }