From caec2f12a9f60c0e73c45d2fa3e07a023d8d9977 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 7 Jan 2003 02:47:47 +0000 Subject: [PATCH] More optimizations. (CVS 816) FossilOrigin-Name: a362981b20fd33254ad498619eedf75b576682e3 --- manifest | 16 ++++++------- manifest.uuid | 2 +- src/parse.y | 5 ++-- src/tokenize.c | 4 ++-- src/vdbe.c | 65 ++++++++++++++++++++++++++++++++++---------------- 5 files changed, 59 insertions(+), 33 deletions(-) diff --git a/manifest b/manifest index 5f018e7a5b..d720c37623 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Optimizations\sto\sthe\stokenizer.\s(CVS\s815) -D 2003-01-07T01:44:38 +C More\soptimizations.\s(CVS\s816) +D 2003-01-07T02:47:48 F Makefile.in 868c17a1ae1c07603d491274cc8f86c04acf2a1e F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -34,7 +34,7 @@ F src/os.c 740022806209e44cab0abddfb1fee65c77702e21 F src/os.h 09fd96b4d733aae2f3b98b2ae9ceea40b8fd780d F src/pager.c e7d05fa23a61f109c2276bb05be7a8d6721980f1 F src/pager.h 540833e8cb826b80ce2e39aa917deee5e12db626 -F src/parse.y 469c9636ff713e63c00234662209f11668671ae9 +F src/parse.y 427a17888c117cc9cc35311eda0603d55437f02b F src/printf.c 5c50fc1da75c8f5bf432b1ad17d91d6653acd167 F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe F src/select.c cc8640e5d4e3ec1a8de58fde6b2fdd6f846b7263 @@ -48,11 +48,11 @@ F src/test1.c a46e9f61915b32787c5d5a05a4b92e4dacc437d9 F src/test2.c 03f05e984c8e2f2badc44644d42baf72b249096b F src/test3.c c12ea7f1c3fbbd58904e81e6cb10ad424e6fc728 F src/threadtest.c d641a5219e718e18a1a80a50eb9bb549f451f42e -F src/tokenize.c 8eaa8f878aa8c6375b567504736a5047f367ce9b +F src/tokenize.c 7ac1c33e0149647c9eb5959c48992df6906d4809 F src/trigger.c 5ba917fc226b96065108da28186c2efaec53e481 F src/update.c 881e4c8e7c786545da4fd2d95da19252b2e31137 F src/util.c e2d108842e02810d3d3242cac0e024b09cdb3c4a -F src/vdbe.c 1d396c7029487630b16b8a310a8c5440d05945dd +F src/vdbe.c a92cbde50ab9ddd6eeee086531252211ce00e3f9 F src/vdbe.h 754eba497cfe0c3e352b9c101ab2f811f10d0a55 F src/where.c af235636b7bc7f7f42ee1c7162d1958ad0102cab F test/all.test 873d30e25a41b3aa48fec5633a7ec1816e107029 @@ -152,7 +152,7 @@ F www/speed.tcl a20a792738475b68756ea7a19321600f23d1d803 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P b96ec281ff29aad8af340b30c6ff4e129ffeeefb -R eca56f05aef2b5cf05bae2fe3b0da7b4 +P 032b3daa1d3cf3e00a4a6ba0b09624f1aba6445c +R 049c740e00e3ae1c8ab222520497ef43 U drh -Z f083eac995258132bf28df3cbcdc9fef +Z e3868eb77f429973c82f0ac95cfb0d3a diff --git a/manifest.uuid b/manifest.uuid index 85ff51d59d..34e957bf50 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -032b3daa1d3cf3e00a4a6ba0b09624f1aba6445c \ No newline at end of file +a362981b20fd33254ad498619eedf75b576682e3 \ No newline at end of file diff --git a/src/parse.y b/src/parse.y index d6f07ad65a..1df236b0d6 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.85 2002/10/27 19:35:34 drh Exp $ +** @(#) $Id: parse.y,v 1.86 2003/01/07 02:47:48 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -48,7 +48,8 @@ struct LimitVal { ** Then the "b" IdList records the list "a,b,c". */ struct TrigEvent { int a; IdList * b; }; -} + +} // end %include // These are extra tokens used by the lexer but never seen by the // parser. We put them in a rule so that the parser generator will diff --git a/src/tokenize.c b/src/tokenize.c index 191e9f2b64..7e551f9bc5 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.52 2003/01/07 01:44:38 drh Exp $ +** $Id: tokenize.c,v 1.53 2003/01/07 02:47:48 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -442,7 +442,7 @@ int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0); nErr++; - goto abort_parse;cvs + goto abort_parse; } default: { sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse); diff --git a/src/vdbe.c b/src/vdbe.c index 335884776f..8f70c95a5a 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -36,7 +36,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.191 2003/01/06 23:54:06 drh Exp $ +** $Id: vdbe.c,v 1.192 2003/01/07 02:47:48 drh Exp $ */ #include "sqliteInt.h" #include @@ -1313,6 +1313,20 @@ __inline__ unsigned long long int hwtime(void){ } #endif +/* +** The CHECK_FOR_INTERRUPT macro defined here looks to see if the +** sqlite_interrupt() routine has been called. If it has been, then +** processing of the VDBE program is interrupted. +** +** This macro added to every instruction that does a jump in order to +** implement a loop. This test used to be on every single instruction, +** but that meant we more testing that we needed. By only testing the +** flag on jump instructions, we get a (small) speed improvement. +*/ +#define CHECK_FOR_INTERRUPT \ + if( db->flags & SQLITE_Interrupt ) goto abort_due_to_interrupt; + + /* ** Execute the program in the VDBE. ** @@ -1374,6 +1388,7 @@ int sqliteVdbeExec( ** ** Allocation all the stack space we will ever need. */ + sqliteVdbeAddOp(p, OP_Halt, 0, 0); zStack = p->zStack = sqliteMalloc( p->nOp*sizeof(zStack[0]) ); aStack = p->aStack = sqliteMalloc( p->nOp*sizeof(aStack[0]) ); p->tos = -1; @@ -1399,27 +1414,14 @@ int sqliteVdbeExec( } #endif if( sqlite_malloc_failed ) goto no_mem; - for(pc=0; !sqlite_malloc_failed && rc==SQLITE_OK && pcnOp - VERIFY(&& pc>=0); pc++){ + for(pc=0; rc==SQLITE_OK; pc++){ + assert( pc>=0 && pcnOp ); #ifdef VDBE_PROFILE origPc = pc; start = hwtime(); #endif pOp = &p->aOp[pc]; - /* Interrupt processing if requested. - */ - if( db->flags & SQLITE_Interrupt ){ - db->flags &= ~SQLITE_Interrupt; - if( db->magic!=SQLITE_MAGIC_BUSY ){ - rc = SQLITE_MISUSE; - }else{ - rc = SQLITE_INTERRUPT; - } - sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0); - break; - } - /* Only allow tracing if NDEBUG is not defined. */ #ifndef NDEBUG @@ -1466,6 +1468,7 @@ int sqliteVdbeExec( ** the program. */ case OP_Goto: { + CHECK_FOR_INTERRUPT; pc = pOp->p2 - 1; break; } @@ -1535,9 +1538,8 @@ case OP_Halt: { } goto abort_due_to_error; }else{ - pc = p->nOp-1; + goto cleanup; } - break; } /* Opcode: Integer P1 * P3 @@ -3947,6 +3949,7 @@ case OP_FullKey: { } if( amt>NBFS ){ z = sqliteMallocRaw( amt ); + if( z==0 ) goto no_mem; aStack[tos].flags = STK_Str | STK_Dyn; }else{ z = aStack[tos].z; @@ -4043,6 +4046,7 @@ case OP_Next: { Cursor *pC; BtCursor *pCrsr; + CHECK_FOR_INTERRUPT; if( VERIFY( pOp->p1>=0 && pOp->p1nCursor && ) (pCrsr = (pC = &p->aCsr[pOp->p1])->pCursor)!=0 ){ int res; @@ -4317,7 +4321,8 @@ case OP_IntegrityCk: { VERIFY( if( iSet<0 || iSet>=p->nSet ) goto bad_instruction; ) pSet = &p->aSet[iSet]; nRoot = sqliteHashCount(&pSet->hash); - aRoot = sqliteMalloc( sizeof(int)*(nRoot+1) ); + aRoot = sqliteMallocRaw( sizeof(int)*(nRoot+1) ); + if( aRoot==0 ) goto no_mem; for(j=0, i=sqliteHashFirst(&pSet->hash); i; i=sqliteHashNext(i), j++){ toInt((char*)sqliteHashKey(i), &aRoot[j]); } @@ -4378,6 +4383,7 @@ case OP_ListRewind: { */ case OP_ListRead: { Keylist *pKeylist; + CHECK_FOR_INTERRUPT; pKeylist = p->pList; if( pKeylist!=0 ){ VERIFY( @@ -4421,6 +4427,7 @@ case OP_ListPush: { assert(p->keylistStackDepth > 0); p->keylistStack = sqliteRealloc(p->keylistStack, sizeof(Keylist *) * p->keylistStackDepth); + if( p->keylistStack==0 ) goto no_mem; p->keylistStack[p->keylistStackDepth - 1] = p->pList; p->pList = 0; break; @@ -4624,6 +4631,7 @@ case OP_Sort: { */ case OP_SortNext: { Sorter *pSorter = p->pSort; + CHECK_FOR_INTERRUPT; if( pSorter!=0 ){ p->pSort = pSorter->pNext; p->tos++; @@ -4710,6 +4718,7 @@ case OP_FileOpen: { case OP_FileRead: { int n, eol, nField, i, c, nDelim; char *zDelim, *z; + CHECK_FOR_INTERRUPT; if( p->pFile==0 ) goto fileread_jump; nField = pOp->p1; if( nField<=0 ) goto fileread_jump; @@ -4949,6 +4958,7 @@ case OP_AggReset: { AggReset(&p->agg); p->agg.nMem = pOp->p2; p->agg.apFunc = sqliteMalloc( p->agg.nMem*sizeof(p->agg.apFunc[0]) ); + if( p->agg.apFunc==0 ) goto no_mem; break; } @@ -5117,6 +5127,7 @@ case OP_AggGet: { ** in between an AggNext and an AggReset. */ case OP_AggNext: { + CHECK_FOR_INTERRUPT; if( p->agg.pSearch==0 ){ p->agg.pSearch = sqliteHashFirst(&p->agg.hash); }else{ @@ -5243,6 +5254,7 @@ case OP_SetFirst: case OP_SetNext: { Set *pSet; int tos; + CHECK_FOR_INTERRUPT; if( pOp->p1<0 || pOp->p1>=p->nSet ){ if( pOp->opcode==OP_SetFirst ) pc = pOp->p2 - 1; break; @@ -5440,6 +5452,20 @@ abort_due_to_error: sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0); goto cleanup; + /* Jump to here if the sqlite_interrupt() API sets the interrupt + ** flag. + */ +abort_due_to_interrupt: + assert( db->flags & SQLITE_Interrupt ); + db->flags &= ~SQLITE_Interrupt; + if( db->magic!=SQLITE_MAGIC_BUSY ){ + rc = SQLITE_MISUSE; + }else{ + rc = SQLITE_INTERRUPT; + } + sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0); + goto cleanup; + /* Jump to here if a operator is encountered that requires more stack ** operands than are currently available on the stack. */ @@ -5447,7 +5473,6 @@ not_enough_stack: sprintf(zBuf,"%d",pc); sqliteSetString(pzErrMsg, "too few operands on stack at ", zBuf, 0); rc = SQLITE_INTERNAL; - goto cleanup; /* Jump here if an illegal or illformed instruction is executed. */