Index: TODO =================================================================== diff -u -r7d1e68dd44eb6cddb6755e335e1070bb7be2e6f8 -r3b654bd0096ee0be729cbdefa63c0d981a708828 --- TODO (.../TODO) (revision 7d1e68dd44eb6cddb6755e335e1070bb7be2e6f8) +++ TODO (.../TODO) (revision 3b654bd0096ee0be729cbdefa63c0d981a708828) @@ -3574,9 +3574,14 @@ - moved methodEpochCounters from global vars to the interp state to improve resue in multi threaded apps - separated objectMethodEpoch and instanceMethodEpoch - - bumped version number to 2.0a2 + - bump version number to 2.0a2 +nsf.c: + - new cmd for debugging: nsf::__db_show_obj + - added MethodDupInternalRep() and FlagDupInternalRep() + since they appear to be required in Tcl 8.6b2. + TODO: - unknown arg handler must find a way to aviod method deletions or redefinitions or to recover from these gracefully Index: generic/nsf.c =================================================================== diff -u -r7d1e68dd44eb6cddb6755e335e1070bb7be2e6f8 -r3b654bd0096ee0be729cbdefa63c0d981a708828 --- generic/nsf.c (.../nsf.c) (revision 7d1e68dd44eb6cddb6755e335e1070bb7be2e6f8) +++ generic/nsf.c (.../nsf.c) (revision 3b654bd0096ee0be729cbdefa63c0d981a708828) @@ -9548,8 +9548,8 @@ } #if defined(METHOD_OBJECT_TRACE) - fprintf(stderr, "methodname %s type %p <%s>\n", - methodName, methodObj->typePtr, + fprintf(stderr, "method %p/%d '%s' type %p <%s>\n", + methodObj, methodObj->refCount, methodName, methodObj->typePtr, methodObj->typePtr ? methodObj->typePtr->name : ""); #endif @@ -9749,7 +9749,7 @@ cmd = mcPtr->cmd; //cl = mcPtr->cl; #if defined(METHOD_OBJECT_TRACE) - fprintf(stderr, "... reuse object method %p %s cmd %p cl %p %s\n", + fprintf(stderr, "... use internal rep method %p %s cmd %p cl %p %s\n", methodObj, ObjStr(methodObj), cmd, cl, cl ? ClassName(cl) : ObjectName(object)); #endif @@ -9786,10 +9786,10 @@ int nsfInstanceMethodEpoch = rst->instanceMethodEpoch; #if defined(METHOD_OBJECT_TRACE) - fprintf(stderr, "... method %p '%s' type? %d context? %d nsfMethodEpoch %d/%d\n", - methodObj, ObjStr(methodObj), + fprintf(stderr, "... method %p/%d '%s' type? %d context? %d nsfMethodEpoch %d => %d\n", + methodObj, methodObj->refCount, ObjStr(methodObj), methodObj->typePtr == &NsfInstanceMethodObjType, - methodObj->typePtr == &NsfInstanceMethodObjType ? currentClass : 0, + methodObj->typePtr == &NsfInstanceMethodObjType ? mcPtr->context == currentClass : 0, methodObj->typePtr == &NsfInstanceMethodObjType ? mcPtr->methodEpoch : 0, nsfInstanceMethodEpoch ); #endif @@ -9802,7 +9802,7 @@ cmd = mcPtr->cmd; cl = mcPtr->cl; #if defined(METHOD_OBJECT_TRACE) - fprintf(stderr, "... reuse instance method %p %s cmd %p cl %p %s\n", + fprintf(stderr, "... use internal rep method %p %s cmd %p cl %p %s\n", methodObj, ObjStr(methodObj), cmd, cl, cl ? ClassName(cl) : ObjectName(object)); #endif @@ -9823,7 +9823,6 @@ } else { cl = SearchPLMethod(currentClass->order, methodName, &cmd, NSF_CMD_CALL_PRIVATE_METHOD); } - NsfMethodObjSet(interp, methodObj, &NsfInstanceMethodObjType, currentClass, nsfInstanceMethodEpoch, cmd, cl, flags); @@ -15861,7 +15860,7 @@ NsfFlag *flagPtr = argumentObj->internalRep.twoPtrValue.ptr1; #if defined(PARSE_TRACE_FULL) - fprintf(stderr, "... arg %p %s expect nonpos arg in block %s isFlag %d sig %d serial %d (%d/%d)\n", + fprintf(stderr, "... arg %p %s expect nonpos arg in block %s isFlag %d sig %d serial %d (%d => %d)\n", argumentObj, ObjStr(argumentObj), currentParamPtr->name, argumentObj->typePtr == &NsfFlagObjType, argumentObj->typePtr == &NsfFlagObjType ? flagPtr->signature == paramPtr : 0, @@ -17415,6 +17414,34 @@ } /* +cmd __db_show_obj NsfDebugShowObj { + {-argName "obj" -required 1 -type tclobj} +} +*/ +static int +NsfDebugShowObj(Tcl_Interp *interp, Tcl_Obj *objPtr) { + + fprintf(stderr, "*** obj %p refCount %d type <%s>\n", + objPtr, objPtr->refCount, + objPtr->typePtr ? objPtr->typePtr->name : ""); + + if (objPtr->typePtr == &NsfObjectMethodObjType + || objPtr->typePtr == &NsfInstanceMethodObjType + ) { + NsfMethodContext *mcPtr = objPtr->internalRep.twoPtrValue.ptr1; + int currentMethodEpoch = objPtr->typePtr == &NsfObjectMethodObjType ? + RUNTIME_STATE(interp)->objectMethodEpoch : + RUNTIME_STATE(interp)->instanceMethodEpoch; + + fprintf(stderr, " method epoch %d max %d flags %.6x\n", + mcPtr->methodEpoch, currentMethodEpoch, mcPtr->flags); + + assert( currentMethodEpoch >= mcPtr->methodEpoch); + } + return TCL_OK; +} + +/* cmd __db_show_stack NsfShowStackCmd {} */ static int @@ -23119,7 +23146,6 @@ Nsf_OT_doubleType = Tcl_GetObjType("double"); assert(Nsf_OT_doubleType); - NsfMutexUnlock(&initMutex); Index: generic/nsfAPI.decls =================================================================== diff -u -r95c4d29515cfda9283b406ba7a7ac1dd029de8c9 -r3b654bd0096ee0be729cbdefa63c0d981a708828 --- generic/nsfAPI.decls (.../nsfAPI.decls) (revision 95c4d29515cfda9283b406ba7a7ac1dd029de8c9) +++ generic/nsfAPI.decls (.../nsfAPI.decls) (revision 3b654bd0096ee0be729cbdefa63c0d981a708828) @@ -19,6 +19,9 @@ cmd __db_compile_epoch NsfDebugCompileEpoch {} cmd __db_run_assertions NsfDebugRunAssertionsCmd {} cmd __db_show_stack NsfShowStackCmd {} +cmd __db_show_obj NsfDebugShowObj { + {-argName "obj" -required 1 -type tclobj} +} cmd __profile_clear NsfProfileClearDataStub {} cmd __profile_get NsfProfileGetDataStub {} cmd __unset_unknown_args NsfUnsetUnknownArgsCmd {} Index: generic/nsfAPI.h =================================================================== diff -u -r2ba521e3dfbb1294908b51ed8e13dab5adc3ca03 -r3b654bd0096ee0be729cbdefa63c0d981a708828 --- generic/nsfAPI.h (.../nsfAPI.h) (revision 2ba521e3dfbb1294908b51ed8e13dab5adc3ca03) +++ generic/nsfAPI.h (.../nsfAPI.h) (revision 3b654bd0096ee0be729cbdefa63c0d981a708828) @@ -237,6 +237,7 @@ static int NsfCurrentCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfDebugCompileEpochStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfDebugRunAssertionsCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); +static int NsfDebugShowObjStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfDirectDispatchCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfDispatchCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); static int NsfFinalizeCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv []); @@ -334,6 +335,7 @@ static int NsfCurrentCmd(Tcl_Interp *interp, int currentoption); static int NsfDebugCompileEpoch(Tcl_Interp *interp); static int NsfDebugRunAssertionsCmd(Tcl_Interp *interp); +static int NsfDebugShowObj(Tcl_Interp *interp, Tcl_Obj *obj); static int NsfDirectDispatchCmd(Tcl_Interp *interp, NsfObject *object, int withFrame, Tcl_Obj *command, int nobjc, Tcl_Obj *CONST nobjv[]); static int NsfDispatchCmd(Tcl_Interp *interp, NsfObject *object, int withIntrinsic, int withSystem, Tcl_Obj *command, int nobjc, Tcl_Obj *CONST nobjv[]); static int NsfFinalizeCmd(Tcl_Interp *interp, int withKeepvars); @@ -432,6 +434,7 @@ NsfCurrentCmdIdx, NsfDebugCompileEpochIdx, NsfDebugRunAssertionsCmdIdx, + NsfDebugShowObjIdx, NsfDirectDispatchCmdIdx, NsfDispatchCmdIdx, NsfFinalizeCmdIdx, @@ -1071,6 +1074,22 @@ } static int +NsfDebugShowObjStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { + (void)clientData; + + + + if (objc != 2) { + return NsfArgumentError(interp, "wrong # of arguments:", + method_definitions[NsfDebugShowObjIdx].paramDefs, + NULL, objv[0]); + } + + return NsfDebugShowObj(interp, objc == 2 ? objv[1] : NULL); + +} + +static int NsfDirectDispatchCmdStub(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { ParseContext pc; (void)clientData; @@ -2481,6 +2500,9 @@ {"::nsf::__db_run_assertions", NsfDebugRunAssertionsCmdStub, 0, { {NULL, 0, 0, NULL, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} }, +{"::nsf::__db_show_obj", NsfDebugShowObjStub, 1, { + {"obj", NSF_ARG_REQUIRED, 1, Nsf_ConvertToTclobj, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}} +}, {"::nsf::directdispatch", NsfDirectDispatchCmdStub, 4, { {"object", NSF_ARG_REQUIRED, 1, Nsf_ConvertToObject, NULL,NULL,"object",NULL,NULL,NULL,NULL,NULL}, {"-frame", 0|NSF_ARG_IS_ENUMERATION, 1, ConvertToFrame, NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL}, Index: generic/nsfInt.h =================================================================== diff -u -r7d1e68dd44eb6cddb6755e335e1070bb7be2e6f8 -r3b654bd0096ee0be729cbdefa63c0d981a708828 --- generic/nsfInt.h (.../nsfInt.h) (revision 7d1e68dd44eb6cddb6755e335e1070bb7be2e6f8) +++ generic/nsfInt.h (.../nsfInt.h) (revision 3b654bd0096ee0be729cbdefa63c0d981a708828) @@ -931,7 +931,7 @@ typedef struct { CONST Nsf_Param *signature; int serial; - Nsf_Param *paramPtr; + Nsf_Param CONST *paramPtr; Tcl_Obj *payload; int flags; } NsfFlag; Index: generic/nsfObj.c =================================================================== diff -u -r877c1e7d364b91e0a1d501738dfbb7b9dcb7d5ac -r3b654bd0096ee0be729cbdefa63c0d981a708828 --- generic/nsfObj.c (.../nsfObj.c) (revision 877c1e7d364b91e0a1d501738dfbb7b9dcb7d5ac) +++ generic/nsfObj.c (.../nsfObj.c) (revision 3b654bd0096ee0be729cbdefa63c0d981a708828) @@ -27,18 +27,19 @@ */ static Tcl_FreeInternalRepProc MethodFreeInternalRep; +static Tcl_DupInternalRepProc MethodDupInternalRep; Tcl_ObjType NsfInstanceMethodObjType = { "nsfInstanceMethod", /* name */ MethodFreeInternalRep, /* freeIntRepProc */ - NULL, /* dupIntRepProc */ + MethodDupInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL /* setFromAnyProc */ }; Tcl_ObjType NsfObjectMethodObjType = { "nsfObjectMethod", /* name */ MethodFreeInternalRep, /* freeIntRepProc */ - NULL, /* dupIntRepProc */ + MethodDupInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL /* setFromAnyProc */ }; @@ -54,18 +55,41 @@ NsfMethodContext *mcPtr = (NsfMethodContext *)objPtr->internalRep.twoPtrValue.ptr1; if (mcPtr != NULL) { - - /*fprintf(stderr, "MethodFreeInternalRep %p flagPtr %p serial (%d) payload %p\n", - objPtr, flagPtr, flagPtr->serial, flagPtr->payload);*/ - +#if defined(METHOD_OBJECT_TRACE) + fprintf(stderr, "MethodFreeInternalRep %p methodContext %p methodEpoch %d type <%s>\n", + objPtr, mcPtr, mcPtr->methodEpoch, + objPtr->typePtr ? objPtr->typePtr->name : "none"); +#endif /* * ... and free structure */ FREE(NsfMethodContext, mcPtr); objPtr->internalRep.twoPtrValue.ptr1 = NULL; // TODO: needed? + objPtr->typePtr = NULL; } } +/* + * dupIntRepProc + */ +static void +MethodDupInternalRep( + Tcl_Obj *srcPtr, + Tcl_Obj *dstPtr) +{ + register NsfMethodContext *srcMcPtr = srcPtr->internalRep.twoPtrValue.ptr1, *dstMcPtr; + +#if defined(METHOD_OBJECT_TRACE) + fprintf(stderr, "MethodDupInternalRep src %p dst %p\n", srcPtr, dstPtr); +#endif + + dstMcPtr = NEW(NsfMethodContext); + memcpy(dstMcPtr, srcMcPtr, sizeof(NsfMethodContext)); + + dstPtr->typePtr = srcPtr->typePtr; + dstPtr->internalRep.twoPtrValue.ptr1 = dstMcPtr; +} + /* *---------------------------------------------------------------------- * @@ -105,12 +129,16 @@ objPtr->internalRep.twoPtrValue.ptr1 = (void *)mcPtr; objPtr->internalRep.twoPtrValue.ptr2 = NULL; objPtr->typePtr = objectType; +#if defined(METHOD_OBJECT_TRACE) + fprintf(stderr, "alloc %p methodContext %p methodEpoch %d type <%s> %s\n", + objPtr, mcPtr, methodEpoch, objectType->name, ObjStr(objPtr), objPtr->refCount); +#endif } else { mcPtr = (NsfMethodContext *)objPtr->internalRep.twoPtrValue.ptr1; - - /*fprintf(stderr, "... NsfMethodObjSet %p reuses interal rep, serial (%d/%d)\n", - objPtr, mcPtr->methodEpoch, methodEpoch);*/ - +#if defined(METHOD_OBJECT_TRACE) + fprintf(stderr, "... NsfMethodObjSet %p reuses interal rep, serial (%d/%d) refCount %d\n", + objPtr, mcPtr->methodEpoch, methodEpoch); +#endif } assert(mcPtr); @@ -139,11 +167,12 @@ */ static Tcl_FreeInternalRepProc FlagFreeInternalRep; +static Tcl_DupInternalRepProc FlagDupInternalRep; Tcl_ObjType NsfFlagObjType = { "nsfFlag", /* name */ FlagFreeInternalRep, /* freeIntRepProc */ - NULL, /* dupIntRepProc */ + FlagDupInternalRep, /* dupIntRepProc */ NULL, /* updateStringProc */ NULL /* setFromAnyProc */ }; @@ -153,10 +182,10 @@ */ static void FlagFreeInternalRep( - register Tcl_Obj *objPtr) /* Tcl_Obj structure object with internal - * representation to free. */ + Tcl_Obj *objPtr) /* Tcl_Obj structure object with internal + * representation to free. */ { - NsfFlag *flagPtr = (NsfFlag *)objPtr->internalRep.twoPtrValue.ptr1; + register NsfFlag *flagPtr = (NsfFlag *)objPtr->internalRep.twoPtrValue.ptr1; if (flagPtr != NULL) { @@ -176,6 +205,27 @@ } } +/* + * dupIntRepProc + */ +static void +FlagDupInternalRep( + Tcl_Obj *srcObjPtr, + Tcl_Obj *dstObjPtr) +{ + register NsfFlag *srcPtr = (NsfFlag *)srcObjPtr->internalRep.twoPtrValue.ptr1, *dstPtr; + +#if defined(METHOD_OBJECT_TRACE) + fprintf(stderr, "FlagDupInternalRepx src %p dst %p\n", srcObjPtr, dstObjPtr); +#endif + + dstPtr = NEW(NsfFlag); + memcpy(dstPtr, srcPtr, sizeof(NsfFlag)); + + srcObjPtr->typePtr = srcObjPtr->typePtr; + srcObjPtr->internalRep.twoPtrValue.ptr1 = dstPtr; +} + /* *---------------------------------------------------------------------- * Index: tests/methods.test =================================================================== diff -u -rd8dcbc3ba475a4617d540b4499a9c41e8bf81b07 -r3b654bd0096ee0be729cbdefa63c0d981a708828 --- tests/methods.test (.../methods.test) (revision d8dcbc3ba475a4617d540b4499a9c41e8bf81b07) +++ tests/methods.test (.../methods.test) (revision 3b654bd0096ee0be729cbdefa63c0d981a708828) @@ -340,7 +340,7 @@ ? {C info methods} "a" ? {C class info methods} x ? {c1 a b} {expected integer but got "b" for parameter "a"} - + set s(C) [C serialize] set s(c1) [c1 serialize] @@ -682,7 +682,7 @@ # simple speed tests # ensemble unknown tests are in submethods.test # -nx::Test parameter count 100000 +nx::Test parameter count 1000 nx::Test case speed-dispatch { #