]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Change OP_Return such that if P3 is 1, the Return is a no-op when the
authordrh <>
Sun, 17 Apr 2022 20:30:52 +0000 (20:30 +0000)
committerdrh <>
Sun, 17 Apr 2022 20:30:52 +0000 (20:30 +0000)
P1 register contains a NULL.

FossilOrigin-Name: c90602328a4b26f06d76c5343d29ebb7a782186c86ea88f5965a41040cff5346

manifest
manifest.uuid
src/expr.c
src/vdbe.c
src/where.c
src/whereInt.h

index 3be5508455624c01a22a52ea90a568efab9e7462..ff4937a42311608576a2f11e45a3710fc8c87e0e 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Further\simprovements\sto\sUSING()\sprocessing\sfor\sRIGHT\sand\sFULL\sJOINs.\s\sAll\ncurrently\sknown\sissues\sare\snow\sresolved.\s\sPerformace\sis\simproved.
-D 2022-04-17T18:46:17.120
+C Change\sOP_Return\ssuch\sthat\sif\sP3\sis\s1,\sthe\sReturn\sis\sa\sno-op\swhen\sthe\nP1\sregister\scontains\sa\sNULL.
+D 2022-04-17T20:30:52.124
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -503,7 +503,7 @@ F src/date.c 15082566229d4b1e5f24fdb490bf9bcc68824b911d70e3573ef075a1b9e2d26f
 F src/dbpage.c 90661a87e1db8bfbc8d2ebbdcd3749651ddb287c555c07a28fb17c7c591ffb68
 F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
 F src/delete.c a8e844af211a48b13b5b358be77a12c860c6a557c21990ad51a548e2536500ce
-F src/expr.c 5f4fa51dde6af4f7a622f4f6b04bcdae400bf7ef0090c37b9a03740113ad71c0
+F src/expr.c efde3f5034b94999ce34458ddcc43d9a82de7b43cf3a0d377b74585af7f140a1
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 94927f9b46d72a9cb858c208febf04ceb0a3270c5fa5fd0b7f436cf16e09f72a
 F src/func.c a3407a6fbb0d4088d8d502e46f0ace63e0aeae7467ae23a9ca9815bbf9239761
@@ -624,7 +624,7 @@ F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
 F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
 F src/util.c 602fe229f32a96ceccae4f40824129669582096f7c355f53dbac156c9fecef23
 F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3
-F src/vdbe.c b72147e70498ad005eece5c6336bfa1b9eaff09a673044eb866df8e402d1f12f
+F src/vdbe.c 1b48646ce4824b4e3aa31b1aa278200b87b4218fedc2f606a25f1a467a978c87
 F src/vdbe.h 89f5edb1422c8783a0b29db836e409876f2b3e847f78e2b21b1fbcc48a93f85f
 F src/vdbeInt.h ef43f7fdc5fde29fc3fd29c506c12830f366178fdb4edbbf0cbc3dfbd1278b5f
 F src/vdbeapi.c 354c893f1500cf524cc45c32879b9c68893a28b77e3442c24668d6afe4236217
@@ -639,8 +639,8 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
 F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
 F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
-F src/where.c 963c06826218535bcebc8a8c41dcb2a8abf3cd340022d5b2cb503e7ce328cc47
-F src/whereInt.h ea1e4b6639c4c32246f4c54b733143df76109894adf08bedee4f3999ece62c2d
+F src/where.c cbbfdcbf701cc018f1a688da53b082f9cf2ea067ecadd0648ecd6c4244ecc4da
+F src/whereInt.h eecce79edc6f7005f91f35be6b18b7053f794e1b50e95bcd06a2d537fc176734
 F src/wherecode.c cb747d628e8fdc0396529c07be9c772c2978016a723eba9c3329f8ef5e4411f1
 F src/whereexpr.c 174d4ad5be165c610c907abb779ef4a97974d22b84e1ce7898d2d9f6947249e5
 F src/window.c 42a71595263dbd8ef8248218e4fc7d4b5ddccece52146ad48e079342d93f6f8f
@@ -1948,8 +1948,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P bd5fd68435ff068c18d7d46b33cf7591263a03c32a917a7df7c087b08c573cc8
-R 59e0d103b473769389ca9e8aa4f28bed
+P 9fd3f22e2228dfba127f6ffe549109f3a4e910fa124adcc9c5483931bd6d5cd7
+R 18079ef5a0c4d399c9c19e3618838c8a
 U drh
