summaryrefslogtreecommitdiffstats
path: root/generic/tclOODefineCmds.c
diff options
context:
space:
mode:
authorpooryorick <com.digitalsmarties@pooryorick.com>2018-02-15 09:30:29 (GMT)
committerpooryorick <com.digitalsmarties@pooryorick.com>2018-02-15 09:30:29 (GMT)
commit08b8c1713e0d0cfedc6e525c03173e61776fad5e (patch)
tree3d954db33d5a0bb6c4e28ca3a187bccbb1b32d91 /generic/tclOODefineCmds.c
parent91e15742f17bdb0d585dad1b1f605f36182259bd (diff)
downloadtcl-08b8c1713e0d0cfedc6e525c03173e61776fad5e.zip
tcl-08b8c1713e0d0cfedc6e525c03173e61776fad5e.tar.gz
tcl-08b8c1713e0d0cfedc6e525c03173e61776fad5e.tar.bz2
Streamline TclOO object cleanup routines.
Diffstat (limited to 'generic/tclOODefineCmds.c')
-rw-r--r--generic/tclOODefineCmds.c64
1 files changed, 52 insertions, 12 deletions
diff --git a/generic/tclOODefineCmds.c b/generic/tclOODefineCmds.c
index 47b34bb..d05d899 100644
--- a/generic/tclOODefineCmds.c
+++ b/generic/tclOODefineCmds.c
@@ -326,9 +326,7 @@ TclOOObjectSetMixins(
if (numMixins == 0) {
if (oPtr->mixins.num != 0) {
FOREACH(mixinPtr, oPtr->mixins) {
- if (mixinPtr) {
- TclOORemoveFromInstances(oPtr, mixinPtr);
- }
+ TclOORemoveFromInstances(oPtr, mixinPtr);
}
ckfree(oPtr->mixins.list);
oPtr->mixins.num = 0;
@@ -352,6 +350,10 @@ TclOOObjectSetMixins(
FOREACH(mixinPtr, oPtr->mixins) {
if (mixinPtr != oPtr->selfCls) {
TclOOAddToInstances(oPtr, mixinPtr);
+ /* Corresponding TclOODecrRefCount() is in the caller of this
+ * function.
+ */
+ TclOODecrRefCount(mixinPtr->thisPtr);
}
}
}
@@ -399,6 +401,10 @@ TclOOClassSetMixins(
memcpy(classPtr->mixins.list, mixins, sizeof(Class *) * numMixins);
FOREACH(mixinPtr, classPtr->mixins) {
TclOOAddToMixinSubs(classPtr, mixinPtr);
+ /* Corresponding TclOODecrRefCount() is in the caller of this
+ * function
+ */
+ TclOODecrRefCount(mixinPtr->thisPtr);
}
}
BumpGlobalEpoch(interp, classPtr);
@@ -914,7 +920,7 @@ TclOODefineObjCmd(
} else {
result = MagicDefinitionInvoke(interp, fPtr->defineNs, 2, objc, objv);
}
- DelRef(oPtr);
+ TclOODecrRefCount(oPtr);
/*
* Restore the previous "current" namespace.
@@ -981,7 +987,7 @@ TclOOObjDefObjCmd(
} else {
result = MagicDefinitionInvoke(interp, fPtr->objdefNs, 2, objc, objv);
}
- DelRef(oPtr);
+ TclOODecrRefCount(oPtr);
/*
* Restore the previous "current" namespace.
@@ -1048,7 +1054,7 @@ TclOODefineSelfObjCmd(
} else {
result = MagicDefinitionInvoke(interp, fPtr->objdefNs, 1, objc, objv);
}
- DelRef(oPtr);
+ TclOODecrRefCount(oPtr);
/*
* Restore the previous "current" namespace.
@@ -1120,11 +1126,11 @@ TclOODefineClassObjCmd(
if (oPtr->selfCls != clsPtr) {
TclOORemoveFromInstances(oPtr, oPtr->selfCls);
+
+ /* Reference count already incremented 3 lines up. */
oPtr->selfCls = clsPtr;
+
TclOOAddToInstances(oPtr, oPtr->selfCls);
- if (!(clsPtr->thisPtr->flags & OBJECT_DELETED)) {
- oPtr->flags &= ~CLASS_GONE;
- }
if (oPtr->classPtr != NULL) {
BumpGlobalEpoch(interp, oPtr->classPtr);
} else {
@@ -1580,6 +1586,10 @@ TclOODefineMixinObjCmd(
goto freeAndError;
}
mixins[i-1] = clsPtr;
+ /* Corresponding TclOODecrRefCount() is in TclOOObjectSetMixins,
+ * TclOOClassSetMixinsk, or just below if this function fails.
+ */
+ AddRef(mixins[i-1]->thisPtr);
}
if (isInstanceMixin) {
@@ -1592,6 +1602,9 @@ TclOODefineMixinObjCmd(
return TCL_OK;
freeAndError:
+ while (--i > 0) {
+ TclOODecrRefCount(mixins[i]->thisPtr);
+ }
TclStackFree(interp, mixins);
return TCL_ERROR;
}
@@ -2007,6 +2020,7 @@ ClassMixinSet(
mixins[i] = GetClassInOuterContext(interp, mixinv[i],
"may only mix in classes");
if (mixins[i] == NULL) {
+ i--;
goto freeAndError;
}
if (TclOOIsReachable(oPtr->classPtr, mixins[i])) {
@@ -2015,6 +2029,10 @@ ClassMixinSet(
Tcl_SetErrorCode(interp, "TCL", "OO", "SELF_MIXIN", NULL);
goto freeAndError;
}
+ /* Corresponding TclOODecrRefCount() is in TclOOClassSetMixins, or just
+ * below if this function fails
+ */
+ AddRef(mixins[i]->thisPtr);
}
TclOOClassSetMixins(interp, oPtr->classPtr, mixinc, mixins);
@@ -2022,6 +2040,9 @@ ClassMixinSet(
return TCL_OK;
freeAndError:
+ while (i-- > 0) {
+ TclOODecrRefCount(mixins[i]->thisPtr);
+ }
TclStackFree(interp, mixins);
return TCL_ERROR;
}
@@ -2124,16 +2145,20 @@ ClassSuperSet(
if (superc == 0) {
superclasses = ckrealloc(superclasses, sizeof(Class *));
- superclasses[0] = oPtr->fPtr->objectCls;
- superc = 1;
if (TclOOIsReachable(oPtr->fPtr->classCls, oPtr->classPtr)) {
superclasses[0] = oPtr->fPtr->classCls;
+ } else {
+ superclasses[0] = oPtr->fPtr->objectCls;
}
+ superc = 1;
+ /* Corresponding TclOODecrRefCount is near the end of this function */
+ AddRef(superclasses[0]->thisPtr);
} else {
for (i=0 ; i<superc ; i++) {
superclasses[i] = GetClassInOuterContext(interp, superv[i],
"only a class can be a superclass");
if (superclasses[i] == NULL) {
+ i--;
goto failedAfterAlloc;
}
for (j=0 ; j<i ; j++) {
@@ -2150,9 +2175,15 @@ ClassSuperSet(
"attempt to form circular dependency graph", -1));
Tcl_SetErrorCode(interp, "TCL", "OO", "CIRCULARITY", NULL);
failedAfterAlloc:
- ckfree((char *) superclasses);
+ for (; i > 0; i--) {
+ TclOODecrRefCount(superclasses[i]->thisPtr);
+ }
+ ckfree(superclasses);
return TCL_ERROR;
}
+ /* Corresponding TclOODecrRefCount() is near the end of this
+ * function */
+ AddRef(superclasses[i]->thisPtr);
}
}
@@ -2173,6 +2204,8 @@ ClassSuperSet(
oPtr->classPtr->superclasses.num = superc;
FOREACH(superPtr, oPtr->classPtr->superclasses) {
TclOOAddToSubclasses(oPtr->classPtr, superPtr);
+ /* To account for the AddRef() earlier in this function */
+ TclOODecrRefCount(superPtr->thisPtr);
}
BumpGlobalEpoch(interp, oPtr->classPtr);
@@ -2463,9 +2496,16 @@ ObjMixinSet(
mixins[i] = GetClassInOuterContext(interp, mixinv[i],
"may only mix in classes");
if (mixins[i] == NULL) {
+ while (i-- > 0) {
+ TclOODecrRefCount(mixins[i]->thisPtr);
+ }
TclStackFree(interp, mixins);
return TCL_ERROR;
}
+ /* Corresponding TclOODecrRefCount() is in TclOOObjectSetMixins() or
+ * just above if this function fails.
+ */
+ AddRef(mixins[i]->thisPtr);
}
TclOOObjectSetMixins(oPtr, mixinc, mixins);