소스 검색

refactor: 改变gc运行策略

调整gc启动机制
调整gc遍历机制
提高程序运行效率
SongZihuan 4 년 전
부모
커밋
504be2c9ef

+ 3 - 1
.gitignore

@@ -234,4 +234,6 @@ vgcore.*
 /bin*
 /lib*
 gmon.out
-profile.txt
+profile.txt
+call_graph.dot
+output.png

+ 3 - 0
CMakeLists.txt

@@ -6,6 +6,9 @@ OPTION(GC "GC" ON)
 OPTION(PG "PG" OFF)
 OPTION(SET_DEBUG "SET_DEBUG" ON)
 
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
+
 IF (NOT PG)
     SET(LIBRARY_OUTPUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib-${CMAKE_BUILD_TYPE})
     SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin-${CMAKE_BUILD_TYPE})

+ 59 - 58
vmcore/gc/gc.c

@@ -4,82 +4,83 @@
 static void gc_iterVar(Var *var);
 static void gc_iterLinkValue(LinkValue *value);
 static void gc_iterValue(Value *value);
-static void gc_varList(VarList *vl);
 static void gc_iterHashTable(HashTable *ht);
 
 #define resetGC(gcs) ((gcs)->continue_ = false, (gcs)->link = 0)
 
 // 若(gcs)->continue_为true, 则直接返回; 若为false则自增(+1后为false), 并返回自增前的值
-#define gc_iterAlready(gcs) (((gcs)->continue_) ? true : (((gcs)->continue_ = true), false))
+#define gc_shouldIter(gcs) (!((gcs)->continue_))
+#define gc_setIterAlready(gcs) ((gcs)->continue_ = true)
 
 #define gc_needFree(gcs) ((gcs)->statement_link == 0 && (gcs)->tmp_link == 0 && (gcs)->link == 0)