-Z de5ba2466670ff117c1fafe3df9d0ad6
+Z 584bf1a379a2119bed4485fb42b41022
 # Remove this line to create a well-formed Fossil manifest.
index 8f146051429c95a81d32cd2887ddc1c11cea1e2e..133b551cdc97ba927e0d4757bc47df2d80f30c22 100644 (file)
@@ -1 +1 @@
-9fd3f22e2228dfba127f6ffe549109f3a4e910fa124adcc9c5483931bd6d5cd7
\ No newline at end of file
+c90602328a4b26f06d76c5343d29ebb7a782186c86ea88f5965a41040cff5346
\ No newline at end of file
index 4e036c93432b6c63b9e4ccc1b5b2779e9c46fb7d..b90d537d8d143d9ae08bab8d325430932c1a84b3 100644 (file)
@@ -3175,9 +3175,9 @@ void sqlite3CodeRhsOfIN(
     assert( ExprUseYSub(pExpr) );
     assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
             || pParse->nErr );
-    sqlite3VdbeAddOp2(v, OP_Return, pExpr->y.sub.regReturn,
-                      pExpr->y.sub.iAddr);
-    sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
+    sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn,
+                      pExpr->y.sub.iAddr, 1);
+    VdbeCoverage(v);
     sqlite3ClearTempRegCache(pParse);
   }
 }
@@ -3306,9 +3306,9 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
   assert( ExprUseYSub(pExpr) );
   assert( sqlite3VdbeGetOp(v,pExpr->y.sub.iAddr-1)->opcode==OP_BeginSubrtn
           || pParse->nErr );
-  sqlite3VdbeAddOp2(v, OP_Return, pExpr->y.sub.regReturn,
-                    pExpr->y.sub.iAddr);
-  sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
+  sqlite3VdbeAddOp3(v, OP_Return, pExpr->y.sub.regReturn,
+                    pExpr->y.sub.iAddr, 1);
+  VdbeCoverage(v);
   sqlite3ClearTempRegCache(pParse);
   return rReg;
 }
