From: drh Date: Sat, 5 Jan 2008 16:29:28 +0000 (+0000) Subject: Registerify binary operators. Add register tracing to debugging output. (CVS 4686) X-Git-Tag: version-3.6.10~1491 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5b6afba9242dadd7a7585dea150be2788d49f525;p=thirdparty%2Fsqlite.git Registerify binary operators. Add register tracing to debugging output. (CVS 4686) FossilOrigin-Name: 66396d2f0289e36b5fc0af5078c08d1b17f342ae --- diff --git a/manifest b/manifest index 221210f5fe..88780f56b9 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Expression\scode\sgenerator\stakes\sadvantage\sof\srecent\sopcode\schanges.\s(CVS\s4685) -D 2008-01-05T06:51:30 +C Registerify\sbinary\soperators.\s\sAdd\sregister\stracing\sto\sdebugging\soutput.\s(CVS\s4686) +D 2008-01-05T16:29:28 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -69,7 +69,7 @@ F mkdll.sh 5f8438dcac98e795d7df6529159a1ec566de0183 F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f F mkextw.sh 1a866b53637dab137191341cc875575a5ca110fb F mkopcodec.awk 3fb9bf077053c968451f4dd03d11661ac373f9d1 -F mkopcodeh.awk b5b810762528f195111fb9b72bbd224a007a5260 +F mkopcodeh.awk 165780c5d75f55fbfa02ed9bedb6eef74b9d81da F mkso.sh 24bde4c09e6fe80f718db3c31c068f45e13a2f2c F publish.sh 1c0658c63d70f182a8f5e17cc28422f1b237f51d F publish_osx.sh eca87df1e3d43d128d97d3261fd48b3d6877996e @@ -79,7 +79,7 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4 F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc F src/alter.c 5a54f58d9481ac14c4e58b702f3f8758dee84d04 -F src/analyze.c d80f65d2a02c69ac72a00c6aeb91513a26a9aca3 +F src/analyze.c 96e12e03c101cffaab50be7829d7194184864f42 F src/attach.c 1c96631e56cdc51d3d70736bf61f1fe01c62cbea F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff @@ -92,7 +92,7 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6 F src/delete.c cb1d5be17c99e41d1675763a57848bb5dd45191c F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b -F src/expr.c 991ae77f4e78584553d8d6c8b10537bec021b0a9 +F src/expr.c cb8b65c3adc8bb39f67503dfe8db8da24ebe5d21 F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 @@ -127,7 +127,7 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c 0cb6ccea4b9615627d61d7c4417cedc45776d429 F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa F src/parse.y 2ae06e8d3190faace49c5b82e7cea1fc60d084a1 -F src/pragma.c 1627b350b4d3b807f36185bfe7aab34be4a6e40c +F src/pragma.c dfb200ec383b5ab3e81cd7bc4e1305e71053ef9a F src/prepare.c f1bb8eb642082e618a359c08e3e107490eafe0e3 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da @@ -168,7 +168,7 @@ F src/update.c ac6cdfebf88340fd68550b1d7fd6a15ad7144fd8 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0 -F src/vdbe.c 5174adfb84a5db3881b53096da32d8329cb121d3 +F src/vdbe.c 0c16e643e83c8f14364213c6862864f31dbadca3 F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5 F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346 F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c @@ -603,7 +603,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 32380dcabcd3839e79f91430b0c250d6e02d9243 -R 23d7fd092a9617107d94aa7f01f63d28 +P 6c78d2a49a3e6ee8bc31f16488a430cba9eda59d +R fdff0af63eb57b92a8e5bcade477a016 U drh -Z 806d577e383a52170c44489fe3b3b0e5 +Z c3fdc5267d8f427a421314acf39cdbc6 diff --git a/manifest.uuid b/manifest.uuid index 36ab26efff..6f2823bcce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6c78d2a49a3e6ee8bc31f16488a430cba9eda59d \ No newline at end of file +66396d2f0289e36b5fc0af5078c08d1b17f342ae \ No newline at end of file diff --git a/mkopcodeh.awk b/mkopcodeh.awk index de04fab611..b40b4fdba9 100644 --- a/mkopcodeh.awk +++ b/mkopcodeh.awk @@ -130,6 +130,7 @@ END { for(name in op){ x = op[name] a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0 + a8 = a9 = a10 = a11 = a12 = a13 = a14 = a15 = 0 if( jump[name] ) a0 = 1; if( nopush[name]==0 ) a1 = 2; if( out2_prerelease[name] ) a2 = 4; @@ -138,24 +139,25 @@ END { if( in3[name] ) a5 = 32; if( out2[name] ) a6 = 64; if( out3[name] ) a7 = 128; - bv[x] = a0+a1+a2+a3+a4+a5+a6+a7; + bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15; } print "\n" print "/* Properties such as \"out2\" or \"jump\" that are specified in" print "** comments following the "case" for each opcode in the vdbe.c" print "** are encoded into bitvectors as follows:" print "*/" - print "#define OPFLG_JUMP 0x01 /* jump: P2 holds jmp target */" - print "#define OPFLG_PUSH 0x02 /* ~no-push: Does not push */" - print "#define OPFLG_OUT2_PRERELEASE 0x04 /* out2-prerelease: */" - print "#define OPFLG_IN1 0x08 /* in1: P1 is an input */" - print "#define OPFLG_IN2 0x10 /* in2: P2 is an input */" - print "#define OPFLG_IN3 0x20 /* in3: P3 is an input */" - print "#define OPFLG_OUT2 0x40 /* out2: P2 is an output */" - print "#define OPFLG_OUT3 0x80 /* out3: P3 is an output */" + print "#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */" + print "#define OPFLG_PUSH 0x0002 /* ~no-push: Does not push */" + print "#define OPFLG_OUT2_PRERELEASE 0x0004 /* out2-prerelease: */" + print "#define OPFLG_IN1 0x0008 /* in1: P1 is an input */" + print "#define OPFLG_IN2 0x0010 /* in2: P2 is an input */" + print "#define OPFLG_IN3 0x0020 /* in3: P3 is an input */" + print "#define OPFLG_OUT2 0x0040 /* out2: P2 is an output */" + print "#define OPFLG_OUT3 0x0080 /* out3: P3 is an output */" print "#define OPFLG_INITIALIZER {\\" for(i=0; i<=max; i++){ - printf " 0x%02x,", bv[i] + if( i%8==0 ) printf("/* %3d */",i) + printf " 0x%04x,", bv[i] if( i%8==7 ) printf("\\\n"); } print "}" diff --git a/src/analyze.c b/src/analyze.c index 54d985510d..9b5494a2d5 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.33 2008/01/05 05:20:10 drh Exp $ +** @(#) $Id: analyze.c,v 1.34 2008/01/05 16:29:28 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" @@ -159,7 +159,7 @@ static void analyzeOneTable( for(i=0; izName, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pIdx->zName, 0); sqlite3VdbeAddOp1(v, OP_SCopy, iMem); - sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, " ", 0); for(i=0; i @@ -2086,6 +2086,7 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ case TK_LSHIFT: case TK_RSHIFT: case TK_CONCAT: { + int r1, r2; assert( TK_AND==OP_And ); assert( TK_OR==OP_Or ); assert( TK_PLUS==OP_Add ); @@ -2097,10 +2098,13 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ assert( TK_LSHIFT==OP_ShiftLeft ); assert( TK_RSHIFT==OP_ShiftRight ); assert( TK_CONCAT==OP_Concat ); - sqlite3ExprCode(pParse, pExpr->pLeft, 0); - sqlite3ExprCode(pParse, pExpr->pRight, 0); - sqlite3VdbeAddOp0(v, op); - stackChng = -1; + r1 = sqlite3ExprCode(pParse, pExpr->pLeft, 0); + r2 = sqlite3ExprCode(pParse, pExpr->pRight, 0); + sqlite3VdbeAddOp3(v, op, r2, r1, target); + if( r1==0 ) stackChng--; + if( r2==0 ) stackChng--; + if( target==0 ) stackChng++; + inReg = target; break; } case TK_UMINUS: { @@ -2349,8 +2353,12 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){ } #endif } - if( inReg!=target && origTarget!=-1 ){ - sqlite3VdbeAddOp2(v, (inReg>0 ? OP_SCopy : OP_Move), inReg, target); + if( inReg!=target ){ + if( origTarget!=-1 ){ + sqlite3VdbeAddOp2(v, (inReg>0 ? OP_SCopy : OP_Move), inReg, target); + }else{ + target = inReg; + } stackChng = 0; } if( pParse->ckOffset ){ diff --git a/src/pragma.c b/src/pragma.c index ec4a0f80f5..50e3f9c8ff 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.160 2008/01/05 05:20:10 drh Exp $ +** $Id: pragma.c,v 1.161 2008/01/05 16:29:28 drh Exp $ */ #include "sqliteInt.h" #include @@ -887,7 +887,7 @@ void sqlite3Pragma( sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zName), P4_DYNAMIC); sqlite3VdbeAddOp2(v, OP_Pull, 1, 0); - sqlite3VdbeAddOp2(v, OP_Concat, 0, 0); + sqlite3VdbeAddOp0(v, OP_Concat); sqlite3VdbeAddOp2(v, OP_Callback, 1, 0); sqlite3VdbeJumpHere(v, addr); @@ -914,7 +914,9 @@ void sqlite3Pragma( { OP_Rowid, 1, 0, 0}, { OP_String8, 0, 0, 0}, /* 3 */ { OP_String8, 0, 0, 0}, /* 4 */ - { OP_Concat, 2, 0, 0}, + { OP_Concat, 0, 0, 0}, + { OP_Concat, 0, 0, 0}, + { OP_Concat, 0, 0, 0}, { OP_Callback, 1, 0, 0}, }; sqlite3GenerateIndexKey(v, pIdx, 1); diff --git a/src/vdbe.c b/src/vdbe.c index ae8245612f..711653432a 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.683 2008/01/05 06:51:32 drh Exp $ +** $Id: vdbe.c,v 1.684 2008/01/05 16:29:28 drh Exp $ */ #include "sqliteInt.h" #include @@ -178,7 +178,7 @@ static void _storeTypeInfo(Mem *pMem){ ** from the comments following the "case OP_xxxx:" statements in ** this file. */ -static unsigned char opcodeProperty[] = OPFLG_INITIALIZER; +static unsigned short opcodeProperty[] = OPFLG_INITIALIZER; /* ** Return true if an opcode has any of the OPFLG_xxx properties @@ -396,6 +396,39 @@ void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){ } #endif +#ifdef SQLITE_DEBUG +/* +** Print the value of a register for tracing purposes: +*/ +static void memTracePrint(FILE *out, Mem *p){ + if( p->flags & MEM_Null ){ + fprintf(out, " NULL"); + }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ + fprintf(out, " si:%lld", p->u.i); + }else if( p->flags & MEM_Int ){ + fprintf(out, " i:%lld", p->u.i); + }else if( p->flags & MEM_Real ){ + fprintf(out, " r:%g", p->r); + }else{ + char zBuf[200]; + sqlite3VdbeMemPrettyPrint(p, zBuf); + fprintf(out, " "); + fprintf(out, "%s", zBuf); + } +} +static void registerTrace(FILE *out, int iReg, Mem *p){ + fprintf(out, "REG[%d] = ", iReg); + memTracePrint(out, p); + fprintf(out, "\n"); +} +#endif + +#ifdef SQLITE_DEBUG +# define REGISTER_TRACE(R,M) if(p->trace&&R>0)registerTrace(p->trace,R,M) +#else +# define REGISTER_TRACE(R,M) +#endif + #ifdef VDBE_PROFILE /* @@ -467,7 +500,7 @@ int sqlite3VdbeExec( sqlite3 *db = p->db; /* The database */ u8 encoding = ENC(db); /* The database encoding */ Mem *pTos; /* Top entry in the operand stack */ - Mem *pIn1, *pIn2; /* Input operands */ + Mem *pIn1, *pIn2, *pIn3; /* Input operands */ Mem *pOut; /* Output operand */ int nPop = 0; /* Number of times to pop the stack */ u8 opProperty; @@ -632,6 +665,7 @@ int sqlite3VdbeExec( }else{ assert( pOp->p1<=p->nMem ); pIn1 = &p->aMem[pOp->p1]; + REGISTER_TRACE(pOp->p1, pIn1); } if( (opProperty & OPFLG_IN2)!=0 ){ assert( pOp->p2>=0 ); @@ -641,13 +675,18 @@ int sqlite3VdbeExec( }else{ assert( pOp->p2<=p->nMem ); pIn2 = &p->aMem[pOp->p2]; + REGISTER_TRACE(pOp->p2, pIn2); } if( (opProperty & OPFLG_OUT3)!=0 ){ assert( pOp->p3>=0 ); if( pOp->p3==0 ){ - pTos++; + nPop--; + if( nPop<0 ){ + assert( nPop==(-1) ); + pTos++; + nPop = 0; + } pOut = &pTos[-nPop]; - pOut->flags = MEM_Null; }else{ assert( pOp->p3<=p->nMem ); pOut = &p->aMem[pOp->p3]; @@ -656,18 +695,23 @@ int sqlite3VdbeExec( }else if( (opProperty & OPFLG_IN3)!=0 ){ assert( pOp->p3>=0 ); if( pOp->p3==0 ){ - pIn2 = &pTos[-nPop]; + pIn3 = &pTos[-nPop]; nPop++; }else{ assert( pOp->p3<=p->nMem ); - pIn2 = &p->aMem[pOp->p3]; + pIn3 = &p->aMem[pOp->p3]; + REGISTER_TRACE(pOp->p3, pIn3); } }else if( (opProperty & OPFLG_OUT2)!=0 ){ assert( pOp->p2>=0 ); if( pOp->p2==0 ){ - pTos++; + nPop--; + if( nPop<0 ){ + assert( nPop==(-1) ); + pTos++; + nPop = 0; + } pOut = &pTos[-nPop]; - pOut->flags = MEM_Null; }else{ assert( pOp->p2<=p->nMem ); pOut = &p->aMem[pOp->p2]; @@ -1047,6 +1091,7 @@ case OP_SCopy: { }else{ assert( pOp->p1<=p->nMem ); pIn1 = &p->aMem[pOp->p1]; + REGISTER_TRACE(pOp->p1, pIn1); } assert( pOp->p2>=0 ); if( pOp->p2==0 ){ @@ -1065,6 +1110,7 @@ case OP_SCopy: { Deephemeralize(pOut); } } + REGISTER_TRACE(pOp->p2, pOut); break; } @@ -1217,79 +1263,43 @@ case OP_ResultRow: { /* no-push */ goto vdbe_return; } -/* Opcode: Concat P1 P2 * -** -** Look at the first P1+2 elements of the stack. Append them all -** together with the lowest element first. The original P1+2 elements -** are popped from the stack if P2==0 and retained if P2==1. If -** any element of the stack is NULL, then the result is NULL. +/* Opcode: Concat P1 P2 P3 * * ** -** When P1==1, this routine makes a copy of the top stack element -** into memory obtained from sqlite3_malloc(). +** Add the text in register P1 onto the end of the text in +** register P2 and store the result in register P3. +** If either the P1 or P2 text are NULL then store NULL in P3. */ -case OP_Concat: { /* same as TK_CONCAT */ +case OP_Concat: { /* same as TK_CONCAT, in1, in2, out3 */ char *zNew; i64 nByte; - int nField; - int i, j; - Mem *pTerm; - - /* Loop through the stack elements to see how long the result will be. */ - nField = pOp->p1 + 2; - pTerm = &pTos[1-nField]; - nByte = 0; - for(i=0; ip2==0 || (pTerm->flags&MEM_Str) ); - if( pTerm->flags&MEM_Null ){ - nByte = -1; - break; - } - ExpandBlob(pTerm); - Stringify(pTerm, encoding); - nByte += pTerm->n; - } - if( nByte<0 ){ - /* If nByte is less than zero, then there is a NULL value on the stack. - ** In this case just pop the values off the stack (if required) and - ** push on a NULL. - */ - if( pOp->p2==0 ){ - popStack(&pTos, nField); - } - pTos++; - pTos->flags = MEM_Null; - }else{ - /* Otherwise malloc() space for the result and concatenate all the - ** stack values. - */ - if( nByte+2>SQLITE_MAX_LENGTH ){ - goto too_big; - } - zNew = sqlite3DbMallocRaw(db, nByte+2 ); - if( zNew==0 ) goto no_mem; - j = 0; - pTerm = &pTos[1-nField]; - for(i=j=0; in; - assert( pTerm->flags & (MEM_Str|MEM_Blob) ); - memcpy(&zNew[j], pTerm->z, n); - j += n; - } - zNew[j] = 0; - zNew[j+1] = 0; - assert( j==nByte ); - - if( pOp->p2==0 ){ - popStack(&pTos, nField); - } - pTos++; - pTos->n = j; - pTos->flags = MEM_Str|MEM_Dyn|MEM_Term; - pTos->xDel = 0; - pTos->enc = encoding; - pTos->z = zNew; + if( (pIn1->flags | pIn2->flags) & MEM_Null ){ + Release(pOut); + pOut->flags = MEM_Null; + break; + } + ExpandBlob(pIn1); + Stringify(pIn1, encoding); + ExpandBlob(pIn2); + Stringify(pIn2, encoding); + nByte = pIn1->n + pIn2->n; + if( nByte>SQLITE_MAX_LENGTH ){ + goto too_big; } + zNew = sqlite3DbMallocRaw(db, nByte+2); + if( zNew==0 ){ + goto no_mem; + } + memcpy(zNew, pIn2->z, pIn2->n); + memcpy(&zNew[pIn2->n], pIn1->z, pIn1->n); + zNew[nByte] = 0; + zNew[nByte+1] = 0; + Release(pOut); + pOut->n = nByte; + pOut->flags = MEM_Str|MEM_Dyn|MEM_Term; + pOut->xDel = 0; + pOut->enc = encoding; + pOut->z = zNew; break; } @@ -1339,24 +1349,20 @@ case OP_Concat: { /* same as TK_CONCAT */ ** function before the division. Division by zero returns NULL. ** If either operand is NULL, the result is NULL. */ -case OP_Add: /* same as TK_PLUS, no-push */ -case OP_Subtract: /* same as TK_MINUS, no-push */ -case OP_Multiply: /* same as TK_STAR, no-push */ -case OP_Divide: /* same as TK_SLASH, no-push */ -case OP_Remainder: { /* same as TK_REM, no-push */ - Mem *pNos = &pTos[-1]; +case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ +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; - assert( pNos>=p->aStack ); - flags = pTos->flags | pNos->flags; + flags = pIn1->flags | pIn2->flags; if( (flags & MEM_Null)!=0 ){ - Release(pTos); - pTos--; - Release(pTos); - pTos->flags = MEM_Null; - }else if( (pTos->flags & pNos->flags & MEM_Int)==MEM_Int ){ + Release(pOut); + pOut->flags = MEM_Null; + }else if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ i64 a, b; - a = pTos->u.i; - b = pNos->u.i; + a = pIn1->u.i; + b = pIn2->u.i; switch( pOp->opcode ){ case OP_Add: b += a; break; case OP_Subtract: b -= a; break; @@ -1381,15 +1387,13 @@ case OP_Remainder: { /* same as TK_REM, no-push */ break; } } - Release(pTos); - pTos--; - Release(pTos); - pTos->u.i = b; - pTos->flags = MEM_Int; + Release(pOut); + pOut->u.i = b; + pOut->flags = MEM_Int; }else{ double a, b; - a = sqlite3VdbeRealValue(pTos); - b = sqlite3VdbeRealValue(pNos); + a = sqlite3VdbeRealValue(pIn1); + b = sqlite3VdbeRealValue(pIn2); switch( pOp->opcode ){ case OP_Add: b += a; break; case OP_Subtract: b -= a; break; @@ -1411,22 +1415,18 @@ case OP_Remainder: { /* same as TK_REM, no-push */ if( sqlite3_isnan(b) ){ goto divide_by_zero; } - Release(pTos); - pTos--; - Release(pTos); - pTos->r = b; - pTos->flags = MEM_Real; + Release(pOut); + pOut->r = b; + pOut->flags = MEM_Real; if( (flags & MEM_Real)==0 ){ - sqlite3VdbeIntegerAffinity(pTos); + sqlite3VdbeIntegerAffinity(pOut); } } break; divide_by_zero: - Release(pTos); - pTos--; - Release(pTos); - pTos->flags = MEM_Null; + Release(pOut); + pOut->flags = MEM_Null; break; } @@ -1569,22 +1569,19 @@ case OP_Function: { ** right by N bits where N is the top element on the stack. ** If either operand is NULL, the result is NULL. */ -case OP_BitAnd: /* same as TK_BITAND, no-push */ -case OP_BitOr: /* same as TK_BITOR, no-push */ -case OP_ShiftLeft: /* same as TK_LSHIFT, no-push */ -case OP_ShiftRight: { /* same as TK_RSHIFT, no-push */ - Mem *pNos = &pTos[-1]; +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; - assert( pNos>=p->aStack ); - if( (pTos->flags | pNos->flags) & MEM_Null ){ - popStack(&pTos, 2); - pTos++; - pTos->flags = MEM_Null; + if( (pIn1->flags | pIn2->flags) & MEM_Null ){ + Release(pOut); + pOut->flags = MEM_Null; break; } - a = sqlite3VdbeIntValue(pNos); - b = sqlite3VdbeIntValue(pTos); + a = sqlite3VdbeIntValue(pIn2); + b = sqlite3VdbeIntValue(pIn1); switch( pOp->opcode ){ case OP_BitAnd: a &= b; break; case OP_BitOr: a |= b; break; @@ -1592,11 +1589,9 @@ case OP_ShiftRight: { /* same as TK_RSHIFT, no-push */ case OP_ShiftRight: a >>= b; break; default: /* CANT HAPPEN */ break; } - Release(pTos); - pTos--; - Release(pTos); - pTos->u.i = a; - pTos->flags = MEM_Int; + Release(pOut); + pOut->u.i = a; + pOut->flags = MEM_Int; break; } @@ -1664,6 +1659,7 @@ case OP_MustBeInt: { /* no-push, jump */ Mem *pMem = ((pOp->p3==0)?pTos:&p->aMem[pOp->p3]); assert( pOp->p3 || pTos>=p->aStack ); assert( pOp->p3>=0 && pOp->p3<=p->nMem ); + REGISTER_TRACE(pOp->p3, pMem); applyAffinity(pMem, SQLITE_AFF_NUMERIC, encoding); if( (pMem->flags & MEM_Int)==0 ){ if( pOp->p2==0 ){ @@ -1943,50 +1939,51 @@ case OP_Ge: { /* same as TK_GE, no-push, jump */ break; } -/* Opcode: And * * * +/* Opcode: And P1 P2 P3 * * +** +** Take the logical AND of the values in registers P1 and P2 and +** write the result into register P3. ** -** Pop two values off the stack. Take the logical AND of the -** two values and push the resulting boolean value back onto the -** stack. +** If either P1 or P2 is 0 (false) then the result is 0 even if +** the other input is NULL. A NULL and true or two NULLs give +** a NULL output. */ -/* Opcode: Or * * * +/* Opcode: Or P1 P2 P3 * * ** -** Pop two values off the stack. Take the logical OR of the -** two values and push the resulting boolean value back onto the -** stack. +** Take the logical OR of the values in register P1 and P2 and +** store the answer in register P3. +** +** If either P1 or P2 is nonzero (true) then the result is 1 (true) +** even if the other input is NULL. A NULL and false or two NULLs +** give a NULL output. */ -case OP_And: /* same as TK_AND, no-push */ -case OP_Or: { /* same as TK_OR, no-push */ - Mem *pNos = &pTos[-1]; - int v1, v2; /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */ +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 */ - assert( pNos>=p->aStack ); - if( pTos->flags & MEM_Null ){ + if( pIn1->flags & MEM_Null ){ v1 = 2; }else{ - sqlite3VdbeMemIntegerify(pTos); - v1 = pTos->u.i==0; + v1 = sqlite3VdbeIntValue(pIn1)!=0; } - if( pNos->flags & MEM_Null ){ + if( pIn2->flags & MEM_Null ){ v2 = 2; }else{ - sqlite3VdbeMemIntegerify(pNos); - v2 = pNos->u.i==0; + v2 = sqlite3VdbeIntValue(pIn2)!=0; } if( pOp->opcode==OP_And ){ - static const unsigned char and_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; + static const unsigned char and_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; v1 = and_logic[v1*3+v2]; }else{ - static const unsigned char or_logic[] = { 0, 0, 0, 0, 1, 2, 0, 2, 2 }; + static const unsigned char or_logic[] = { 0, 1, 2, 1, 1, 1, 2, 1, 2 }; v1 = or_logic[v1*3+v2]; } - popStack(&pTos, 2); - pTos++; + Release(pOut); if( v1==2 ){ - pTos->flags = MEM_Null; + pOut->flags = MEM_Null; }else{ - pTos->u.i = v1==0; - pTos->flags = MEM_Int; + pOut->u.i = v1; + pOut->flags = MEM_Int; } break; } @@ -2425,6 +2422,7 @@ case OP_Column: { rc = sqlite3VdbeMemMakeWriteable(pDest); op_column_out: + REGISTER_TRACE(pOp->p3, pDest); break; } @@ -3504,6 +3502,7 @@ case OP_NotExists: { /* no-push, jump */ if( pOp->p3 ){ assert( pOp->p3<=p->nMem ); pKey = &p->aMem[pOp->p3]; + REGISTER_TRACE(pOp->p3, pKey); }else{ pKey = pTos; assert( pTos>=p->aStack ); @@ -3658,6 +3657,7 @@ case OP_NewRowid: { /* out2-prerelease */ 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); sqlite3VdbeMemIntegerify(pMem); assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ @@ -3739,6 +3739,8 @@ case OP_Insert: { /* no-push */ Cursor *pC; assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); + REGISTER_TRACE(pOp->p2, pData); + REGISTER_TRACE(pOp->p3, pKey); if( ((pC = p->apCsr[i])->pCursor!=0 || pC->pseudoTable) ){ i64 iKey; /* The integer ROWID or key for the record to be inserted */ @@ -3962,6 +3964,7 @@ case OP_RowData: { pOut->flags = MEM_Null; } pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ + REGISTER_TRACE(pOp->p3, pOut); break; } @@ -4646,6 +4649,7 @@ case OP_IntegrityCk: { case OP_FifoWrite: { /* no-push */ Mem *pReg = &p->aMem[pOp->p1]; assert( pOp->p1>0 && pOp->p1<=p->nMem ); + REGISTER_TRACE(pOp->p1, pReg); sqlite3VdbeMemIntegerify(pReg); if( sqlite3VdbeFifoPush(&p->sFifo, pReg->u.i)==SQLITE_NOMEM ){ goto no_mem; @@ -4671,6 +4675,7 @@ case OP_FifoRead: { /* jump */ Mem *pOut = &p->aMem[pOp->p1]; assert( pOp->p1>0 && pOp->p1<=p->nMem ); sqlite3VdbeMemSetInt64(pOut, v); + REGISTER_TRACE(pOp->p1, pOut); } break; } @@ -5084,6 +5089,8 @@ case OP_VFilter: { /* no-push, jump */ Mem *pArgc = &pQuery[1]; Cursor *pCur = p->apCsr[pOp->p1]; + + REGISTER_TRACE(pOp->p3, pQuery); assert( pCur->pVtabCursor ); pModule = pCur->pVtabCursor->pVtab->pModule; @@ -5184,6 +5191,7 @@ case OP_VColumn: { if( pOp->p3>0 ){ assert( pOp->p3<=p->nMem ); pDest = &p->aMem[pOp->p3]; + REGISTER_TRACE(pOp->p3, pDest); }else{ pDest = ++pTos; pDest->flags = 0; @@ -5256,6 +5264,7 @@ case OP_VRename: { /* no-push */ sqlite3_vtab *pVtab = pOp->p4.pVtab; Mem *pName = &p->aMem[pOp->p1]; assert( pVtab->pModule->xRename ); + REGISTER_TRACE(pOp->p1, pName); Stringify(pName, encoding); @@ -5391,27 +5400,22 @@ default: { #ifdef SQLITE_DEBUG /* Code for tracing the vdbe stack. */ - if( p->trace && pTos>=p->aStack ){ - int i; - fprintf(p->trace, "Stack:"); - for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){ - if( pTos[i].flags & MEM_Null ){ - fprintf(p->trace, " NULL"); - }else if( (pTos[i].flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ - fprintf(p->trace, " si:%lld", pTos[i].u.i); - }else if( pTos[i].flags & MEM_Int ){ - fprintf(p->trace, " i:%lld", pTos[i].u.i); - }else if( pTos[i].flags & MEM_Real ){ - fprintf(p->trace, " r:%g", pTos[i].r); - }else{ - char zBuf[200]; - sqlite3VdbeMemPrettyPrint(&pTos[i], zBuf); - fprintf(p->trace, " "); - fprintf(p->trace, "%s", zBuf); + if( p->trace ){ + if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc); + if( (opProperty&(OPFLG_OUT2_PRERELEASE|OPFLG_OUT2))!=0 && pOp->p2>0 ){ + registerTrace(p->trace, pOp->p2, pOut); + } + if( (opProperty&OPFLG_OUT3)!=0 && pOp->p3>0 ){ + registerTrace(p->trace, pOp->p3, pOut); + } + if( pTos>=p->aStack ){ + int i; + fprintf(p->trace, "Stack:"); + for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){ + memTracePrint(p->trace, &pTos[i]); } + fprintf(p->trace,"\n"); } - if( rc!=0 ) fprintf(p->trace," rc=%d",rc); - fprintf(p->trace,"\n"); } #endif /* SQLITE_DEBUG */ #endif /* NDEBUG */