gcj_mlc.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
  3. * Copyright (c) 1999 by Hewlett-Packard Company. All rights reserved.
  4. *
  5. * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  6. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
  7. *
  8. * Permission is hereby granted to use or copy this program
  9. * for any purpose, provided the above notices are retained on all copies.
  10. * Permission to modify the code and to distribute modified code is granted,
  11. * provided the above notices are retained, and a notice that the code was
  12. * modified is included with the above copyright notice.
  13. *
  14. */
  15. /* Boehm, July 31, 1995 5:02 pm PDT */
  16. /*
  17. * This is an allocator interface tuned for gcj (the GNU static
  18. * java compiler).
  19. *
  20. * Each allocated object has a pointer in its first word to a vtable,
  21. * which for our purposes is simply a structure describing the type of
  22. * the object.
  23. * This descriptor structure contains a GC marking descriptor at offset
  24. * MARK_DESCR_OFFSET.
  25. *
  26. * It is hoped that this interface may also be useful for other systems,
  27. * possibly with some tuning of the constants. But the immediate goal
  28. * is to get better gcj performance.
  29. *
  30. * We assume:
  31. * 1) We have an ANSI conforming C compiler.
  32. * 2) Counting on explicit initialization of this interface is OK.
  33. * 3) FASTLOCK is not a significant win.
  34. */
  35. #include "private/gc_pmark.h"
  36. #include "gc_gcj.h"
  37. #include "private/dbg_mlc.h"
  38. #ifdef GC_GCJ_SUPPORT
  39. GC_bool GC_gcj_malloc_initialized = FALSE;
  40. int GC_gcj_kind; /* Object kind for objects with descriptors */
  41. /* in "vtable". */
  42. int GC_gcj_debug_kind; /* The kind of objects that is always marked */
  43. /* with a mark proc call. */
  44. ptr_t * GC_gcjobjfreelist;
  45. ptr_t * GC_gcjdebugobjfreelist;
  46. /* Caller does not hold allocation lock. */
  47. void GC_init_gcj_malloc(int mp_index, void * /* really GC_mark_proc */mp)
  48. {
  49. register int i;
  50. GC_bool ignore_gcj_info;
  51. DCL_LOCK_STATE;
  52. GC_init(); /* In case it's not already done. */
  53. DISABLE_SIGNALS();
  54. LOCK();
  55. if (GC_gcj_malloc_initialized) {
  56. UNLOCK();
  57. ENABLE_SIGNALS();
  58. return;
  59. }
  60. GC_gcj_malloc_initialized = TRUE;
  61. ignore_gcj_info = (0 != GETENV("GC_IGNORE_GCJ_INFO"));
  62. # ifdef CONDPRINT
  63. if (GC_print_stats && ignore_gcj_info) {
  64. GC_printf0("Gcj-style type information is disabled!\n");
  65. }
  66. # endif
  67. GC_ASSERT(GC_mark_procs[mp_index] == (GC_mark_proc)0); /* unused */
  68. GC_mark_procs[mp_index] = (GC_mark_proc)mp;
  69. if (mp_index >= GC_n_mark_procs) ABORT("GC_init_gcj_malloc: bad index");
  70. /* Set up object kind gcj-style indirect descriptor. */
  71. GC_gcjobjfreelist = (ptr_t *)GC_new_free_list_inner();
  72. if (ignore_gcj_info) {
  73. /* Use a simple length-based descriptor, thus forcing a fully */
  74. /* conservative scan. */
  75. GC_gcj_kind = GC_new_kind_inner((void **)GC_gcjobjfreelist,
  76. (0 | GC_DS_LENGTH),
  77. TRUE, TRUE);
  78. } else {
  79. GC_gcj_kind = GC_new_kind_inner(
  80. (void **)GC_gcjobjfreelist,
  81. (((word)(-MARK_DESCR_OFFSET - GC_INDIR_PER_OBJ_BIAS))
  82. | GC_DS_PER_OBJECT),
  83. FALSE, TRUE);
  84. }
  85. /* Set up object kind for objects that require mark proc call. */
  86. if (ignore_gcj_info) {
  87. GC_gcj_debug_kind = GC_gcj_kind;
  88. GC_gcjdebugobjfreelist = GC_gcjobjfreelist;
  89. } else {
  90. GC_gcjdebugobjfreelist = (ptr_t *)GC_new_free_list_inner();
  91. GC_gcj_debug_kind = GC_new_kind_inner(
  92. (void **)GC_gcjdebugobjfreelist,
  93. GC_MAKE_PROC(mp_index,
  94. 1 /* allocated with debug info */),
  95. FALSE, TRUE);
  96. }
  97. UNLOCK();
  98. ENABLE_SIGNALS();
  99. }
  100. ptr_t GC_clear_stack();
  101. #define GENERAL_MALLOC(lb,k) \
  102. (GC_PTR)GC_clear_stack(GC_generic_malloc_inner((word)lb, k))
  103. #define GENERAL_MALLOC_IOP(lb,k) \
  104. (GC_PTR)GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k))
  105. /* We need a mechanism to release the lock and invoke finalizers. */
  106. /* We don't really have an opportunity to do this on a rarely executed */
  107. /* path on which the lock is not held. Thus we check at a */
  108. /* rarely executed point at which it is safe to release the lock. */
  109. /* We do this even where we could just call GC_INVOKE_FINALIZERS, */
  110. /* since it's probably cheaper and certainly more uniform. */
  111. /* FIXME - Consider doing the same elsewhere? */
  112. static void maybe_finalize()
  113. {
  114. static int last_finalized_no = 0;
  115. if (GC_gc_no == last_finalized_no) return;
  116. if (!GC_is_initialized) return;
  117. UNLOCK();
  118. GC_INVOKE_FINALIZERS();
  119. last_finalized_no = GC_gc_no;
  120. LOCK();
  121. }
  122. /* Allocate an object, clear it, and store the pointer to the */
  123. /* type structure (vtable in gcj). */
  124. /* This adds a byte at the end of the object if GC_malloc would.*/
  125. void * GC_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr)
  126. {
  127. register ptr_t op;
  128. register ptr_t * opp;
  129. register word lw;
  130. DCL_LOCK_STATE;
  131. if( EXPECT(SMALL_OBJ(lb), 1) ) {
  132. # ifdef MERGE_SIZES
  133. lw = GC_size_map[lb];
  134. # else
  135. lw = ALIGNED_WORDS(lb);
  136. # endif
  137. opp = &(GC_gcjobjfreelist[lw]);
  138. LOCK();
  139. op = *opp;
  140. if(EXPECT(op == 0, 0)) {
  141. maybe_finalize();
  142. op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
  143. if (0 == op) {
  144. UNLOCK();
  145. return(GC_oom_fn(lb));
  146. }
  147. # ifdef MERGE_SIZES
  148. lw = GC_size_map[lb]; /* May have been uninitialized. */
  149. # endif
  150. } else {
  151. *opp = obj_link(op);
  152. GC_words_allocd += lw;
  153. }
  154. *(void **)op = ptr_to_struct_containing_descr;
  155. GC_ASSERT(((void **)op)[1] == 0);
  156. UNLOCK();
  157. } else {
  158. LOCK();
  159. maybe_finalize();
  160. op = (ptr_t)GENERAL_MALLOC((word)lb, GC_gcj_kind);
  161. if (0 == op) {
  162. UNLOCK();
  163. return(GC_oom_fn(lb));
  164. }
  165. *(void **)op = ptr_to_struct_containing_descr;
  166. UNLOCK();
  167. }
  168. return((GC_PTR) op);
  169. }
  170. /* Similar to GC_gcj_malloc, but add debug info. This is allocated */
  171. /* with GC_gcj_debug_kind. */
  172. GC_PTR GC_debug_gcj_malloc(size_t lb, void * ptr_to_struct_containing_descr,
  173. GC_EXTRA_PARAMS)
  174. {
  175. GC_PTR result;
  176. /* We're careful to avoid extra calls, which could */
  177. /* confuse the backtrace. */
  178. LOCK();
  179. maybe_finalize();
  180. result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
  181. if (result == 0) {
  182. UNLOCK();
  183. GC_err_printf2("GC_debug_gcj_malloc(%ld, 0x%lx) returning NIL (",
  184. (unsigned long) lb,
  185. (unsigned long) ptr_to_struct_containing_descr);
  186. GC_err_puts(s);
  187. GC_err_printf1(":%ld)\n", (unsigned long)i);
  188. return(GC_oom_fn(lb));
  189. }
  190. *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
  191. UNLOCK();
  192. if (!GC_debugging_started) {
  193. GC_start_debugging();
  194. }
  195. ADD_CALL_CHAIN(result, ra);
  196. return (GC_store_debug_info(result, (word)lb, s, (word)i));
  197. }
  198. /* Similar to GC_gcj_malloc, but the size is in words, and we don't */
  199. /* adjust it. The size is assumed to be such that it can be */
  200. /* allocated as a small object. */
  201. void * GC_gcj_fast_malloc(size_t lw, void * ptr_to_struct_containing_descr)
  202. {
  203. ptr_t op;
  204. ptr_t * opp;
  205. DCL_LOCK_STATE;
  206. opp = &(GC_gcjobjfreelist[lw]);
  207. LOCK();
  208. op = *opp;
  209. if( EXPECT(op == 0, 0) ) {
  210. maybe_finalize();
  211. op = (ptr_t)GC_clear_stack(
  212. GC_generic_malloc_words_small_inner(lw, GC_gcj_kind));
  213. if (0 == op) {
  214. UNLOCK();
  215. return GC_oom_fn(WORDS_TO_BYTES(lw));
  216. }
  217. } else {
  218. *opp = obj_link(op);
  219. GC_words_allocd += lw;
  220. }
  221. *(void **)op = ptr_to_struct_containing_descr;
  222. UNLOCK();
  223. return((GC_PTR) op);
  224. }
  225. /* And a debugging version of the above: */
  226. void * GC_debug_gcj_fast_malloc(size_t lw,
  227. void * ptr_to_struct_containing_descr,
  228. GC_EXTRA_PARAMS)
  229. {
  230. GC_PTR result;
  231. size_t lb = WORDS_TO_BYTES(lw);
  232. /* We clone the code from GC_debug_gcj_malloc, so that we */
  233. /* dont end up with extra frames on the stack, which could */
  234. /* confuse the backtrace. */
  235. LOCK();
  236. maybe_finalize();
  237. result = GC_generic_malloc_inner(lb + DEBUG_BYTES, GC_gcj_debug_kind);
  238. if (result == 0) {
  239. UNLOCK();
  240. GC_err_printf2("GC_debug_gcj_fast_malloc(%ld, 0x%lx) returning NIL (",
  241. (unsigned long) lw,
  242. (unsigned long) ptr_to_struct_containing_descr);
  243. GC_err_puts(s);
  244. GC_err_printf1(":%ld)\n", (unsigned long)i);
  245. return GC_oom_fn(WORDS_TO_BYTES(lw));
  246. }
  247. *((void **)((ptr_t)result + sizeof(oh))) = ptr_to_struct_containing_descr;
  248. UNLOCK();
  249. if (!GC_debugging_started) {
  250. GC_start_debugging();
  251. }
  252. ADD_CALL_CHAIN(result, ra);
  253. return (GC_store_debug_info(result, (word)lb, s, (word)i));
  254. }
  255. void * GC_gcj_malloc_ignore_off_page(size_t lb,
  256. void * ptr_to_struct_containing_descr)
  257. {
  258. register ptr_t op;
  259. register ptr_t * opp;
  260. register word lw;
  261. DCL_LOCK_STATE;
  262. if( SMALL_OBJ(lb) ) {
  263. # ifdef MERGE_SIZES
  264. lw = GC_size_map[lb];
  265. # else
  266. lw = ALIGNED_WORDS(lb);
  267. # endif
  268. opp = &(GC_gcjobjfreelist[lw]);
  269. LOCK();
  270. if( (op = *opp) == 0 ) {
  271. maybe_finalize();
  272. op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
  273. # ifdef MERGE_SIZES
  274. lw = GC_size_map[lb]; /* May have been uninitialized. */
  275. # endif
  276. } else {
  277. *opp = obj_link(op);
  278. GC_words_allocd += lw;
  279. }
  280. *(void **)op = ptr_to_struct_containing_descr;
  281. UNLOCK();
  282. } else {
  283. LOCK();
  284. maybe_finalize();
  285. op = (ptr_t)GENERAL_MALLOC_IOP(lb, GC_gcj_kind);
  286. if (0 != op) {
  287. *(void **)op = ptr_to_struct_containing_descr;
  288. }
  289. UNLOCK();
  290. }
  291. return((GC_PTR) op);
  292. }
  293. #else
  294. char GC_no_gcj_support;
  295. #endif /* GC_GCJ_SUPPORT */