ems_gc_internal.h 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #ifndef _EMS_GC_INTERNAL_H
  6. #define _EMS_GC_INTERNAL_H
  7. #ifdef __cplusplus
  8. extern "C" {
  9. #endif
  10. #include "bh_platform.h"
  11. #include "bh_thread.h"
  12. #include "bh_memory.h"
  13. #include "bh_assert.h"
  14. #include "ems_gc.h"
  15. /* basic block managed by EMS gc is the so-called HMU (heap memory unit)*/
  16. typedef enum _hmu_type_enum
  17. {
  18. HMU_TYPE_MIN = 0,
  19. HMU_TYPE_MAX = 3,
  20. HMU_JO = 3,
  21. HMU_VO = 2,
  22. HMU_FC = 1,
  23. HMU_FM = 0
  24. }hmu_type_t;
  25. typedef struct _hmu_struct
  26. {
  27. gc_uint32 header;
  28. }hmu_t;
  29. #if defined(GC_VERIFY)
  30. #define GC_OBJECT_PREFIX_PADDING_CNT 3
  31. #define GC_OBJECT_SUFFIX_PADDING_CNT 4
  32. #define GC_OBJECT_PADDING_VALUE (0x12345678)
  33. typedef struct _gc_object_prefix
  34. {
  35. const char *file_name;
  36. gc_int32 line_no;
  37. gc_int32 size;
  38. gc_uint32 padding[GC_OBJECT_PREFIX_PADDING_CNT];
  39. }gc_object_prefix_t;
  40. #define OBJ_PREFIX_SIZE (sizeof(gc_object_prefix_t))
  41. typedef struct _gc_object_suffix
  42. {
  43. gc_uint32 padding[GC_OBJECT_SUFFIX_PADDING_CNT];
  44. }gc_object_suffix_t;
  45. #define OBJ_SUFFIX_SIZE (sizeof(gc_object_suffix_t))
  46. extern void hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size, const char *file_name, int line_no);
  47. extern void hmu_verify(hmu_t *hmu);
  48. #define SKIP_OBJ_PREFIX(p) ((void*)((gc_uint8*)(p) + OBJ_PREFIX_SIZE))
  49. #define SKIP_OBJ_SUFFIX(p) ((void*)((gc_uint8*)(p) + OBJ_SUFFIX_SIZE))
  50. #define OBJ_EXTRA_SIZE (HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE)
  51. #else
  52. #define OBJ_PREFIX_SIZE 0
  53. #define OBJ_SUFFIX_SIZE 0
  54. #define SKIP_OBJ_PREFIX(p) ((void*)((gc_uint8*)(p) + OBJ_PREFIX_SIZE))
  55. #define SKIP_OBJ_SUFFIX(p) ((void*)((gc_uint8*)(p) + OBJ_SUFFIX_SIZE))
  56. #define OBJ_EXTRA_SIZE (HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE)
  57. #endif /* GC_DEBUG*/
  58. #define hmu_obj_size(s) ((s)-OBJ_EXTRA_SIZE)
  59. #define GC_ALIGN_8(s) (((uint32)(s) + 7) & (uint32)~7)
  60. #define GC_SMALLEST_SIZE GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + 8)
  61. #define GC_GET_REAL_SIZE(x) GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + (((x) > 8) ? (x): 8))
  62. /*////// functions for bit operation*/
  63. #define SETBIT(v, offset) (v) |= (1 << (offset))
  64. #define GETBIT(v, offset) ((v) & (1 << (offset)) ? 1 : 0)
  65. #define CLRBIT(v, offset) (v) &= (uint32)(~(1 << (offset)))
  66. #define SETBITS(v, offset, size, value) do { \
  67. (v) &= (uint32)(~(((1 << size) - 1) << offset));\
  68. (v) |= (uint32)(value << offset); \
  69. } while(0)
  70. #define CLRBITS(v, offset, size) (v) &= ~(((1 << size) - 1) << offset)
  71. #define GETBITS(v, offset, size) (((v) & ((uint32)(((1 << size) - 1) << offset))) >> offset)
  72. /*////// gc object layout definition*/
  73. #define HMU_SIZE (sizeof(hmu_t))
  74. #define hmu_to_obj(hmu) (gc_object_t)(SKIP_OBJ_PREFIX((hmu_t*) (hmu) + 1))
  75. #define obj_to_hmu(obj) ((hmu_t *)((gc_uint8*)(obj) - OBJ_PREFIX_SIZE) - 1)
  76. #define HMU_UT_SIZE 2
  77. #define HMU_UT_OFFSET 30
  78. #define hmu_get_ut(hmu) GETBITS ((hmu)->header, HMU_UT_OFFSET, HMU_UT_SIZE)
  79. #define hmu_set_ut(hmu, type) SETBITS ((hmu)->header, HMU_UT_OFFSET, HMU_UT_SIZE, type)
  80. #define hmu_is_ut_valid(tp) (tp >= HMU_TYPE_MIN && tp <= HMU_TYPE_MAX)
  81. /* P in use bit means the previous chunk is in use */
  82. #define HMU_P_OFFSET 29
  83. #define hmu_mark_pinuse(hmu) SETBIT ((hmu)->header, HMU_P_OFFSET)
  84. #define hmu_unmark_pinuse(hmu) CLRBIT ((hmu)->header, HMU_P_OFFSET)
  85. #define hmu_get_pinuse(hmu) GETBIT ((hmu)->header, HMU_P_OFFSET)
  86. #define HMU_JO_VT_SIZE 27
  87. #define HMU_JO_VT_OFFSET 0
  88. #define HMU_JO_MB_OFFSET 28
  89. #define hmu_mark_jo(hmu) SETBIT ((hmu)->header, HMU_JO_MB_OFFSET)
  90. #define hmu_unmark_jo(hmu) CLRBIT ((hmu)->header, HMU_JO_MB_OFFSET)
  91. #define hmu_is_jo_marked(hmu) GETBIT ((hmu)->header, HMU_JO_MB_OFFSET)
  92. #define HMU_SIZE_SIZE 27
  93. #define HMU_SIZE_OFFSET 0
  94. #define HMU_VO_FB_OFFSET 28
  95. #define hmu_is_vo_freed(hmu) GETBIT ((hmu)->header, HMU_VO_FB_OFFSET)
  96. #define hmu_unfree_vo(hmu) CLRBIT ((hmu)->header, HMU_VO_FB_OFFSET)
  97. #define hmu_get_size(hmu) GETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE)
  98. #define hmu_set_size(hmu, size) SETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE, size)
  99. /*////// HMU free chunk management*/
  100. #define HMU_NORMAL_NODE_CNT 32
  101. #define HMU_FC_NORMAL_MAX_SIZE ((HMU_NORMAL_NODE_CNT - 1) << 3)
  102. #define HMU_IS_FC_NORMAL(size) ((size) < HMU_FC_NORMAL_MAX_SIZE)
  103. #if HMU_FC_NORMAL_MAX_SIZE >= GC_MAX_HEAP_SIZE
  104. #error "Too small GC_MAX_HEAP_SIZE"
  105. #endif
  106. typedef struct _hmu_normal_node
  107. {
  108. hmu_t hmu_header;
  109. struct _hmu_normal_node *next;
  110. }hmu_normal_node_t;
  111. typedef struct _hmu_tree_node
  112. {
  113. hmu_t hmu_header;
  114. gc_size_t size;
  115. struct _hmu_tree_node *left;
  116. struct _hmu_tree_node *right;
  117. struct _hmu_tree_node *parent;
  118. }hmu_tree_node_t;
  119. typedef struct _gc_heap_struct
  120. {
  121. gc_handle_t heap_id; /* for double checking*/
  122. gc_uint8 *base_addr;
  123. gc_size_t current_size;
  124. gc_size_t max_size;
  125. korp_mutex lock;
  126. hmu_normal_node_t kfc_normal_list[HMU_NORMAL_NODE_CNT];
  127. /* order in kfc_tree is: size[left] <= size[cur] < size[right]*/
  128. hmu_tree_node_t kfc_tree_root;
  129. /* for rootset enumeration of private heap*/
  130. void *root_set;
  131. /* whether the fast mode of marking process that requires
  132. additional memory fails. When the fast mode fails, the
  133. marking process can still be done in the slow mode, which
  134. doesn't need additional memory (by walking through all
  135. blocks and marking sucessors of marked nodes until no new
  136. node is marked). TODO: slow mode is not implemented. */
  137. unsigned is_fast_marking_failed : 1;
  138. #if GC_STAT_DATA != 0
  139. gc_size_t highmark_size;
  140. gc_size_t init_size;
  141. gc_size_t total_gc_count;
  142. gc_size_t total_free_size;
  143. gc_size_t gc_threshold;
  144. gc_size_t gc_threshold_factor;
  145. gc_int64 total_gc_time;
  146. #endif
  147. }gc_heap_t;
  148. /*////// MISC internal used APIs*/
  149. extern void gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size);
  150. extern int gci_is_heap_valid(gc_heap_t *heap);
  151. #ifdef GC_DEBUG
  152. extern void gci_verify_heap(gc_heap_t *heap);
  153. extern void gci_dump(char* buf, gc_heap_t *heap);
  154. #endif
  155. #if GC_STAT_DATA != 0
  156. /* the default GC threshold size is free_size * GC_DEFAULT_THRESHOLD_FACTOR / 1000 */
  157. #define GC_DEFAULT_THRESHOLD_FACTOR 400
  158. static inline void gc_update_threshold(gc_heap_t *heap)
  159. {
  160. heap->gc_threshold = heap->total_free_size * heap->gc_threshold_factor / 1000;
  161. }
  162. #endif
  163. /*////// MISC data structures*/
  164. #define MARK_NODE_OBJ_CNT 256
  165. /* mark node is used for gc marker*/
  166. typedef struct _mark_node_struct
  167. {
  168. /* number of to-expand objects can be saved in this node*/
  169. gc_size_t cnt;
  170. /* the first unused index*/
  171. int idx;
  172. /* next node on the node list*/
  173. struct _mark_node_struct *next;
  174. /* the actual to-expand objects list*/
  175. gc_object_t set[MARK_NODE_OBJ_CNT];
  176. }mark_node_t;
  177. /*////// Imported APIs wrappers under TEST mode*/
  178. #ifdef GC_TEST
  179. extern int (*gct_vm_get_java_object_ref_list)(
  180. gc_object_t obj,
  181. int *is_compact_mode, /* can be set to GC_TRUE, or GC_FALSE */
  182. gc_size_t *ref_num,
  183. gc_uint16 **ref_list,
  184. gc_uint32 *ref_start_offset);
  185. extern int (*gct_vm_mutex_init)(korp_mutex *mutex);
  186. extern int (*gct_vm_mutex_destroy)(korp_mutex *mutex);
  187. extern int (*gct_vm_mutex_lock)(korp_mutex *mutex);
  188. extern int (*gct_vm_mutex_unlock)(korp_mutex *mutex);
  189. extern gc_handle_t (*gct_vm_get_gc_handle_for_current_instance)(void);
  190. extern int (*gct_vm_begin_rootset_enumeration)(void* heap);
  191. extern int (*gct_vm_gc_finished)(void);
  192. #else
  193. #define gct_vm_get_java_object_ref_list bh_get_java_object_ref_list
  194. #define gct_vm_mutex_init vm_mutex_init
  195. #define gct_vm_mutex_destroy vm_mutex_destroy
  196. #define gct_vm_mutex_lock vm_mutex_lock
  197. #define gct_vm_mutex_unlock vm_mutex_unlock
  198. #define gct_vm_get_gc_handle_for_current_instance app_manager_get_cur_applet_heap
  199. #define gct_vm_begin_rootset_enumeration vm_begin_rootset_enumeration
  200. #define gct_vm_gc_finished jeff_runtime_gc_finished
  201. #endif
  202. #ifdef __cplusplus
  203. }
  204. #endif
  205. #endif