gc.c 8.2 KB

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