diff options
author | drh <drh@noemail.net> | 2020-02-07 19:44:13 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2020-02-07 19:44:13 +0000 |
commit | dc4f6fc099b3fd2476f95286503985f1a22370bc (patch) | |
tree | 4270e12b34467a53fe7bffd2462bd572db57201c /src | |
parent | b48c0d59faf3bfd3e1fc0c3bed5557816c36cb7e (diff) | |
download | sqlite-dc4f6fc099b3fd2476f95286503985f1a22370bc.tar.gz sqlite-dc4f6fc099b3fd2476f95286503985f1a22370bc.zip |
During byte-code generation, strive to avoid jumps that merely jump to the
following instruction.
FossilOrigin-Name: bcf876e67e75f6709f2b25683a3952bbbb87c672bb9d7af456feebc0ab9f6c31
Diffstat (limited to 'src')
-rw-r--r-- | src/delete.c | 4 | ||||
-rw-r--r-- | src/fkey.c | 2 | ||||
-rw-r--r-- | src/select.c | 2 | ||||
-rw-r--r-- | src/update.c | 4 | ||||
-rw-r--r-- | src/vdbe.h | 1 | ||||
-rw-r--r-- | src/vdbeaux.c | 28 |
6 files changed, 37 insertions, 4 deletions
diff --git a/src/delete.c b/src/delete.c index 0a83f1b64..60efc9d56 100644 --- a/src/delete.c +++ b/src/delete.c @@ -533,7 +533,9 @@ void sqlite3DeleteFrom( iTabCur, aToOpen, &iDataCur, &iIdxCur); assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur ); assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 ); - if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce); + if( eOnePass==ONEPASS_MULTI ){ + sqlite3VdbeJumpHereOrPopInst(v, iAddrOnce); + } } /* Set up a loop over the rowids/primary-keys that were found in the diff --git a/src/fkey.c b/src/fkey.c index 9698d343c..7bc20fed0 100644 --- a/src/fkey.c +++ b/src/fkey.c @@ -658,7 +658,7 @@ static void fkScanChildren( /* Clean up the WHERE clause constructed above. */ sqlite3ExprDelete(db, pWhere); if( iFkIfZero ){ - sqlite3VdbeJumpHere(v, iFkIfZero); + sqlite3VdbeJumpHereOrPopInst(v, iFkIfZero); } } diff --git a/src/select.c b/src/select.c index 595b6eb6b..6f8d45c4e 100644 --- a/src/select.c +++ b/src/select.c @@ -5493,7 +5493,7 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){ pAggInfo->directMode = 0; if( addrHitTest ){ - sqlite3VdbeJumpHere(v, addrHitTest); + sqlite3VdbeJumpHereOrPopInst(v, addrHitTest); } } diff --git a/src/update.c b/src/update.c index 61b1740b4..d54a6cb9f 100644 --- a/src/update.c +++ b/src/update.c @@ -616,7 +616,9 @@ void sqlite3Update( } sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur, aToOpen, 0, 0); - if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); + if( addrOnce ){ + sqlite3VdbeJumpHereOrPopInst(v, addrOnce); + } } /* Top of the update loop */ diff --git a/src/vdbe.h b/src/vdbe.h index bfde25873..482331eff 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -230,6 +230,7 @@ void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3); void sqlite3VdbeChangeP5(Vdbe*, u16 P5); void sqlite3VdbeJumpHere(Vdbe*, int addr); +void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr); int sqlite3VdbeChangeToNoop(Vdbe*, int addr); int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op); #ifdef SQLITE_DEBUG diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 52959a43e..2a4741573 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1065,6 +1065,34 @@ void sqlite3VdbeJumpHere(Vdbe *p, int addr){ sqlite3VdbeChangeP2(p, addr, p->nOp); } +/* +** Change the P2 operand of the jump instruction at addr so that +** the jump lands on the next opcode. Or if the jump instruction was +** the previous opcode (and is thus a no-op) then simply back up +** the next instruction counter by one slot so that the jump is +** overwritten by the next inserted opcode. +** +** This routine is an optimization of sqlite3VdbeJumpHere() that +** strives to omit useless byte-code like this: +** +** 7 Once 0 8 0 +** 8 ... +*/ +void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){ + if( addr==p->nOp-1 ){ + assert( p->aOp[addr].opcode==OP_Once + || p->aOp[addr].opcode==OP_If + || p->aOp[addr].opcode==OP_FkIfZero ); + assert( p->aOp[addr].p4type==0 ); +#ifdef SQLITE_VDBE_COVERAGE + sqlite3VdbeGetOp(v,-1)->iSrcLine = 0; /* Erase VdbeCoverage() macros */ +#endif + p->nOp--; + }else{ + sqlite3VdbeChangeP2(p, addr, p->nOp); + } +} + /* ** If the input FuncDef structure is ephemeral, then free it. If |