summaryrefslogtreecommitdiffstats
path: root/generic/tclNamesp.c
diff options
context:
space:
mode:
authorMiguel Sofer <miguel.sofer@gmail.com>2007-07-05 11:49:12 (GMT)
committerMiguel Sofer <miguel.sofer@gmail.com>2007-07-05 11:49:12 (GMT)
commit7ce3408e22a5d7aedd6e01a5fcdfaa2d6876cb37 (patch)
treef10d9c5f0790c77712ef5452f0dc8eda26315cd0 /generic/tclNamesp.c
parent56b81839c7271c23ed51776a7a922d3a49fce775 (diff)
downloadtcl-7ce3408e22a5d7aedd6e01a5fcdfaa2d6876cb37.zip
tcl-7ce3408e22a5d7aedd6e01a5fcdfaa2d6876cb37.tar.gz
tcl-7ce3408e22a5d7aedd6e01a5fcdfaa2d6876cb37.tar.bz2
* generic/tclNamesp.c (SetNsNameFromAny):
* generic/tclObj.c (SetCmdNameFromAny): Avoid unnecessary ckfree/ckalloc when the old structs can be reused.
Diffstat (limited to 'generic/tclNamesp.c')
-rw-r--r--generic/tclNamesp.c49
1 files changed, 28 insertions, 21 deletions
diff --git a/generic/tclNamesp.c b/generic/tclNamesp.c
index 8e25637..564be56 100644
--- a/generic/tclNamesp.c
+++ b/generic/tclNamesp.c
@@ -22,7 +22,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclNamesp.c,v 1.144 2007/07/04 23:56:58 msofer Exp $
+ * RCS: @(#) $Id: tclNamesp.c,v 1.145 2007/07/05 11:49:16 msofer Exp $
*/
#include "tclInt.h"
@@ -4819,29 +4819,45 @@ SetNsNameFromAny(
register ResolvedNsName *resNamePtr;
/*
- * Get the string representation. Make it up-to-date if necessary.
- */
-
- name = TclGetString(objPtr);
-
- /*
* Look for the namespace "name" in the current namespace. If there is an
* error parsing the (possibly qualified) name, return an error. If the
* namespace isn't found, we convert the object to an nsName object with a
* NULL ResolvedNsName* internal rep.
*/
+ name = TclGetString(objPtr);
TclGetNamespaceForQualName(interp, name, NULL, TCL_FIND_ONLY_NS,
&nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
/*
* If we found a namespace, then create a new ResolvedNsName structure
* that holds a reference to it.
+ *
+ * Free the old internalRep before setting the new one. Do this after
+ * getting the string rep to allow the conversion code (in particular,
+ * Tcl_GetStringFromObj) to use that old internalRep.
*/
- if (nsPtr != NULL) {
+ if (nsPtr) {
nsPtr->refCount++;
- resNamePtr = (ResolvedNsName *) ckalloc(sizeof(ResolvedNsName));
+ resNamePtr = (ResolvedNsName *) objPtr->internalRep.otherValuePtr;
+ if ((objPtr->typePtr == &tclNsNameType)
+ && resNamePtr && (resNamePtr->refCount == 1)) {
+ /*
+ * Reuse the old ResolvedNsName struct after freeing it
+ */
+
+ Namespace *oldNsPtr = resNamePtr->nsPtr;
+ if ((--oldNsPtr->refCount == 0) && (oldNsPtr->flags & NS_DEAD)) {
+ NamespaceFree(oldNsPtr);
+ }
+ } else {
+ TclFreeIntRep(objPtr);
+ resNamePtr = (ResolvedNsName *) ckalloc(sizeof(ResolvedNsName));
+ resNamePtr->refCount = 1;
+ objPtr->internalRep.otherValuePtr = (void *) resNamePtr;
+ objPtr->typePtr = &tclNsNameType;
+ }
resNamePtr->nsPtr = nsPtr;
resNamePtr->nsId = nsPtr->nsId;
if ((*name++ == ':') && (*name == ':')) {
@@ -4850,20 +4866,11 @@ SetNsNameFromAny(
resNamePtr->refNsPtr =
(Namespace *) TclGetCurrentNamespace(interp);
}
- resNamePtr->refCount = 1;
} else {
- resNamePtr = NULL;
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.otherValuePtr = (void *) NULL;
+ objPtr->typePtr = &tclNsNameType;
}
-
- /*
- * Free the old internalRep before setting the new one. We do this as late
- * as possible to allow the conversion code (in particular,
- * Tcl_GetStringFromObj) to use that old internalRep.
- */
-
- TclFreeIntRep(objPtr);
- objPtr->internalRep.otherValuePtr = (void *) resNamePtr;
- objPtr->typePtr = &tclNsNameType;
return TCL_OK;
}