-#define gc_resetValue(value) ((value)->gc_status.c_value = not_free)
 #define gc_needFreeValue(value) (gc_needFree(&(value)->gc_status) && (value)->gc_status.c_value == need_free)
 
 static void gc_iterLinkValue(LinkValue *value){
-    if (value == NULL)
-        return;
+    gc_setIterAlready(&value->gc_status);
     gc_addLink(&value->gc_status);
-    if (!gc_iterAlready(&value->gc_status)){
+    if (value->belong != NULL && gc_shouldIter(&value->belong->gc_status))
         gc_iterLinkValue(value->belong);
+    if (gc_shouldIter(&value->value->gc_status))
         gc_iterValue(value->value);
-    }
 }
 
 static void gc_iterValue(Value *value){
-    if (value == NULL)
-        return;
+    gc_setIterAlready(&value->gc_status);
     gc_addLink(&value->gc_status);
-    if (gc_iterAlready(&value->gc_status))
-        return;
-    gc_varList(value->object.var);
-    gc_varList(value->object.out_var);
-    {
-        Inherit *ih = value->object.inherit;
-        for (PASS; ih != NULL; ih = ih->next)
+
+    for (VarList *vl = value->object.var; vl != NULL; vl = vl->next) {
+        if (gc_shouldIter(&vl->hashtable->gc_status))
+            gc_iterHashTable(vl->hashtable);
+    }
+
+    for (VarList *vl = value->object.out_var; vl != NULL; vl = vl->next) {
+        if (gc_shouldIter(&vl->hashtable->gc_status))
+            gc_iterHashTable(vl->hashtable);
+    }
+
+    for (Inherit *ih = value->object.inherit; ih != NULL; ih = ih->next) {
+        if (gc_shouldIter(&ih->value->gc_status))
             gc_iterLinkValue(ih->value);
     }
-    gc_resetValue(value);
+
+    // 不重置value的c_value属性, __del__始终只执行一次
     switch (value->type) {
         case V_list:
-            for (int i=0;i < value->data.list.size;i++)
-                gc_iterLinkValue(value->data.list.list[i]);
+            for (int i=0;i < value->data.list.size;i++) {
+                if (gc_shouldIter(&value->data.list.list[i]->gc_status))
+                    gc_iterLinkValue(value->data.list.list[i]);
+            }
             break;
         case V_dict:
-            gc_iterHashTable(value->data.dict.dict);
+            if (gc_shouldIter(&value->data.dict.dict->gc_status))
+                gc_iterHashTable(value->data.dict.dict);
             break;
         case V_func:
-            gc_iterLinkValue(value->data.function.function_data.cls);
+            if (value->data.function.function_data.cls != NULL && gc_shouldIter(&value->data.function.function_data.cls->gc_status))
+                gc_iterLinkValue(value->data.function.function_data.cls);
             break;
         default:
             break;
     }
 }
 
-static void gc_varList(VarList *vl){
-    for (PASS; vl != NULL; vl = vl->next)
-        gc_iterHashTable(vl->hashtable);
-}
-
 static void gc_iterHashTable(HashTable *ht){
-    if (ht == NULL)
-        return;
+    gc_setIterAlready(&ht->gc_status);
     gc_addLink(&ht->gc_status);
-    if (gc_iterAlready(&ht->gc_status))
-        return;
-    for (int i=0;i < MAX_SIZE;i++)
-        gc_iterVar(ht->hashtable[i]);
+    for (int i=0;i < MAX_SIZE;i++) {
+        if (ht->hashtable[i] != NULL)
+            gc_iterVar(ht->hashtable[i]);
+    }
 }
 
 static void gc_iterVar(Var *var){
-    if (var == NULL)
-        return;
-    if (gc_iterAlready(&var->gc_status))
-        return;
+    gc_setIterAlready(&var->gc_status);
     for (PASS; var != NULL; var = var->next){
         gc_addLink(&var->gc_status);
-        gc_iterLinkValue(var->name_);
-        gc_iterLinkValue(var->value);
+        if (gc_shouldIter(&var->name_->gc_status))
+            gc_iterLinkValue(var->name_);
+        if (gc_shouldIter(&var->value->gc_status))
+            gc_iterLinkValue(var->value);
     }
 }
 
@@ -96,34 +97,32 @@ static void gc_iterVar(Var *var){
 
 static void gc_checkBase(Inter *inter){
     for (Value *value_base = inter->base; value_base != NULL; value_base = value_base->gc_next)
-        if (!gc_needFree(&value_base->gc_status) && !value_base->gc_status.continue_)
+        if (!gc_needFree(&value_base->gc_status) && gc_shouldIter(&value_base->gc_status))
             gc_iterValue(value_base);
 
     for (LinkValue *link_base = inter->link_base; link_base != NULL; link_base = link_base->gc_next)
-        if (!gc_needFree(&link_base->gc_status) && !link_base->gc_status.continue_)
+        if (!gc_needFree(&link_base->gc_status) && gc_shouldIter(&link_base->gc_status))
             gc_iterLinkValue(link_base);
 
     for (HashTable *hash_base = inter->hash_base; hash_base != NULL; hash_base = hash_base->gc_next)
-        if (!gc_needFree(&hash_base->gc_status) && !hash_base->gc_status.continue_)
+        if (!gc_needFree(&hash_base->gc_status) && gc_shouldIter(&hash_base->gc_status))
             gc_iterHashTable(hash_base);
 
     for (Var *var_base = inter->base_var; var_base != NULL; var_base = var_base->gc_next)
-        if (!gc_needFree(&var_base->gc_status) && !var_base->gc_status.continue_)
+        if (!gc_needFree(&var_base->gc_status) && gc_shouldIter(&var_base->gc_status))
             gc_iterVar(var_base);
 }
 
 static void gc_checkDel(Inter *inter){
-    for (Value *value = inter->base; value != NULL; value = value->gc_next)
-        if (!gc_needFree(&value->gc_status))
-            gc_resetValue(value);
-        else if (value->gc_status.c_value == not_free){
-            if (needDel(value, inter)){
-                gc_iterValue(value);
+    for (Value *value = inter->base; value != NULL; value = value->gc_next) {
+        if (value->gc_status.c_value == not_free) {
+            if (needDel(value, inter)) {
+                gc_iterValue(value);  // 不需要检查是否位shouldIter, 因为他必然不是
                 value->gc_status.c_value = run_del;
-            }
-            else
+            } else
                 value->gc_status.c_value = need_free;
         }
+    }
 }
 
 void gc_runDelAll(Inter *inter){
@@ -131,7 +130,8 @@ void gc_runDelAll(Inter *inter){
     setResultCore(&result);
     for (Value *value = inter->base; value != NULL; value = value->gc_next) {
         gc_addTmpLink(&value->gc_status);
-        if (needDel(value, inter)) {
+        if (value->gc_status.c_value != need_free && needDel(value, inter)) {  // 检查value->gc_status.c_value != need_free; 是避免二次运行__del__
+            value->gc_status.c_value = need_free;
             callDel(value, &result, inter, inter->var_list);
             if (!RUN_TYPE(result.type))
                 printError(&result, inter, true);
@@ -146,24 +146,18 @@ static void gc_runDel(Inter *inter, VarList *var_list){
     setResultCore(&result);
     for (Value *value = inter->base; value != NULL; value = value->gc_next) {
         if (value->gc_status.c_value == run_del) {
+            value->gc_status.c_value = need_free;
             gc_addTmpLink(&value->gc_status);
             callDel(value, &result, inter, var_list);
             if (!RUN_TYPE(result.type))
                 printError(&result, inter, true);
             gc_freeTmpLink(&value->gc_status);
-            value->gc_status.c_value = need_free;
             freeResult(&result);
         }
     }
 }
 
 static void gc_freeBase(Inter *inter){
-    for (Value **value_base = &inter->base; *value_base != NULL;)
-        if (gc_needFreeValue(*value_base))
-            freeValue(value_base);
-        else
-            value_base = &(*value_base)->gc_next;
-
     for (LinkValue **link_base = &inter->link_base; *link_base != NULL;)
         if (gc_needFree(&(*link_base)->gc_status))
             freeLinkValue(link_base);
@@ -181,10 +175,17 @@ static void gc_freeBase(Inter *inter){
             freeVar(var_base);
         else
             var_base = &(*var_base)->gc_next;
+
+    for (Value **value_base = &inter->base; *value_base != NULL;)
+        if (gc_needFreeValue(*value_base))
+            freeValue(value_base);
+        else
+            value_base = &(*value_base)->gc_next;
 }
 
 void gc_run(Inter *inter, VarList *run_var){
     gc_resetBase(inter);
+    inter->data.run_gc = 0;
     gc_checkBase(inter);
     gc_checkDel(inter);
     gc_freeBase(inter);

+ 2 - 2
vmcore/include/gc.h

@@ -41,10 +41,10 @@ void gc_run(struct Inter *inter, struct VarList *run_var);
 #define gc_addStatementLink(gcs) ((void)0)
 #define gc_addLink(gcs) ((void)0)
 #define gc_freeTmpLink(gcs) ((void)0)
+#define gc_freeStatementLink(gcs) ((void)0)
+#define setGC(...) ((void)0)
 
 #define gc_run(...) ((void)0)
-#define setGC(...) ((void)0)
-#define gc_freeStatementLink(gcs) ((void)0)
 #define gc_runDelAll(...) ((void)0)
 #endif
 

+ 6 - 0
vmcore/include/inter.h

@@ -3,6 +3,10 @@
 
 struct Result;
 
+/* 100 大概是最好的值 */
+#define RUNGC (100)
+#define SHOULD_RUNGC(inter) ((inter)->data.start_gc && (inter)->data.run_gc >= RUNGC)
+
 #define BASEOBJSZIE (17)
 #define VARNAMESIZE (10)
 #define BASEEXCESIZE (19)
@@ -119,6 +123,8 @@ struct Inter{
             assert_run,  // 仅执行
             assert_raise,  // 执行并生效
         } assert_run;
+        int run_gc;  // gc的启动计数
+        bool start_gc;  // 是否启动gc
     } data;
 };
 

+ 3 - 0
vmcore/include/mem.h

@@ -6,6 +6,7 @@
 extern jmp_buf memVirtualMath_Env;
 extern bool memVirtualMathUseJmp;
 
+void memError(void);
 void *memCalloc(size_t num, size_t size);
 void *memRealloc(void *old, size_t size);
 char *memStrcpy(const char *str);
@@ -28,4 +29,6 @@ wchar_t *memStrToWcs(char *str, bool free_old);
 #define memStrlen(p) (((p) == NULL) ? 0 :strlen((p)))
 #define memWidelen(p) (((p) == NULL) ? 0 :wcslen((p)))
 
+#define MACRO_CALLOC(var, n, size) (((var = (typeof(var))calloc(n, size)) == NULL) ? (memError()) : (var))
+
 #endif //VIRTUALMATH_MEM_H

+ 1 - 0
vmcore/include/run.h

@@ -18,6 +18,7 @@ typedef ResultType (*VarInfo)(wchar_t **name, int *times, FUNC);
 
 ResultType globalIterStatement(Result *result, Inter *inter, Statement *st, bool p_clock);
 bool operationSafeInterStatement(FUNC);
+bool optSafeInterStatement(FUNC);
 bool ifBranchSafeInterStatement(FUNC);
 bool functionSafeInterStatement(FUNC);
 bool includeSafeInterStatement(FUNC);

+ 2 - 2
vmcore/include/value.h

@@ -16,6 +16,7 @@
 
 #define GET_RESULT(val, res) do {(val) = (res)->value; (res)->value=NULL; freeResult(res);} while(0)
 #define GET_RESULTONLY(val, res) do {(val) = (res)->value; (res)->value=NULL;} while(0)
+#define copyLinkValue(val, inter) makeLinkValue((val)->value, (val)->belong, (val)->aut, (inter))
 
 typedef struct Argument Argument;
 typedef struct Inter Inter;
@@ -231,9 +232,8 @@ enum BaseErrorType{
 
 Value *makeObject(Inter *inter, VarList *object, VarList *out_var, Inherit *inherit);
 void freeValue(Value **Value);
-LinkValue *makeLinkValue(Value *value, LinkValue *belong, Inter *inter);
+LinkValue *makeLinkValue(Value *value, LinkValue *belong, enum ValueAuthority aut, Inter *inter);
 void freeLinkValue(LinkValue **value);
-LinkValue *copyLinkValue(LinkValue *value, Inter *inter);
 Value *useNoneValue(Inter *inter, Result *result);
 Value *makeBoolValue(bool bool_num, fline line, char *file, FUNC_NT);
 Value *makePassValue(fline line, char *file, FUNC_NT);

+ 0 - 1
vmcore/include/var.h

@@ -35,7 +35,6 @@ struct VarList{
 };
 
 enum VarOperation {
-    get_var,
     read_var,
     del_var,
 };

+ 11 - 12
vmcore/memory/mem.c

@@ -3,25 +3,24 @@
 jmp_buf memVirtualMath_Env;
 bool memVirtualMathUseJmp;
 
+void memError(void) {
+    if (memVirtualMathUseJmp)
+        longjmp(memVirtualMath_Env, -1);
+    else
+        exit(2);
+}
+
 void *memCalloc(size_t num, size_t size){
     void *tmp = calloc(num, size);
-    if (tmp == NULL) {
-        if (memVirtualMathUseJmp)
-            longjmp(memVirtualMath_Env, -1);
-        else
-            exit(2);
-    }
+    if (tmp == NULL)
+        memError();
     return tmp;
 }
 
 void *memRealloc(void *old, size_t size){
     void *tmp = realloc(old, size);
-    if (tmp == NULL) {
-        if (memVirtualMathUseJmp)
-            longjmp(memVirtualMath_Env, -1);
-        else
-            exit(2);
-    }
+    if (tmp == NULL)
+        memError();
     return tmp;
 }
 

+ 1 - 1
vmcore/ofunc/src/__ofunc.c

@@ -75,7 +75,7 @@ LinkValue *makeBaseChildClass(LinkValue *inherit, Inter *inter) {
         gc_freeTmpLink(&inherit->gc_status);
     }
     new = makeClassValue(inter->var_list, inter, father_value);
-    re = makeLinkValue(new, inter->base_belong, inter);
+    re = makeLinkValue(new, inter->base_belong, auto_aut, inter);
     gc_freeTmpLink(&new->gc_status);
     return re;
 }

+ 2 - 2
vmcore/ofunc/src/dict.c

@@ -50,9 +50,9 @@ ResultType dict_down(O_FUNC){
     {
         LinkValue *element = NULL;
         wchar_t *name = getNameFromValue(ap[1].value->value, inter->data.var_deep, inter);
-        element = findVar(name, get_var, inter, ap[0].value->value->data.dict.dict);
+        element = findVar(name, read_var, inter, ap[0].value->value->data.dict.dict);
         if (element != NULL)
-            setResultOperationBase(result, copyLinkValue(element, inter));
+            setResultOperationBase(result, element);
         else {
             wchar_t *message = memWidecat(L"Dict could not find key value: ", name, false, false);
             setResultError(E_KeyException, message, LINEFILE, true, CNEXT_NT);

+ 2 - 3
vmcore/ofunc/src/function.c

@@ -22,7 +22,7 @@ ResultType function_new(O_FUNC){
         Inherit *object_father = getInheritFromValueCore(inter->data.base_obj[B_FUNCTION]);
         VarList *new_var = copyVarList(var_list, false, inter);
         Value *new_object = makeObject(inter, NULL, new_var, object_father);
-        value = makeLinkValue(new_object, belong, inter);
+        value = makeLinkValue(new_object, belong, auto_aut, inter);
         gc_freeTmpLink(&new_object->gc_status);
     }
 
@@ -86,8 +86,7 @@ ResultType function_set(O_FUNC){  // 针对FFI设置vaargs
         GET_RESULT(list, result);
         addAttributes(L"vaargs", false, list, LINEFILE, true, CFUNC_NT(var_list, result, func));
         gc_freeTmpLink(&list->gc_status);
-    }
-    else
+    } else
         findFromVarList(L"vaargs", 0, del_var, CFUNC_CORE(var_list));
 
     if (CHECK_RESULT(result))

+ 1 - 1
vmcore/ofunc/src/listiter.c

@@ -15,7 +15,7 @@ ResultType listiter_init(O_FUNC){
         return R_error;
     }
 
-    index = makeLinkValue(makeIntValue(0, LINEFILE, CNEXT_NT), ap[0].value, inter);
+    index = makeLinkValue(makeIntValue(0, LINEFILE, CNEXT_NT), ap[0].value, auto_aut, inter);
     if (!CHECK_RESULT(result))
         return result->type;
 

+ 3 - 3
vmcore/ofunc/src/object.c

@@ -89,13 +89,13 @@ void makeBaseObject(Inter *inter, LinkValue *belong){
 
     {
         Value *global_belong = makeObject(inter, copyVarList(inter->var_list, false, inter), NULL, NULL);
-        g_belong = makeLinkValue(global_belong, belong, inter);
+        g_belong = makeLinkValue(global_belong, belong, auto_aut, inter);
         gc_freeTmpLink(&global_belong->gc_status);
         inter->base_belong = g_belong;
         gc_addStatementLink(&inter->base_belong->gc_status);
     }
 
-    inter->data.base_obj[B_OBJECT] = makeLinkValue(object, g_belong, inter);
+    inter->data.base_obj[B_OBJECT] = makeLinkValue(object, g_belong, auto_aut, inter);
     gc_freeTmpLink(&object->gc_status);
     gc_addStatementLink(&inter->data.base_obj[B_OBJECT]->gc_status);
     for (Inherit *ih=g_belong->value->object.inherit; ih != NULL; ih = ih->next) {
@@ -106,7 +106,7 @@ void makeBaseObject(Inter *inter, LinkValue *belong){
 
     {
         Result result;
-        Argument *arg = makeValueArgument(makeLinkValue(object, g_belong, inter));
+        Argument *arg = makeValueArgument(makeLinkValue(object, g_belong, auto_aut, inter));
         setResultCore(&result);
         object_new(CO_FUNC(arg, inter->var_list, &result, g_belong));
 

+ 5 - 3
vmcore/src/__run.c

@@ -302,7 +302,7 @@ void freeFunctionArgument(Argument *arg, Argument *base) {
 LinkValue *findStrVar(wchar_t *name, bool free_old, fline line, char *file, bool nowrun, FUNC_NT){
     LinkValue *tmp = NULL;
     wchar_t *name_ = setStrVarName(name, free_old, inter);
-    tmp = findFromVarList(name_, 0, get_var, CFUNC_CORE(var_list));
+    tmp = findFromVarList(name_, 0, read_var, CFUNC_CORE(var_list));
     memFree(name_);
     if (tmp != NULL && nowrun) {
         setResultCore(result);
@@ -360,8 +360,10 @@ void addStrVar(wchar_t *name, bool free_old, bool setting, LinkValue *value, fli
 LinkValue *findAttributes(wchar_t *name, bool free_old, fline line, char *file, bool nowrun, FUNC_NT) {
     LinkValue *attr;
     attr = findStrVar(name, free_old, line, file, nowrun, CFUNC_NT(belong->value->object.var, result, belong));
-    if (attr != NULL && (attr->belong == NULL || attr->belong->value == belong->value || checkAttribution(belong->value, attr->belong->value)))
+    if (attr != NULL && attr->belong != NULL && attr->belong->value != belong->value && checkAttribution(belong->value, attr->belong->value)) {
+        attr = copyLinkValue(attr, inter);
         attr->belong = belong;
+    }
     return attr;
 }
 
@@ -543,7 +545,7 @@ LinkValue *make_new(Inter *inter, LinkValue *belong, LinkValue *class){
     Inherit *object_father = getInheritFromValueCore(class);
     VarList *new_var = copyVarList(class->value->object.out_var, false, inter);
     Value *new_object = makeObject(inter, NULL, new_var, object_father);
-    LinkValue *re = makeLinkValue(new_object, belong, inter);
+    LinkValue *re = makeLinkValue(new_object, belong, auto_aut, inter);
     gc_freeTmpLink(&new_object->gc_status);
     return re;
 }

+ 7 - 0
vmcore/src/inter.c

@@ -49,6 +49,11 @@ Inter *makeInter(char *out, char *error_, char *in, LinkValue *belong) {
     }
 
     registeredFunctionName(tmp, belong);
+    printf("start run gc = %d sec\n", tmp->data.run_gc);
+    tmp->data.start_gc = true;
+#if START_GC
+    gc_run(tmp, tmp->var_list);
+#endif
     return tmp;
 }
 
@@ -119,6 +124,8 @@ void setBaseInterData(struct Inter *inter){
     inter->data.var_max = 100;
     inter->data.var_deep = 3;
     inter->data.assert_run = assert_raise;
+    inter->data.run_gc = 0;
+    inter->data.start_gc = false;
 }
 
 void freeBaseInterData(struct Inter *inter){

+ 19 - 12
vmcore/src/run.c

@@ -9,7 +9,7 @@
  */
 ResultType runStatement(FUNC) {
     ResultType type = R_not;
-    bool run_gc = st->next == NULL;  // 若st已经没有下一部了则执行gc
+    bool run_gc = false;  // 若st已经没有下一部了则执行gc
     setResultCore(result);
     gc_addTmpLink(&belong->gc_status);
 
@@ -22,6 +22,7 @@ ResultType runStatement(FUNC) {
             break;
         case base_svar:
             type = getVar(CNEXT, getBaseSVarInfo);
+            run_gc = true;
             break;
         case base_list:
             type = getList(CNEXT);
@@ -38,38 +39,30 @@ ResultType runStatement(FUNC) {
             break;
         case set_class:
             type = setClass(CNEXT);
-            run_gc = true;
             break;
         case set_function:
             type = setFunction(CNEXT);
-            run_gc = true;
             break;
         case slice_:
             type = elementSlice(CNEXT);
             break;
         case call_function:
             type = callBack(CNEXT);
-            run_gc = true;
             break;
         case if_branch:
             type = ifBranch(CNEXT);
-            run_gc = true;
             break;
         case while_branch:
             type = whileBranch(CNEXT);
-            run_gc = true;
             break;
         case for_branch:
             type = forBranch(CNEXT);
-            run_gc = true;
             break;
         case with_branch:
             type = withBranch(CNEXT);
-            run_gc = true;
             break;
         case try_branch:
             type = tryBranch(CNEXT);
-            run_gc = true;
             break;
         case break_cycle:
             type = breakCycle(CNEXT);
@@ -126,13 +119,13 @@ ResultType runStatement(FUNC) {
     result->node = st;
     gc_freeTmpLink(&belong->gc_status);
 #if START_GC
-    if (run_gc)
+    if (run_gc && SHOULD_RUNGC(inter))
         gc_run(inter, var_list);
 #endif
     return type;
 }
 
-ResultType runStatementOpt(FUNC) {  // 不运行gc机制
+ResultType runStatementOpt(bool run_gc, FUNC) {  // 不运行gc机制
     ResultType type = R_not;
     setResultCore(result);
     gc_addTmpLink(&belong->gc_status);
@@ -174,6 +167,10 @@ ResultType runStatementOpt(FUNC) {  // 不运行gc机制
     if (RUN_TYPE(type) && st->aut != auto_aut)
         result->value->aut = st->aut;  // 权限覆盖
     result->node = st;
+#if START_GC
+    if (run_gc && SHOULD_RUNGC(inter))
+        gc_run(inter, var_list);
+#endif
     gc_freeTmpLink(&belong->gc_status);
     return type;
 }
@@ -324,7 +321,17 @@ ResultType globalIterStatement(Result *result, Inter *inter, Statement *st, bool
 bool operationSafeInterStatement(FUNC){
     ResultType type;
     assert(st->next == NULL);  // opt 以单句形式存在
-    type = runStatementOpt(CNEXT);
+    type = runStatementOpt(true, CNEXT);
+    if (RUN_TYPE(type))
+        return false;
+    assert(type == return_code || type == R_error);
+    return true;
+}
+
+bool optSafeInterStatement(FUNC){
+    ResultType type;
+    assert(st->next == NULL);  // opt 以单句形式存在
+    type = runStatementOpt(false, CNEXT);
     if (RUN_TYPE(type))
         return false;
     assert(type == return_code || type == R_error);

+ 31 - 22
vmcore/src/runcall.c

@@ -13,7 +13,7 @@ ResultType setClass(FUNC) {
     class_inherit = setFather(call);
     freeArgument(call, false);
 
-    tmp = makeLinkValue(makeClassValue(var_list, inter, class_inherit), belong, inter);
+    tmp = makeLinkValue(makeClassValue(var_list, inter, class_inherit), belong, auto_aut, inter);
     gc_freeTmpLink(&tmp->value->gc_status);
     gc_addTmpLink(&tmp->gc_status);
     freeResult(result);
@@ -241,7 +241,12 @@ static ResultType callCFunction(LinkValue *func_value, Argument *arg, long int l
     popVarList(function_var);
     freeFunctionArgument(arg, bak);
 
-    return_: gc_freeTmpLink(&func_value->gc_status);
+    return_:
+#if START_GC
+    if (SHOULD_RUNGC(inter))
+        gc_run(inter, var_list);
+#endif
+    gc_freeTmpLink(&func_value->gc_status);
     return result->type;
 }
 
@@ -536,28 +541,32 @@ static ResultType callVMFunction(LinkValue *func_value, Argument *arg, long int
 ResultType callBackCore(LinkValue *function_value, Argument *arg, fline line, char *file, int pt_sep, FUNC_NT) {
     setResultCore(result);
     gc_addTmpLink(&function_value->gc_status);
-    if (function_value->value->type == V_func) {
-        switch (function_value->value->data.function.type) {
-            case vm_func:
-                callVMFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
-                break;
-            case c_func:
-                callCFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
-                break;
-            case f_func:
-                callFFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
-                break;
-            default:
-                setResultError(E_SystemException, L"function type error", line, file, true, CNEXT_NT);
-                goto return_;
-        }
-    } else if (function_value->value->type == V_class)
-        callClass(function_value, arg, line, file, pt_sep, CNEXT_NT);
-    else
-        callObject(function_value, arg, line, file, pt_sep, CNEXT_NT);
+    switch (function_value->value->type) {
+        case V_func:
+            switch (function_value->value->data.function.type) {
+                case vm_func:
+                    callVMFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
+                    break;
+                case c_func:
+                    callCFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
+                    break;
+                case f_func:
+                    callFFunction(function_value, arg, line, file, pt_sep, CNEXT_NT);
+                    break;
+                default:
+                    setResultError(E_SystemException, L"function type error", line, file, true, CNEXT_NT);
+                    break;
+            }
+            break;
+        case V_class:
+            callClass(function_value, arg, line, file, pt_sep, CNEXT_NT);
+            break;
+        default :
+            callObject(function_value, arg, line, file, pt_sep, CNEXT_NT);
+            break;
+    }
     // callBackCore不执行错误回溯
 
-    return_:
     gc_freeTmpLink(&function_value->gc_status);
     return result->type;
 }

+ 1 - 1
vmcore/src/runfile.c

@@ -218,7 +218,7 @@ static bool getPackage(LinkValue **imp_value, char *md5_str, char *split, int st
         }
     } else
         *is_new = false;
-    *imp_value = makeLinkValue(pg, belong, inter);
+    *imp_value = makeLinkValue(pg, belong, auto_aut, inter);
     gc_freeTmpLink(&pg->gc_status);
     gc_addTmpLink(&(*imp_value)->gc_status);
     return true;

+ 20 - 18
vmcore/src/runoperation.c

@@ -126,7 +126,7 @@ ResultType boolNotOperation(FUNC) {
     bool new;
     LinkValue *left;
     setResultCore(result);
-    if (operationSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)))
+    if (optSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)))
         return result->type;
     GET_RESULT(left, result);
 
@@ -145,7 +145,7 @@ ResultType boolOperation(FUNC) {
     LinkValue *left;
     setResultCore(result);
 
-    if (operationSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)))
+    if (optSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)))
         return result->type;
     GET_RESULT(left, result);
 
@@ -157,14 +157,14 @@ ResultType boolOperation(FUNC) {
     freeResult(result);
     if (st->u.operation.OperationType == OPT_AND) {  // 与运算
         if (left_bool)
-            operationSafeInterStatement(CFUNC(st->u.operation.right, var_list, result, belong));
+            optSafeInterStatement(CFUNC(st->u.operation.right, var_list, result, belong));
         else
             setResultOperation(result, left);
     } else {  // 或运算
         if (left_bool)
             setResultOperation(result, left);
         else
-            operationSafeInterStatement(CFUNC(st->u.operation.right, var_list, result, belong));
+            optSafeInterStatement(CFUNC(st->u.operation.right, var_list, result, belong));
     }
     return result->type;
 }
@@ -174,7 +174,7 @@ ResultType pointOperation(FUNC) {
     VarList *object = NULL;
     bool pri_auto;
     setResultCore(result);
-    if (operationSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)) || result->value->value->type == V_none)
+    if (optSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)) || result->value->value->type == V_none)
         return result->type;
     GET_RESULT(left, result);
     if (st->aut != auto_aut)
@@ -189,12 +189,14 @@ ResultType pointOperation(FUNC) {
         setResultError(E_TypeException, OBJ_NOTSUPPORT(->/.), st->line, st->code_file, true, CNEXT_NT);
         goto return_;
     }
-    operationSafeInterStatement(CFUNC(st->u.operation.right, object, result, left));  // 点运算运算时需要调整belong为点的左值
-    pri_auto = result->value->belong == NULL || result->value->belong->value == belong->value || checkAttribution(belong->value, result->value->belong->value);
+    optSafeInterStatement(CFUNC(st->u.operation.right, object, result, left));  // 点运算运算时需要调整belong为点的左值
+    pri_auto = result->value->belong == NULL || result->value->belong->value == belong->value || checkAttribution(belong->value, result->value->belong->value);  // 检查获取的value是是否属于belong, 或属于belong的父亲
     if (!CHECK_RESULT(result) || !checkAut(left->aut, result->value->aut, st->line, st->code_file, NULL, pri_auto, CNEXT_NT))
         PASS;
-    else if (result->value->belong == NULL || result->value->belong->value == left->value || checkAttribution(left->value, result->value->belong->value))  // 检查result所属于的对象是否位左值的父亲
+    else if (result->value->belong != NULL && result->value->belong->value != left->value && checkAttribution(left->value, result->value->belong->value)) { // 检查result所属于的对象是否位左值的父亲(若是则需要重新设定belong)
+        result->value = copyLinkValue(result->value, inter);
         result->value->belong = left;
+    }
 
     return_:
     gc_freeTmpLink(&left->gc_status);
@@ -260,7 +262,7 @@ ResultType pointDel(Statement *name, FUNC_NT) {
     Statement *right = name->u.operation.right;
 
     setResultCore(result);
-    if (operationSafeInterStatement(CFUNC(name->u.operation.left, var_list, result, belong)))
+    if (optSafeInterStatement(CFUNC(name->u.operation.left, var_list, result, belong)))
         return result->type;
     GET_RESULT(left, result);  // 不关心左值和整体(st)权限
 
@@ -286,7 +288,7 @@ ResultType downDel(Statement *name, FUNC_NT) {
     Parameter *pt = name->u.slice_.index;
 
     setResultCore(result);
-    if (operationSafeInterStatement(CFUNC(name->u.slice_.element, var_list, result, belong)))
+    if (optSafeInterStatement(CFUNC(name->u.slice_.element, var_list, result, belong)))
         return result->type;
     GET_RESULT(iter, result);
 
@@ -334,7 +336,7 @@ ResultType assOperation(FUNC) {
         gc_freeTmpLink(&func->gc_status);
     }
     else{
-        if (operationSafeInterStatement(CFUNC(st->u.operation.right, var_list, result, belong)))
+        if (optSafeInterStatement(CFUNC(st->u.operation.right, var_list, result, belong)))
             return result->type;
         value = result->value;
 
@@ -436,7 +438,7 @@ ResultType downAss(Statement *name, LinkValue *value, FUNC_NT) {
     Parameter *pt = name->u.slice_.index;
 
     setResultCore(result);
-    if (operationSafeInterStatement(CFUNC(name->u.slice_.element, var_list, result, belong)))
+    if (optSafeInterStatement(CFUNC(name->u.slice_.element, var_list, result, belong)))
         return result->type;
     GET_RESULT(iter, result);
 
@@ -476,7 +478,7 @@ ResultType pointAss(Statement *name, LinkValue *value, FUNC_NT) {
     VarList *object = NULL;
 
     setResultCore(result);
-    if (operationSafeInterStatement(CFUNC(name->u.operation.left, var_list, result, belong)))
+    if (optSafeInterStatement(CFUNC(name->u.operation.left, var_list, result, belong)))
         return result->type;
     GET_RESULT(left, result);  // 不关心左值和整体(st)权限
 
@@ -549,7 +551,7 @@ ResultType getVar(FUNC, VarInfo var_info) {
     }
 
     GET_RESULT(val, result);
-    var = findFromVarList(name, int_times, get_var, CFUNC_CORE(var_list));
+    var = findFromVarList(name, int_times, read_var, CFUNC_CORE(var_list));
 
     if (var == NULL) {
         if (st->type == base_svar && !st->u.base_svar.is_var) {
@@ -640,7 +642,7 @@ ResultType getDict(FUNC) {
     }
 
     freeResult(result);
-    LinkValue *value = makeLinkValue(tmp_value, belong, inter);
+    LinkValue *value = makeLinkValue(tmp_value, belong, auto_aut, inter);
     setResultOperation(result, value);
     freeArgument(at, false);
 
@@ -672,12 +674,12 @@ ResultType setDefault(FUNC){
 }
 
 bool getLeftRightValue(Result *left, Result *right, FUNC){
-    if (operationSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)))
+    if (optSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)))
         return true;
     *left = *result;
     setResultCore(result);
 
-    if (operationSafeInterStatement(CFUNC(st->u.operation.right, var_list, result, belong)))
+    if (optSafeInterStatement(CFUNC(st->u.operation.right, var_list, result, belong)))
         return true;
     *right = *result;
     setResultCore(result);
@@ -704,7 +706,7 @@ ResultType operationCore2(FUNC, wchar_t *name) {
     LinkValue *left;
     setResultCore(result);
 
-    if (operationSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)))
+    if (optSafeInterStatement(CFUNC(st->u.operation.left, var_list, result, belong)))
         return result->type;
     GET_RESULTONLY(left, result);  // 不使用freeResult, 不需要多余的把result.value设置为none
     runOperationFromValue(left, NULL, name, st->line, st->code_file, CNEXT_NT);

+ 10 - 16
vmcore/src/value.c

@@ -4,7 +4,7 @@ Value *makeObject(Inter *inter, VarList *object, VarList *out_var, Inherit *inhe
     register Value **list_tmp = &inter->base;
     Value *last;
     Value *tmp;
-    tmp = memCalloc(1, sizeof(Value));
+    MACRO_CALLOC(tmp, 1, sizeof(Value));
     setGC(&tmp->gc_status);
     gc_addTmpLink(&tmp->gc_status);
     tmp->type = V_obj;
@@ -267,22 +267,23 @@ void freeValue(Value **value) {
     return_: return;
 }
 
-LinkValue *makeLinkValue(Value *value, LinkValue *belong, Inter *inter){  // TODO-szh 为LinkValue添加gc_tmpLink
+LinkValue *makeLinkValue(Value *value, LinkValue *belong, enum ValueAuthority aut, Inter *inter) {  // TODO-szh 为LinkValue添加gc_tmpLink
     LinkValue **list_tmp = &inter->link_base;
     LinkValue *last;
     LinkValue *tmp;
-    tmp = memCalloc(1, sizeof(Value));
+    MACRO_CALLOC(tmp, 1, sizeof(LinkValue));
     tmp->belong = belong;
     tmp->value = value;
     tmp->gc_next = NULL;
     setGC(&tmp->gc_status);
 
+    inter->data.run_gc ++;
     for (last = NULL; *list_tmp != NULL; list_tmp = &(*list_tmp)->gc_next)
         last = *list_tmp;
 
     *list_tmp = tmp;
     tmp->gc_last = last;
-    tmp->aut = auto_aut;
+    tmp->aut = aut;
     return tmp;
 }
 
@@ -298,15 +299,6 @@ void freeLinkValue(LinkValue **value) {
     return_: return;
 }
 
-LinkValue *copyLinkValue(LinkValue *value, Inter *inter) {
-    LinkValue *tmp = NULL;
-    if (value == NULL)
-        return NULL;
-    tmp = makeLinkValue(value->value, value->belong, inter);
-    tmp->aut = value->aut;
-    return tmp;
-}
-
 void setResultCore(Result *ru) {
     ru->type = R_not;
     ru->times = 0;
@@ -610,10 +602,12 @@ bool callDel(Value *object_value, Result *result, Inter *inter, VarList *var_lis
     LinkValue *_del_ = findStrVarOnly(inter->data.mag_func[M_DEL], false, CFUNC_CORE(object_value->object.var));
     setResultCore(result);
 
-    if (_del_ != NULL){
+    if (_del_ != NULL){  // TODO-szh 让__del__只运行一次
         gc_addTmpLink(&_del_->gc_status);
-        if (_del_->belong == NULL || _del_->belong->value == object_value || checkAttribution(object_value, _del_->belong->value))
-            _del_->belong = makeLinkValue(object_value, inter->base_belong, inter);
+        if (_del_->belong != NULL && _del_->belong->value != object_value && checkAttribution(object_value, _del_->belong->value)) {  // 与point运算道理相同
+            _del_ = copyLinkValue(_del_, inter);
+            _del_->belong = makeLinkValue(object_value, inter->base_belong, auto_aut, inter);
+        }
         callBackCore(_del_, NULL, LINEFILE, 0, CFUNC_NT(var_list, result, inter->base_belong));
         gc_freeTmpLink(&_del_->gc_status);
         return true;

+ 9 - 21
vmcore/src/var.c

@@ -4,14 +4,15 @@ Var *makeVar(wchar_t *name, LinkValue *value, LinkValue *name_, Inter *inter) {
     Var **list_tmp = &inter->base_var;
     Var *last;
     Var *tmp;
-    tmp = memCalloc(1, sizeof(Var));
+    MACRO_CALLOC(tmp, 1, sizeof(Var));
     setGC(&tmp->gc_status);
     tmp->name = memWidecpy(name);
-    tmp->value = copyLinkValue(value, inter);
-    tmp->name_ = copyLinkValue(name_, inter);
+    tmp->value = value;
+    tmp->name_ = name_;
     tmp->next = NULL;
     tmp->gc_next = NULL;
 
+    // var 不算入 inter 的 run_gc 中
     for (last = NULL; *list_tmp !=  NULL; list_tmp = &(*list_tmp)->gc_next)
         last = *list_tmp;
     *list_tmp = tmp;
@@ -36,12 +37,13 @@ HashTable *makeHashTable(Inter *inter) {
     register HashTable **list_tmp = &inter->hash_base;
     HashTable *last;
     HashTable *tmp;
-    tmp = memCalloc(1, sizeof(Value));
-    tmp->hashtable = (Var **)calloc(MAX_SIZE, sizeof(Var *));
+    MACRO_CALLOC(tmp, 1, sizeof(HashTable));
+    MACRO_CALLOC(tmp->hashtable, MAX_SIZE, sizeof(Var *));
     setGC(&tmp->gc_status);
     gc_addTmpLink(&tmp->gc_status);
     tmp->gc_next = NULL;
 
+    // hashTable 不算入 inter 的 run_gc 中
     for (last = NULL; *list_tmp != NULL; list_tmp = &(*list_tmp)->gc_next)
         last = *list_tmp;
     *list_tmp = tmp;
@@ -144,21 +146,7 @@ static void addVarCore(Var **base, wchar_t *name, LinkValue *value, LinkValue *n
             *base = makeVar(name, value, name_, inter);
             break;
         } else if (eqWide((*base)->name, name)) {
-            enum ValueAuthority aut = (*base)->value->aut;
-            (*base)->value = copyLinkValue(value, inter);
-            switch (aut) {
-                default:
-                case public_aut:
-                case auto_aut:
-                    break;
-                case protect_aut:
-                    if (value->aut != private_aut)
-                        (*base)->value->aut = protect_aut;
-                    break;
-                case private_aut:
-                    (*base)->value->aut = private_aut;
-                    break;
-            }
+            (*base)->value = value;
             break;
         }
     }
@@ -190,7 +178,7 @@ LinkValue *findVar(wchar_t *name, VarOperation operating, Inter *inter, HashTabl
             goto return_;
         }
     }
-    return_: return operating == get_var ? copyLinkValue(tmp, inter) : tmp;
+    return_: return tmp;
 }
 
 /**