vector_mlc.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. * Copyright (c) 1991-1994 by Xerox Corporation. All rights reserved.
  3. * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
  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. #include "private/gc_pmark.h" /* includes gc_priv.h */
  16. #ifdef GC_GCJ_SUPPORT
  17. /*
  18. * This is an allocator interface tuned for gcj (the GNU static
  19. * java compiler).
  20. *
  21. * Each allocated object has a pointer in its first word to a vtable,
  22. * which for our purposes is simply a structure describing the type of
  23. * the object.
  24. * This descriptor structure contains a GC marking descriptor at offset
  25. * MARK_DESCR_OFFSET.
  26. *
  27. * It is hoped that this interface may also be useful for other systems,
  28. * possibly with some tuning of the constants. But the immediate goal
  29. * is to get better gcj performance.
  30. *
  31. * We assume:
  32. * 1) Counting on explicit initialization of this interface is OK;
  33. * 2) FASTLOCK is not a significant win.
  34. */
  35. #include "gc_vector.h"
  36. #include "private/dbg_mlc.h"
  37. #include "gc_typed.h"
  38. #ifdef GC_ASSERTIONS
  39. GC_INNER /* variable is also used in thread_local_alloc.c */
  40. #else
  41. STATIC
  42. #endif
  43. GC_bool GC_gcj_vector_initialized = FALSE;
  44. int GC_gcj_vector_kind = 0; /* Object kind for objects with descriptors */
  45. /* in "vtable". */
  46. int GC_gcj_vector_mp_index = 0;
  47. GC_INNER ptr_t * GC_gcjvecfreelist = NULL;
  48. /* Caller does not hold allocation lock. */
  49. GC_API void GC_CALL GC_init_gcj_vector (int mp_index,
  50. void * /* really GC_mark_proc */mp)
  51. {
  52. DCL_LOCK_STATE;
  53. if (mp == 0) /* In case GC_DS_PROC is unused. */
  54. ABORT ("GC_init_gcj_vector: bad index");
  55. GC_init (); /* In case it's not already done. */
  56. LOCK ();
  57. if (GC_gcj_vector_initialized) {
  58. UNLOCK ();
  59. return;
  60. }
  61. GC_gcj_vector_initialized = TRUE;
  62. GC_gcj_vector_mp_index = mp_index;
  63. GC_ASSERT (GC_mark_procs[mp_index] == (GC_mark_proc)0); /* unused */
  64. GC_mark_procs[mp_index ] = (GC_mark_proc)(word)mp;
  65. if ((unsigned)mp_index >= GC_n_mark_procs)
  66. ABORT ("GC_init_gcj_vector: bad index");
  67. GC_gcjvecfreelist = (ptr_t *)GC_new_free_list_inner ();
  68. GC_gcj_vector_kind = GC_new_kind_inner ((void **)GC_gcjvecfreelist,
  69. GC_MAKE_PROC (mp_index,
  70. 0),
  71. FALSE, TRUE);
  72. UNLOCK ();
  73. }
  74. #define GENERAL_MALLOC_INNER(lb,k) \
  75. GC_clear_stack(GC_generic_malloc_inner(lb, k))
  76. #define GENERAL_MALLOC_INNER_IOP(lb,k) \
  77. GC_clear_stack(GC_generic_malloc_inner_ignore_off_page(lb, k))
  78. #if !IL2CPP_ENABLE_WRITE_BARRIER_VALIDATION
  79. #ifdef THREAD_LOCAL_ALLOC
  80. GC_INNER void * GC_gcj_vector_malloc(size_t lb,
  81. void * ptr_to_struct_containing_descr)
  82. #else
  83. GC_API GC_ATTR_MALLOC void * GC_CALL GC_gcj_vector_malloc (size_t lb,
  84. void * ptr_to_struct_containing_descr)
  85. #endif
  86. {
  87. ptr_t op;
  88. DCL_LOCK_STATE;
  89. GC_DBG_COLLECT_AT_MALLOC (lb);
  90. if (SMALL_OBJ (lb)) {
  91. word lg;
  92. LOCK ();
  93. lg = GC_size_map[lb];
  94. op = GC_gcjvecfreelist[lg];
  95. if (EXPECT (0 == op, FALSE)) {
  96. maybe_finalize ();
  97. op = (ptr_t)GENERAL_MALLOC_INNER ((word)lb, GC_gcj_vector_kind);
  98. if (0 == op) {
  99. GC_oom_func oom_fn = GC_oom_fn;
  100. UNLOCK ();
  101. return((*oom_fn)(lb));
  102. }
  103. }
  104. else {
  105. GC_gcjvecfreelist[lg] = (ptr_t)obj_link (op);
  106. GC_bytes_allocd += GRANULES_TO_BYTES ((word)lg);
  107. }
  108. GC_ASSERT (((void **)op)[1] == 0);
  109. }
  110. else {
  111. LOCK ();
  112. maybe_finalize ();
  113. op = (ptr_t)GENERAL_MALLOC_INNER ((word)lb, GC_gcj_vector_kind);
  114. if (0 == op) {
  115. GC_oom_func oom_fn = GC_oom_fn;
  116. UNLOCK ();
  117. return((*oom_fn)(lb));
  118. }
  119. }
  120. *(void **)op = ptr_to_struct_containing_descr;
  121. UNLOCK ();
  122. GC_dirty (op);
  123. return((void *)op);
  124. }
  125. #define ELEMENT_CHUNK_SIZE 256
  126. GC_API mse *GC_CALL
  127. GC_gcj_vector_mark_proc (mse *mark_stack_ptr, mse* mark_stack_limit, GC_descr element_desc, word *start, word *end, int words_per_element)
  128. {
  129. /* create new descriptor that is shifted two bits to account
  130. * for lack of object header. Descriptors for value types include
  131. * the object header for boxed values */
  132. /* remove tags */
  133. GC_descr element_desc_shifted = element_desc & ~(GC_DS_TAGS);
  134. /* shift actual bits */
  135. element_desc_shifted = element_desc_shifted << 2;
  136. /* shifted and unmasked desc to use for bulk processing */
  137. GC_descr element_desc_shifted_unmasked = element_desc_shifted;
  138. /* add back tag to indicate descriptor is a bitmap */
  139. element_desc_shifted |= GC_DS_BITMAP;
  140. size_t remaining_elements = (end - start) / words_per_element;
  141. /* attempt to bulk process multiple elements with single descriptor */
  142. size_t elements_per_desc = (CPP_WORDSZ - GC_DS_TAG_BITS) / words_per_element;
  143. if (mark_stack_ptr >= mark_stack_limit)
  144. return GC_signal_mark_stack_overflow (mark_stack_ptr);
  145. /* setup bulk processing */
  146. if (elements_per_desc > 1) {
  147. word *current = start;
  148. size_t bulk_count = remaining_elements / elements_per_desc;
  149. size_t remainder_count = remaining_elements % elements_per_desc;
  150. /* bulk processing */
  151. if (bulk_count) {
  152. size_t bulk_stride = elements_per_desc * words_per_element;
  153. GC_descr bulk_desc = 0;
  154. size_t i;
  155. for (i = 0; i < elements_per_desc; ++i) {
  156. bulk_desc |= element_desc_shifted_unmasked >> (i * words_per_element);
  157. }
  158. bulk_desc |= GC_DS_BITMAP;
  159. if (bulk_count > ELEMENT_CHUNK_SIZE) {
  160. bulk_count = ELEMENT_CHUNK_SIZE;
  161. /* only process chunk number of items */
  162. end = start + bulk_count * bulk_stride;
  163. remainder_count = 0;
  164. mark_stack_ptr++;
  165. if (mark_stack_ptr >= mark_stack_limit)
  166. mark_stack_ptr = GC_signal_mark_stack_overflow (mark_stack_ptr);
  167. mark_stack_ptr->mse_descr.w = GC_MAKE_PROC (GC_gcj_vector_mp_index, 1 /* continue processing */);
  168. mark_stack_ptr->mse_start = (ptr_t)end;
  169. }
  170. while (bulk_count > 0) {
  171. mark_stack_ptr++;
  172. if (mark_stack_ptr >= mark_stack_limit)
  173. mark_stack_ptr = GC_signal_mark_stack_overflow (mark_stack_ptr);
  174. mark_stack_ptr->mse_start = (ptr_t) (current);
  175. mark_stack_ptr->mse_descr.w = bulk_desc;
  176. current += bulk_stride;
  177. bulk_count--;
  178. }
  179. }
  180. while (remainder_count > 0) {
  181. mark_stack_ptr++;
  182. if (mark_stack_ptr >= mark_stack_limit)
  183. mark_stack_ptr = GC_signal_mark_stack_overflow (mark_stack_ptr);
  184. mark_stack_ptr->mse_start = (ptr_t) (current);
  185. mark_stack_ptr->mse_descr.w = element_desc_shifted;
  186. current += words_per_element;
  187. remainder_count--;
  188. }
  189. } else {
  190. size_t remainder_count = remaining_elements;
  191. if (remainder_count > ELEMENT_CHUNK_SIZE) {
  192. remainder_count = ELEMENT_CHUNK_SIZE;
  193. /* only process chunk number of items */
  194. end = start + remainder_count * words_per_element;
  195. mark_stack_ptr++;
  196. if (mark_stack_ptr >= mark_stack_limit)
  197. mark_stack_ptr = GC_signal_mark_stack_overflow (mark_stack_ptr);
  198. mark_stack_ptr->mse_descr.w = GC_MAKE_PROC (GC_gcj_vector_mp_index, 1 /* continue processing */);
  199. mark_stack_ptr->mse_start = (ptr_t)end;
  200. }
  201. word *current = start;
  202. while (remainder_count > 0) {
  203. mark_stack_ptr++;
  204. if (mark_stack_ptr >= mark_stack_limit)
  205. mark_stack_ptr = GC_signal_mark_stack_overflow (mark_stack_ptr);
  206. mark_stack_ptr->mse_start = (ptr_t) (current);
  207. mark_stack_ptr->mse_descr.w = element_desc_shifted;
  208. current += words_per_element;
  209. remainder_count--;
  210. }
  211. }
  212. return (mark_stack_ptr);
  213. }
  214. #endif
  215. #endif /* GC_GCJ_SUPPORT */