0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

patch 9.0.1035: object members are not being marked as used

Problem:    Object members are not being marked as used, garbage collection
            may free them.
Solution:   Mark object members as used.  Fix reference counting.
This commit is contained in:
Bram Moolenaar
2022-12-08 20:42:00 +00:00
parent e5eae82bb7
commit d28d7b94f5
8 changed files with 288 additions and 158 deletions

View File

@@ -419,13 +419,18 @@ class_object_index(
CLEAR_FIELD(funcexe);
funcexe.fe_evaluate = TRUE;
// Clear the class or object after calling the function, in
// case the refcount is one.
typval_T tv_tofree = *rettv;
rettv->v_type = VAR_UNKNOWN;
// Call the user function. Result goes into rettv;
// TODO: pass the object
rettv->v_type = VAR_UNKNOWN;
int error = call_user_func_check(fp, argcount, argvars,
rettv, &funcexe, NULL);
// Clear the arguments.
// Clear the previous rettv and the arguments.
clear_tv(&tv_tofree);
for (int idx = 0; idx < argcount; ++idx)
clear_tv(&argvars[idx]);
@@ -494,7 +499,11 @@ object_clear(object_T *obj)
for (int i = 0; i < cl->class_obj_member_count; ++i)
clear_tv(tv + i);
// Remove from the list headed by "first_object".
object_cleared(obj);
vim_free(obj);
class_unref(cl);
}
/*
@@ -522,9 +531,8 @@ copy_class(typval_T *from, typval_T *to)
* Unreference a class. Free it when the reference count goes down to zero.
*/
void
class_unref(typval_T *tv)
class_unref(class_T *cl)
{
class_T *cl = tv->vval.v_class;
if (cl != NULL && --cl->class_refcount <= 0)
{
vim_free(cl->class_name);
@@ -547,5 +555,60 @@ class_unref(typval_T *tv)
}
}
static object_T *first_object = NULL;
/*
* Call this function when an object has been created. It will be added to the
* list headed by "first_object".
*/
void
object_created(object_T *obj)
{
if (first_object != NULL)
{
obj->obj_next_used = first_object;
first_object->obj_prev_used = obj;
}
first_object = obj;
}
/*
* Call this function when an object has been cleared and is about to be freed.
* It is removed from the list headed by "first_object".
*/
void
object_cleared(object_T *obj)
{
if (obj->obj_next_used != NULL)
obj->obj_next_used->obj_prev_used = obj->obj_prev_used;
if (obj->obj_prev_used != NULL)
obj->obj_prev_used->obj_next_used = obj->obj_next_used;
else if (first_object == obj)
first_object = obj->obj_next_used;
}
/*
* Go through the list of all objects and free items without "copyID".
*/
int
object_free_nonref(int copyID)
{
int did_free = FALSE;
object_T *next_obj;
for (object_T *obj = first_object; obj != NULL; obj = next_obj)
{
next_obj = obj->obj_next_used;
if ((obj->obj_copyID & COPYID_MASK) != (copyID & COPYID_MASK))
{
// Free the object and items it contains.
object_clear(obj);
did_free = TRUE;
}
}
return did_free;
}
#endif // FEAT_EVAL