]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
An alternative, experimental lookaside memory allocator that uses two
authorsperry <sperry@noemail.net>
Wed, 9 Oct 2019 17:06:38 +0000 (17:06 +0000)
committersperry <sperry@noemail.net>
Wed, 9 Oct 2019 17:06:38 +0000 (17:06 +0000)
different slot sizes.

FossilOrigin-Name: 5ba8cee8f710eb2a6844d5de0d975c207e5645754e30211a4cb5a4869248b693

20 files changed:
Makefile.in
Makefile.msc
main.mk
manifest
manifest.uuid
src/analyze.c
src/build.c
src/fkey.c
src/lookaside.c [new file with mode: 0644]
src/lookaside.h [new file with mode: 0644]
src/main.c
src/malloc.c
src/parse.y
src/prepare.c
src/select.c
src/sqliteInt.h
src/status.c
tool/mksqlite3c-noext.tcl
tool/mksqlite3c.tcl
tool/mksqlite3internalh.tcl

index cadc2eda9973c77ce25f01e2f9ef762d22c792f5..3d3011f7d801a8fed08f515d4815bf681ba3d73a 100644 (file)
@@ -234,6 +234,8 @@ SRC = \
   $(TOP)/src/insert.c \
   $(TOP)/src/legacy.c \
   $(TOP)/src/loadext.c \
+  $(TOP)/src/lookaside.c \
+  $(TOP)/src/lookaside.h \
   $(TOP)/src/main.c \
   $(TOP)/src/malloc.c \
   $(TOP)/src/mem0.c \
@@ -525,6 +527,7 @@ HDR = \
    $(TOP)/src/hash.h \
    $(TOP)/src/hwtime.h \
    keywordhash.h \
+   $(TOP)/src/lookaside.h \
    $(TOP)/src/msvc.h \
    $(TOP)/src/mutex.h \
    opcodes.h \
@@ -869,6 +872,9 @@ legacy.lo:  $(TOP)/src/legacy.c $(HDR)
 loadext.lo:    $(TOP)/src/loadext.c $(HDR)
        $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/loadext.c
 
+lookaside.lo:  $(TOP)/src/lookaside.c $(HDR)
+       $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/lookaside.c
+
 main.lo:       $(TOP)/src/main.c $(HDR)
        $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/main.c
 
index 01d20d2d65f98e71b21b2219e61d1e70fe821d1d..c4d537a2918514da70a73b5bc16df3643d2b83a1 100644 (file)
@@ -1290,6 +1290,7 @@ SRC00 = \
   $(TOP)\src\insert.c \
   $(TOP)\src\legacy.c \
   $(TOP)\src\loadext.c \
+  $(TOP)\src\lookaside.c \
   $(TOP)\src\main.c \
   $(TOP)\src\malloc.c \
   $(TOP)\src\mem0.c \
@@ -1360,6 +1361,7 @@ SRC04 = \
   $(TOP)\src\btreeInt.h \
   $(TOP)\src\hash.h \
   $(TOP)\src\hwtime.h \
+  $(TOP)\src\lookaside.h \
   $(TOP)\src\msvc.h \
   $(TOP)\src\mutex.h \
   $(TOP)\src\os.h \
@@ -1580,6 +1582,7 @@ HDR = \
    $(TOP)\src\btreeInt.h \
    $(TOP)\src\hash.h \
    $(TOP)\src\hwtime.h \
+   $(TOP)\src\lookaside.h \
    keywordhash.h \
    $(TOP)\src\msvc.h \
    $(TOP)\src\mutex.h \
@@ -1961,6 +1964,9 @@ legacy.lo:        $(TOP)\src\legacy.c $(HDR)
 loadext.lo:    $(TOP)\src\loadext.c $(HDR)
        $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\loadext.c
 
