PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/libgc/new_hblk.c

https://bitbucket.org/danipen/mono
C | 263 lines | 175 code | 28 blank | 60 comment | 20 complexity | f9c90c949db03af983f08385da6eac57 MD5 | raw file
Possible License(s): Unlicense, Apache-2.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0
  1. /*
  2. * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
  3. * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
  4. * Copyright (c) 2000 by Hewlett-Packard Company. All rights reserved.
  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. * This file contains the functions:
  16. * ptr_t GC_build_flXXX(h, old_fl)
  17. * void GC_new_hblk(n)
  18. */
  19. /* Boehm, May 19, 1994 2:09 pm PDT */
  20. # include <stdio.h>
  21. # include "private/gc_priv.h"
  22. #ifndef SMALL_CONFIG
  23. /*
  24. * Build a free list for size 1 objects inside hblk h. Set the last link to
  25. * be ofl. Return a pointer tpo the first free list entry.
  26. */
  27. ptr_t GC_build_fl1(h, ofl)
  28. struct hblk *h;
  29. ptr_t ofl;
  30. {
  31. register word * p = h -> hb_body;
  32. register word * lim = (word *)(h + 1);
  33. p[0] = (word)ofl;
  34. p[1] = (word)(p);
  35. p[2] = (word)(p+1);
  36. p[3] = (word)(p+2);
  37. p += 4;
  38. for (; p < lim; p += 4) {
  39. p[0] = (word)(p-1);
  40. p[1] = (word)(p);
  41. p[2] = (word)(p+1);
  42. p[3] = (word)(p+2);
  43. };
  44. return((ptr_t)(p-1));
  45. }
  46. /* The same for size 2 cleared objects */
  47. ptr_t GC_build_fl_clear2(h, ofl)
  48. struct hblk *h;
  49. ptr_t ofl;
  50. {
  51. register word * p = h -> hb_body;
  52. register word * lim = (word *)(h + 1);
  53. p[0] = (word)ofl;
  54. p[1] = 0;
  55. p[2] = (word)p;
  56. p[3] = 0;
  57. p += 4;
  58. for (; p < lim; p += 4) {
  59. p[0] = (word)(p-2);
  60. p[1] = 0;
  61. p[2] = (word)p;
  62. p[3] = 0;
  63. };
  64. return((ptr_t)(p-2));
  65. }
  66. /* The same for size 3 cleared objects */
  67. ptr_t GC_build_fl_clear3(h, ofl)
  68. struct hblk *h;
  69. ptr_t ofl;
  70. {
  71. register word * p = h -> hb_body;
  72. register word * lim = (word *)(h + 1) - 2;
  73. p[0] = (word)ofl;
  74. p[1] = 0;
  75. p[2] = 0;
  76. p += 3;
  77. for (; p < lim; p += 3) {
  78. p[0] = (word)(p-3);
  79. p[1] = 0;
  80. p[2] = 0;
  81. };
  82. return((ptr_t)(p-3));
  83. }
  84. /* The same for size 4 cleared objects */
  85. ptr_t GC_build_fl_clear4(h, ofl)
  86. struct hblk *h;
  87. ptr_t ofl;
  88. {
  89. register word * p = h -> hb_body;
  90. register word * lim = (word *)(h + 1);
  91. p[0] = (word)ofl;
  92. p[1] = 0;
  93. p[2] = 0;
  94. p[3] = 0;
  95. p += 4;
  96. for (; p < lim; p += 4) {
  97. PREFETCH_FOR_WRITE((ptr_t)(p+64));
  98. p[0] = (word)(p-4);
  99. p[1] = 0;
  100. CLEAR_DOUBLE(p+2);
  101. };
  102. return((ptr_t)(p-4));
  103. }
  104. /* The same for size 2 uncleared objects */
  105. ptr_t GC_build_fl2(h, ofl)
  106. struct hblk *h;
  107. ptr_t ofl;
  108. {
  109. register word * p = h -> hb_body;
  110. register word * lim = (word *)(h + 1);
  111. p[0] = (word)ofl;
  112. p[2] = (word)p;
  113. p += 4;
  114. for (; p < lim; p += 4) {
  115. p[0] = (word)(p-2);
  116. p[2] = (word)p;
  117. };
  118. return((ptr_t)(p-2));
  119. }
  120. /* The same for size 4 uncleared objects */
  121. ptr_t GC_build_fl4(h, ofl)
  122. struct hblk *h;
  123. ptr_t ofl;
  124. {
  125. register word * p = h -> hb_body;
  126. register word * lim = (word *)(h + 1);
  127. p[0] = (word)ofl;
  128. p[4] = (word)p;
  129. p += 8;
  130. for (; p < lim; p += 8) {
  131. PREFETCH_FOR_WRITE((ptr_t)(p+64));
  132. p[0] = (word)(p-4);
  133. p[4] = (word)p;
  134. };
  135. return((ptr_t)(p-4));
  136. }
  137. #endif /* !SMALL_CONFIG */
  138. /* Build a free list for objects of size sz inside heap block h. */
  139. /* Clear objects inside h if clear is set. Add list to the end of */
  140. /* the free list we build. Return the new free list. */
  141. /* This could be called without the main GC lock, if we ensure that */
  142. /* there is no concurrent collection which might reclaim objects that */
  143. /* we have not yet allocated. */
  144. ptr_t GC_build_fl(h, sz, clear, list)
  145. struct hblk *h;
  146. word sz;
  147. GC_bool clear;
  148. ptr_t list;
  149. {
  150. word *p, *prev;
  151. word *last_object; /* points to last object in new hblk */
  152. /* Do a few prefetches here, just because its cheap. */
  153. /* If we were more serious about it, these should go inside */
  154. /* the loops. But write prefetches usually don't seem to */
  155. /* matter much. */
  156. PREFETCH_FOR_WRITE((ptr_t)h);
  157. PREFETCH_FOR_WRITE((ptr_t)h + 128);
  158. PREFETCH_FOR_WRITE((ptr_t)h + 256);
  159. PREFETCH_FOR_WRITE((ptr_t)h + 378);
  160. /* Handle small objects sizes more efficiently. For larger objects */
  161. /* the difference is less significant. */
  162. # ifndef SMALL_CONFIG
  163. switch (sz) {
  164. case 1: return GC_build_fl1(h, list);
  165. case 2: if (clear) {
  166. return GC_build_fl_clear2(h, list);
  167. } else {
  168. return GC_build_fl2(h, list);
  169. }
  170. case 3: if (clear) {
  171. return GC_build_fl_clear3(h, list);
  172. } else {
  173. /* It's messy to do better than the default here. */
  174. break;
  175. }
  176. case 4: if (clear) {
  177. return GC_build_fl_clear4(h, list);
  178. } else {
  179. return GC_build_fl4(h, list);
  180. }
  181. default:
  182. break;
  183. }
  184. # endif /* !SMALL_CONFIG */
  185. /* Clear the page if necessary. */
  186. if (clear) BZERO(h, HBLKSIZE);
  187. /* Add objects to free list */
  188. p = &(h -> hb_body[sz]); /* second object in *h */
  189. prev = &(h -> hb_body[0]); /* One object behind p */
  190. last_object = (word *)((char *)h + HBLKSIZE);
  191. last_object -= sz;
  192. /* Last place for last object to start */
  193. /* make a list of all objects in *h with head as last object */
  194. while (p <= last_object) {
  195. /* current object's link points to last object */
  196. obj_link(p) = (ptr_t)prev;
  197. prev = p;
  198. p += sz;
  199. }
  200. p -= sz; /* p now points to last object */
  201. /*
  202. * put p (which is now head of list of objects in *h) as first
  203. * pointer in the appropriate free list for this size.
  204. */
  205. obj_link(h -> hb_body) = list;
  206. return ((ptr_t)p);
  207. }
  208. /*
  209. * Allocate a new heapblock for small objects of size n.
  210. * Add all of the heapblock's objects to the free list for objects
  211. * of that size.
  212. * Set all mark bits if objects are uncollectable.
  213. * Will fail to do anything if we are out of memory.
  214. */
  215. void GC_new_hblk(sz, kind)
  216. register word sz;
  217. int kind;
  218. {
  219. register struct hblk *h; /* the new heap block */
  220. register GC_bool clear = GC_obj_kinds[kind].ok_init;
  221. # ifdef PRINTSTATS
  222. if ((sizeof (struct hblk)) > HBLKSIZE) {
  223. ABORT("HBLK SZ inconsistency");
  224. }
  225. # endif
  226. if (GC_debugging_started) clear = TRUE;
  227. /* Allocate a new heap block */
  228. h = GC_allochblk(sz, kind, 0);
  229. if (h == 0) return;
  230. /* Mark all objects if appropriate. */
  231. if (IS_UNCOLLECTABLE(kind)) GC_set_hdr_marks(HDR(h));
  232. /* Build the free list */
  233. GC_obj_kinds[kind].ok_freelist[sz] =
  234. GC_build_fl(h, sz, clear, GC_obj_kinds[kind].ok_freelist[sz]);
  235. }