]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Registerification of the VDBE is complete. The operand stack has been
authordrh <drh@noemail.net>
Thu, 17 Jan 2008 16:22:13 +0000 (16:22 +0000)
committerdrh <drh@noemail.net>
Thu, 17 Jan 2008 16:22:13 +0000 (16:22 +0000)
removed from the code.  All instructions operate out of registers only. (CVS 4718)

FossilOrigin-Name: 706b41b70bd1e2030e6fa44358c38a26c5cf0985

20 files changed:
manifest
manifest.uuid
mkopcodeh.awk
src/alter.c
src/attach.c
src/build.c
src/delete.c
src/expr.c
src/insert.c
src/pragma.c
src/select.c
src/sqliteInt.h
src/trigger.c
src/update.c
src/vdbe.c
src/vdbeInt.h
src/vdbeaux.c
src/vtab.c
src/where.c
test/in3.test

index df9f4b9117839ae08463d7998b6ac7bde4074836..a599ffc1a0c0a087d1f789900cdfcea69de8541f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Registerification\sof\sthe\sWHERE\sclause\slogic.\s(CVS\s4717)
-D 2008-01-17T02:36:28
+C Registerification\sof\sthe\sVDBE\sis\scomplete.\s\sThe\soperand\sstack\shas\sbeen\nremoved\sfrom\sthe\scode.\s\sAll\sinstructions\soperate\sout\sof\sregisters\sonly.\s(CVS\s4718)
+D 2008-01-17T16:22:14
 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 754a156fc83d47933c985186fba7fc800f88d2e1
+F mkopcodeh.awk 926deb36f57c3b573cfa79db675fdcff2ea6c5db
 F mkso.sh 24bde4c09e6fe80f718db3c31c068f45e13a2f2c
 F publish.sh 1c0658c63d70f182a8f5e17cc28422f1b237f51d
 F publish_osx.sh eca87df1e3d43d128d97d3261fd48b3d6877996e
@@ -78,25 +78,25 @@ F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
 F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
 F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
 F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc
-F src/alter.c 5a54f58d9481ac14c4e58b702f3f8758dee84d04
+F src/alter.c 2a101cb062b82fa29db9b105a1078690aa0a3c11
 F src/analyze.c ac17da1f9c804aabf709a1afff12ed35fc215104
-F src/attach.c 71f5c886004a9740fc6e6033d4e1ce0517ab6574
+F src/attach.c f7a34eb0f0e01db5fbfd8acb12109f87aed8159d
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff
 F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef
 F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb
 F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76
-F src/build.c ea291f091434aa9cd9700ea1611f2601c3c6a118
+F src/build.c 27a3be10a7186515915ac73c40667dc55beacbac
 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
-F src/delete.c ca07deed95f6f79c64338147147f698811628dc9
+F src/delete.c 739ccbab8fa7478762bded5c9cc67f16a4d09dbe
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c 00ee6555e323cd772f85e48b353109865d1eb539
+F src/expr.c 217ba4f47ffc17b10c79b091d896535e28aaa033
 F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
 F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c 8a90ba2d934bef98562cee12b778a17446730594
+F src/insert.c ed16eaf9391929e29fdbfa589db09b7224b31905
 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
@@ -127,16 +127,16 @@ 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 0768de04ea4e97c8c79748110147c5bc6986c440
+F src/pragma.c 155315ee3e6a861a0060ba4d184dfffd08ebbc03
 F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
 F src/random.c 02ef38b469237482f1ea14a78b2087cfbaec48bd
-F src/select.c 841eba5f83fb81f267bb2633bbf1b0cb7cfda96f
+F src/select.c fb2d6653954478c0a7f4ca64b5c4a6f024212296
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 0691a3d52dc37cf6ac2f74838e5ff8ae1055ac9b
 F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
 F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h 89dc8eb7784948ef80966addc645721e20f9b772
+F src/sqliteInt.h 8389662011bc23851199750ea1e6dc1a72d26109
 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
@@ -163,21 +163,21 @@ F src/test_server.c a6ece6c835e7eae835054124e09e947e422b1ac5
 F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
 F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
-F src/trigger.c 5e869352a2f35890dc4711161bfe958fcec8f4d7
-F src/update.c a4da9976e06bf1cc676dc270e0e0dba8ae39729c
+F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3
+F src/update.c 2513c6120f9510ae782446a2b839931e994b75dd
 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
-F src/vdbe.c 9de1ce4ddf2906a63cef6bd11156d299edf31cd0
+F src/vdbe.c 94d3da762729118e8062abf7866b22b6e41e7a3b
 F src/vdbe.h a9166e1601f5b74c20516a74182773a20baee43e
-F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
+F src/vdbeInt.h 835e6f0337ce89d705ef9a162338788808adc4b7
 F src/vdbeapi.c cb8c427a3ab646490c83204a98e94eff03ee2e89
-F src/vdbeaux.c e5b401253f66f099c5d790dcbee43d614681eae5
+F src/vdbeaux.c 0d2a9730195d40f7d1156731bc69f240927255c5
 F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120
 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
 F src/vdbemem.c a86119b5ccc41ab8653e4746f83d591ff0ae892e
-F src/vtab.c 7f206d148f6e76f427f008f589610c72a4b9336c
-F src/where.c 75908cb6dbcc7f2f21e42d65b68b1a24e6b5f679
+F src/vtab.c 9924e37cf7f5c527aeabb5da025874af505fb91d
+F src/where.c 0cc6052f73aef0d2ce59505d7ae06d6fbf696025
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/all.test ee350b9ab15b175fc0a8fb51bf2141ed3a3b9cba
@@ -323,7 +323,7 @@ F test/hook.test 3870abead2ee75d2c03585c916256ca8b5584679
 F test/icu.test e6bfae7f625c88fd14df6f540fe835bdfc1e4329
 F test/in.test 763a29007a4850d611ac4441bfa488fb9969ad30
 F test/in2.test b1f447f4f0f67e9f83ff931e7e2e30873f9ea055
-F test/in3.test e335959db24d71d6cfdff9553c90ce2b56fb978c
+F test/in3.test 2f829007cc8d25d17b859f7fe882ef2bd2e2eb49
 F test/incrblob.test 854c23b7ff8dd3822f675936b22c094655b3c739
 F test/incrblob_err.test 5273097dc7c97f9b7008423a6ffd5c80d21923cb
 F test/incrvacuum.test 1ed44535e89a0fa10c48c1aa0a3d48ee72bcc733
@@ -606,7 +606,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P b3a141b2b0c09bf3c7704deeade290d71b7c9b77
-R 9b81ffae960f644182cd49ff81018f5f
+P 5581160f43c60825d03de58e67aa66904d9d8964
+R 9b66d11764748ee0bf0a1a49c0663779
 U drh
-Z e206730fa35a583eeb4dac70ee5ed4f0
+Z a08c417a1e9cffb9cc564c4f53d0978f
index e5c7aa56e7279d73c0de40383f4f2a9136745352..c19098bb27f253a249cbdb2f575af97e1097feea 100644 (file)
@@ -1 +1 @@
-5581160f43c60825d03de58e67aa66904d9d8964
\ No newline at end of file
+706b41b70bd1e2030e6fa44358c38a26c5cf0985
\ No newline at end of file
index 2b57a41622d6962a51ebde6867a93d57c5582d19..538bccc0cc2d4f5b6f8a99ec74fba548f3c8f361 100644 (file)
@@ -51,7 +51,6 @@
   sub("\r","",name)
   op[name] = -1
   jump[name] = 0
-  nopush[name] = 0
   out2_prerelease[name] = 0
   in1[name] = 0
   in2[name] = 0
@@ -68,9 +67,7 @@
     }
     x = $i
     sub(",","",x)
-    if(x=="no-push"){
-      nopush[name] = 1
-    }else if(x=="jump"){
+    if(x=="jump"){
       jump[name] = 1
     }else if(x=="out2-prerelease"){
       out2_prerelease[name] = 1
@@ -130,16 +127,16 @@ 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
+    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+a8+a9+a10+a11+a12+a13+a14+a15;
+    if( out2_prerelease[name] ) a1 = 2;
+    if( in1[name] ) a2 = 4;
+    if( in2[name] ) a3 = 8;
+    if( in3[name] ) a4 = 16;
+    if( out2[name] ) a5 = 32;
+    if( out3[name] ) a6 = 64;
+    # bv[x] = a0+a1+a2+a3+a4+a5+a6+a7+a8+a9+a10+a11+a12+a13+a14+a15;
+    bv[x] = a0+a1+a2+a3+a4+a5+a6;
   }
   print "\n"
   print "/* Properties such as \"out2\" or \"jump\" that are specified in"
@@ -147,17 +144,16 @@ END {
   print "** are encoded into bitvectors as follows:"
   print "*/"
   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_OUT2_PRERELEASE 0x0002  /* out2-prerelease: */"
+  print "#define OPFLG_IN1             0x0004  /* in1:   P1 is an input */"
+  print "#define OPFLG_IN2             0x0008  /* in2:   P2 is an input */"
+  print "#define OPFLG_IN3             0x0010  /* in3:   P3 is an input */"
+  print "#define OPFLG_OUT2            0x0020  /* out2:  P2 is an output */"
+  print "#define OPFLG_OUT3            0x0040  /* out3:  P3 is an output */"
   print "#define OPFLG_INITIALIZER {\\"
   for(i=0; i<=max; i++){
     if( i%8==0 ) printf("/* %3d */",i)
-    printf " 0x%04x,", bv[i]
+    printf " 0x%02x,", bv[i]
     if( i%8==7 ) printf("\\\n");
   }
   print "}"
index 3f87ce642f20c200f6fae670f5c5214b362de128..c182c024bfca69f66bccb8baab4bd3b62c394902 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that used to generate VDBE code
 ** that implements the ALTER TABLE command.
 **
-** $Id: alter.c,v 1.39 2008/01/04 22:01:03 drh Exp $
+** $Id: alter.c,v 1.40 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -353,7 +353,7 @@ void sqlite3AlterRenameTable(
     goto exit_rename_table;
   }
   sqlite3BeginWriteOperation(pParse, isVirtualRename, iDb);
-  sqlite3ChangeCookie(db, v, iDb);
+  sqlite3ChangeCookie(pParse, iDb);
 
   /* If this is a virtual table, invoke the xRename() function if
   ** one is defined. The xRename() callback will modify the names
@@ -621,7 +621,7 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
   sqlite3BeginWriteOperation(pParse, 0, iDb);
   v = sqlite3GetVdbe(pParse);
   if( !v ) goto exit_begin_add_column;
-  sqlite3ChangeCookie(db, v, iDb);
+  sqlite3ChangeCookie(pParse, iDb);
 
 exit_begin_add_column:
   sqlite3SrcListDelete(pSrc);
index 20eb93bc6e61114062551c13f06588bf73bdca8e..af2312c8a1acf1de83da49773d0cbdcd0ca350e6 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the ATTACH and DETACH commands.
 **
-** $Id: attach.c,v 1.68 2008/01/12 19:03:49 drh Exp $
+** $Id: attach.c,v 1.69 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -327,7 +327,7 @@ static void codeAttach(
   }
 
   v = sqlite3GetVdbe(pParse);
-  regArgs = sqlite3GetTempRange(pParse, nFunc);
+  regArgs = sqlite3GetTempRange(pParse, 3);
   sqlite3ExprCode(pParse, pFilename, regArgs);
   sqlite3ExprCode(pParse, pDbname, regArgs+1);
   sqlite3ExprCode(pParse, pKey, regArgs+2);
index 91d94f04efe243c2802fc74d2c2d504b994548fa..02e1ae4036871cc32999c66891ea40969f6bef2d 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.466 2008/01/17 02:36:28 drh Exp $
+** $Id: build.c,v 1.467 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1277,9 +1277,13 @@ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName){
 ** and the probability of hitting the same cookie value is only
 ** 1 chance in 2^32.  So we're safe enough.
 */
-void sqlite3ChangeCookie(sqlite3 *db, Vdbe *v, int iDb){
-  sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, 0);
-  sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 0);
+void sqlite3ChangeCookie(Parse *pParse, int iDb){
+  int r1 = sqlite3GetTempReg(pParse);
+  sqlite3 *db = pParse->db;
+  Vdbe *v = pParse->pVdbe;
+  sqlite3VdbeAddOp2(v, OP_Integer, db->aDb[iDb].pSchema->schema_cookie+1, r1);
+  sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 0, r1);
+  sqlite3ReleaseTempReg(pParse, r1);
 }
 
 /*
@@ -1544,7 +1548,7 @@ void sqlite3EndTable(
       pParse->regRowid
     );
     sqlite3_free(zStmt);
-    sqlite3ChangeCookie(db, v, iDb);
+    sqlite3ChangeCookie(pParse, iDb);
 
 #ifndef SQLITE_OMIT_AUTOINCREMENT
     /* Check to see if we need to create an sqlite_sequence table for
@@ -2066,7 +2070,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
       sqlite3VdbeAddOp4(v, OP_VDestroy, iDb, 0, 0, pTab->zName, 0);
     }
     sqlite3VdbeAddOp4(v, OP_DropTable, iDb, 0, 0, pTab->zName, 0);
-    sqlite3ChangeCookie(db, v, iDb);
+    sqlite3ChangeCookie(pParse, iDb);
   }
   sqliteViewResetAll(db, iDb);
 
@@ -2688,7 +2692,7 @@ void sqlite3CreateIndex(
     */
     if( pTblName ){
       sqlite3RefillIndex(pParse, pIndex, iMem);
-      sqlite3ChangeCookie(db, v, iDb);
+      sqlite3ChangeCookie(pParse, iDb);
       sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0,
          sqlite3MPrintf(db, "name='%q'", pIndex->zName), P4_DYNAMIC);
       sqlite3VdbeAddOp1(v, OP_Expire, 0);
@@ -2840,7 +2844,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
        db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
        pIndex->zName
     );
-    sqlite3ChangeCookie(db, v, iDb);
+    sqlite3ChangeCookie(pParse, iDb);
     destroyRootPage(pParse, pIndex->tnum, iDb);
     sqlite3VdbeAddOp4(v, OP_DropIndex, iDb, 0, 0, pIndex->zName, 0);
   }
index ae2ecf9115993b013a47cc1113334b1438a4ab94..9fe4ae8b27057c1edc96d072c1072926f4ceb7b7 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** in order to generate code for DELETE FROM statements.
 **
-** $Id: delete.c,v 1.158 2008/01/17 02:36:28 drh Exp $
+** $Id: delete.c,v 1.159 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -317,7 +317,6 @@ void sqlite3DeleteFrom(
       sqlite3VdbeResolveLabel(v, addr);
     }
     addr = sqlite3VdbeAddOp2(v, OP_FifoRead, iRowid, end);
