Browse Source

fix args_foreach handler

add PikaGC class

add gc.onMarkObj

add GC DUMP

support gcdump()

improve gcdump
pikastech 3 years ago
parent
commit
ca65efd1fa

+ 4 - 0
package/PikaStdLib/PikaStdLib.pyi

@@ -134,6 +134,10 @@ class SysObj:
     @PIKA_C_MACRO_IF("!PIKA_NANO_ENABLE")
     def clear(): ...
 
+    @staticmethod
+    @PIKA_C_MACRO_IF("PIKA_GC_MARK_SWEEP_ENABLE")
+    def gcdump(): ...
+
 
 @PIKA_C_MACRO_IF("0")
 class RangeObj:

+ 6 - 2
package/PikaStdLib/PikaStdLib_SysObj.c

@@ -531,8 +531,8 @@ PikaObj* PikaStdLib_SysObj_open(PikaObj* self, char* path, char* mode) {
 }
 
 /* __dir_each */
-int32_t __dir_each(Arg* argEach, Args* context) {
-    PikaObj* list = args_getPtr(context, "list");
+int32_t __dir_each(Arg* argEach, void* context) {
+    PikaObj* list = args_getPtr((Args*)context, "list");
     if (argType_isCallable(arg_getType(argEach))) {
         char name_buff[PIKA_LINE_BUFF_SIZE] = {0};
         char* method_name =
@@ -670,3 +670,7 @@ void PikaStdLib_SysObj_reboot(PikaObj* self) {
 void PikaStdLib_SysObj_clear(PikaObj* self) {
     pika_platform_clear();
 }
+
+void PikaStdLib_SysObj_gcdump(PikaObj *self){
+    pikaGC_markDump();
+}

+ 1 - 1
port/linux/.vscode/launch.json

@@ -11,7 +11,7 @@
             "program": "${workspaceFolder}/build/test/pikascript_test",
             // "program": "${workspaceFolder}/build/boot/demo06-pikamain/pikascript_demo06-pikamain",
             "args": [
-                "--gtest_filter=pikaui.*"
+                // "--gtest_filter=pikaui.*"
                 // "--gtest_filter=parser.for_in_split"
             ],
             "stopAtEntry": false,

+ 4 - 0
port/linux/package/pikascript/PikaStdLib.pyi

@@ -134,6 +134,10 @@ class SysObj:
     @PIKA_C_MACRO_IF("!PIKA_NANO_ENABLE")
     def clear(): ...
 
+    @staticmethod
+    @PIKA_C_MACRO_IF("PIKA_GC_MARK_SWEEP_ENABLE")
+    def gcdump(): ...
+
 
 @PIKA_C_MACRO_IF("0")
 class RangeObj:

+ 6 - 2
port/linux/package/pikascript/pikascript-lib/PikaStdLib/PikaStdLib_SysObj.c

@@ -531,8 +531,8 @@ PikaObj* PikaStdLib_SysObj_open(PikaObj* self, char* path, char* mode) {
 }
 
 /* __dir_each */
-int32_t __dir_each(Arg* argEach, Args* context) {
-    PikaObj* list = args_getPtr(context, "list");
+int32_t __dir_each(Arg* argEach, void* context) {
+    PikaObj* list = args_getPtr((Args*)context, "list");
     if (argType_isCallable(arg_getType(argEach))) {
         char name_buff[PIKA_LINE_BUFF_SIZE] = {0};
         char* method_name =
@@ -670,3 +670,7 @@ void PikaStdLib_SysObj_reboot(PikaObj* self) {
 void PikaStdLib_SysObj_clear(PikaObj* self) {
     pika_platform_clear();
 }
+
+void PikaStdLib_SysObj_gcdump(PikaObj *self){
+    pikaGC_markDump();
+}

+ 35 - 35
src/PikaCompiler.c

@@ -300,7 +300,7 @@ int LibObj_staticLinkFile(LibObj* self, char* input_file_name) {
     return 0;
 }
 
-static int32_t __foreach_handler_listModules(Arg* argEach, Args* context) {
+static int32_t __foreach_handler_listModules(Arg* argEach, void* context) {
     if (arg_isObject(argEach)) {
         PikaObj* module_obj = arg_getPtr(argEach);
         pika_platform_printf("%s\r\n", obj_getStr(module_obj, "name"));
@@ -312,8 +312,8 @@ void LibObj_listModules(LibObj* self) {
     args_foreach(self->list, __foreach_handler_listModules, NULL);
 }
 
-static int32_t __foreach_handler_libWriteBytecode(Arg* argEach, Args* context) {
-    FILE* out_file = args_getPtr(context, "out_file");
+static int32_t __foreach_handler_libWriteBytecode(Arg* argEach, void* context) {
+    FILE* out_file = args_getPtr((Args*)context, "out_file");
     if (arg_isObject(argEach)) {
         PikaObj* module_obj = arg_getPtr(argEach);
         char* bytecode = obj_getPtr(module_obj, "bytecode");
@@ -327,8 +327,9 @@ static int32_t __foreach_handler_libWriteBytecode(Arg* argEach, Args* context) {
     return 0;
 }
 
-static int32_t __foreach_handler_libWriteIndex(Arg* argEach, Args* context) {
-    FILE* out_file = args_getPtr(context, "out_file");
+static int32_t __foreach_handler_libWriteIndex(Arg* argEach, void* context) {
+    Args* args = context;
+    FILE* out_file = args_getPtr(args, "out_file");
     Args buffs = {0};
     if (arg_isObject(argEach)) {
         PikaObj* module_obj = arg_getPtr(argEach);
@@ -348,21 +349,22 @@ static int32_t __foreach_handler_libWriteIndex(Arg* argEach, Args* context) {
     return 0;
 }
 
-static int32_t __foreach_handler_libSumSize(Arg* argEach, Args* context) {
+static int32_t __foreach_handler_libSumSize(Arg* argEach, void* context) {
+    Args* args = context;
     if (arg_isObject(argEach)) {
         PikaObj* module_obj = arg_getPtr(argEach);
         uint32_t bytecode_size = obj_getBytesSize(module_obj, "buff");
         bytecode_size = aline_by(bytecode_size, sizeof(uint32_t));
-        args_setInt(context, "sum_size",
-                    args_getInt(context, "sum_size") + bytecode_size);
+        args_setInt(args, "sum_size",
+                    args_getInt(args, "sum_size") + bytecode_size);
     }
     return 0;
 }
 
-static int32_t __foreach_handler_getModuleNum(Arg* argEach, Args* context) {
+static int32_t __foreach_handler_getModuleNum(Arg* argEach, void* context) {
+    Args* args = (Args*)context;
     if (arg_isObject(argEach)) {
-        args_setInt(context, "module_num",
-                    args_getInt(context, "module_num") + 1);
+        args_setInt(args, "module_num", args_getInt(args, "module_num") + 1);
     }
     return 0;
 }
@@ -496,15 +498,15 @@ PIKA_RES _loadModuleDataWithName(uint8_t* library_bytes,
 /**
  * @brief 打开 .pack 文件,并返回这个pack 文件的library_bytes
  *
- * @param pikafs_FILE** fp pikafs_FILE 二级文件指针,提供了文件加载内存中的地址以及大小等信息
+ * @param pikafs_FILE** fp pikafs_FILE
+ * 二级文件指针,提供了文件加载内存中的地址以及大小等信息
  * @param Arg** f_arg
  * @param char* pack_name pack 文件的名字
  * @return  PIKA_RES_OK when success, otherwise failed;
  * @note  if failed *fp if freed
- * 
+ *
  */
 PIKA_RES _getPack_libraryBytes(pikafs_FILE** fp, Arg** f_arg, char* pack_name) {
-
     if (NULL == pack_name) {
         return PIKA_RES_ERR_INVALID_PTR;
     }
@@ -518,7 +520,8 @@ PIKA_RES _getPack_libraryBytes(pikafs_FILE** fp, Arg** f_arg, char* pack_name) {
 
     *f_arg = arg_loadFile(NULL, pack_name);
     if (NULL == *f_arg) {
-        pika_platform_printf("Error: Could not load file \'%s\'\r\n", pack_name);
+        pika_platform_printf("Error: Could not load file \'%s\'\r\n",
+                             pack_name);
         pikaFree(*fp, sizeof(pikafs_FILE));
         // fp == NULL;
         return PIKA_RES_ERR_IO_ERROR;
@@ -543,7 +546,7 @@ int LibObj_loadLibrary(LibObj* self, uint8_t* library_bytes) {
     return PIKA_RES_OK;
 }
 
-int32_t __foreach_handler_printModule(Arg* argEach, Args* context) {
+int32_t __foreach_handler_printModule(Arg* argEach, void* context) {
     if (arg_isObject(argEach)) {
         PikaObj* module_obj = arg_getPtr(argEach);
         char* module_name = obj_getStr(module_obj, "name");
@@ -578,13 +581,12 @@ int LibObj_loadLibraryFile(LibObj* self, char* lib_file_name) {
 
 /**
  * @brief unpack *.pack file to Specified path
- * 
+ *
  * @param pack_name  the name of *.pack file
  * @param out_path   output path
- * @return           
+ * @return
  */
 PIKA_RES LibObj_unpackFileToPath(char* pack_name, char* out_path) {
-
     PIKA_RES stat = PIKA_RES_OK;
     Arg* file_arg = NULL;
     uint8_t* library_bytes = NULL;
@@ -593,8 +595,7 @@ PIKA_RES LibObj_unpackFileToPath(char* pack_name, char* out_path) {
     stat = _getPack_libraryBytes(&fptr, &file_arg, pack_name);
     if (PIKA_RES_OK == stat) {
         library_bytes = arg_getBytes(file_arg);
-    }
-    else {
+    } else {
         return stat;
     }
 
@@ -603,7 +604,7 @@ PIKA_RES LibObj_unpackFileToPath(char* pack_name, char* out_path) {
         return (PIKA_RES)module_num;
     }
 
-    Args buffs = { 0 };
+    Args buffs = {0};
     char* output_file_path = NULL;
     FILE* new_fp = NULL;
 
@@ -612,15 +613,15 @@ PIKA_RES LibObj_unpackFileToPath(char* pack_name, char* out_path) {
         uint8_t* addr = NULL;
         size_t size = 0;
         _loadModuleDataWithIndex(library_bytes, module_num, i, &name, &addr,
-            &size);
+                                 &size);
         output_file_path = strsPathJoin(&buffs, out_path, name);
         new_fp = pika_platform_fopen(output_file_path, "wb+");
         if (NULL != new_fp) {
             pika_platform_fwrite(addr, size, 1, new_fp);
             pika_platform_fclose(new_fp);
-            pika_platform_printf("extract %s to %s\r\n", name, output_file_path);
-        }
-        else {
+            pika_platform_printf("extract %s to %s\r\n", name,
+                                 output_file_path);
+        } else {
             pika_platform_printf("can't open %s\r\n", output_file_path);
             break;
         }
@@ -872,7 +873,7 @@ exit:
     return res;
 }
 
-int32_t __foreach_handler_printStates(Arg* argEach, Args* context) {
+int32_t __foreach_handler_printStates(Arg* argEach, void* context) {
     if (arg_isObject(argEach)) {
         PikaObj* module_obj = arg_getPtr(argEach);
         pika_platform_printf("%s: %s\r\n", obj_getStr(module_obj, "name"),
@@ -885,17 +886,17 @@ void pikaMaker_printStates(PikaMaker* self) {
     args_foreach(self->list, __foreach_handler_printStates, NULL);
 }
 
-int32_t __foreach_handler_getFirstNocompiled(Arg* argEach, Args* context) {
+int32_t __foreach_handler_getFirstNocompiled(Arg* argEach, void* context) {
     if (arg_isObject(argEach)) {
         PikaObj* module_obj = arg_getPtr(argEach);
         char* state = obj_getStr(module_obj, "state");
-        if (args_isArgExist(context, "res")) {
+        if (args_isArgExist((Args*)context, "res")) {
             /* already get method */
             return 0;
         }
         if (strEqu("nocompiled", state)) {
             /* push module */
-            args_setStr(context, "res", obj_getStr(module_obj, "name"));
+            args_setStr((Args*)context, "res", obj_getStr(module_obj, "name"));
             return 0;
         }
     }
@@ -947,11 +948,11 @@ PIKA_RES pikaMaker_compileModuleWithDepends(PikaMaker* self,
     return PIKA_RES_OK;
 }
 
-int32_t __foreach_handler_linkCompiledModules(Arg* argEach, Args* context) {
+int32_t __foreach_handler_linkCompiledModules(Arg* argEach, void* context) {
     Args buffs = {0};
     if (arg_isObject(argEach)) {
-        LibObj* lib = args_getPtr(context, "@lib");
-        PikaMaker* maker = args_getPtr(context, "__maker");
+        LibObj* lib = args_getPtr((Args*)context, "@lib");
+        PikaMaker* maker = args_getPtr((Args*)context, "__maker");
         PikaObj* module_obj = arg_getPtr(argEach);
         char* module_name = obj_getStr(module_obj, "name");
         char* state = obj_getStr(module_obj, "state");
@@ -1057,8 +1058,7 @@ pikafs_FILE* pikafs_fopen_pack(char* pack_name, char* file_name) {
     stat = _getPack_libraryBytes(&f, &file_arg, pack_name);
     if (PIKA_RES_OK == stat) {
         library_bytes = arg_getBytes(file_arg);
-    }
-    else {
+    } else {
         return NULL;
     }
 

+ 110 - 46
src/PikaObj.c

@@ -57,6 +57,9 @@ PikaObj* New_PikaStdData_List(Args* args);
 PikaObj* New_PikaStdData_Tuple(Args* args);
 void _mem_cache_deinit(void);
 void _VMEvent_deinit(void);
+void pikaGC_markObj(PikaGC* gc, PikaObj* self);
+void _pikaGC_mark(PikaGC* gc);
+void obj_dump(PikaObj* self);
 
 static enum shellCTRL __obj_shellLineHandler_REPL(PikaObj* self,
                                                   char* input_line,
@@ -134,7 +137,7 @@ static int32_t obj_deinit_no_del(PikaObj* self) {
 #endif
     extern volatile PikaObj* __pikaMain;
     /* remove self from gc chain */
-    pikaGC_remove(self);
+    obj_removeGcChain(self);
     /* free the pointer */
     pikaFree(self, sizeof(PikaObj));
     if (self == (PikaObj*)__pikaMain) {
@@ -144,7 +147,7 @@ static int32_t obj_deinit_no_del(PikaObj* self) {
 }
 
 int obj_GC(PikaObj* self) {
-    if (!pikaGC_checkAlive(self)) {
+    if (!obj_checkAlive(self)) {
         return 0;
     }
     obj_refcntDec(self);
@@ -287,7 +290,7 @@ PIKA_BOOL obj_getBool(PikaObj* self, char* argPath) {
 }
 
 Arg* obj_getArg(PikaObj* self, char* argPath) {
-    pika_assert(pikaGC_checkAlive(self));
+    pika_assert(obj_checkAlive(self));
     PIKA_BOOL is_temp = PIKA_FALSE;
     PikaObj* obj = obj_getHostObjWithIsTemp(self, argPath, &is_temp);
     if (NULL == obj) {
@@ -335,11 +338,30 @@ size_t obj_loadBytes(PikaObj* self, char* argPath, uint8_t* out_buff) {
     return size_mem;
 }
 
+void obj_setName(PikaObj* self, char* name) {
+#if !PIKA_KERNAL_DEBUG_ENABLE
+    return;
+#else
+    if (strEqu(name, "self")) {
+        return;
+    }
+    if (NULL != self->aName) {
+        if (!strstr(self->name, name)) {
+            self->aName = arg_strAppend(self->aName, "|");
+            self->aName = arg_strAppend(self->aName, name);
+        }
+    } else {
+        self->aName = arg_newStr(name);
+    }
+    self->name = arg_getStr(self->aName);
+#endif
+}
+
 static PIKA_RES _obj_setArg(PikaObj* self,
                             char* argPath,
                             Arg* arg,
                             uint8_t is_copy) {
-    pika_assert(pikaGC_checkAlive(self));
+    pika_assert(obj_checkAlive(self));
     /* setArg would copy arg */
     PikaObj* host = obj_getHostObj(self, argPath);
     PikaObj* oNew = NULL;
@@ -359,24 +381,20 @@ static PIKA_RES _obj_setArg(PikaObj* self,
     if (arg_isObject(aNew)) {
         oNew = arg_getPtr(aNew);
         bNew = PIKA_TRUE;
-        pika_assert(pikaGC_checkAlive(oNew));
+        pika_assert(obj_checkAlive(oNew));
 #if PIKA_KERNAL_DEBUG_ENABLE
         if (host != oNew) {
             /* skip self ref */
             oNew->parent = host;
         }
-        if (NULL != oNew->aName) {
-            arg_deinit(oNew->aName);
-        }
-        oNew->aName = arg_newStr(sArgName);
-        oNew->name = arg_getStr(oNew->aName);
 #endif
+        obj_setName(oNew, sArgName);
     }
     args_setArg(host->list, aNew);
     /* enable mark sweep to collect this object */
     if (bNew) {
         /* only enable mark sweep after setArg */
-        pikaGC_enable(oNew);
+        obj_enableGC(oNew);
     }
     return PIKA_RES_OK;
 }
@@ -598,6 +616,7 @@ PikaObj* newRootObj(char* name, NewFun newObjFun) {
         return NULL;
     }
     __pikaMain = newObj;
+    obj_setName(newObj, name);
     g_PikaObjState.inRootObj = PIKA_FALSE;
     return newObj;
 }
@@ -624,16 +643,17 @@ static PikaObj* _obj_initMetaObj(PikaObj* obj, char* name) {
     NewFun constructor = (NewFun)getNewClassObjFunByName(obj, name);
     Args buffs = {0};
     PikaObj* thisClass;
-    PikaObj* new_obj;
+    PikaObj* oNew;
     if (NULL == constructor) {
         /* no such object */
         res = NULL;
         goto exit;
     }
     thisClass = obj_newObjFromConstructor(obj, name, constructor);
-    new_obj = removeMethodInfo(thisClass);
-    obj_runNativeMethod(new_obj, "__init__", NULL);
-    args_setPtrWithType(obj->list, name, ARG_TYPE_OBJECT, new_obj);
+    oNew = removeMethodInfo(thisClass);
+    obj_setName(oNew, name);
+    obj_runNativeMethod(oNew, "__init__", NULL);
+    args_setPtrWithType(obj->list, name, ARG_TYPE_OBJECT, oNew);
     res = obj_getPtr(obj, name);
     // pikaGC_enable(res);
     goto exit;
@@ -735,7 +755,7 @@ static PikaObj* _obj_getObjWithKeepDeepth(PikaObj* self,
     goto exit;
 exit:
     if (NULL != obj) {
-        pika_assert(pikaGC_checkAlive(obj));
+        pika_assert(obj_checkAlive(obj));
     }
     return obj;
 }
@@ -1736,7 +1756,7 @@ PikaObj* pikaGC_getLast(PikaObj* self) {
     return NULL;
 }
 
-void pikaGC_cleanMark(void) {
+void pikaGC_clean(PikaGC* gc) {
     PikaObj* obj = g_PikaObjState.gcChain;
     while (NULL != obj) {
         obj_clearFlag(obj, OBJ_FLAG_GC_MARKED);
@@ -1774,7 +1794,8 @@ uint32_t pikaGC_printFreeList(void) {
     while (NULL != obj) {
         if (!obj_getFlag(obj, OBJ_FLAG_GC_MARKED)) {
             count++;
-            pika_platform_printf("gc free: %p\r\n", obj);
+            pika_platform_printf("gc free: ");
+            obj_dump(obj);
         }
         obj = obj->gcNext;
     }
@@ -1782,10 +1803,18 @@ uint32_t pikaGC_printFreeList(void) {
     return count;
 }
 
-uint32_t pikaGC_FreeOnce(void) {
-    pikaGC_markRoot();
-    // pika_platform_printf("-----\r\n");
-    // pikaGC_printCanFree();
+void obj_dump(PikaObj* self) {
+#if !PIKA_KERNAL_DEBUG_ENABLE
+    return;
+#else
+    pika_platform_printf("[%s]", self->name);
+    pika_platform_printf("\t\t@%p", self);
+    pika_platform_printf("\r\n");
+#endif
+}
+
+uint32_t pikaGC_markSweepOnce(PikaGC* gc) {
+    _pikaGC_mark(gc);
     uint32_t count = 0;
     PikaObj* freeList[16] = {0};
     PikaObj* obj = g_PikaObjState.gcChain;
@@ -1797,6 +1826,7 @@ uint32_t pikaGC_FreeOnce(void) {
         obj = obj->gcNext;
     }
     if (count > 0) {
+        pikaGC_markDump();
         pikaGC_printFreeList();
         for (uint32_t i = 0; i < count; i++) {
             obj_GC(freeList[i]);
@@ -1805,59 +1835,91 @@ uint32_t pikaGC_FreeOnce(void) {
     return count;
 }
 
-int32_t pikaGC_markHandler(Arg* argEach, Args* context) {
+int32_t _pikaGC_markHandler(Arg* argEach, void* context) {
+    PikaGC* gc = (PikaGC*)context;
     if (arg_isObject(argEach)) {
         PikaObj* obj = (PikaObj*)arg_getPtr(argEach);
 #if PIKA_KERNAL_DEBUG_ENABLE
-        obj->gcRoot = (void*)context;
+        obj->gcRoot = (void*)gc->oThis;
 #endif
-        pikaGC_mark(obj);
+        pikaGC_markObj(gc, obj);
     }
     return 0;
 }
 
-void pikaGC_mark(PikaObj* self) {
+void pikaGC_markObj(PikaGC* gc, PikaObj* self) {
+    gc->oThis = self;
+    gc->markDeepth++;
     if (NULL == self) {
-        return;
+        goto __exit;
     }
     if (obj_getFlag(self, OBJ_FLAG_GC_MARKED)) {
-        return;
+        goto __exit;
     }
     obj_setFlag(self, OBJ_FLAG_GC_MARKED);
-    args_foreach(self->list, pikaGC_markHandler, (void*)self);
+    if (NULL != gc->onMarkObj) {
+        gc->onMarkObj(gc);
+    }
+    args_foreach(self->list, _pikaGC_markHandler, gc);
     if (self->constructor == New_PikaStdData_Dict) {
         PikaDict* dict = obj_getPtr(self, "dict");
         if (NULL == dict) {
-            return;
+            goto __exit;
         }
-        args_foreach(&dict->super, pikaGC_markHandler, (void*)self);
-        return;
+        args_foreach(&dict->super, _pikaGC_markHandler, (void*)gc);
+        goto __exit;
     }
     if (self->constructor == New_PikaStdData_List ||
         self->constructor == New_PikaStdData_Tuple) {
         PikaList* list = obj_getPtr(self, "list");
         if (NULL == list) {
-            return;
+            goto __exit;
         }
-        args_foreach(&list->super, pikaGC_markHandler, (void*)self);
-        return;
+        args_foreach(&list->super, _pikaGC_markHandler, (void*)gc);
+        goto __exit;
     }
+__exit:
+    gc->markDeepth--;
+    return;
 }
 
-void pikaGC_markRoot() {
-    pikaGC_cleanMark();
+void _pikaGC_mark(PikaGC* gc) {
+    pikaGC_clean(gc);
     PikaObj* root = g_PikaObjState.gcChain;
     while (NULL != root) {
         if (obj_getFlag(root, OBJ_FLAG_GC_ROOT)) {
-            pikaGC_mark(root);
+            pikaGC_markObj(gc, root);
         }
         root = root->gcNext;
     }
 }
 
+void pikaGC_mark(void) {
+    PikaGC gc = {0};
+    _pikaGC_mark(&gc);
+}
+
+int _pikaGC_markDumpHandler(PikaGC* gc) {
+    for (uint32_t i = 0; i < gc->markDeepth - 1; i++) {
+        pika_platform_printf("  ");
+    }
+    if (gc->markDeepth != 1) {
+        pika_platform_printf("- ");
+    }
+    obj_dump(gc->oThis);
+    return 0;
+}
+
+void pikaGC_markDump(void) {
+    PikaGC gc = {0};
+    pika_platform_printf("========= PIKA GC DUMP =========\r\n");
+    gc.onMarkObj = _pikaGC_markDumpHandler;
+    _pikaGC_mark(&gc);
+}
+
 #endif
 
-PIKA_BOOL pikaGC_checkAlive(PikaObj* self) {
+PIKA_BOOL obj_checkAlive(PikaObj* self) {
 #if !PIKA_GC_MARK_SWEEP_ENABLE
     return PIKA_TRUE;
 #else
@@ -1888,12 +1950,13 @@ uint32_t pikaGC_markSweep(void) {
 #if !PIKA_GC_MARK_SWEEP_ENABLE
     return 0;
 #else
+    PikaGC gc = {0};
     uint32_t count = 0;
     if (pikaGC_islock()) {
         return 0;
     }
     pikaGC_lock();
-    while (pikaGC_FreeOnce() != 0) {
+    while (pikaGC_markSweepOnce(&gc) != 0) {
         count++;
     };
     /* update gc state */
@@ -1933,7 +1996,7 @@ void pikaGC_append(PikaObj* self) {
 #endif
 }
 
-void pikaGC_remove(PikaObj* self) {
+void obj_removeGcChain(PikaObj* self) {
 #if !PIKA_GC_MARK_SWEEP_ENABLE
     return;
 #else
@@ -1948,7 +2011,7 @@ void pikaGC_remove(PikaObj* self) {
 #endif
 }
 
-void pikaGC_enable(PikaObj* self) {
+void obj_enableGC(PikaObj* self) {
 #if !PIKA_GC_MARK_SWEEP_ENABLE
     return;
 #else
@@ -1993,7 +2056,7 @@ PikaObj* New_PikaObj(void) {
 #endif
 #if PIKA_KERNAL_DEBUG_ENABLE
     self->aName = NULL;
-    self->name = NULL;
+    self->name = "PikaObj";
     self->parent = NULL;
     self->isAlive = PIKA_TRUE;
 #endif
@@ -2019,6 +2082,7 @@ Arg* arg_setRef(Arg* self, char* name, PikaObj* obj) {
 int32_t obj_newDirectObj(PikaObj* self, char* objName, NewFun newFunPtr) {
     Arg* aNewObj = arg_newDirectObj(newFunPtr);
     aNewObj = arg_setName(aNewObj, objName);
+    obj_setName(arg_getPtr(aNewObj), objName);
     arg_setType(aNewObj, ARG_TYPE_OBJECT);
     // pikaGC_enable(arg_getPtr(aNewObj));
     args_setArg(self->list, aNewObj);
@@ -2027,9 +2091,9 @@ int32_t obj_newDirectObj(PikaObj* self, char* objName, NewFun newFunPtr) {
 
 int32_t obj_newMetaObj(PikaObj* self, char* objName, NewFun newFunPtr) {
     /* add meta Obj, no inited */
-    Arg* new_obj = arg_newMetaObj(newFunPtr);
-    new_obj = arg_setName(new_obj, objName);
-    args_setArg(self->list, new_obj);
+    Arg* aMetaObj = arg_newMetaObj(newFunPtr);
+    aMetaObj = arg_setName(aMetaObj, objName);
+    args_setArg(self->list, aMetaObj);
     return 0;
 }
 

+ 42 - 36
src/PikaObj.h

@@ -75,29 +75,34 @@ struct NativeProperty {
     uint32_t methodGroupCount;
 };
 
-/* clang-format off */
 typedef struct PikaObj PikaObj;
 struct PikaObj {
     Args* list;
     void* constructor;
-    #if PIKA_GC_MARK_SWEEP_ENABLE
-        PikaObj* gcNext;
-        #if PIKA_KERNAL_DEBUG_ENABLE
-            PikaObj* gcRoot;
-        #endif
-    #endif
-    #if PIKA_KERNAL_DEBUG_ENABLE
-        char* name;
-        Arg* aName;
-        PikaObj* parent;
-        PIKA_BOOL isAlive;
-        PIKA_BOOL isGCRoot;
-    #endif
+#if PIKA_GC_MARK_SWEEP_ENABLE
+    PikaObj* gcNext;
+#endif
+#if PIKA_KERNAL_DEBUG_ENABLE
+    char* name;
+    Arg* aName;
+    PikaObj* parent;
+    PIKA_BOOL isAlive;
+    PIKA_BOOL isGCRoot;
+#endif
+#if PIKA_GC_MARK_SWEEP_ENABLE && PIKA_KERNAL_DEBUG_ENABLE
+    PikaObj* gcRoot;
+#endif
     uint8_t refcnt;
     uint8_t flag;
 };
 
-/* clang-format on */
+typedef struct PikaGC PikaGC;
+typedef int (*pikaGC_hook)(PikaGC* gc);
+struct PikaGC {
+    uint32_t markDeepth;
+    pikaGC_hook onMarkObj;
+    PikaObj* oThis;
+};
 
 typedef struct RangeData RangeData;
 struct RangeData {
@@ -625,34 +630,35 @@ void obj_printModules(PikaObj* self);
     } while (0)
 #endif
 
-#define pika_assert_arg_alive(__arg)                                 \
-    do {                                                             \
-        if (NULL != (__arg)) {                                       \
-            if (arg_isObject((__arg))) {                             \
-                pika_assert(pikaGC_checkAlive(arg_getPtr((__arg)))); \
-            }                                                        \
-        }                                                            \
+#define pika_assert_arg_alive(__arg)                              \
+    do {                                                          \
+        if (NULL != (__arg)) {                                    \
+            if (arg_isObject((__arg))) {                          \
+                pika_assert(obj_checkAlive(arg_getPtr((__arg)))); \
+            }                                                     \
+        }                                                         \
     } while (0)
 
-#define pika_assert_obj_alive(__obj)             \
-    do {                                         \
-        pika_assert(pikaGC_checkAlive((__obj))); \
+#define pika_assert_obj_alive(__obj)          \
+    do {                                      \
+        pika_assert(obj_checkAlive((__obj))); \
     } while (0)
 
-void pikaGC_append(PikaObj* self);
-uint32_t pikaGC_count(void);
-void pikaGC_remove(PikaObj* self);
-void pikaGC_mark(PikaObj* self);
-void pikaGC_markRoot(void);
-uint32_t pikaGC_countMarked(void);
-uint32_t pikaGC_printFreeList(void);
-uint32_t pikaGC_markSweep(void);
-PIKA_BOOL pikaGC_checkAlive(PikaObj* self);
-void pikaGC_enable(PikaObj* self);
-void pikaGC_try(void);
+void obj_appendGcChain(PikaObj* self);
+void obj_removeGcChain(PikaObj* self);
+void obj_enableGC(PikaObj* self);
+PIKA_BOOL obj_checkAlive(PikaObj* self);
+void obj_setName(PikaObj* self, char* name);
+
+void pikaGC_mark(void);
+void pikaGC_markDump(void);
 void pikaGC_lock(void);
 void pikaGC_unlock(void);
 PIKA_BOOL pikaGC_islock(void);
+uint32_t pikaGC_count(void);
+uint32_t pikaGC_countMarked(void);
+uint32_t pikaGC_markSweep(void);
+uint32_t pikaGC_printFreeList(void);
 
 int pika_GIL_EXIT(void);
 int pika_GIL_ENTER(void);

+ 2 - 1
src/PikaVM.c

@@ -1780,7 +1780,7 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self,
         goto exit;
     }
 
-    pika_assert(pikaGC_checkAlive(oMethodHost));
+    pika_assert(obj_checkAlive(oMethodHost));
 
 #if !PIKA_NANO_ENABLE
     if (!bSkipInit && vm->in_super &&
@@ -1864,6 +1864,7 @@ static Arg* VM_instruction_handler_RUN(PikaObj* self,
         arg_setType(aReturn, ARG_TYPE_OBJECT);
         /* init object */
         PikaObj* oNew = arg_getPtr(aReturn);
+        obj_setName(oNew, sRunPath);
         Arg* aMethod = obj_getMethodArg_noalloc(oNew, "__init__", &arg_reg1);
         oSublocalsInit = New_Locals(NULL);
         Arg* aReturnInit = NULL;

+ 6 - 0
src/TinyObj.c

@@ -34,11 +34,17 @@ const NativeProperty TinyObjNativeProp = {.super = NULL,
 PikaObj* New_TinyObj(Args* args) {
     PikaObj* self = New_PikaObj();
     self->constructor = New_TinyObj;
+#if PIKA_KERNAL_DEBUG_ENABLE
+    self->name = "TinyObj";
+#endif
     return self;
 }
 
 PikaObj* New_Locals(Args* args) {
     PikaObj* self = New_PikaObj();
     self->constructor = New_Locals;
+#if PIKA_KERNAL_DEBUG_ENABLE
+    self->name = "Locals";
+#endif
     return self;
 }

+ 2 - 2
src/dataArgs.c

@@ -441,8 +441,8 @@ Arg* args_getArgByIndex(Args* self, int index) {
 }
 
 PIKA_RES args_foreach(Args* self,
-                      int32_t (*eachHandle)(Arg* argEach, Args* context),
-                      Args* context) {
+                      int32_t (*eachHandle)(Arg* argEach, void* context),
+                      void* context) {
     if (NULL == self->firstNode) {
         return PIKA_RES_OK;
     }

+ 2 - 2
src/dataArgs.h

@@ -107,8 +107,8 @@ PIKA_RES args_setPtrWithType(Args* self,
                              ArgType type,
                              void* objPtr);
 PIKA_RES args_foreach(Args* self,
-                      int32_t (*eachHandle)(Arg* argEach, Args* context),
-                      Args* context);
+                      int32_t (*eachHandle)(Arg* argEach, void* context),
+                      void* context);
 
 char* args_getBuff(Args* self, int32_t size);
 PIKA_RES args_pushArg(Args* self, Arg* arg);

+ 1 - 1
src/dataStack.c

@@ -168,7 +168,7 @@ static int32_t _stack_pushArg(Stack* stack, Arg* arg, PIKA_BOOL is_alloc) {
 int32_t stack_pushArg(Stack* stack, Arg* arg) {
     pika_assert(arg != NULL);
     if (arg_isObject(arg)) {
-        pika_assert(pikaGC_checkAlive(arg_getPtr(arg)));
+        pika_assert(obj_checkAlive(arg_getPtr(arg)));
     }
     if (arg_isSerialized(arg)) {
         return _stack_pushArg(stack, arg, PIKA_TRUE);

+ 12 - 1
test/gc-test.cpp

@@ -130,7 +130,7 @@ TEST(gc, heap_failed1) {
 #if PIKA_GC_MARK_SWEEP_ENABLE
     int cnt = pikaGC_count();
     EXPECT_EQ(cnt != 0, 1);
-    pikaGC_markRoot();
+    pikaGC_markDump();
     int cnt_marked = pikaGC_countMarked();
     EXPECT_EQ(cnt, cnt_marked);
     /* deinit */
@@ -165,6 +165,17 @@ TEST(gc, circle2) {
     obj_deinit(pikaMain);
     EXPECT_EQ(pikaMemNow(), 0);
 }
+
+TEST(gc, tree1) {
+    /* init */
+    PikaObj* pikaMain = newRootObj("pikaMain", New_PikaMain);
+    /* run */
+    pikaVM_runSingleFile(pikaMain, "test/python/gc/gc_tree1.py");
+    /* assert */
+    /* deinit */
+    obj_deinit(pikaMain);
+    EXPECT_EQ(pikaMemNow(), 0);
+}
 #endif
 
 TEST_END

+ 1 - 2
test/pikaui-test.cpp

@@ -1,6 +1,6 @@
 #include "test_common.h"
 TEST_START
-#if !PIKA_NANO_ENABLE && 0
+#if !PIKA_NANO_ENABLE && 1
 
 TEST(pikaui, page) {
     /* init */
@@ -16,6 +16,5 @@ TEST(pikaui, page) {
     EXPECT_EQ(pikaMemNow(), 0);
 }
 
-
 #endif
 TEST_END

+ 2 - 0
test/python/PikaUI/test_page.py

@@ -59,6 +59,8 @@ class Page2(ui.Page):
 
 
 app = ui.App()
+page1 = Page1()
+page1.add(page1.build())
 app.pageManager.enter(Page2())
 app.timer.cb(0)
 # mem.now()

+ 11 - 0
test/python/gc/gc_tree1.py

@@ -0,0 +1,11 @@
+
+class Tree:
+    parent = None
+    child = []
+
+t1 = Tree()
+t2 = Tree()
+t1.child.append(t2)
+del t2
+
+gcdump()