浏览代码

feat: Object新增读写锁

SongZihuan 3 年之前
父节点
当前提交
bf85429c1b
共有 9 个文件被更改,包括 222 次插入51 次删除
  1. 1 0
      include/core/object.h
  2. 3 0
      src/core/__object.h
  3. 2 2
      src/core/__var.h
  4. 15 13
      src/core/env.c
  5. 9 6
      src/core/gc.c
  6. 71 16
      src/core/object.c
  7. 6 4
      src/core/run.c
  8. 114 9
      src/core/var.c
  9. 1 1
      src/runtime/runtime.c

+ 1 - 0
include/core/object.h

@@ -46,6 +46,7 @@ AFUN_CORE_EXPORT af_Object *findObjectAttributes(char *name, af_Object *visitor,
 AFUN_CORE_EXPORT char *getObjectID(af_Object *obj);
 AFUN_CORE_EXPORT af_ObjectAPI *getObjectAPI(af_Object *obj);
 AFUN_CORE_EXPORT af_Inherit *getObjectInherit(af_Object *obj);
+AFUN_CORE_EXPORT af_VarSpace *getObjectVarSpace(af_Object *obj);
 
 /* API表 属性访问 */
 AFUN_CORE_EXPORT void *findAPI(char *api_name, af_ObjectAPI *api);

+ 3 - 0
src/core/__object.h

@@ -14,6 +14,7 @@ typedef struct af_ObjectAPINode af_ObjectAPINode;
 
 #include "object.h"
 #include "__gc.h"
+#include "pthread.h"
 
 #define API_HASHTABLE_SIZE (8)
 
@@ -51,6 +52,8 @@ struct af_ObjectData {
 struct af_Object {
     struct af_Object *belong;  // 只有顶级属对象的belong属性可为NULL
     struct af_ObjectData *data;
+    pthread_rwlock_t lock;  // 保护上面两个字段
+
     GC_Object gc;
 };
 

+ 2 - 2
src/core/__var.h

@@ -22,7 +22,7 @@ struct af_Var {
     char *name;
     struct af_VarNode *vn;
     char permissions[3];  // 读-1 写-2 读且写-3 不读不写-0 [自身权限 后代权限 外部权限]
-    pthread_rwlock_t lock;
+    pthread_rwlock_t lock;  // 保护上面三个字段
 
     GC_Var gc;
 };
@@ -37,7 +37,7 @@ struct af_VarSpace {
     struct af_VarCup *(var[VAR_HASHTABLE_SIZE]);
     struct af_Object *belong;  // 属主
     char permissions[3];  // 可定义(2),可删除(1) [自身权限 后代权限 外部权限]
-    pthread_rwlock_t lock;  // 控制 除gc 外其他字段的访问
+    pthread_rwlock_t lock;  // 控制 除gc外其他字段的访问
 
     GC_VarSpace gc;  // 仅能由 gc 机制访问
 };

+ 15 - 13
src/core/env.c

@@ -204,7 +204,7 @@ static af_Activity *makeTopActivity(af_Code *bt_top, af_Code *bt_start, af_VarSp
     activity->status = act_func_normal;
 
     activity->count_run_varlist = 2;
-    activity->run_varlist = makeVarSpaceList(belong->data->var_space);
+    activity->run_varlist = makeVarSpaceList(getObjectVarSpace(belong));
     activity->run_varlist->next = makeVarSpaceList(protect);
 
     setActivityBtTop(NULL, activity);  // top-activity直接就在normal, bt_top将不被设定
@@ -1045,10 +1045,10 @@ static bool isInfixFunc(af_Code *code, af_Environment *env) {
         return false;
 
     af_Object *obj = findVarNode(var, NULL);
-    obj_isInfixFunc *func = findAPI("obj_isInfixFunc", obj->data->api);
+    obj_isInfixFunc *func = findAPI("obj_isInfixFunc", getObjectAPI(obj));
     if (func == NULL)
         return false;
-    return func(obj->data->id, obj);
+    return func(getObjectID(obj), obj);
 }
 
 bool pushExecutionActivity(af_Code *bt, bool return_first, af_Environment *env) {
@@ -1225,8 +1225,9 @@ void setArgCodeListToActivity(af_ArgCodeList *acl, af_Environment *env) {
 }
 
 bool setFuncActivityToArg(af_Object *func, af_Environment *env) {
-    obj_funcGetArgCodeList *get_acl = findAPI("obj_funcGetArgCodeList", func->data->api);
-    obj_funcGetVarList *get_var_list = findAPI("obj_funcGetVarList", func->data->api);
+    af_ObjectAPI *api = getObjectAPI(func);
+    obj_funcGetArgCodeList *get_acl = findAPI("obj_funcGetArgCodeList", api);
+    obj_funcGetVarList *get_var_list = findAPI("obj_funcGetVarList", api);
 
     if (get_var_list == NULL) {
         pushMessageDown(makeERRORMessage(TYPE_ERROR, API_NOT_FOUND_INFO(obj_funcGetVarList), env), env);
@@ -1239,12 +1240,12 @@ bool setFuncActivityToArg(af_Object *func, af_Environment *env) {
 
     /* 遇到错误时 get_acl 和 get_var_list 要自行设定msg */
     if (get_acl != NULL) {
-        if (!get_acl(func->data->id, func, &env->activity->acl_start, env->activity->bt_top, &env->activity->mark, env))  // 设置acl
+        if (!get_acl(getObjectID(func), func, &env->activity->acl_start, env->activity->bt_top, &env->activity->mark, env))  // 设置acl
             return false;
     } else
         env->activity->acl_start = NULL;
 
-    if (!get_var_list(func->data->id, func, &env->activity->func_varlist, env->activity->mark, env))  // 设置 func_var_list
+    if (!get_var_list(getObjectID(func), func, &env->activity->func_varlist, env->activity->mark, env))  // 设置 func_var_list
         return false;
 
     env->activity->acl_done = env->activity->acl_start;
@@ -1253,8 +1254,9 @@ bool setFuncActivityToArg(af_Object *func, af_Environment *env) {
 }
 
 bool setFuncActivityAddVar(af_Environment *env){
-    obj_funcGetInfo *get_info = findAPI("obj_funcGetInfo", env->activity->func->data->api);
-    obj_funcGetArgList *get_arg_list = findAPI("obj_funcGetArgList", env->activity->func->data->api);
+    af_ObjectAPI *api = getObjectAPI(env->activity->func);
+    obj_funcGetInfo *get_info = findAPI("obj_funcGetInfo", api);
+    obj_funcGetArgList *get_arg_list = findAPI("obj_funcGetArgList", api);
     af_FuncInfo *fi = NULL;
 
     if (get_info == NULL) {
@@ -1263,7 +1265,7 @@ bool setFuncActivityAddVar(af_Environment *env){
     }
 
     /* env->activity->fi可能还存储着旧的FuncInfo(尾调用优化), 因此不能直接保存到 env->activity->fi 中 */
-    if (!get_info(env->activity->func->data->id, env->activity->func, &fi, env->activity->bt_top, env->activity->mark, env))
+    if (!get_info(getObjectID(env->activity->func), env->activity->func, &fi, env->activity->bt_top, env->activity->mark, env))
         return false;
     if (fi == NULL) {
         pushMessageDown(makeERRORMessage(API_RUN_ERROR, API_DONOT_GIVE(FuncInfo), env), env);
@@ -1327,7 +1329,7 @@ bool setFuncActivityAddVar(af_Environment *env){
     /* 计算参数 */
     if (get_arg_list != NULL) {
         af_ArgList *al;
-        if (!get_arg_list(env->activity->func->data->id, env->activity->func, &al, env->activity->acl_start, env->activity->mark, env))
+        if (!get_arg_list(getObjectID(env->activity->func), env->activity->func, &al, env->activity->acl_start, env->activity->mark, env))
             return false;
         runArgList(al, env->activity->run_varlist, env);
         freeAllArgList(al);
@@ -1455,9 +1457,9 @@ void runTopMessageProcess(bool is_top, af_Environment *env) {
 
 static void freeMark(af_Activity *activity) {
     if (activity->type == act_func && activity->func != NULL && activity->mark != NULL) {
-        obj_funcFreeMask *func = findAPI("obj_funcFreeMask", activity->func->data->api);
+        obj_funcFreeMask *func = findAPI("obj_funcFreeMask", getObjectAPI(activity->func));
         if (func != NULL)
-            func(activity->func->data->id, activity->func, activity->mark);
+            func(getObjectID(activity->func), activity->func, activity->mark);
         activity->mark = NULL;
     }
 }

+ 9 - 6
src/core/gc.c

@@ -176,7 +176,7 @@ static pgc_Analyzed reachableVar(struct af_Var *var, pgc_Analyzed plist);
 static pgc_Analyzed reachableVarSpace(struct af_VarSpace *vs, pgc_Analyzed plist);
 static pgc_Analyzed reachableVarSpaceList(struct af_VarSpaceListNode *vsl, pgc_Analyzed plist);
 static pgc_Analyzed reachableObjectData(struct af_ObjectData *od, pgc_Analyzed plist);
-static pgc_Analyzed reachableObject(struct af_Object *od, pgc_Analyzed plist);
+static pgc_Analyzed reachableObject(struct af_Object *obj, pgc_Analyzed plist);
 
 /* gc运行函数 */
 static void freeValue(af_Environment *env);
@@ -191,11 +191,14 @@ static pgc_Analyzed checkAnalyzed(gc_Analyzed *analyzed, pgc_Analyzed plist);
 // ObjectData可能要调用API, 因此其需要调用的对象是不确定的, 但只有Object需要gc_Analyzed
 // VarSpace和Var的调用是确定的, 他们不会往回调用除Object外的其他量
 // 所以gc_Analyzed记录Object就足够了
-static pgc_Analyzed reachableObject(struct af_Object *od, pgc_Analyzed plist) {
-    for (NULL; od != NULL && !od->gc.info.reachable; od = od->belong) {
-        od->gc.info.reachable = true;
-        if (!od->data->gc.info.reachable)
-            plist = reachableObjectData(od->data, plist);
+static pgc_Analyzed reachableObject(struct af_Object *obj, pgc_Analyzed plist) {
+    for (NULL; obj != NULL && !obj->gc.info.reachable; obj = obj->belong) {
+        obj->gc.info.reachable = true;
+
+        pthread_rwlock_rdlock(&obj->lock);
+        if (!obj->data->gc.info.reachable)
+            plist = reachableObjectData(obj->data, plist);
+        pthread_rwlock_unlock(&obj->lock);
     }
     return plist;
 }

+ 71 - 16
src/core/object.c

@@ -57,6 +57,7 @@ static af_Object *makeObject_Pri(char *id, bool free_api, af_ObjectAPI *api, boo
     af_Object *obj = calloc(1, sizeof(af_Object));
     obj->belong = NULL;
     makeObjectData_Pri(id, free_api, api, allow_inherit, obj, env);
+    pthread_rwlock_init(&obj->lock, NULL);
     gc_addObject(obj, env);
     return obj;
 }
@@ -133,17 +134,23 @@ void freeObjectData(af_ObjectData *od, af_Environment *env) {
 
 void freeObject(af_Object *obj, af_Environment *env) {
     GC_FREE_EXCHANGE(obj, Object, env);
+    pthread_rwlock_destroy(&obj->lock);
     free(obj);
 }
 
 void *getObjectData(af_Object *obj) {
-    return obj->data->data;
+    pthread_rwlock_rdlock(&obj->lock);
+    void *data = obj->data->data;
+    pthread_rwlock_unlock(&obj->lock);
+
+    return data;
 }
 
 af_Object *getBelongObject(af_Object *object){
-    if (object->belong == NULL)
-        return object;
-    return object->belong;
+    pthread_rwlock_wrlock(&object->lock);
+    af_Object *belong = (object->belong == NULL ? object : object->belong);
+    pthread_rwlock_unlock(&object->lock);
+    return belong;
 }
 
 af_Inherit *makeInherit(af_Object *obj) {
@@ -182,10 +189,19 @@ void freeAllInherit(af_Inherit *ih) {
 }
 
 bool checkPosterity(af_Object *base, af_Object *posterity) {
+    pthread_rwlock_rdlock(&posterity->lock);
+    af_ObjectData *data = posterity->data;
+    pthread_rwlock_unlock(&posterity->lock);
+
+    pthread_rwlock_rdlock(&base->lock);
     for (af_Inherit *ih = base->data->inherit; ih != NULL; ih = ih->next) {
-        if (ih->obj->data == posterity->data)
+        if (ih->obj->data == data) {
+            pthread_rwlock_unlock(&base->lock);
             return true;
+        }
     }
+
+    pthread_rwlock_unlock(&base->lock);
     return false;
 }
 
@@ -288,9 +304,12 @@ static af_ObjectAPINode *findObjectDataAPINode(char *api_name, af_ObjectData *od
  * 函数名: findObjectDataAPINode
  * 目标: 从DLC中获取函数并写入Object的API
  */
-int addAPIToObject(DLC_SYMBOL(objectAPIFunc) func, char *api_name,
-                   af_Object *obj) {
-    return addAPIToObjectData(func, api_name, obj->data);
+int addAPIToObject(DLC_SYMBOL(objectAPIFunc) func, char *api_name, af_Object *obj) {
+    pthread_rwlock_rdlock(&obj->lock);
+    af_ObjectData *data = obj->data;
+    pthread_rwlock_unlock(&obj->lock);
+
+    return addAPIToObjectData(func, api_name, data);
 }
 
 /*
@@ -298,19 +317,27 @@ int addAPIToObject(DLC_SYMBOL(objectAPIFunc) func, char *api_name,
  * 目标: 从Object中获取指定api的函数指针
  */
 void *findObjectAPI(char *api_name, af_Object *obj) {
-    af_ObjectAPINode *node = findObjectDataAPINode(api_name, obj->data);
+    pthread_rwlock_rdlock(&obj->lock);
+    af_ObjectData *data = obj->data;
+    pthread_rwlock_unlock(&obj->lock);
+
+    af_ObjectAPINode *node = findObjectDataAPINode(api_name, data);
     if (node == NULL)
         return NULL;
     return GET_SYMBOL(node->api);
 }
 
 af_Object *findObjectAttributes(char *name, af_Object *visitor, af_Object *obj) {
-    af_Var *var = findVarFromVarSpace(name, visitor, obj->data->var_space);
+    pthread_rwlock_rdlock(&obj->lock);
+    af_ObjectData *data = obj->data;
+    pthread_rwlock_unlock(&obj->lock);
+
+    af_Var *var = findVarFromVarSpace(name, visitor, data->var_space);
 
     if (var != NULL)
         return findVarNode(var, NULL);
 
-    for (af_Inherit *ih = obj->data->inherit; ih != NULL; ih = ih->next) {
+    for (af_Inherit *ih = data->inherit; ih != NULL; ih = ih->next) {
         var = findVarFromVarSpace(name, visitor, ih->vs);  // 搜索共享变量空间
         if (var != NULL)
             return findVarNode(var, NULL);
@@ -321,7 +348,11 @@ af_Object *findObjectAttributes(char *name, af_Object *visitor, af_Object *obj)
 
 bool setObjectAttributes(char *name, char p_self, char p_posterity, char p_external, af_Object *attributes,
                          af_Object *obj, af_Object *visitor, af_Environment *env){
-    return makeVarToVarSpace(name, p_self, p_posterity, p_external, attributes, obj->data->var_space, visitor, env);
+    pthread_rwlock_rdlock(&obj->lock);
+    af_ObjectData *data = obj->data;
+    pthread_rwlock_unlock(&obj->lock);
+
+    return makeVarToVarSpace(name, p_self, p_posterity, p_external, attributes, data->var_space, visitor, env);
 }
 
 af_Object *findObjectAttributesByObjectData(char *name, af_Object *visitor, af_ObjectData *od) {
@@ -340,15 +371,35 @@ af_Object *findObjectAttributesByObjectData(char *name, af_Object *visitor, af_O
 }
 
 char *getObjectID(af_Object *obj) {
-    return obj->data->id;
+    pthread_rwlock_rdlock(&obj->lock);
+    af_ObjectData *data = obj->data;
+    pthread_rwlock_unlock(&obj->lock);
+
+    return data->id;
 }
 
 af_ObjectAPI *getObjectAPI(af_Object *obj) {
-    return obj->data->api;
+    pthread_rwlock_rdlock(&obj->lock);
+    af_ObjectData *data = obj->data;
+    pthread_rwlock_unlock(&obj->lock);
+
+    return data->api;
 }
 
 af_Inherit *getObjectInherit(af_Object *obj) {
-    return obj->data->inherit;
+    pthread_rwlock_rdlock(&obj->lock);
+    af_ObjectData *data = obj->data;
+    pthread_rwlock_unlock(&obj->lock);
+
+    return data->inherit;
+}
+
+af_VarSpace *getObjectVarSpace(af_Object *obj) {
+    pthread_rwlock_rdlock(&obj->lock);
+    af_ObjectData *data = obj->data;
+    pthread_rwlock_unlock(&obj->lock);
+
+    return data->var_space;
 }
 
 af_Inherit *getInheritNext(af_Inherit *ih) {
@@ -368,5 +419,9 @@ ObjAPIUint getAPICount(af_ObjectAPI *api) {
 }
 
 void objectSetAllowInherit(af_Object *obj, bool allow) {
-    obj->data->allow_inherit = allow;
+    pthread_rwlock_rdlock(&obj->lock);
+    af_ObjectData *data = obj->data;
+    pthread_rwlock_unlock(&obj->lock);
+
+    data->allow_inherit = allow;
 }

+ 6 - 4
src/core/run.c

@@ -47,7 +47,7 @@ static bool checkLiteral(af_Message **msg, af_Environment *env) {
         return false;
 
     af_Object *obj = *(af_Object **)((*msg)->msg);
-    obj_literalSetting *func = findAPI("obj_literalSetting", obj->data->api);
+    obj_literalSetting *func = findAPI("obj_literalSetting", getObjectAPI(obj));
     if (func == NULL) {
         gc_delReference(obj);
         freeMessage(*msg);
@@ -56,7 +56,7 @@ static bool checkLiteral(af_Message **msg, af_Environment *env) {
     }
 
     for (af_LiteralDataList *ld = env->activity->ld; ld != NULL; ld = ld->next)
-        func(obj->data->id, obj, obj->data->data, ld->literal_data, env);
+        func(getObjectID(obj), obj, getObjectData(obj), ld->literal_data, env);
 
     freeAllLiteralData(env->activity->ld);
     env->activity->ld = NULL;
@@ -189,10 +189,12 @@ static bool codeElement(af_Code *code, af_Environment *env) {
     obj_isInfixFunc *is_infix;
 
     if (code->prefix != getPrefix(E_QUOTE, env)) {
-        if ((is_obj = findAPI("obj_isObjFunc", obj->data->api)) != NULL && is_obj(obj->data->id, obj))
+        af_ObjectAPI *api = getObjectAPI(obj);
+        char *id = getObjectID(obj);
+        if ((is_obj = findAPI("obj_isObjFunc", api)) != NULL && is_obj(id, obj))
             return pushVariableActivity(code, obj, env);  // 对象函数
         else if (env->activity->status != act_func_get && // 在act_func_get 模式下不检查是否为is_infix函数 因为本来就要将其作为函数调用
-                 (is_infix = findAPI("obj_isInfixFunc", obj->data->api)) != NULL && is_infix(obj->data->id, obj)) {
+                 (is_infix = findAPI("obj_isInfixFunc", api)) != NULL && is_infix(id, obj)) {
             pushMessageDown(makeERRORMessageFormat(INFIX_PROTECT, env,
                                                    "Infix protect variable: %s.", code->element.data), env);
             return false;

+ 114 - 9
src/core/var.c

@@ -196,7 +196,21 @@ bool freeVarSpaceListCount(size_t count, af_VarSpaceListNode *vsl) {
 static bool checkVarSpaceDefinePermissions(af_Object *visitor, af_VarSpace *vs){
     char p = vs->permissions[2];  // 默认外部权限
 
-    if (vs->belong == NULL || (visitor != NULL && vs->belong->data == visitor->data))  // (无权限设定或ObjectData匹配) 应用自身权限
+    af_ObjectData *belong_data = NULL;
+    if (vs->belong != NULL) {
+        pthread_rwlock_rdlock(&vs->belong->lock);
+        belong_data = vs->belong->data;
+        pthread_rwlock_unlock(&vs->belong->lock);
+    }
+
+    af_ObjectData *visitor_data = NULL;
+    if (visitor != NULL) {
+        pthread_rwlock_rdlock(&visitor->lock);
+        visitor_data = visitor->data;
+        pthread_rwlock_unlock(&visitor->lock);
+    }
+
+    if (vs->belong == NULL || (visitor != NULL && belong_data == visitor_data))  // (无权限设定或ObjectData匹配) 应用自身权限
         p = vs->permissions[0];
     else if (visitor != NULL && checkPosterity(vs->belong, visitor))  // 应用后代权限
         p = vs->permissions[1];
@@ -333,7 +347,21 @@ bool addVarToProtectVarSpace(af_Var *var, af_Environment *env) {
 static bool checkVarSpaceDelPermissions(af_Object *visitor, af_VarSpace *vs) {
     char p = vs->permissions[2];  // 默认外部权限
 
-    if (vs->belong == NULL || (visitor != NULL && vs->belong->data == visitor->data))  // (无权限设定或ObjectData匹配) 应用自身权限
+    af_ObjectData *belong_data = NULL;
+    if (vs->belong != NULL) {
+        pthread_rwlock_rdlock(&vs->belong->lock);
+        belong_data = vs->belong->data;
+        pthread_rwlock_unlock(&vs->belong->lock);
+    }
+
+    af_ObjectData *visitor_data = NULL;
+    if (visitor != NULL) {
+        pthread_rwlock_rdlock(&visitor->lock);
+        visitor_data = visitor->data;
+        pthread_rwlock_unlock(&visitor->lock);
+    }
+
+    if (vs->belong == NULL || (visitor != NULL && belong_data == visitor_data))  // (无权限设定或ObjectData匹配) 应用自身权限
         p = vs->permissions[0];
     else if (visitor != NULL && checkPosterity(vs->belong, visitor))  // 应用后代权限
         p = vs->permissions[1];
@@ -424,10 +452,26 @@ static bool checkVarReadPermissions(af_Var *var, af_Object *visitor, af_VarSpace
 
     pthread_rwlock_rdlock(&vs->lock);
     pthread_rwlock_rdlock(&var->lock);
-    if (vs->belong == NULL || (visitor != NULL && vs->belong->data == visitor->data))  // (无权限设定或ObjectData匹配) 应用自身权限
+
+    af_ObjectData *belong_data = NULL;
+    if (vs->belong != NULL) {
+        pthread_rwlock_rdlock(&vs->belong->lock);
+        belong_data = vs->belong->data;
+        pthread_rwlock_unlock(&vs->belong->lock);
+    }
+
+    af_ObjectData *visitor_data = NULL;
+    if (visitor != NULL) {
+        pthread_rwlock_rdlock(&visitor->lock);
+        visitor_data = visitor->data;
+        pthread_rwlock_unlock(&visitor->lock);
+    }
+
+    if (vs->belong == NULL || (visitor != NULL && belong_data == visitor_data))  // (无权限设定或ObjectData匹配) 应用自身权限
         p = var->permissions[0];
     else if (visitor != NULL && checkPosterity(vs->belong, visitor))  // 应用后代权限
         p = var->permissions[1];
+
     pthread_rwlock_unlock(&vs->lock);
     pthread_rwlock_unlock(&var->lock);
     return p == 1 || p == 3;
@@ -480,8 +524,22 @@ af_Var *findVarFromVarList(char *name, af_Object *visitor, af_VarSpaceListNode *
 static bool checkVarWritePermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs){
     char p = var->permissions[2];  // 默认外部权限
 
+    af_ObjectData *belong_data = NULL;
+    if (vs->belong != NULL) {
+        pthread_rwlock_rdlock(&vs->belong->lock);
+        belong_data = vs->belong->data;
+        pthread_rwlock_unlock(&vs->belong->lock);
+    }
+
+    af_ObjectData *visitor_data = NULL;
+    if (visitor != NULL) {
+        pthread_rwlock_rdlock(&visitor->lock);
+        visitor_data = visitor->data;
+        pthread_rwlock_unlock(&visitor->lock);
+    }
+
     pthread_rwlock_rdlock(&vs->lock);
-    if (vs->belong == NULL || (visitor != NULL && vs->belong->data == visitor->data))  // (无权限设定或ObjectData匹配) 应用自身权限
+    if (vs->belong == NULL || (visitor != NULL && belong_data == visitor_data))  // (无权限设定或ObjectData匹配) 应用自身权限
         p = var->permissions[0];
     else if (visitor != NULL && checkPosterity(vs->belong, visitor))  // 应用后代权限
         p = var->permissions[1];
@@ -551,10 +609,26 @@ af_VarSpaceListNode *pushNewVarList(af_Object *belong, af_VarSpaceListNode *base
 
 void setVarPermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external) {
     pthread_rwlock_rdlock(&vs->lock);
-    if (vs->belong->data != visitor->data)
-        return;
+
+    af_ObjectData *belong_data = NULL;
+    if (vs->belong != NULL) {
+        pthread_rwlock_rdlock(&vs->belong->lock);
+        belong_data = vs->belong->data;
+        pthread_rwlock_unlock(&vs->belong->lock);
+    }
+
+    af_ObjectData *visitor_data = NULL;
+    if (visitor != NULL) {
+        pthread_rwlock_rdlock(&visitor->lock);
+        visitor_data = visitor->data;
+        pthread_rwlock_unlock(&visitor->lock);
+    }
+
     pthread_rwlock_unlock(&vs->lock);
 
+    if (belong_data != NULL && belong_data != visitor_data)
+        return;
+
     pthread_rwlock_wrlock(&var->lock);
     var->permissions[0] = p_self;
     var->permissions[1] = p_posterity;
@@ -564,10 +638,26 @@ void setVarPermissions(af_Var *var, af_Object *visitor, af_VarSpace *vs, char p_
 
 void setVarSpacePermissions(af_Object *visitor, af_VarSpace *vs, char p_self, char p_posterity, char p_external) {
     pthread_rwlock_rdlock(&vs->lock);
-    if (vs->belong->data != visitor->data)
-        return;
+
+    af_ObjectData *belong_data = NULL;
+    if (vs->belong != NULL) {
+        pthread_rwlock_rdlock(&vs->belong->lock);
+        belong_data = vs->belong->data;
+        pthread_rwlock_unlock(&vs->belong->lock);
+    }
+
+    af_ObjectData *visitor_data = NULL;
+    if (visitor != NULL) {
+        pthread_rwlock_rdlock(&visitor->lock);
+        visitor_data = visitor->data;
+        pthread_rwlock_unlock(&visitor->lock);
+    }
+
     pthread_rwlock_unlock(&vs->lock);
 
+    if (belong_data != NULL && belong_data != visitor_data)
+        return;
+
     vs->permissions[0] = p_self;
     vs->permissions[1] = p_posterity;
     vs->permissions[2] = p_external;
@@ -583,7 +673,22 @@ bool isProtectVarSpace(af_VarSpace *vs) {
 bool setVarSpaceProtect(af_Object *visitor, af_VarSpace *vs, bool protect) {
     pthread_rwlock_wrlock(&vs->lock);
     bool re = vs->is_protect;
-    if (vs->belong != NULL && vs->belong->data != visitor->data) {
+
+    af_ObjectData *belong_data = NULL;
+    if (vs->belong != NULL) {
+        pthread_rwlock_rdlock(&vs->belong->lock);
+        belong_data = vs->belong->data;
+        pthread_rwlock_unlock(&vs->belong->lock);
+    }
+
+    af_ObjectData *visitor_data = NULL;
+    if (visitor != NULL) {
+        pthread_rwlock_rdlock(&visitor->lock);
+        visitor_data = visitor->data;
+        pthread_rwlock_unlock(&visitor->lock);
+    }
+
+    if (belong_data != NULL && belong_data != visitor_data) {
         pthread_rwlock_unlock(&vs->lock);
         return re;
     }

+ 1 - 1
src/runtime/runtime.c

@@ -37,7 +37,7 @@ int runtimeToolImport(char *name, af_Object **obj, af_Code **code, af_Environmen
     if (name == NULL || code == NULL || env == NULL || obj == NULL)
         return 1;
     *obj = makeGlobalObject(env);
-    return runtimeTool(name, code, *obj, (*obj)->data->var_space, env);
+    return runtimeTool(name, code, *obj, getObjectVarSpace((*obj)), env);
 }
 
 /*