/ Check-in [75c095ee]
Login

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

Overview
Comment:Reorganize code to remove a few of the branches introduced into the critical sqlite3DbMallocXXX() path by the previous commit.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | calloc
Files: files | file ages | folders
SHA1: 75c095ee463c0c76e9637edccd33e807f837eb4e
User & Date: dan 2012-07-18 11:28:51
Context
2012-07-18
16:07
Remove another branch from the DbMalloc() paths. check-in: defd828e user: dan tags: calloc
11:28
Reorganize code to remove a few of the branches introduced into the critical sqlite3DbMallocXXX() path by the previous commit. check-in: 75c095ee user: dan tags: calloc
2012-07-17
19:32
Enhance the custom memory allocation interface to allow the user to specify a calloc() function. check-in: 8752237d user: dan tags: calloc
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/malloc.c.

255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
...
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
...
384
385
386
387
388
389
390
391


392

393
394
395
396
397
398
399
...
593
594
595
596
597
598
599































600
601
602
603
604
605
606
607
608
...
610
611
612
613
614
615
616
617
618
619
620
621
622
623

624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643


644

645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672




673
674















675
676
677
678
679
680
681
682
  mem0.alarmArg = pArg;
}

/*
** Do a memory allocation with statistics and alarms.  Assume the
** lock is already held.
*/
static int mallocWithAlarm(
  void *(*xAlloc)(int),          /* Memory allocation function */
  int n,                         /* Bytes of memory to allocate */
  void **pp                      /* OUT: Pointer to allocation */
){
  int nFull;
  void *p;

  assert( sqlite3_mutex_held(mem0.mutex) );
  assert( xAlloc==sqlite3GlobalConfig.m.xMalloc 
       || xAlloc==sqlite3GlobalConfig.m.xCalloc 
................................................................................
  }
#endif
  if( p ){
    nFull = sqlite3MallocSize(p);
    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
    sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
  }
  *pp = p;
  return nFull;
}

/*
** Use allocator function xAlloc to allocate n bytes of memory.
*/
static void *memAllocate(
  void *(*xAlloc)(int),           /* Memory allocation function */
................................................................................
    ** signed integer value might cause an integer overflow inside of the
    ** xMalloc().  Hence we limit the maximum size to 0x7fffff00, giving
    ** 255 bytes of overhead.  SQLite itself will never use anything near
    ** this amount.  The only way to reach the limit is with sqlite3_malloc() */
    p = 0;
  }else if( sqlite3GlobalConfig.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    mallocWithAlarm(xAlloc, n, &p);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    p = xAlloc(n);
  }
  assert( EIGHT_BYTE_ALIGNMENT(p) );  /* IMP: R-04675-44850 */
  return p;
}
................................................................................
    mem0.nScratchFree--;
    sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
    sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    if( sqlite3GlobalConfig.bMemstat ){
      sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
      n = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n, &p);


      if( p ) sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);

      sqlite3_mutex_leave(mem0.mutex);
    }else{
      sqlite3_mutex_leave(mem0.mutex);
      p = sqlite3GlobalConfig.m.xMalloc(n);
    }
    sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
  }
................................................................................
#ifndef SQLITE_OMIT_AUTOINIT
  if( sqlite3_initialize() ) return 0;
#endif
  return sqlite3Realloc(pOld, n);
}

