Modify OP_VUpdate to read arguments from a range of memory cells instead of from the stack. (CVS 4668)

FossilOrigin-Name: 955b15a020e9ea6401fe03a36f5139a03ea80b8a
diff --git a/src/delete.c b/src/delete.c
index b97ce70..6e7f85e 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -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.142 2008/01/03 09:51:55 danielk1977 Exp $
+** $Id: delete.c,v 1.143 2008/01/03 17:31:45 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -75,6 +75,24 @@
 }
 
 /*
+** Allocate nVal contiguous memory cells and return the index of the
+** first. Also pop nVal elements from the stack and store them in the 
+** registers. The element on the top of the stack is stored in the
+** register with the largest index.
+*/
+int sqlite3StackToReg(Parse *p, int nVal){
+  int i;
+  int iRet = p->nMem;
+  Vdbe *v = sqlite3GetVdbe(p);
+  assert(v);
+  p->nMem += nVal;
+  for(i=nVal-1; i>=0; i--){
+    sqlite3VdbeAddOp2(v, OP_MemStore, iRet+i, 1);
+  }
+  return iRet;
+}
+
+/*
 ** Generate code that will open a table for reading.
 */
 void sqlite3OpenTable(
@@ -354,8 +372,9 @@
       /* Delete the row */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
       if( IsVirtual(pTab) ){
+        int iReg = sqlite3StackToReg(pParse, 1);
         pParse->pVirtualLock = pTab;
-        sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, 0,
+        sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iReg,
                           (const char*)pTab->pVtab, P4_VTAB);
       }else
 #endif
diff --git a/src/insert.c b/src/insert.c
index 5ef9295..068bc8e 100644
--- a/src/insert.c
+++ b/src/insert.c
@@ -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.205 2008/01/03 11:50:30 danielk1977 Exp $
+** $Id: insert.c,v 1.206 2008/01/03 17:31:45 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -795,8 +795,9 @@
     */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
     if( IsVirtual(pTab) ){
+      int iReg = sqlite3StackToReg(pParse, pTab->nCol+2);
       pParse->pVirtualLock = pTab;
-      sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, 0,
+      sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, iReg,
                      (const char*)pTab->pVtab, P4_VTAB);
     }else
 #endif
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 912a318..fad6ca9 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.633 2008/01/03 11:50:30 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.634 2008/01/03 17:31:45 danielk1977 Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1919,7 +1919,7 @@
 char *sqlite3StrAccumFinish(StrAccum*);
 void sqlite3StrAccumReset(StrAccum*);
 void sqlite3CodeInsert(Parse *, int, u8);
-
+int sqlite3StackToReg(Parse *, int);
 
 /*
 ** The interface to the LEMON-generated parser
diff --git a/src/update.c b/src/update.c
index d7ae939..60fd195 100644
--- a/src/update.c
+++ b/src/update.c
@@ -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.152 2008/01/03 09:51:55 danielk1977 Exp $
+** $Id: update.c,v 1.153 2008/01/03 17:31:45 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -647,8 +647,10 @@
     sqlite3VdbeAddOp2(v, OP_Column, ephemTab, i+1+(pRowid!=0));
   }
   pParse->pVirtualLock = pTab;
-  sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, 0,
-                     (const char*)pTab->pVtab, P4_VTAB);
+  sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, 
+      sqlite3StackToReg(pParse, pTab->nCol+2), 
+      (const char*)pTab->pVtab, P4_VTAB
+  );
   sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr);
   sqlite3VdbeJumpHere(v, addr-1);
   sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
diff --git a/src/vdbe.c b/src/vdbe.c
index 0ecee75..47079cf 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.669 2008/01/03 11:50:30 danielk1977 Exp $
+** $Id: vdbe.c,v 1.670 2008/01/03 17:31:45 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -5198,21 +5198,21 @@
 #endif
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VUpdate P1 P2 P4
+/* Opcode: VUpdate P1 P2 P3 P4
 **
 ** P4 is a pointer to a virtual table object, an sqlite3_vtab structure.
 ** This opcode invokes the corresponding xUpdate method. P2 values
-** are taken from the stack to pass to the xUpdate invocation. The
-** value on the top of the stack corresponds to the p2th element 
-** of the argv array passed to xUpdate.
+** are contiguous memory cells starting at P3 to pass to the xUpdate 
+** invocation. The value in register (P3+P2-1) corresponds to the 
+** p2th element of the argv array passed to xUpdate.
 **
 ** The xUpdate method will do a DELETE or an INSERT or both.
-** The argv[0] element (which corresponds to the P2-th element down
-** on the stack) is the rowid of a row to delete.  If argv[0] is
-** NULL then no deletion occurs.  The argv[1] element is the rowid
-** of the new row.  This can be NULL to have the virtual table
-** select the new rowid for itself.  The higher elements in the
-** stack are the values of columns in the new row.
+** The argv[0] element (which corresponds to memory cell P3)
+** is the rowid of a row to delete.  If argv[0] is NULL then no 
+** deletion occurs.  The argv[1] element is the rowid of the new 
+** row.  This can be NULL to have the virtual table select the new 
+** rowid for itself.  The subsequent elements in the array are 
+** the values of columns in the new row.
 **
 ** If P2==1 then no insert is performed.  argv[0] is the rowid of
 ** a row to delete.
@@ -5233,10 +5233,11 @@
     int i;
     sqlite_int64 rowid;
     Mem **apArg = p->apArg;
-    Mem *pX = &pTos[1-nArg];
-    for(i = 0; i<nArg; i++, pX++){
+    Mem *pX = &p->aMem[pOp->p3];
+    for(i=0; i<nArg; i++){
       storeTypeInfo(pX, 0);
       apArg[i] = pX;
+      pX++;
     }
     if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
     sqlite3VtabLock(pVtab);
@@ -5248,7 +5249,6 @@
       db->lastRowid = rowid;
     }
   }
-  popStack(&pTos, nArg);
   break;
 }
 #endif /* SQLITE_OMIT_VIRTUALTABLE */