/libs/headers/gc/gc_inline.h

http://github.com/nddrylliog/ooc · C++ Header · 128 lines · 71 code · 9 blank · 48 comment · 11 complexity · eae1f65e7530dbdd1d4fef3ec18c5cc0 MD5 · raw file

  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. /* USE OF THIS FILE IS NOT RECOMMENDED unless GC_all_interior_pointers */
  16. /* is not set, or the collector has been built with */
  17. /* -DDONT_ADD_BYTE_AT_END, or the specified size includes a pointerfree */
  18. /* word at the end. In the standard collector configuration, */
  19. /* the final word of each object may not be scanned. */
  20. /* This interface is most useful for compilers that generate C. */
  21. /* It is also used internally for thread-local allocation, in which */
  22. /* case, the size is suitably adjusted by the caller. */
  23. /* Manual use is hereby discouraged. */
  24. #include "gc.h"
  25. #include "gc_tiny_fl.h"
  26. #if __GNUC__ >= 3
  27. # define GC_EXPECT(expr, outcome) __builtin_expect(expr,outcome)
  28. /* Equivalent to (expr), but predict that usually (expr)==outcome. */
  29. #else
  30. # define GC_EXPECT(expr, outcome) (expr)
  31. #endif /* __GNUC__ */
  32. /* The ultimately general inline allocation macro. Allocate an object */
  33. /* of size granules, putting the resulting pointer in result. Tiny_fl */
  34. /* is a "tiny" free list array, which will be used first, if the size */
  35. /* is appropriate. If granules is too large, we allocate with */
  36. /* default_expr instead. If we need to refill the free list, we use */
  37. /* GC_generic_malloc_many with the indicated kind. */
  38. /* Tiny_fl should be an array of GC_TINY_FREELISTS void * pointers. */
  39. /* If num_direct is nonzero, and the individual free list pointers */
  40. /* are initialized to (void *)1, then we allocate numdirect granules */
  41. /* directly using gmalloc before putting multiple objects into the */
  42. /* tiny_fl entry. If num_direct is zero, then the free lists may also */
  43. /* be initialized to (void *)0. */
  44. /* We rely on much of this hopefully getting optimized away in the */
  45. /* num_direct = 0 case. */
  46. /* Particularly if granules is constant, this should generate a small */
  47. /* amount of code. */
  48. # define GC_FAST_MALLOC_GRANS(result,granules,tiny_fl,num_direct,\
  49. kind,default_expr,init) \
  50. { \
  51. if (GC_EXPECT(granules >= GC_TINY_FREELISTS,0)) { \
  52. result = default_expr; \
  53. } else { \
  54. void **my_fl = tiny_fl + granules; \
  55. void *my_entry=*my_fl; \
  56. void *next; \
  57. \
  58. while (GC_EXPECT((GC_word)my_entry \
  59. <= num_direct + GC_TINY_FREELISTS + 1, 0)) { \
  60. /* Entry contains counter or NULL */ \
  61. if ((GC_word)my_entry - 1 < num_direct) { \
  62. /* Small counter value, not NULL */ \
  63. *my_fl = (char *)my_entry + granules + 1; \
  64. result = default_expr; \
  65. goto out; \
  66. } else { \
  67. /* Large counter or NULL */ \
  68. GC_generic_malloc_many(((granules) == 0? GC_GRANULE_BYTES : \
  69. GC_RAW_BYTES_FROM_INDEX(granules)), \
  70. kind, my_fl); \
  71. my_entry = *my_fl; \
  72. if (my_entry == 0) { \
  73. result = GC_oom_fn(granules*GC_GRANULE_BYTES); \
  74. goto out; \
  75. } \
  76. } \
  77. } \
  78. next = *(void **)(my_entry); \
  79. result = (void *)my_entry; \
  80. *my_fl = next; \
  81. init; \
  82. PREFETCH_FOR_WRITE(next); \
  83. GC_ASSERT(GC_size(result) >= granules*GC_GRANULE_BYTES); \
  84. GC_ASSERT((kind) == PTRFREE || ((GC_word *)result)[1] == 0); \
  85. out: ; \
  86. } \
  87. }
  88. # define GC_WORDS_TO_WHOLE_GRANULES(n) \
  89. GC_WORDS_TO_GRANULES((n) + GC_GRANULE_WORDS - 1)
  90. /* Allocate n words (NOT BYTES). X is made to point to the result. */
  91. /* This should really only be used if GC_all_interior_pointers is */
  92. /* not set, or DONT_ADD_BYTE_AT_END is set. See above. */
  93. /* The semantics changed in version 7.0; we no longer lock, and */
  94. /* the caller is responsible for supplying a cleared tiny_fl */
  95. /* free list array. For single-threaded applications, this may be */
  96. /* a global array. */
  97. # define GC_MALLOC_WORDS(result,n,tiny_fl) \
  98. { \
  99. size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \
  100. GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \
  101. NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \
  102. *(void **)result = 0); \
  103. }
  104. # define GC_MALLOC_ATOMIC_WORDS(result,n,tiny_fl) \
  105. { \
  106. size_t grans = GC_WORDS_TO_WHOLE_GRANULES(n); \
  107. GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \
  108. PTRFREE, GC_malloc_atomic(grans*GC_GRANULE_BYTES), \
  109. /* no initialization */); \
  110. }
  111. /* And once more for two word initialized objects: */
  112. # define GC_CONS(result, first, second, tiny_fl) \
  113. { \
  114. size_t grans = GC_WORDS_TO_WHOLE_GRANULES(2); \
  115. GC_FAST_MALLOC_GRANS(result, grans, tiny_fl, 0, \
  116. NORMAL, GC_malloc(grans*GC_GRANULE_BYTES), \
  117. *(void **)result = (void *)(first)); \
  118. ((void **)(result))[1] = (void *)(second); \
  119. }