/*































** Allocate and, if bZero is true, zero memory. If the allocation 
** fails, set the mallocFailed flag in the connection pointer.
**
** If db!=0 and db->mallocFailed is true (indicating a prior malloc
** failure on the same database connection) then always return 0.
** Hence for a particular database connection, once malloc starts
** failing, it fails consistently until mallocFailed is reset.
** This is an important assumption.  There are many places in the
** code that do things like this:
................................................................................
**         int *a = (int*)sqlite3DbMallocRaw(db, 100);
**         int *b = (int*)sqlite3DbMallocRaw(db, 200);
**         if( b ) a[10] = 9;
**
** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
** that all prior mallocs (ex: "a") worked too.
*/
static void *dbMalloc(sqlite3 *db, int n, int bZero){
  void *p;
  assert( db==0 || sqlite3_mutex_held(db->mutex) );
  assert( db==0 || db->pnBytesFreed==0 );
#ifndef SQLITE_OMIT_LOOKASIDE
  if( db ){
    LookasideSlot *pBuf;

    if( db->mallocFailed ){
      return 0;
    }
    if( db->lookaside.bEnabled ){
      if( n>db->lookaside.sz ){
        db->lookaside.anStat[1]++;
      }else if( (pBuf = db->lookaside.pFree)==0 ){
        db->lookaside.anStat[2]++;
      }else{
        db->lookaside.pFree = pBuf->pNext;
        db->lookaside.nOut++;
        db->lookaside.anStat[0]++;
        if( db->lookaside.nOut>db->lookaside.mxOut ){
          db->lookaside.mxOut = db->lookaside.nOut;
        }
        if( bZero ) memset(pBuf, 0, n);
        return (void*)pBuf;
      }
    }
  }


#else

  if( db && db->mallocFailed ){
    return 0;
  }
#endif
  if( bZero ){
    p = sqlite3MallocZero(n);
  }else{
    p = sqlite3Malloc(n);
  }
  if( !p && db ){
    db->mallocFailed = 1;
  }
  sqlite3MemdebugSetType(p, MEMTYPE_DB |
         ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
  return p;
} 

/*
** Allocate and zero memory. If the allocation fails, set the 
** mallocFailed flag in the connection pointer.
*/
void *sqlite3DbMallocZero(sqlite3 *db, int n){
  return dbMalloc(db, n, 1);
}

/*
** Allocate memory. If the allocation fails, make the mallocFailed 
** flag in the connection pointer.




*/
void *sqlite3DbMallocRaw(sqlite3 *db, int n){















  return dbMalloc(db, n, 0);
}

/*
** Resize the block of memory pointed to by p to n bytes. If the
** resize fails, set the mallocFailed flag in the connection object.
*/
void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){







|

|
<







 







|
|







 







|







 







|
>
>
|
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|







 







|

<
<
<
|
<
>
|
|
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
>
>
|
>
|
<
|
<
<
<
<
<

<
<
|



<
<
<
<
<
<
<
<





>
>
>
>


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|







255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
...
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
...
643
644
645
646
647
648
649
650
651



652

653
654
655






656











657
658
659
660
661

662





663


664
665
666
667








668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
  mem0.alarmArg = pArg;
}

/*
** Do a memory allocation with statistics and alarms.  Assume the
** lock is already held.
*/
static void *mallocWithAlarm(
  void *(*xAlloc)(int),          /* Memory allocation function */
  int n                          /* Bytes of memory to allocate */

){
  int nFull;
  void *p;

  assert( sqlite3_mutex_held(mem0.mutex) );
  assert( xAlloc==sqlite3GlobalConfig.m.xMalloc 
       || xAlloc==sqlite3GlobalConfig.m.xCalloc 
................................................................................
  }
#endif
  if( p ){
    nFull = sqlite3MallocSize(p);
    sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
    sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
  }

  return p;
}

/*
** Use allocator function xAlloc to allocate n bytes of memory.
*/
static void *memAllocate(
  void *(*xAlloc)(int),           /* Memory allocation function */
................................................................................
    ** signed integer value might cause an integer overflow inside of the
    ** xMalloc().  Hence we limit the maximum size to 0x7fffff00, giving
    ** 255 bytes of overhead.  SQLite itself will never use anything near
    ** this amount.  The only way to reach the limit is with sqlite3_malloc() */
    p = 0;
  }else if( sqlite3GlobalConfig.bMemstat ){
    sqlite3_mutex_enter(mem0.mutex);
    p = mallocWithAlarm(xAlloc, n);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    p = xAlloc(n);
  }
  assert( EIGHT_BYTE_ALIGNMENT(p) );  /* IMP: R-04675-44850 */
  return p;
}
................................................................................
    mem0.nScratchFree--;
    sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
    sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
    sqlite3_mutex_leave(mem0.mutex);
  }else{
    if( sqlite3GlobalConfig.bMemstat ){
      sqlite3StatusSet(SQLITE_STATUS_SCRATCH_SIZE, n);
      p = mallocWithAlarm(sqlite3GlobalConfig.m.xMalloc, n);
      if( p ){
        n = sqlite3MallocSize(p);
        sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, n);
      }
      sqlite3_mutex_leave(mem0.mutex);
    }else{
      sqlite3_mutex_leave(mem0.mutex);
      p = sqlite3GlobalConfig.m.xMalloc(n);
    }
    sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
  }