index 283151d1fc5bdf0a0389ad55ccd761f9607518b8..ca94f06419624cebe601b52758736e87f6a97f53 100644 (file)
@@ -988,12 +988,17 @@ case OP_Gosub: {            /* jump */
 
 /* Opcode:  Return P1 P2 P3 * *
 **
-** Jump to the next instruction after the address stored in register P1.
+** Jump to the address stored in register P1.  If P1 is a return address
+** register, then this accomplishes a return from a subroutine.
 **
-** It used to be that after the jump, register P1 would become undefined.
-** However, for the subroutine used for the inner loop of a RIGHT JOIN,
-** it is useful for R1 register to be unchanged, so that is what happens
-** now.
+** If P3 is 1, then the jump is only taken if register P1 holds an integer
+** values, otherwise execution falls through to the next opcode, and the
+** OP_Return becomes a no-op. If P3 is 0, then register P1 must hold an
+** integer or else an assert() is raised.  P3 should be set to 1 when
+** this opcode is used in combination with OP_BeginSubrtn, and set to 0
+** otherwise.
+**
+** The value in register P1 is unchanged by this opcode.
 **
 ** P2 is not used by the byte-code engine.  However, if P2 is positive
 ** and also less than the current address, then the "EXPLAIN" output
@@ -1002,16 +1007,15 @@ case OP_Gosub: {            /* jump */
 ** in the subroutine from which this opcode is returnning.  Thus the P2
 ** value is a byte-code indentation hint.  See tag-20220407a in
 ** wherecode.c and shell.c.
-**
-** P3 is not used by the byte-code engine.  However, the code generator
-** sets P3 to address of the associated OP_BeginSubrtn opcode, if there is
-** one.
 */
 case OP_Return: {           /* in1 */
   pIn1 = &aMem[pOp->p1];
-  assert( pIn1->flags==MEM_Int );
-  pOp = &aOp[pIn1->u.i];
-  /*  pIn1->flags = MEM_Undefined; */
+  if( pIn1->flags & MEM_Int ){
+    if( pOp->p3 ) VdbeBranchTaken(1, 2);
+    pOp = &aOp[pIn1->u.i];
+  }else if( ALWAYS(pOp->p3) ){
+    VdbeBranchTaken(0, 2);
+  }
   break;
 }
 
@@ -1197,22 +1201,11 @@ case OP_Halt: {
   goto vdbe_return;
 }
 
-/* Opcode: BeginSubrtn P1 P2 * * *
-** Synopsis: r[P2]=P1
-**
-** Mark the beginning of a subroutine by loading the integer value P1
-** into register r[P2].  The P2 register is used to store the return
-** address of the subroutine call.
-**
-** This opcode is identical to OP_Integer.  It has a different name
-** only to make the byte code easier to read and verify.
-*/
 /* Opcode: Integer P1 P2 * * *
 ** Synopsis: r[P2]=P1
 **
 ** The 32-bit integer value P1 is written into register P2.
 */
-case OP_BeginSubrtn:
 case OP_Integer: {         /* out2 */
   pOut = out2Prerelease(p, pOp);
   pOut->u.i = pOp->p1;
@@ -1319,6 +1312,28 @@ case OP_String: {          /* out2 */
   break;
 }
 
+/* Opcode: BeginSubrtn * P2 * * *
+** Synopsis: r[P2]=NULL
+**
+** Mark the beginning of a subroutine that can be entered in-line
+** or that can be called using OP_Gosub.  The subroutine should
+** be terminated by an OP_Return instruction that has a P1 operand that
+** is the same as the P2 operand to this opcode and that has P3 set to 1.
+** If the subroutine is entered in-line, then the OP_Return will simply
+** fall through.  But if the subroutine is entered using OP_Gosub, then
+** the OP_Return will jump back to the first instruction after the OP_Gosub.
+**
+** This routine works by loading a NULL into the P2 register.  When the
+** return address register contains a NULL, the OP_Return instruction is
+** a no-op that simply falls through to the next instruction (assuming that
+** the OP_Return opcode has a P3 value of 1).  Thus if the subroutine is
+** entered in-line, then the OP_Return will cause in-line execution to
+** continue.  But if the subroutine is entered via OP_Gosub, then the
+** OP_Return will cause a return to the address following the OP_Gosub.
+**
+** This opcode is identical to OP_Null.  It has a different name
+** only to make the byte code easier to read and verify.
+*/
 /* Opcode: Null P1 P2 P3 * *
 ** Synopsis: r[P2..P3]=NULL
 **
@@ -1331,6 +1346,7 @@ case OP_String: {          /* out2 */
 ** NULL values will not compare equal even if SQLITE_NULLEQ is set on
 ** OP_Ne or OP_Eq.
 */
+case OP_BeginSubrtn:
 case OP_Null: {           /* out2 */
   int cnt;
   u16 nullFlag;
index 7b37db21582393a8ebce9cdb7b49c76ec021e4c8..8755ccd2ce1c9bd125b9d25dfe1b550a6c612502 100644 (file)
@@ -5883,7 +5883,7 @@ WhereInfo *sqlite3WhereBegin(
       pRJ->regBloom = ++pParse->nMem;
       sqlite3VdbeAddOp2(v, OP_Blob, 65536, pRJ->regBloom);
       pRJ->regReturn = ++pParse->nMem;
-      pRJ->addrInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, pRJ->regReturn);
+      sqlite3VdbeAddOp2(v, OP_Null, 0, pRJ->regReturn);
       assert( pTab==pTabItem->pTab );
       if( HasRowid(pTab) ){
         KeyInfo *pInfo;
@@ -6022,12 +6022,10 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
       /* Terminate the subroutine that forms the interior of the loop of
       ** the RIGHT JOIN table */
       WhereRightJoin *pRJ = pLevel->pRJ;
-      int addrHere = sqlite3VdbeCurrentAddr(v);
-      sqlite3VdbeChangeP1(v, pRJ->addrSubrtn-1, addrHere);
-      sqlite3VdbeChangeP1(v, pRJ->addrInit, addrHere);
       sqlite3VdbeResolveLabel(v, pLevel->addrCont);
       pLevel->addrCont = 0;
-      sqlite3VdbeAddOp2(v, OP_Return, pRJ->regReturn, pRJ->addrSubrtn);
+      sqlite3VdbeAddOp3(v, OP_Return, pRJ->regReturn, pRJ->addrSubrtn, 1);
+      VdbeCoverage(v);
       assert( pParse->withinRJSubrtn>0 );
       pParse->withinRJSubrtn--;
     }
index c8a188f80c55efe251e571219a64dab14db00665..acc9ec3ddd15b5d8dca02fddb484e9f27bc92913 100644 (file)
@@ -52,7 +52,6 @@ struct WhereRightJoin {
   int regBloom;        /* Bloom filter for iRJMatch */
   int regReturn;       /* Return register for the interior subroutine */
   int addrSubrtn;      /* Starting address for the interior subroutine */
-  int addrInit;        /* OP_Integer used for early init of regReturn */
 };
 
 /*