/ Check-in [4fe879d4]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:In the amalgamation, allocate the parser engine object from stack rather than from heap, for improved performance. This only happens in the amalgamation, since otherwise the sqlite3RunParser() routine does not know the object size.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 4fe879d4b5da6ae0688a7a99004683a234966597
User & Date: drh 2017-01-28 20:46:37
Context
2017-01-30
11:38
Fix building with SQLITE_OMIT_FOREIGN_KEY defined. check-in: e93d2c49 user: dan tags: trunk
2017-01-28
20:46
In the amalgamation, allocate the parser engine object from stack rather than from heap, for improved performance. This only happens in the amalgamation, since otherwise the sqlite3RunParser() routine does not know the object size. check-in: 4fe879d4 user: drh tags: trunk
19:53
Fix a couple comment typos. No changes to code. check-in: 2a2e7d86 user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/parse.y.

    61     61   
    62     62   /*
    63     63   ** Indicate that sqlite3ParserFree() will never be called with a null
    64     64   ** pointer.
    65     65   */
    66     66   #define YYPARSEFREENEVERNULL 1
    67     67   
           68  +/*
           69  +** In the amalgamation, the parse.c file generated by lemon and the
           70  +** tokenize.c file are concatenated.  In that case, sqlite3RunParser()
           71  +** has access to the the size of the yyParser object and so the parser
           72  +** engine can be allocated from stack.  In that case, only the
           73  +** sqlite3ParserInit() and sqlite3ParserFinalize() routines are invoked
           74  +** and the sqlite3ParserAlloc() and sqlite3ParserFree() routines can be
           75  +** omitted.
           76  +*/
           77  +#ifdef SQLITE_AMALGAMATION
           78  +# define sqlite3Parser_ENGINEALWAYSONSTACK 1
           79  +#endif
           80  +
    68     81   /*
    69     82   ** Alternative datatype for the argument to the malloc() routine passed
    70     83   ** into sqlite3ParserAlloc().  The default is size_t.
    71     84   */
    72     85   #define YYMALLOCARGTYPE  u64
    73     86   
    74     87   /*

Changes to src/sqliteInt.h.

  4069   4069   int sqlite3Stat4Column(sqlite3*, const void*, int, int, sqlite3_value**);
  4070   4070   char sqlite3IndexColumnAffinity(sqlite3*, Index*, int);
  4071   4071   #endif
  4072   4072   
  4073   4073   /*
  4074   4074   ** The interface to the LEMON-generated parser
  4075   4075   */
  4076         -void *sqlite3ParserAlloc(void*(*)(u64));
  4077         -void sqlite3ParserFree(void*, void(*)(void*));
         4076  +#ifndef SQLITE_AMALGAMATION
         4077  +  void *sqlite3ParserAlloc(void*(*)(u64));
         4078  +  void sqlite3ParserFree(void*, void(*)(void*));
         4079  +#endif
  4078   4080   void sqlite3Parser(void*, int, Token, Parse*);
  4079   4081   #ifdef YYTRACKMAXSTACKDEPTH
  4080   4082     int sqlite3ParserStackPeak(void*);
  4081   4083   #endif
  4082   4084   
  4083   4085   void sqlite3AutoLoadExtensions(sqlite3*);
  4084   4086   #ifndef SQLITE_OMIT_LOAD_EXTENSION

