]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Continuing work toward registerizing the code generator. (CVS 4703)
authordrh <drh@noemail.net>
Thu, 10 Jan 2008 03:46:36 +0000 (03:46 +0000)
committerdrh <drh@noemail.net>
Thu, 10 Jan 2008 03:46:36 +0000 (03:46 +0000)
FossilOrigin-Name: 173698c963473ab1b9db88b23a2de82e4097b96d

manifest
manifest.uuid
src/expr.c
src/insert.c
src/select.c
src/sqliteInt.h

index 300261c5660201a47c81de138fb9c88cc008bca1..afef6b1e09343b4d042a280121ddf979248a4ca9 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\smixing\squote\sexcapes\sin\san\sawk\sscript.\s\sTicket\s#2877.\s(CVS\s4702)
-D 2008-01-10T00:08:43
+C Continuing\swork\stoward\sregisterizing\sthe\scode\sgenerator.\s(CVS\s4703)
+D 2008-01-10T03:46:36
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -92,11 +92,11 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
 F src/delete.c 4f760fb7e9b0bb3cf05534bb9d43ea9e726b7e74
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c 27971029714d4b24081cf20b35e7c96d0e148311
+F src/expr.c 522ba17fa6253a98dc6451e600341277ea43d5c6
 F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
 F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c 8630ee92dac91944c9f7b75847fa4ef74292b220
+F src/insert.c b8406b40cc1cac732932ef587cbc0da006bfd68b
 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
@@ -131,12 +131,12 @@ F src/pragma.c bc6063d91d56a8b3cdad9e3478bba86700759cc4
 F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
-F src/select.c 7b88e17052dce3c89530cd6be014505b00d6ff4c
+F src/select.c 095296a572c296c9ce718768c6c984d33b239e5a
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
 F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
 F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h c2866ab4a8eb42e4daffe30d19afc82952ed67c1
+F src/sqliteInt.h 0606321d38df78adef2325e0b51cd3963731f290
 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
@@ -605,7 +605,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 1134c5ea7116bb2f342ccf09548d075c308c427b
-R 965fc5391bf9a2a36bfcbb9b6a1fc252
+P 05fbca91085cb1b271a05e62181596b4f6f1bb9e
+R 44353c14eaa458d109462754e477c6c2
 U drh
-Z b84d4a6ab04978dba07488e081c74e60
+Z d88167e0b41893f49eaf4061856356de
index 1374695cbbc5b272469b5ae7329a0259e52d2d50..486aad7ba657a6143ef83ad03c1db779119e48e8 100644 (file)
@@ -1 +1 @@
-05fbca91085cb1b271a05e62181596b4f6f1bb9e
\ No newline at end of file
+173698c963473ab1b9db88b23a2de82e4097b96d
\ No newline at end of file
index 39004b15ce8162c51d78cbb1400186bbba20f5c8..c1cb722c5dd6bc401dd84b091f443bc1c726b242 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.340 2008/01/09 23:04:12 drh Exp $
+** $Id: expr.c,v 1.341 2008/01/10 03:46:36 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1610,8 +1610,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){
       int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
       sqlite3VdbeUsesBtree(v, iDb);
 
-      sqlite3VdbeAddOp1(v, OP_SCopy, iMem);
-      iAddr = sqlite3VdbeAddOp2(v, OP_If, 0, iMem);
+      iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
       sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
 
       sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
@@ -1647,8 +1646,7 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){
           iDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
           sqlite3VdbeUsesBtree(v, iDb);
 
-          sqlite3VdbeAddOp1(v, OP_SCopy, iMem);
-          iAddr = sqlite3VdbeAddOp2(v, OP_If, 0, iMem);
+          iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem);
           sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
   
           sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
@@ -1704,10 +1702,9 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
   */
   if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
     int mem = ++pParse->nMem;