-    sqlite3VdbeAddOp1(v, OP_StackDepth, -1);
 
     if( triggers_exist ){
       int iData = ++pParse->nMem;   /* For storing row data of OLD table */
@@ -458,12 +457,15 @@ void sqlite3GenerateRowIndexDelete(
 ){
   int i;
   Index *pIdx;
+  int r1;
 
+  r1 = sqlite3GetTempReg(pParse);
   for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
     if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
-    sqlite3GenerateIndexKey(pParse, pIdx, iCur, 0);
-    sqlite3VdbeAddOp2(pParse->pVdbe, OP_IdxDelete, iCur+i, 0);
+    sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1);
+    sqlite3VdbeAddOp2(pParse->pVdbe, OP_IdxDelete, iCur+i, r1);
   }
+  sqlite3ReleaseTempReg(pParse, r1);
 }
 
 /*
index 559939826cdd964a9008f48039c66f52f64b427a..6693db4614d9605914d37f0dffd83fa5cb6aa466 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.346 2008/01/17 02:36:28 drh Exp $
+** $Id: expr.c,v 1.347 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1848,7 +1848,7 @@ static char *dup8bytes(Vdbe *v, const char *in){
 
 /*
 ** Generate an instruction that will put the floating point
-** value described by z[0..n-1] on the stack.
+** value described by z[0..n-1] into register iMem.
 **
 ** The z[] string will probably not be zero-terminated.  But the 
 ** z[n] character is guaranteed to be something that does not look
@@ -1870,7 +1870,7 @@ static void codeReal(Vdbe *v, const char *z, int n, int negateFlag, int iMem){
 
 /*
 ** Generate an instruction that will put the integer describe by
-** text z[0..n-1] on the stack.
+** text z[0..n-1] into register iMem.
 **
 ** The z[] string will probably not be zero-terminated.  But the 
 ** z[n] character is guaranteed to be something that does not look
@@ -1900,8 +1900,8 @@ static void codeInteger(Vdbe *v, const char *z, int n, int negFlag, int iMem){
 
 /*
 ** Generate code that will extract the iColumn-th column from
-** table pTab and store the column value in register iMem, or on
-** the stack if iMem==0.  There is an open cursor to pTab in 
+** table pTab and store the column value in register iReg.
+** There is an open cursor to pTab in 
 ** iTable.  If iColumn<0 then code is generated that extracts the rowid.
 */
 void sqlite3ExprCodeGetColumn(
@@ -1948,7 +1948,7 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
   int r1, r2, r3;           /* Various register numbers */
 
   assert( v!=0 || pParse->db->mallocFailed );
-  assert( target>=0 );
+  assert( target>0 && target<=pParse->nMem );
   if( v==0 ) return 0;
 
   if( pExpr==0 ){
@@ -2417,11 +2417,13 @@ int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
 ** in register target.
 */
 int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
-  int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
+  int inReg;
+
+  assert( target>0 && target<=pParse->nMem );
+  inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
   assert( pParse->pVdbe || pParse->db->mallocFailed );
   if( inReg!=target && pParse->pVdbe ){
-    sqlite3VdbeAddOp2(pParse->pVdbe, (inReg>0 ? OP_SCopy : OP_Move), 
-                      inReg, target);
+    sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
   }
   return target;
 }
@@ -2461,8 +2463,7 @@ int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
 
 /*
 ** Generate code that pushes the value of every element of the given
-** expression list onto the stack if target==0 or into a sequence of
-** registers beginning at target.
+** expression list into a sequence of registers beginning at target.
 **
 ** Return the number of elements evaluated.
 */
@@ -2472,19 +2473,16 @@ int sqlite3ExprCodeExprList(
   int target         /* Where to write results */
 ){
   struct ExprList_item *pItem;
-  int i, n, incr = 1;
+  int i, n;
   assert( pList!=0 || pParse->db->mallocFailed );
   if( pList==0 ){
     return 0;
   }
-  assert( target>=0 );
+  assert( target>0 );
   n = pList->nExpr;
-  if( target==0 ){
-    incr = 0;
-  }
   for(pItem=pList->a, i=n; i>0; i--, pItem++){
     sqlite3ExprCode(pParse, pItem->pExpr, target);
-    target += incr; 
+    target++;
   }
   return n;
 }
index 158dbae4d43ece7967c7d91f4b634883b04dbbc8..e62e623fbc7ef8c22dc920e4f9dc9039c63993fc 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.224 2008/01/17 02:36:28 drh Exp $
+** $Id: insert.c,v 1.225 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -667,7 +667,6 @@ void sqlite3Insert(
   }else if( pSelect ){
     sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop);
     sqlite3VdbeResolveLabel(v, iInsertBlock);
-    sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);
   }
 
   /* Allocate registers for holding the rowid of the new row,
index 11350aea9e79a4b120a8788d087f058b29b1b94d..7e32012e2c967d89ab4fe2b650b6bc4f985cf254 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.167 2008/01/17 02:36:28 drh Exp $
+** $Id: pragma.c,v 1.168 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -252,7 +252,7 @@ void sqlite3Pragma(
   Db *pDb;
   Vdbe *v = pParse->pVdbe = sqlite3VdbeCreate(db);
   if( v==0 ) return;
-  pParse->nMem = 1;
+  pParse->nMem = 2;
 
   /* Interpret the [database.] part of the pragma statement. iDb is the
   ** index of the database this pragma is being applied to in db.aDb[]. */
@@ -321,12 +321,12 @@ void sqlite3Pragma(
       int size = atoi(zRight);
       if( size<0 ) size = -size;
       sqlite3BeginWriteOperation(pParse, 0, iDb);
-      sqlite3VdbeAddOp1(v, OP_Integer, size);
-      sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 0, 2);
-      addr = sqlite3VdbeAddOp2(v, OP_IfPos, 0, 0);
-      sqlite3VdbeAddOp1(v, OP_Integer, -size);
+      sqlite3VdbeAddOp2(v, OP_Integer, size, 1);
+      sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 2, 2);
+      addr = sqlite3VdbeAddOp2(v, OP_IfPos, 2, 0);
+      sqlite3VdbeAddOp2(v, OP_Integer, -size, 1);
       sqlite3VdbeJumpHere(v, addr);
-      sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 2);
+      sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 2, 1);
       pDb->pSchema->cache_size = size;
       sqlite3BtreeSetCacheSize(pDb->pBt, pDb->pSchema->cache_size);
     }
