new_gc_alloc.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  1. /*
  2. * Copyright (c) 1996-1998 by Silicon Graphics. All rights reserved.
  3. *
  4. * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  5. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  6. *
  7. * Permission is hereby granted to use or copy this program
  8. * for any purpose, provided the above notices are retained on all copies.
  9. * Permission to modify the code and to distribute modified code is granted,
  10. * provided the above notices are retained, and a notice that the code was
  11. * modified is included with the above copyright notice.
  12. */
  13. //
  14. // This is a revision of gc_allocator.h for SGI STL versions > 3.0.
  15. // Unlike earlier versions, it supplements the standard (STL) alloc.h
  16. // instead of replacing it.
  17. //
  18. // This is sloppy about variable names used in header files.
  19. // It also doesn't yet understand the new header file names or
  20. // namespaces.
  21. //
  22. // This assumes the collector has been compiled with -DGC_ATOMIC_UNCOLLECTABLE.
  23. // The user should also consider -DREDIRECT_MALLOC=GC_uncollectable_malloc,
  24. // to ensure that object allocated through malloc are traced.
  25. //
  26. // Some of this could be faster in the explicit deallocation case.
  27. // In particular, we spend too much time clearing objects on the
  28. // free lists. That could be avoided.
  29. //
  30. // This uses template classes with static members, and hence does not work
  31. // with g++ 2.7.2 and earlier.
  32. //
  33. // Unlike its predecessor, this one simply defines
  34. // gc_alloc
  35. // single_client_gc_alloc
  36. // traceable_alloc
  37. // single_client_traceable_alloc
  38. //
  39. // It does not redefine alloc. Nor does it change the default allocator,
  40. // though the user may wish to do so. (The argument against changing
  41. // the default allocator is that it may introduce subtle link compatibility
  42. // problems. The argument for changing it is that the usual default
  43. // allocator is usually a very bad choice for a garbage collected environment.)
  44. //
  45. #ifndef GC_ALLOC_H
  46. #include "gc.h"
  47. #if GC_GNUC_PREREQ(3, 0)
  48. # include <bits/stl_alloc.h>
  49. # ifndef __STL_BEGIN_NAMESPACE
  50. # define __STL_BEGIN_NAMESPACE namespace std {
  51. # define __STL_END_NAMESPACE };
  52. # endif
  53. # ifndef __STL_USE_STD_ALLOCATORS
  54. # define __STL_USE_STD_ALLOCATORS
  55. # endif
  56. #else
  57. # include <stack> // A more portable way to get stl_alloc.h file.
  58. #endif
  59. /* A hack to deal with gcc 3.1. If you are using gcc3.1 and later, */
  60. /* you should probably really use gc_allocator.h instead. */
  61. #if GC_GNUC_PREREQ(3, 1)
  62. # define simple_alloc __simple_alloc
  63. #endif
  64. #define GC_ALLOC_H
  65. #include <stddef.h>
  66. #include <string.h>
  67. // We can't include gc_priv.h, since that pulls in way too much stuff.
  68. #include "gc_alloc_ptrs.h"
  69. #define GC_generic_malloc_words_small(lw, k) \
  70. GC_generic_malloc((lw) * sizeof(GC_word), k)
  71. // Object kinds; must match PTRFREE, NORMAL, UNCOLLECTABLE, and
  72. // AUNCOLLECTABLE in gc_priv.h.
  73. enum { GC_PTRFREE = 0, GC_NORMAL = 1, GC_UNCOLLECTABLE = 2,
  74. GC_AUNCOLLECTABLE = 3 };
  75. enum { GC_max_fast_bytes = 255 };
  76. enum { GC_byte_alignment = 8 };
  77. #if defined(CPPCHECK)
  78. const unsigned GC_bytes_per_word = sizeof(char *);
  79. const unsigned GC_word_alignment = GC_byte_alignment/GC_bytes_per_word;
  80. #else
  81. enum { GC_bytes_per_word = sizeof(char *) };
  82. enum { GC_word_alignment = GC_byte_alignment/GC_bytes_per_word };
  83. #endif
  84. inline void * &GC_obj_link(void * p)
  85. { return *reinterpret_cast<void **>(p); }
  86. // Compute a number of words >= n+1 bytes.
  87. // The +1 allows for pointers one past the end.
  88. inline size_t GC_round_up(size_t n)
  89. {
  90. return ((n + GC_byte_alignment)/GC_byte_alignment)*GC_word_alignment;
  91. }
  92. // The same but don't allow for extra byte.
  93. inline size_t GC_round_up_uncollectable(size_t n)
  94. {
  95. return ((n + GC_byte_alignment - 1)/GC_byte_alignment)*GC_word_alignment;
  96. }
  97. template <int dummy>
  98. class GC_aux_template {
  99. public:
  100. // File local count of allocated words. Occasionally this is
  101. // added into the global count. A separate count is necessary since the
  102. // real one must be updated with a procedure call.
  103. static size_t GC_bytes_recently_allocd;
  104. // Same for uncollectible memory. Not yet reflected in either
  105. // GC_bytes_recently_allocd or GC_non_gc_bytes.
  106. static size_t GC_uncollectable_bytes_recently_allocd;
  107. // Similar counter for explicitly deallocated memory.
  108. static size_t GC_bytes_recently_freed;
  109. // Again for uncollectible memory.
  110. static size_t GC_uncollectable_bytes_recently_freed;
  111. static void * GC_out_of_line_malloc(size_t nwords, int kind);
  112. };
  113. template <int dummy>
  114. size_t GC_aux_template<dummy>::GC_bytes_recently_allocd = 0;
  115. template <int dummy>
  116. size_t GC_aux_template<dummy>::GC_uncollectable_bytes_recently_allocd = 0;
  117. template <int dummy>
  118. size_t GC_aux_template<dummy>::GC_bytes_recently_freed = 0;
  119. template <int dummy>
  120. size_t GC_aux_template<dummy>::GC_uncollectable_bytes_recently_freed = 0;
  121. template <int dummy>
  122. void * GC_aux_template<dummy>::GC_out_of_line_malloc(size_t nwords, int kind)
  123. {
  124. GC_bytes_recently_allocd += GC_uncollectable_bytes_recently_allocd;
  125. GC_non_gc_bytes +=
  126. GC_uncollectable_bytes_recently_allocd;
  127. GC_uncollectable_bytes_recently_allocd = 0;
  128. GC_bytes_recently_freed += GC_uncollectable_bytes_recently_freed;
  129. GC_non_gc_bytes -= GC_uncollectable_bytes_recently_freed;
  130. GC_uncollectable_bytes_recently_freed = 0;
  131. GC_incr_bytes_allocd(GC_bytes_recently_allocd);
  132. GC_bytes_recently_allocd = 0;
  133. GC_incr_bytes_freed(GC_bytes_recently_freed);
  134. GC_bytes_recently_freed = 0;
  135. return GC_generic_malloc_words_small(nwords, kind);
  136. }
  137. typedef GC_aux_template<0> GC_aux;
  138. // A fast, single-threaded, garbage-collected allocator
  139. // We assume the first word will be immediately overwritten.
  140. // In this version, deallocation is not a no-op, and explicit
  141. // deallocation is likely to help performance.
  142. template <int dummy>
  143. class single_client_gc_alloc_template {
  144. public:
  145. static void * allocate(size_t n)
  146. {
  147. size_t nwords = GC_round_up(n);
  148. void ** flh;
  149. void * op;
  150. if (n > GC_max_fast_bytes) return GC_malloc(n);
  151. flh = &GC_objfreelist_ptr[nwords];
  152. op = *flh;
  153. if (0 == op) {
  154. return GC_aux::GC_out_of_line_malloc(nwords, GC_NORMAL);
  155. }
  156. *flh = GC_obj_link(op);
  157. GC_aux::GC_bytes_recently_allocd += nwords * GC_bytes_per_word;
  158. return op;
  159. }
  160. static void * ptr_free_allocate(size_t n)
  161. {
  162. size_t nwords = GC_round_up(n);
  163. void ** flh;
  164. void * op;
  165. if (n > GC_max_fast_bytes) return GC_malloc_atomic(n);
  166. flh = &GC_aobjfreelist_ptr[nwords];
  167. op = *flh;
  168. if (0 == op) {
  169. return GC_aux::GC_out_of_line_malloc(nwords, GC_PTRFREE);
  170. }
  171. *flh = GC_obj_link(op);
  172. GC_aux::GC_bytes_recently_allocd += nwords * GC_bytes_per_word;
  173. return op;
  174. }
  175. static void deallocate(void *p, size_t n)
  176. {
  177. if (n > GC_max_fast_bytes) {
  178. GC_free(p);
  179. } else {
  180. size_t nwords = GC_round_up(n);
  181. void ** flh = &GC_objfreelist_ptr[nwords];
  182. GC_obj_link(p) = *flh;
  183. memset(reinterpret_cast<char *>(p) + GC_bytes_per_word, 0,
  184. GC_bytes_per_word * (nwords - 1));
  185. *flh = p;
  186. GC_aux::GC_bytes_recently_freed += nwords * GC_bytes_per_word;
  187. }
  188. }
  189. static void ptr_free_deallocate(void *p, size_t n)
  190. {
  191. if (n > GC_max_fast_bytes) {
  192. GC_free(p);
  193. } else {
  194. size_t nwords = GC_round_up(n);
  195. void ** flh = &GC_aobjfreelist_ptr[nwords];
  196. GC_obj_link(p) = *flh;
  197. *flh = p;
  198. GC_aux::GC_bytes_recently_freed += nwords * GC_bytes_per_word;
  199. }
  200. }
  201. };
  202. typedef single_client_gc_alloc_template<0> single_client_gc_alloc;
  203. // Once more, for uncollectible objects.
  204. template <int dummy>
  205. class single_client_traceable_alloc_template {
  206. public:
  207. static void * allocate(size_t n)
  208. {
  209. size_t nwords = GC_round_up_uncollectable(n);
  210. void ** flh;
  211. void * op;
  212. if (n > GC_max_fast_bytes) return GC_malloc_uncollectable(n);
  213. flh = &GC_uobjfreelist_ptr[nwords];
  214. op = *flh;
  215. if (0 == op) {
  216. return GC_aux::GC_out_of_line_malloc(nwords, GC_UNCOLLECTABLE);
  217. }
  218. *flh = GC_obj_link(op);
  219. GC_aux::GC_uncollectable_bytes_recently_allocd +=
  220. nwords * GC_bytes_per_word;
  221. return op;
  222. }
  223. static void * ptr_free_allocate(size_t n)
  224. {
  225. size_t nwords = GC_round_up_uncollectable(n);
  226. void ** flh;
  227. void * op;
  228. if (n > GC_max_fast_bytes) return GC_malloc_atomic_uncollectable(n);
  229. flh = &GC_auobjfreelist_ptr[nwords];
  230. op = *flh;
  231. if (0 == op) {
  232. return GC_aux::GC_out_of_line_malloc(nwords, GC_AUNCOLLECTABLE);
  233. }
  234. *flh = GC_obj_link(op);
  235. GC_aux::GC_uncollectable_bytes_recently_allocd +=
  236. nwords * GC_bytes_per_word;
  237. return op;
  238. }
  239. static void deallocate(void *p, size_t n)
  240. {
  241. if (n > GC_max_fast_bytes) {
  242. GC_free(p);
  243. } else {
  244. size_t nwords = GC_round_up_uncollectable(n);
  245. void ** flh = &GC_uobjfreelist_ptr[nwords];
  246. GC_obj_link(p) = *flh;
  247. *flh = p;
  248. GC_aux::GC_uncollectable_bytes_recently_freed +=
  249. nwords * GC_bytes_per_word;
  250. }
  251. }
  252. static void ptr_free_deallocate(void *p, size_t n)
  253. {
  254. if (n > GC_max_fast_bytes) {
  255. GC_free(p);
  256. } else {
  257. size_t nwords = GC_round_up_uncollectable(n);
  258. void ** flh = &GC_auobjfreelist_ptr[nwords];
  259. GC_obj_link(p) = *flh;
  260. *flh = p;
  261. GC_aux::GC_uncollectable_bytes_recently_freed +=
  262. nwords * GC_bytes_per_word;
  263. }
  264. }
  265. };
  266. typedef single_client_traceable_alloc_template<0> single_client_traceable_alloc;
  267. template < int dummy >
  268. class gc_alloc_template {
  269. public:
  270. static void * allocate(size_t n) { return GC_malloc(n); }
  271. static void * ptr_free_allocate(size_t n)
  272. { return GC_malloc_atomic(n); }
  273. static void deallocate(void *, size_t) { }
  274. static void ptr_free_deallocate(void *, size_t) { }
  275. };
  276. typedef gc_alloc_template < 0 > gc_alloc;
  277. template < int dummy >
  278. class traceable_alloc_template {
  279. public:
  280. static void * allocate(size_t n) { return GC_malloc_uncollectable(n); }
  281. static void * ptr_free_allocate(size_t n)
  282. { return GC_malloc_atomic_uncollectable(n); }
  283. static void deallocate(void *p, size_t) { GC_free(p); }
  284. static void ptr_free_deallocate(void *p, size_t) { GC_free(p); }
  285. };
  286. typedef traceable_alloc_template < 0 > traceable_alloc;
  287. // We want to specialize simple_alloc so that it does the right thing
  288. // for all pointer-free types. At the moment there is no portable way to
  289. // even approximate that. The following approximation should work for
  290. // SGI compilers, and recent versions of g++.
  291. // GC_SPECIALIZE() is used internally.
  292. #define GC_SPECIALIZE(T,alloc) \
  293. class simple_alloc<T, alloc> { \
  294. public: \
  295. static T *allocate(size_t n) \
  296. { return 0 == n? 0 : \
  297. reinterpret_cast<T*>(alloc::ptr_free_allocate(n * sizeof(T))); } \
  298. static T *allocate(void) \
  299. { return reinterpret_cast<T*>(alloc::ptr_free_allocate(sizeof(T))); } \
  300. static void deallocate(T *p, size_t n) \
  301. { if (0 != n) alloc::ptr_free_deallocate(p, n * sizeof(T)); } \
  302. static void deallocate(T *p) \
  303. { alloc::ptr_free_deallocate(p, sizeof(T)); } \
  304. };
  305. __STL_BEGIN_NAMESPACE
  306. GC_SPECIALIZE(char, gc_alloc)
  307. GC_SPECIALIZE(int, gc_alloc)
  308. GC_SPECIALIZE(unsigned, gc_alloc)
  309. GC_SPECIALIZE(float, gc_alloc)
  310. GC_SPECIALIZE(double, gc_alloc)
  311. GC_SPECIALIZE(char, traceable_alloc)
  312. GC_SPECIALIZE(int, traceable_alloc)
  313. GC_SPECIALIZE(unsigned, traceable_alloc)
  314. GC_SPECIALIZE(float, traceable_alloc)
  315. GC_SPECIALIZE(double, traceable_alloc)
  316. GC_SPECIALIZE(char, single_client_gc_alloc)
  317. GC_SPECIALIZE(int, single_client_gc_alloc)
  318. GC_SPECIALIZE(unsigned, single_client_gc_alloc)
  319. GC_SPECIALIZE(float, single_client_gc_alloc)
  320. GC_SPECIALIZE(double, single_client_gc_alloc)
  321. GC_SPECIALIZE(char, single_client_traceable_alloc)
  322. GC_SPECIALIZE(int, single_client_traceable_alloc)
  323. GC_SPECIALIZE(unsigned, single_client_traceable_alloc)
  324. GC_SPECIALIZE(float, single_client_traceable_alloc)
  325. GC_SPECIALIZE(double, single_client_traceable_alloc)
  326. __STL_END_NAMESPACE
  327. #ifdef __STL_USE_STD_ALLOCATORS
  328. __STL_BEGIN_NAMESPACE
  329. template <class _Tp>
  330. struct _Alloc_traits<_Tp, gc_alloc >
  331. {
  332. static const bool _S_instanceless = true;
  333. typedef simple_alloc<_Tp, gc_alloc > _Alloc_type;
  334. typedef __allocator<_Tp, gc_alloc > allocator_type;
  335. };
  336. inline bool operator==(const gc_alloc&,
  337. const gc_alloc&)
  338. {
  339. return true;
  340. }
  341. inline bool operator!=(const gc_alloc&,
  342. const gc_alloc&)
  343. {
  344. return false;
  345. }
  346. template <class _Tp>
  347. struct _Alloc_traits<_Tp, single_client_gc_alloc >
  348. {
  349. static const bool _S_instanceless = true;
  350. typedef simple_alloc<_Tp, single_client_gc_alloc > _Alloc_type;
  351. typedef __allocator<_Tp, single_client_gc_alloc > allocator_type;
  352. };
  353. inline bool operator==(const single_client_gc_alloc&,
  354. const single_client_gc_alloc&)
  355. {
  356. return true;
  357. }
  358. inline bool operator!=(const single_client_gc_alloc&,
  359. const single_client_gc_alloc&)
  360. {
  361. return false;
  362. }
  363. template <class _Tp>
  364. struct _Alloc_traits<_Tp, traceable_alloc >
  365. {
  366. static const bool _S_instanceless = true;
  367. typedef simple_alloc<_Tp, traceable_alloc > _Alloc_type;
  368. typedef __allocator<_Tp, traceable_alloc > allocator_type;
  369. };
  370. inline bool operator==(const traceable_alloc&,
  371. const traceable_alloc&)
  372. {
  373. return true;
  374. }
  375. inline bool operator!=(const traceable_alloc&,
  376. const traceable_alloc&)
  377. {
  378. return false;
  379. }
  380. template <class _Tp>
  381. struct _Alloc_traits<_Tp, single_client_traceable_alloc >
  382. {
  383. static const bool _S_instanceless = true;
  384. typedef simple_alloc<_Tp, single_client_traceable_alloc > _Alloc_type;
  385. typedef __allocator<_Tp, single_client_traceable_alloc > allocator_type;
  386. };
  387. inline bool operator==(const single_client_traceable_alloc&,
  388. const single_client_traceable_alloc&)
  389. {
  390. return true;
  391. }
  392. inline bool operator!=(const single_client_traceable_alloc&,
  393. const single_client_traceable_alloc&)
  394. {
  395. return false;
  396. }
  397. __STL_END_NAMESPACE
  398. #endif /* __STL_USE_STD_ALLOCATORS */
  399. #endif /* GC_ALLOC_H */