................................................................................
#ifndef SQLITE_OMIT_AUTOINIT
  if( sqlite3_initialize() ) return 0;
#endif
  return sqlite3Realloc(pOld, n);
}

/*
** Attempt to allocate an n byte block from the lookaside buffer of
** connection db. If successful, return a pointer to the new allocation.
** Otherwise, return a NULL pointer.
*/
#ifndef SQLITE_OMIT_LOOKASIDE
static void *lookasideAlloc(sqlite3 *db, int n){
  if( db->lookaside.bEnabled ){
    if( n>db->lookaside.sz ){
      db->lookaside.anStat[1]++;
    }else{
      LookasideSlot *pBuf;
      if( (pBuf = db->lookaside.pFree)==0 ){
        db->lookaside.anStat[2]++;
      }else{
        db->lookaside.pFree = pBuf->pNext;
        db->lookaside.nOut++;
        db->lookaside.anStat[0]++;
        if( db->lookaside.nOut>db->lookaside.mxOut ){
          db->lookaside.mxOut = db->lookaside.nOut;
        }
      }
      return (void*)pBuf;
    }
  }
  return 0;
}
#else
# define lookasideAlloc(x,y) 0
#endif

/*
** Allocate and zero memory. If the allocation fails, set the 
** mallocFailed flag in the connection pointer.
**
** If db!=0 and db->mallocFailed is true (indicating a prior malloc
** failure on the same database connection) then always return 0.
** Hence for a particular database connection, once malloc starts
** failing, it fails consistently until mallocFailed is reset.
** This is an important assumption.  There are many places in the
** code that do things like this:
................................................................................
**         int *a = (int*)sqlite3DbMallocRaw(db, 100);
**         int *b = (int*)sqlite3DbMallocRaw(db, 200);
**         if( b ) a[10] = 9;
**
** In other words, if a subsequent malloc (ex: "b") worked, it is assumed
** that all prior mallocs (ex: "a") worked too.
*/
void *sqlite3DbMallocZero(sqlite3 *db, int n){
  void *p;



  if( db==0 ){

    p = memAllocate(sqlite3GlobalConfig.m.xCalloc, n);
  }else if( db->mallocFailed ){
    p = 0;






  }else{











    if( (p = lookasideAlloc(db, n)) ){
      memset(p, 0, n);
    }else{
      p = memAllocate(sqlite3GlobalConfig.m.xCalloc, n);
      if( !p ) db->mallocFailed = 1;

    }





  }



  sqlite3MemdebugSetType(p, MEMTYPE_DB |
         ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
  return p;








}

/*
** Allocate memory. If the allocation fails, make the mallocFailed 
** flag in the connection pointer.
**
** If db!=0 and db->mallocFailed is true (indicating a prior malloc
** failure on the same database connection) then always return 0.
** See also comments above sqlite3DbMallocZero() for details.
*/
void *sqlite3DbMallocRaw(sqlite3 *db, int n){
  void *p;
  if( db==0 ){
    p = memAllocate(sqlite3GlobalConfig.m.xMalloc, n);
  }else if( db->mallocFailed ){
    p = 0;
  }else{
    p = lookasideAlloc(db, n);
    if( !p ){
      p = memAllocate(sqlite3GlobalConfig.m.xMalloc, n);
      if( !p ) db->mallocFailed = 1;
    }
  }

  sqlite3MemdebugSetType(p, MEMTYPE_DB |
         ((db && db->lookaside.bEnabled) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
  return p;
}

/*
** Resize the block of memory pointed to by p to n bytes. If the
** resize fails, set the mallocFailed flag in the connection object.
*/
void *sqlite3DbRealloc(sqlite3 *db, void *p, int n){

Changes to src/mem1.c.

98
99
100
101
102
103
104
105
106
107







108
109
110
111
112
113

114
115

116
117
118
119
120
121
122
123
124
125

126
127
128
129
130
131

132
133
134
135
136







137
138












139
140
141

142
143
144
145
146
147
148
#else
# undef SQLITE_MALLOCSIZE
#endif

#endif /* __APPLE__ or not __APPLE__ */

/*
** Like malloc() (if bZero==0) or calloc() (if bZero!=0), except remember 
** the size of the allocation so that we can find it later using 
** sqlite3MemSize().







**
** For this low-level routine, we are guaranteed that nByte>0 because
** cases of nByte<=0 will be intercepted and dealt with by higher level
** routines.
*/
static void *memMalloc(int nByte, int bZero){

#ifdef SQLITE_MALLOCSIZE
  void *p = (bZero ? SQLITE_CALLOC( nByte ) : SQLITE_MALLOC( nByte ));

  if( p==0 ){
    testcase( sqlite3GlobalConfig.xLog!=0 );
    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
  }
  return p;
#else
  sqlite3_int64 *p;
  assert( nByte>0 );
  nByte = ROUND8(nByte);
  p = (bZero ? SQLITE_CALLOC( nByte+8 ) : SQLITE_MALLOC( nByte+8 ));

  if( p ){
    p[0] = nByte;
    p++;
  }else{
    testcase( sqlite3GlobalConfig.xLog!=0 );
    sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);

  }
  return (void *)p;
#endif
}








static void *sqlite3MemMalloc(int nByte){
  return memMalloc(nByte, 0);












}
static void *sqlite3MemCalloc(int nByte){
  return memMalloc(nByte, 1);

}

/*
** Like free() but works for allocations obtained from sqlite3MemMalloc()
** or sqlite3MemRealloc().
**
** For this low-level routine, we already know that pPrior!=0 since







|
|
|
>
>
>
>
>
>
>





|
>

<
>

<
<
<
<

<
<

<
>

|
<

<
|
>


<


>
>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
|
<
<
>







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

123
124




125


126

127
128
129

130

131
132
133
134

135
136
137
138
139
140
141
142
143
144

145
146
147
148
149
150
151
152
153
154
155
156
157


158
159
160
161
162
163
164
165
#else
# undef SQLITE_MALLOCSIZE
#endif

#endif /* __APPLE__ or not __APPLE__ */

/*
** A memory allocation of nByte bytes has failed. Log an error message
** using sqlite3_log().
*/
static void logAllocationError(int nByte){
  testcase( sqlite3GlobalConfig.xLog!=0 );
  sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes of memory", nByte);
}

/*
** Allocate nByte bytes of memory.
**
** For this low-level routine, we are guaranteed that nByte>0 because
** cases of nByte<=0 will be intercepted and dealt with by higher level
** routines.
*/
static void *sqlite3MemMalloc(int nByte){
  i64 *p;
#ifdef SQLITE_MALLOCSIZE

  p = SQLITE_MALLOC(nByte);
  if( p==0 ){




#else


  nByte = ROUND8(nByte);

  p = SQLITE_MALLOC(nByte+8);
  if( p ){
    *(p++) = (i64)nByte;

  }else{

#endif
    logAllocationError(nByte);
  }
  return (void *)p;

}

/*
** Allocate and zero nByte bytes of memory.
**
** For this low-level routine, we are guaranteed that nByte>0 because
** cases of nByte<=0 will be intercepted and dealt with by higher level
** routines.
*/
static void *sqlite3MemCalloc(int nByte){

  i64 *p;
#ifdef SQLITE_MALLOCSIZE
  p = SQLITE_CALLOC(nByte);
  if( p==0 ){
#else
  nByte = ROUND8(nByte);
  p = SQLITE_CALLOC(nByte+8);
  if( p ){
    *(p++) = (i64)nByte;
  }else{
#endif
    logAllocationError(nByte);
  }


  return (void *)p;
}

/*
** Like free() but works for allocations obtained from sqlite3MemMalloc()
** or sqlite3MemRealloc().
**
** For this low-level routine, we already know that pPrior!=0 since