-    sqlite3VdbeAddOp1(v, OP_SCopy, mem);
-    testAddr = sqlite3VdbeAddOp0(v, OP_If);
+    sqlite3VdbeAddOp1(v, OP_If, mem);
+    testAddr = sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
     assert( testAddr>0 || pParse->db->mallocFailed );
-    sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
   }
 
   switch( pExpr->op ){
@@ -1783,8 +1780,8 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
           ** this code only executes once.  Because for a non-constant
           ** expression we need to rerun this code each time.
           */
-          if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){
-            sqlite3VdbeChangeToNoop(v, testAddr-1, 3);
+          if( testAddr && !sqlite3ExprIsConstant(pE2) ){
+            sqlite3VdbeChangeToNoop(v, testAddr-1, 2);
             testAddr = 0;
           }
 
@@ -1830,7 +1827,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
   }
 
   if( testAddr ){
-    sqlite3VdbeJumpHere(v, testAddr);
+    sqlite3VdbeJumpHere(v, testAddr-1);
   }
 
   return;
@@ -2178,7 +2175,12 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
       nId = pExpr->token.n;
       pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
       assert( pDef!=0 );
-      nExpr = sqlite3ExprCodeExprList(pParse, pList, 0);
+      if( pList ){
+        nExpr = pList->nExpr;
+        sqlite3ExprCodeExprList(pParse, pList, 0);
+      }else{
+        nExpr = 0;
+      }
 #ifndef SQLITE_OMIT_VIRTUALTABLE
       /* Possibly overload the function if the first argument is
       ** a virtual table column.
@@ -2402,9 +2404,10 @@ void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){
 
 /*
 ** Generate code that pushes the value of every element of the given
-** expression list onto the stack.
+** expression list onto the stack if target==0 or into a sequence of
+** registers beginning at target.
 **
-** Return the number of elements pushed onto the stack.
+** Return the number of elements evaluated.
 */
 int sqlite3ExprCodeExprList(
   Parse *pParse,     /* Parsing context */
@@ -2413,12 +2416,13 @@ int sqlite3ExprCodeExprList(
 ){
   struct ExprList_item *pItem;
   int i, n, incr = 1;
-  if( pList==0 ) return 0;
+  assert( pList!=0 || pParse->db->mallocFailed );
+  if( pList==0 ){
+    return 0;
+  }
+  assert( target>=0 );
   n = pList->nExpr;
-  if( target<0 ){
-    target = pParse->nMem+1;
-    pParse->nMem += n;
-  }else if( target==0 ){
+  if( target==0 ){
     incr = 0;
   }
   for(pItem=pList->a, i=n; i>0; i--, pItem++){
@@ -2888,3 +2892,41 @@ int sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){
   }
   return nErr;
 }
+
+/*
+** Allocate or deallocate temporary use registers during code generation.
+*/
+int sqlite3GetTempReg(Parse *pParse){
+  if( pParse->nTempReg ){
+    return pParse->aTempReg[--pParse->nTempReg];
+  }else{
+    return ++pParse->nMem;
+  }
+}
+void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
+  if( pParse->nTempReg<sizeof(pParse->aTempReg)/sizeof(pParse->aTempReg[0]) ){
+    pParse->aTempReg[pParse->nTempReg++] = iReg;
+  }
+}
+
+/*
+** Allocate or deallocate a block of nReg consecutive registers
+*/
+int sqlite3GetTempRange(Parse *pParse, int nReg){
+  int i;
+  if( nReg<=pParse->nRangeReg ){
+    i  = pParse->iRangeReg;
+    pParse->iRangeReg += nReg;
+    pParse->nRangeReg -= nReg;
+  }else{
+    i = pParse->nMem+1;
+    pParse->nMem += nReg;
+  }
+  return i;
+}
+void sqlite3ReleaseTempRange(Parse *pParse, int iReg, int nReg){
+  if( nReg>pParse->nRangeReg ){
+    pParse->nRangeReg = nReg;
+    pParse->iRangeReg = iReg;
+  }
+}
index b9931abab1b8f11948086dfbe3b1c5b80c9f5a3c..72585705d57741b453fa68a0107df44337d681cd 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.220 2008/01/09 23:04:12 drh Exp $
+** $Id: insert.c,v 1.221 2008/01/10 03:46:36 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1107,9 +1107,7 @@ void sqlite3GenerateConstraintChecks(
     }
     
     if( isUpdate ){
-      sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-1);
-      sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
-      j2 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0);
+      j2 = sqlite3VdbeAddOp3(v, OP_Eq, regRowid, 0, regRowid-1);
     }
     j3 = sqlite3VdbeAddOp3(v, OP_NotExists, baseCur, 0, regRowid);
     switch( onError ){
@@ -1127,8 +1125,7 @@ void sqlite3GenerateConstraintChecks(
       case OE_Replace: {
         sqlite3GenerateRowIndexDelete(v, pTab, baseCur, 0);
         if( isUpdate ){
-          sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
-          sqlite3VdbeAddOp2(v, OP_MoveGe, baseCur, 0);
+          sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-hasTwoRowids);
         }
         seenReplace = 1;
         break;
@@ -1142,8 +1139,7 @@ void sqlite3GenerateConstraintChecks(
     sqlite3VdbeJumpHere(v, j3);
     if( isUpdate ){
       sqlite3VdbeJumpHere(v, j2);
-      sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-1);
-      sqlite3VdbeAddOp2(v, OP_MoveGe, baseCur, 0);
+      sqlite3VdbeAddOp3(v, OP_MoveGe, baseCur, 0, regRowid-1);
     }
   }
 
index 794b9af6f3e2ac2a2910060f24f09adca377fe65..f7ab87c9eecdb9442e04b51ad78fddb9a1648107 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.395 2008/01/09 23:04:12 drh Exp $
+** $Id: select.c,v 1.396 2008/01/10 03:46:36 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -397,11 +397,16 @@ static void pushOntoSorter(
   Select *pSelect        /* The whole SELECT statement */
 ){
   Vdbe *v = pParse->pVdbe;
-  sqlite3ExprCodeExprList(pParse, pOrderBy, 0);
-  sqlite3VdbeAddOp1(v, OP_Sequence, pOrderBy->iECursor);
-  sqlite3VdbeAddOp1(v, OP_Pull, pOrderBy->nExpr + 1);
-  sqlite3VdbeAddOp1(v, OP_MakeRecord, pOrderBy->nExpr + 2);
-  sqlite3VdbeAddOp1(v, OP_IdxInsert, pOrderBy->iECursor);
+  int nExpr = pOrderBy->nExpr;
+  int regBase = sqlite3GetTempRange(pParse, nExpr+2);
+  int regRecord = sqlite3GetTempReg(pParse);
+  sqlite3ExprCodeExprList(pParse, pOrderBy, regBase);
+  sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
+  sqlite3VdbeAddOp2(v, OP_Move, 0, regBase+nExpr+1);
+  sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nExpr + 2, regRecord);
+  sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
+  sqlite3ReleaseTempReg(pParse, regRecord);
+  sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
   if( pSelect->iLimit>=0 ){
     int addr1, addr2;
     addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, pSelect->iLimit+1);
@@ -3002,8 +3007,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
     ExprList *pList = pF->pExpr->pList;
     if( pList ){
       nArg = pList->nExpr;
-      sqlite3ExprCodeExprList(pParse, pList, 0);
-      regAgg = sqlite3StackToReg(pParse, nArg);
+      regAgg = sqlite3GetTempRange(pParse, nArg);
+      sqlite3ExprCodeExprList(pParse, pList, regAgg);
     }else{
       nArg = 0;
       regAgg = 0;
@@ -3029,6 +3034,7 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
     sqlite3VdbeAddOp4(v, OP_AggStep, 0, regAgg, pF->iMem,
                       (void*)pF->pFunc, P4_FUNCDEF);
     sqlite3VdbeChangeP5(v, nArg);
+    sqlite3ReleaseTempRange(pParse, regAgg, nArg);
     if( addrNext ){
       sqlite3VdbeResolveLabel(v, addrNext);
     }
@@ -3545,18 +3551,38 @@ int sqlite3Select(
         ** then loop over the sorting index in order to get the output
         ** in sorted order
         */
+        int regBase;
+        int regRecord;
+        int nCol;
+        int nGroupBy;
+
         groupBySort = 1;
-        sqlite3ExprCodeExprList(pParse, pGroupBy, 0);
-        sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx, 0);
-        j = pGroupBy->nExpr+1;
+        nGroupBy = pGroupBy->nExpr;
+        nCol = nGroupBy + 1;
+        j = nGroupBy+1;
+        for(i=0; i<sAggInfo.nColumn; i++){
+          if( sAggInfo.aCol[i].iSorterColumn>=j ){
+            nCol++;
+            j++;
+          }
+        }
+        regBase = sqlite3GetTempRange(pParse, nCol);
+        sqlite3ExprCodeExprList(pParse, pGroupBy, regBase);
+        sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy);
+        j = nGroupBy+1;
         for(i=0; i<sAggInfo.nColumn; i++){
           struct AggInfo_col *pCol = &sAggInfo.aCol[i];
-          if( pCol->iSorterColumn<j ) continue;
-          sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn,pCol->iTable,0);
-          j++;
+          if( pCol->iSorterColumn>=j ){
+            sqlite3ExprCodeGetColumn(v, pCol->pTab, pCol->iColumn, pCol->iTable,
+                                     j + regBase);
+            j++;
+          }
         }