Changes to src/tokenize.c.

   477    477     int nErr = 0;                   /* Number of errors encountered */
   478    478     int i;                          /* Loop counter */
   479    479     void *pEngine;                  /* The LEMON-generated LALR(1) parser */
   480    480     int tokenType;                  /* type of the next token */
   481    481     int lastTokenParsed = -1;       /* type of the previous token */
   482    482     sqlite3 *db = pParse->db;       /* The database connection */
   483    483     int mxSqlLen;                   /* Max length of an SQL string */
          484  +#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
          485  +  unsigned char zSpace[sizeof(yyParser)];  /* Space for parser engine object */
          486  +#endif
   484    487   
   485    488     assert( zSql!=0 );
   486    489     mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
   487    490     if( db->nVdbeActive==0 ){
   488    491       db->u1.isInterrupted = 0;
   489    492     }
   490    493     pParse->rc = SQLITE_OK;
   491    494     pParse->zTail = zSql;
   492    495     i = 0;
   493    496     assert( pzErrMsg!=0 );
   494    497     /* sqlite3ParserTrace(stdout, "parser: "); */
          498  +#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
          499  +  pEngine = zSpace;
          500  +  sqlite3ParserInit(pEngine);
          501  +#else
   495    502     pEngine = sqlite3ParserAlloc(sqlite3Malloc);
   496    503     if( pEngine==0 ){
   497    504       sqlite3OomFault(db);
   498    505       return SQLITE_NOMEM_BKPT;
   499    506     }
          507  +#endif
   500    508     assert( pParse->pNewTable==0 );
   501    509     assert( pParse->pNewTrigger==0 );
   502    510     assert( pParse->nVar==0 );
   503    511     assert( pParse->pVList==0 );
   504    512     while( 1 ){
   505    513       assert( i>=0 );
   506    514       if( zSql[i]!=0 ){
................................................................................
   544    552   #ifdef YYTRACKMAXSTACKDEPTH
   545    553     sqlite3_mutex_enter(sqlite3MallocMutex());
   546    554     sqlite3StatusHighwater(SQLITE_STATUS_PARSER_STACK,
   547    555         sqlite3ParserStackPeak(pEngine)
   548    556     );
   549    557     sqlite3_mutex_leave(sqlite3MallocMutex());
   550    558   #endif /* YYDEBUG */
          559  +#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
          560  +  sqlite3ParserFinalize(pEngine);
          561  +#else
   551    562     sqlite3ParserFree(pEngine, sqlite3_free);
          563  +#endif
   552    564     if( db->mallocFailed ){
   553    565       pParse->rc = SQLITE_NOMEM_BKPT;
   554    566     }
   555    567     if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){
   556    568       pParse->zErrMsg = sqlite3MPrintf(db, "%s", sqlite3ErrStr(pParse->rc));
   557    569     }
   558    570     assert( pzErrMsg!=0 );

Changes to tool/lempar.c.

   312    312   ** putting an appropriate #define in the %include section of the input
   313    313   ** grammar.
   314    314   */
   315    315   #ifndef YYMALLOCARGTYPE
   316    316   # define YYMALLOCARGTYPE size_t
   317    317   #endif
   318    318   
          319  +/* Initialize a new parser that has already been allocated.
          320  +*/
          321  +void ParseInit(void *yypParser){
          322  +  yyParser *pParser = (yyParser*)yypParser;
          323  +#ifdef YYTRACKMAXSTACKDEPTH
          324  +  pParser->yyhwm = 0;
          325  +#endif
          326  +#if YYSTACKDEPTH<=0
          327  +  pParser->yytos = NULL;
          328  +  pParser->yystack = NULL;
          329  +  pParser->yystksz = 0;
          330  +  if( yyGrowStack(pParser) ){
          331  +    pParser->yystack = &pParser->yystk0;
          332  +    pParser->yystksz = 1;
          333  +  }
          334  +#endif
          335  +#ifndef YYNOERRORRECOVERY
          336  +  pParser->yyerrcnt = -1;
          337  +#endif
          338  +  pParser->yytos = pParser->yystack;
          339  +  pParser->yystack[0].stateno = 0;
          340  +  pParser->yystack[0].major = 0;
          341  +}
          342  +
          343  +#ifndef Parse_ENGINEALWAYSONSTACK
   319    344   /* 
   320    345   ** This function allocates a new parser.
   321    346   ** The only argument is a pointer to a function which works like
   322    347   ** malloc.
   323    348   **
   324    349   ** Inputs:
   325    350   ** A pointer to the function used to allocate memory.
................................................................................
   327    352   ** Outputs:
   328    353   ** A pointer to a parser.  This pointer is used in subsequent calls
   329    354   ** to Parse and ParseFree.
   330    355   */
   331    356   void *ParseAlloc(void *(*mallocProc)(YYMALLOCARGTYPE)){
   332    357     yyParser *pParser;
   333    358     pParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
   334         -  if( pParser ){
   335         -#ifdef YYTRACKMAXSTACKDEPTH
   336         -    pParser->yyhwm = 0;
   337         -#endif
   338         -#if YYSTACKDEPTH<=0
   339         -    pParser->yytos = NULL;
   340         -    pParser->yystack = NULL;
   341         -    pParser->yystksz = 0;
   342         -    if( yyGrowStack(pParser) ){
   343         -      pParser->yystack = &pParser->yystk0;
   344         -      pParser->yystksz = 1;
   345         -    }
   346         -#endif
   347         -#ifndef YYNOERRORRECOVERY
   348         -    pParser->yyerrcnt = -1;
   349         -#endif
   350         -    pParser->yytos = pParser->yystack;
   351         -    pParser->yystack[0].stateno = 0;
   352         -    pParser->yystack[0].major = 0;
   353         -  }
          359  +  if( pParser ) ParseInit(pParser);
   354    360     return pParser;
   355    361   }
          362  +#endif /* Parse_ENGINEALWAYSONSTACK */
          363  +
   356    364   
   357    365   /* The following function deletes the "minor type" or semantic value
   358    366   ** associated with a symbol.  The symbol can be either a terminal
   359    367   ** or nonterminal. "yymajor" is the symbol code, and "yypminor" is
   360    368   ** a pointer to the value to be deleted.  The code used to do the 
   361    369   ** deletions is derived from the %destructor and/or %token_destructor
   362    370   ** directives of the input grammar.
................................................................................
   402    410         yyTracePrompt,
   403    411         yyTokenName[yytos->major]);
   404    412     }
   405    413   #endif
   406    414     yy_destructor(pParser, yytos->major, &yytos->minor);
   407    415   }
   408    416   
          417  +/*
          418  +** Clear all secondary memory allocations from the parser
          419  +*/
          420  +void ParseFinalize(void *p){
          421  +  yyParser *pParser = (yyParser*)p;
          422  +  while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
          423  +#if YYSTACKDEPTH<=0
          424  +  if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
          425  +#endif
          426  +}
          427  +
          428  +#ifndef Parse_ENGINEALWAYSONSTACK
   409    429   /* 
   410    430   ** Deallocate and destroy a parser.  Destructors are called for
   411    431   ** all stack elements before shutting the parser down.
   412    432   **
   413    433   ** If the YYPARSEFREENEVERNULL macro exists (for example because it
   414    434   ** is defined in a %include section of the input grammar) then it is
   415    435   ** assumed that the input pointer is never NULL.
   416    436   */
   417    437   void ParseFree(
   418    438     void *p,                    /* The parser to be deleted */
   419    439     void (*freeProc)(void*)     /* Function used to reclaim memory */
   420    440   ){
   421         -  yyParser *pParser = (yyParser*)p;
   422    441   #ifndef YYPARSEFREENEVERNULL
   423         -  if( pParser==0 ) return;
          442  +  if( p==0 ) return;
   424    443   #endif
   425         -  while( pParser->yytos>pParser->yystack ) yy_pop_parser_stack(pParser);
   426         -#if YYSTACKDEPTH<=0
   427         -  if( pParser->yystack!=&pParser->yystk0 ) free(pParser->yystack);
   428         -#endif
   429         -  (*freeProc)((void*)pParser);
          444  +  ParseFinalize(p);
          445  +  (*freeProc)(p);
   430    446   }
          447  +#endif /* Parse_ENGINEALWAYSONSTACK */
   431    448   
   432    449   /*
   433    450   ** Return the peak depth of the stack for a parser.
   434    451   */
   435    452   #ifdef YYTRACKMAXSTACKDEPTH
   436    453   int ParseStackPeak(void *p){
   437    454     yyParser *pParser = (yyParser*)p;