ems_gc_internal.h 8.4 KB

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