-        sqlite3VdbeAddOp2(v, OP_MakeRecord, j, 0);
-        sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, 0);
+        regRecord = sqlite3GetTempReg(pParse);
+        sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nCol, regRecord);
+        sqlite3VdbeAddOp2(v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord);
+        sqlite3ReleaseTempReg(pParse, regRecord);
+        sqlite3ReleaseTempRange(pParse, regBase, nCol);
         sqlite3WhereEnd(pWInfo);
         sqlite3VdbeAddOp2(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
         VdbeComment((v, "GROUP BY sort"));
index ef1aab0d9a8ce7fd0608aba6ae8e3030ca4dda7f..6f6842acde04cd394f17c5ebacd09f18181e4c1f 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.645 2008/01/09 23:04:12 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.646 2008/01/10 03:46:36 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1399,6 +1399,10 @@ struct Parse {
   u8 checkSchema;      /* Causes schema cookie check after an error */
   u8 nested;           /* Number of nested calls to the parser/code generator */
   u8 parseError;       /* True after a parsing error.  Ticket #1794 */
+  u8 nTempReg;         /* Number of temporary registers in aTempReg[] */
+  int aTempReg[8];     /* Holding area for temporary registers */
+  int nRangeReg;       /* Size of the temporary register block */
+  int iRangeReg;       /* First register in temporary register block */
   int nErr;            /* Number of errors seen */
   int nTab;            /* Number of previously allocated VDBE cursors */
   int nMem;            /* Number of memory cells used so far */
@@ -1692,6 +1696,10 @@ void sqlite3DequoteExpr(sqlite3*, Expr*);
 int sqlite3KeywordCode(const unsigned char*, int);
 int sqlite3RunParser(Parse*, const char*, char **);
 void sqlite3FinishCoding(Parse*);
+int sqlite3GetTempReg(Parse*);
+void sqlite3ReleaseTempReg(Parse*,int);
+int sqlite3GetTempRange(Parse*,int);
+void sqlite3ReleaseTempRange(Parse*,int,int);
 Expr *sqlite3Expr(sqlite3*, int, Expr*, Expr*, const Token*);
 Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
 Expr *sqlite3RegisterExpr(Parse*,Token*);