Index: mkopcodeh.awk ================================================================== --- mkopcodeh.awk +++ mkopcodeh.awk @@ -128,35 +128,37 @@ # for(i=0; i<=max; i++) bv[i] = 0; 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; if( in1[name] ) a3 = 8; if( in2[name] ) a4 = 16; 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 "}" } Index: src/analyze.c ================================================================== --- src/analyze.c +++ src/analyze.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** 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" /* @@ -157,11 +157,11 @@ topOfLoop = sqlite3VdbeCurrentAddr(v); sqlite3VdbeAddOp2(v, OP_AddImm, iMem, 1); 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 /* @@ -2084,10 +2084,11 @@ case TK_BITOR: case TK_SLASH: 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 ); assert( TK_MINUS==OP_Subtract ); assert( TK_REM==OP_Remainder ); @@ -2095,14 +2096,17 @@ assert( TK_BITOR==OP_BitOr ); assert( TK_SLASH==OP_Divide ); 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: { Expr *pLeft = pExpr->pLeft; assert( pLeft ); @@ -2347,12 +2351,16 @@ stackChng = 0; break; } #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 ){ pParse->ckOffset += stackChng; assert( pParse->ckOffset ); Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** 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 /* Ignore this whole file if pragmas are disabled @@ -885,11 +885,11 @@ addr = sqlite3VdbeAddOp2(v, OP_IsNull, -1, 0); sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, 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); /* Make sure all the indices are constructed correctly. */ @@ -912,11 +912,13 @@ { OP_AddImm, 1, -1, 0}, { OP_String8, 0, 0, 0}, /* 1 */ { 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); jmp2 = sqlite3VdbeAddOp2(v, OP_Found, j+2, 0); addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -41,11 +41,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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 #include "vdbeInt.h" @@ -176,11 +176,11 @@ ** Properties of opcodes. The OPFLG_INITIALIZER macro is ** created by mkopcodeh.awk during compilation. Data is obtained ** from the comments following the "case OP_xxxx:" statements in ** this file. */ -static unsigned char opcodeProperty[] = OPFLG_INITIALIZER; +static unsigned short opcodeProperty[] = OPFLG_INITIALIZER; /* ** Return true if an opcode has any of the OPFLG_xxx properties ** specified by mask. */ @@ -394,10 +394,43 @@ zBuf[k++] = 0; } } #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 /* ** The following routine only works on pentium-class processors. ** It uses the RDTSC opcode to read the cycle count value out of the @@ -465,11 +498,11 @@ Op *pOp; /* Current operation */ int rc = SQLITE_OK; /* Value to return */ 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; #ifdef VDBE_PROFILE unsigned long long start; /* CPU clock count at start of opcode */ @@ -630,46 +663,57 @@ pIn1 = pTos; nPop = 1; }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 ); if( pOp->p2==0 ){ pIn2 = &pTos[-nPop]; nPop++; }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]; } } }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]; } } @@ -1045,10 +1089,11 @@ pIn1 = &pTos[pOp->p1]; assert( pIn1>=p->aStack ); }else{ assert( pOp->p1<=p->nMem ); pIn1 = &p->aMem[pOp->p1]; + REGISTER_TRACE(pOp->p1, pIn1); } assert( pOp->p2>=0 ); if( pOp->p2==0 ){ pOut = ++pTos; pOut->flags = MEM_Null; @@ -1063,10 +1108,11 @@ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); if( pOp->opcode==OP_Copy ){ Deephemeralize(pOut); } } + REGISTER_TRACE(pOp->p2, pOut); break; } /* Opcode: Pull P1 * * ** @@ -1215,83 +1261,47 @@ p->pTos = pTos; rc = SQLITE_ROW; 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. -** -** When P1==1, this routine makes a copy of the top stack element -** into memory obtained from sqlite3_malloc(). -*/ -case OP_Concat: { /* same as TK_CONCAT */ +/* Opcode: Concat P1 P2 P3 * * +** +** 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, 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; } /* Opcode: Add * * * ** @@ -1337,28 +1347,24 @@ ** and push the remainder after division onto the stack. If either element ** is a string then it is converted to a double using the atof() ** 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; case OP_Multiply: b *= a; break; case OP_Divide: { @@ -1379,19 +1385,17 @@ if( a==-1 ) a = 1; b %= a; 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; case OP_Multiply: b *= a; break; case OP_Divide: { @@ -1409,26 +1413,22 @@ } } 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; } /* Opcode: CollSeq * * P4 ** @@ -1567,38 +1567,33 @@ ** Pop the top two elements from the stack. Convert both elements ** to integers. Push back onto the stack the second element shifted ** 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; case OP_ShiftLeft: a <<= b; break; 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; } /* Opcode: AddImm P1 P2 * * * ** @@ -1662,10 +1657,11 @@ */ 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 ){ rc = SQLITE_MISMATCH; goto abort_due_to_error; @@ -1941,54 +1937,55 @@ pTos->u.i = res; } break; } -/* Opcode: And * * * -** -** Pop two values off the stack. Take the logical AND of the -** two values and push the resulting boolean value back onto the -** stack. -*/ -/* Opcode: Or * * * -** -** Pop two values off the stack. Take the logical OR of the -** two values and push the resulting boolean value back onto the -** stack. -*/ -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 */ - - assert( pNos>=p->aStack ); - if( pTos->flags & MEM_Null ){ +/* Opcode: And P1 P2 P3 * * +** +** Take the logical AND of the values in registers P1 and P2 and +** write the result into register P3. +** +** 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 P1 P2 P3 * * +** +** 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, in1, in2, out3 */ +case OP_Or: { /* same as TK_OR, in1, in2, out3 */ + int v1, v2; /* 0==FALSE, 1==TRUE, 2==UNKNOWN or 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; } /* Opcode: Negative * * * @@ -2423,10 +2420,11 @@ /* pDest->z might be pointing to sMem.zShort[]. Fix that so that we ** can abandon sMem */ rc = sqlite3VdbeMemMakeWriteable(pDest); op_column_out: + REGISTER_TRACE(pOp->p3, pDest); break; } /* Opcode: MakeRecord P1 P2 P4 ** @@ -3502,10 +3500,11 @@ BtCursor *pCrsr; Mem *pKey; 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 ); } assert( i>=0 && inCursor ); @@ -3656,10 +3655,11 @@ #ifndef SQLITE_OMIT_AUTOINCREMENT if( pOp->p3 ){ Mem *pMem; assert( pOp->p3>0 && pOp->p3<=p->nMem ); /* P3 is a valid memory cell */ pMem = &p->aMem[pOp->p3]; + REGISTER_TRACE(pOp->p3, pMem); sqlite3VdbeMemIntegerify(pMem); assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ if( pMem->u.i==MAX_ROWID || pC->useRandomRowid ){ rc = SQLITE_FULL; goto abort_due_to_error; @@ -3737,10 +3737,12 @@ int i = pOp->p1; 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 */ assert( pKey->flags & MEM_Int ); assert( pC->isTable ); @@ -3960,10 +3962,11 @@ pOut->flags = MEM_Blob|MEM_Ephem; }else{ pOut->flags = MEM_Null; } pOut->enc = SQLITE_UTF8; /* In case the blob is ever cast to text */ + REGISTER_TRACE(pOp->p3, pOut); break; } /* Opcode: Rowid P1 P2 * * * ** @@ -4644,10 +4647,11 @@ ** Write the integer from memory cell P1 into the Fifo. */ 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; } break; @@ -4669,10 +4673,11 @@ pc = pOp->p2 - 1; }else{ Mem *pOut = &p->aMem[pOp->p1]; assert( pOp->p1>0 && pOp->p1<=p->nMem ); sqlite3VdbeMemSetInt64(pOut, v); + REGISTER_TRACE(pOp->p1, pOut); } break; } #ifndef SQLITE_OMIT_TRIGGER @@ -5082,10 +5087,12 @@ const sqlite3_module *pModule; Mem *pQuery = &p->aMem[pOp->p3]; Mem *pArgc = &pQuery[1]; Cursor *pCur = p->apCsr[pOp->p1]; + + REGISTER_TRACE(pOp->p3, pQuery); assert( pCur->pVtabCursor ); pModule = pCur->pVtabCursor->pVtab->pModule; /* Grab the index number and argc parameters off the top of the stack. */ assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int ); @@ -5182,10 +5189,11 @@ */ sqlite3VdbeChangeEncoding(&sContext.s, encoding); 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; } sqlite3VdbeMemMove(pDest, &sContext.s); @@ -5254,10 +5262,11 @@ */ 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); if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; sqlite3VtabLock(pVtab); @@ -5389,31 +5398,26 @@ } assert( pc>=-1 && pcnOp ); #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( rc!=0 ) fprintf(p->trace," rc=%d",rc); - fprintf(p->trace,"\n"); + 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"); + } } #endif /* SQLITE_DEBUG */ #endif /* NDEBUG */ } /* The end of the for(;;) loop the loops through opcodes */