@@ -1109,8 +1109,8 @@ void sqlite3Pragma(
       /* Write the specified cookie value */
       static const VdbeOpList setCookie[] = {
         { OP_Transaction,    0,  1,  0},    /* 0 */
-        { OP_Integer,        0,  0,  0},    /* 1 */
-        { OP_SetCookie,      0,  0,  0},    /* 2 */
+        { OP_Integer,        0,  1,  0},    /* 1 */
+        { OP_SetCookie,      0,  0,  1},    /* 2 */
       };
       int addr = sqlite3VdbeAddOpList(v, ArraySize(setCookie), setCookie);
       sqlite3VdbeChangeP1(v, addr, iDb);
index 3f181d4f7d6ad152e6b4a692438ce1f8987ccdf4..4c6b1f2b80f5010d3b1d1a1f13ff77aac69bf479 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.403 2008/01/17 02:36:28 drh Exp $
+** $Id: select.c,v 1.404 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -583,11 +583,14 @@ static int selectInnerLoop(
     */
 #ifndef SQLITE_OMIT_COMPOUND_SELECT
     case SRT_Union: {
-      sqlite3VdbeAddOp2(v, OP_MakeRecord, iMem, nColumn);
+      int r1;
+      r1 = sqlite3GetTempReg(pParse);
+      sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1);
       if( aff ){
         sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
       }
-      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
+      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+      sqlite3ReleaseTempReg(pParse, r1);
       break;
     }
 
@@ -596,11 +599,13 @@ static int selectInnerLoop(
     ** the temporary table iParm.
     */
     case SRT_Except: {
-      int addr;
-      addr = sqlite3VdbeAddOp2(v, OP_MakeRecord, iMem, nColumn);
+      int addr, r1;
+      r1 = sqlite3GetTempReg(pParse);
+      addr = sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, nColumn, r1);
       sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
-      sqlite3VdbeAddOp2(v, OP_NotFound, iParm, addr+3);
-      sqlite3VdbeAddOp2(v, OP_Delete, iParm, 0);
+      sqlite3VdbeAddOp3(v, OP_NotFound, iParm, addr+3, r1);
+      sqlite3VdbeAddOp1(v, OP_Delete, iParm);
+      sqlite3ReleaseTempReg(pParse, r1);
       break;
     }
 #endif
@@ -2067,6 +2072,7 @@ static int multiSelect(
       Expr *pLimit, *pOffset;
       int addr;
       SelectDest intersectdest;
+      int r1;
 
       /* INTERSECT is different from the others since it requires
       ** two temporary tables.  Hence it has its own case.  Begin
@@ -2127,8 +2133,10 @@ static int multiSelect(
       iCont = sqlite3VdbeMakeLabel(v);
       computeLimitRegisters(pParse, p, iBreak);
       sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak);
-      iStart = sqlite3VdbeAddOp1(v, OP_RowKey, tab1);
-      sqlite3VdbeAddOp2(v, OP_NotFound, tab2, iCont);
+      r1 = sqlite3GetTempReg(pParse);
+      iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1);
+      sqlite3VdbeAddOp3(v, OP_NotFound, tab2, iCont, r1);
+      sqlite3ReleaseTempReg(pParse, r1);
       rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
                              pOrderBy, -1, &dest, iCont, iBreak, 0);
       if( rc ){
index 12552e404f55e8345e80162b8564821929557a8b..7529318cf62454620c93d37ea18aa05a82915d1f 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.650 2008/01/17 02:36:28 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.651 2008/01/17 16:22:15 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1819,7 +1819,7 @@ void sqlite3RegisterDateTimeFunctions(sqlite3*);
 int sqlite3SafetyOn(sqlite3*);
 int sqlite3SafetyOff(sqlite3*);
 int sqlite3SafetyCheck(sqlite3*);
-void sqlite3ChangeCookie(sqlite3*, Vdbe*, int);
+void sqlite3ChangeCookie(Parse*, int);
 
 #ifndef SQLITE_OMIT_TRIGGER
   void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
index 09cbc437cea0fbe4ac51aa076aca27f4fa023a49..70cf6aba53184d1f9ee153a8ecf71764e8cd2e7d 100644 (file)
@@ -240,7 +240,7 @@ void sqlite3FinishTrigger(
        db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTrig->name,
        pTrig->table, z);
     sqlite3_free(z);
-    sqlite3ChangeCookie(db, v, iDb);
+    sqlite3ChangeCookie(pParse, iDb);
     sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
         db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC
     );
@@ -538,7 +538,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
     base = sqlite3VdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger);
     sqlite3VdbeChangeP4(v, base+1, pTrigger->name, 0);
     sqlite3VdbeChangeP4(v, base+4, "trigger", P4_STATIC);
-    sqlite3ChangeCookie(db, v, iDb);
+    sqlite3ChangeCookie(pParse, iDb);
     sqlite3VdbeAddOp2(v, OP_Close, 0, 0);
     sqlite3VdbeAddOp4(v, OP_DropTrigger, iDb, 0, 0, pTrigger->name, 0);
   }
index 8d39dbc7588ceacd8f278044c67231fadc4f4ece..b769d2f1f6983e3c1ac67a653160980f7c5779d1 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle UPDATE statements.
 **
-** $Id: update.c,v 1.168 2008/01/17 02:36:28 drh Exp $
+** $Id: update.c,v 1.169 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -401,7 +401,6 @@ void sqlite3Update(
 
   /* Top of the update loop */
   addr = sqlite3VdbeAddOp2(v, OP_FifoRead, regOldRowid, 0);
-  sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);
 
   if( triggers_exist ){
     int regRowid;
index 144aafc18b961637291b406455225a086e92e9c8..50394d6cb50097862088a1d8c876dd723cdf0e9e 100644 (file)
 ** the VDBE to do the work of the SQL statement.  VDBE programs are 
 ** similar in form to assembly language.  The program consists of
 ** a linear sequence of operations.  Each operation has an opcode 
-** and 3 operands.  Operands P1 and P2 are integers.  Operand P4 
-** is a null-terminated string.   The P2 operand must be non-negative.
-** Opcodes will typically ignore one or more operands.  Many opcodes
-** ignore all three operands.
+** and 5 operands.  Operands P1, P2, and P3 are integers.  Operand P4 
+** is a null-terminated string.  Operand P5 is an unsigned character.
+** Few opcodes use all 5 operands.
 **
-** Computation results are stored on a stack.  Each entry on the
-** stack is either an integer, a null-terminated string, a floating point
+** Computation results are stored on a set of registers numbered beginning
+** with 1 and going up to Vdbe.nMem.  Each register can store
+** either an integer, a null-terminated string, a floating point
 ** number, or the SQL "NULL" value.  An inplicit conversion from one
 ** type to the other occurs as necessary.
 ** 
@@ -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.697 2008/01/17 02:36:28 drh Exp $
+** $Id: vdbe.c,v 1.698 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -85,7 +85,7 @@ int sqlite3_sort_count = 0;
 
 /*
 ** The next global variable records the size of the largest MEM_Blob
-** or MEM_Str that has appeared on the VDBE stack.  The test procedures
+** or MEM_Str that has been used by a VDBE opcode.  The test procedures
 ** use this information to make sure that the zero-blob functionality
 ** is working correctly.   This variable has no function other than to
 ** help verify the correct operation of the library.
@@ -107,13 +107,13 @@ int sqlite3_max_blobsize = 0;
 #endif
 
 /*
-** Release the memory associated with the given stack level.  This
+** Release the memory associated with a register.  This
 ** leaves the Mem.flags field in an inconsistent state.
 */
 #define Release(P) if((P)->flags&MEM_Dyn){ sqlite3VdbeMemRelease(P); }
 
 /*
-** Convert the given stack entity into a string if it isn't one
+** Convert the given register into a string if it isn't one
 ** already. Return non-zero if a malloc() fails.
 */
 #define Stringify(P, enc) \
@@ -140,12 +140,12 @@ int sqlite3_max_blobsize = 0;
 /*
 ** An ephemeral string value (signified by the MEM_Ephem flag) contains
 ** a pointer to a dynamically allocated string where some other entity
-** is responsible for deallocating that string.  Because the stack entry
-** does not control the string, it might be deleted without the stack
-** entry knowing it.
+** is responsible for deallocating that string.  Because the register
+** does not control the string, it might be deleted without the register
+** knowing it.
 **
 ** This routine converts an ephemeral string into a dynamically allocated
-** string that the stack entry itself controls.  In other words, it
+** string that the register itself controls.  In other words, it
 ** converts an MEM_Ephem string into an MEM_Dyn string.
 */
 #define Deephemeralize(P) \
@@ -159,10 +159,10 @@ int sqlite3_max_blobsize = 0;
 #define ExpandBlob(P) (((P)->flags&MEM_Zero)?sqlite3VdbeMemExpandBlob(P):0)
 
 /*
-** Argument pMem points at a memory cell that will be passed to a
+** Argument pMem points at a regiser that will be passed to a
 ** user-defined function or returned to the user as the result of a query.
 ** The second argument, 'db_enc' is the text encoding used by the vdbe for
-** stack variables.  This routine sets the pMem->enc and pMem->type
+** register variables.  This routine sets the pMem->enc and pMem->type
 ** variables used by the sqlite3_value_*() routines.
 */
 #define storeTypeInfo(A,B) _storeTypeInfo(A)
@@ -190,7 +190,7 @@ static void _storeTypeInfo(Mem *pMem){
 ** from the comments following the "case OP_xxxx:" statements in
 ** this file.  
 */
-static unsigned short opcodeProperty[] = OPFLG_INITIALIZER;
+static unsigned char opcodeProperty[] = OPFLG_INITIALIZER;
 
 /*
 ** Return true if an opcode has any of the OPFLG_xxx properties
@@ -201,19 +201,6 @@ int sqlite3VdbeOpcodeHasProperty(int opcode, int mask){
   return (opcodeProperty[opcode]&mask)!=0;
 }
 
-/*
-** Pop the stack N times.
-*/
-static void popStack(Mem **ppTos, int N){
-  Mem *pTos = *ppTos;
-  while( N>0 ){
-    N--;
-    Release(pTos);
-    pTos--;
-  }
-  *ppTos = pTos;
-}
-
 /*
 ** Allocate cursor number iCur.  Return a pointer to it.  Return NULL
 ** if we run out of memory.
@@ -511,10 +498,8 @@ int sqlite3VdbeExec(
   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, *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 */
@@ -523,13 +508,9 @@ int sqlite3VdbeExec(
 #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
   int nProgressOps = 0;      /* Opcodes executed since progress callback. */
 #endif
-#ifndef NDEBUG
-  Mem *pStackLimit;
-#endif
 
   if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
   assert( db->magic==SQLITE_MAGIC_BUSY );
-  pTos = p->pTos;
   sqlite3BtreeMutexArrayEnter(&p->aMutex);
   if( p->rc==SQLITE_NOMEM ){
     /* This happens if a malloc() inside a call to sqlite3_column_text() or
@@ -539,10 +520,6 @@ int sqlite3VdbeExec(
   assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
   p->rc = SQLITE_OK;
   assert( p->explain==0 );
-  if( p->popStack ){
-    popStack(&pTos, p->popStack);
-    p->popStack = 0;
-  }
   p->pResultSet = 0;
   db->busyHandler.nBusy = 0;
   CHECK_FOR_INTERRUPT;
@@ -564,7 +541,6 @@ int sqlite3VdbeExec(
 #endif
   for(pc=p->pc; rc==SQLITE_OK; pc++){
     assert( pc>=0 && pc<p->nOp );
-    assert( pTos<=&p->aStack[pc] );
     if( db->mallocFailed ) goto no_mem;
 #ifdef VDBE_PROFILE
     origPc = pc;
@@ -624,34 +600,17 @@ int sqlite3VdbeExec(
     }
 #endif
 
-#ifndef NDEBUG
-    /* This is to check to make sure that the OPFLG_PUSH property
-    ** is set correctly on all opcodes.
-    */ 
-    pStackLimit = pTos;
-    if( sqlite3VdbeOpcodeHasProperty(pOp->opcode, OPFLG_PUSH) ){
-      pStackLimit++;
-    }
-    assert( pTos>=&p->aStack[-1] && pTos<=pStackLimit );
-#endif
-
     /* Do common setup processing for any opcode that is marked
     ** with the "out2-prerelease" tag.  Such opcodes have a single
-    ** output which is specified by the P2 parameter.  The output
-    ** is normally written into the P2-th register.  But if P2==0
-    ** then the output is pushed onto the stack.  The P2 operand
+    ** output which is specified by the P2 parameter.  The P2 register
     ** is initialized to a NULL.
     */
     opProperty = opcodeProperty[pOp->opcode];
     if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){
-      assert( pOp->p2>=0 );
-      if( pOp->p2==0 ){
-        pOut = ++pTos;
-      }else{
-        assert( pOp->p2<=p->nMem );
-        pOut = &p->aMem[pOp->p2];
-        sqlite3VdbeMemRelease(pOut);
-      }
+      assert( pOp->p2>0 );
+      assert( pOp->p2<=p->nMem );
+      pOut = &p->aMem[pOp->p2];
+      sqlite3VdbeMemRelease(pOut);
       pOut->flags = MEM_Null;
     }else
  
@@ -664,91 +623,44 @@ int sqlite3VdbeExec(
     **           in1 in3
     **           in1 out2
     **
-    ** Variables pIn1 and pIn2 are made to point to the first two
-    ** inputs and pOut points to the output.  Variable nPop holds the
-    ** number of times that the stack should be popped after the
-    ** the instruction.
+    ** Variables pIn1, pIn2, and pIn3 are made to point to appropriate
+    ** registers for inputs.  Variable pOut points to the output register.
     */
     if( (opProperty & OPFLG_IN1)!=0 ){
-      assert( pOp->p1>=0 );
-      if( pOp->p1==0 ){
-        pIn1 = pTos;
-        nPop = 1;
-      }else{
-        assert( pOp->p1<=p->nMem );
-        pIn1 = &p->aMem[pOp->p1];
-        REGISTER_TRACE(pOp->p1, pIn1);
-      }
+      assert( pOp->p1>0 );
+      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 ){
-            nPop--;
-            if( nPop<0 ){
-              assert( nPop==(-1) );
-              pTos++;
-              nPop = 0;
-            }
-            pOut = &pTos[-nPop];
-          }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 ){
-          pIn3 = &pTos[-nPop];
-          nPop++;
-        }else{
-          assert( pOp->p3<=p->nMem );
-          pIn3 = &p->aMem[pOp->p3];
-          REGISTER_TRACE(pOp->p3, pIn3);
-        }
-      }else if( (opProperty & OPFLG_OUT2)!=0 ){
-        assert( pOp->p2>=0 );
-        if( pOp->p2==0 ){
-          nPop--;
-          if( nPop<0 ){
-            assert( nPop==(-1) );
-            pTos++;
-            nPop = 0;
-          }
-          pOut = &pTos[-nPop];
-        }else{
-          assert( pOp->p2<=p->nMem );
-          pOut = &p->aMem[pOp->p2];
-        }
-      }
-    }else if( (opProperty & OPFLG_IN2)!=0 ){
-      assert( pOp->p2>=0 );
-      if( pOp->p2==0 ){
-        pIn2 = pTos;
-        nPop = 1;
-      }else{
+        assert( pOp->p2>0 );
         assert( pOp->p2<=p->nMem );
         pIn2 = &p->aMem[pOp->p2];
         REGISTER_TRACE(pOp->p2, pIn2);
-      }
-    }else if( (opProperty & OPFLG_IN3)!=0 ){
-      assert( pOp->p3>=0 );
-      if( pOp->p3==0 ){
-        pIn3 = pTos;
-        nPop = 1;
-      }else{
+        if( (opProperty & OPFLG_OUT3)!=0 ){
+          assert( pOp->p3>0 );
+          assert( pOp->p3<=p->nMem );
+          pOut = &p->aMem[pOp->p3];
+        }
+      }else if( (opProperty & OPFLG_IN3)!=0 ){
+        assert( pOp->p3>0 );
         assert( pOp->p3<=p->nMem );
         pIn3 = &p->aMem[pOp->p3];
         REGISTER_TRACE(pOp->p3, pIn3);
+      }else if( (opProperty & OPFLG_OUT2)!=0 ){
+        assert( pOp->p2>0 );
+        assert( pOp->p2<=p->nMem );
+        pOut = &p->aMem[pOp->p2];
       }
+    }else if( (opProperty & OPFLG_IN2)!=0 ){
+      assert( pOp->p2>0 );
+      assert( pOp->p2<=p->nMem );
+      pIn2 = &p->aMem[pOp->p2];
+      REGISTER_TRACE(pOp->p2, pIn2);
+    }else if( (opProperty & OPFLG_IN3)!=0 ){
+      assert( pOp->p3>0 );
+      assert( pOp->p3<=p->nMem );
+      pIn3 = &p->aMem[pOp->p3];
+      REGISTER_TRACE(pOp->p3, pIn3);
     }
 
     switch( pOp->opcode ){
@@ -771,10 +683,10 @@ int sqlite3VdbeExec(
 ** case statement is followed by a comment of the form "/# same as ... #/"
 ** that comment is used to determine the particular value of the opcode.
 **
-** If a comment on the same line as the "case OP_" construction contains
-** the word "no-push", then the opcode is guarenteed not to grow the 
-** vdbe stack when it is executed. See function opcode() in
-** vdbeaux.c for details.
+** Other keywords in the comment that follows each case are used to
+** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[].
+** Keywords include: in1, in2, in3, out2_prerelease, out2, out3.  See
+** the mkopcodeh.awk script for additional information.
 **
 ** Documentation about VDBE opcodes is generated by scanning this file
 ** for lines of that contain "Opcode:".  That line and all subsequent
@@ -788,20 +700,20 @@ int sqlite3VdbeExec(
 **
 *****************************************************************************/
 
-/* Opcode:  Goto * P2 *
+/* Opcode:  Goto * P2 * * *
 **
 ** An unconditional jump to address P2.
 ** The next instruction executed will be 
 ** the one at index P2 from the beginning of
 ** the program.
 */
-case OP_Goto: {             /* no-push, jump */
+case OP_Goto: {             /* jump */
   CHECK_FOR_INTERRUPT;
   pc = pOp->p2 - 1;
   break;
 }
 
-/* Opcode:  Gosub * P2 *
+/* Opcode:  Gosub * P2 * * *
 **
 ** Push the current address plus 1 onto the return address stack
 ** and then jump to address P2.
@@ -811,27 +723,27 @@ case OP_Goto: {             /* no-push, jump */
 ** the return address stack will fill up and processing will abort
 ** with a fatal error.
 */
-case OP_Gosub: {            /* no-push, jump */
+case OP_Gosub: {            /* jump */
   assert( p->returnDepth<sizeof(p->returnStack)/sizeof(p->returnStack[0]) );
   p->returnStack[p->returnDepth++] = pc+1;
   pc = pOp->p2 - 1;
   break;
 }
 
-/* Opcode:  Return * * *
+/* Opcode:  Return * * * * *
 **
 ** Jump immediately to the next instruction after the last unreturned
 ** OP_Gosub.  If an OP_Return has occurred for all OP_Gosubs, then
 ** processing aborts with a fatal error.
 */
-case OP_Return: {           /* no-push */
+case OP_Return: {
   assert( p->returnDepth>0 );
   p->returnDepth--;
   pc = p->returnStack[p->returnDepth] - 1;
   break;
 }
 
-/* Opcode:  Halt P1 P2 P4
+/* Opcode:  Halt P1 P2 * P4 *
 **
 ** Exit immediately.  All open cursors, Fifos, etc are closed
 ** automatically.
@@ -850,8 +762,7 @@ case OP_Return: {           /* no-push */
 ** every program.  So a jump past the last instruction of the program
 ** is the same as executing Halt.
 */
-case OP_Halt: {            /* no-push */
-  p->pTos = pTos;
+case OP_Halt: {
   p->rc = pOp->p1;
   p->pc = pc;
   p->errorAction = pOp->p2;
@@ -868,33 +779,9 @@ case OP_Halt: {            /* no-push */
   goto vdbe_return;
 }
 
-/* Opcode:  StackDepth P1 * *
-**
-** If P1 is less than zero, then store the current stack depth
-** in P1.  If P1 is zero or greater, verify that the current stack
-** depth is equal to P1 and throw an exception if it is not.
-**
-** This opcode is used for internal consistency checking.
-*/
-case OP_StackDepth: {       /* no-push */
-  int n = pTos - p->aStack + 1;
-  if( pOp->p1<0 ){
-    pOp->p1 = n;
-  }else if( pOp->p1!=n ){
-    p->pTos = pTos;
-    p->rc = rc = SQLITE_INTERNAL;
-    p->pc = pc;
-    p->errorAction = OE_Rollback;
-    sqlite3SetString(&p->zErrMsg, "internal error: VDBE stack leak", (char*)0);
-    goto vdbe_return;
-  }
-  break;
-}
-
 /* Opcode: Integer P1 P2 * * *
 **
-** The 32-bit integer value P1 is written into register P2, or 
-** pushed onto the stack if P2==0.
+** The 32-bit integer value P1 is written into register P2.
 */
 case OP_Integer: {         /* out2-prerelease */
   pOut->flags = MEM_Int;
@@ -905,7 +792,7 @@ case OP_Integer: {         /* out2-prerelease */
 /* Opcode: Int64 * P2 * P4 *
 **
 ** P4 is a pointer to a 64-bit integer value.
-** Write that value into register P2 or push onto the stack if P2 is 0.
+** Write that value into register P2.
 */
 case OP_Int64: {           /* out2-prerelease */
   assert( pOp->p4.pI64!=0 );
@@ -917,7 +804,7 @@ case OP_Int64: {           /* out2-prerelease */
 /* Opcode: Real * P2 * P4 *
 **
 ** P4 is a pointer to a 64-bit floating point value.
-** Write that value into register P2 or push onto the stack if P2 is 0.
+** Write that value into register P2.
 */
 case OP_Real: {            /* same as TK_FLOAT, out2-prerelease */
   pOut->flags = MEM_Real;
@@ -963,8 +850,7 @@ case OP_String8: {         /* same as TK_STRING, out2-prerelease */
   
 /* Opcode: String P1 P2 * P4 *
 **
-** The string value P4 of length P1 (bytes) is stored in register P2
-** or is pushed onto the stack if P2==0.
+** The string value P4 of length P1 (bytes) is stored in register P2.
 */
 case OP_String: {          /* out2-prerelease */
   assert( pOp->p4.z!=0 );
@@ -978,8 +864,7 @@ case OP_String: {          /* out2-prerelease */
 
 /* Opcode: Null * P2 * * *
 **
-** Write a NULL into register P2 or push a NULL onto the stack 
-** if P2==0.
+** Write a NULL into register P2.
 */
 case OP_Null: {           /* out2-prerelease */
   break;
@@ -990,7 +875,7 @@ case OP_Null: {           /* out2-prerelease */
 /* Opcode: HexBlob * P2 * P4 *
 **
 ** P4 is an UTF-8 SQL hex encoding of a blob. The blob is stored in
-** register P2 or pushed onto the stack if P2 is zero.
+** register P2.
 **
 ** The first time this instruction executes, in transforms itself into a
 ** 'Blob' opcode with a binary blob as P4.
@@ -1040,8 +925,7 @@ case OP_Blob: {                /* out2-prerelease */
 
 /* Opcode: Variable P1 P2 * * *
 **
-** The value of variable P1 is written into register P2 or pushed
-** onto the stack if P2 is zero.  A variable is
+** The value of variable P1 is written into register P2. A variable is
 ** an unknown in the original SQL string as handed to sqlite3_compile().
 ** Any occurance of the '?' character in the original SQL is considered
 ** a variable.  Variables in the SQL string are number from left to
@@ -1064,40 +948,20 @@ case OP_Variable: {           /* out2-prerelease */
 
 /* Opcode: Move P1 P2 * * *
 **
-** Move the value in P1 into P2.  If P1 is positive then read from the
-** P1-th register.  If P1 is zero or negative read from the stack.
-** When P1 is 0 read from the top the stack.  When P1 is -1 read from
-** the next entry down on the stack.  And so forth.
-**
-** If P2 is zero, push the new value onto the top of the stack.  
-** If P2 is positive, write into the P2-th register.
-**
-** If P1 is zero then the stack is popped once.  The stack is
-** unchanged for all other values of P1.  The P1 value contains
-** a NULL after this operation.
+** Move the value in register P1 over into register P2.  Register P1
+** is left holding a NULL.  It is an error for P1 and P2 to be the
+** same register.
 */
 /* Opcode: Copy P1 P2 * * *
 **
-** Make a copy of P1 into P2.  If P1 is positive then read from the
-** P1-th register.  If P1 is zero or negative read from the stack.
-** When P1 is 0 read from the top the stack.  When P1 is -1 read from
-** the next entry down on the stack.  And so forth.
-**
-** If P2 is zero, push the new value onto the top of the stack.  
-** If P2 is positive, write into the P2-th register.
+** Make a copy of register P1 into register P2.
 **
 ** This instruction makes a deep copy of the value.  A duplicate
 ** is made of any string or blob constant.  See also OP_SCopy.
 */
 /* Opcode: SCopy P1 P2 * * *
 **
-** Make a shallow copy of P1 into P2.  If P1 is positive then read from the
-** P1-th register.  If P1 is zero or negative read from the stack.
-** When P1 is 0 read from the top the stack.  When P1 is -1 read from
-** the next entry down on the stack.  And so forth.
-**
-** If P2 is zero, push the new value onto the top of the stack.  
-** If P2 is positive, write into the P2-th register.
+** Make a shallow copy of register P1 into register P2.
 **
 ** This instruction makes a shallow copy of the value.  If the value
 ** is a string or blob, then the copy is only a pointer to the
@@ -1110,26 +974,16 @@ case OP_Variable: {           /* out2-prerelease */
 case OP_Move:
 case OP_Copy:
 case OP_SCopy: {
-  if( pOp->p1<=0 ){
-    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;
-  }else{
-    assert( pOp->p2<=p->nMem );
-    pOut = &p->aMem[pOp->p2];
-  }
+  assert( pOp->p1>0 );
+  assert( pOp->p1<=p->nMem );
+  pIn1 = &p->aMem[pOp->p1];
+  REGISTER_TRACE(pOp->p1, pIn1);
+  assert( pOp->p2>0 );
+  assert( pOp->p2<=p->nMem );
+  pOut = &p->aMem[pOp->p2];
   assert( pOut!=pIn1 );
   if( pOp->opcode==OP_Move ){
     rc = sqlite3VdbeMemMove(pOut, pIn1);
-    if( pOp->p1==0 ) pTos--;
   }else{
     Release(pOut);
     sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
@@ -1141,33 +995,21 @@ case OP_SCopy: {
   break;
 }
 
-/* Opcode: ResultRow P1 P2 *
+/* Opcode: ResultRow P1 P2 * * *
 **
 ** The registers P1 throught P1+P2-1 contain a single row of
 ** results. This opcode causes the sqlite3_step() call to terminate
 ** with an SQLITE_ROW return code and it sets up the sqlite3_stmt
 ** structure to provide access to the top P1 values as the result
-** row.  When the sqlite3_step() function is run again, the top P1
-** values will be automatically popped from the stack before the next
-** instruction executes.
+** row.
 */
-case OP_ResultRow: {            /* no-push */
+case OP_ResultRow: {
   Mem *pMem;
   int i;
   assert( p->nResColumn==pOp->p2 );
   assert( pOp->p1>0 );
   assert( pOp->p1+pOp->p2<=p->nMem );
 
-  /* Data in the pager might be moved or changed out from under us
-  ** in between the return from this sqlite3_step() call and the
-  ** next call to sqlite3_step().  So deephermeralize everything on 
-  ** the stack.  Note that ephemeral data is never stored in memory 
-  ** cells so we do not have to worry about them.
-  */
-  for(pMem = p->aStack; pMem<=pTos; pMem++){
-    Deephemeralize(pMem);
-  }
-
   /* Invalidate all ephemeral cursor row caches */
   p->cacheCtr = (p->cacheCtr + 2)|1;
 
@@ -1184,9 +1026,7 @@ case OP_ResultRow: {            /* no-push */
   /* Return SQLITE_ROW
   */
   p->nCallback++;
-  p->popStack = 0;
   p->pc = pc + 1;
-  p->pTos = pTos;
   rc = SQLITE_ROW;
   goto vdbe_return;
 }
@@ -1249,13 +1089,13 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
 ** in P3.
 ** If either operand is NULL, the result is NULL.
 */
-/* Opcode: Divide * * *
+/* Opcode: Divide P1 P2 P3 * *
 **
 ** Divide the value in P1 by the value in P2 and store the result
 ** in P3.  If the value in P2 is zero, then the result is NULL.
 ** If either operand is NULL, the result is NULL.
 */
-/* Opcode: Remainder * * *
+/* Opcode: Remainder P1 P2 P3 * *
 **
 ** Compute the remainder after integer division of the value in
 ** register P1 by the value in register P2 and store the result in P3. 
@@ -1354,7 +1194,7 @@ divide_by_zero:
 ** to retrieve the collation sequence set by this opcode is not available
 ** publicly, only to user functions defined in func.c.
 */
-case OP_CollSeq: {             /* no-push */
+case OP_CollSeq: {
   assert( pOp->p4type==P4_COLLSEQ );
   break;
 }
@@ -1363,8 +1203,7 @@ case OP_CollSeq: {             /* no-push */
 **
 ** Invoke a user function (P4 is a pointer to a Function structure that
 ** defines the function) with P5 arguments taken from register P2 and
-** successors, or if P2==0 from the stack.  The result of the function
-** is stored in register P3 or on the stack if P3==0.
+** successors.  The result of the function is stored in register P3.
 **
 ** P1 is a 32-bit bitmask indicating whether or not each argument to the 
 ** function was determined to be constant at compile time. If the first
@@ -1385,11 +1224,8 @@ case OP_Function: {
   apVal = p->apArg;
   assert( apVal || n==0 );
 
-  if( pOp->p2==0 ){
-    pArg = &pTos[1-n];
-  }else{
-    pArg = &p->aMem[pOp->p2];
-  }
+  assert( n==0 || (pOp->p2>0 && pOp->p2+n<=p->nMem) );
+  pArg = &p->aMem[pOp->p2];
   for(i=0; i<n; i++, pArg++){
     apVal[i] = pArg;
     storeTypeInfo(pArg, encoding);
@@ -1432,9 +1268,6 @@ case OP_Function: {
     sqlite3VdbeMemRelease(&ctx.s);
     goto no_mem;
   }
-  if( pOp->p2==0 ){
-    popStack(&pTos, n);
-  }
 
   /* If any auxilary data functions have been called by this user function,
   ** immediately call the destructor for any non-static values.
@@ -1451,13 +1284,10 @@ case OP_Function: {
     rc = SQLITE_ERROR;
   }
 
-  /* Copy the result of the function to the top of the stack */
+  /* Copy the result of the function into register P3 */
   sqlite3VdbeChangeEncoding(&ctx.s, encoding);
-  if( pOp->p3==0 ){
-    pOut = ++pTos;
-  }else{
-    pOut = &p->aMem[pOp->p3];
-  }
+  assert( pOp->p3>0 && pOp->p3<=p->nMem );
+  pOut = &p->aMem[pOp->p3];
   sqlite3VdbeMemMove(pOut, &ctx.s);
   if( sqlite3VdbeMemTooBig(pOut) ){
     goto too_big;
@@ -1526,8 +1356,7 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT, in1, in2, out3 */
 **
 ** To force any register to be an integer, just add 0.
 */
-case OP_AddImm: {            /* no-push, in1 */
-  nPop = 0;
+case OP_AddImm: {            /* in1 */
   sqlite3VdbeMemIntegerify(pIn1);
   pIn1->u.i += pOp->p2;
   break;
@@ -1543,14 +1372,13 @@ case OP_AddImm: {            /* no-push, in1 */
 ** current value if P3==0, or to the least integer that is strictly
 ** greater than its current value if P3==1.
 */
-case OP_ForceInt: {            /* no-push, jump, in1 */
+case OP_ForceInt: {            /* jump, in1 */
   i64 v;
   applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
   if( (pIn1->flags & (MEM_Int|MEM_Real))==0 ){
     pc = pOp->p2 - 1;
     break;
   }
-  nPop = 0;
   if( pIn1->flags & MEM_Int ){
     v = pIn1->u.i + (pOp->p3!=0);
   }else{
@@ -1565,29 +1393,20 @@ case OP_ForceInt: {            /* no-push, jump, in1 */
   break;
 }
 
-/* Opcode: MustBeInt P1 P2 P3
+/* Opcode: MustBeInt P1 P2 * * *
 ** 
-** Force the value in register P1 to be an integer.  If P1==0 then
-** use the top of the stack.  If the value in P1 
-** is not an integer and cannot be converted into an integer
+** Force the value in register P1 to be an integer.  If the value
+** in P1 is not an integer and cannot be converted into an integer
 ** without data loss, then jump immediately to P2, or if P2==0
 ** raise an SQLITE_MISMATCH exception.
-**
-** If the P1==0 and the top of the stack is not an integer
-** and P2 is not zero and P3 is 1, then the stack is popped.
-** In all other cases, the depth of the stack is unchanged.
 */
-case OP_MustBeInt: {            /* no-push, jump, in1 */
-  nPop = 0;
+case OP_MustBeInt: {            /* jump, in1 */
   applyAffinity(pIn1, SQLITE_AFF_NUMERIC, encoding);
   if( (pIn1->flags & MEM_Int)==0 ){
     if( pOp->p2==0 ){
       rc = SQLITE_MISMATCH;
       goto abort_due_to_error;
     }else{
-      if( pOp->p3 && pOp->p1==0 ){
-        popStack(&pTos, 1);
-      }
       pc = pOp->p2 - 1;
     }
   }else{
@@ -1606,8 +1425,7 @@ case OP_MustBeInt: {            /* no-push, jump, in1 */
 ** integers, for space efficiency, but after extraction we want them
 ** to have only a real value.
 */
-case OP_RealAffinity: {                  /* no-push, in1 */
-  nPop = 0;
+case OP_RealAffinity: {                  /* in1 */
   if( pIn1->flags & MEM_Int ){
     sqlite3VdbeMemRealify(pIn1);
   }
@@ -1624,8 +1442,7 @@ case OP_RealAffinity: {                  /* no-push, in1 */
 **
 ** A NULL value is not changed by this routine.  It remains NULL.
 */
-case OP_ToText: {                  /* same as TK_TO_TEXT, no-push, in1 */
-  nPop = 0;
+case OP_ToText: {                  /* same as TK_TO_TEXT, in1 */
   if( pIn1->flags & MEM_Null ) break;
   assert( MEM_Str==(MEM_Blob>>3) );
   pIn1->flags |= (pIn1->flags&MEM_Blob)>>3;
@@ -1646,8 +1463,7 @@ case OP_ToText: {                  /* same as TK_TO_TEXT, no-push, in1 */
 **
 ** A NULL value is not changed by this routine.  It remains NULL.
 */
-case OP_ToBlob: {                  /* same as TK_TO_BLOB, no-push, in1 */
-  nPop = 0;
+case OP_ToBlob: {                  /* same as TK_TO_BLOB, in1 */
   if( pIn1->flags & MEM_Null ) break;
   if( (pIn1->flags & MEM_Blob)==0 ){
     applyAffinity(pIn1, SQLITE_AFF_TEXT, encoding);
@@ -1669,8 +1485,7 @@ case OP_ToBlob: {                  /* same as TK_TO_BLOB, no-push, in1 */
 **
 ** A NULL value is not changed by this routine.  It remains NULL.
 */
-case OP_ToNumeric: {                  /* same as TK_TO_NUMERIC, no-push, in1 */
-  nPop = 0;
+case OP_ToNumeric: {                  /* same as TK_TO_NUMERIC, in1 */
   if( (pIn1->flags & (MEM_Null|MEM_Int|MEM_Real))==0 ){
     sqlite3VdbeMemNumerify(pIn1);
   }
@@ -1687,8 +1502,7 @@ case OP_ToNumeric: {                  /* same as TK_TO_NUMERIC, no-push, in1 */
 **
 ** A NULL value is not changed by this routine.  It remains NULL.
 */
-case OP_ToInt: {                  /* same as TK_TO_INT, no-push, in1 */
-  nPop = 0;
+case OP_ToInt: {                  /* same as TK_TO_INT, in1 */
   if( (pIn1->flags & MEM_Null)==0 ){
     sqlite3VdbeMemIntegerify(pIn1);
   }
@@ -1705,8 +1519,7 @@ case OP_ToInt: {                  /* same as TK_TO_INT, no-push, in1 */
 **
 ** A NULL value is not changed by this routine.  It remains NULL.
 */
-case OP_ToReal: {                  /* same as TK_TO_REAL, no-push, in1 */
-  nPop = 0;
+case OP_ToReal: {                  /* same as TK_TO_REAL, in1 */
   if( (pIn1->flags & MEM_Null)==0 ){
     sqlite3VdbeMemRealify(pIn1);
   }
@@ -1746,42 +1559,42 @@ case OP_ToReal: {                  /* same as TK_TO_REAL, no-push, in1 */
 ** If the SQLITE_STOREP2 bit of P5 is set, then do not jump.  Instead,
 ** store a boolean result (either 0, or 1, or NULL) in register P2.
 */
-/* Opcode: Ne P1 P2 P4
+/* Opcode: Ne P1 P2 P3 P4 P5
 **
 ** This works just like the Lt opcode except that the jump is taken if
 ** the operands in registers P1 and P3 are not equal.  See the Lt opcode for
 ** additional information.
 */
-/* Opcode: Eq P1 P2 P4
+/* Opcode: Eq P1 P2 P3 P4 P5
 **
 ** This works just like the Lt opcode except that the jump is taken if
 ** the operands in registers P1 and P3 are equal.
 ** See the Lt opcode for additional information.
 */
-/* Opcode: Le P1 P2 P4
+/* Opcode: Le P1 P2 P3 P4 P5
 **
 ** This works just like the Lt opcode except that the jump is taken if
 ** the content of register P3 is less than or equal to the content of
 ** register P1.  See the Lt opcode for additional information.
 */
-/* Opcode: Gt P1 P2 P4
+/* Opcode: Gt P1 P2 P3 P4 P5
 **
 ** This works just like the Lt opcode except that the jump is taken if
 ** the content of register P3 is greater than the content of
 ** register P1.  See the Lt opcode for additional information.
 */
-/* Opcode: Ge P1 P2 P4
+/* Opcode: Ge P1 P2 P3 P4 P5
 **
 ** This works just like the Lt opcode except that the jump is taken if
 ** the content of register P3 is greater than or equal to the content of
 ** register P1.  See the Lt opcode for additional information.
 */
-case OP_Eq:               /* same as TK_EQ, no-push, jump, in1, in3 */
-case OP_Ne:               /* same as TK_NE, no-push, jump, in1, in3 */
-case OP_Lt:               /* same as TK_LT, no-push, jump, in1, in3 */
-case OP_Le:               /* same as TK_LE, no-push, jump, in1, in3 */
-case OP_Gt:               /* same as TK_GT, no-push, jump, in1, in3 */
-case OP_Ge: {             /* same as TK_GE, no-push, jump, in1, in3 */
+case OP_Eq:               /* same as TK_EQ, jump, in1, in3 */
+case OP_Ne:               /* same as TK_NE, jump, in1, in3 */
+case OP_Lt:               /* same as TK_LT, jump, in1, in3 */
+case OP_Le:               /* same as TK_LE, jump, in1, in3 */
+case OP_Gt:               /* same as TK_GT, jump, in1, in3 */
+case OP_Ge: {             /* same as TK_GE, jump, in1, in3 */
   int flags;
   int res;
   char affinity;
@@ -1789,10 +1602,6 @@ case OP_Ge: {             /* same as TK_GE, no-push, jump, in1, in3 */
 
   flags = pIn1->flags|pIn3->flags;
 
-  /* If either value is a NULL P2 is not zero, take the jump if the least
-  ** significant byte of P1 is true. If P2 is zero, then push a NULL onto
-  ** the stack.
-  */
   if( flags&MEM_Null ){
     if( (pOp->p5 & SQLITE_NULLEQUAL)!=0 ){
       /*
@@ -1913,8 +1722,7 @@ case OP_Or: {             /* same as TK_OR, in1, in2, out3 */
 ** with its complement.  If the value in register P1 is NULL its value
 ** is unchanged.
 */
-case OP_Not: {                /* same as TK_NOT, no-push, in1 */
-  nPop = 0;
+case OP_Not: {                /* same as TK_NOT, in1 */
   if( pIn1->flags & MEM_Null ) break;  /* Do nothing to NULLs */
   sqlite3VdbeMemIntegerify(pIn1);
   pIn1->u.i = !pIn1->u.i;
@@ -1928,8 +1736,7 @@ case OP_Not: {                /* same as TK_NOT, no-push, in1 */
 ** with its ones-complement.  If the value is originally NULL, leave
 ** it unchanged.
 */
-case OP_BitNot: {             /* same as TK_BITNOT, no-push, in1 */
-  nPop = 0;
+case OP_BitNot: {             /* same as TK_BITNOT, in1 */
   if( pIn1->flags & MEM_Null ) break;  /* Do nothing to NULLs */
   sqlite3VdbeMemIntegerify(pIn1);
   pIn1->u.i = ~pIn1->u.i;
@@ -1949,7 +1756,7 @@ case OP_BitNot: {             /* same as TK_BITNOT, no-push, in1 */
 ** the same as a no-op.  This opcodesnever appears in a real VM program.
 */
 case OP_Explain:
-case OP_Noop: {            /* no-push */
+case OP_Noop: {
   break;
 }
 
@@ -1965,8 +1772,8 @@ case OP_Noop: {            /* no-push */
 ** is considered true if it has a numeric value of zero.  If the value
 ** in P1 is NULL then take the jump if P3 is true.
 */
-case OP_If:                 /* no-push, jump, in1 */
-case OP_IfNot: {            /* no-push, jump, in1 */
+case OP_If:                 /* jump, in1 */
+case OP_IfNot: {            /* jump, in1 */
   int c;
   if( pIn1->flags & MEM_Null ){
     c = pOp->p3;
@@ -1989,11 +1796,8 @@ case OP_IfNot: {            /* no-push, jump, in1 */
 ** Jump to P2 if the value in register P1 is NULL.  If P3 is greater
 ** than zero, then check all values reg(P1), reg(P1+1), 
 ** reg(P1+2), ..., reg(P1+P3-1).
-**
-** If P1 is 0 then use the top of the stack instead of a register
-** and pop the stack regardless of whether or not the jump is taken.
 */
-case OP_IsNull: {            /* same as TK_ISNULL, no-push, jump, in1 */
+case OP_IsNull: {            /* same as TK_ISNULL, jump, in1 */
   int n = pOp->p3;
   assert( pOp->p3==0 || pOp->p1>0 );
   do{
@@ -2009,11 +1813,8 @@ case OP_IsNull: {            /* same as TK_ISNULL, no-push, jump, in1 */
 /* Opcode: NotNull P1 P2 * * *
 **
 ** Jump to P2 if the value in register P1 is not NULL.  
-**
-** If P1 is 0 then use the top of the stack instead of a register
-** and pop the stack regardless of whether or not the jump is taken.
 */
-case OP_NotNull: {            /* same as TK_NOTNULL, no-push, jump, in1 */
+case OP_NotNull: {            /* same as TK_NOTNULL, jump, in1 */
   if( (pIn1->flags & MEM_Null)==0 ){
     pc = pOp->p2 - 1;
   }
@@ -2030,7 +1831,7 @@ case OP_NotNull: {            /* same as TK_NOTNULL, no-push, jump, in1 */
 ** If OP_KeyAsData is to be applied to cursor P1, it must be executed
 ** before this op-code.
 */
-case OP_SetNumColumns: {       /* no-push */
+case OP_SetNumColumns: {
   Cursor *pC;
   assert( (pOp->p1)<p->nCursor );
   assert( p->apCsr[pOp->p1]!=0 );
@@ -2047,9 +1848,7 @@ case OP_SetNumColumns: {       /* no-push */
 ** from this record.  If there are less that (P2+1) 
 ** values in the record, extract a NULL.
 **
-** The value extracted is pushed onto the stack.  Or if P3 is a positive
-** non-zero integer register number, then the value is written into that
-** register.
+** The value extracted is stored in register P3.
 **
 ** If the KeyAsData opcode has previously executed on this cursor, then the
 ** field might be extracted from the key rather than the data.
@@ -2076,11 +1875,8 @@ case OP_Column: {
 
   sMem.flags = 0;
   assert( p1<p->nCursor );
-  if( pOp->p3>0 ){
-    pDest = &p->aMem[pOp->p3];
-  }else{
-    pDest = ++pTos;
-  }
+  assert( pOp->p3>0 && pOp->p3<=p->nMem );
+  pDest = &p->aMem[pOp->p3];
   sqlite3VdbeMemSetNull(pDest);
 
   /* This block sets the variable payloadSize to be the total number of
@@ -2093,9 +1889,7 @@ case OP_Column: {
   ** If the data is unavailable,  zRec is set to NULL.
   **
   ** We also compute the number of columns in the record.  For cursors,
-  ** the number of columns is stored in the Cursor.nField element.  For
-  ** records on the stack, the next entry down on the stack is an integer
-  ** which is the number of records.
+  ** the number of columns is stored in the Cursor.nField element.
   */
   pC = p->apCsr[p1];
   assert( pC!=0 );
@@ -2136,7 +1930,7 @@ case OP_Column: {
     nField = 0;
   }
 
-  /* If payloadSize is 0, then just push a NULL onto the stack. */
+  /* If payloadSize is 0, then just store a NULL */
   if( payloadSize==0 ){
     assert( pDest->flags==MEM_Null );
     goto op_column_out;
@@ -2227,8 +2021,8 @@ case OP_Column: {
         /* If i is less that nField, then there are less fields in this
         ** record than SetNumColumns indicated there are columns in the
         ** table. Set the offset for any extra columns not present in
-        ** the record to 0. This tells code below to push a NULL onto the
-        ** stack instead of deserializing a value from the record.
+        ** the record to 0. This tells code below to store a NULL
+        ** instead of deserializing a value from the record.
         */
         aOffset[i] = 0;
       }
@@ -2310,8 +2104,7 @@ op_column_out:
 **
 ** P4 may be a string that is P1 characters long.  The nth character of the
 ** string indicates the column affinity that should be used for the nth
-** field of the index key (i.e. the first character of P4 corresponds to the
-** lowest element on the stack).
+** field of the index key.
 **
 ** The mapping from character to affinity is given by the SQLITE_AFF_
 ** macros defined in sqliteInt.h.
@@ -2326,8 +2119,8 @@ case OP_MakeRecord: {
   ** | hdr-size | type 0 | type 1 | ... | type N-1 | data0 | ... | data N-1 | 
   ** ------------------------------------------------------------------------
   **
-  ** Data(0) is taken from the lowest element of the stack and data(N-1) is
-  ** the top of the stack.
+  ** Data(0) is taken from register P1.  Data(1) comes from register P1+1
+  ** and so froth.
   **
   ** Each type field is a varint representing the serial type of the 
   ** corresponding data element (see sqlite3VdbeSerialType()). The
@@ -2413,12 +2206,9 @@ case OP_MakeRecord: {
   }
   assert( i==nByte );
 
-  if( pOp->p3==0 ){
-    pOut = ++pTos;
-  }else{
-    pOut = &p->aMem[pOp->p3];
-    Release(pOut);
-  }
+  assert( pOp->p3>0 && pOp->p3<=p->nMem );
+  pOut = &p->aMem[pOp->p3];
+  Release(pOut);
   pOut->n = nByte;
   if( nByte<=sizeof(zTemp) ){
     assert( zNewRecord==(unsigned char *)zTemp );
@@ -2453,7 +2243,7 @@ case OP_MakeRecord: {
 ** database file has an index of 0 and the file used for temporary tables
 ** has an index of 1.
 */
-case OP_Statement: {       /* no-push */
+case OP_Statement: {
   int i = pOp->p1;
   Btree *pBt;
   if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt)!=0
@@ -2476,7 +2266,7 @@ case OP_Statement: {       /* no-push */
 **
 ** This instruction causes the VM to halt.
 */
-case OP_AutoCommit: {       /* no-push */
+case OP_AutoCommit: {
   u8 i = pOp->p1;
   u8 rollback = pOp->p2;
 
@@ -2501,7 +2291,6 @@ case OP_AutoCommit: {       /* no-push */
     }else{
       db->autoCommit = i;
       if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
-        p->pTos = pTos;
         p->pc = pc;
         db->autoCommit = 1-i;
         p->rc = rc = SQLITE_BUSY;
@@ -2545,7 +2334,7 @@ case OP_AutoCommit: {       /* no-push */
 **
 ** If P2 is zero, then a read-lock is obtained on the database file.
 */
-case OP_Transaction: {       /* no-push */
+case OP_Transaction: {
   int i = pOp->p1;
   Btree *pBt;
 
@@ -2558,7 +2347,6 @@ case OP_Transaction: {       /* no-push */
     if( rc==SQLITE_BUSY ){
       p->pc = pc;
       p->rc = rc = SQLITE_BUSY;
-      p->pTos = pTos;
       goto vdbe_return;
     }
     if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){
@@ -2570,8 +2358,7 @@ case OP_Transaction: {       /* no-push */
 
 /* Opcode: ReadCookie P1 P2 P3 * *
 **
-** Read cookie number P3 from database P1 and write it into register
-** P2 or push it onto the stack if P2==0.
+** Read cookie number P3 from database P1 and write it into register P2.
 ** P3==0 is the schema version.  P3==1 is the database format.
 ** P3==2 is the recommended pager cache size, and so forth.  P1==0 is
 ** the main database file and P1==1 is the database file used to store
@@ -2623,7 +2410,7 @@ case OP_ReadCookie: {               /* out2-prerelease */
 **
 ** A transaction must be started before executing this opcode.
 */
-case OP_SetCookie: {       /* no-push, in3 */
+case OP_SetCookie: {       /* in3 */
   Db *pDb;
   assert( pOp->p2<SQLITE_N_BTREE_META );
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
@@ -2665,7 +2452,7 @@ case OP_SetCookie: {       /* no-push, in3 */
 ** to be executed (to establish a read lock) before this opcode is
 ** invoked.
 */
-case OP_VerifyCookie: {       /* no-push */
+case OP_VerifyCookie: {
   int iMeta;
   Btree *pBt;
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
@@ -2746,8 +2533,8 @@ case OP_VerifyCookie: {       /* no-push */
 **
 ** See also OpenRead.
 */
-case OP_OpenRead:          /* no-push */
-case OP_OpenWrite: {       /* no-push */
+case OP_OpenRead:
+case OP_OpenWrite: {
   int i = pOp->p1;
   int p2 = pOp->p2;
   int iDb = pOp->p3;
@@ -2770,18 +2557,11 @@ case OP_OpenWrite: {       /* no-push */
     wrFlag = 0;
   }
   if( pOp->p5 ){
-    if( p2==0 ){
-      assert( pTos>=p->aStack );
-      sqlite3VdbeMemIntegerify(pTos);
-      p2 = pTos->u.i;
-      assert( (pTos->flags & MEM_Dyn)==0 );
-      pTos--;
-    }else{
-      assert( p2<=p->nMem );
-      pIn2 = &p->aMem[p2];
-      sqlite3VdbeMemIntegerify(pIn2);
-      p2 = pIn2->u.i;
-    }
+    assert( p2>0 );
+    assert( p2<=p->nMem );
+    pIn2 = &p->aMem[p2];
+    sqlite3VdbeMemIntegerify(pIn2);
+    p2 = pIn2->u.i;
     assert( p2>=2 );
   }
   assert( i>=0 );
@@ -2806,7 +2586,6 @@ case OP_OpenWrite: {       /* no-push */
     case SQLITE_BUSY: {
       p->pc = pc;
       p->rc = rc = SQLITE_BUSY;
-      p->pTos = &pTos[(pOp->p2<=0)]; /* Operands must remain on stack */
       goto vdbe_return;
     }
     case SQLITE_OK: {
@@ -2865,7 +2644,7 @@ case OP_OpenWrite: {       /* no-push */
 ** this opcode.  Then this opcode was call OpenVirtual.  But
 ** that created confusion with the whole virtual-table idea.
 */
-case OP_OpenEphemeral: {       /* no-push */
+case OP_OpenEphemeral: {
   int i = pOp->p1;
   Cursor *pCx;
   static const int openFlags = 
@@ -2926,7 +2705,7 @@ case OP_OpenEphemeral: {       /* no-push */
 ** row output from the sorter so that the row can be decomposed into
 ** individual columns using the OP_Column opcode.
 */
-case OP_OpenPseudo: {       /* no-push */
+case OP_OpenPseudo: {
   int i = pOp->p1;
   Cursor *pCx;
   assert( i>=0 );
@@ -2945,7 +2724,7 @@ case OP_OpenPseudo: {       /* no-push */
 ** Close a cursor previously opened as P1.  If P1 is not
 ** currently open, this instruction is a no-op.
 */
-case OP_Close: {       /* no-push */
+case OP_Close: {
   int i = pOp->p1;
   if( i>=0 && i<p->nCursor ){
     sqlite3VdbeFreeCursor(p, p->apCsr[i]);
@@ -2964,7 +2743,7 @@ case OP_Close: {       /* no-push */
 **
 ** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe
 */
-/* Opcode: MoveGt P1 P2 *
+/* Opcode: MoveGt P1 P2 P3 * *
 **
 ** Use the value in register P3 as a key.  Reposition
 ** cursor P1 so that it points to the smallest entry that is greater
@@ -2974,7 +2753,7 @@ case OP_Close: {       /* no-push */
 **
 ** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe
 */
-/* Opcode: MoveLt P1 P2 *
+/* Opcode: MoveLt P1 P2 P3 * * 
 **
 ** Use the value in register P3 as a key.  Reposition
 ** cursor P1 so that it points to the largest entry that is less
@@ -2984,7 +2763,7 @@ case OP_Close: {       /* no-push */
 **
 ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe
 */
-/* Opcode: MoveLe P1 P2 *
+/* Opcode: MoveLe P1 P2 P3 * *
 **
 ** Use the value in register P3 as a key.  Reposition
 ** cursor P1 so that it points to the largest entry that is less than
@@ -2994,10 +2773,10 @@ case OP_Close: {       /* no-push */
 **
 ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
 */
-case OP_MoveLt:         /* no-push, jump, in3 */
-case OP_MoveLe:         /* no-push, jump, in3 */
-case OP_MoveGe:         /* no-push, jump, in3 */
-case OP_MoveGt: {       /* no-push, jump, in3 */
+case OP_MoveLt:         /* jump, in3 */
+case OP_MoveLe:         /* jump, in3 */
+case OP_MoveGe:         /* jump, in3 */
+case OP_MoveGt: {       /* jump, in3 */
   int i = pOp->p1;
   Cursor *pC;
 
@@ -3072,8 +2851,8 @@ case OP_MoveGt: {       /* no-push, jump, in3 */
 /* Opcode: Found P1 P2 P3 * *
 **
 ** Register P3 holds a blob constructed by MakeRecord.  P1 is an index.
-** If an entry that matches the top of the stack exists in P1 then
-** jump to P2.  If the top of the stack does not match any entry in P1
+** If an entry that matches the value in register p3 exists in P1 then
+** jump to P2.  If the P3 value does not match any entry in P1
 ** then fall thru.  The P1 cursor is left pointing at the matching entry
 ** if it exists.
 **
@@ -3085,8 +2864,8 @@ case OP_MoveGt: {       /* no-push, jump, in3 */
 **
 ** This instruction checks if index P1 contains a record for which 
 ** the first N serialised values exactly match the N serialised values
-** in the record on the stack, where N is the total number of values in
-** the stack record (stack record is a prefix of the P1 record). 
+** in the record in register P3, where N is the total number of values in
+** the P3 record (the P3 record is a prefix of the P1 record). 
 **
 ** See also: NotFound, MoveTo, IsUnique, NotExists
 */
@@ -3095,15 +2874,12 @@ case OP_MoveGt: {       /* no-push, jump, in3 */
 ** Register P3 holds a blob constructed by MakeRecord.  P1 is
 ** an index.  If no entry exists in P1 that matches the blob then jump
 ** to P2.  If an entry does existing, fall through.  The cursor is left
-** pointing to the entry that matches.  The blob is popped from the stack.
-**
-** The difference between this operation and Distinct is that
-** Distinct does not pop the key from the stack.
+** pointing to the entry that matches.
 **
-** See also: Distinct, Found, MoveTo, NotExists, IsUnique
+** See also: Found, MoveTo, NotExists, IsUnique
 */
-case OP_NotFound:       /* no-push, jump, in3 */
-case OP_Found: {        /* no-push, jump, in3 */
+case OP_NotFound:       /* jump, in3 */
+case OP_Found: {        /* jump, in3 */
   int i = pOp->p1;
   int alreadyExists = 0;
   Cursor *pC;
@@ -3151,9 +2927,9 @@ case OP_Found: {        /* no-push, jump, in3 */
 ** number for that entry is written into P3 and control
 ** falls through to the next instruction.
 **
-** See also: Distinct, NotFound, NotExists, Found
+** See also: NotFound, NotExists, Found
 */
-case OP_IsUnique: {        /* no-push, jump, in3 */
+case OP_IsUnique: {        /* jump, in3 */
   int i = pOp->p1;
   Cursor *pCx;
   BtCursor *pCrsr;
@@ -3163,12 +2939,8 @@ case OP_IsUnique: {        /* no-push, jump, in3 */
   /* Pop the value R off the top of the stack
   */
   assert( pOp->p4type==P4_INT32 );
-  if( pOp->p4.i==0 ){
-    assert( pOp->p3==0 );
-    pK = &pIn3[-1];
-  }else{
-    pK = &p->aMem[pOp->p4.i];
-  }
+  assert( pOp->p4.i>0 && pOp->p4.i<=p->nMem );
+  pK = &p->aMem[pOp->p4.i];
   sqlite3VdbeMemIntegerify(pIn3);
   R = pIn3->u.i;
   assert( (pIn3->flags & MEM_Dyn)==0 );
@@ -3230,34 +3002,31 @@ case OP_IsUnique: {        /* no-push, jump, in3 */
       break;
     }
 
-    /* The final varint of the key is different from R.  Push it onto
-    ** the stack.  (The record number of an entry that violates a UNIQUE
-    ** constraint.)
+    /* The final varint of the key is different from R.  Store it back
+    ** into register R3.  (The record number of an entry that violates
+    ** a UNIQUE constraint.)
     */
-    nPop = 0;
     pIn3->u.i = v;
     assert( pIn3->flags==MEM_Int );
   }
   break;
 }
 
-/* Opcode: NotExists P1 P2 P3
+/* Opcode: NotExists P1 P2 P3 * *
 **
-** Use the top of the stack as a integer key. Or, if P3 is non-zero,
-** use the contents of register P3 as an integer key. If a record 
+** Use the content of register P3 as a integer key.  If a record 
 ** with that key does not exist in table of P1, then jump to P2. 
 ** If the record does exist, then fall thru.  The cursor is left 
-** pointing to the record if it exists. The integer key is popped 
-** from the stack if P3==0.
+** pointing to the record if it exists.
 **
 ** The difference between this operation and NotFound is that this
 ** operation assumes the key is an integer and that P1 is a table whereas
 ** NotFound assumes key is a blob constructed from MakeRecord and
 ** P1 is an index.
 **
-** See also: Distinct, Found, MoveTo, NotFound, IsUnique
+** See also: Found, MoveTo, NotFound, IsUnique
 */
-case OP_NotExists: {        /* no-push, jump, in3 */
+case OP_NotExists: {        /* jump, in3 */
   int i = pOp->p1;
   Cursor *pC;
   BtCursor *pCrsr;
@@ -3290,8 +3059,7 @@ case OP_NotExists: {        /* no-push, jump, in3 */
 /* Opcode: Sequence P1 P2 * * *
 **
 ** Find the next available sequence number for cursor P1.
-** Write the sequence number into register P2, or push it onto
-** the stack if P2==0.
+** Write the sequence number into register P2.
 ** The sequence number on the cursor is incremented after this
 ** instruction.  
 */
@@ -3309,8 +3077,8 @@ case OP_Sequence: {           /* out2-prerelease */
 **
 ** Get a new integer record number (a.k.a "rowid") used as the key to a table.
 ** The record number is not previously used as a key in the database
-** table that cursor P1 points to.  The new record number is pushed 
-** onto the stack if P2 is 0 or written to register P2 otherwise.
+** table that cursor P1 points to.  The new record number is written
+** written to register P2.
 **
 ** If P3>0 then P3 is a register that holds the largest previously
 ** generated record number.  No new record numbers are allowed to be less
@@ -3486,7 +3254,7 @@ case OP_NewRowid: {           /* out2-prerelease */
 ** This instruction only works on tables.  The equivalent instruction
 ** for indices is OP_IdxInsert.
 */
-case OP_Insert: {         /* no-push */
+case OP_Insert: {
   Mem *pData = &p->aMem[pOp->p2];
   Mem *pKey = &p->aMem[pOp->p3];
 
@@ -3574,7 +3342,7 @@ case OP_Insert: {         /* no-push */
 **
 ** If P1 is a pseudo-table, then this instruction is a no-op.
 */
-case OP_Delete: {        /* no-push */
+case OP_Delete: {
   int i = pOp->p1;
   Cursor *pC;
   assert( i>=0 && i<p->nCursor );
@@ -3624,7 +3392,7 @@ case OP_Delete: {        /* no-push */
 ** change counter (returned by subsequent calls to sqlite3_changes())
 ** before it is reset. This is used by trigger programs.
 */
-case OP_ResetCount: {        /* no-push */
+case OP_ResetCount: {
   if( pOp->p1 ){
     sqlite3VdbeSetChanges(db, p->nChange);
   }
@@ -3646,7 +3414,7 @@ case OP_ResetCount: {        /* no-push */
 **
 ** Write into register P2 the complete row key for cursor P1.
 ** There is no interpretation of the data.  
-** It is just copied onto the stack or into the memory cell exactly as 
+** The key is copied onto the P3 register exactly as 
 ** it is found in the database file.
 **
 ** If the cursor is not pointing to a valid row, a NULL is
@@ -3748,13 +3516,13 @@ case OP_Rowid: {                 /* out2-prerelease */
   break;
 }
 
-/* Opcode: NullRow P1 * *
+/* Opcode: NullRow P1 * * * *
 **
 ** Move the cursor P1 to a null row.  Any OP_Column operations
-** that occur while the cursor is on the null row will always push 
-** a NULL onto the stack.
+** that occur while the cursor is on the null row will always
+** write a NULL.
 */
-case OP_NullRow: {        /* no-push */
+case OP_NullRow: {
   int i = pOp->p1;
   Cursor *pC;
 
@@ -3766,7 +3534,7 @@ case OP_NullRow: {        /* no-push */
   break;
 }
 
-/* Opcode: Last P1 P2 *
+/* Opcode: Last P1 P2 * * *
 **
 ** The next use of the Rowid or Column or Next instruction for P1 
 ** will refer to the last entry in the database table or index.
@@ -3774,7 +3542,7 @@ case OP_NullRow: {        /* no-push */
 ** If P2 is 0 or if the table or index is not empty, fall through
 ** to the following instruction.
 */
-case OP_Last: {        /* no-push, jump */
+case OP_Last: {        /* jump */
   int i = pOp->p1;
   Cursor *pC;
   BtCursor *pCrsr;
@@ -3798,7 +3566,7 @@ case OP_Last: {        /* no-push, jump */
 }
 
 
-/* Opcode: Sort P1 P2 *
+/* Opcode: Sort P1 P2 * * *
 **
 ** This opcode does exactly the same thing as OP_Rewind except that
 ** it increments an undocumented global variable used for testing.
@@ -3810,14 +3578,14 @@ case OP_Last: {        /* no-push, jump */
 ** regression tests can determine whether or not the optimizer is
 ** correctly optimizing out sorts.
 */
-case OP_Sort: {        /* no-push, jump */
+case OP_Sort: {        /* jump */
 #ifdef SQLITE_TEST
   sqlite3_sort_count++;
   sqlite3_search_count--;
 #endif
   /* Fall through into OP_Rewind */
 }
-/* Opcode: Rewind P1 P2 *
+/* Opcode: Rewind P1 P2 * * *
 **
 ** The next use of the Rowid or Column or Next instruction for P1 
 ** will refer to the first entry in the database table or index.
@@ -3825,7 +3593,7 @@ case OP_Sort: {        /* no-push, jump */
 ** If P2 is 0 or if the table or index is not empty, fall through
 ** to the following instruction.
 */
-case OP_Rewind: {        /* no-push, jump */
+case OP_Rewind: {        /* jump */
   int i = pOp->p1;
   Cursor *pC;
   BtCursor *pCrsr;
@@ -3849,7 +3617,7 @@ case OP_Rewind: {        /* no-push, jump */
   break;
 }
 
-/* Opcode: Next P1 P2 *
+/* Opcode: Next P1 P2 * * *
 **
 ** Advance cursor P1 so that it points to the next key/data pair in its
 ** table or index.  If there are no more key/value pairs then fall through
@@ -3858,15 +3626,15 @@ case OP_Rewind: {        /* no-push, jump */
 **
 ** See also: Prev
 */
-/* Opcode: Prev P1 P2 *
+/* Opcode: Prev P1 P2 * * *
 **
 ** Back up cursor P1 so that it points to the previous key/data pair in its
 ** table or index.  If there is no previous key/value pairs then fall through
 ** to the following instruction.  But if the cursor backup was successful,
 ** jump immediately to P2.
 */
-case OP_Prev:          /* no-push, jump */
-case OP_Next: {        /* no-push, jump */
+case OP_Prev:          /* jump */
+case OP_Next: {        /* jump */
   Cursor *pC;
   BtCursor *pCrsr;
 
@@ -3900,7 +3668,7 @@ case OP_Next: {        /* no-push, jump */
   break;
 }
 
-/* Opcode: IdxInsert P1 P2 P3
+/* Opcode: IdxInsert P1 P2 P3 * *
 **
 ** Register P2 holds a SQL index key made using the
 ** MakeIdxRec instructions.  This opcode writes that key
@@ -3912,7 +3680,7 @@ case OP_Next: {        /* no-push, jump */
 ** This instruction only works for indices.  The equivalent instruction
 ** for tables is OP_Insert.
 */
-case OP_IdxInsert: {        /* no-push, in2 */
+case OP_IdxInsert: {        /* in2 */
   int i = pOp->p1;
   Cursor *pC;
   BtCursor *pCrsr;
@@ -3933,12 +3701,12 @@ case OP_IdxInsert: {        /* no-push, in2 */
   break;
 }
 
-/* Opcode: IdxDelete P1 P2 *
+/* Opcode: IdxDelete P1 P2 * * *
 **
 ** The content of register P2 is an index key built using the either the
 ** MakeIdxRec opcode.  Removes that entry from the index.
 */
-case OP_IdxDelete: {        /* no-push, in2 */
+case OP_IdxDelete: {        /* in2 */
   int i = pOp->p1;
   Cursor *pC;
   BtCursor *pCrsr;
@@ -4030,9 +3798,9 @@ case OP_IdxRowid: {              /* out2-prerelease */
 ** an epsilon prior to the comparison.  This makes the opcode work
 ** like IdxLE.
 */
-case OP_IdxLT:          /* no-push, jump, in3 */
-case OP_IdxGT:          /* no-push, jump, in3 */
-case OP_IdxGE: {        /* no-push, jump, in3 */
+case OP_IdxLT:          /* jump, in3 */
+case OP_IdxGT:          /* jump, in3 */
+case OP_IdxGE: {        /* jump, in3 */
   int i= pOp->p1;
   Cursor *pC;
 
@@ -4076,7 +3844,7 @@ case OP_IdxGE: {        /* no-push, jump, in3 */
 ** might be moved into the newly deleted root page in order to keep all
 ** root pages contiguous at the beginning of the database.  The former
 ** value of the root page that moved - its value before the move occurred -
-** is stored in register P2 or pushed onto the stack if P2==0.  If no page 
+** is stored in register P2.  If no page 
 ** movement was required (because the table being dropped was already 
 ** the last one in the database) then a zero is stored in register P2.
 ** If AUTOVACUUM is disabled then a zero is stored in register P2.
@@ -4128,7 +3896,7 @@ case OP_Destroy: {     /* out2-prerelease */
 **
 ** See also: Destroy
 */
-case OP_Clear: {        /* no-push */
+case OP_Clear: {
   assert( (p->btreeMask & (1<<pOp->p2))!=0 );
   rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
   break;
@@ -4139,7 +3907,7 @@ case OP_Clear: {        /* no-push */
 ** Allocate a new table in the main database file if P1==0 or in the
 ** auxiliary database file if P1==1 or in an attached database if
 ** P1>1.  Write the root page number of the new table into
-** register P2 or push it onto the stack if P2==0.
+** register P2
 **
 ** The difference between a table and an index is this:  A table must
 ** have a 4-byte integer key and can have arbitrary data.  An index
@@ -4152,7 +3920,7 @@ case OP_Clear: {        /* no-push */
 ** Allocate a new index in the main database file if P1==0 or in the
 ** auxiliary database file if P1==1 or in an attached database if
 ** P1>1.  Write the root page number of the new table into
-** register P2 or push it onto the stack if P2==0.
+** register P2.
 **
 ** See documentation on OP_CreateTable for additional information.
 */
@@ -4191,7 +3959,7 @@ case OP_CreateTable: {          /* out2-prerelease */
 ** This opcode invokes the parser to create a new virtual machine,
 ** then runs the new virtual machine.  It is thus a reentrant opcode.
 */
-case OP_ParseSchema: {        /* no-push */
+case OP_ParseSchema: {
   char *zSql;
   int iDb = pOp->p1;
   const char *zMaster;
@@ -4231,7 +3999,7 @@ case OP_ParseSchema: {        /* no-push */
 ** of that table into the internal index hash table.  This will cause
 ** the analysis to be used when preparing all subsequent queries.
 */
-case OP_LoadAnalysis: {        /* no-push */
+case OP_LoadAnalysis: {
   int iDb = pOp->p1;
   assert( iDb>=0 && iDb<db->nDb );
   rc = sqlite3AnalysisLoad(db, iDb);
@@ -4246,7 +4014,7 @@ case OP_LoadAnalysis: {        /* no-push */
 ** is dropped in order to keep the internal representation of the
 ** schema consistent with what is on disk.
 */
-case OP_DropTable: {        /* no-push */
+case OP_DropTable: {
   sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
   break;
 }
@@ -4258,7 +4026,7 @@ case OP_DropTable: {        /* no-push */
 ** is dropped in order to keep the internal representation of the
 ** schema consistent with what is on disk.
 */
-case OP_DropIndex: {        /* no-push */
+case OP_DropIndex: {
   sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
   break;
 }
@@ -4270,7 +4038,7 @@ case OP_DropIndex: {        /* no-push */
 ** is dropped in order to keep the internal representation of the
 ** schema consistent with what is on disk.
 */
-case OP_DropTrigger: {        /* no-push */
+case OP_DropTrigger: {
   sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
   break;
 }
@@ -4345,7 +4113,7 @@ case OP_IntegrityCk: {
 **
 ** Write the integer from register P1 into the Fifo.
 */
-case OP_FifoWrite: {        /* no-push, in1 */
+case OP_FifoWrite: {        /* in1 */
   if( sqlite3VdbeFifoPush(&p->sFifo, sqlite3VdbeIntValue(pIn1))==SQLITE_NOMEM ){
     goto no_mem;
   }
@@ -4378,7 +4146,7 @@ case OP_FifoRead: {         /* jump */
 ** opcode. The context stores the last insert row id, the last statement change
 ** count, and the current statement change count.
 */
-case OP_ContextPush: {        /* no-push */
+case OP_ContextPush: {
   int i = p->contextStackTop++;
   Context *pContext;
 
@@ -4404,7 +4172,7 @@ case OP_ContextPush: {        /* no-push */
 ** executed. The context stores the last insert row id, the last statement
 ** change count, and the current statement change count.
 */
-case OP_ContextPop: {        /* no-push */
+case OP_ContextPop: {
   Context *pContext = &p->contextStack[--p->contextStackTop];
   assert( p->contextStackTop>=0 );
   db->lastRowid = pContext->lastRowid;
@@ -4424,13 +4192,12 @@ case OP_ContextPop: {        /* no-push */
 ** This instruction throws an error if the memory cell is not initially
 ** an integer.
 */
-case OP_MemMax: {        /* no-push, in1, in2 */
+case OP_MemMax: {        /* in1, in2 */
   sqlite3VdbeMemIntegerify(pIn1);
   sqlite3VdbeMemIntegerify(pIn2);
   if( pIn1->u.i<pIn2->u.i){
     pIn1->u.i = pIn2->u.i;
   }
-  nPop = 0;
   break;
 }
 #endif /* SQLITE_OMIT_AUTOINCREMENT */
@@ -4442,7 +4209,7 @@ case OP_MemMax: {        /* no-push, in1, in2 */
 ** It is illegal to use this instruction on a register that does
 ** not contain an integer.  An assertion fault will result if you try.
 */
-case OP_IfPos: {        /* no-push, jump, in1 */
+case OP_IfPos: {        /* jump, in1 */
   assert( pIn1->flags==MEM_Int );
   if( pIn1->u.i>0 ){
      pc = pOp->p2 - 1;
@@ -4457,7 +4224,7 @@ case OP_IfPos: {        /* no-push, jump, in1 */
 ** It is illegal to use this instruction on a register that does
 ** not contain an integer.  An assertion fault will result if you try.
 */
-case OP_IfNeg: {        /* no-push, jump, in1 */
+case OP_IfNeg: {        /* jump, in1 */
   assert( pIn1->flags==MEM_Int );
   if( pIn1->u.i<0 ){
      pc = pOp->p2 - 1;
@@ -4472,7 +4239,7 @@ case OP_IfNeg: {        /* no-push, jump, in1 */
 ** It is illegal to use this instruction on a register that does
 ** not contain an integer.  An assertion fault will result if you try.
 */
-case OP_IfZero: {        /* no-push, jump, in1 */
+case OP_IfZero: {        /* jump, in1 */
   assert( pIn1->flags==MEM_Int );
   if( pIn1->u.i==0 ){
      pc = pOp->p2 - 1;
@@ -4490,7 +4257,7 @@ case OP_IfZero: {        /* no-push, jump, in1 */
 ** The P5 arguments are taken from register P2 and its
 ** successors.
 */
-case OP_AggStep: {        /* no-push */
+case OP_AggStep: {
   int n = pOp->p5;
   int i;
   Mem *pMem, *pRec;
@@ -4542,7 +4309,7 @@ case OP_AggStep: {        /* no-push */
 ** P4 argument is only needed for the degenerate case where
 ** the step function was not previously called.
 */
-case OP_AggFinal: {        /* no-push */
+case OP_AggFinal: {
   Mem *pMem;
   assert( pOp->p1>0 && pOp->p1<=p->nMem );
   pMem = &p->aMem[pOp->p1];
@@ -4566,7 +4333,7 @@ case OP_AggFinal: {        /* no-push */
 ** machines to be created and run.  It may not be called from within
 ** a transaction.
 */
-case OP_Vacuum: {        /* no-push */
+case OP_Vacuum: {
   if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; 
   rc = sqlite3RunVacuum(&p->zErrMsg, db);
   if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
@@ -4581,7 +4348,7 @@ case OP_Vacuum: {        /* no-push */
 ** the P1 database. If the vacuum has finished, jump to instruction
 ** P2. Otherwise, fall through to the next instruction.
 */
-case OP_IncrVacuum: {        /* no-push, jump */
+case OP_IncrVacuum: {        /* jump */
   Btree *pBt;
 
   assert( pOp->p1>=0 && pOp->p1<db->nDb );
@@ -4605,7 +4372,7 @@ case OP_IncrVacuum: {        /* no-push, jump */
 ** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
 ** then only the currently executing statement is affected. 
 */
-case OP_Expire: {        /* no-push */
+case OP_Expire: {
   if( !pOp->p1 ){
     sqlite3ExpirePreparedStatements(db);
   }else{
@@ -4631,7 +4398,7 @@ case OP_Expire: {        /* no-push */
 ** P4 contains a pointer to the name of the table being locked. This is only
 ** used to generate an error message if the lock cannot be obtained.
 */
-case OP_TableLock: {        /* no-push */
+case OP_TableLock: {
   int p1 = pOp->p1; 
   u8 isWriteLock = (p1<0);
   if( isWriteLock ){
@@ -4654,7 +4421,7 @@ case OP_TableLock: {        /* no-push */
 ** P4 a pointer to an sqlite3_vtab structure. Call the xBegin method 
 ** for that table.
 */
-case OP_VBegin: {   /* no-push */
+case OP_VBegin: {
   rc = sqlite3VtabBegin(db, pOp->p4.pVtab);
   break;
 }
@@ -4666,7 +4433,7 @@ case OP_VBegin: {   /* no-push */
 ** P4 is the name of a virtual table in database P1. Call the xCreate method
 ** for that table.
 */
-case OP_VCreate: {   /* no-push */
+case OP_VCreate: {
   rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg);
   break;
 }
@@ -4678,7 +4445,7 @@ case OP_VCreate: {   /* no-push */
 ** P4 is the name of a virtual table in database P1.  Call the xDestroy method
 ** of that table.
 */
-case OP_VDestroy: {   /* no-push */
+case OP_VDestroy: {
   p->inVtabMethod = 2;
   rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
   p->inVtabMethod = 0;
@@ -4693,7 +4460,7 @@ case OP_VDestroy: {   /* no-push */
 ** P1 is a cursor number.  This opcode opens a cursor to the virtual
 ** table and stores that cursor in P1.
 */
-case OP_VOpen: {   /* no-push */
+case OP_VOpen: {
   Cursor *pCur = 0;
   sqlite3_vtab_cursor *pVtabCursor = 0;
 
@@ -4741,7 +4508,7 @@ case OP_VOpen: {   /* no-push */
 **
 ** A jump is made to P2 if the result set after filtering would be empty.
 */
-case OP_VFilter: {   /* no-push, jump */
+case OP_VFilter: {   /* jump */
   int nArg;
   int iQuery;
   const sqlite3_module *pModule;
@@ -4754,7 +4521,7 @@ case OP_VFilter: {   /* no-push, jump */
   assert( pCur->pVtabCursor );
   pModule = pCur->pVtabCursor->pVtab->pModule;
 
-  /* Grab the index number and argc parameters off the top of the stack. */
+  /* Grab the index number and argc parameters */
   assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int );
   nArg = pArgc->u.i;
   iQuery = pQuery->u.i;
@@ -4792,7 +4559,6 @@ case OP_VFilter: {   /* no-push, jump */
 **
 ** Store into register P2  the rowid of
 ** the virtual-table that the P1 cursor is pointing to.
-** If P2==0, push the value onto the stack.
 */
 case OP_VRowid: {             /* out2-prerelease */
   const sqlite3_module *pModule;
@@ -4823,7 +4589,6 @@ case OP_VRowid: {             /* out2-prerelease */
 ** Store the value of the P2-th column of
 ** the row of the virtual-table that the 
 ** P1 cursor is pointing to into register P3.
-** Or if P3==0 push the value onto the stack.
 */
 case OP_VColumn: {
   const sqlite3_module *pModule;
@@ -4843,19 +4608,14 @@ case OP_VColumn: {
     if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
     rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
 
-    /* Copy the result of the function to the top of the stack. We
+    /* Copy the result of the function to the P3 register. We
     ** do this regardless of whether or not an error occured to ensure any
     ** dynamic allocation in sContext.s (a Mem struct) is  released.
     */
     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;
-    }
+    assert( pOp->p3>0 && pOp->p3<=p->nMem );
+    pDest = &p->aMem[pOp->p3];
+    REGISTER_TRACE(pOp->p3, pDest);
     sqlite3VdbeMemMove(pDest, &sContext.s);
     UPDATE_MAX_BLOBSIZE(pDest);
 
@@ -4878,7 +4638,7 @@ case OP_VColumn: {
 ** jump to instruction P2.  Or, if the virtual table has reached
 ** the end of its result set, then fall through to the next instruction.
 */
-case OP_VNext: {   /* no-push, jump */
+case OP_VNext: {   /* jump */
   const sqlite3_module *pModule;
   int res = 0;
 
@@ -4921,7 +4681,7 @@ case OP_VNext: {   /* no-push, jump */
 ** This opcode invokes the corresponding xRename method. The value
 ** in register P1 is passed as the zName argument to the xRename method.
 */
-case OP_VRename: {   /* no-push */
+case OP_VRename: {
   sqlite3_vtab *pVtab = pOp->p4.pVtab;
   Mem *pName = &p->aMem[pOp->p1];
   assert( pVtab->pModule->xRename );
@@ -4963,7 +4723,7 @@ case OP_VRename: {   /* no-push */
 ** is successful, then the value returned by sqlite3_last_insert_rowid() 
 ** is set to the value of the rowid for the row just inserted.
 */
-case OP_VUpdate: {   /* no-push */
+case OP_VUpdate: {
   sqlite3_vtab *pVtab = pOp->p4.pVtab;
   sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule;
   int nArg = pOp->p2;
@@ -5031,15 +4791,6 @@ default: {
 *****************************************************************************/
     }
 
-    /* Pop the stack if necessary */
-    if( nPop ){
-      popStack(&pTos, nPop);
-      nPop = 0;
-    }
-
-    /* Make sure the stack limit was not exceeded */
-    assert( pTos>=&p->aStack[-1] && pTos<=pStackLimit );
-
 #ifdef VDBE_PROFILE
     {
       long long elapse = hwtime() - start;
@@ -5058,20 +4809,9 @@ default: {
     ** the evaluator loop.  So we can leave it out when NDEBUG is defined.
     */
 #ifndef NDEBUG
-    /* Sanity checking on the top element of the stack. If the previous
-    ** instruction was VNoChange, then the flags field of the top
-    ** of the stack is set to 0. This is technically invalid for a memory
-    ** cell, so avoid calling MemSanity() in this case.
-    */
-    if( pTos>=p->aStack && pTos->flags ){
-      assert( pTos->db==db );
-      sqlite3VdbeMemSanity(pTos);
-      assert( !sqlite3VdbeMemTooBig(pTos) );
-    }
     assert( pc>=-1 && pc<p->nOp );
 
 #ifdef SQLITE_DEBUG
-    /* Code for tracing the vdbe stack. */
     if( p->trace ){
       if( rc!=0 ) fprintf(p->trace,"rc=%d\n",rc);
       if( (opProperty&(OPFLG_OUT2_PRERELEASE|OPFLG_OUT2))!=0 && pOp->p2>0 ){
@@ -5080,14 +4820,6 @@ default: {
       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 */
@@ -5103,7 +4835,6 @@ vdbe_halt:
     rc = SQLITE_DONE;
   }
   sqlite3VdbeHalt(p);
-  p->pTos = pTos;
 
   /* This is the only way out of this procedure.  We have to
   ** release the mutexes on btrees that were acquired at the
index 36c71e728e756886daf140d39c4cfe4129af038d..094867fa6d8aa921cdf6e6d419985fca3883c22b 100644 (file)
@@ -291,8 +291,6 @@ struct Vdbe {
   int nLabel;         /* Number of labels used */
   int nLabelAlloc;    /* Number of slots allocated in aLabel[] */
   int *aLabel;        /* Space to hold the labels */
-  Mem *aStack;        /* The operand stack, except string values */
-  Mem *pTos;          /* Top entry in the operand stack */
   Mem **apArg;        /* Arguments to currently executing user function */
   Mem *aColName;      /* Column names to return */
   int nCursor;        /* Number of slots in apCsr[] */
@@ -319,7 +317,6 @@ struct Vdbe {
   int returnDepth;        /* Next unused element in returnStack[] */
   int nResColumn;         /* Number of columns in one row of the result set */
   char **azResColumn;     /* Values for one row of result */ 
-  int popStack;           /* Pop the stack this much on entry to VdbeExec() */
   char *zErrMsg;          /* Error message written here */
   Mem *pResultSet;        /* Pointer to an array of results */
   u8 explain;             /* True if EXPLAIN present on SQL command */
index 95d4818843108e305878cd530f1a49165633896e..66160ef54f456124eca6f0873356b783950ad20c 100644 (file)
@@ -233,9 +233,9 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
 }
 
 /*
-** Loop through the program looking for P2 values that are negative.
-** Each such value is a label.  Resolve the label by setting the P2
-** value to its correct non-zero value.
+** Loop through the program looking for P2 values that are negative
+** on jump instructions.  Each such value is a label.  Resolve the
+** label by setting the P2 value to its correct non-zero value.
 **
 ** This routine is called once after all opcodes have been inserted.
 **
@@ -243,9 +243,6 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
 ** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by 
 ** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
 **
-** The integer *pMaxStack is set to the maximum number of vdbe stack
-** entries that static analysis reveals this program might need.
-**
 ** This routine also does the following optimization:  It scans for
 ** instructions that might cause a statement rollback.  Such instructions
 ** are:
@@ -259,10 +256,9 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
 ** is changed to a Noop.  In this way, we avoid creating the statement 
 ** journal file unnecessarily.
 */
-static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
+static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
   int i;
   int nMaxArgs = 0;
-  int nMaxStack = p->nOp;
   Op *pOp;
   int *aLabel = p->aLabel;
   int doesStatementRollback = 0;
@@ -298,9 +294,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
       if( n>nMaxArgs ) nMaxArgs = n;
 #endif
     }
-    if( !sqlite3VdbeOpcodeHasProperty(opcode, OPFLG_PUSH) ){
-      nMaxStack--;
-    }
 
     if( sqlite3VdbeOpcodeHasProperty(opcode, OPFLG_JUMP) && pOp->p2<0 ){
       assert( -1-pOp->p2<p->nLabel );
@@ -311,7 +304,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
   p->aLabel = 0;
 
   *pMaxFuncArgs = nMaxArgs;
-  *pMaxStack = nMaxStack;
 
   /* If we never rollback a statement transaction, then statement
   ** transactions are not needed.  So change every OP_Statement
@@ -739,7 +731,7 @@ static void releaseMemArray(Mem *p, int N){
   if( p ){
     while( N-->0 ){
       assert( N<2 || p[0].db==p[1].db );
-      sqlite3VdbeMemRelease(p++);
+      sqlite3VdbeMemSetNull(p++);
     }
   }
 }
@@ -751,6 +743,11 @@ static void releaseMemArray(Mem *p, int N){
 ** The interface is the same as sqlite3VdbeExec().  But instead of
 ** running the code, it invokes the callback once for each instruction.
 ** This feature is used to implement "EXPLAIN".
+**
+** When p->explain==1, each instruction is listed.  When
+** p->explain==2, only OP_Explain instructions are listed and these
+** are shown in a different format.  p->explain==2 is used to implement
+** EXPLAIN QUERY PLAN.
 */
 int sqlite3VdbeList(
   Vdbe *p                   /* The VDBE */
@@ -758,20 +755,18 @@ int sqlite3VdbeList(
   sqlite3 *db = p->db;
   int i;
   int rc = SQLITE_OK;
+  Mem *pMem = p->pResultSet = &p->aMem[1];
 
   assert( p->explain );
   if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
   assert( db->magic==SQLITE_MAGIC_BUSY );
   assert( p->rc==SQLITE_OK || p->rc==SQLITE_BUSY );
 
-  /* Even though this opcode does not put dynamic strings onto the
-  ** the stack, they may become dynamic if the user calls
+  /* Even though this opcode does not use dynamic strings for
+  ** the result, result columns may become dynamic if the user calls
   ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
   */
-  if( p->pResultSet ){
-    releaseMemArray(p->pResultSet, 5);
-    p->pResultSet = 0;
-  }
+  releaseMemArray(pMem, p->nMem);
 
   do{
     i = p->pc++;
@@ -785,7 +780,6 @@ int sqlite3VdbeList(
     sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0);
   }else{
     Op *pOp = &p->aOp[i];
-    Mem *pMem = p->pResultSet = p->aStack;
     if( p->explain==1 ){
       pMem->flags = MEM_Int;
       pMem->type = SQLITE_INTEGER;
@@ -846,7 +840,6 @@ int sqlite3VdbeList(
     }
 
     p->nResColumn = 8 - 5*(p->explain-1);
-    p->pTos = pMem;
     p->rc = SQLITE_OK;
     rc = SQLITE_ROW;
   }
@@ -935,36 +928,27 @@ void sqlite3VdbeMakeReady(
    */
   p->magic = VDBE_MAGIC_RUN;
 
-  /* No instruction ever pushes more than a single element onto the
-  ** stack.  And the stack never grows on successive executions of the
-  ** same loop.  So the total number of instructions is an upper bound
-  ** on the maximum stack depth required.  (Added later:)  The
-  ** resolveP2Values() call computes a tighter upper bound on the
-  ** stack size.
-  **
-  ** Allocation all the stack space we will ever need.
+  /*
+  ** Allocation space for registers.
   */
-  if( p->aStack==0 ){
+  if( p->aMem==0 ){
     int nArg;       /* Maximum number of args passed to a user function. */
-    int nStack;     /* Maximum number of stack entries required */
-    resolveP2Values(p, &nArg, &nStack);
+    resolveP2Values(p, &nArg);
     resizeOpArray(p, p->nOp);
     assert( nVar>=0 );
-    assert( nStack<p->nOp );
-    if( isExplain ){
-      nStack = 16;
+    if( isExplain && nMem<10 ){
+      p->nMem = nMem = 10;
     }
-    p->aStack = sqlite3DbMallocZero(db,
-        nStack*sizeof(p->aStack[0])    /* aStack */
-      + nArg*sizeof(Mem*)              /* apArg */
+    p->aMem = sqlite3DbMallocZero(db,
+        nMem*sizeof(Mem)               /* aMem */
       + nVar*sizeof(Mem)               /* aVar */
+      + nArg*sizeof(Mem*)              /* apArg */
       + nVar*sizeof(char*)             /* azVar */
-      + nMem*sizeof(Mem)               /* aMem */
       + nCursor*sizeof(Cursor*) + 1    /* apCsr */
     );
     if( !db->mallocFailed ){
-      p->aMem = &p->aStack[nStack-1];  /* aMem[] goes from 1..nMem */
-      p->nMem = nMem;                  /*       not from 0..nMem-1 */
+      p->aMem--;             /* aMem[] goes from 1..nMem */
+      p->nMem = nMem;        /*       not from 0..nMem-1 */
       p->aVar = &p->aMem[nMem+1];
       p->nVar = nVar;
       p->okVar = 0;
@@ -976,23 +960,24 @@ void sqlite3VdbeMakeReady(
         p->aVar[n].flags = MEM_Null;
         p->aVar[n].db = db;
       }
-      for(n=0; n<nStack; n++){
-        p->aStack[n].db = db;
+      for(n=1; n<=nMem; n++){
+        p->aMem[n].flags = MEM_Null;
+        p->aMem[n].db = db;
       }
     }
   }
-  for(n=1; n<=p->nMem; n++){
-    p->aMem[n].flags = MEM_Null;
-    p->aMem[n].db = db;
+#ifdef SQLITE_DEBUG
+  for(n=1; n<p->nMem; n++){
+    assert( p->aMem[n].db==db );
+    assert( p->aMem[n].flags==MEM_Null );
   }
+#endif
 
-  p->pTos = &p->aStack[-1];
   p->pc = -1;
   p->rc = SQLITE_OK;
   p->uniqueCnt = 0;
   p->returnDepth = 0;
   p->errorAction = OE_Abort;
-  p->popStack =  0;
   p->explain |= isExplain;
   p->magic = VDBE_MAGIC_RUN;
   p->nChange = 0;
@@ -1065,10 +1050,6 @@ static void closeAllCursorsExceptActiveVtabs(Vdbe *p){
 */
 static void Cleanup(Vdbe *p){
   int i;
-  if( p->aStack ){
-    releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack));
-    p->pTos = &p->aStack[-1];
-  }
   closeAllCursorsExceptActiveVtabs(p);
   releaseMemArray(&p->aMem[1], p->nMem);
   sqlite3VdbeFifoClear(&p->sFifo);
@@ -1664,7 +1645,6 @@ int sqlite3VdbeReset(Vdbe *p){
 
   /* Save profiling information from this VDBE run.
   */
-  assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || !p->aStack );
 #ifdef VDBE_PROFILE
   {
     FILE *out = fopen("vdbe_profile.out", "a");
@@ -1755,7 +1735,9 @@ void sqlite3VdbeDelete(Vdbe *p){
   }
   releaseMemArray(p->aVar, p->nVar);
   sqlite3_free(p->aLabel);
-  sqlite3_free(p->aStack);
+  if( p->aMem ){
+    sqlite3_free(&p->aMem[1]);
+  }
   releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
   sqlite3_free(p->aColName);
   sqlite3_free(p->zSql);
index 398fd649fef4e21c80d10d2a3e4f9f901a32e0a5..5402695e80e3a612249b0b90ebfc1574065b30e0 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to help implement virtual tables.
 **
-** $Id: vtab.c,v 1.61 2008/01/12 12:48:08 drh Exp $
+** $Id: vtab.c,v 1.62 2008/01/17 16:22:15 drh Exp $
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 #include "sqliteInt.h"
@@ -276,7 +276,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
     );
     sqlite3_free(zStmt);
     v = sqlite3GetVdbe(pParse);
-    sqlite3ChangeCookie(db, v, iDb);
+    sqlite3ChangeCookie(pParse, iDb);
 
     sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
     zWhere = sqlite3MPrintf(db, "name='%q'", pTab->zName);
index e046ba6eca9e2648bf6cccb4dcfa63f2c8ec5789..a1c48f1e92fab564e6da986a02f5d17ed13b94cb 100644 (file)
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.282 2008/01/17 02:36:28 drh Exp $
+** $Id: where.c,v 1.283 2008/01/17 16:22:15 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -2647,7 +2647,6 @@ WhereInfo *sqlite3WhereBegin(
       pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, OP_Rewind, iCur, brk);
     }
     notReady &= ~getMask(&maskSet, iCur);
-    sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);
 
     /* Insert code to test every subexpression that can be completely
     ** computed using the current set of tables.
index 2c91e41a5f96ca0fe17db3ac94e2817bd8e68012..c93df38a4fe290de7a1c82abad3fe2f757a703d9 100644 (file)
@@ -13,7 +13,7 @@
 #
 #     <value> IN (SELECT <column> FROM <table>)
 #
-# $Id: in3.test,v 1.2 2007/12/10 05:03:48 danielk1977 Exp $
+# $Id: in3.test,v 1.3 2008/01/17 16:22:16 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -266,4 +266,3 @@ do_test in3-4.6 {
 } {}
 
 finish_test
-