gc_inline.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*
  2. * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  3. * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
  4. * Copyright (c) 2005 Hewlett-Packard Development Company, L.P.
  5. *
  6. * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  7. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  8. *
  9. * Permission is hereby granted to use or copy this program
  10. * for any purpose, provided the above notices are retained on all copies.
  11. * Permission to modify the code and to distribute modified code is granted,
  12. * provided the above notices are retained, and a notice that the code was
  13. * modified is included with the above copyright notice.
  14. */
  15. #ifndef GC_INLINE_H
  16. #define GC_INLINE_H
  17. /* WARNING: */
  18. /* Note that for these routines, it is the clients responsibility to */
  19. /* add the extra byte at the end to deal with one-past-the-end pointers.*/
  20. /* In the standard collector configuration, the collector assumes that */
  21. /* such a byte has been added, and hence does not trace the last word */
  22. /* in the resulting object. */
  23. /* This is not an issue if the collector is compiled with */
  24. /* DONT_ADD_BYTE_AT_END, or if GC_all_interior_pointers is not set. */
  25. /* This interface is most useful for compilers that generate C. */
  26. /* It is also used internally for thread-local allocation. */
  27. /* Manual use is hereby discouraged. */
  28. #include "gc.h"
  29. #include "gc_tiny_fl.h"
  30. #if GC_GNUC_PREREQ(3, 0)
  31. # define GC_EXPECT(expr, outcome) __builtin_expect(expr,outcome)
  32. /* Equivalent to (expr), but predict that usually (expr)==outcome. */
  33. #else
  34. # define GC_EXPECT(expr, outcome) (expr)
  35. #endif
  36. #ifndef GC_ASSERT
  37. # ifdef NDEBUG
  38. # define GC_ASSERT(expr) /* empty */
  39. # else
  40. # include <assert.h>
  41. # define GC_ASSERT(expr) assert(expr)
  42. # endif
  43. #endif
  44. #ifdef __cplusplus
  45. extern "C" {
  46. #endif
  47. #ifndef GC_PREFETCH_FOR_WRITE
  48. # if GC_GNUC_PREREQ(3, 0) && !defined(GC_NO_PREFETCH_FOR_WRITE)
  49. # define GC_PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1)
  50. # else
  51. # define GC_PREFETCH_FOR_WRITE(x) (void)0
  52. # endif
  53. #endif
  54. /* Object kinds; must match PTRFREE, NORMAL in gc_priv.h. */
  55. #define GC_I_PTRFREE 0
  56. #define GC_I_NORMAL 1
  57. /* Store a pointer to a list of newly allocated objects of kind k and */
  58. /* size lb in *result. The caller must make sure that *result is */
  59. /* traced even if objects are ptrfree. */
  60. GC_API void GC_CALL GC_generic_malloc_many(size_t /* lb */, int /* k */,
  61. void ** /* result */);
  62. /* Generalized version of GC_malloc and GC_malloc_atomic. */
  63. /* Uses appropriately the thread-local (if available) or the global */
  64. /* free-list of the specified kind. */
  65. GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
  66. GC_malloc_kind(size_t /* lb */, int /* k */);
  67. #ifdef GC_THREADS
  68. /* Same as above but uses only the global free-list. */
  69. GC_API GC_ATTR_MALLOC GC_ATTR_ALLOC_SIZE(1) void * GC_CALL
  70. GC_malloc_kind_global(size_t /* lb */, int /* k */);
  71. #else
  72. # define GC_malloc_kind_global GC_malloc_kind
  73. #endif
  74. /* An internal macro to update the free list pointer atomically (if */
  75. /* the AO primitives are available) to avoid race with the marker. */
  76. #if defined(GC_THREADS) && defined(AO_HAVE_store)
  77. # define GC_FAST_M_AO_STORE(my_fl, next) \
  78. AO_store((volatile AO_t *)(my_fl), (AO_t)(next))
  79. #else
  80. # define GC_FAST_M_AO_STORE(my_fl, next) (void)(*(my_fl) = (next))
  81. #endif
  82. /* The ultimately general inline allocation macro. Allocate an object */
  83. /* of size granules, putting the resulting pointer in result. Tiny_fl */
  84. /* is a "tiny" free list array, which will be used first, if the size */
  85. /* is appropriate. If granules is too large, we allocate with */
  86. /* default_expr instead. If we need to refill the free list, we use */
  87. /* GC_generic_malloc_many with the indicated kind. */
  88. /* Tiny_fl should be an array of GC_TINY_FREELISTS void * pointers. */
  89. /* If num_direct is nonzero, and the individual free list pointers */
  90. /* are initialized to (void *)1, then we allocate num_direct granules */
  91. /* directly using generic_malloc before putting multiple objects into */
  92. /* the tiny_fl entry. If num_direct is zero, then the free lists may */
  93. /* also be initialized to (void *)0. */
  94. /* Note that we use the zeroth free list to hold objects 1 granule in */
  95. /* size that are used to satisfy size 0 allocation requests. */
  96. /* We rely on much of this hopefully getting optimized away in the */
  97. /* num_direct = 0 case. */
  98. /* Particularly if granules is constant, this should generate a small */
  99. /* amount of code. */
  100. # define GC_FAST_MALLOC_GRANS(result,granules,tiny_fl,num_direct, \
  101. kind,default_expr,init) \
  102. do { \
  103. if (GC_EXPECT((granules) >= GC_TINY_FREELISTS,0)) { \
  104. result = (default_expr); \
  105. } else { \
  106. void **my_fl = (tiny_fl) + (granules); \
  107. void *my_entry=*my_fl; \
  108. void *next; \
  109. \
  110. for (;;) { \
  111. if (GC_EXPECT((GC_word)my_entry \
  112. > (num_direct) + GC_TINY_FREELISTS + 1, 1)) { \
  113. next = *(void **)(my_entry); \
  114. result = (void *)my_entry; \
  115. GC_FAST_M_AO_STORE(my_fl, next); \
  116. init; \
  117. GC_PREFETCH_FOR_WRITE(next); \
  118. if ((kind) != GC_I_PTRFREE) GC_end_stubborn_change(my_fl); \
  119. GC_ASSERT(GC_size(result) >= (granules)*GC_GRANULE_BYTES); \
  120. GC_ASSERT((kind) == GC_I_PTRFREE \
  121. || ((GC_word *)result)[1] == 0); \
  122. break; \
  123. } \
  124. /* Entry contains counter or NULL */ \
  125. if ((GC_signed_word)my_entry - (GC_signed_word)(num_direct) <= 0 \
  126. /* (GC_word)my_entry <= (num_direct) */ \
  127. && my_entry != NULL) { \
  128. /* Small counter value, not NULL */ \
  129. GC_FAST_M_AO_STORE(my_fl, (char *)my_entry \
  130. + (granules) + 1); \
  131. if ((kind) != GC_I_PTRFREE) GC_end_stubborn_change(my_fl); \
  132. result = (default_expr); \
  133. break; \
  134. } else { \
  135. /* Large counter or NULL */ \
  136. GC_generic_malloc_many(((granules) == 0? GC_GRANULE_BYTES : \
  137. GC_RAW_BYTES_FROM_INDEX(granules)), \
  138. kind, my_fl); \
  139. my_entry = *my_fl; \
  140. if (my_entry == 0) { \
  141. result = (*GC_get_oom_fn())((granules)*GC_GRANULE_BYTES); \
  142. break; \
  143. } \
  144. } \
  145. } \
  146. } \
  147. } while (0)
  148. # define GC_WORDS_TO_WHOLE_GRANULES(n) \
  149. GC_WORDS_TO_GRANULES((n) + GC_GRANULE_WORDS - 1)
  150. /* Allocate n words (NOT BYTES). X is made to point to the result. */
  151. /* This should really only be used if GC_all_interior_pointers is */
  152. /* not set, or DONT_ADD_BYTE_AT_END is set. See above. */
  153. /* The semantics changed in version 7.0; we no longer lock, and */
  154. /* the caller is responsible for supplying a cleared tiny_fl */
  155. /* free list array. For single-threaded applications, this may be */
  156. /* a global array. */
  157. # define GC_MALLOC_WORDS_KIND(result,n,tiny_fl,kind,init) \
  158. do { \
  159. size_t granules = GC_WORDS_TO_WHOLE_GRANULES(n); \
  160. GC_FAST_MALLOC_GRANS(result, granules, tiny_fl, 0, kind, \
  161. GC_malloc_kind(granules*GC_GRANULE_BYTES, kind), \
  162. init); \
  163. } while (0)
  164. # define GC_MALLOC_WORDS(result,n,tiny_fl) \
  165. GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_NORMAL, \
  166. *(void **)(result) = 0)
  167. # define GC_MALLOC_ATOMIC_WORDS(result,n,tiny_fl) \
  168. GC_MALLOC_WORDS_KIND(result, n, tiny_fl, GC_I_PTRFREE, (void)0)
  169. /* And once more for two word initialized objects: */
  170. # define GC_CONS(result, first, second, tiny_fl) \
  171. do { \
  172. GC_MALLOC_WORDS_KIND(result, 2, tiny_fl, GC_I_NORMAL, (void)0); \
  173. if ((result) != NULL) { \
  174. *(void **)(result) = (void *)(first); \
  175. ((void **)(result))[1] = (void *)(second); \
  176. GC_end_stubborn_change(result); \
  177. } \
  178. } while (0)
  179. GC_API void GC_CALL GC_print_free_list(int /* kind */,
  180. size_t /* sz_in_granules */);
  181. #ifdef __cplusplus
  182. } /* extern "C" */
  183. #endif
  184. #endif /* !GC_INLINE_H */