lj_alloc.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485
  1. /*
  2. ** Bundled memory allocator.
  3. **
  4. ** Beware: this is a HEAVILY CUSTOMIZED version of dlmalloc.
  5. ** The original bears the following remark:
  6. **
  7. ** This is a version (aka dlmalloc) of malloc/free/realloc written by
  8. ** Doug Lea and released to the public domain, as explained at
  9. ** https://creativecommons.org/licenses/publicdomain.
  10. **
  11. ** * Version pre-2.8.4 Wed Mar 29 19:46:29 2006 (dl at gee)
  12. **
  13. ** No additional copyright is claimed over the customizations.
  14. ** Please do NOT bother the original author about this version here!
  15. **
  16. ** If you want to use dlmalloc in another project, you should get
  17. ** the original from: ftp://gee.cs.oswego.edu/pub/misc/
  18. ** For thread-safe derivatives, take a look at:
  19. ** - ptmalloc: https://www.malloc.de/
  20. ** - nedmalloc: https://www.nedprod.com/programs/portable/nedmalloc/
  21. */
  22. #define lj_alloc_c
  23. #define LUA_CORE
  24. /* To get the mremap prototype. Must be defined before any system includes. */
  25. #if defined(__linux__) && !defined(_GNU_SOURCE)
  26. #define _GNU_SOURCE
  27. #endif
  28. #include "lj_def.h"
  29. #include "lj_arch.h"
  30. #include "lj_alloc.h"
  31. #include "lj_prng.h"
  32. #ifndef LUAJIT_USE_SYSMALLOC
  33. #define MAX_SIZE_T (~(size_t)0)
  34. #define MALLOC_ALIGNMENT ((size_t)8U)
  35. #define DEFAULT_GRANULARITY ((size_t)128U * (size_t)1024U)
  36. #define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U)
  37. #define DEFAULT_MMAP_THRESHOLD ((size_t)128U * (size_t)1024U)
  38. #define MAX_RELEASE_CHECK_RATE 255
  39. /* ------------------- size_t and alignment properties -------------------- */
  40. /* The byte and bit size of a size_t */
  41. #define SIZE_T_SIZE (sizeof(size_t))
  42. #define SIZE_T_BITSIZE (sizeof(size_t) << 3)
  43. /* Some constants coerced to size_t */
  44. /* Annoying but necessary to avoid errors on some platforms */
  45. #define SIZE_T_ZERO ((size_t)0)
  46. #define SIZE_T_ONE ((size_t)1)
  47. #define SIZE_T_TWO ((size_t)2)
  48. #define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1)
  49. #define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2)
  50. #define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES)
  51. /* The bit mask value corresponding to MALLOC_ALIGNMENT */
  52. #define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE)
  53. /* the number of bytes to offset an address to align it */
  54. #define align_offset(A)\
  55. ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\
  56. ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK))
  57. /* -------------------------- MMAP support ------------------------------- */
  58. #define MFAIL ((void *)(MAX_SIZE_T))
  59. #define CMFAIL ((char *)(MFAIL)) /* defined for convenience */
  60. #define IS_DIRECT_BIT (SIZE_T_ONE)
  61. /* Determine system-specific block allocation method. */
  62. #if LJ_TARGET_WINDOWS
  63. #define WIN32_LEAN_AND_MEAN
  64. #include <windows.h>
  65. #define LJ_ALLOC_VIRTUALALLOC 1
  66. #if LJ_64 && !LJ_GC64
  67. #define LJ_ALLOC_NTAVM 1
  68. #endif
  69. #else
  70. #include <errno.h>
  71. /* If this include fails, then rebuild with: -DLUAJIT_USE_SYSMALLOC */
  72. #include <sys/mman.h>
  73. #define LJ_ALLOC_MMAP 1
  74. #if LJ_64
  75. #define LJ_ALLOC_MMAP_PROBE 1
  76. #if LJ_GC64
  77. #define LJ_ALLOC_MBITS 47 /* 128 TB in LJ_GC64 mode. */
  78. #elif LJ_TARGET_X64 && LJ_HASJIT
  79. /* Due to limitations in the x64 compiler backend. */
  80. #define LJ_ALLOC_MBITS 31 /* 2 GB on x64 with !LJ_GC64. */
  81. #else
  82. #define LJ_ALLOC_MBITS 32 /* 4 GB on other archs with !LJ_GC64. */
  83. #endif
  84. #endif
  85. #if LJ_64 && !LJ_GC64 && defined(MAP_32BIT)
  86. #define LJ_ALLOC_MMAP32 1
  87. #endif
  88. #if LJ_TARGET_LINUX
  89. #define LJ_ALLOC_MREMAP 1
  90. #endif
  91. #endif
  92. #if LJ_ALLOC_VIRTUALALLOC
  93. #if LJ_ALLOC_NTAVM
  94. /* Undocumented, but hey, that's what we all love so much about Windows. */
  95. typedef long (*PNTAVM)(HANDLE handle, void **addr, ULONG_PTR zbits,
  96. size_t *size, ULONG alloctype, ULONG prot);
  97. static PNTAVM ntavm;
  98. /* Number of top bits of the lower 32 bits of an address that must be zero.
  99. ** Apparently 0 gives us full 64 bit addresses and 1 gives us the lower 2GB.
  100. */
  101. #define NTAVM_ZEROBITS 1
  102. static void init_mmap(void)
  103. {
  104. ntavm = (PNTAVM)GetProcAddress(GetModuleHandleA("ntdll.dll"),
  105. "NtAllocateVirtualMemory");
  106. }
  107. #define INIT_MMAP() init_mmap()
  108. /* Win64 32 bit MMAP via NtAllocateVirtualMemory. */
  109. static void *mmap_plain(size_t size)
  110. {
  111. DWORD olderr = GetLastError();
  112. void *ptr = NULL;
  113. long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size,
  114. MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
  115. SetLastError(olderr);
  116. return st == 0 ? ptr : MFAIL;
  117. }
  118. /* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
  119. static void *direct_mmap(size_t size)
  120. {
  121. DWORD olderr = GetLastError();
  122. void *ptr = NULL;
  123. long st = ntavm(INVALID_HANDLE_VALUE, &ptr, NTAVM_ZEROBITS, &size,
  124. MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_READWRITE);
  125. SetLastError(olderr);
  126. return st == 0 ? ptr : MFAIL;
  127. }
  128. #else
  129. /* Win32 MMAP via VirtualAlloc */
  130. static void *mmap_plain(size_t size)
  131. {
  132. DWORD olderr = GetLastError();
  133. void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
  134. SetLastError(olderr);
  135. return ptr ? ptr : MFAIL;
  136. }
  137. /* For direct MMAP, use MEM_TOP_DOWN to minimize interference */
  138. static void *direct_mmap(size_t size)
  139. {
  140. DWORD olderr = GetLastError();
  141. void *ptr = LJ_WIN_VALLOC(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN,
  142. PAGE_READWRITE);
  143. SetLastError(olderr);
  144. return ptr ? ptr : MFAIL;
  145. }
  146. #endif
  147. #define CALL_MMAP(prng, size) mmap_plain(size)
  148. #define DIRECT_MMAP(prng, size) direct_mmap(size)
  149. /* This function supports releasing coalesed segments */
  150. static int CALL_MUNMAP(void *ptr, size_t size)
  151. {
  152. DWORD olderr = GetLastError();
  153. MEMORY_BASIC_INFORMATION minfo;
  154. char *cptr = (char *)ptr;
  155. while (size) {
  156. if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0)
  157. return -1;
  158. if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr ||
  159. minfo.State != MEM_COMMIT || minfo.RegionSize > size)
  160. return -1;
  161. if (VirtualFree(cptr, 0, MEM_RELEASE) == 0)
  162. return -1;
  163. cptr += minfo.RegionSize;
  164. size -= minfo.RegionSize;
  165. }
  166. SetLastError(olderr);
  167. return 0;
  168. }
  169. #elif LJ_ALLOC_MMAP
  170. #define MMAP_PROT (PROT_READ|PROT_WRITE)
  171. #if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
  172. #define MAP_ANONYMOUS MAP_ANON
  173. #endif
  174. #define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS)
  175. #if LJ_ALLOC_MMAP_PROBE
  176. #ifdef MAP_TRYFIXED
  177. #define MMAP_FLAGS_PROBE (MMAP_FLAGS|MAP_TRYFIXED)
  178. #else
  179. #define MMAP_FLAGS_PROBE MMAP_FLAGS
  180. #endif
  181. #define LJ_ALLOC_MMAP_PROBE_MAX 30
  182. #define LJ_ALLOC_MMAP_PROBE_LINEAR 5
  183. #define LJ_ALLOC_MMAP_PROBE_LOWER ((uintptr_t)0x4000)
  184. static void *mmap_probe(PRNGState *rs, size_t size)
  185. {
  186. /* Hint for next allocation. Doesn't need to be thread-safe. */
  187. static uintptr_t hint_addr = 0;
  188. int olderr = errno;
  189. int retry;
  190. for (retry = 0; retry < LJ_ALLOC_MMAP_PROBE_MAX; retry++) {
  191. void *p = mmap((void *)hint_addr, size, MMAP_PROT, MMAP_FLAGS_PROBE, -1, 0);
  192. uintptr_t addr = (uintptr_t)p;
  193. if ((addr >> LJ_ALLOC_MBITS) == 0 && addr >= LJ_ALLOC_MMAP_PROBE_LOWER &&
  194. ((addr + size) >> LJ_ALLOC_MBITS) == 0) {
  195. /* We got a suitable address. Bump the hint address. */
  196. hint_addr = addr + size;
  197. errno = olderr;
  198. return p;
  199. }
  200. if (p != MFAIL) {
  201. munmap(p, size);
  202. } else if (errno == ENOMEM) {
  203. return MFAIL;
  204. }
  205. if (hint_addr) {
  206. /* First, try linear probing. */
  207. if (retry < LJ_ALLOC_MMAP_PROBE_LINEAR) {
  208. hint_addr += 0x1000000;
  209. if (((hint_addr + size) >> LJ_ALLOC_MBITS) != 0)
  210. hint_addr = 0;
  211. continue;
  212. } else if (retry == LJ_ALLOC_MMAP_PROBE_LINEAR) {
  213. /* Next, try a no-hint probe to get back an ASLR address. */
  214. hint_addr = 0;
  215. continue;
  216. }
  217. }
  218. /* Finally, try pseudo-random probing. */
  219. do {
  220. hint_addr = lj_prng_u64(rs) & (((uintptr_t)1<<LJ_ALLOC_MBITS)-LJ_PAGESIZE);
  221. } while (hint_addr < LJ_ALLOC_MMAP_PROBE_LOWER);
  222. }
  223. errno = olderr;
  224. return MFAIL;
  225. }
  226. #endif
  227. #if LJ_ALLOC_MMAP32
  228. #if LJ_TARGET_SOLARIS
  229. #define LJ_ALLOC_MMAP32_START ((uintptr_t)0x1000)
  230. #else
  231. #define LJ_ALLOC_MMAP32_START ((uintptr_t)0)
  232. #endif
  233. #if LJ_ALLOC_MMAP_PROBE
  234. static void *mmap_map32(PRNGState *rs, size_t size)
  235. #else
  236. static void *mmap_map32(size_t size)
  237. #endif
  238. {
  239. #if LJ_ALLOC_MMAP_PROBE
  240. static int fallback = 0;
  241. if (fallback)
  242. return mmap_probe(rs, size);
  243. #endif
  244. {
  245. int olderr = errno;
  246. void *ptr = mmap((void *)LJ_ALLOC_MMAP32_START, size, MMAP_PROT, MAP_32BIT|MMAP_FLAGS, -1, 0);
  247. errno = olderr;
  248. /* This only allows 1GB on Linux. So fallback to probing to get 2GB. */
  249. #if LJ_ALLOC_MMAP_PROBE
  250. if (ptr == MFAIL) {
  251. fallback = 1;
  252. return mmap_probe(rs, size);
  253. }
  254. #endif
  255. return ptr;
  256. }
  257. }
  258. #endif
  259. #if LJ_ALLOC_MMAP32
  260. #if LJ_ALLOC_MMAP_PROBE
  261. #define CALL_MMAP(prng, size) mmap_map32(prng, size)
  262. #else
  263. #define CALL_MMAP(prng, size) mmap_map32(size)
  264. #endif
  265. #elif LJ_ALLOC_MMAP_PROBE
  266. #define CALL_MMAP(prng, size) mmap_probe(prng, size)
  267. #else
  268. static void *mmap_plain(size_t size)
  269. {
  270. int olderr = errno;
  271. void *ptr = mmap(NULL, size, MMAP_PROT, MMAP_FLAGS, -1, 0);
  272. errno = olderr;
  273. return ptr;
  274. }
  275. #define CALL_MMAP(prng, size) mmap_plain(size)
  276. #endif
  277. #if LJ_64 && !LJ_GC64 && ((defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__FreeBSD_kernel__)) && !LJ_TARGET_PS4 && !LJ_TARGET_PS5
  278. #include <sys/resource.h>
  279. static void init_mmap(void)
  280. {
  281. struct rlimit rlim;
  282. rlim.rlim_cur = rlim.rlim_max = 0x10000;
  283. setrlimit(RLIMIT_DATA, &rlim); /* Ignore result. May fail later. */
  284. }
  285. #define INIT_MMAP() init_mmap()
  286. #endif
  287. static int CALL_MUNMAP(void *ptr, size_t size)
  288. {
  289. int olderr = errno;
  290. int ret = munmap(ptr, size);
  291. errno = olderr;
  292. return ret;
  293. }
  294. #if LJ_ALLOC_MREMAP
  295. /* Need to define _GNU_SOURCE to get the mremap prototype. */
  296. static void *CALL_MREMAP_(void *ptr, size_t osz, size_t nsz, int flags)
  297. {
  298. int olderr = errno;
  299. ptr = mremap(ptr, osz, nsz, flags);
  300. errno = olderr;
  301. return ptr;
  302. }
  303. #define CALL_MREMAP(addr, osz, nsz, mv) CALL_MREMAP_((addr), (osz), (nsz), (mv))
  304. #define CALL_MREMAP_NOMOVE 0
  305. #define CALL_MREMAP_MAYMOVE 1
  306. #if LJ_64 && (!LJ_GC64 || LJ_TARGET_ARM64)
  307. #define CALL_MREMAP_MV CALL_MREMAP_NOMOVE
  308. #else
  309. #define CALL_MREMAP_MV CALL_MREMAP_MAYMOVE
  310. #endif
  311. #endif
  312. #endif
  313. #ifndef INIT_MMAP
  314. #define INIT_MMAP() ((void)0)
  315. #endif
  316. #ifndef DIRECT_MMAP
  317. #define DIRECT_MMAP(prng, s) CALL_MMAP(prng, s)
  318. #endif
  319. #ifndef CALL_MREMAP
  320. #define CALL_MREMAP(addr, osz, nsz, mv) ((void)osz, MFAIL)
  321. #endif
  322. /* ----------------------- Chunk representations ------------------------ */
  323. struct malloc_chunk {
  324. size_t prev_foot; /* Size of previous chunk (if free). */
  325. size_t head; /* Size and inuse bits. */
  326. struct malloc_chunk *fd; /* double links -- used only if free. */
  327. struct malloc_chunk *bk;
  328. };
  329. typedef struct malloc_chunk mchunk;
  330. typedef struct malloc_chunk *mchunkptr;
  331. typedef struct malloc_chunk *sbinptr; /* The type of bins of chunks */
  332. typedef size_t bindex_t; /* Described below */
  333. typedef unsigned int binmap_t; /* Described below */
  334. typedef unsigned int flag_t; /* The type of various bit flag sets */
  335. /* ------------------- Chunks sizes and alignments ----------------------- */
  336. #define MCHUNK_SIZE (sizeof(mchunk))
  337. #define CHUNK_OVERHEAD (SIZE_T_SIZE)
  338. /* Direct chunks need a second word of overhead ... */
  339. #define DIRECT_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES)
  340. /* ... and additional padding for fake next-chunk at foot */
  341. #define DIRECT_FOOT_PAD (FOUR_SIZE_T_SIZES)
  342. /* The smallest size we can malloc is an aligned minimal chunk */
  343. #define MIN_CHUNK_SIZE\
  344. ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
  345. /* conversion from malloc headers to user pointers, and back */
  346. #define chunk2mem(p) ((void *)((char *)(p) + TWO_SIZE_T_SIZES))
  347. #define mem2chunk(mem) ((mchunkptr)((char *)(mem) - TWO_SIZE_T_SIZES))
  348. /* chunk associated with aligned address A */
  349. #define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A)))
  350. /* Bounds on request (not chunk) sizes. */
  351. #define MAX_REQUEST ((~MIN_CHUNK_SIZE+1) << 2)
  352. #define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE)
  353. /* pad request bytes into a usable size */
  354. #define pad_request(req) \
  355. (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK)
  356. /* pad request, checking for minimum (but not maximum) */
  357. #define request2size(req) \
  358. (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req))
  359. /* ------------------ Operations on head and foot fields ----------------- */
  360. #define PINUSE_BIT (SIZE_T_ONE)
  361. #define CINUSE_BIT (SIZE_T_TWO)
  362. #define INUSE_BITS (PINUSE_BIT|CINUSE_BIT)
  363. /* Head value for fenceposts */
  364. #define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE)
  365. /* extraction of fields from head words */
  366. #define cinuse(p) ((p)->head & CINUSE_BIT)
  367. #define pinuse(p) ((p)->head & PINUSE_BIT)
  368. #define chunksize(p) ((p)->head & ~(INUSE_BITS))
  369. #define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT)
  370. #define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT)
  371. /* Treat space at ptr +/- offset as a chunk */
  372. #define chunk_plus_offset(p, s) ((mchunkptr)(((char *)(p)) + (s)))
  373. #define chunk_minus_offset(p, s) ((mchunkptr)(((char *)(p)) - (s)))
  374. /* Ptr to next or previous physical malloc_chunk. */
  375. #define next_chunk(p) ((mchunkptr)(((char *)(p)) + ((p)->head & ~INUSE_BITS)))
  376. #define prev_chunk(p) ((mchunkptr)(((char *)(p)) - ((p)->prev_foot) ))
  377. /* extract next chunk's pinuse bit */
  378. #define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT)
  379. /* Get/set size at footer */
  380. #define get_foot(p, s) (((mchunkptr)((char *)(p) + (s)))->prev_foot)
  381. #define set_foot(p, s) (((mchunkptr)((char *)(p) + (s)))->prev_foot = (s))
  382. /* Set size, pinuse bit, and foot */
  383. #define set_size_and_pinuse_of_free_chunk(p, s)\
  384. ((p)->head = (s|PINUSE_BIT), set_foot(p, s))
  385. /* Set size, pinuse bit, foot, and clear next pinuse */
  386. #define set_free_with_pinuse(p, s, n)\
  387. (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s))
  388. #define is_direct(p)\
  389. (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_DIRECT_BIT))
  390. /* Get the internal overhead associated with chunk p */
  391. #define overhead_for(p)\
  392. (is_direct(p)? DIRECT_CHUNK_OVERHEAD : CHUNK_OVERHEAD)
  393. /* ---------------------- Overlaid data structures ----------------------- */
  394. struct malloc_tree_chunk {
  395. /* The first four fields must be compatible with malloc_chunk */
  396. size_t prev_foot;
  397. size_t head;
  398. struct malloc_tree_chunk *fd;
  399. struct malloc_tree_chunk *bk;
  400. struct malloc_tree_chunk *child[2];
  401. struct malloc_tree_chunk *parent;
  402. bindex_t index;
  403. };
  404. typedef struct malloc_tree_chunk tchunk;
  405. typedef struct malloc_tree_chunk *tchunkptr;
  406. typedef struct malloc_tree_chunk *tbinptr; /* The type of bins of trees */
  407. /* A little helper macro for trees */
  408. #define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1])
  409. /* ----------------------------- Segments -------------------------------- */
  410. struct malloc_segment {
  411. char *base; /* base address */
  412. size_t size; /* allocated size */
  413. struct malloc_segment *next; /* ptr to next segment */
  414. };
  415. typedef struct malloc_segment msegment;
  416. typedef struct malloc_segment *msegmentptr;
  417. /* ---------------------------- malloc_state ----------------------------- */
  418. /* Bin types, widths and sizes */
  419. #define NSMALLBINS (32U)
  420. #define NTREEBINS (32U)
  421. #define SMALLBIN_SHIFT (3U)
  422. #define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT)
  423. #define TREEBIN_SHIFT (8U)
  424. #define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT)
  425. #define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE)
  426. #define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD)
  427. struct malloc_state {
  428. binmap_t smallmap;
  429. binmap_t treemap;
  430. size_t dvsize;
  431. size_t topsize;
  432. mchunkptr dv;
  433. mchunkptr top;
  434. size_t trim_check;
  435. size_t release_checks;
  436. mchunkptr smallbins[(NSMALLBINS+1)*2];
  437. tbinptr treebins[NTREEBINS];
  438. msegment seg;
  439. PRNGState *prng;
  440. };
  441. typedef struct malloc_state *mstate;
  442. #define is_initialized(M) ((M)->top != 0)
  443. /* -------------------------- system alloc setup ------------------------- */
  444. /* page-align a size */
  445. #define page_align(S)\
  446. (((S) + (LJ_PAGESIZE - SIZE_T_ONE)) & ~(LJ_PAGESIZE - SIZE_T_ONE))
  447. /* granularity-align a size */
  448. #define granularity_align(S)\
  449. (((S) + (DEFAULT_GRANULARITY - SIZE_T_ONE))\
  450. & ~(DEFAULT_GRANULARITY - SIZE_T_ONE))
  451. #if LJ_TARGET_WINDOWS
  452. #define mmap_align(S) granularity_align(S)
  453. #else
  454. #define mmap_align(S) page_align(S)
  455. #endif
  456. /* True if segment S holds address A */
  457. #define segment_holds(S, A)\
  458. ((char *)(A) >= S->base && (char *)(A) < S->base + S->size)
  459. /* Return segment holding given address */
  460. static msegmentptr segment_holding(mstate m, char *addr)
  461. {
  462. msegmentptr sp = &m->seg;
  463. for (;;) {
  464. if (addr >= sp->base && addr < sp->base + sp->size)
  465. return sp;
  466. if ((sp = sp->next) == 0)
  467. return 0;
  468. }
  469. }
  470. /* Return true if segment contains a segment link */
  471. static int has_segment_link(mstate m, msegmentptr ss)
  472. {
  473. msegmentptr sp = &m->seg;
  474. for (;;) {
  475. if ((char *)sp >= ss->base && (char *)sp < ss->base + ss->size)
  476. return 1;
  477. if ((sp = sp->next) == 0)
  478. return 0;
  479. }
  480. }
  481. /*
  482. TOP_FOOT_SIZE is padding at the end of a segment, including space
  483. that may be needed to place segment records and fenceposts when new
  484. noncontiguous segments are added.
  485. */
  486. #define TOP_FOOT_SIZE\
  487. (align_offset(TWO_SIZE_T_SIZES)+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE)
  488. /* ---------------------------- Indexing Bins ---------------------------- */
  489. #define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS)
  490. #define small_index(s) ((s) >> SMALLBIN_SHIFT)
  491. #define small_index2size(i) ((i) << SMALLBIN_SHIFT)
  492. #define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE))
  493. /* addressing by index. See above about smallbin repositioning */
  494. #define smallbin_at(M, i) ((sbinptr)((char *)&((M)->smallbins[(i)<<1])))
  495. #define treebin_at(M,i) (&((M)->treebins[i]))
  496. /* assign tree index for size S to variable I */
  497. #define compute_tree_index(S, I)\
  498. {\
  499. unsigned int X = (unsigned int)(S >> TREEBIN_SHIFT);\
  500. if (X == 0) {\
  501. I = 0;\
  502. } else if (X > 0xFFFF) {\
  503. I = NTREEBINS-1;\
  504. } else {\
  505. unsigned int K = lj_fls(X);\
  506. I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\
  507. }\
  508. }
  509. /* Bit representing maximum resolved size in a treebin at i */
  510. #define bit_for_tree_index(i) \
  511. (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2)
  512. /* Shift placing maximum resolved bit in a treebin at i as sign bit */
  513. #define leftshift_for_tree_index(i) \
  514. ((i == NTREEBINS-1)? 0 : \
  515. ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2)))
  516. /* The size of the smallest chunk held in bin with index i */
  517. #define minsize_for_tree_index(i) \
  518. ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \
  519. (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1)))
  520. /* ------------------------ Operations on bin maps ----------------------- */
  521. /* bit corresponding to given index */
  522. #define idx2bit(i) ((binmap_t)(1) << (i))
  523. /* Mark/Clear bits with given index */
  524. #define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i))
  525. #define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i))
  526. #define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i))
  527. #define mark_treemap(M,i) ((M)->treemap |= idx2bit(i))
  528. #define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i))
  529. #define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i))
  530. /* mask with all bits to left of least bit of x on */
  531. #define left_bits(x) ((x<<1) | (~(x<<1)+1))
  532. /* Set cinuse bit and pinuse bit of next chunk */
  533. #define set_inuse(M,p,s)\
  534. ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\
  535. ((mchunkptr)(((char *)(p)) + (s)))->head |= PINUSE_BIT)
  536. /* Set cinuse and pinuse of this chunk and pinuse of next chunk */
  537. #define set_inuse_and_pinuse(M,p,s)\
  538. ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\
  539. ((mchunkptr)(((char *)(p)) + (s)))->head |= PINUSE_BIT)
  540. /* Set size, cinuse and pinuse bit of this chunk */
  541. #define set_size_and_pinuse_of_inuse_chunk(M, p, s)\
  542. ((p)->head = (s|PINUSE_BIT|CINUSE_BIT))
  543. /* ----------------------- Operations on smallbins ----------------------- */
  544. /* Link a free chunk into a smallbin */
  545. #define insert_small_chunk(M, P, S) {\
  546. bindex_t I = small_index(S);\
  547. mchunkptr B = smallbin_at(M, I);\
  548. mchunkptr F = B;\
  549. if (!smallmap_is_marked(M, I))\
  550. mark_smallmap(M, I);\
  551. else\
  552. F = B->fd;\
  553. B->fd = P;\
  554. F->bk = P;\
  555. P->fd = F;\
  556. P->bk = B;\
  557. }
  558. /* Unlink a chunk from a smallbin */
  559. #define unlink_small_chunk(M, P, S) {\
  560. mchunkptr F = P->fd;\
  561. mchunkptr B = P->bk;\
  562. bindex_t I = small_index(S);\
  563. if (F == B) {\
  564. clear_smallmap(M, I);\
  565. } else {\
  566. F->bk = B;\
  567. B->fd = F;\
  568. }\
  569. }
  570. /* Unlink the first chunk from a smallbin */
  571. #define unlink_first_small_chunk(M, B, P, I) {\
  572. mchunkptr F = P->fd;\
  573. if (B == F) {\
  574. clear_smallmap(M, I);\
  575. } else {\
  576. B->fd = F;\
  577. F->bk = B;\
  578. }\
  579. }
  580. /* Replace dv node, binning the old one */
  581. /* Used only when dvsize known to be small */
  582. #define replace_dv(M, P, S) {\
  583. size_t DVS = M->dvsize;\
  584. if (DVS != 0) {\
  585. mchunkptr DV = M->dv;\
  586. insert_small_chunk(M, DV, DVS);\
  587. }\
  588. M->dvsize = S;\
  589. M->dv = P;\
  590. }
  591. /* ------------------------- Operations on trees ------------------------- */
  592. /* Insert chunk into tree */
  593. #define insert_large_chunk(M, X, S) {\
  594. tbinptr *H;\
  595. bindex_t I;\
  596. compute_tree_index(S, I);\
  597. H = treebin_at(M, I);\
  598. X->index = I;\
  599. X->child[0] = X->child[1] = 0;\
  600. if (!treemap_is_marked(M, I)) {\
  601. mark_treemap(M, I);\
  602. *H = X;\
  603. X->parent = (tchunkptr)H;\
  604. X->fd = X->bk = X;\
  605. } else {\
  606. tchunkptr T = *H;\
  607. size_t K = S << leftshift_for_tree_index(I);\
  608. for (;;) {\
  609. if (chunksize(T) != S) {\
  610. tchunkptr *C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\
  611. K <<= 1;\
  612. if (*C != 0) {\
  613. T = *C;\
  614. } else {\
  615. *C = X;\
  616. X->parent = T;\
  617. X->fd = X->bk = X;\
  618. break;\
  619. }\
  620. } else {\
  621. tchunkptr F = T->fd;\
  622. T->fd = F->bk = X;\
  623. X->fd = F;\
  624. X->bk = T;\
  625. X->parent = 0;\
  626. break;\
  627. }\
  628. }\
  629. }\
  630. }
  631. #define unlink_large_chunk(M, X) {\
  632. tchunkptr XP = X->parent;\
  633. tchunkptr R;\
  634. if (X->bk != X) {\
  635. tchunkptr F = X->fd;\
  636. R = X->bk;\
  637. F->bk = R;\
  638. R->fd = F;\
  639. } else {\
  640. tchunkptr *RP;\
  641. if (((R = *(RP = &(X->child[1]))) != 0) ||\
  642. ((R = *(RP = &(X->child[0]))) != 0)) {\
  643. tchunkptr *CP;\
  644. while ((*(CP = &(R->child[1])) != 0) ||\
  645. (*(CP = &(R->child[0])) != 0)) {\
  646. R = *(RP = CP);\
  647. }\
  648. *RP = 0;\
  649. }\
  650. }\
  651. if (XP != 0) {\
  652. tbinptr *H = treebin_at(M, X->index);\
  653. if (X == *H) {\
  654. if ((*H = R) == 0) \
  655. clear_treemap(M, X->index);\
  656. } else {\
  657. if (XP->child[0] == X) \
  658. XP->child[0] = R;\
  659. else \
  660. XP->child[1] = R;\
  661. }\
  662. if (R != 0) {\
  663. tchunkptr C0, C1;\
  664. R->parent = XP;\
  665. if ((C0 = X->child[0]) != 0) {\
  666. R->child[0] = C0;\
  667. C0->parent = R;\
  668. }\
  669. if ((C1 = X->child[1]) != 0) {\
  670. R->child[1] = C1;\
  671. C1->parent = R;\
  672. }\
  673. }\
  674. }\
  675. }
  676. /* Relays to large vs small bin operations */
  677. #define insert_chunk(M, P, S)\
  678. if (is_small(S)) { insert_small_chunk(M, P, S)\
  679. } else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); }
  680. #define unlink_chunk(M, P, S)\
  681. if (is_small(S)) { unlink_small_chunk(M, P, S)\
  682. } else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); }
  683. /* ----------------------- Direct-mmapping chunks ----------------------- */
  684. static void *direct_alloc(mstate m, size_t nb)
  685. {
  686. size_t mmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
  687. if (LJ_LIKELY(mmsize > nb)) { /* Check for wrap around 0 */
  688. char *mm = (char *)(DIRECT_MMAP(m->prng, mmsize));
  689. if (mm != CMFAIL) {
  690. size_t offset = align_offset(chunk2mem(mm));
  691. size_t psize = mmsize - offset - DIRECT_FOOT_PAD;
  692. mchunkptr p = (mchunkptr)(mm + offset);
  693. p->prev_foot = offset | IS_DIRECT_BIT;
  694. p->head = psize|CINUSE_BIT;
  695. chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD;
  696. chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0;
  697. return chunk2mem(p);
  698. }
  699. }
  700. UNUSED(m);
  701. return NULL;
  702. }
  703. static mchunkptr direct_resize(mchunkptr oldp, size_t nb)
  704. {
  705. size_t oldsize = chunksize(oldp);
  706. if (is_small(nb)) /* Can't shrink direct regions below small size */
  707. return NULL;
  708. /* Keep old chunk if big enough but not too big */
  709. if (oldsize >= nb + SIZE_T_SIZE &&
  710. (oldsize - nb) <= (DEFAULT_GRANULARITY >> 1)) {
  711. return oldp;
  712. } else {
  713. size_t offset = oldp->prev_foot & ~IS_DIRECT_BIT;
  714. size_t oldmmsize = oldsize + offset + DIRECT_FOOT_PAD;
  715. size_t newmmsize = mmap_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
  716. char *cp = (char *)CALL_MREMAP((char *)oldp - offset,
  717. oldmmsize, newmmsize, CALL_MREMAP_MV);
  718. if (cp != CMFAIL) {
  719. mchunkptr newp = (mchunkptr)(cp + offset);
  720. size_t psize = newmmsize - offset - DIRECT_FOOT_PAD;
  721. newp->head = psize|CINUSE_BIT;
  722. chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD;
  723. chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0;
  724. return newp;
  725. }
  726. }
  727. return NULL;
  728. }
  729. /* -------------------------- mspace management -------------------------- */
  730. /* Initialize top chunk and its size */
  731. static void init_top(mstate m, mchunkptr p, size_t psize)
  732. {
  733. /* Ensure alignment */
  734. size_t offset = align_offset(chunk2mem(p));
  735. p = (mchunkptr)((char *)p + offset);
  736. psize -= offset;
  737. m->top = p;
  738. m->topsize = psize;
  739. p->head = psize | PINUSE_BIT;
  740. /* set size of fake trailing chunk holding overhead space only once */
  741. chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE;
  742. m->trim_check = DEFAULT_TRIM_THRESHOLD; /* reset on each update */
  743. }
  744. /* Initialize bins for a new mstate that is otherwise zeroed out */
  745. static void init_bins(mstate m)
  746. {
  747. /* Establish circular links for smallbins */
  748. bindex_t i;
  749. for (i = 0; i < NSMALLBINS; i++) {
  750. sbinptr bin = smallbin_at(m,i);
  751. bin->fd = bin->bk = bin;
  752. }
  753. }
  754. /* Allocate chunk and prepend remainder with chunk in successor base. */
  755. static void *prepend_alloc(mstate m, char *newbase, char *oldbase, size_t nb)
  756. {
  757. mchunkptr p = align_as_chunk(newbase);
  758. mchunkptr oldfirst = align_as_chunk(oldbase);
  759. size_t psize = (size_t)((char *)oldfirst - (char *)p);
  760. mchunkptr q = chunk_plus_offset(p, nb);
  761. size_t qsize = psize - nb;
  762. set_size_and_pinuse_of_inuse_chunk(m, p, nb);
  763. /* consolidate remainder with first chunk of old base */
  764. if (oldfirst == m->top) {
  765. size_t tsize = m->topsize += qsize;
  766. m->top = q;
  767. q->head = tsize | PINUSE_BIT;
  768. } else if (oldfirst == m->dv) {
  769. size_t dsize = m->dvsize += qsize;
  770. m->dv = q;
  771. set_size_and_pinuse_of_free_chunk(q, dsize);
  772. } else {
  773. if (!cinuse(oldfirst)) {
  774. size_t nsize = chunksize(oldfirst);
  775. unlink_chunk(m, oldfirst, nsize);
  776. oldfirst = chunk_plus_offset(oldfirst, nsize);
  777. qsize += nsize;
  778. }
  779. set_free_with_pinuse(q, qsize, oldfirst);
  780. insert_chunk(m, q, qsize);
  781. }
  782. return chunk2mem(p);
  783. }
  784. /* Add a segment to hold a new noncontiguous region */
  785. static void add_segment(mstate m, char *tbase, size_t tsize)
  786. {
  787. /* Determine locations and sizes of segment, fenceposts, old top */
  788. char *old_top = (char *)m->top;
  789. msegmentptr oldsp = segment_holding(m, old_top);
  790. char *old_end = oldsp->base + oldsp->size;
  791. size_t ssize = pad_request(sizeof(struct malloc_segment));
  792. char *rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK);
  793. size_t offset = align_offset(chunk2mem(rawsp));
  794. char *asp = rawsp + offset;
  795. char *csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp;
  796. mchunkptr sp = (mchunkptr)csp;
  797. msegmentptr ss = (msegmentptr)(chunk2mem(sp));
  798. mchunkptr tnext = chunk_plus_offset(sp, ssize);
  799. mchunkptr p = tnext;
  800. /* reset top to new space */
  801. init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE);
  802. /* Set up segment record */
  803. set_size_and_pinuse_of_inuse_chunk(m, sp, ssize);
  804. *ss = m->seg; /* Push current record */
  805. m->seg.base = tbase;
  806. m->seg.size = tsize;
  807. m->seg.next = ss;
  808. /* Insert trailing fenceposts */
  809. for (;;) {
  810. mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE);
  811. p->head = FENCEPOST_HEAD;
  812. if ((char *)(&(nextp->head)) < old_end)
  813. p = nextp;
  814. else
  815. break;
  816. }
  817. /* Insert the rest of old top into a bin as an ordinary free chunk */
  818. if (csp != old_top) {
  819. mchunkptr q = (mchunkptr)old_top;
  820. size_t psize = (size_t)(csp - old_top);
  821. mchunkptr tn = chunk_plus_offset(q, psize);
  822. set_free_with_pinuse(q, psize, tn);
  823. insert_chunk(m, q, psize);
  824. }
  825. }
  826. /* -------------------------- System allocation -------------------------- */
  827. static void *alloc_sys(mstate m, size_t nb)
  828. {
  829. char *tbase = CMFAIL;
  830. size_t tsize = 0;
  831. /* Directly map large chunks */
  832. if (LJ_UNLIKELY(nb >= DEFAULT_MMAP_THRESHOLD)) {
  833. void *mem = direct_alloc(m, nb);
  834. if (mem != 0)
  835. return mem;
  836. }
  837. {
  838. size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE;
  839. size_t rsize = granularity_align(req);
  840. if (LJ_LIKELY(rsize > nb)) { /* Fail if wraps around zero */
  841. char *mp = (char *)(CALL_MMAP(m->prng, rsize));
  842. if (mp != CMFAIL) {
  843. tbase = mp;
  844. tsize = rsize;
  845. }
  846. }
  847. }
  848. if (tbase != CMFAIL) {
  849. msegmentptr sp = &m->seg;
  850. /* Try to merge with an existing segment */
  851. while (sp != 0 && tbase != sp->base + sp->size)
  852. sp = sp->next;
  853. if (sp != 0 && segment_holds(sp, m->top)) { /* append */
  854. sp->size += tsize;
  855. init_top(m, m->top, m->topsize + tsize);
  856. } else {
  857. sp = &m->seg;
  858. while (sp != 0 && sp->base != tbase + tsize)
  859. sp = sp->next;
  860. if (sp != 0) {
  861. char *oldbase = sp->base;
  862. sp->base = tbase;
  863. sp->size += tsize;
  864. return prepend_alloc(m, tbase, oldbase, nb);
  865. } else {
  866. add_segment(m, tbase, tsize);
  867. }
  868. }
  869. if (nb < m->topsize) { /* Allocate from new or extended top space */
  870. size_t rsize = m->topsize -= nb;
  871. mchunkptr p = m->top;
  872. mchunkptr r = m->top = chunk_plus_offset(p, nb);
  873. r->head = rsize | PINUSE_BIT;
  874. set_size_and_pinuse_of_inuse_chunk(m, p, nb);
  875. return chunk2mem(p);
  876. }
  877. }
  878. return NULL;
  879. }
  880. /* ----------------------- system deallocation -------------------------- */
  881. /* Unmap and unlink any mmapped segments that don't contain used chunks */
  882. static size_t release_unused_segments(mstate m)
  883. {
  884. size_t released = 0;
  885. size_t nsegs = 0;
  886. msegmentptr pred = &m->seg;
  887. msegmentptr sp = pred->next;
  888. while (sp != 0) {
  889. char *base = sp->base;
  890. size_t size = sp->size;
  891. msegmentptr next = sp->next;
  892. nsegs++;
  893. {
  894. mchunkptr p = align_as_chunk(base);
  895. size_t psize = chunksize(p);
  896. /* Can unmap if first chunk holds entire segment and not pinned */
  897. if (!cinuse(p) && (char *)p + psize >= base + size - TOP_FOOT_SIZE) {
  898. tchunkptr tp = (tchunkptr)p;
  899. if (p == m->dv) {
  900. m->dv = 0;
  901. m->dvsize = 0;
  902. } else {
  903. unlink_large_chunk(m, tp);
  904. }
  905. if (CALL_MUNMAP(base, size) == 0) {
  906. released += size;
  907. /* unlink obsoleted record */
  908. sp = pred;
  909. sp->next = next;
  910. } else { /* back out if cannot unmap */
  911. insert_large_chunk(m, tp, psize);
  912. }
  913. }
  914. }
  915. pred = sp;
  916. sp = next;
  917. }
  918. /* Reset check counter */
  919. m->release_checks = nsegs > MAX_RELEASE_CHECK_RATE ?
  920. nsegs : MAX_RELEASE_CHECK_RATE;
  921. return released;
  922. }
  923. static int alloc_trim(mstate m, size_t pad)
  924. {
  925. size_t released = 0;
  926. if (pad < MAX_REQUEST && is_initialized(m)) {
  927. pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */
  928. if (m->topsize > pad) {
  929. /* Shrink top space in granularity-size units, keeping at least one */
  930. size_t unit = DEFAULT_GRANULARITY;
  931. size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit -
  932. SIZE_T_ONE) * unit;
  933. msegmentptr sp = segment_holding(m, (char *)m->top);
  934. if (sp->size >= extra &&
  935. !has_segment_link(m, sp)) { /* can't shrink if pinned */
  936. size_t newsize = sp->size - extra;
  937. /* Prefer mremap, fall back to munmap */
  938. if ((CALL_MREMAP(sp->base, sp->size, newsize, CALL_MREMAP_NOMOVE) != MFAIL) ||
  939. (CALL_MUNMAP(sp->base + newsize, extra) == 0)) {
  940. released = extra;
  941. }
  942. }
  943. if (released != 0) {
  944. sp->size -= released;
  945. init_top(m, m->top, m->topsize - released);
  946. }
  947. }
  948. /* Unmap any unused mmapped segments */
  949. released += release_unused_segments(m);
  950. /* On failure, disable autotrim to avoid repeated failed future calls */
  951. if (released == 0 && m->topsize > m->trim_check)
  952. m->trim_check = MAX_SIZE_T;
  953. }
  954. return (released != 0)? 1 : 0;
  955. }
  956. /* ---------------------------- malloc support --------------------------- */
  957. /* allocate a large request from the best fitting chunk in a treebin */
  958. static void *tmalloc_large(mstate m, size_t nb)
  959. {
  960. tchunkptr v = 0;
  961. size_t rsize = ~nb+1; /* Unsigned negation */
  962. tchunkptr t;
  963. bindex_t idx;
  964. compute_tree_index(nb, idx);
  965. if ((t = *treebin_at(m, idx)) != 0) {
  966. /* Traverse tree for this bin looking for node with size == nb */
  967. size_t sizebits = nb << leftshift_for_tree_index(idx);
  968. tchunkptr rst = 0; /* The deepest untaken right subtree */
  969. for (;;) {
  970. tchunkptr rt;
  971. size_t trem = chunksize(t) - nb;
  972. if (trem < rsize) {
  973. v = t;
  974. if ((rsize = trem) == 0)
  975. break;
  976. }
  977. rt = t->child[1];
  978. t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1];
  979. if (rt != 0 && rt != t)
  980. rst = rt;
  981. if (t == 0) {
  982. t = rst; /* set t to least subtree holding sizes > nb */
  983. break;
  984. }
  985. sizebits <<= 1;
  986. }
  987. }
  988. if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */
  989. binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap;
  990. if (leftbits != 0)
  991. t = *treebin_at(m, lj_ffs(leftbits));
  992. }
  993. while (t != 0) { /* find smallest of tree or subtree */
  994. size_t trem = chunksize(t) - nb;
  995. if (trem < rsize) {
  996. rsize = trem;
  997. v = t;
  998. }
  999. t = leftmost_child(t);
  1000. }
  1001. /* If dv is a better fit, return NULL so malloc will use it */
  1002. if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
  1003. mchunkptr r = chunk_plus_offset(v, nb);
  1004. unlink_large_chunk(m, v);
  1005. if (rsize < MIN_CHUNK_SIZE) {
  1006. set_inuse_and_pinuse(m, v, (rsize + nb));
  1007. } else {
  1008. set_size_and_pinuse_of_inuse_chunk(m, v, nb);
  1009. set_size_and_pinuse_of_free_chunk(r, rsize);
  1010. insert_chunk(m, r, rsize);
  1011. }
  1012. return chunk2mem(v);
  1013. }
  1014. return NULL;
  1015. }
  1016. /* allocate a small request from the best fitting chunk in a treebin */
  1017. static void *tmalloc_small(mstate m, size_t nb)
  1018. {
  1019. tchunkptr t, v;
  1020. mchunkptr r;
  1021. size_t rsize;
  1022. bindex_t i = lj_ffs(m->treemap);
  1023. v = t = *treebin_at(m, i);
  1024. rsize = chunksize(t) - nb;
  1025. while ((t = leftmost_child(t)) != 0) {
  1026. size_t trem = chunksize(t) - nb;
  1027. if (trem < rsize) {
  1028. rsize = trem;
  1029. v = t;
  1030. }
  1031. }
  1032. r = chunk_plus_offset(v, nb);
  1033. unlink_large_chunk(m, v);
  1034. if (rsize < MIN_CHUNK_SIZE) {
  1035. set_inuse_and_pinuse(m, v, (rsize + nb));
  1036. } else {
  1037. set_size_and_pinuse_of_inuse_chunk(m, v, nb);
  1038. set_size_and_pinuse_of_free_chunk(r, rsize);
  1039. replace_dv(m, r, rsize);
  1040. }
  1041. return chunk2mem(v);
  1042. }
  1043. /* ----------------------------------------------------------------------- */
  1044. void *lj_alloc_create(PRNGState *rs)
  1045. {
  1046. size_t tsize = DEFAULT_GRANULARITY;
  1047. char *tbase;
  1048. INIT_MMAP();
  1049. UNUSED(rs);
  1050. tbase = (char *)(CALL_MMAP(rs, tsize));
  1051. if (tbase != CMFAIL) {
  1052. size_t msize = pad_request(sizeof(struct malloc_state));
  1053. mchunkptr mn;
  1054. mchunkptr msp = align_as_chunk(tbase);
  1055. mstate m = (mstate)(chunk2mem(msp));
  1056. memset(m, 0, msize);
  1057. msp->head = (msize|PINUSE_BIT|CINUSE_BIT);
  1058. m->seg.base = tbase;
  1059. m->seg.size = tsize;
  1060. m->release_checks = MAX_RELEASE_CHECK_RATE;
  1061. init_bins(m);
  1062. mn = next_chunk(mem2chunk(m));
  1063. init_top(m, mn, (size_t)((tbase + tsize) - (char *)mn) - TOP_FOOT_SIZE);
  1064. return m;
  1065. }
  1066. return NULL;
  1067. }
  1068. void lj_alloc_setprng(void *msp, PRNGState *rs)
  1069. {
  1070. mstate ms = (mstate)msp;
  1071. ms->prng = rs;
  1072. }
  1073. void lj_alloc_destroy(void *msp)
  1074. {
  1075. mstate ms = (mstate)msp;
  1076. msegmentptr sp = &ms->seg;
  1077. while (sp != 0) {
  1078. char *base = sp->base;
  1079. size_t size = sp->size;
  1080. sp = sp->next;
  1081. CALL_MUNMAP(base, size);
  1082. }
  1083. }
  1084. static LJ_NOINLINE void *lj_alloc_malloc(void *msp, size_t nsize)
  1085. {
  1086. mstate ms = (mstate)msp;
  1087. void *mem;
  1088. size_t nb;
  1089. if (nsize <= MAX_SMALL_REQUEST) {
  1090. bindex_t idx;
  1091. binmap_t smallbits;
  1092. nb = (nsize < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(nsize);
  1093. idx = small_index(nb);
  1094. smallbits = ms->smallmap >> idx;
  1095. if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */
  1096. mchunkptr b, p;
  1097. idx += ~smallbits & 1; /* Uses next bin if idx empty */
  1098. b = smallbin_at(ms, idx);
  1099. p = b->fd;
  1100. unlink_first_small_chunk(ms, b, p, idx);
  1101. set_inuse_and_pinuse(ms, p, small_index2size(idx));
  1102. mem = chunk2mem(p);
  1103. return mem;
  1104. } else if (nb > ms->dvsize) {
  1105. if (smallbits != 0) { /* Use chunk in next nonempty smallbin */
  1106. mchunkptr b, p, r;
  1107. size_t rsize;
  1108. binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx));
  1109. bindex_t i = lj_ffs(leftbits);
  1110. b = smallbin_at(ms, i);
  1111. p = b->fd;
  1112. unlink_first_small_chunk(ms, b, p, i);
  1113. rsize = small_index2size(i) - nb;
  1114. /* Fit here cannot be remainderless if 4byte sizes */
  1115. if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) {
  1116. set_inuse_and_pinuse(ms, p, small_index2size(i));
  1117. } else {
  1118. set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
  1119. r = chunk_plus_offset(p, nb);
  1120. set_size_and_pinuse_of_free_chunk(r, rsize);
  1121. replace_dv(ms, r, rsize);
  1122. }
  1123. mem = chunk2mem(p);
  1124. return mem;
  1125. } else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) {
  1126. return mem;
  1127. }
  1128. }
  1129. } else if (nsize >= MAX_REQUEST) {
  1130. nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */
  1131. } else {
  1132. nb = pad_request(nsize);
  1133. if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
  1134. return mem;
  1135. }
  1136. }
  1137. if (nb <= ms->dvsize) {
  1138. size_t rsize = ms->dvsize - nb;
  1139. mchunkptr p = ms->dv;
  1140. if (rsize >= MIN_CHUNK_SIZE) { /* split dv */
  1141. mchunkptr r = ms->dv = chunk_plus_offset(p, nb);
  1142. ms->dvsize = rsize;
  1143. set_size_and_pinuse_of_free_chunk(r, rsize);
  1144. set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
  1145. } else { /* exhaust dv */
  1146. size_t dvs = ms->dvsize;
  1147. ms->dvsize = 0;
  1148. ms->dv = 0;
  1149. set_inuse_and_pinuse(ms, p, dvs);
  1150. }
  1151. mem = chunk2mem(p);
  1152. return mem;
  1153. } else if (nb < ms->topsize) { /* Split top */
  1154. size_t rsize = ms->topsize -= nb;
  1155. mchunkptr p = ms->top;
  1156. mchunkptr r = ms->top = chunk_plus_offset(p, nb);
  1157. r->head = rsize | PINUSE_BIT;
  1158. set_size_and_pinuse_of_inuse_chunk(ms, p, nb);
  1159. mem = chunk2mem(p);
  1160. return mem;
  1161. }
  1162. return alloc_sys(ms, nb);
  1163. }
  1164. static LJ_NOINLINE void *lj_alloc_free(void *msp, void *ptr)
  1165. {
  1166. if (ptr != 0) {
  1167. mchunkptr p = mem2chunk(ptr);
  1168. mstate fm = (mstate)msp;
  1169. size_t psize = chunksize(p);
  1170. mchunkptr next = chunk_plus_offset(p, psize);
  1171. if (!pinuse(p)) {
  1172. size_t prevsize = p->prev_foot;
  1173. if ((prevsize & IS_DIRECT_BIT) != 0) {
  1174. prevsize &= ~IS_DIRECT_BIT;
  1175. psize += prevsize + DIRECT_FOOT_PAD;
  1176. CALL_MUNMAP((char *)p - prevsize, psize);
  1177. return NULL;
  1178. } else {
  1179. mchunkptr prev = chunk_minus_offset(p, prevsize);
  1180. psize += prevsize;
  1181. p = prev;
  1182. /* consolidate backward */
  1183. if (p != fm->dv) {
  1184. unlink_chunk(fm, p, prevsize);
  1185. } else if ((next->head & INUSE_BITS) == INUSE_BITS) {
  1186. fm->dvsize = psize;
  1187. set_free_with_pinuse(p, psize, next);
  1188. return NULL;
  1189. }
  1190. }
  1191. }
  1192. if (!cinuse(next)) { /* consolidate forward */
  1193. if (next == fm->top) {
  1194. size_t tsize = fm->topsize += psize;
  1195. fm->top = p;
  1196. p->head = tsize | PINUSE_BIT;
  1197. if (p == fm->dv) {
  1198. fm->dv = 0;
  1199. fm->dvsize = 0;
  1200. }
  1201. if (tsize > fm->trim_check)
  1202. alloc_trim(fm, 0);
  1203. return NULL;
  1204. } else if (next == fm->dv) {
  1205. size_t dsize = fm->dvsize += psize;
  1206. fm->dv = p;
  1207. set_size_and_pinuse_of_free_chunk(p, dsize);
  1208. return NULL;
  1209. } else {
  1210. size_t nsize = chunksize(next);
  1211. psize += nsize;
  1212. unlink_chunk(fm, next, nsize);
  1213. set_size_and_pinuse_of_free_chunk(p, psize);
  1214. if (p == fm->dv) {
  1215. fm->dvsize = psize;
  1216. return NULL;
  1217. }
  1218. }
  1219. } else {
  1220. set_free_with_pinuse(p, psize, next);
  1221. }
  1222. if (is_small(psize)) {
  1223. insert_small_chunk(fm, p, psize);
  1224. } else {
  1225. tchunkptr tp = (tchunkptr)p;
  1226. insert_large_chunk(fm, tp, psize);
  1227. if (--fm->release_checks == 0)
  1228. release_unused_segments(fm);
  1229. }
  1230. }
  1231. return NULL;
  1232. }
  1233. static LJ_NOINLINE void *lj_alloc_realloc(void *msp, void *ptr, size_t nsize)
  1234. {
  1235. if (nsize >= MAX_REQUEST) {
  1236. return NULL;
  1237. } else {
  1238. mstate m = (mstate)msp;
  1239. mchunkptr oldp = mem2chunk(ptr);
  1240. size_t oldsize = chunksize(oldp);
  1241. mchunkptr next = chunk_plus_offset(oldp, oldsize);
  1242. mchunkptr newp = 0;
  1243. size_t nb = request2size(nsize);
  1244. /* Try to either shrink or extend into top. Else malloc-copy-free */
  1245. if (is_direct(oldp)) {
  1246. newp = direct_resize(oldp, nb); /* this may return NULL. */
  1247. } else if (oldsize >= nb) { /* already big enough */
  1248. size_t rsize = oldsize - nb;
  1249. newp = oldp;
  1250. if (rsize >= MIN_CHUNK_SIZE) {
  1251. mchunkptr rem = chunk_plus_offset(newp, nb);
  1252. set_inuse(m, newp, nb);
  1253. set_inuse(m, rem, rsize);
  1254. lj_alloc_free(m, chunk2mem(rem));
  1255. }
  1256. } else if (next == m->top && oldsize + m->topsize > nb) {
  1257. /* Expand into top */
  1258. size_t newsize = oldsize + m->topsize;
  1259. size_t newtopsize = newsize - nb;
  1260. mchunkptr newtop = chunk_plus_offset(oldp, nb);
  1261. set_inuse(m, oldp, nb);
  1262. newtop->head = newtopsize |PINUSE_BIT;
  1263. m->top = newtop;
  1264. m->topsize = newtopsize;
  1265. newp = oldp;
  1266. }
  1267. if (newp != 0) {
  1268. return chunk2mem(newp);
  1269. } else {
  1270. void *newmem = lj_alloc_malloc(m, nsize);
  1271. if (newmem != 0) {
  1272. size_t oc = oldsize - overhead_for(oldp);
  1273. memcpy(newmem, ptr, oc < nsize ? oc : nsize);
  1274. lj_alloc_free(m, ptr);
  1275. }
  1276. return newmem;
  1277. }
  1278. }
  1279. }
  1280. void *lj_alloc_f(void *msp, void *ptr, size_t osize, size_t nsize)
  1281. {
  1282. (void)osize;
  1283. if (nsize == 0) {
  1284. return lj_alloc_free(msp, ptr);
  1285. } else if (ptr == NULL) {
  1286. return lj_alloc_malloc(msp, nsize);
  1287. } else {
  1288. return lj_alloc_realloc(msp, ptr, nsize);
  1289. }
  1290. }
  1291. #endif