]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Registerify binary operators. Add register tracing to debugging output. (CVS 4686)
authordrh <drh@noemail.net>
Sat, 5 Jan 2008 16:29:28 +0000 (16:29 +0000)
committerdrh <drh@noemail.net>
Sat, 5 Jan 2008 16:29:28 +0000 (16:29 +0000)
FossilOrigin-Name: 66396d2f0289e36b5fc0af5078c08d1b17f342ae

manifest
manifest.uuid
mkopcodeh.awk
src/analyze.c
src/expr.c
src/pragma.c
src/vdbe.c

index 221210f5fedb4ddb1fd5e782ab82da2f2a4549b1..88780f56b9aab9de318a39d766c15201c9f153cf 100644 (file)
--- 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
index 36ab26efff704d94aae922ddb850823f99998aa5..6f2823bcce3003ee3381a9dc9fe3bb0ade4e1f51 100644 (file)
@@ -1 +1 @@
-6c78d2a49a3e6ee8bc31f16488a430cba9eda59d
\ No newline at end of file
+66396d2f0289e36b5fc0af5078c08d1b17f342ae
\ No newline at end of file
index de04fab6117f608942ab7c4b2a9907394d5ae5ea..b40b4fdba92a1446f78f0146689880ddf79c3aa1 100644 (file)
@@ -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 "}"
index 54d985510dd4401c75930d68ee8926a264dd33cc..9b5494a2d5311e65515fbea42cd80365c86156ad 100644 (file)
@@ -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; i<nCol; i++){
       sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, i);
       sqlite3VdbeAddOp1(v, OP_SCopy, iMem+nCol+i+1);
-      sqlite3VdbeAddOp1(v, OP_Ne, 0x100);
+      sqlite3VdbeAddOp1(v, OP_Ne, 0x100);  /* FIX ME: use collating sequence */
     }
     sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop);
     for(i=0; i<nCol; i++){
@@ -195,20 +195,14 @@ static void analyzeOneTable(
     sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 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<nCol; i++){
-      sqlite3VdbeAddOp1(v, OP_SCopy, iMem);
-      sqlite3VdbeAddOp1(v, OP_SCopy, iMem+i+1);
-      sqlite3VdbeAddOp0(v, OP_Add);
+      sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, " ", 0);
+      sqlite3VdbeAddOp0(v, OP_Concat);
+      sqlite3VdbeAddOp2(v, OP_Add, iMem, iMem+i+1);
       sqlite3VdbeAddOp2(v, OP_AddImm, 0, -1);
-      sqlite3VdbeAddOp1(v, OP_SCopy, iMem+i+1);
-      sqlite3VdbeAddOp0(v, OP_Divide);
+      sqlite3VdbeAddOp2(v, OP_Divide, iMem+i+1, 0);
       sqlite3VdbeAddOp0(v, OP_ToInt);
-      if( i==nCol-1 ){
-        sqlite3VdbeAddOp1(v, OP_Concat, nCol*2-1);
-      }else{
-        sqlite3VdbeAddOp1(v, OP_Copy, -1);
-      }
+      sqlite3VdbeAddOp0(v, OP_Concat);
     }
     sqlite3VdbeAddOp4(v, OP_MakeRecord, 3, 0, 0, "aaa", 0);
     sqlite3CodeInsert(pParse, iStatCur, OPFLAG_APPEND);
index 6fe25e517deab5bad0d7214397b2f1985cf3c4d5..47129793278721ff424effec1a378381101eb2c0 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.333 2008/01/05 06:51:30 drh Exp $
+** $Id: expr.c,v 1.334 2008/01/05 16:29:28 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -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 ){
index ec4a0f80f593d07131adac39fc2219f41fc5b3f5..50e3f9c8ff96a48c2f328531211c5b55a8b99c87 100644 (file)
@@ -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 <ctype.h>
@@ -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);
index ae8245612fb9109c84e7e80d8081d749dd66ea91..711653432a8a92c2dc487b0ca17e133af97c353f 100644 (file)
@@ -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 <ctype.h>
@@ -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; i<nField; i++, pTerm++){
-    assert( pOp->p2==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; i<nField; i++, pTerm++){
-      int n = pTerm->n;
-      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 && i<p->nCursor );
   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 */