Index: TODO =================================================================== diff -u -r2b8b3b10404d6e67ce420e8e2a2fda57991d7c5f -r65ec5477000f631789c0809b8a832f45e1b634a4 --- TODO (.../TODO) (revision 2b8b3b10404d6e67ce420e8e2a2fda57991d7c5f) +++ TODO (.../TODO) (revision 65ec5477000f631789c0809b8a832f45e1b634a4) @@ -2548,6 +2548,12 @@ * make sure to create the cmds for objects with Tcl_NRCreateCommand() to choose trampoline-path in the trunk version of Tcl +* The newest trunk version of Tcl in fossil has TclStackFree() and + TclStackAlloc() removed We had to substitute this + functions. Unfortunately, the lifetime of the strack structures has + changed, so we had shuffle some interals around. + + TODO: - maybe the destructor of a slot should remove the setter/forwarder - how to delete attributes? Index: generic/nsf.c =================================================================== diff -u -r2b8b3b10404d6e67ce420e8e2a2fda57991d7c5f -r65ec5477000f631789c0809b8a832f45e1b634a4 --- generic/nsf.c (.../nsf.c) (revision 2b8b3b10404d6e67ce420e8e2a2fda57991d7c5f) +++ generic/nsf.c (.../nsf.c) (revision 65ec5477000f631789c0809b8a832f45e1b634a4) @@ -7492,10 +7492,11 @@ NsfObject *object = cscPtr->self; NsfObjectOpt *opt = object->opt; #endif - /*fprintf(stderr, "ProcMethodDispatchFinalize %s.%s flags %.6x isNRE %d\n", - ObjectName(object), methodName - cscPtr->flags, (cscPtr->flags & NSF_CSC_CALL_IS_NRE));*/ + /*fprintf(stderr, "ProcMethodDispatchFinalize %s flags %.6x isNRE %d\n", + ObjectName(object), + cscPtr->flags, (cscPtr->flags & NSF_CSC_CALL_IS_NRE));*/ + #if defined(NSF_WITH_ASSERTIONS) if (opt && object->teardown && (opt->checkoptions & CHECK_POST)) { int rc; @@ -7545,10 +7546,10 @@ CONST char *methodName, NsfObject *object, NsfClass *cl, Tcl_Command cmdPtr, NsfCallStackContent *cscPtr) { int result, releasePc = 0; + NsfParamDefs *paramDefs; #if defined(NSF_WITH_ASSERTIONS) NsfObjectOpt *opt = object->opt; #endif - NsfParamDefs *paramDefs; #if defined(NRE) ParseContext *pcPtr = NULL; #else @@ -7628,9 +7629,6 @@ */ paramDefs = ParamDefsGet(cmdPtr); - /*Tcl_Command_deleteProc(cmdPtr) == NsfProcDeleteProc ? - ((NsfProcContext *)Tcl_Command_deleteData(cmdPtr))->paramDefs : NULL;*/ - if (paramDefs && paramDefs->paramsPtr) { #if defined(NRE) pcPtr = (ParseContext *) NsfTclStackAlloc(interp, sizeof(ParseContext), "parse context"); @@ -7774,7 +7772,8 @@ static int MethodDispatchCsc(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], - NsfCallStackContent *cscPtr, CONST char *methodName) { + NsfCallStackContent *cscPtr, CONST char *methodName, + int *validCscPtr) { Tcl_Command cmd = cscPtr->cmdPtr; NsfObject *object = cscPtr->self; ClientData cp = Tcl_Command_objClientData(cmd); @@ -7792,33 +7791,47 @@ methodName, cmd, cp, objc);*/ assert(object->teardown); + /* + * The default assumption is that the CscPtr is valid after this function + * finishes. + */ + *validCscPtr = 1; + if (proc == TclObjInterpProc) { #if defined(NRE) NRE_callback *rootPtr = TOP_CB(interp); + int isImmediate = (cscPtr->flags & NSF_CSC_IMMEDIATE); +# if defined(NRE_CALLBACK_TRACE) + NsfClass *cl = cscPtr->cl; +# endif #endif /* * The cmd is a scripted method */ result = ProcMethodDispatch(cp, interp, objc, objv, methodName, object, cscPtr->cl, cmd, cscPtr); - #if defined(NRE) - if ((cscPtr->flags & NSF_CSC_IMMEDIATE)) { + /* + * In the NRE case, there is no trust in the cscPtr anymore, it might be already gone. + */ + *validCscPtr = 0; + + if (isImmediate) { # if defined(NRE_CALLBACK_TRACE) fprintf(stderr, ".... manual run callbacks rootPtr = %p, result %d methodName %s.%s\n", - rootPtr, result, cscPtr->cl?ClassName(cscPtr->cl):"NULL", methodName); + rootPtr, result, cl?ClassName(cl):"NULL", methodName); # endif result = NsfNRRunCallbacks(interp, result, rootPtr); } else { # if defined(NRE_CALLBACK_TRACE) fprintf(stderr, ".... don't run callbacks rootPtr = %p, result %d methodName %s.%s\n", - rootPtr, result, cscPtr->cl?ClassName(cscPtr->cl):"NULL", methodName); + rootPtr, result, cl?ClassName(cl):"NULL", methodName); # endif } #endif /* - * scriped cmd done + * scripted method done */ return result; @@ -8006,7 +8019,7 @@ Tcl_Command cmd, NsfObject *object, NsfClass *cl, CONST char *methodName, int frameType, int flags) { NsfCallStackContent csc, *cscPtr; - int result; + int result, validCscPtr; assert (object->teardown); assert (cmd); @@ -8024,10 +8037,11 @@ CscInit(cscPtr, object, cl, cmd, frameType, flags, methodName); result = MethodDispatchCsc(clientData, interp, objc, objv, - cscPtr, methodName); + cscPtr, methodName, &validCscPtr); #if defined(NRE) - if ((cscPtr->flags & NSF_CSC_CALL_IS_NRE) == 0) { + if (validCscPtr) { + //fprintf(stderr, "forced finalize 2 cscPtr %p\n", cscPtr); CscListRemove(interp, cscPtr); CscFinish(interp, cscPtr, result, "csc cleanup"); } @@ -8146,8 +8160,9 @@ *---------------------------------------------------------------------- */ NSF_INLINE static int -ObjectDispatch(ClientData clientData, Tcl_Interp *interp, int objc, - Tcl_Obj *CONST objv[], int flags) { +ObjectDispatch(ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[], + int flags) { register NsfObject *object = (NsfObject*)clientData; int result = TCL_OK, objflags, shift, frameType = NSF_CSC_TYPE_PLAIN; @@ -8156,6 +8171,7 @@ Tcl_Command cmd = NULL; Tcl_Obj *cmdName = object->cmdName, *methodObj, *cmdObj; NsfCallStackContent csc, *cscPtr = NULL; + int validCscPtr; if (flags & NSF_CM_NO_SHIFT) { shift = 0; @@ -8359,7 +8375,7 @@ } result = MethodDispatchCsc(clientData, interp, objc-shift, objv+shift, - cscPtr, methodName); + cscPtr, methodName, &validCscPtr); if (result == TCL_ERROR) { /*fprintf(stderr, "Call ErrInProc cl = %p, cmd %p, flags %.6x\n", @@ -8372,9 +8388,9 @@ /* * The method to be dispatched is unknown */ + validCscPtr = 1; cscPtr = CscAlloc(interp, &csc, cmd); CscInit(cscPtr, object, cl, cmd, frameType, flags, methodName); - cscPtr->flags |= NSF_CSC_METHOD_IS_UNKNOWN; if ((flags & NSF_CM_NO_UNKNOWN)) { cscPtr->flags |= NSF_CSC_CALL_NO_UNKNOWN; @@ -8384,12 +8400,13 @@ } exit_object_dispatch: - /* - * In every situation, we have a cscPtr containing all context information - */ - assert(cscPtr); + if (validCscPtr) { + /* + * In every situation, we have a cscPtr containing all context information + */ + assert(cscPtr); - if (!(cscPtr->flags & NSF_CSC_CALL_IS_NRE)) { + //fprintf(stderr, "forced finalize 1 cscPtr %p objc %d %p\n", cscPtr, cscPtr->objc, cscPtr->objv); result = ObjectDispatchFinalize(interp, cscPtr, result /*, "immediate" , methodName*/); CscListRemove(interp, cscPtr); CscFinish(interp, cscPtr, result, "non-scripted finalize"); @@ -8543,7 +8560,7 @@ delegator?ObjStr(objv[1]) : NULL, methodName);*/ - if (unknownObj && methodObj != unknownObj && (flags & NSF_CSC_CALL_NO_UNKNOWN) == 0) { + if (unknownObj && methodObj != unknownObj && (flags & NSF_CSC_CALL_NO_UNKNOWN) == 0) { /* * back off and try unknown; */ @@ -8584,7 +8601,7 @@ ObjStr(methodObj), ObjectName(object), 1, ObjStr(objv[1]));*/ result = NsfPrintError(interp, "%s: unable to dispatch method '%s'", - ObjectName(object), MethodName(objv[1])); + ObjectName(object), /*methodName*/ objc > 1 ? MethodName(objv[1]) : methodName); } return result; Index: generic/nsf.h =================================================================== diff -u -r1c4cb273089674161189c6d19deae17fc56334b3 -r65ec5477000f631789c0809b8a832f45e1b634a4 --- generic/nsf.h (.../nsf.h) (revision 1c4cb273089674161189c6d19deae17fc56334b3) +++ generic/nsf.h (.../nsf.h) (revision 65ec5477000f631789c0809b8a832f45e1b634a4) @@ -155,7 +155,7 @@ /*fprintf(stderr, "NsfCleanupObject %p %s\n",object,string);*/ \ NsfCleanupObject_(object) # define CscFinish(interp,cscPtr,retCode,string) \ - /*fprintf(stderr, "CscFinish %p %s\n",cscPtr,string);*/ \ + /*fprintf(stderr, "CscFinish %p %s\n",cscPtr,string); */ \ NSF_DTRACE_METHOD_RETURN_PROBE(cscPtr,retCode); \ CscFinish_(interp, cscPtr) #else Index: generic/nsfInt.h =================================================================== diff -u -rc2baf6c2b4e9a88c3580bdadf5e735dfe96d7f10 -r65ec5477000f631789c0809b8a832f45e1b634a4 --- generic/nsfInt.h (.../nsfInt.h) (revision c2baf6c2b4e9a88c3580bdadf5e735dfe96d7f10) +++ generic/nsfInt.h (.../nsfInt.h) (revision 65ec5477000f631789c0809b8a832f45e1b634a4) @@ -726,6 +726,8 @@ #if defined(NRE_SANE_PATCH) # define NsfNRRunCallbacks(interp, result, rootPtr) TclNRRunCallbacks(interp, result, rootPtr) +# define TclStackFree(interp, ptr) ckfree(ptr) +# define TclStackAlloc(interp, size) ckalloc(size) #else # define NsfNRRunCallbacks(interp, result, rootPtr) TclNRRunCallbacks(interp, result, rootPtr, 0) # define TEOV_callback NRE_callback Index: generic/nsfStack.c =================================================================== diff -u -r32b1b0210fbe6c5794d9bfe6def1fda904254ea6 -r65ec5477000f631789c0809b8a832f45e1b634a4 --- generic/nsfStack.c (.../nsfStack.c) (revision 32b1b0210fbe6c5794d9bfe6def1fda904254ea6) +++ generic/nsfStack.c (.../nsfStack.c) (revision 65ec5477000f631789c0809b8a832f45e1b634a4) @@ -834,9 +834,9 @@ * Track object activations */ object->activationCount ++; - /*fprintf(stderr, "CscInit %s method %s activationCount ++ (%s) --> %d\n", - msg, cmd ? Tcl_GetCommandName(object->teardown,cmd) : "UNK", - ObjectName(object), object->activationCount);*/ + /*fprintf(stderr, "CscInit %p method %s activationCount ++ (%s) --> %d (cl %p)\n", + cscPtr, cmd ? Tcl_GetCommandName(object->teardown,cmd) : "UNK", + ObjectName(object), object->activationCount, cl);*/ /* * Track class activations */ @@ -900,7 +900,7 @@ object = cscPtr->self; /*fprintf(stderr, "CscFinish %p object %p %s flags %.6x cmdPtr %p\n",cscPtr, - object, ObjectName(object), flags, cscPtr->cmdPtr); */ + object, ObjectName(object), cscPtr->flags, cscPtr->cmdPtr); */ /* * In the cases, where an cmd was provided, we tracked in init the