gc.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include "__virtualmath.h"
  2. #if START_GC
  3. static void gc_iterVar(Var *var);
  4. static void gc_iterLinkValue(LinkValue *value);
  5. static void gc_iterValue(Value *value);
  6. static void gc_varList(VarList *vl);
  7. static void gc_iterHashTable(HashTable *ht);
  8. #define resetGC(gcs) ((gcs)->continue_ = false, (gcs)->link = 0)
  9. // 若(gcs)->continue_为true, 则直接返回; 若为false则自增(+1后为false), 并返回自增前的值
  10. //#define gc_iterAlready(gcs) ((gcs)->continue_) || (((gcs)->continue_)++) // TODO-szh 不能达到预期的效果
  11. static bool gc_iterAlready(GCStatus *gcs){
  12. bool return_ = gcs->continue_;
  13. gcs->continue_ = true;
  14. return return_;
  15. }
  16. #define gc_needFree(gcs) ((gcs)->statement_link == 0 && (gcs)->tmp_link == 0 && (gcs)->link == 0)
  17. #define gc_resetValue(value) ((value)->gc_status.c_value = not_free)
  18. #define gc_needFreeValue(value) (gc_needFree(&(value)->gc_status) && (value)->gc_status.c_value == need_free)
  19. static void gc_iterLinkValue(LinkValue *value){
  20. if (value == NULL)
  21. return;
  22. gc_addLink(&value->gc_status);
  23. if (!gc_iterAlready(&value->gc_status)){
  24. gc_iterLinkValue(value->belong);
  25. gc_iterValue(value->value);
  26. }
  27. }
  28. static void gc_iterValue(Value *value){
  29. if (value == NULL)
  30. return;
  31. gc_addLink(&value->gc_status);
  32. if (gc_iterAlready(&value->gc_status))
  33. return;
  34. gc_varList(value->object.var);
  35. gc_varList(value->object.out_var);
  36. {
  37. Inherit *ih = value->object.inherit;
  38. for (PASS; ih != NULL; ih = ih->next)
  39. gc_iterLinkValue(ih->value);
  40. }
  41. gc_resetValue(value);
  42. switch (value->type) {
  43. case V_list:
  44. for (int i=0;i < value->data.list.size;i++)
  45. gc_iterLinkValue(value->data.list.list[i]);
  46. break;
  47. case V_dict:
  48. gc_iterHashTable(value->data.dict.dict);
  49. break;
  50. case V_func:
  51. gc_iterLinkValue(value->data.function.function_data.cls);
  52. break;
  53. default:
  54. break;
  55. }
  56. }
  57. static void gc_varList(VarList *vl){
  58. for (PASS; vl != NULL; vl = vl->next)
  59. gc_iterHashTable(vl->hashtable);
  60. }
  61. static void gc_iterHashTable(HashTable *ht){
  62. if (ht == NULL)
  63. return;
  64. gc_addLink(&ht->gc_status);
  65. if (gc_iterAlready(&ht->gc_status))
  66. return;
  67. for (int i=0;i < MAX_SIZE;i++)
  68. gc_iterVar(ht->hashtable[i]);
  69. }
  70. static void gc_iterVar(Var *var){
  71. if (var == NULL)
  72. return;
  73. if (gc_iterAlready(&var->gc_status))
  74. return;
  75. for (PASS; var != NULL; var = var->next){
  76. gc_addLink(&var->gc_status);
  77. gc_iterLinkValue(var->name_);
  78. gc_iterLinkValue(var->value);
  79. }
  80. }
  81. #define gc_resetBase(inter) do { \
  82. for (Value *value_base = (inter)->base; value_base != NULL; value_base = value_base->gc_next) \
  83. {resetGC(&value_base->gc_status);} \
  84. for (LinkValue *link_base = (inter)->link_base; link_base != NULL; link_base = link_base->gc_next) \
  85. {resetGC(&link_base->gc_status);} \
  86. for (HashTable *hash_base = (inter)->hash_base; hash_base != NULL; hash_base = hash_base->gc_next) \
  87. {resetGC(&hash_base->gc_status);} \
  88. for (Var *var_base = (inter)->base_var; var_base != NULL; var_base = var_base->gc_next) \
  89. {resetGC(&var_base->gc_status);} \
  90. } while(0)
  91. static void gc_checkBase(Inter *inter){
  92. for (Value *value_base = inter->base; value_base != NULL; value_base = value_base->gc_next)
  93. if (!gc_needFree(&value_base->gc_status) && !value_base->gc_status.continue_)
  94. gc_iterValue(value_base);
  95. for (LinkValue *link_base = inter->link_base; link_base != NULL; link_base = link_base->gc_next)
  96. if (!gc_needFree(&link_base->gc_status) && !link_base->gc_status.continue_)
  97. gc_iterLinkValue(link_base);
  98. for (HashTable *hash_base = inter->hash_base; hash_base != NULL; hash_base = hash_base->gc_next)
  99. if (!gc_needFree(&hash_base->gc_status) && !hash_base->gc_status.continue_)
  100. gc_iterHashTable(hash_base);
  101. for (Var *var_base = inter->base_var; var_base != NULL; var_base = var_base->gc_next)
  102. if (!gc_needFree(&var_base->gc_status) && !var_base->gc_status.continue_)
  103. gc_iterVar(var_base);
  104. }
  105. static void gc_checkDel(Inter *inter){
  106. for (Value *value = inter->base; value != NULL; value = value->gc_next)
  107. if (!gc_needFree(&value->gc_status))
  108. gc_resetValue(value);
  109. else if (value->gc_status.c_value == not_free){
  110. if (needDel(value, inter)){
  111. gc_iterValue(value);
  112. value->gc_status.c_value = run_del;
  113. }
  114. else
  115. value->gc_status.c_value = need_free;
  116. }
  117. }
  118. void gc_runDelAll(Inter *inter){
  119. Result result;
  120. setResultCore(&result);
  121. for (Value *value = inter->base; value != NULL; value = value->gc_next) {
  122. gc_addTmpLink(&value->gc_status);
  123. if (needDel(value, inter)) {
  124. callDel(value, &result, inter, inter->var_list);
  125. if (!RUN_TYPE(result.type))
  126. printError(&result, inter, true);
  127. freeResult(&result);
  128. }
  129. gc_freeTmpLink(&value->gc_status);
  130. }
  131. }
  132. static void gc_runDel(Inter *inter, VarList *var_list){
  133. Result result;
  134. setResultCore(&result);
  135. for (Value *value = inter->base; value != NULL; value = value->gc_next) {
  136. if (value->gc_status.c_value == run_del) {
  137. gc_addTmpLink(&value->gc_status);
  138. callDel(value, &result, inter, var_list);
  139. if (!RUN_TYPE(result.type))
  140. printError(&result, inter, true);
  141. gc_freeTmpLink(&value->gc_status);
  142. value->gc_status.c_value = need_free;
  143. freeResult(&result);
  144. }
  145. }
  146. }
  147. static void gc_freeBase(Inter *inter){
  148. for (Value **value_base = &inter->base; *value_base != NULL;)
  149. if (gc_needFreeValue(*value_base))
  150. freeValue(value_base);
  151. else
  152. value_base = &(*value_base)->gc_next;
  153. for (LinkValue **link_base = &inter->link_base; *link_base != NULL;)
  154. if (gc_needFree(&(*link_base)->gc_status))
  155. freeLinkValue(link_base);
  156. else
  157. link_base = &(*link_base)->gc_next;
  158. for (HashTable **hash_base = &inter->hash_base; *hash_base != NULL;)
  159. if (gc_needFree(&(*hash_base)->gc_status))
  160. freeHashTable(hash_base);
  161. else
  162. hash_base = &(*hash_base)->gc_next;
  163. for (Var **var_base = &inter->base_var; *var_base != NULL;)
  164. if (gc_needFree(&(*var_base)->gc_status))
  165. freeVar(var_base);
  166. else
  167. var_base = &(*var_base)->gc_next;
  168. }
  169. void gc_run(Inter *inter, VarList *run_var, int var_list, int link_value, int value, ...){
  170. gc_resetBase(inter);
  171. va_list arg;
  172. va_start(arg, value);
  173. for (int i =0;i < var_list;i ++){
  174. VarList *tmp = va_arg(arg, VarList *);
  175. gc_varList(tmp);
  176. }
  177. for (int i =0;i < link_value;i ++){
  178. LinkValue *tmp = va_arg(arg, LinkValue *);
  179. gc_iterLinkValue(tmp);
  180. }
  181. for (int i =0;i < value;i ++){
  182. Value *tmp = va_arg(arg, Value *);
  183. gc_iterValue(tmp);
  184. }
  185. va_end(arg);
  186. gc_checkBase(inter);
  187. gc_checkDel(inter);
  188. gc_freeBase(inter);
  189. gc_runDel(inter, run_var);
  190. }
  191. static void gc_freezeHashTable(HashTable *ht, bool is_lock){
  192. if (ht == NULL)
  193. return;
  194. if (is_lock) {
  195. gc_addTmpLink(&ht->gc_status);
  196. } else {
  197. gc_freeTmpLink(&ht->gc_status);
  198. }
  199. gc_iterAlready(&ht->gc_status);
  200. }
  201. /**
  202. * 冻结不可达的VarList的hashTable
  203. * @param inter
  204. * @param freeze
  205. * @param is_lock
  206. */
  207. void gc_freeze(Inter *inter, VarList *freeze, bool is_lock) {
  208. gc_resetBase(inter);
  209. for (PASS; freeze != NULL; freeze = freeze->next)
  210. gc_freezeHashTable(freeze->hashtable, is_lock);
  211. }
  212. #endif