+lookaside.lo:  $(TOP)\src\lookaside.c $(HDR)
+       $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\lookaside.c
+
 main.lo:       $(TOP)\src\main.c $(HDR)
        $(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\main.c
 
diff --git a/main.mk b/main.mk
index 5462292023700e421ccf0f2221c4db0849c4cf7b..fceb2942adc373b2bcd7b4cfce84590612411863 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -111,6 +111,8 @@ SRC = \
   $(TOP)/src/insert.c \
   $(TOP)/src/legacy.c \
   $(TOP)/src/loadext.c \
+  $(TOP)/src/lookaside.c \
+  $(TOP)/src/lookaside.h \
   $(TOP)/src/main.c \
   $(TOP)/src/malloc.c \
   $(TOP)/src/mem0.c \
@@ -443,6 +445,7 @@ HDR = \
    $(TOP)/src/hash.h \
    $(TOP)/src/hwtime.h \
    keywordhash.h \
+   $(TOP)/src/lookaside.h \
    $(TOP)/src/msvc.h \
    $(TOP)/src/mutex.h \
    opcodes.h \
index d1101db0c5ee86e343aaa02219941e60769d3713..7a32feb0f9bcdf93abbefb729970f0cfa35b4349 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,11 +1,11 @@
-C Fix\sproblems\swith\susing\sthe\sfts5\s'rebuild'\scommand\sinside\sa\stransaction\sthat\scontains\sother\supdates\sof\sthe\ssame\stable.\sFix\sfor\s[e258f008].
-D 2019-10-08T13:34:24.536
+C An\salternative,\sexperimental\slookaside\smemory\sallocator\sthat\suses\stwo\ndifferent\sslot\ssizes.
+D 2019-10-09T17:06:38.567
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
-F Makefile.in 578f123620087ea459aa08fa872810a25ca7c0aaf16331de985bfcddb5f1e747
+F Makefile.in 97473628071905a0496a38e1b0721dda732829c89fa0b87675d877c26d95936a
 F Makefile.linux-gcc f609543700659711fbd230eced1f01353117621dccae7b9fb70daa64236c5241
-F Makefile.msc a463dca3c50d8a36094fe5c8c39077907f530b54edfc5388c66c85e2cfc8dc04
+F Makefile.msc 99a026807172f0e99c982d386a6470c445307a9fd0383aa4692406102ad7e7e4
 F README.md 1514a365ffca3c138e00c5cc839906108a01011a6b082bad19b09781e3aa498a
 F VERSION 4c516d84c2a5f26c477ed34c09ac4136630f71c68139631f2eb591b22eea7cf1
 F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@@ -447,7 +447,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
 F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
-F main.mk 09716d345766a55b25ed157b14786526cf67c761c61d99c53e117196fb3b391a
+F main.mk b939f7fa33486a28466c40dcbd6681b817a66de73aa9e121434e471b16ac731a
 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -460,7 +460,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
 F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
 F src/alter.c 5773b28684a001dcab45adcefa3cbf5e846335c0c8fee0da8a3770cb0123bba8
-F src/analyze.c 481d9cf34a3c70631ef5c416be70033e8d4cd85eb5ad1b37286aed8b0e29e889
+F src/analyze.c 777b22900cfcbb1e87f73b09ac45986c91ed76beea0442cf55fce7eb2bba4228
 F src/attach.c 3ca19504849c2d9be10fc5899d6811f9d6e848665d1a41ffb53df0cd6e7c13ed
 F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06
 F src/backup.c f70077d40c08b7787bfe934e4d1da8030cb0cc57d46b345fba2294b7d1be23ab
@@ -469,7 +469,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
 F src/btree.c fdc4389b271bca30138db27dc2dfb9f52c2a7baaa44845aaf31a3c54663d837f
 F src/btree.h c11446f07ec0e9dc85af8041cb0855c52f5359c8b2a43e47e02a685282504d89
 F src/btreeInt.h 6111c15868b90669f79081039d19e7ea8674013f907710baa3c814dc3f8bfd3f
-F src/build.c 13de2fdabbabcf2e2aaf6443a049fb851d9d3170136c08345468e158ceea3dc6
+F src/build.c 804fd944dde39ae429a913541091785eede543ad6fdbef3eafbb3224c9c329d7
 F src/callback.c 25dda5e1c2334a367b94a64077b1d06b2553369f616261ca6783c48bcb6bda73
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/ctime.c 1b0724e66f95f33b160b1af85caaf9cceb325d22abf39bd24df4f54a73982251
@@ -479,7 +479,7 @@ F src/dbstat.c c12833de69cb655751487d2c5a59607e36be1c58ba1f4bd536609909ad47b319
 F src/delete.c d08c9e01a2664afd12edcfa3a9c6578517e8ff8735f35509582693adbe0edeaf
 F src/expr.c 1e9a6da29e3e13c14783891e867e19a54e2731c6a9b58d011cc4f3b4742a59e4
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
-F src/fkey.c 6271fda51794b569d736eba4097d28f13080cd0c9eb66d5fcecb4b77336fae50
+F src/fkey.c 48921db21c10b7857efe8a9f4dd9dbe7fe931df3eaea0913629e8512924fc8ef
 F src/func.c ed33e38cd642058182a31a3f518f2e34f4bbe53aa483335705c153c4d3e50b12
 F src/global.c a1a8d698762ddd9a1543aac26c1e0029b20fcc3fcb56bfa41ec8cea2368f2798
 F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
@@ -489,8 +489,10 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
 F src/insert.c 40557ebd69f4115e7a273f9304a8ab637a47ce44f3c6923396928f023967b5e8
 F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
 F src/loadext.c 4ddc65ae13c0d93db0ceedc8b14a28c8c260513448b0eb8c5a2ac375e3b6a85d
-F src/main.c 3e01f6a1c96643381b5f9d79e4ff7f2520bc5712197746fb0852283e78cccf66
-F src/malloc.c b7640bcf8992cf2e98447da0d27e372abdc4621a6760418bad6d1470f041ada9
+F src/lookaside.c 3d569191e4f177153524eb376ac18ada6ab49430c15c392291aed033bd7a3203
+F src/lookaside.h 088106f3dc9933f7e9f3570eff86ef29e762ba351027cac733c866a4a5b6244c
+F src/main.c 5771725469dcb97667c647ebd8192073c925d13efdd46f94a84738187fa0a0bb
+F src/malloc.c 7b36b39aae0da3a9253ae5c7396831e45b2afb342a9f22a4afa314fe7e492c9d
 F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
 F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
 F src/mem2.c f1940d9e91948dd6a908fbb9ce3835c36b5d83c3
@@ -514,25 +516,25 @@ F src/os_win.c 035a813cbd17f355bdcad7ab894af214a9c13a1db8aeac902365350b98cd45a7
 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
 F src/pager.c 422fd8cfa59fb9173eff36a95878904a0eeb0dcc62ba49350acc8b1e51c4dc7b
 F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
-F src/parse.y 19c8b65c87a5bec5efcb7eaf44e3178d860bc77baab4b03d7b53b08369ac83bf
+F src/parse.y 916f6f75b929b13fe26b18023a80b9085893ef3f6483611489b5185d7df2d3bf
 F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
 F src/pcache1.c 62714cbd1b7299a6e6a27a587b66b4fd3a836a84e1181e7f96f5c34a50917848
 F src/pragma.c b47bc7db02ab13d04c680aee424466b4e34f4ef5aa7b2e464876ec005806f98f
 F src/pragma.h 40962d65b645bb3f08c1f4c456effd01c6e7f073f68ea25177e0c95e181cff75
-F src/prepare.c fc245d2049e5e9e76738cd403e63c9832ff61c706d19607d2b62a51f1747609c
+F src/prepare.c 5cd97fadcf1b98de8260fd5077abb666929433ec48c533fc6b4b222a64c99276
 F src/printf.c 9be6945837c839ba57837b4bc3af349eba630920fa5532aa518816defe42a7d4
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c e021be0c1c4a2125fa38aabcd8dbb764bf5b2c889a948c30d3708430ec6ccd00
 F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
-F src/select.c f509982c96bb24ccf57a0155fbe1e6184e0b8fb8866a04397dc41baa400e5240
+F src/select.c fd56dee1f38362ba6a1c2b8f07ca4a73e2a195d5b16d562d4264a7cfa061ceeb
 F src/shell.c.in d70bcf630c4073eaa994fa74be98886c781918e794cb8b562be8df10f018e274
 F src/sqlite.h.in 5725a6b20190a1e8d662077a1c1c8ea889ad7be90dd803f914c2de226f5fe6ab
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h cef696ce3293242c67b2339763608427bf72ee66f1f3a05389ac2a7b46001c31
-F src/sqliteInt.h b70ac8e3e7e74838bc45dca1a3b2c3ef4b4e04a49036448bf462cfd657cc663f
+F src/sqliteInt.h 2ce2d769c4accccc58df69de32f935585086e205bb17730ea6f72c11f43dd938
 F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
-F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
+F src/status.c 364babdad7295c0219b398468e0a24374f6e1bf27906837be347ea0538148ce2
 F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
 F src/tclsqlite.c 50c93be3e1c03b4e6cf6756e5197afcfe7f5cd0497d83a7ac317cde09e19b290
 F src/test1.c 17e1395cbddeb9226b756d723a7566b45b43b99a5f9f55afb4ff70888de6ad6f
@@ -1783,10 +1785,10 @@ F tool/mkpragmatab.tcl f115d63ada8171f9da28dc8e34e043a1a159692d46b89f66b6e681140
 F tool/mkshellc.tcl 70a9978e363b0f3280ca9ce1c46d72563ff479c1930a12a7375e3881b7325712
 F tool/mksourceid.c d458f9004c837bee87a6382228ac20d3eae3c49ea3b0a5aace936f8b60748d3b
 F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
-F tool/mksqlite3c-noext.tcl 4f7cfef5152b0c91920355cbfc1d608a4ad242cb819f1aea07f6d0274f584a7f
-F tool/mksqlite3c.tcl 5fed3d75069d8f66f202d3b5200b0cea4aa7108481acd06732a06fdd42eb83a2
+F tool/mksqlite3c-noext.tcl ed9eee26b0a54d38b15e56a8dba7936369306b8b3b359fb13269cfd3bb8df764
+F tool/mksqlite3c.tcl bba4605f267e5884fc8213f1d0b49b4670c6a0852c8e5186bd0b39f8005c9c67
 F tool/mksqlite3h.tcl 080873e3856eceb9d289a08a00c4b30f875ea3feadcbece796bd509b1532792c
-F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
+F tool/mksqlite3internalh.tcl dd425d58d29dedabe24246ed61dd6c0bfd7d9458ca05bb3b9acb46453a043947
 F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
 F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
 F tool/omittest.tcl 27f9413c3343bac200a28d81e8234adb0f5e141c4771893cb19b40235a91f1e0
@@ -1846,7 +1848,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 8ab0aebdb3c2d6fb3160b2c58ce6cc0495a6ddd960878a6395958c837f3d1b71
-R 74814f3b82ccc57c689e36d5b9ae7e28
-U dan
-Z 1ced3dbc55f7a754d800609f44681fb4
+P 238e0835714696aba0631f288fcc30ec5fddb43893d469c6bf017f386b3cddee
+R ff93c002380d3f08d9900baed24887de
+T *branch * 2-size-lookaside
+T *sym-2-size-lookaside *
+T -sym-trunk *
+U sperry
+Z f6212e7bc680bb8a80c6fe2ff4a2e853
index 0913b6b215ccfd594b45df4208852cec7ee7c9f8..2fe8c23022f231832595d6b624fbbb809052511f 100644 (file)
@@ -1 +1 @@
-238e0835714696aba0631f288fcc30ec5fddb43893d469c6bf017f386b3cddee
\ No newline at end of file
+5ba8cee8f710eb2a6844d5de0d975c207e5645754e30211a4cb5a4869248b693
\ No newline at end of file
index 8f73853c85f0f33210da2b63fc25316737bb582e..45b3cf3968bfcff6151314df2586f571e12a4e27 100644 (file)
 */
 #ifndef SQLITE_OMIT_ANALYZE
 #include "sqliteInt.h"
+#include "lookaside.h"
 
 #if defined(SQLITE_ENABLE_STAT4)
 # define IsStat4     1
@@ -1662,7 +1663,7 @@ static int loadStatTbl(
   Index *pPrevIdx = 0;          /* Previous index in the loop */
   IndexSample *pSample;         /* A slot in pIdx->aSample[] */
 
-  assert( db->lookaside.bDisable );
+  assert( sqlite3LookasideDisabled(&db->lookaside) );
   zSql = sqlite3MPrintf(db, zSql1, zDb);
   if( !zSql ){
     return SQLITE_NOMEM_BKPT;
@@ -1773,7 +1774,7 @@ static int loadStatTbl(
 static int loadStat4(sqlite3 *db, const char *zDb){
   int rc = SQLITE_OK;             /* Result codes from subroutines */
 
-  assert( db->lookaside.bDisable );
+  assert( sqlite3LookasideDisabled(&db->lookaside) );
   if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
     rc = loadStatTbl(db,
       "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", 
@@ -1854,9 +1855,9 @@ int sqlite3AnalysisLoad(sqlite3 *db, int iDb){
   /* Load the statistics from the sqlite_stat4 table. */
 #ifdef SQLITE_ENABLE_STAT4
   if( rc==SQLITE_OK ){
-    DisableLookaside;
+    sqlite3LookasideDisable(&db->lookaside);
     rc = loadStat4(db, sInfo.zDatabase);
-    EnableLookaside;
+    sqlite3LookasideEnable(&db->lookaside);
   }
   for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
     Index *pIdx = sqliteHashData(i);
index e4f8d5e3c68c7ff3b5f6ac682b4c758df2ce084e..04b97d2a3b0765769379d5b9ab25cae78839977f 100644 (file)
@@ -23,6 +23,7 @@
 **     ROLLBACK
 */
 #include "sqliteInt.h"
+#include "lookaside.h"
 
 #ifndef SQLITE_OMIT_SHARED_CACHE
 /*
@@ -626,7 +627,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
   ** that no lookaside memory is used in this case either. */
   int nLookaside = 0;
   if( db && !db->mallocFailed && (pTable->tabFlags & TF_Ephemeral)==0 ){
-    nLookaside = sqlite3LookasideUsed(db, 0);
+    nLookaside = sqlite3LookasideUsed(&db->lookaside, 0);
   }
 #endif
 
@@ -662,7 +663,7 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
   sqlite3DbFree(db, pTable);
 
   /* Verify that no lookaside memory was used by schema tables */
-  assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(db,0) );
+  assert( nLookaside==0 || nLookaside==sqlite3LookasideUsed(&db->lookaside,0) );
 }
 void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
   /* Do not delete the table until the reference count reaches zero. */
index 1b86692da75a80b0b6341343d57e4971e26944ab..abe8d287fea3ede398219d9e7c646db0b9144ef8 100644 (file)
@@ -12,6 +12,7 @@
 ** support to compiled SQL statements.
 */
 #include "sqliteInt.h"
+#include "lookaside.h"
 
 #ifndef SQLITE_OMIT_FOREIGN_KEY
 #ifndef SQLITE_OMIT_TRIGGER
@@ -1299,7 +1300,7 @@ static Trigger *fkActionTrigger(
     }
 
     /* Disable lookaside memory allocation */
-    DisableLookaside;
+    sqlite3LookasideDisable(&db->lookaside);
 
     pTrigger = (Trigger *)sqlite3DbMallocZero(db, 
         sizeof(Trigger) +         /* struct Trigger */
@@ -1321,7 +1322,7 @@ static Trigger *fkActionTrigger(
     }
 
     /* Re-enable the lookaside buffer, if it was disabled earlier. */
-    EnableLookaside;
+    sqlite3LookasideEnable(&db->lookaside);
 
     sqlite3ExprDelete(db, pWhere);
     sqlite3ExprDelete(db, pWhen);
diff --git a/src/lookaside.c b/src/lookaside.c
new file mode 100644 (file)
index 0000000..9687536
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+** 2019-10-02
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+**
+** Lookaside memory allocation functions used throughout sqlite.
+*/
+
+#include "sqliteInt.h"
+#include "lookaside.h"
+
+/*
+** Return the number of LookasideSlot elements on the linked list
+*/
+static u32 countLookasideSlots(LookasideSlot *p){
+  u32 cnt = 0;
+  while( p ){
+    p = p->pNext;
+    cnt++;
+  }
+  return cnt;
+}
+
+/*
+** Count the number of slots of lookaside memory that are outstanding
+*/
+int sqlite3LookasideUsed(Lookaside *pLookaside, int *pHighwater){
+  u32 nInit = countLookasideSlots(pLookaside->pInit);
+  u32 nFree = countLookasideSlots(pLookaside->pFree);
+  if( pHighwater ) *pHighwater = pLookaside->nSlot - nInit;
+  return pLookaside->nSlot - (nInit+nFree);
+}
+
+void sqlite3LookasideResetUsed(Lookaside *pLookaside){
+  LookasideSlot *p = pLookaside->pFree;
+  if( p ){
+    while( p->pNext ) p = p->pNext;
+    p->pNext = pLookaside->pInit;
+    pLookaside->pInit = pLookaside->pFree;
+    pLookaside->pFree = 0;
+  }
+}
+
+#ifndef SQLITE_OMIT_LOOKASIDE
+
+static void *lookasideSlotAlloc(Lookaside *pLookaside, u64 n){
+  LookasideSlot *pBuf;
+  if( (pBuf = pLookaside->pFree)!=0 ){
+    pLookaside->pFree = pBuf->pNext;
+    pLookaside->anStat[0]++;
+    return (void*)pBuf;
+  }else if( (pBuf = pLookaside->pInit)!=0 ){
+    pLookaside->pInit = pBuf->pNext;
+    pLookaside->anStat[0]++;
+    return (void*)pBuf;
+  }else{
+    pLookaside->anStat[2]++;
+    return 0;
+  }
+}
+
+static void lookasideSlotFree(Lookaside *pLookaside, void *p){
+  LookasideSlot *pBuf = (LookasideSlot*)p;
+# ifdef SQLITE_DEBUG
+  /* Scribble over the content in the buffer being freed */
+  memset(p, 0xaa, pLookaside->szTrue);
+# endif
+  pBuf->pNext = pLookaside->pFree;
+  pLookaside->pFree = pBuf;
+}
+
+# ifndef SQLITE_OMIT_MINI_LOOKASIDE
+#  ifndef SQLITE_MINI_LOOKASIDE_MIN_SLOT_SIZE
+#   define SQLITE_MINI_LOOKASIDE_MIN_SLOT_SIZE 128
+#  endif
+
+static void *miniLookasideAlloc(Lookaside *pLookaside, u16 n){
+  void *p = 0;
+  LookasideSlot *pSlot;
+  int iMiniSlot;
+  
+  assert( n<=pLookaside->szMini );
+  
+  if( !pLookaside->pMini ){
+    pSlot = lookasideSlotAlloc(pLookaside, pLookaside->szTrue);
+    if( !pSlot ){
+      return p;
+    }
+    bzero(pSlot, sizeof(LookasideSlot));
+    pLookaside->pMini = pSlot;
+  }else{
+    pSlot = pLookaside->pMini;
+    assert( pSlot->bMembership );
+  }
+  
+  assert( pSlot->bMembership < (1<<pLookaside->nMini)-1 );
+
+  iMiniSlot = __builtin_ffs(~pSlot->bMembership) - 1;
+  assert(iMiniSlot < pLookaside->nMini);
+  assert( (pSlot->bMembership&(1<<iMiniSlot))==0 );
+  pSlot->bMembership |= 1<<iMiniSlot;
+
+  p = (char *)pSlot + sizeof(LookasideSlot) + (pLookaside->szMini * iMiniSlot);
+
+  /* Remove slot from pMini if it is full of sub-allocations */
+  if( pSlot->bMembership == (1<<pLookaside->nMini)-1 ){
+    /* Slot is full, dequeue from list */
+    if( pSlot->pNext ){
+      assert( pSlot->pNext->pPrev == pSlot );
+      pSlot->pNext->pPrev = pSlot->pPrev;
+    }
+    if( pSlot->pPrev ){
+      assert( pSlot->pPrev->pNext == pSlot );
+      pSlot->pPrev->pNext = pSlot->pNext;
+    }else{
+      assert( pLookaside->pMini == pSlot );
+      pLookaside->pMini = pSlot->pNext;
+    }
+    pSlot->pNext = pSlot->pPrev = 0;
+  }
+  return p;
+}
+
+static void miniLookasideFree(Lookaside *pLookaside, void *p){
+  int iSlotNum = ((u8*)p - (u8*)pLookaside->pStart) / pLookaside->szTrue;
+  LookasideSlot *pSlot = (LookasideSlot *)(iSlotNum * pLookaside->szTrue + (u8*)pLookaside->pStart);
+  int iMiniSlot = ((u8*)p - ((u8*)pSlot + sizeof(LookasideSlot))) / pLookaside->szMini;
+  
+  assert( pSlot->bMembership );
+  assert( pSlot->bMembership < (1<<pLookaside->nMini) );
+  assert( iMiniSlot<pLookaside->nMini );
+  
+  /* Return slot to pMini list if it was full */
+  if( pSlot->bMembership == (1<<pLookaside->nMini)-1 ){
+    assert( pSlot->pNext == pSlot->pPrev && pSlot->pPrev == 0 );
+    if( pLookaside->pMini ){
+      assert( !pLookaside->pMini->pPrev );
+      pSlot->pNext = pLookaside->pMini;
+      pSlot->pNext->pPrev = pSlot;
+    }
+    pLookaside->pMini = pSlot;
+  }
+  
+  pSlot->bMembership &= ~(1<<iMiniSlot);
+#ifdef SQLITE_DEBUG
+  memset(p, 0xaa, pLookaside->szMini);
+#endif
+  
+  /* Return slot to the lookaside pool if it is empty */
+  if( pSlot->bMembership == 0 ){
+    if( pSlot->pNext ){
+      assert( pSlot->pNext->pPrev == pSlot );
+      pSlot->pNext->pPrev = pSlot->pPrev;
+    }
+    if( pSlot->pPrev ){
+      assert( pSlot->pPrev->pNext == pSlot );
+      pSlot->pPrev->pNext = pSlot->pNext;
+    }else{
+      assert( pLookaside->pMini==pSlot );
+      pLookaside->pMini = pSlot->pNext;
+    }
+    lookasideSlotFree(pLookaside, pSlot);
+  }
+}
+
+# else
+#  define miniLookasideAlloc(A, B) lookasideSlotAlloc(A, B)
+#  define miniLookasideFree(A, B) lookasideSlowFree(A, B)
+# endif /* !SQLITE_OMIT_MINI_LOOKASIDE */
+
+int sqlite3LookasideOpen(void *pBuf, int sz, int cnt, Lookaside *pLookaside){
+  void *pStart;
+
+  if( sqlite3LookasideUsed(pLookaside,0)>0 ){
+    return SQLITE_BUSY;
+  }
+  /* Free any existing lookaside buffer for this handle before
+  ** allocating a new one so we don't have to have space for
+  ** both at the same time.
+  */
+  if( pLookaside->bMalloced ){
+    sqlite3_free(pLookaside->pStart);
+  }
+  /* The size of a lookaside slot after ROUNDDOWN8 needs to be larger
+  ** than sizeof(LookasideSlot) to be useful.
+  */
+  sz = ROUNDDOWN8(sz);  /* IMP: R-33038-09382 */
+  if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
+  if( cnt<0 ) cnt = 0;
+  if( sz==0 || cnt==0 ){
+    sz = 0;
+    pStart = 0;
+  }else if( pBuf==0 ){
+    sqlite3BeginBenignMalloc();
+    pStart = sqlite3Malloc( sz*(sqlite3_int64)cnt );  /* IMP: R-61949-35727 */
+    sqlite3EndBenignMalloc();
+    if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
+  }else{
+    pStart = pBuf;
+  }
+  pLookaside->pStart = pStart;
+  pLookaside->pInit = 0;
+  pLookaside->pFree = 0;
+  pLookaside->sz = (u16)sz;
+  pLookaside->szTrue = (u16)sz;
+#ifndef SQLITE_OMIT_MINILOOKASIDE
+  pLookaside->pMini = 0;
+  pLookaside->nMini = (sz - sizeof(LookasideSlot)) / SQLITE_MINI_LOOKASIDE_MIN_SLOT_SIZE;
+  if( pLookaside->nMini ){
+    pLookaside->szMini = ((sz - sizeof(LookasideSlot)) / pLookaside->nMini) & ~(sizeof(void *) - 1);
+  }else{
+    pLookaside->szMini = 0;
+  }
+#endif /* SQLITE_OMIT_MINILOOKASIDE */
+  if( pStart ){
+    int i;
+    LookasideSlot *p;
+    assert( sz > (int)sizeof(LookasideSlot*) );
+    pLookaside->nSlot = cnt;
+    p = (LookasideSlot*)pStart;
+    for(i=cnt-1; i>=0; i--){
+      p->pNext = pLookaside->pInit;
+      pLookaside->pInit = p;
+      p = (LookasideSlot*)&((u8*)p)[sz];
+    }
+    pLookaside->pEnd = p;
+    pLookaside->bDisable = 0;
+    pLookaside->bMalloced = pBuf==0 ?1:0;
+  }else{
+    pLookaside->pStart = 0;
+    pLookaside->pEnd = 0;
+    pLookaside->bDisable = 1;
+    pLookaside->bMalloced = 0;
+    pLookaside->nSlot = 0;
+  }
+  return SQLITE_OK;
+}
+
+void sqlite3LookasideClose(Lookaside *pLookaside){
+  assert( sqlite3LookasideUsed(pLookaside,0)==0 );
+  if( pLookaside->bMalloced ){
+    sqlite3_free(pLookaside->pStart);
+  }
+}
+
+int sqlite3IsLookaside(Lookaside *pLookaside, void *p){
+  return SQLITE_WITHIN(p, pLookaside->pStart, pLookaside->pEnd);
+}
+
+/*
+** Returns a pointer to a region at least n bytes in size, or NULL if the
+** lookaside allocator has exhausted its available memory.
+*/
+void *sqlite3LookasideAlloc(Lookaside *pLookaside, u64 n){
+  if( n>pLookaside->sz ){
+    if( !pLookaside->bDisable ){
+      pLookaside->anStat[1]++;
+    }
+    return 0;
+  }
+  if( n<=pLookaside->szMini && pLookaside->nMini > 1 ){
+    return miniLookasideAlloc(pLookaside, n);
+  }
+  return lookasideSlotAlloc(pLookaside, n);
+}
+
+/*
+** Free memory previously obtained from sqlite3LookasideAlloc().
+*/
+void sqlite3LookasideFree(Lookaside *pLookaside, void *p){
+  assert( sqlite3IsLookaside(pLookaside, p) );
+  if( ((u8*)p - (u8*)pLookaside->pStart) % pLookaside->szTrue == 0 ){
+    lookasideSlotFree(pLookaside, p);
+  }else{
+    miniLookasideFree(pLookaside, p);
+  }
+}
+
+/*
+** Return the size of a memory allocation previously obtained from
+** sqlite3LookasideAlloc().
+*/
+int sqlite3LookasideSize(Lookaside *pLookaside, void *p){
+  assert(sqlite3IsLookaside(pLookaside, p));
+
+# ifndef SQLITE_OMIT_MINI_LOOKASIDE
+  if( ((u8*)p - (u8*)pLookaside->pStart) % pLookaside->szTrue != 0 ){
+    return pLookaside->szMini;
+  }else
+#endif /* SQLITE_OMIT_MINI_LOOKASIDE */
+  {
+    return pLookaside->szTrue;
+  }
+}
+
+#endif /* !SQLITE_OMIT_LOOKASIDE */
diff --git a/src/lookaside.h b/src/lookaside.h
new file mode 100644 (file)
index 0000000..641b251
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+** 2019-10-02
+**
+** The author disclaims copyright to this source code.  In place of
+** a legal notice, here is a blessing:
+**
+**    May you do good and not evil.
+**    May you find forgiveness for yourself and forgive others.
+**    May you share freely, never taking more than you give.
+**
+*************************************************************************
+** Header file for the lookaside allocator
+**
+** This header defines the interface to the lookaside allocator.
+** The lookaside allocator implements a two-size memory allocator using a
+** buffer provided at initialization-time to exploit the fact that 75% of
+** SQLite's allocations are <=128B.
+*/
+#ifndef SQLITE_LOOKASIDE_H
+#define SQLITE_LOOKASIDE_H
+
+/*
+** Count the number of slots of lookaside memory that are outstanding
+*/
+int sqlite3LookasideUsed(Lookaside *pLookaside, int *pHighwater);
+
+void sqlite3LookasideResetUsed(Lookaside *pLookaside);
+
+#define sqlite3LookasideDisable(pLookaside) do{(pLookaside)->bDisable++;\
+  (pLookaside)->sz=0;}while(0)
+#define sqlite3LookasideEnable(pLookaside) do{(pLookaside)->bDisable--;\
+  (pLookaside)->sz=(pLookaside)->bDisable?0:(pLookaside)->szTrue;} while(0)
+#define sqlite3LookasideEnableCnt(pLookaside, CNT) do{(pLookaside)->bDisable -= (CNT);\
+  (pLookaside)->sz=(pLookaside)->bDisable?0:(pLookaside)->szTrue;} while(0)
+#define sqlite3LookasideDisabled(pLookaside) ((pLookaside)->bDisable)
+
+# ifndef SQLITE_OMIT_LOOKASIDE
+
+/*
+** Set up a lookaside allocator.
+** Returns SQLITE_OK on success.
+** If lookaside is already active, return SQLITE_BUSY.
+**
+** If pStart is NULL the space for the lookaside memory is obtained from
+** sqlite3_malloc(). If pStart is not NULL then it is sz*cnt bytes of memory
+** to use for the lookaside memory.
+*/
+int sqlite3LookasideOpen(
+  void *pBuf,           /* NULL or sz*cnt bytes of memory */
+  int sz,               /* Number of bytes in each lookaside slot */
+  int cnt,              /* Number of slots */
+  Lookaside *pLookaside /* Preallocated space for the Lookaside */
+);
+
+/* Reset and close the lookaside object */
+void sqlite3LookasideClose(Lookaside *pLookaside);
+
+/*
+** Returns TRUE if p is a lookaside memory allocation from db
+*/
+int sqlite3IsLookaside(Lookaside *pLookaside, void *p);
+
+/*
+** Returns a pointer to a region at least n bytes in size, or NULL if the
+** lookaside allocator has exhausted its available memory.
+*/
+void *sqlite3LookasideAlloc(Lookaside *pLookaside, u64 n);
+
+/*
+** Free memory previously obtained from sqlite3LookasideAlloc().
+*/
+void sqlite3LookasideFree(Lookaside *pLookaside, void *p);
+
+/*
+** Return the size of a memory allocation previously obtained from
+** sqlite3LookasideAlloc().
+*/
+int sqlite3LookasideSize(Lookaside *pLookaside, void *p);
+
+# else
+#  define sqlite3LookasideOpen(A, B, C, D) SQLITE_OK
+#  define sqlite3LookasideClose(A)
+#  define sqlite3IsLookaside(A, B) 0
+#  define sqlite3LookasideAlloc(A, B) 0
+#  define sqlite3LookasideFree(A, B) assert(0);
+#  define sqlite3LookasideSize(A, B) -1
+# endif
+
+#endif /* SQLITE_LOOKASIDE_H */
index 39ab4a8fee80426b5ecfd3ceecbf4b4bc3a30393..f182b43a66ea7a92eb06c40947cc5672238a19c7 100644 (file)
@@ -15,6 +15,7 @@
 ** accessed by users of the library.
 */
 #include "sqliteInt.h"
+#include "lookaside.h"
 
 #ifdef SQLITE_ENABLE_FTS3
 # include "fts3.h"
@@ -669,79 +670,6 @@ int sqlite3_config(int op, ...){
   return rc;
 }
 
-/*
-** Set up the lookaside buffers for a database connection.
-** Return SQLITE_OK on success.  
-** If lookaside is already active, return SQLITE_BUSY.
-**
-** The sz parameter is the number of bytes in each lookaside slot.
-** The cnt parameter is the number of slots.  If pStart is NULL the
-** space for the lookaside memory is obtained from sqlite3_malloc().
-** If pStart is not NULL then it is sz*cnt bytes of memory to use for
-** the lookaside memory.
-*/
-static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
-#ifndef SQLITE_OMIT_LOOKASIDE
-  void *pStart;
-  
-  if( sqlite3LookasideUsed(db,0)>0 ){
-    return SQLITE_BUSY;
-  }
-  /* Free any existing lookaside buffer for this handle before
-  ** allocating a new one so we don't have to have space for 
-  ** both at the same time.
-  */
-  if( db->lookaside.bMalloced ){
-    sqlite3_free(db->lookaside.pStart);
-  }
-  /* The size of a lookaside slot after ROUNDDOWN8 needs to be larger
-  ** than a pointer to be useful.
-  */
-  sz = ROUNDDOWN8(sz);  /* IMP: R-33038-09382 */
-  if( sz<=(int)sizeof(LookasideSlot*) ) sz = 0;
-  if( cnt<0 ) cnt = 0;
-  if( sz==0 || cnt==0 ){
-    sz = 0;
-    pStart = 0;
-  }else if( pBuf==0 ){
-    sqlite3BeginBenignMalloc();
-    pStart = sqlite3Malloc( sz*(sqlite3_int64)cnt );  /* IMP: R-61949-35727 */
-    sqlite3EndBenignMalloc();
-    if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
-  }else{
-    pStart = pBuf;
-  }
-  db->lookaside.pStart = pStart;
-  db->lookaside.pInit = 0;
-  db->lookaside.pFree = 0;
-  db->lookaside.sz = (u16)sz;
-  db->lookaside.szTrue = (u16)sz;
-  if( pStart ){
-    int i;
-    LookasideSlot *p;
-    assert( sz > (int)sizeof(LookasideSlot*) );
-    db->lookaside.nSlot = cnt;
-    p = (LookasideSlot*)pStart;
-    for(i=cnt-1; i>=0; i--){
-      p->pNext = db->lookaside.pInit;
-      db->lookaside.pInit = p;
-      p = (LookasideSlot*)&((u8*)p)[sz];
-    }
-    db->lookaside.pEnd = p;
-    db->lookaside.bDisable = 0;
-    db->lookaside.bMalloced = pBuf==0 ?1:0;
-  }else{
-    db->lookaside.pStart = db;
-    db->lookaside.pEnd = db;
-    db->lookaside.bDisable = 1;
-    db->lookaside.sz = 0;
-    db->lookaside.bMalloced = 0;
-    db->lookaside.nSlot = 0;
-  }
-#endif /* SQLITE_OMIT_LOOKASIDE */
-  return SQLITE_OK;
-}
-
 /*
 ** Return the mutex associated with a database connection.
 */
@@ -828,7 +756,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
       void *pBuf = va_arg(ap, void*); /* IMP: R-26835-10964 */
       int sz = va_arg(ap, int);       /* IMP: R-47871-25994 */
       int cnt = va_arg(ap, int);      /* IMP: R-04460-53386 */
-      rc = setupLookaside(db, pBuf, sz, cnt);
+      rc = sqlite3LookasideOpen(pBuf, sz, cnt, &db->lookaside);
       break;
     }
     default: {
@@ -1264,10 +1192,7 @@ void sqlite3LeaveMutexAndCloseZombie(sqlite3 *db){
   sqlite3_mutex_leave(db->mutex);
   db->magic = SQLITE_MAGIC_CLOSED;
   sqlite3_mutex_free(db->mutex);
-  assert( sqlite3LookasideUsed(db,0)==0 );
-  if( db->lookaside.bMalloced ){
-    sqlite3_free(db->lookaside.pStart);
-  }
+  sqlite3LookasideClose(&db->lookaside);
   sqlite3_free(db);
 }
 
@@ -3065,8 +2990,7 @@ static int openDatabase(
   db->nDb = 2;
   db->magic = SQLITE_MAGIC_BUSY;
   db->aDb = db->aDbStatic;
-  db->lookaside.bDisable = 1;
-  db->lookaside.sz = 0;
+  sqlite3LookasideDisable(&db->lookaside);
 
   assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
   memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
@@ -3323,8 +3247,8 @@ static int openDatabase(
   if( rc ) sqlite3Error(db, rc);
 
   /* Enable the lookaside-malloc subsystem */
-  setupLookaside(db, 0, sqlite3GlobalConfig.szLookaside,
-                        sqlite3GlobalConfig.nLookaside);
+  sqlite3LookasideOpen(0, sqlite3GlobalConfig.szLookaside,
+                        sqlite3GlobalConfig.nLookaside, &db->lookaside);
 
   sqlite3_wal_autocheckpoint(db, SQLITE_DEFAULT_WAL_AUTOCHECKPOINT);
 
index 8a2b234853eaa238c11a1061d4f14d7423c894bb..bf299f4ac1227e1d649534490c46f60f109a3d91 100644 (file)
@@ -13,6 +13,7 @@
 ** Memory allocation functions used throughout sqlite.
 */
 #include "sqliteInt.h"
+#include "lookaside.h"
 #include <stdarg.h>
 
 /*
@@ -264,17 +265,6 @@ void *sqlite3_malloc64(sqlite3_uint64 n){
   return sqlite3Malloc(n);
 }
 
-/*
-** TRUE if p is a lookaside memory allocation from db
-*/
-#ifndef SQLITE_OMIT_LOOKASIDE
-static int isLookaside(sqlite3 *db, void *p){
-  return SQLITE_WITHIN(p, db->lookaside.pStart, db->lookaside.pEnd);
-}
-#else
-#define isLookaside(A,B) 0
-#endif
-
 /*
 ** Return the size of a memory allocation previously obtained from
 ** sqlite3Malloc() or sqlite3_malloc().
@@ -285,7 +275,7 @@ int sqlite3MallocSize(void *p){
 }
 int sqlite3DbMallocSize(sqlite3 *db, void *p){
   assert( p!=0 );
-  if( db==0 || !isLookaside(db,p) ){
+  if( db==0 || !sqlite3IsLookaside(&db->lookaside,p) ){
 #ifdef SQLITE_DEBUG
     if( db==0 ){
       assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
@@ -298,7 +288,7 @@ int sqlite3DbMallocSize(sqlite3 *db, void *p){
     return sqlite3GlobalConfig.m.xSize(p);
   }else{
     assert( sqlite3_mutex_held(db->mutex) );
-    return db->lookaside.szTrue;
+    return sqlite3LookasideSize(&db->lookaside, p);
   }
 }
 sqlite3_uint64 sqlite3_msize(void *p){
@@ -346,14 +336,8 @@ void sqlite3DbFreeNN(sqlite3 *db, void *p){
       measureAllocationSize(db, p);
       return;
     }
-    if( isLookaside(db, p) ){
-      LookasideSlot *pBuf = (LookasideSlot*)p;
-#ifdef SQLITE_DEBUG
-      /* Trash all content in the buffer being freed */
-      memset(p, 0xaa, db->lookaside.szTrue);
-#endif
-      pBuf->pNext = db->lookaside.pFree;
-      db->lookaside.pFree = pBuf;
+    if( sqlite3IsLookaside(&db->lookaside, p) ){
+      sqlite3LookasideFree(&db->lookaside, p);
       return;
     }
   }
@@ -468,10 +452,11 @@ void *sqlite3DbMallocZero(sqlite3 *db, u64 n){
 static SQLITE_NOINLINE void *dbMallocRawFinish(sqlite3 *db, u64 n){
   void *p;
   assert( db!=0 );
+  if( db->mallocFailed ){ return 0; }
   p = sqlite3Malloc(n);
   if( !p ) sqlite3OomFault(db);
   sqlite3MemdebugSetType(p, 
-         (db->lookaside.bDisable==0) ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP);
+    sqlite3LookasideDisabled(&db->lookaside) ? MEMTYPE_HEAP : MEMTYPE_LOOKASIDE);
   return p;
 }
 
@@ -505,27 +490,11 @@ void *sqlite3DbMallocRaw(sqlite3 *db, u64 n){
   return p;
 }
 void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
-#ifndef SQLITE_OMIT_LOOKASIDE
-  LookasideSlot *pBuf;
   assert( db!=0 );
   assert( sqlite3_mutex_held(db->mutex) );
   assert( db->pnBytesFreed==0 );
-  if( n>db->lookaside.sz ){
-    if( db->lookaside.bDisable ){
-      return db->mallocFailed ? 0 : dbMallocRawFinish(db, n);
-    }
-    db->lookaside.anStat[1]++;
-  }else if( (pBuf = db->lookaside.pFree)!=0 ){
-    db->lookaside.pFree = pBuf->pNext;
-    db->lookaside.anStat[0]++;
-    return (void*)pBuf;
-  }else if( (pBuf = db->lookaside.pInit)!=0 ){
-    db->lookaside.pInit = pBuf->pNext;
-    db->lookaside.anStat[0]++;
-    return (void*)pBuf;
-  }else{
-    db->lookaside.anStat[2]++;
-  }
+#ifndef SQLITE_OMIT_LOOKASIDE
+  return sqlite3LookasideAlloc(&db->lookaside, n) ?: dbMallocRawFinish(db, n);
 #else
   assert( db!=0 );
   assert( sqlite3_mutex_held(db->mutex) );
@@ -533,8 +502,8 @@ void *sqlite3DbMallocRawNN(sqlite3 *db, u64 n){
   if( db->mallocFailed ){
     return 0;
   }
-#endif
   return dbMallocRawFinish(db, n);
+#endif
 }
 
 /* Forward declaration */
@@ -548,7 +517,7 @@ void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
   assert( db!=0 );
   if( p==0 ) return sqlite3DbMallocRawNN(db, n);
   assert( sqlite3_mutex_held(db->mutex) );
-  if( isLookaside(db,p) && n<=db->lookaside.szTrue ) return p;
+  if( sqlite3IsLookaside(&db->lookaside,p) && n<=sqlite3LookasideSize(&db->lookaside, p) ) return p;
   return dbReallocFinish(db, p, n);
 }
 static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
@@ -556,10 +525,10 @@ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
   assert( db!=0 );
   assert( p!=0 );
   if( db->mallocFailed==0 ){
-    if( isLookaside(db, p) ){
+    if( sqlite3IsLookaside(&db->lookaside,p) ){
       pNew = sqlite3DbMallocRawNN(db, n);
       if( pNew ){
-        memcpy(pNew, p, db->lookaside.szTrue);
+        memcpy(pNew, p, sqlite3LookasideSize(&db->lookaside, p));
         sqlite3DbFree(db, p);
       }
     }else{
@@ -570,8 +539,8 @@ static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
       if( !pNew ){
         sqlite3OomFault(db);
       }
-      sqlite3MemdebugSetType(pNew,
-            (db->lookaside.bDisable==0 ? MEMTYPE_LOOKASIDE : MEMTYPE_HEAP));
+      sqlite3MemdebugSetType(p,
+        sqlite3LookasideDisabled(&db->lookaside) ? MEMTYPE_HEAP : MEMTYPE_LOOKASIDE);
     }
   }
   return pNew;
@@ -648,8 +617,7 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
 
 /*
 ** Call this routine to record the fact that an OOM (out-of-memory) error
-** has happened.  This routine will set db->mallocFailed, and also
-** temporarily disable the lookaside memory allocator and interrupt
+** has happened.  This routine will set db->mallocFailed and interrupt
 ** any running VDBEs.
 */
 void sqlite3OomFault(sqlite3 *db){
@@ -658,7 +626,7 @@ void sqlite3OomFault(sqlite3 *db){
     if( db->nVdbeExec>0 ){
       db->u1.isInterrupted = 1;
     }
-    DisableLookaside;
+    sqlite3LookasideDisable(&db->lookaside);;
     if( db->pParse ){
       db->pParse->rc = SQLITE_NOMEM_BKPT;
     }
@@ -676,7 +644,7 @@ void sqlite3OomClear(sqlite3 *db){
   if( db->mallocFailed && db->nVdbeExec==0 ){
     db->mallocFailed = 0;
     db->u1.isInterrupted = 0;
-    assert( db->lookaside.bDisable>0 );
+    assert( sqlite3LookasideDisabled(&db->lookaside) );
     EnableLookaside;
   }
 }
index 7d31dda405da25d7ec86ebb5c43519a1f097f9fb..329a6e8634846ae31fca33ecc55e2fae359a9ed5 100644 (file)
@@ -51,6 +51,7 @@
 //
 %include {
 #include "sqliteInt.h"
+#include "lookaside.h"
 
 /*
 ** Disable all error recovery processing in the parser push-down
@@ -108,7 +109,7 @@ struct FrameBound     { int eType; Expr *pExpr; };
 static void disableLookaside(Parse *pParse){
   sqlite3 *db = pParse->db;
   pParse->disableLookaside++;
-  DisableLookaside;
+  sqlite3LookasideDisable(&db->lookaside);
 }
 
 } // end %include
index c6709a3d3d78be7095c336499d6822353845e525..cce5069b8e5872e5fbbf6557abb921cfe277aaef 100644 (file)
@@ -14,6 +14,7 @@
 ** from disk.
 */
 #include "sqliteInt.h"
+#include "lookaside.h"
 
 /*
 ** Fill the InitData structure with an error message that indicates
@@ -538,9 +539,8 @@ void sqlite3ParserReset(Parse *pParse){
   sqlite3DbFree(db, pParse->aLabel);
   sqlite3ExprListDelete(db, pParse->pConstExpr);
   if( db ){
-    assert( db->lookaside.bDisable >= pParse->disableLookaside );
-    db->lookaside.bDisable -= pParse->disableLookaside;
-    db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
+    assert( sqlite3LookasideDisabled(&db->lookaside) >= pParse->disableLookaside );
+    sqlite3LookasideEnableCnt(&db->lookaside, pParse->disableLookaside);
   }
   pParse->disableLookaside = 0;
 }
@@ -574,7 +574,7 @@ static int sqlite3Prepare(
   */
   if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
     sParse.disableLookaside++;
-    DisableLookaside;
+    sqlite3LookasideDisable(&db->lookaside);
   }
   sParse.disableVtab = (prepFlags & SQLITE_PREPARE_NO_VTAB)!=0;
 
index 6d18f75245a4d75bf32d71ba14b5e41f7bb4c6fe..4ccd6f2c2f36d8f4483046e7112e10e7702738d6 100644 (file)
@@ -13,6 +13,7 @@
 ** to handle SELECT statements in SQLite.
 */
 #include "sqliteInt.h"
+#include "lookaside.h"
 
 /*
 ** Trace output macros
index 9b8578ba5d5e9aa8971e95231a46e290c6b35d4a..604eba61691ba1fed043a56c066bb49caf8d91a3 100644 (file)
@@ -1289,9 +1289,19 @@ struct Lookaside {
   LookasideSlot *pFree;   /* List of available buffers */
   void *pStart;           /* First byte of available memory space */
   void *pEnd;             /* First byte past end of available space */
+#ifndef SQLITE_OMIT_MINILOOKASIDE
+  LookasideSlot *pMini;   /* List of buffers used by mini allocator */
+  u16 szMini;             /* Size of each mini-allocator buffer in bytes */
+  u16 nMini;              /* Number of mini-allocator buffers per slot */
+#endif /* SQLITE_OMIT_MINILOOKASIDE */
 };
 struct LookasideSlot {
-  LookasideSlot *pNext;    /* Next buffer in the list of free buffers */
+  LookasideSlot *pNext;    /* Next buffer in the list of buffers */
+#ifndef SQLITE_OMIT_MINILOOKASIDE
+  /* The members below are only valid for slots inside the mini-allocator */
+  LookasideSlot *pPrev;    /* Previous partially-used buffer in the list */
+  int bMembership;         /* Bitfield tracking sub-allocations within slot */
+#endif /* SQLITE_OMIT_MINILOOKASIDE */
 };
 
 #define DisableLookaside  db->lookaside.bDisable++;db->lookaside.sz=0
@@ -3825,7 +3835,6 @@ sqlite3_int64 sqlite3StatusValue(int);
 void sqlite3StatusUp(int, int);
 void sqlite3StatusDown(int, int);
 void sqlite3StatusHighwater(int, int);
-int sqlite3LookasideUsed(sqlite3*,int*);
 
 /* Access to mutexes used by sqlite3_status() */
 sqlite3_mutex *sqlite3Pcache1Mutex(void);
index a5a39f4c18282bb9a9d357a7f0974dcb6307c7fd..618136f96687b98f25103a0eed8eb8792190ef1d 100644 (file)
@@ -14,6 +14,7 @@
 ** functionality.
 */
 #include "sqliteInt.h"
+#include "lookaside.h"
 #include "vdbeInt.h"
 
 /*
@@ -170,28 +171,6 @@ int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
   return rc;
 }
 
-/*
-** Return the number of LookasideSlot elements on the linked list
-*/
-static u32 countLookasideSlots(LookasideSlot *p){
-  u32 cnt = 0;
-  while( p ){
-    p = p->pNext;
-    cnt++;
-  }
-  return cnt;
-}
-
-/*
-** Count the number of slots of lookaside memory that are outstanding
-*/
-int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
-  u32 nInit = countLookasideSlots(db->lookaside.pInit);
-  u32 nFree = countLookasideSlots(db->lookaside.pFree);
-  if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
-  return db->lookaside.nSlot - (nInit+nFree);
-}
-
 /*
 ** Query status information for a single database connection
 */
@@ -211,15 +190,9 @@ int sqlite3_db_status(
   sqlite3_mutex_enter(db->mutex);
   switch( op ){
     case SQLITE_DBSTATUS_LOOKASIDE_USED: {
-      *pCurrent = sqlite3LookasideUsed(db, pHighwater);
+      *pCurrent = sqlite3LookasideUsed(&db->lookaside, pHighwater);
       if( resetFlag ){
-        LookasideSlot *p = db->lookaside.pFree;
-        if( p ){
-          while( p->pNext ) p = p->pNext;
-          p->pNext = db->lookaside.pInit;
-          db->lookaside.pInit = db->lookaside.pFree;
-          db->lookaside.pFree = 0;
-        }
+        sqlite3LookasideResetUsed(&db->lookaside);
       }
       break;
     }
index 84520725646ec187e7cd77bf2ac3f1165ee7871c..e377fbd4072294213427ec0221b90c54693e66ba 100644 (file)
@@ -98,6 +98,7 @@ foreach hdr {
    hash.h
    hwtime.h
    keywordhash.h
+   lookaside.h
    msvc.h
    mutex.h
    opcodes.h
@@ -283,6 +284,7 @@ foreach file {
    os.c
 
    fault.c
+   lookaside.c
    mem0.c
    mem1.c
    mem2.c
index 2f9bd866b9b126f863b59f037c58e479f3037ff9..992342ecea152a34ec1ba334d83ccd18ab8a7327 100644 (file)
@@ -103,6 +103,7 @@ foreach hdr {
    hash.h
    hwtime.h
    keywordhash.h
+   lookaside.h
    msvc.h
    mutex.h
    opcodes.h
@@ -300,6 +301,7 @@ foreach file {
    os.c
 
    fault.c
+   lookaside.c
    mem0.c
    mem1.c
    mem2.c
index 8db593fe756316c8236817628f8fb8e4203efa16..034e103ffcc584dfec6f1dc536c1fdcd82f92049 100644 (file)
@@ -58,6 +58,7 @@ foreach hdr {
    hash.h
    hwtime.h
    keywordhash.h
+   lookaside.h
    msvc.h
    opcodes.h
    os_common.h