Index: TODO =================================================================== diff -u -r9d0fec2bda60c9541c31cc726737129cec0d1350 -r7b09de6f9ec1cc5caf39751fa4f23c62365e8dfe --- TODO (.../TODO) (revision 9d0fec2bda60c9541c31cc726737129cec0d1350) +++ TODO (.../TODO) (revision 7b09de6f9ec1cc5caf39751fa4f23c62365e8dfe) @@ -3238,6 +3238,11 @@ - disposition.test: * remove/check exit (see comments in the file) +- fixed book-keeping for TclNamespace refcounting such that now + alias.test, destroy.test and test.xotcl run now clean, + 2 test are still open with tcl 8.5.10 (contains.test and xotcomm.test) + + TODO: - strange refcounting bug in 8.6b2 bug-is-86.tcl @@ -3266,16 +3271,6 @@ - disposition.test: * handle exit from eval/inticmd with proper refcounts - - nsf-refcounts on TclNamespace are not correct, when namespaces - are deleted by tcl. Maybe this is not a problem, but we have to check. - - Test case explicit-namespace-free { - Object create o {:method foo {} {return 1}} - namespace delete ::o - } - - fix mem_count on alias.test (currently 1 / 1) and destroy.test (-2/-2), - most probably related with the point above; values after slash: new - deletion of all procs and vars in all namespaces - fix mem_count on contains.test (currently 4 / 4) the minimal script seems to be the following and is related to the following message @@ -3287,16 +3282,14 @@ puts stderr ====EXIT exit ======================= - - - fix mem_count on testx (currently 3 / -1 (TclNamespace)) - - fix mem_count on slottest.test (currently 4 / 0) - fix mem_count on xocomm.test (currently 26 / 26) - interface of "variable" and "attribute": * add switch -array for "variable"? * should we switch from "-class" to "-slotclass"? * should we change interface for default value in attribute? probably not, same interface is used in methodparameters as well + - Should we leave "variable" and "attribute" as it ist? options: (a) leave it as it is @@ -3309,7 +3302,10 @@ (d) use "attribute" instead of "variable" Variable is the tcl term, attribute is the UML term (e) others? + - call user defined setter in object parameters? + - add flag -array to "variable" (just setting is trivial, + handling setters and incremental setter is more work) - [obj/cls info method handle "FOO foo"] does neither return a proper submethod handle nor any valid handle ... needs a fix. @@ -3356,14 +3352,13 @@ - nsf.m4 seems to be currently unused (SC_PATH_NSFCONFIG and SC_LOAD_NSFCONFIG) Should we delete it? -- add explicit regression tests for disposition + types -- check refcounting for dispo+types - maybe: add a disposition=pipe - MixinComputeOrderFullList() could receive a flag to store source classes in checkList - if the check on eg. info-heritage-circular in test/info.method.tcl - reports a warning on exit, if we get an exception. + reports a warning on exit, if we get an exception. + - should be be concerned about message like DEBUG obj 0x100227960 ::nx::Object activationcount 2 on stack 3; might be from non-stacked but active callstack content in the regression test? @@ -3375,12 +3370,6 @@ Still needed? Already replaced by new doctool? Does it have to run on make? Can doctool run on Make? -- the scripted init block is called before init. If the default - setting of the default parameters depend on each other, this has to - be set in the "init". But this won't be available in the init block. - This is not nice in the mongo case, where one has "mongo_ns", - "mongo_db" and "mongo_collection" which are related variables. - - Higher binary compatibility for future versions: * It is not nice to have the full Nsf_Param structure in nsf.h (required for Nsf_methodDefinition in the c code generator) @@ -3392,6 +3381,7 @@ no redefined-protection on those. Since the script does not know, on which class|object these are defined one cannot make assumption on these. Problem? + - The structure of the script body requires currently that "class|object ?-per-object?" is inserted at the 1nd pos. This is not sufficient, if we would like to test in this Index: generic/nsf.c =================================================================== diff -u -r5ac6229f27005543dfe6bbc7f76356195dedbe4d -r7b09de6f9ec1cc5caf39751fa4f23c62365e8dfe --- generic/nsf.c (.../nsf.c) (revision 5ac6229f27005543dfe6bbc7f76356195dedbe4d) +++ generic/nsf.c (.../nsf.c) (revision 7b09de6f9ec1cc5caf39751fa4f23c62365e8dfe) @@ -53,10 +53,6 @@ # endif #endif -#ifdef NSF_MEM_COUNT -int nsfMemCountInterpCounter = 0; -#endif - #ifdef USE_TCL_STUBS # define Nsf_ExprObjCmd(clientData, interp, objc, objv) \ NsfCallCommand(interp, NSF_EXPR, objc, objv) @@ -130,6 +126,19 @@ } AliasCmdClientData; /* + * When NSF_MEM_COUNT is set, we want to trace as well the mem-count frees + * associated with the interp. Therefore, we need in this case a special + * client data structure. + */ +#ifdef NSF_MEM_COUNT +typedef struct NsfNamespaceClientData { + NsfObject *object; + Tcl_Namespace *nsPtr; + Tcl_Interp *interp; +} NsfNamespaceClientData; +#endif + +/* * Argv parsing specific definitions */ @@ -221,7 +230,7 @@ static Tcl_Obj *NameInNamespaceObj(Tcl_Interp *interp, CONST char *name, Tcl_Namespace *ns); static Tcl_Namespace *CallingNameSpace(Tcl_Interp *interp); NSF_INLINE static Tcl_Command NSFindCommand(Tcl_Interp *interp, CONST char *name); -static Tcl_Namespace *NSGetFreshNamespace(Tcl_Interp *interp, ClientData clientData, +static Tcl_Namespace *NSGetFreshNamespace(Tcl_Interp *interp, NsfObject *object, CONST char *name); static Tcl_Namespace *RequireObjNamespace(Tcl_Interp *interp, NsfObject *object); static int NSDeleteCmd(Tcl_Interp *interp, Tcl_Namespace *nsPtr, CONST char *methodName); @@ -3923,16 +3932,31 @@ } } - static void NSNamespaceDeleteProc(ClientData clientData) { - /* dummy for ns identification by pointer comparison */ +#ifdef NSF_MEM_COUNT + NsfNamespaceClientData *nsClientData = (NsfNamespaceClientData *)clientData; + NsfObject *object; + + assert(clientData); + /*fprintf(stderr, "NSNamespaceDeleteProc cd %p\n", clientData); + fprintf(stderr, "... nsPtr %p name '%s'\n", nsClientData->nsPtr, nsClientData->nsPtr->fullName);*/ + + object = nsClientData->object; + INTERP_MEMBER_GET(nsClientData) + + ckfree((char *)nsClientData); +#else NsfObject *object = (NsfObject *) clientData; +#endif + + assert(object); + /*fprintf(stderr, "namespacedeleteproc obj=%p ns=%p\n", clientData, object ? object->nsPtr : NULL);*/ - if (object) { - object->nsPtr = NULL; - } + + MEM_COUNT_FREE("NSNamespace", object->nsPtr); + object->nsPtr = NULL; } void @@ -3959,7 +3983,7 @@ /*fprintf(stderr, "to %d. \n", ((Namespace *)nsPtr)->activationCount);*/ - MEM_COUNT_FREE("TclNamespace", nsPtr); + //MEM_COUNT_FREE("TclNamespace", nsPtr); if (Tcl_Namespace_deleteProc(nsPtr)) { /*fprintf(stderr, "calling deteteNamespace %s\n", nsPtr->fullName);*/ Tcl_DeleteNamespace(nsPtr); @@ -4013,25 +4037,44 @@ *---------------------------------------------------------------------- */ static Tcl_Namespace* -NSGetFreshNamespace(Tcl_Interp *interp, ClientData clientData, CONST char *name) { +NSGetFreshNamespace(Tcl_Interp *interp, NsfObject *object, CONST char *name) { Namespace *dummy1Ptr, *dummy2Ptr, *nsPtr; const char *dummy; TclGetNamespaceForQualName(interp, name, NULL, TCL_FIND_ONLY_NS|TCL_CREATE_NS_IF_UNKNOWN, &nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy); if (nsPtr->deleteProc != NSNamespaceDeleteProc) { - /* reuse the namespace */ + /* + * Avoid hijacking a namespace with different client data + */ if (nsPtr->deleteProc || nsPtr->clientData) { Tcl_Panic("Namespace '%s' exists already with delProc %p and clientData %p; " "Can only convert a plain Tcl namespace into an nsf namespace, my delete Proc %p", name, nsPtr->deleteProc, nsPtr->clientData, NSNamespaceDeleteProc); } - nsPtr->clientData = clientData; - nsPtr->deleteProc = (Tcl_NamespaceDeleteProc *)NSNamespaceDeleteProc; + + { +#ifdef NSF_MEM_COUNT + NsfNamespaceClientData *nsClientData = (NsfNamespaceClientData *)ckalloc(sizeof(NsfNamespaceClientData)); + + nsClientData->object = object; + nsClientData->nsPtr = (Tcl_Namespace *)nsPtr; + INTERP_MEMBER_SET(nsClientData, interp) + nsPtr->clientData = nsClientData; + + /*fprintf(stderr, "Adding NsfNamespaceClientData nsPtr %p cd %p name '%s'\n", + nsPtr, nsClientData, nsPtr->fullName);*/ +#else + nsPtr->clientData = object; +#endif + nsPtr->deleteProc = (Tcl_NamespaceDeleteProc *)NSNamespaceDeleteProc; + } + MEM_COUNT_ALLOC("NSNamespace", nsPtr); + } else { + fprintf(stderr, "NSGetFreshNamespace: reusing namespace %p %s\n", nsPtr, nsPtr->fullName); } - MEM_COUNT_ALLOC("TclNamespace", nsPtr); return (Tcl_Namespace *)nsPtr; } @@ -13317,7 +13360,6 @@ /*fprintf(stderr, "primitive cdestroy calls deletenamespace for obj %p, nsPtr %p flags %.6x\n", cl, saved, ((Namespace *)saved)->flags);*/ - saved->clientData = NULL; Nsf_DeleteNamespace(interp, saved); /*fprintf(stderr, "primitive cdestroy %p DONE\n", cl);*/ return; @@ -13339,7 +13381,7 @@ RUNTIME_STATE(interp)->NsfClassesNS, 0) != TCL_OK) { return; } - nsPtr = NSGetFreshNamespace(interp, cl, name); + nsPtr = NSGetFreshNamespace(interp, &cl->object, name); Tcl_PopCallFrame(interp); CleanupInitClass(interp, cl, nsPtr, 0, 0); @@ -16966,9 +17008,6 @@ if (Nsf_Init(slave) == TCL_ERROR) { return TCL_ERROR; } -#ifdef NSF_MEM_COUNT - nsfMemCountInterpCounter++; -#endif } return TCL_OK; }