Index: TODO =================================================================== diff -u -r4c9e3b2b545a49698aa2284cc8dc5d5bb2719703 -rabc6afbec5bf2984e6480f32f91829b54c1d8c91 --- TODO (.../TODO) (revision 4c9e3b2b545a49698aa2284cc8dc5d5bb2719703) +++ TODO (.../TODO) (revision abc6afbec5bf2984e6480f32f91829b54c1d8c91) @@ -4211,9 +4211,13 @@ nsf.c: - fix potential bad interaction between per-object mixins and per-class caching of object-parameters +- first draft of per-object parameter caching (for + per-object-mixins and per-object properties). ======================================================================== TODO: +- invalidation of per-object parameter cache for mixins and + deletion/adding of per-object slots - regression tests for "/obj/ info lookup parameter ...." - handling of "required" in reconfigure (see parameter-object-mixin-dependency in parameters.test) @@ -4231,6 +4235,7 @@ should be ? {o __alloc x} {method alloc not dispatched on valid class} +- recreate for slots - document "private property" - document new setable object properties perobjectdispatch and keepcallerself Index: generic/nsf.c =================================================================== diff -u -r4c9e3b2b545a49698aa2284cc8dc5d5bb2719703 -rabc6afbec5bf2984e6480f32f91829b54c1d8c91 --- generic/nsf.c (.../nsf.c) (revision 4c9e3b2b545a49698aa2284cc8dc5d5bb2719703) +++ generic/nsf.c (.../nsf.c) (revision abc6afbec5bf2984e6480f32f91829b54c1d8c91) @@ -303,6 +303,7 @@ static int GetMatchObject(Tcl_Interp *interp, Tcl_Obj *patternObj, Tcl_Obj *origObj, NsfObject **matchObject, CONST char **pattern); static void NsfProcDeleteProc(ClientData clientData); +static int NsfInvalidateObjObjectParameterCmd(Tcl_Interp *interp, NsfObject *object); /* prototypes for alias management */ static int AliasDelete(Tcl_Interp *interp, Tcl_Obj *cmdName, CONST char *methodName, int withPer_object); @@ -14392,6 +14393,12 @@ opt->assertions = NULL; #endif +#if defined(PER_OBJECT_PARAMETER_CACHING) + if (object->opt->parsedParamPtr) { + NsfInvalidateObjObjectParameterCmd(interp, object); + } +#endif + if (!softrecreate) { /* * Remove this object from all per object mixin lists and clear the @@ -19188,14 +19195,33 @@ static int NsfInvalidateObjectParameterCmd(Tcl_Interp *interp, NsfClass *cl) { if (cl->parsedParamPtr) { + NsfClassParamPtrEpochIncr("NsfInvalidateObjectParameterCmd"); /* fprintf(stderr, " %s invalidate %p\n", ClassName(cl), cl->parsedParamPtr); */ ParsedParamFree(cl->parsedParamPtr); cl->parsedParamPtr = NULL; } return TCL_OK; } +// TODO move me, rename me /* +cmd invalidateobjobjectparameter NsfInvalidateObjObjectParameterCmd { + {-argName "object" -type object} +} +*/ +static int +NsfInvalidateObjObjectParameterCmd(Tcl_Interp *interp, NsfObject *object) { +#if defined(PER_OBJECT_PARAMETER_CACHING) + if (object->opt && object->opt->parsedParamPtr) { + /* fprintf(stderr, " %s invalidate %p\n", ObjectName(object), obj->opt->parsedParamPtr); */ + ParsedParamFree(object->opt->parsedParamPtr); + object->opt->parsedParamPtr = NULL; + } +#endif + return TCL_OK; +} + +/* cmd is NsfIsCmd { {-argName "-complain"} {-argName "constraint" -required 1 -type tclobj} @@ -21622,6 +21648,15 @@ parsedParamPtr->paramDefs = clParsedParamPtr->paramDefs; parsedParamPtr->possibleUnknowns = clParsedParamPtr->possibleUnknowns; result = TCL_OK; +#if defined(PER_OBJECT_PARAMETER_CACHING) + } else if (object->opt && object->opt->parsedParamPtr && + object->opt->classParamPtrEpoch == RUNTIME_STATE(interp)->classParamPtrEpoch) { + NsfParsedParam *objParsedParamPtr = object->opt->parsedParamPtr; + /*fprintf(stderr, "reuse obj param for obj %s paramPtr %p\n", ObjectName(object), objParsedParamPtr);*/ + parsedParamPtr->paramDefs = objParsedParamPtr->paramDefs; + parsedParamPtr->possibleUnknowns = objParsedParamPtr->possibleUnknowns; + result = TCL_OK; +#endif } else { /* * There is no parameter definition available, get a new one in @@ -21630,14 +21665,14 @@ Tcl_Obj *methodObj = NsfMethodObj(object, NSF_c_objectparameter_idx); if (methodObj) { - /*fprintf(stderr, "=== calling %s objectparameter\n", ClassName(class));*/ + /*fprintf(stderr, "calling %s objectparameter\n", ObjectName(object));*/ result = CallMethod(object, interp, methodObj, 2, 0, NSF_CM_IGNORE_PERMISSIONS|NSF_CSC_IMMEDIATE); if (likely(result == TCL_OK)) { rawConfArgs = Tcl_GetObjResult(interp); /*fprintf(stderr, ".... rawConfArgs for %s => '%s'\n", - ClassName(class), ObjStr(rawConfArgs));*/ + ObjectName(object), ObjStr(rawConfArgs));*/ INCR_REF_COUNT(rawConfArgs); /* @@ -21653,6 +21688,14 @@ ppDefPtr->possibleUnknowns = parsedParamPtr->possibleUnknowns; if (class) { class->parsedParamPtr = ppDefPtr; +#if defined(PER_OBJECT_PARAMETER_CACHING) + } else { + NsfObjectOpt *opt = NsfRequireObjectOpt(object); + opt->parsedParamPtr = ppDefPtr; + opt->classParamPtrEpoch = RUNTIME_STATE(interp)->classParamPtrEpoch; + /*fprintf(stderr, "set obj param for obj %s epoch %d ppDefPtr %p\n", + ObjectName(object), opt->classParamPtrEpoch, ppDefPtr);*/ +#endif } if (ppDefPtr->paramDefs) { ParamDefsRefCountIncr(ppDefPtr->paramDefs); Index: generic/nsf.h =================================================================== diff -u -r7495af656ca04a32826ecb0b6e207f886eaaa7f8 -rabc6afbec5bf2984e6480f32f91829b54c1d8c91 --- generic/nsf.h (.../nsf.h) (revision 7495af656ca04a32826ecb0b6e207f886eaaa7f8) +++ generic/nsf.h (.../nsf.h) (revision abc6afbec5bf2984e6480f32f91829b54c1d8c91) @@ -143,6 +143,8 @@ #define NSF_STACKCHECK 1 */ +// #define PER_OBJECT_PARAMETER_CACHING 1 + /* * Sanity checks and dependencies for optional compile flags */ Index: generic/nsfInt.h =================================================================== diff -u -r5d1617640ad71fd52b069f81cfcadbe4cbb6f2a2 -rabc6afbec5bf2984e6480f32f91829b54c1d8c91 --- generic/nsfInt.h (.../nsfInt.h) (revision 5d1617640ad71fd52b069f81cfcadbe4cbb6f2a2) +++ generic/nsfInt.h (.../nsfInt.h) (revision abc6afbec5bf2984e6480f32f91829b54c1d8c91) @@ -486,6 +486,10 @@ NsfCmdList *objFilters; NsfCmdList *objMixins; ClientData clientData; +#if defined(PER_OBJECT_PARAMETER_CACHING) + NsfParsedParam *parsedParamPtr; + int classParamPtrEpoch; +#endif CONST char *volatileVarName; short checkoptions; } NsfObjectOpt; @@ -781,6 +785,9 @@ Tcl_Command currentMixinCmdPtr; /* cmdPtr of currently active mixin, used for "info activemixin" */ int objectMethodEpoch; int instanceMethodEpoch; +#if defined(PER_OBJECT_PARAMETER_CACHING) + int classParamPtrEpoch; +#endif Tcl_Obj **methodObjNames; /* global objects of nsf */ struct NsfShadowTclCommandInfo *tclCommands; /* shadowed Tcl commands */ @@ -961,6 +968,12 @@ # define NsfObjectMethodEpochIncr(msg) RUNTIME_STATE(interp)->objectMethodEpoch++ #endif +#if defined(PER_OBJECT_PARAMETER_CACHING) +# define NsfClassParamPtrEpochIncr(msg) RUNTIME_STATE(interp)->classParamPtrEpoch++ +#else +# define NsfClassParamPtrEpochIncr(msg) +#endif + /* * NsfFlag type */