PageRenderTime 56ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 1ms

/JavaScriptCore/wtf/FastMalloc.cpp

https://github.com/akil/qtwebkit
C++ | 3632 lines | 2493 code | 476 blank | 663 comment | 449 complexity | 197eae57114d7396eb082b0490fdc763 MD5 | raw file
Possible License(s): LGPL-2.1, LGPL-2.0, BSD-3-Clause, MPL-2.0-no-copyleft-exception

Large files files are truncated, but you can click here to view the full file

  1. // Copyright (c) 2005, 2007, Google Inc.
  2. // All rights reserved.
  3. //
  4. // Redistribution and use in source and binary forms, with or without
  5. // modification, are permitted provided that the following conditions are
  6. // met:
  7. //
  8. // * Redistributions of source code must retain the above copyright
  9. // notice, this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above
  11. // copyright notice, this list of conditions and the following disclaimer
  12. // in the documentation and/or other materials provided with the
  13. // distribution.
  14. // * Neither the name of Google Inc. nor the names of its
  15. // contributors may be used to endorse or promote products derived from
  16. // this software without specific prior written permission.
  17. //
  18. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  19. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  21. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  22. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  23. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  24. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  25. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  28. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. // ---
  30. // Author: Sanjay Ghemawat <opensource@google.com>
  31. //
  32. // A malloc that uses a per-thread cache to satisfy small malloc requests.
  33. // (The time for malloc/free of a small object drops from 300 ns to 50 ns.)
  34. //
  35. // See doc/tcmalloc.html for a high-level
  36. // description of how this malloc works.
  37. //
  38. // SYNCHRONIZATION
  39. // 1. The thread-specific lists are accessed without acquiring any locks.
  40. // This is safe because each such list is only accessed by one thread.
  41. // 2. We have a lock per central free-list, and hold it while manipulating
  42. // the central free list for a particular size.
  43. // 3. The central page allocator is protected by "pageheap_lock".
  44. // 4. The pagemap (which maps from page-number to descriptor),
  45. // can be read without holding any locks, and written while holding
  46. // the "pageheap_lock".
  47. // 5. To improve performance, a subset of the information one can get
  48. // from the pagemap is cached in a data structure, pagemap_cache_,
  49. // that atomically reads and writes its entries. This cache can be
  50. // read and written without locking.
  51. //
  52. // This multi-threaded access to the pagemap is safe for fairly
  53. // subtle reasons. We basically assume that when an object X is
  54. // allocated by thread A and deallocated by thread B, there must
  55. // have been appropriate synchronization in the handoff of object
  56. // X from thread A to thread B. The same logic applies to pagemap_cache_.
  57. //
  58. // THE PAGEID-TO-SIZECLASS CACHE
  59. // Hot PageID-to-sizeclass mappings are held by pagemap_cache_. If this cache
  60. // returns 0 for a particular PageID then that means "no information," not that
  61. // the sizeclass is 0. The cache may have stale information for pages that do
  62. // not hold the beginning of any free()'able object. Staleness is eliminated
  63. // in Populate() for pages with sizeclass > 0 objects, and in do_malloc() and
  64. // do_memalign() for all other relevant pages.
  65. //
  66. // TODO: Bias reclamation to larger addresses
  67. // TODO: implement mallinfo/mallopt
  68. // TODO: Better testing
  69. //
  70. // 9/28/2003 (new page-level allocator replaces ptmalloc2):
  71. // * malloc/free of small objects goes from ~300 ns to ~50 ns.
  72. // * allocation of a reasonably complicated struct
  73. // goes from about 1100 ns to about 300 ns.
  74. #include "config.h"
  75. #include "FastMalloc.h"
  76. #include "Assertions.h"
  77. #if USE(MULTIPLE_THREADS)
  78. #include <pthread.h>
  79. #endif
  80. #ifndef NO_TCMALLOC_SAMPLES
  81. #ifdef WTF_CHANGES
  82. #define NO_TCMALLOC_SAMPLES
  83. #endif
  84. #endif
  85. #if !defined(USE_SYSTEM_MALLOC) && defined(NDEBUG)
  86. #define FORCE_SYSTEM_MALLOC 0
  87. #else
  88. #define FORCE_SYSTEM_MALLOC 1
  89. #endif
  90. #ifndef NDEBUG
  91. namespace WTF {
  92. #if USE(MULTIPLE_THREADS)
  93. static pthread_key_t isForbiddenKey;
  94. static pthread_once_t isForbiddenKeyOnce = PTHREAD_ONCE_INIT;
  95. static void initializeIsForbiddenKey()
  96. {
  97. pthread_key_create(&isForbiddenKey, 0);
  98. }
  99. static bool isForbidden()
  100. {
  101. pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey);
  102. return !!pthread_getspecific(isForbiddenKey);
  103. }
  104. void fastMallocForbid()
  105. {
  106. pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey);
  107. pthread_setspecific(isForbiddenKey, &isForbiddenKey);
  108. }
  109. void fastMallocAllow()
  110. {
  111. pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey);
  112. pthread_setspecific(isForbiddenKey, 0);
  113. }
  114. #else
  115. static bool staticIsForbidden;
  116. static bool isForbidden()
  117. {
  118. return staticIsForbidden;
  119. }
  120. void fastMallocForbid()
  121. {
  122. staticIsForbidden = true;
  123. }
  124. void fastMallocAllow()
  125. {
  126. staticIsForbidden = false;
  127. }
  128. #endif // USE(MULTIPLE_THREADS)
  129. } // namespace WTF
  130. #endif // NDEBUG
  131. #include <string.h>
  132. namespace WTF {
  133. void *fastZeroedMalloc(size_t n)
  134. {
  135. void *result = fastMalloc(n);
  136. if (!result)
  137. return 0;
  138. memset(result, 0, n);
  139. #ifndef WTF_CHANGES
  140. MallocHook::InvokeNewHook(result, n);
  141. #endif
  142. return result;
  143. }
  144. }
  145. #if FORCE_SYSTEM_MALLOC
  146. #include <stdlib.h>
  147. #if !PLATFORM(WIN_OS)
  148. #include <pthread.h>
  149. #endif
  150. namespace WTF {
  151. void *fastMalloc(size_t n)
  152. {
  153. ASSERT(!isForbidden());
  154. return malloc(n);
  155. }
  156. void *fastCalloc(size_t n_elements, size_t element_size)
  157. {
  158. ASSERT(!isForbidden());
  159. return calloc(n_elements, element_size);
  160. }
  161. void fastFree(void* p)
  162. {
  163. ASSERT(!isForbidden());
  164. free(p);
  165. }
  166. void *fastRealloc(void* p, size_t n)
  167. {
  168. ASSERT(!isForbidden());
  169. return realloc(p, n);
  170. }
  171. } // namespace WTF
  172. #if PLATFORM(DARWIN)
  173. // This symbol is present in the JavaScriptCore exports file even when FastMalloc is disabled.
  174. // It will never be used in this case, so it's type and value are less interesting than its presence.
  175. extern "C" const int jscore_fastmalloc_introspection = 0;
  176. #endif
  177. #else
  178. #if HAVE(STDINT_H)
  179. #include <stdint.h>
  180. #elif HAVE(INTTYPES_H)
  181. #include <inttypes.h>
  182. #else
  183. #include <sys/types.h>
  184. #endif
  185. #include "AlwaysInline.h"
  186. #include "Assertions.h"
  187. #include "TCPackedCache.h"
  188. #include "TCPageMap.h"
  189. #include "TCSpinLock.h"
  190. #include "TCSystemAlloc.h"
  191. #include <algorithm>
  192. #include <errno.h>
  193. #include <new>
  194. #include <pthread.h>
  195. #include <stdarg.h>
  196. #include <stddef.h>
  197. #include <stdio.h>
  198. #if COMPILER(MSVC)
  199. #ifndef WIN32_LEAN_AND_MEAN
  200. #define WIN32_LEAN_AND_MEAN
  201. #endif
  202. #include <windows.h>
  203. #endif
  204. #if WTF_CHANGES
  205. #if PLATFORM(DARWIN)
  206. #include "MallocZoneSupport.h"
  207. #include <wtf/HashSet.h>
  208. #endif
  209. #ifndef PRIuS
  210. #define PRIuS "zu"
  211. #endif
  212. // Calling pthread_getspecific through a global function pointer is faster than a normal
  213. // call to the function on Mac OS X, and it's used in performance-critical code. So we
  214. // use a function pointer. But that's not necessarily faster on other platforms, and we had
  215. // problems with this technique on Windows, so we'll do this only on Mac OS X.
  216. #if PLATFORM(DARWIN)
  217. static void* (*pthread_getspecific_function_pointer)(pthread_key_t) = pthread_getspecific;
  218. #define pthread_getspecific(key) pthread_getspecific_function_pointer(key)
  219. #endif
  220. #define DEFINE_VARIABLE(type, name, value, meaning) \
  221. namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead { \
  222. type FLAGS_##name(value); \
  223. char FLAGS_no##name; \
  224. } \
  225. using FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead::FLAGS_##name
  226. #define DEFINE_int64(name, value, meaning) \
  227. DEFINE_VARIABLE(int64_t, name, value, meaning)
  228. #define DEFINE_double(name, value, meaning) \
  229. DEFINE_VARIABLE(double, name, value, meaning)
  230. namespace WTF {
  231. #define malloc fastMalloc
  232. #define calloc fastCalloc
  233. #define free fastFree
  234. #define realloc fastRealloc
  235. #define MESSAGE LOG_ERROR
  236. #define CHECK_CONDITION ASSERT
  237. #if PLATFORM(DARWIN)
  238. class TCMalloc_PageHeap;
  239. class TCMalloc_ThreadCache;
  240. class TCMalloc_Central_FreeListPadded;
  241. class FastMallocZone {
  242. public:
  243. static void init();
  244. static kern_return_t enumerate(task_t, void*, unsigned typeMmask, vm_address_t zoneAddress, memory_reader_t, vm_range_recorder_t);
  245. static size_t goodSize(malloc_zone_t*, size_t size) { return size; }
  246. static boolean_t check(malloc_zone_t*) { return true; }
  247. static void print(malloc_zone_t*, boolean_t) { }
  248. static void log(malloc_zone_t*, void*) { }
  249. static void forceLock(malloc_zone_t*) { }
  250. static void forceUnlock(malloc_zone_t*) { }
  251. static void statistics(malloc_zone_t*, malloc_statistics_t*) { }
  252. private:
  253. FastMallocZone(TCMalloc_PageHeap*, TCMalloc_ThreadCache**, TCMalloc_Central_FreeListPadded*);
  254. static size_t size(malloc_zone_t*, const void*);
  255. static void* zoneMalloc(malloc_zone_t*, size_t);
  256. static void* zoneCalloc(malloc_zone_t*, size_t numItems, size_t size);
  257. static void zoneFree(malloc_zone_t*, void*);
  258. static void* zoneRealloc(malloc_zone_t*, void*, size_t);
  259. static void* zoneValloc(malloc_zone_t*, size_t) { LOG_ERROR("valloc is not supported"); return 0; }
  260. static void zoneDestroy(malloc_zone_t*) { }
  261. malloc_zone_t m_zone;
  262. TCMalloc_PageHeap* m_pageHeap;
  263. TCMalloc_ThreadCache** m_threadHeaps;
  264. TCMalloc_Central_FreeListPadded* m_centralCaches;
  265. };
  266. #endif
  267. #endif
  268. #ifndef WTF_CHANGES
  269. // This #ifdef should almost never be set. Set NO_TCMALLOC_SAMPLES if
  270. // you're porting to a system where you really can't get a stacktrace.
  271. #ifdef NO_TCMALLOC_SAMPLES
  272. // We use #define so code compiles even if you #include stacktrace.h somehow.
  273. # define GetStackTrace(stack, depth, skip) (0)
  274. #else
  275. # include <google/stacktrace.h>
  276. #endif
  277. #endif
  278. // Even if we have support for thread-local storage in the compiler
  279. // and linker, the OS may not support it. We need to check that at
  280. // runtime. Right now, we have to keep a manual set of "bad" OSes.
  281. #if defined(HAVE_TLS)
  282. static bool kernel_supports_tls = false; // be conservative
  283. static inline bool KernelSupportsTLS() {
  284. return kernel_supports_tls;
  285. }
  286. # if !HAVE_DECL_UNAME // if too old for uname, probably too old for TLS
  287. static void CheckIfKernelSupportsTLS() {
  288. kernel_supports_tls = false;
  289. }
  290. # else
  291. # include <sys/utsname.h> // DECL_UNAME checked for <sys/utsname.h> too
  292. static void CheckIfKernelSupportsTLS() {
  293. struct utsname buf;
  294. if (uname(&buf) != 0) { // should be impossible
  295. MESSAGE("uname failed assuming no TLS support (errno=%d)\n", errno);
  296. kernel_supports_tls = false;
  297. } else if (strcasecmp(buf.sysname, "linux") == 0) {
  298. // The linux case: the first kernel to support TLS was 2.6.0
  299. if (buf.release[0] < '2' && buf.release[1] == '.') // 0.x or 1.x
  300. kernel_supports_tls = false;
  301. else if (buf.release[0] == '2' && buf.release[1] == '.' &&
  302. buf.release[2] >= '0' && buf.release[2] < '6' &&
  303. buf.release[3] == '.') // 2.0 - 2.5
  304. kernel_supports_tls = false;
  305. else
  306. kernel_supports_tls = true;
  307. } else { // some other kernel, we'll be optimisitic
  308. kernel_supports_tls = true;
  309. }
  310. // TODO(csilvers): VLOG(1) the tls status once we support RAW_VLOG
  311. }
  312. # endif // HAVE_DECL_UNAME
  313. #endif // HAVE_TLS
  314. // __THROW is defined in glibc systems. It means, counter-intuitively,
  315. // "This function will never throw an exception." It's an optional
  316. // optimization tool, but we may need to use it to match glibc prototypes.
  317. #ifndef __THROW // I guess we're not on a glibc system
  318. # define __THROW // __THROW is just an optimization, so ok to make it ""
  319. #endif
  320. //-------------------------------------------------------------------
  321. // Configuration
  322. //-------------------------------------------------------------------
  323. // Not all possible combinations of the following parameters make
  324. // sense. In particular, if kMaxSize increases, you may have to
  325. // increase kNumClasses as well.
  326. static const size_t kPageShift = 12;
  327. static const size_t kPageSize = 1 << kPageShift;
  328. static const size_t kMaxSize = 8u * kPageSize;
  329. static const size_t kAlignShift = 3;
  330. static const size_t kAlignment = 1 << kAlignShift;
  331. static const size_t kNumClasses = 68;
  332. // Allocates a big block of memory for the pagemap once we reach more than
  333. // 128MB
  334. static const size_t kPageMapBigAllocationThreshold = 128 << 20;
  335. // Minimum number of pages to fetch from system at a time. Must be
  336. // significantly bigger than kBlockSize to amortize system-call
  337. // overhead, and also to reduce external fragementation. Also, we
  338. // should keep this value big because various incarnations of Linux
  339. // have small limits on the number of mmap() regions per
  340. // address-space.
  341. static const size_t kMinSystemAlloc = 1 << (20 - kPageShift);
  342. // Number of objects to move between a per-thread list and a central
  343. // list in one shot. We want this to be not too small so we can
  344. // amortize the lock overhead for accessing the central list. Making
  345. // it too big may temporarily cause unnecessary memory wastage in the
  346. // per-thread free list until the scavenger cleans up the list.
  347. static int num_objects_to_move[kNumClasses];
  348. // Maximum length we allow a per-thread free-list to have before we
  349. // move objects from it into the corresponding central free-list. We
  350. // want this big to avoid locking the central free-list too often. It
  351. // should not hurt to make this list somewhat big because the
  352. // scavenging code will shrink it down when its contents are not in use.
  353. static const int kMaxFreeListLength = 256;
  354. // Lower and upper bounds on the per-thread cache sizes
  355. static const size_t kMinThreadCacheSize = kMaxSize * 2;
  356. static const size_t kMaxThreadCacheSize = 2 << 20;
  357. // Default bound on the total amount of thread caches
  358. static const size_t kDefaultOverallThreadCacheSize = 16 << 20;
  359. // For all span-lengths < kMaxPages we keep an exact-size list.
  360. // REQUIRED: kMaxPages >= kMinSystemAlloc;
  361. static const size_t kMaxPages = kMinSystemAlloc;
  362. /* The smallest prime > 2^n */
  363. static int primes_list[] = {
  364. // Small values might cause high rates of sampling
  365. // and hence commented out.
  366. // 2, 5, 11, 17, 37, 67, 131, 257,
  367. // 521, 1031, 2053, 4099, 8209, 16411,
  368. 32771, 65537, 131101, 262147, 524309, 1048583,
  369. 2097169, 4194319, 8388617, 16777259, 33554467 };
  370. // Twice the approximate gap between sampling actions.
  371. // I.e., we take one sample approximately once every
  372. // tcmalloc_sample_parameter/2
  373. // bytes of allocation, i.e., ~ once every 128KB.
  374. // Must be a prime number.
  375. #ifdef NO_TCMALLOC_SAMPLES
  376. DEFINE_int64(tcmalloc_sample_parameter, 0,
  377. "Unused: code is compiled with NO_TCMALLOC_SAMPLES");
  378. static size_t sample_period = 0;
  379. #else
  380. DEFINE_int64(tcmalloc_sample_parameter, 262147,
  381. "Twice the approximate gap between sampling actions."
  382. " Must be a prime number. Otherwise will be rounded up to a "
  383. " larger prime number");
  384. static size_t sample_period = 262147;
  385. #endif
  386. // Protects sample_period above
  387. static SpinLock sample_period_lock = SPINLOCK_INITIALIZER;
  388. // Parameters for controlling how fast memory is returned to the OS.
  389. DEFINE_double(tcmalloc_release_rate, 1,
  390. "Rate at which we release unused memory to the system. "
  391. "Zero means we never release memory back to the system. "
  392. "Increase this flag to return memory faster; decrease it "
  393. "to return memory slower. Reasonable rates are in the "
  394. "range [0,10]");
  395. //-------------------------------------------------------------------
  396. // Mapping from size to size_class and vice versa
  397. //-------------------------------------------------------------------
  398. // Sizes <= 1024 have an alignment >= 8. So for such sizes we have an
  399. // array indexed by ceil(size/8). Sizes > 1024 have an alignment >= 128.
  400. // So for these larger sizes we have an array indexed by ceil(size/128).
  401. //
  402. // We flatten both logical arrays into one physical array and use
  403. // arithmetic to compute an appropriate index. The constants used by
  404. // ClassIndex() were selected to make the flattening work.
  405. //
  406. // Examples:
  407. // Size Expression Index
  408. // -------------------------------------------------------
  409. // 0 (0 + 7) / 8 0
  410. // 1 (1 + 7) / 8 1
  411. // ...
  412. // 1024 (1024 + 7) / 8 128
  413. // 1025 (1025 + 127 + (120<<7)) / 128 129
  414. // ...
  415. // 32768 (32768 + 127 + (120<<7)) / 128 376
  416. static const size_t kMaxSmallSize = 1024;
  417. static const int shift_amount[2] = { 3, 7 }; // For divides by 8 or 128
  418. static const int add_amount[2] = { 7, 127 + (120 << 7) };
  419. static unsigned char class_array[377];
  420. // Compute index of the class_array[] entry for a given size
  421. static inline int ClassIndex(size_t s) {
  422. const int i = (s > kMaxSmallSize);
  423. return static_cast<int>((s + add_amount[i]) >> shift_amount[i]);
  424. }
  425. // Mapping from size class to max size storable in that class
  426. static size_t class_to_size[kNumClasses];
  427. // Mapping from size class to number of pages to allocate at a time
  428. static size_t class_to_pages[kNumClasses];
  429. // TransferCache is used to cache transfers of num_objects_to_move[size_class]
  430. // back and forth between thread caches and the central cache for a given size
  431. // class.
  432. struct TCEntry {
  433. void *head; // Head of chain of objects.
  434. void *tail; // Tail of chain of objects.
  435. };
  436. // A central cache freelist can have anywhere from 0 to kNumTransferEntries
  437. // slots to put link list chains into. To keep memory usage bounded the total
  438. // number of TCEntries across size classes is fixed. Currently each size
  439. // class is initially given one TCEntry which also means that the maximum any
  440. // one class can have is kNumClasses.
  441. static const int kNumTransferEntries = kNumClasses;
  442. // Note: the following only works for "n"s that fit in 32-bits, but
  443. // that is fine since we only use it for small sizes.
  444. static inline int LgFloor(size_t n) {
  445. int log = 0;
  446. for (int i = 4; i >= 0; --i) {
  447. int shift = (1 << i);
  448. size_t x = n >> shift;
  449. if (x != 0) {
  450. n = x;
  451. log += shift;
  452. }
  453. }
  454. ASSERT(n == 1);
  455. return log;
  456. }
  457. // Some very basic linked list functions for dealing with using void * as
  458. // storage.
  459. static inline void *SLL_Next(void *t) {
  460. return *(reinterpret_cast<void**>(t));
  461. }
  462. static inline void SLL_SetNext(void *t, void *n) {
  463. *(reinterpret_cast<void**>(t)) = n;
  464. }
  465. static inline void SLL_Push(void **list, void *element) {
  466. SLL_SetNext(element, *list);
  467. *list = element;
  468. }
  469. static inline void *SLL_Pop(void **list) {
  470. void *result = *list;
  471. *list = SLL_Next(*list);
  472. return result;
  473. }
  474. // Remove N elements from a linked list to which head points. head will be
  475. // modified to point to the new head. start and end will point to the first
  476. // and last nodes of the range. Note that end will point to NULL after this
  477. // function is called.
  478. static inline void SLL_PopRange(void **head, int N, void **start, void **end) {
  479. if (N == 0) {
  480. *start = NULL;
  481. *end = NULL;
  482. return;
  483. }
  484. void *tmp = *head;
  485. for (int i = 1; i < N; ++i) {
  486. tmp = SLL_Next(tmp);
  487. }
  488. *start = *head;
  489. *end = tmp;
  490. *head = SLL_Next(tmp);
  491. // Unlink range from list.
  492. SLL_SetNext(tmp, NULL);
  493. }
  494. static inline void SLL_PushRange(void **head, void *start, void *end) {
  495. if (!start) return;
  496. SLL_SetNext(end, *head);
  497. *head = start;
  498. }
  499. static inline size_t SLL_Size(void *head) {
  500. int count = 0;
  501. while (head) {
  502. count++;
  503. head = SLL_Next(head);
  504. }
  505. return count;
  506. }
  507. // Setup helper functions.
  508. static ALWAYS_INLINE size_t SizeClass(size_t size) {
  509. return class_array[ClassIndex(size)];
  510. }
  511. // Get the byte-size for a specified class
  512. static ALWAYS_INLINE size_t ByteSizeForClass(size_t cl) {
  513. return class_to_size[cl];
  514. }
  515. static int NumMoveSize(size_t size) {
  516. if (size == 0) return 0;
  517. // Use approx 64k transfers between thread and central caches.
  518. int num = static_cast<int>(64.0 * 1024.0 / size);
  519. if (num < 2) num = 2;
  520. // Clamp well below kMaxFreeListLength to avoid ping pong between central
  521. // and thread caches.
  522. if (num > static_cast<int>(0.8 * kMaxFreeListLength))
  523. num = static_cast<int>(0.8 * kMaxFreeListLength);
  524. // Also, avoid bringing in too many objects into small object free
  525. // lists. There are lots of such lists, and if we allow each one to
  526. // fetch too many at a time, we end up having to scavenge too often
  527. // (especially when there are lots of threads and each thread gets a
  528. // small allowance for its thread cache).
  529. //
  530. // TODO: Make thread cache free list sizes dynamic so that we do not
  531. // have to equally divide a fixed resource amongst lots of threads.
  532. if (num > 32) num = 32;
  533. return num;
  534. }
  535. // Initialize the mapping arrays
  536. static void InitSizeClasses() {
  537. // Do some sanity checking on add_amount[]/shift_amount[]/class_array[]
  538. if (ClassIndex(0) < 0) {
  539. MESSAGE("Invalid class index %d for size 0\n", ClassIndex(0));
  540. abort();
  541. }
  542. if (static_cast<size_t>(ClassIndex(kMaxSize)) >= sizeof(class_array)) {
  543. MESSAGE("Invalid class index %d for kMaxSize\n", ClassIndex(kMaxSize));
  544. abort();
  545. }
  546. // Compute the size classes we want to use
  547. size_t sc = 1; // Next size class to assign
  548. unsigned char alignshift = kAlignShift;
  549. int last_lg = -1;
  550. for (size_t size = kAlignment; size <= kMaxSize; size += (1 << alignshift)) {
  551. int lg = LgFloor(size);
  552. if (lg > last_lg) {
  553. // Increase alignment every so often.
  554. //
  555. // Since we double the alignment every time size doubles and
  556. // size >= 128, this means that space wasted due to alignment is
  557. // at most 16/128 i.e., 12.5%. Plus we cap the alignment at 256
  558. // bytes, so the space wasted as a percentage starts falling for
  559. // sizes > 2K.
  560. if ((lg >= 7) && (alignshift < 8)) {
  561. alignshift++;
  562. }
  563. last_lg = lg;
  564. }
  565. // Allocate enough pages so leftover is less than 1/8 of total.
  566. // This bounds wasted space to at most 12.5%.
  567. size_t psize = kPageSize;
  568. while ((psize % size) > (psize >> 3)) {
  569. psize += kPageSize;
  570. }
  571. const size_t my_pages = psize >> kPageShift;
  572. if (sc > 1 && my_pages == class_to_pages[sc-1]) {
  573. // See if we can merge this into the previous class without
  574. // increasing the fragmentation of the previous class.
  575. const size_t my_objects = (my_pages << kPageShift) / size;
  576. const size_t prev_objects = (class_to_pages[sc-1] << kPageShift)
  577. / class_to_size[sc-1];
  578. if (my_objects == prev_objects) {
  579. // Adjust last class to include this size
  580. class_to_size[sc-1] = size;
  581. continue;
  582. }
  583. }
  584. // Add new class
  585. class_to_pages[sc] = my_pages;
  586. class_to_size[sc] = size;
  587. sc++;
  588. }
  589. if (sc != kNumClasses) {
  590. MESSAGE("wrong number of size classes: found %" PRIuS " instead of %d\n",
  591. sc, int(kNumClasses));
  592. abort();
  593. }
  594. // Initialize the mapping arrays
  595. int next_size = 0;
  596. for (unsigned char c = 1; c < kNumClasses; c++) {
  597. const size_t max_size_in_class = class_to_size[c];
  598. for (size_t s = next_size; s <= max_size_in_class; s += kAlignment) {
  599. class_array[ClassIndex(s)] = c;
  600. }
  601. next_size = static_cast<int>(max_size_in_class + kAlignment);
  602. }
  603. // Double-check sizes just to be safe
  604. for (size_t size = 0; size <= kMaxSize; size++) {
  605. const size_t sc = SizeClass(size);
  606. if (sc == 0) {
  607. MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size);
  608. abort();
  609. }
  610. if (sc > 1 && size <= class_to_size[sc-1]) {
  611. MESSAGE("Allocating unnecessarily large class %" PRIuS " for %" PRIuS
  612. "\n", sc, size);
  613. abort();
  614. }
  615. if (sc >= kNumClasses) {
  616. MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size);
  617. abort();
  618. }
  619. const size_t s = class_to_size[sc];
  620. if (size > s) {
  621. MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc);
  622. abort();
  623. }
  624. if (s == 0) {
  625. MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc);
  626. abort();
  627. }
  628. }
  629. // Initialize the num_objects_to_move array.
  630. for (size_t cl = 1; cl < kNumClasses; ++cl) {
  631. num_objects_to_move[cl] = NumMoveSize(ByteSizeForClass(cl));
  632. }
  633. #ifndef WTF_CHANGES
  634. if (false) {
  635. // Dump class sizes and maximum external wastage per size class
  636. for (size_t cl = 1; cl < kNumClasses; ++cl) {
  637. const int alloc_size = class_to_pages[cl] << kPageShift;
  638. const int alloc_objs = alloc_size / class_to_size[cl];
  639. const int min_used = (class_to_size[cl-1] + 1) * alloc_objs;
  640. const int max_waste = alloc_size - min_used;
  641. MESSAGE("SC %3d [ %8d .. %8d ] from %8d ; %2.0f%% maxwaste\n",
  642. int(cl),
  643. int(class_to_size[cl-1] + 1),
  644. int(class_to_size[cl]),
  645. int(class_to_pages[cl] << kPageShift),
  646. max_waste * 100.0 / alloc_size
  647. );
  648. }
  649. }
  650. #endif
  651. }
  652. // -------------------------------------------------------------------------
  653. // Simple allocator for objects of a specified type. External locking
  654. // is required before accessing one of these objects.
  655. // -------------------------------------------------------------------------
  656. // Metadata allocator -- keeps stats about how many bytes allocated
  657. static uint64_t metadata_system_bytes = 0;
  658. static void* MetaDataAlloc(size_t bytes) {
  659. void* result = TCMalloc_SystemAlloc(bytes, 0);
  660. if (result != NULL) {
  661. metadata_system_bytes += bytes;
  662. }
  663. return result;
  664. }
  665. template <class T>
  666. class PageHeapAllocator {
  667. private:
  668. // How much to allocate from system at a time
  669. static const size_t kAllocIncrement = 32 << 10;
  670. // Aligned size of T
  671. static const size_t kAlignedSize
  672. = (((sizeof(T) + kAlignment - 1) / kAlignment) * kAlignment);
  673. // Free area from which to carve new objects
  674. char* free_area_;
  675. size_t free_avail_;
  676. // Free list of already carved objects
  677. void* free_list_;
  678. // Number of allocated but unfreed objects
  679. int inuse_;
  680. public:
  681. void Init() {
  682. ASSERT(kAlignedSize <= kAllocIncrement);
  683. inuse_ = 0;
  684. free_area_ = NULL;
  685. free_avail_ = 0;
  686. free_list_ = NULL;
  687. }
  688. T* New() {
  689. // Consult free list
  690. void* result;
  691. if (free_list_ != NULL) {
  692. result = free_list_;
  693. free_list_ = *(reinterpret_cast<void**>(result));
  694. } else {
  695. if (free_avail_ < kAlignedSize) {
  696. // Need more room
  697. free_area_ = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement));
  698. if (free_area_ == NULL) abort();
  699. free_avail_ = kAllocIncrement;
  700. }
  701. result = free_area_;
  702. free_area_ += kAlignedSize;
  703. free_avail_ -= kAlignedSize;
  704. }
  705. inuse_++;
  706. return reinterpret_cast<T*>(result);
  707. }
  708. void Delete(T* p) {
  709. *(reinterpret_cast<void**>(p)) = free_list_;
  710. free_list_ = p;
  711. inuse_--;
  712. }
  713. int inuse() const { return inuse_; }
  714. };
  715. // -------------------------------------------------------------------------
  716. // Span - a contiguous run of pages
  717. // -------------------------------------------------------------------------
  718. // Type that can hold a page number
  719. typedef uintptr_t PageID;
  720. // Type that can hold the length of a run of pages
  721. typedef uintptr_t Length;
  722. static const Length kMaxValidPages = (~static_cast<Length>(0)) >> kPageShift;
  723. // Convert byte size into pages. This won't overflow, but may return
  724. // an unreasonably large value if bytes is huge enough.
  725. static inline Length pages(size_t bytes) {
  726. return (bytes >> kPageShift) +
  727. ((bytes & (kPageSize - 1)) > 0 ? 1 : 0);
  728. }
  729. // Convert a user size into the number of bytes that will actually be
  730. // allocated
  731. static size_t AllocationSize(size_t bytes) {
  732. if (bytes > kMaxSize) {
  733. // Large object: we allocate an integral number of pages
  734. ASSERT(bytes <= (kMaxValidPages << kPageShift));
  735. return pages(bytes) << kPageShift;
  736. } else {
  737. // Small object: find the size class to which it belongs
  738. return ByteSizeForClass(SizeClass(bytes));
  739. }
  740. }
  741. // Information kept for a span (a contiguous run of pages).
  742. struct Span {
  743. PageID start; // Starting page number
  744. Length length; // Number of pages in span
  745. Span* next; // Used when in link list
  746. Span* prev; // Used when in link list
  747. void* objects; // Linked list of free objects
  748. unsigned int free : 1; // Is the span free
  749. unsigned int sample : 1; // Sampled object?
  750. unsigned int sizeclass : 8; // Size-class for small objects (or 0)
  751. unsigned int refcount : 11; // Number of non-free objects
  752. #undef SPAN_HISTORY
  753. #ifdef SPAN_HISTORY
  754. // For debugging, we can keep a log events per span
  755. int nexthistory;
  756. char history[64];
  757. int value[64];
  758. #endif
  759. };
  760. #ifdef SPAN_HISTORY
  761. void Event(Span* span, char op, int v = 0) {
  762. span->history[span->nexthistory] = op;
  763. span->value[span->nexthistory] = v;
  764. span->nexthistory++;
  765. if (span->nexthistory == sizeof(span->history)) span->nexthistory = 0;
  766. }
  767. #else
  768. #define Event(s,o,v) ((void) 0)
  769. #endif
  770. // Allocator/deallocator for spans
  771. static PageHeapAllocator<Span> span_allocator;
  772. static Span* NewSpan(PageID p, Length len) {
  773. Span* result = span_allocator.New();
  774. memset(result, 0, sizeof(*result));
  775. result->start = p;
  776. result->length = len;
  777. #ifdef SPAN_HISTORY
  778. result->nexthistory = 0;
  779. #endif
  780. return result;
  781. }
  782. static inline void DeleteSpan(Span* span) {
  783. #ifndef NDEBUG
  784. // In debug mode, trash the contents of deleted Spans
  785. memset(span, 0x3f, sizeof(*span));
  786. #endif
  787. span_allocator.Delete(span);
  788. }
  789. // -------------------------------------------------------------------------
  790. // Doubly linked list of spans.
  791. // -------------------------------------------------------------------------
  792. static inline void DLL_Init(Span* list) {
  793. list->next = list;
  794. list->prev = list;
  795. }
  796. static inline void DLL_Remove(Span* span) {
  797. span->prev->next = span->next;
  798. span->next->prev = span->prev;
  799. span->prev = NULL;
  800. span->next = NULL;
  801. }
  802. static ALWAYS_INLINE bool DLL_IsEmpty(const Span* list) {
  803. return list->next == list;
  804. }
  805. #ifndef WTF_CHANGES
  806. static int DLL_Length(const Span* list) {
  807. int result = 0;
  808. for (Span* s = list->next; s != list; s = s->next) {
  809. result++;
  810. }
  811. return result;
  812. }
  813. #endif
  814. #if 0 /* Not needed at the moment -- causes compiler warnings if not used */
  815. static void DLL_Print(const char* label, const Span* list) {
  816. MESSAGE("%-10s %p:", label, list);
  817. for (const Span* s = list->next; s != list; s = s->next) {
  818. MESSAGE(" <%p,%u,%u>", s, s->start, s->length);
  819. }
  820. MESSAGE("\n");
  821. }
  822. #endif
  823. static inline void DLL_Prepend(Span* list, Span* span) {
  824. ASSERT(span->next == NULL);
  825. ASSERT(span->prev == NULL);
  826. span->next = list->next;
  827. span->prev = list;
  828. list->next->prev = span;
  829. list->next = span;
  830. }
  831. // -------------------------------------------------------------------------
  832. // Stack traces kept for sampled allocations
  833. // The following state is protected by pageheap_lock_.
  834. // -------------------------------------------------------------------------
  835. // size/depth are made the same size as a pointer so that some generic
  836. // code below can conveniently cast them back and forth to void*.
  837. static const int kMaxStackDepth = 31;
  838. struct StackTrace {
  839. uintptr_t size; // Size of object
  840. uintptr_t depth; // Number of PC values stored in array below
  841. void* stack[kMaxStackDepth];
  842. };
  843. static PageHeapAllocator<StackTrace> stacktrace_allocator;
  844. static Span sampled_objects;
  845. // -------------------------------------------------------------------------
  846. // Map from page-id to per-page data
  847. // -------------------------------------------------------------------------
  848. // We use PageMap2<> for 32-bit and PageMap3<> for 64-bit machines.
  849. // We also use a simple one-level cache for hot PageID-to-sizeclass mappings,
  850. // because sometimes the sizeclass is all the information we need.
  851. // Selector class -- general selector uses 3-level map
  852. template <int BITS> class MapSelector {
  853. public:
  854. typedef TCMalloc_PageMap3<BITS-kPageShift> Type;
  855. typedef PackedCache<BITS, uint64_t> CacheType;
  856. };
  857. // A two-level map for 32-bit machines
  858. template <> class MapSelector<32> {
  859. public:
  860. typedef TCMalloc_PageMap2<32-kPageShift> Type;
  861. typedef PackedCache<32-kPageShift, uint16_t> CacheType;
  862. };
  863. // -------------------------------------------------------------------------
  864. // Page-level allocator
  865. // * Eager coalescing
  866. //
  867. // Heap for page-level allocation. We allow allocating and freeing a
  868. // contiguous runs of pages (called a "span").
  869. // -------------------------------------------------------------------------
  870. class TCMalloc_PageHeap {
  871. public:
  872. void init();
  873. // Allocate a run of "n" pages. Returns zero if out of memory.
  874. Span* New(Length n);
  875. // Delete the span "[p, p+n-1]".
  876. // REQUIRES: span was returned by earlier call to New() and
  877. // has not yet been deleted.
  878. void Delete(Span* span);
  879. // Mark an allocated span as being used for small objects of the
  880. // specified size-class.
  881. // REQUIRES: span was returned by an earlier call to New()
  882. // and has not yet been deleted.
  883. void RegisterSizeClass(Span* span, size_t sc);
  884. // Split an allocated span into two spans: one of length "n" pages
  885. // followed by another span of length "span->length - n" pages.
  886. // Modifies "*span" to point to the first span of length "n" pages.
  887. // Returns a pointer to the second span.
  888. //
  889. // REQUIRES: "0 < n < span->length"
  890. // REQUIRES: !span->free
  891. // REQUIRES: span->sizeclass == 0
  892. Span* Split(Span* span, Length n);
  893. // Return the descriptor for the specified page.
  894. inline Span* GetDescriptor(PageID p) const {
  895. return reinterpret_cast<Span*>(pagemap_.get(p));
  896. }
  897. #ifdef WTF_CHANGES
  898. inline Span* GetDescriptorEnsureSafe(PageID p)
  899. {
  900. pagemap_.Ensure(p, 1);
  901. return GetDescriptor(p);
  902. }
  903. #endif
  904. // Dump state to stderr
  905. #ifndef WTF_CHANGES
  906. void Dump(TCMalloc_Printer* out);
  907. #endif
  908. // Return number of bytes allocated from system
  909. inline uint64_t SystemBytes() const { return system_bytes_; }
  910. // Return number of free bytes in heap
  911. uint64_t FreeBytes() const {
  912. return (static_cast<uint64_t>(free_pages_) << kPageShift);
  913. }
  914. bool Check();
  915. bool CheckList(Span* list, Length min_pages, Length max_pages);
  916. // Release all pages on the free list for reuse by the OS:
  917. void ReleaseFreePages();
  918. // Return 0 if we have no information, or else the correct sizeclass for p.
  919. // Reads and writes to pagemap_cache_ do not require locking.
  920. // The entries are 64 bits on 64-bit hardware and 16 bits on
  921. // 32-bit hardware, and we don't mind raciness as long as each read of
  922. // an entry yields a valid entry, not a partially updated entry.
  923. size_t GetSizeClassIfCached(PageID p) const {
  924. return pagemap_cache_.GetOrDefault(p, 0);
  925. }
  926. void CacheSizeClass(PageID p, size_t cl) const { pagemap_cache_.Put(p, cl); }
  927. private:
  928. // Pick the appropriate map and cache types based on pointer size
  929. typedef MapSelector<8*sizeof(uintptr_t)>::Type PageMap;
  930. typedef MapSelector<8*sizeof(uintptr_t)>::CacheType PageMapCache;
  931. PageMap pagemap_;
  932. mutable PageMapCache pagemap_cache_;
  933. // We segregate spans of a given size into two circular linked
  934. // lists: one for normal spans, and one for spans whose memory
  935. // has been returned to the system.
  936. struct SpanList {
  937. Span normal;
  938. Span returned;
  939. };
  940. // List of free spans of length >= kMaxPages
  941. SpanList large_;
  942. // Array mapping from span length to a doubly linked list of free spans
  943. SpanList free_[kMaxPages];
  944. // Number of pages kept in free lists
  945. uintptr_t free_pages_;
  946. // Bytes allocated from system
  947. uint64_t system_bytes_;
  948. bool GrowHeap(Length n);
  949. // REQUIRES span->length >= n
  950. // Remove span from its free list, and move any leftover part of
  951. // span into appropriate free lists. Also update "span" to have
  952. // length exactly "n" and mark it as non-free so it can be returned
  953. // to the client.
  954. //
  955. // "released" is true iff "span" was found on a "returned" list.
  956. void Carve(Span* span, Length n, bool released);
  957. void RecordSpan(Span* span) {
  958. pagemap_.set(span->start, span);
  959. if (span->length > 1) {
  960. pagemap_.set(span->start + span->length - 1, span);
  961. }
  962. }
  963. // Allocate a large span of length == n. If successful, returns a
  964. // span of exactly the specified length. Else, returns NULL.
  965. Span* AllocLarge(Length n);
  966. // Incrementally release some memory to the system.
  967. // IncrementalScavenge(n) is called whenever n pages are freed.
  968. void IncrementalScavenge(Length n);
  969. // Number of pages to deallocate before doing more scavenging
  970. int64_t scavenge_counter_;
  971. // Index of last free list we scavenged
  972. size_t scavenge_index_;
  973. #if defined(WTF_CHANGES) && PLATFORM(DARWIN)
  974. friend class FastMallocZone;
  975. #endif
  976. };
  977. void TCMalloc_PageHeap::init()
  978. {
  979. pagemap_.init(MetaDataAlloc);
  980. pagemap_cache_ = PageMapCache(0);
  981. free_pages_ = 0;
  982. system_bytes_ = 0;
  983. scavenge_counter_ = 0;
  984. // Start scavenging at kMaxPages list
  985. scavenge_index_ = kMaxPages-1;
  986. COMPILE_ASSERT(kNumClasses <= (1 << PageMapCache::kValuebits), valuebits);
  987. DLL_Init(&large_.normal);
  988. DLL_Init(&large_.returned);
  989. for (size_t i = 0; i < kMaxPages; i++) {
  990. DLL_Init(&free_[i].normal);
  991. DLL_Init(&free_[i].returned);
  992. }
  993. }
  994. inline Span* TCMalloc_PageHeap::New(Length n) {
  995. ASSERT(Check());
  996. ASSERT(n > 0);
  997. // Find first size >= n that has a non-empty list
  998. for (Length s = n; s < kMaxPages; s++) {
  999. Span* ll = NULL;
  1000. bool released = false;
  1001. if (!DLL_IsEmpty(&free_[s].normal)) {
  1002. // Found normal span
  1003. ll = &free_[s].normal;
  1004. } else if (!DLL_IsEmpty(&free_[s].returned)) {
  1005. // Found returned span; reallocate it
  1006. ll = &free_[s].returned;
  1007. released = true;
  1008. } else {
  1009. // Keep looking in larger classes
  1010. continue;
  1011. }
  1012. Span* result = ll->next;
  1013. Carve(result, n, released);
  1014. ASSERT(Check());
  1015. free_pages_ -= n;
  1016. return result;
  1017. }
  1018. Span* result = AllocLarge(n);
  1019. if (result != NULL) return result;
  1020. // Grow the heap and try again
  1021. if (!GrowHeap(n)) {
  1022. ASSERT(Check());
  1023. return NULL;
  1024. }
  1025. return AllocLarge(n);
  1026. }
  1027. Span* TCMalloc_PageHeap::AllocLarge(Length n) {
  1028. // find the best span (closest to n in size).
  1029. // The following loops implements address-ordered best-fit.
  1030. bool from_released = false;
  1031. Span *best = NULL;
  1032. // Search through normal list
  1033. for (Span* span = large_.normal.next;
  1034. span != &large_.normal;
  1035. span = span->next) {
  1036. if (span->length >= n) {
  1037. if ((best == NULL)
  1038. || (span->length < best->length)
  1039. || ((span->length == best->length) && (span->start < best->start))) {
  1040. best = span;
  1041. from_released = false;
  1042. }
  1043. }
  1044. }
  1045. // Search through released list in case it has a better fit
  1046. for (Span* span = large_.returned.next;
  1047. span != &large_.returned;
  1048. span = span->next) {
  1049. if (span->length >= n) {
  1050. if ((best == NULL)
  1051. || (span->length < best->length)
  1052. || ((span->length == best->length) && (span->start < best->start))) {
  1053. best = span;
  1054. from_released = true;
  1055. }
  1056. }
  1057. }
  1058. if (best != NULL) {
  1059. Carve(best, n, from_released);
  1060. ASSERT(Check());
  1061. free_pages_ -= n;
  1062. return best;
  1063. }
  1064. return NULL;
  1065. }
  1066. Span* TCMalloc_PageHeap::Split(Span* span, Length n) {
  1067. ASSERT(0 < n);
  1068. ASSERT(n < span->length);
  1069. ASSERT(!span->free);
  1070. ASSERT(span->sizeclass == 0);
  1071. Event(span, 'T', n);
  1072. const Length extra = span->length - n;
  1073. Span* leftover = NewSpan(span->start + n, extra);
  1074. Event(leftover, 'U', extra);
  1075. RecordSpan(leftover);
  1076. pagemap_.set(span->start + n - 1, span); // Update map from pageid to span
  1077. span->length = n;
  1078. return leftover;
  1079. }
  1080. inline void TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) {
  1081. ASSERT(n > 0);
  1082. DLL_Remove(span);
  1083. span->free = 0;
  1084. Event(span, 'A', n);
  1085. const int extra = static_cast<int>(span->length - n);
  1086. ASSERT(extra >= 0);
  1087. if (extra > 0) {
  1088. Span* leftover = NewSpan(span->start + n, extra);
  1089. leftover->free = 1;
  1090. Event(leftover, 'S', extra);
  1091. RecordSpan(leftover);
  1092. // Place leftover span on appropriate free list
  1093. SpanList* listpair = (static_cast<size_t>(extra) < kMaxPages) ? &free_[extra] : &large_;
  1094. Span* dst = released ? &listpair->returned : &listpair->normal;
  1095. DLL_Prepend(dst, leftover);
  1096. span->length = n;
  1097. pagemap_.set(span->start + n - 1, span);
  1098. }
  1099. }
  1100. inline void TCMalloc_PageHeap::Delete(Span* span) {
  1101. ASSERT(Check());
  1102. ASSERT(!span->free);
  1103. ASSERT(span->length > 0);
  1104. ASSERT(GetDescriptor(span->start) == span);
  1105. ASSERT(GetDescriptor(span->start + span->length - 1) == span);
  1106. span->sizeclass = 0;
  1107. span->sample = 0;
  1108. // Coalesce -- we guarantee that "p" != 0, so no bounds checking
  1109. // necessary. We do not bother resetting the stale pagemap
  1110. // entries for the pieces we are merging together because we only
  1111. // care about the pagemap entries for the boundaries.
  1112. //
  1113. // Note that the spans we merge into "span" may come out of
  1114. // a "returned" list. For simplicity, we move these into the
  1115. // "normal" list of the appropriate size class.
  1116. const PageID p = span->start;
  1117. const Length n = span->length;
  1118. Span* prev = GetDescriptor(p-1);
  1119. if (prev != NULL && prev->free) {
  1120. // Merge preceding span into this span
  1121. ASSERT(prev->start + prev->length == p);
  1122. const Length len = prev->length;
  1123. DLL_Remove(prev);
  1124. DeleteSpan(prev);
  1125. span->start -= len;
  1126. span->length += len;
  1127. pagemap_.set(span->start, span);
  1128. Event(span, 'L', len);
  1129. }
  1130. Span* next = GetDescriptor(p+n);
  1131. if (next != NULL && next->free) {
  1132. // Merge next span into this span
  1133. ASSERT(next->start == p+n);
  1134. const Length len = next->length;
  1135. DLL_Remove(next);
  1136. DeleteSpan(next);
  1137. span->length += len;
  1138. pagemap_.set(span->start + span->length - 1, span);
  1139. Event(span, 'R', len);
  1140. }
  1141. Event(span, 'D', span->length);
  1142. span->free = 1;
  1143. if (span->length < kMaxPages) {
  1144. DLL_Prepend(&free_[span->length].normal, span);
  1145. } else {
  1146. DLL_Prepend(&large_.normal, span);
  1147. }
  1148. free_pages_ += n;
  1149. IncrementalScavenge(n);
  1150. ASSERT(Check());
  1151. }
  1152. void TCMalloc_PageHeap::IncrementalScavenge(Length n) {
  1153. // Fast path; not yet time to release memory
  1154. scavenge_counter_ -= n;
  1155. if (scavenge_counter_ >= 0) return; // Not yet time to scavenge
  1156. // If there is nothing to release, wait for so many pages before
  1157. // scavenging again. With 4K pages, this comes to 16MB of memory.
  1158. static const size_t kDefaultReleaseDelay = 1 << 8;
  1159. // Find index of free list to scavenge
  1160. size_t index = scavenge_index_ + 1;
  1161. for (size_t i = 0; i < kMaxPages+1; i++) {
  1162. if (index > kMaxPages) index = 0;
  1163. SpanList* slist = (index == kMaxPages) ? &large_ : &free_[index];
  1164. if (!DLL_IsEmpty(&slist->normal)) {
  1165. // Release the last span on the normal portion of this list
  1166. Span* s = slist->normal.prev;
  1167. DLL_Remove(s);
  1168. TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
  1169. static_cast<size_t>(s->length << kPageShift));
  1170. DLL_Prepend(&slist->returned, s);
  1171. scavenge_counter_ = std::max<size_t>(64UL, std::min<size_t>(kDefaultReleaseDelay, kDefaultReleaseDelay - (free_pages_ / kDefaultReleaseDelay)));
  1172. if (index == kMaxPages && !DLL_IsEmpty(&slist->normal))
  1173. scavenge_index_ = index - 1;
  1174. else
  1175. scavenge_index_ = index;
  1176. return;
  1177. }
  1178. index++;
  1179. }
  1180. // Nothing to scavenge, delay for a while
  1181. scavenge_counter_ = kDefaultReleaseDelay;
  1182. }
  1183. void TCMalloc_PageHeap::RegisterSizeClass(Span* span, size_t sc) {
  1184. // Associate span object with all interior pages as well
  1185. ASSERT(!span->free);
  1186. ASSERT(GetDescriptor(span->start) == span);
  1187. ASSERT(GetDescriptor(span->start+span->length-1) == span);
  1188. Event(span, 'C', sc);
  1189. span->sizeclass = static_cast<unsigned int>(sc);
  1190. for (Length i = 1; i < span->length-1; i++) {
  1191. pagemap_.set(span->start+i, span);
  1192. }
  1193. }
  1194. #ifndef WTF_CHANGES
  1195. static double PagesToMB(uint64_t pages) {
  1196. return (pages << kPageShift) / 1048576.0;
  1197. }
  1198. void TCMalloc_PageHeap::Dump(TCMalloc_Printer* out) {
  1199. int nonempty_sizes = 0;
  1200. for (int s = 0; s < kMaxPages; s++) {
  1201. if (!DLL_IsEmpty(&free_[s].normal) || !DLL_IsEmpty(&free_[s].returned)) {
  1202. nonempty_sizes++;
  1203. }
  1204. }
  1205. out->printf("------------------------------------------------\n");
  1206. out->printf("PageHeap: %d sizes; %6.1f MB free\n",
  1207. nonempty_sizes, PagesToMB(free_pages_));
  1208. out->printf("------------------------------------------------\n");
  1209. uint64_t total_normal = 0;
  1210. uint64_t total_returned = 0;
  1211. for (int s = 0; s < kMaxPages; s++) {
  1212. const int n_length = DLL_Length(&free_[s].normal);
  1213. const int r_length = DLL_Length(&free_[s].returned);
  1214. if (n_length + r_length > 0) {
  1215. uint64_t n_pages = s * n_length;
  1216. uint64_t r_pages = s * r_length;
  1217. total_normal += n_pages;
  1218. total_returned += r_pages;
  1219. out->printf("%6u pages * %6u spans ~ %6.1f MB; %6.1f MB cum"
  1220. "; unmapped: %6.1f MB; %6.1f MB cum\n",
  1221. s,
  1222. (n_length + r_length),
  1223. PagesToMB(n_pages + r_pages),
  1224. PagesToMB(total_normal + total_returned),
  1225. PagesToMB(r_pages),
  1226. PagesToMB(total_returned));
  1227. }
  1228. }
  1229. uint64_t n_pages = 0;
  1230. uint64_t r_pages = 0;
  1231. int n_spans = 0;
  1232. int r_spans = 0;
  1233. out->printf("Normal large spans:\n");
  1234. for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) {
  1235. out->printf(" [ %6" PRIuS " pages ] %6.1f MB\n",
  1236. s->length, PagesToMB(s->length));
  1237. n_pages += s->length;
  1238. n_spans++;
  1239. }
  1240. out->printf("Unmapped large spans:\n");
  1241. for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) {
  1242. out->printf(" [ %6" PRIuS " pages ] %6.1f MB\n",
  1243. s->length, PagesToMB(s->length));
  1244. r_pages += s->length;
  1245. r_spans++;
  1246. }
  1247. total_normal += n_pages;
  1248. total_returned += r_pages;
  1249. out->printf(">255 large * %6u spans ~ %6.1f MB; %6.1f MB cum"
  1250. "; unmapped: %6.1f MB; %6.1f MB cum\n",
  1251. (n_spans + r_spans),
  1252. PagesToMB(n_pages + r_pages),
  1253. PagesToMB(total_normal + total_returned),
  1254. PagesToMB(r_pages),
  1255. PagesToMB(total_returned));
  1256. }
  1257. #endif
  1258. bool TCMalloc_PageHeap::GrowHeap(Length n) {
  1259. ASSERT(kMaxPages >= kMinSystemAlloc);
  1260. if (n > kMaxValidPages) return false;
  1261. Length ask = (n>kMinSystemAlloc) ? n : static_cast<Length>(kMinSystemAlloc);
  1262. size_t actual_size;
  1263. void* ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);
  1264. if (ptr == NULL) {
  1265. if (n < ask) {
  1266. // Try growing just "n" pages
  1267. ask = n;
  1268. ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize);;
  1269. }
  1270. if (ptr == NULL) return false;
  1271. }
  1272. ask = actual_size >> kPageShift;
  1273. uint64_t old_system_bytes = system_bytes_;
  1274. system_bytes_ += (ask << kPageShift);
  1275. const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift;
  1276. ASSERT(p > 0);
  1277. // If we have already a lot of pages allocated, just pre allocate a bunch of
  1278. // memory for the page map. This prevents fragmentation by pagemap metadata
  1279. // when a program keeps allocating and freeing large blocks.
  1280. if (old_system_bytes < kPageMapBigAllocationThreshold
  1281. && system_bytes_ >= kPageMapBigAllocationThreshold) {
  1282. pagemap_.PreallocateMoreMemory();
  1283. }
  1284. // Make sure pagemap_ has entries for all of the new pages.
  1285. // Plus ensure one before and one after so coalescing code
  1286. // does not need bounds-checking.
  1287. if (pagemap_.Ensure(p-1, ask+2)) {
  1288. // Pretend the new area is allocated and then Delete() it to
  1289. // cause any necessary coalescing to occur.
  1290. //
  1291. // We do not adjust free_pages_ here since Delete() will do it for us.
  1292. Span* span = NewSpan(p, ask);
  1293. RecordSpan(span);
  1294. Delete(span);
  1295. ASSERT(Check());
  1296. return true;
  1297. } else {
  1298. // We could not allocate memory within "pagemap_"
  1299. // TODO: Once we can return memory to the system, return the new span
  1300. return false;
  1301. }
  1302. }
  1303. bool TCMalloc_PageHeap::Check() {
  1304. ASSERT(free_[0].normal.next == &free_[0].normal);
  1305. ASSERT(free_[0].returned.next == &free_[0].returned);
  1306. CheckList(&large_.normal, kMaxPages, 1000000000);
  1307. CheckList(&large_.returned, kMaxPages, 1000000000);
  1308. for (Length s = 1; s < kMaxPages; s++) {
  1309. CheckList(&free_[s].normal, s, s);
  1310. CheckList(&free_[s].returned, s, s);
  1311. }
  1312. return true;
  1313. }
  1314. #if ASSERT_DISABLED
  1315. bool TCMalloc_PageHeap::CheckList(Span*, Length, Length) {
  1316. return true;
  1317. }
  1318. #else
  1319. bool TCMalloc_PageHeap::CheckList(Span* list, Length min_pages, Length max_pages) {
  1320. for (Span* s = list->next; s != list; s = s->next) {
  1321. CHECK_CONDITION(s->free);
  1322. CHECK_CONDITION(s->length >= min_pages);
  1323. CHECK_CONDITION(s->length <= max_pages);
  1324. CHECK_CONDITION(GetDescriptor(s->start) == s);
  1325. CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s);
  1326. }
  1327. return true;
  1328. }
  1329. #endif
  1330. static void ReleaseFreeList(Span* list, Span* returned) {
  1331. // Walk backwards through list so that when we push these
  1332. // spans on the "returned" list, we preserve the order.
  1333. while (!DLL_IsEmpty(list)) {
  1334. Span* s = list->prev;
  1335. DLL_Remove(s);
  1336. DLL_Prepend(returned, s);
  1337. TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift),
  1338. static_cast<size

Large files files are truncated, but you can click here to view the full file