ems_gc_internal.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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 "ems_gc.h"
  12. /* HMU (heap memory unit) basic block type */
  13. typedef enum hmu_type_enum {
  14. HMU_TYPE_MIN = 0,
  15. HMU_TYPE_MAX = 3,
  16. HMU_JO = 3,
  17. HMU_VO = 2,
  18. HMU_FC = 1,
  19. HMU_FM = 0
  20. } hmu_type_t;
  21. typedef struct hmu_struct {
  22. gc_uint32 header;
  23. } hmu_t;
  24. #if BH_ENABLE_GC_VERIFY != 0
  25. #define GC_OBJECT_PREFIX_PADDING_CNT 3
  26. #define GC_OBJECT_SUFFIX_PADDING_CNT 4
  27. #define GC_OBJECT_PADDING_VALUE (0x12345678)
  28. typedef struct gc_object_prefix {
  29. const char *file_name;
  30. gc_int32 line_no;
  31. gc_int32 size;
  32. gc_uint32 padding[GC_OBJECT_PREFIX_PADDING_CNT];
  33. } gc_object_prefix_t;
  34. typedef struct gc_object_suffix {
  35. gc_uint32 padding[GC_OBJECT_SUFFIX_PADDING_CNT];
  36. } gc_object_suffix_t;
  37. #define OBJ_PREFIX_SIZE (sizeof(gc_object_prefix_t))
  38. #define OBJ_SUFFIX_SIZE (sizeof(gc_object_suffix_t))
  39. void
  40. hmu_init_prefix_and_suffix(hmu_t *hmu, gc_size_t tot_size,
  41. const char *file_name, int line_no);
  42. void
  43. hmu_verify(hmu_t *hmu);
  44. #define SKIP_OBJ_PREFIX(p) ((void*)((gc_uint8*)(p) + OBJ_PREFIX_SIZE))
  45. #define SKIP_OBJ_SUFFIX(p) ((void*)((gc_uint8*)(p) + OBJ_SUFFIX_SIZE))
  46. #define OBJ_EXTRA_SIZE (HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE)
  47. #else /* else of BH_ENABLE_GC_VERIFY */
  48. #define OBJ_PREFIX_SIZE 0
  49. #define OBJ_SUFFIX_SIZE 0
  50. #define SKIP_OBJ_PREFIX(p) ((void*)((gc_uint8*)(p) + OBJ_PREFIX_SIZE))
  51. #define SKIP_OBJ_SUFFIX(p) ((void*)((gc_uint8*)(p) + OBJ_SUFFIX_SIZE))
  52. #define OBJ_EXTRA_SIZE (HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE)
  53. #endif /* end of BH_ENABLE_GC_VERIFY */
  54. #define hmu_obj_size(s) ((s)-OBJ_EXTRA_SIZE)
  55. #define GC_ALIGN_8(s) (((uint32)(s) + 7) & (uint32)~7)
  56. #define GC_SMALLEST_SIZE GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + 8)
  57. #define GC_GET_REAL_SIZE(x) GC_ALIGN_8(HMU_SIZE + OBJ_PREFIX_SIZE + OBJ_SUFFIX_SIZE + (((x) > 8) ? (x): 8))
  58. /**
  59. * hmu bit operation
  60. */
  61. #define SETBIT(v, offset) (v) |= (1 << (offset))
  62. #define GETBIT(v, offset) ((v) & (1 << (offset)) ? 1 : 0)
  63. #define CLRBIT(v, offset) (v) &= (uint32)(~(1 << (offset)))
  64. #define SETBITS(v, offset, size, value) do { \
  65. (v) &= (uint32)(~(((1 << size) - 1) << offset));\
  66. (v) |= (uint32)(value << offset); \
  67. } while(0)
  68. #define CLRBITS(v, offset, size) (v) &= ~(((1 << size) - 1) << offset)
  69. #define GETBITS(v, offset, size) (((v) & ((uint32)(((1 << size) - 1) << offset))) >> offset)
  70. /**
  71. * gc object layout definition
  72. */
  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. /**
  93. * The hmu size is divisible by 8, its lowest 3 bits are 0, so we only
  94. * store its higher bits of bit [29..3], and bit [2..0] are not stored.
  95. * After that, the maximal heap size can be enlarged from (1<<27) = 128MB
  96. * to (1<<27) * 8 = 1GB.
  97. */
  98. #define HMU_SIZE_SIZE 27
  99. #define HMU_SIZE_OFFSET 0
  100. #define HMU_VO_FB_OFFSET 28
  101. #define hmu_is_vo_freed(hmu) GETBIT ((hmu)->header, HMU_VO_FB_OFFSET)
  102. #define hmu_unfree_vo(hmu) CLRBIT ((hmu)->header, HMU_VO_FB_OFFSET)
  103. #define hmu_get_size(hmu) (GETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE) << 3)
  104. #define hmu_set_size(hmu, size) SETBITS ((hmu)->header, HMU_SIZE_OFFSET, HMU_SIZE_SIZE, ((size) >> 3))
  105. /**
  106. * HMU free chunk management
  107. */
  108. #define HMU_NORMAL_NODE_CNT 32
  109. #define HMU_FC_NORMAL_MAX_SIZE ((HMU_NORMAL_NODE_CNT - 1) << 3)
  110. #define HMU_IS_FC_NORMAL(size) ((size) < HMU_FC_NORMAL_MAX_SIZE)
  111. #if HMU_FC_NORMAL_MAX_SIZE >= GC_MAX_HEAP_SIZE
  112. #error "Too small GC_MAX_HEAP_SIZE"
  113. #endif
  114. typedef struct hmu_normal_node {
  115. hmu_t hmu_header;
  116. gc_int32 next_offset;
  117. } hmu_normal_node_t;
  118. static inline hmu_normal_node_t *
  119. get_hmu_normal_node_next(hmu_normal_node_t *node)
  120. {
  121. return node->next_offset
  122. ? (hmu_normal_node_t *)((uint8*)node + node->next_offset)
  123. : NULL;
  124. }
  125. static inline void
  126. set_hmu_normal_node_next(hmu_normal_node_t *node, hmu_normal_node_t *next)
  127. {
  128. if (next) {
  129. bh_assert((uint8*)next - (uint8*)node < INT32_MAX);
  130. node->next_offset = (gc_int32)(intptr_t)
  131. ((uint8*)next - (uint8*)node);
  132. }
  133. else {
  134. node->next_offset = 0;
  135. }
  136. }
  137. typedef struct hmu_tree_node {
  138. hmu_t hmu_header;
  139. gc_size_t size;
  140. struct hmu_tree_node *left;
  141. struct hmu_tree_node *right;
  142. struct hmu_tree_node *parent;
  143. } hmu_tree_node_t;
  144. typedef struct gc_heap_struct {
  145. /* for double checking*/
  146. gc_handle_t heap_id;
  147. gc_uint8 *base_addr;
  148. gc_size_t current_size;
  149. gc_size_t max_size;
  150. korp_mutex lock;
  151. hmu_normal_node_t kfc_normal_list[HMU_NORMAL_NODE_CNT];
  152. /* order in kfc_tree is: size[left] <= size[cur] < size[right]*/
  153. hmu_tree_node_t kfc_tree_root;
  154. gc_size_t init_size;
  155. gc_size_t highmark_size;
  156. gc_size_t total_free_size;
  157. } gc_heap_t;
  158. /**
  159. * MISC internal used APIs
  160. */
  161. void
  162. gci_add_fc(gc_heap_t *heap, hmu_t *hmu, gc_size_t size);
  163. int
  164. gci_is_heap_valid(gc_heap_t *heap);
  165. /**
  166. * Verify heap integrity
  167. */
  168. void
  169. gci_verify_heap(gc_heap_t *heap);
  170. /**
  171. * Dump heap nodes
  172. */
  173. void
  174. gci_dump(gc_heap_t *heap);
  175. #ifdef __cplusplus
  176. }
  177. #endif
  178. #endif