gc.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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_) ? true : (((gcs)->continue_ = true), false))
  11. #define gc_needFree(gcs) ((gcs)->statement_link == 0 && (gcs)->tmp_link == 0 && (gcs)->link == 0)
  12. #define gc_resetValue(value) ((value)->gc_status.c_value = not_free)
  13. #define gc_needFreeValue(value) (gc_needFree(&(value)->gc_status) && (value)->gc_status.c_value == need_free)
  14. static void gc_iterLinkValue(LinkValue *value){
  15. if (value == NULL)
  16. return;
  17. gc_addLink(&value->gc_status);
  18. if (!gc_iterAlready(&value->gc_status)){
  19. gc_iterLinkValue(value->belong);
  20. gc_iterValue(value->value);
  21. }
  22. }
  23. static void gc_iterValue(Value *value){
  24. if (value == NULL)
  25. return;
  26. gc_addLink(&value->gc_status);
  27. if (gc_iterAlready(&value->gc_status))
  28. return;
  29. gc_varList(value->object.var);
  30. gc_varList(value->object.out_var);
  31. {
  32. Inherit *ih = value->object.inherit;
  33. for (PASS; ih != NULL; ih = ih->next)
  34. gc_iterLinkValue(ih->value);
  35. }
  36. gc_resetValue(value);
  37. switch (value->type) {
  38. case V_list:
  39. for (int i=0;i < value->data.list.size;i++)
  40. gc_iterLinkValue(value->data.list.list[i]);
  41. break;
  42. case V_dict:
  43. gc_iterHashTable(value->data.dict.dict);
  44. break;
  45. case V_func:
  46. gc_iterLinkValue(value->data.function.function_data.cls);
  47. break;
  48. default:
  49. break;
  50. }
  51. }
  52. static void gc_varList(VarList *vl){
  53. for (PASS; vl != NULL; vl = vl->next)
  54. gc_iterHashTable(vl->hashtable);
  55. }
  56. static void gc_iterHashTable(HashTable *ht){
  57. if (ht == NULL)
  58. return;
  59. gc_addLink(&ht->gc_status);
  60. if (gc_iterAlready(&ht->gc_status))
  61. return;
  62. for (int i=0;i < MAX_SIZE;i++)
  63. gc_iterVar(ht->hashtable[i]);
  64. }
  65. static void gc_iterVar(Var *var){
  66. if (var == NULL)
  67. return;
  68. if (gc_iterAlready(&var->gc_status))
  69. return;
  70. for (PASS; var != NULL; var = var->next){
  71. gc_addLink(&var->gc_status);
  72. gc_iterLinkValue(var->name_);
  73. gc_iterLinkValue(var->value);
  74. }
  75. }
  76. #define gc_resetBase(inter) do { \
  77. for (Value *value_base = (inter)->base; value_base != NULL; value_base = value_base->gc_next) \
  78. {resetGC(&value_base->gc_status);} \
  79. for (LinkValue *link_base = (inter)->link_base; link_base != NULL; link_base = link_base->gc_next) \
  80. {resetGC(&link_base->gc_status);} \
  81. for (HashTable *hash_base = (inter)->hash_base; hash_base != NULL; hash_base = hash_base->gc_next) \
  82. {resetGC(&hash_base->gc_status);} \
  83. for (Var *var_base = (inter)->base_var; var_base != NULL; var_base = var_base->gc_next) \
  84. {resetGC(&var_base->gc_status);} \
  85. } while(0)
  86. static void gc_checkBase(Inter *inter){
  87. for (Value *value_base = inter->base; value_base != NULL; value_base = value_base->gc_next)
  88. if (!gc_needFree(&value_base->gc_status) && !value_base->gc_status.continue_)
  89. gc_iterValue(value_base);
  90. for (LinkValue *link_base = inter->link_base; link_base != NULL; link_base = link_base->gc_next)
  91. if (!gc_needFree(&link_base->gc_status) && !link_base->gc_status.continue_)
  92. gc_iterLinkValue(link_base);
  93. for (HashTable *hash_base = inter->hash_base; hash_base != NULL; hash_base = hash_base->gc_next)
  94. if (!gc_needFree(&hash_base->gc_status) && !hash_base->gc_status.continue_)
  95. gc_iterHashTable(hash_base);
  96. for (Var *var_base = inter->base_var; var_base != NULL; var_base = var_base->gc_next)
  97. if (!gc_needFree(&var_base->gc_status) && !var_base->gc_status.continue_)
  98. gc_iterVar(var_base);
  99. }
  100. static void gc_checkDel(Inter *inter){
  101. for (Value *value = inter->base; value != NULL; value = value->gc_next)
  102. if (!gc_needFree(&value->gc_status))
  103. gc_resetValue(value);
  104. else if (value->gc_status.c_value == not_free){
  105. if (needDel(value, inter)){
  106. gc_iterValue(value);
  107. value->gc_status.c_value = run_del;
  108. }
  109. else
  110. value->gc_status.c_value = need_free;
  111. }
  112. }
  113. void gc_runDelAll(Inter *inter){
  114. Result result;
  115. setResultCore(&result);
  116. for (Value *value = inter->base; value != NULL; value = value->gc_next) {
  117. gc_addTmpLink(&value->gc_status);
  118. if (needDel(value, inter)) {
  119. callDel(value, &result, inter, inter->var_list);
  120. if (!RUN_TYPE(result.type))
  121. printError(&result, inter, true);
  122. freeResult(&result);
  123. }
  124. gc_freeTmpLink(&value->gc_status);
  125. }
  126. }
  127. static void gc_runDel(Inter *inter, VarList *var_list){
  128. Result result;
  129. setResultCore(&result);
  130. for (Value *value = inter->base; value != NULL; value = value->gc_next) {
  131. if (value->gc_status.c_value == run_del) {
  132. gc_addTmpLink(&value->gc_status);
  133. callDel(value, &result, inter, var_list);
  134. if (!RUN_TYPE(result.type))
  135. printError(&result, inter, true);
  136. gc_freeTmpLink(&value->gc_status);
  137. value->gc_status.c_value = need_free;
  138. freeResult(&result);
  139. }
  140. }
  141. }
  142. static void gc_freeBase(Inter *inter){
  143. for (Value **value_base = &inter->base; *value_base != NULL;)
  144. if (gc_needFreeValue(*value_base))
  145. freeValue(value_base);
  146. else
  147. value_base = &(*value_base)->gc_next;
  148. for (LinkValue **link_base = &inter->link_base; *link_base != NULL;)
  149. if (gc_needFree(&(*link_base)->gc_status))
  150. freeLinkValue(link_base);
  151. else
  152. link_base = &(*link_base)->gc_next;
  153. for (HashTable **hash_base = &inter->hash_base; *hash_base != NULL;)
  154. if (gc_needFree(&(*hash_base)->gc_status))
  155. freeHashTable(hash_base);
  156. else
  157. hash_base = &(*hash_base)->gc_next;
  158. for (Var **var_base = &inter->base_var; *var_base != NULL;)
  159. if (gc_needFree(&(*var_base)->gc_status))
  160. freeVar(var_base);
  161. else
  162. var_base = &(*var_base)->gc_next;
  163. }
  164. void gc_run(Inter *inter, VarList *run_var){
  165. gc_resetBase(inter);
  166. gc_checkBase(inter);
  167. gc_checkDel(inter);
  168. gc_freeBase(inter);
  169. gc_runDel(inter, run_var);
  170. }
  171. #endif