? objReform.diff.1
? objReform.diff.1.1
? objReform.diff.1.2
? unix/0valgrind
? unix/ERR
? unix/cat
? unix/dltest.marker
? unix/longfile
? unix/output
? unix/pipe
? unix/script
? unix/stdout
? unix/tclsh1
? unix/test2
? unix/test3
Index: generic/tcl.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tcl.h,v
retrieving revision 1.234
diff -u -r1.234 tcl.h
--- generic/tcl.h	31 Jul 2007 17:03:35 -0000	1.234
+++ generic/tcl.h	11 Aug 2007 13:26:56 -0000
@@ -743,6 +743,8 @@
  * or both.
  */
 
+#define TCL_OBJ_STRING_AREA_SIZE 8
+    
 typedef struct Tcl_Obj {
     int refCount;		/* When 0 the object will be freed. */
     char *bytes;		/* This points to the first byte of the
@@ -778,6 +780,7 @@
 				 * single word */
 	} ptrAndLongRep;
     } internalRep;
+    char reserved[TCL_OBJ_STRING_AREA_SIZE];
 } Tcl_Obj;
 
 /*
Index: generic/tclIndexObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIndexObj.c,v
retrieving revision 1.35
diff -u -r1.35 tclIndexObj.c
--- generic/tclIndexObj.c	20 Jun 2007 18:46:13 -0000	1.35
+++ generic/tclIndexObj.c	11 Aug 2007 13:26:56 -0000
@@ -332,15 +332,11 @@
     Tcl_Obj *objPtr)
 {
     IndexRep *indexRep = (IndexRep *) objPtr->internalRep.otherValuePtr;
-    register char *buf;
     register unsigned len;
     register CONST char *indexStr = EXPAND_OF(indexRep);
 
     len = strlen(indexStr);
-    buf = (char *) ckalloc(len + 1);
-    memcpy(buf, indexStr, len+1);
-    objPtr->bytes = buf;
-    objPtr->length = len;
+    TclInitStringRep(objPtr, indexStr, len);
 }
 
 /*
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.331
diff -u -r1.331 tclInt.h
--- generic/tclInt.h	10 Aug 2007 18:40:24 -0000	1.331
+++ generic/tclInt.h	11 Aug 2007 13:26:59 -0000
@@ -3068,6 +3068,19 @@
  *----------------------------------------------------------------
  */
 
+#define TclSetEmptyStringRep(objPtr) \
+    (objPtr)->bytes    = (objPtr)->reserved; \
+    (objPtr)->length   = 0; \
+    *((void **)(objPtr)->reserved) = NULL
+
+#define TclObjEmbeddedString(objPtr) \
+    ((objPtr)->bytes == (objPtr)->reserved)
+
+#define TclFreeStringRep(objPtr) \
+    if (objPtr->bytes && !TclObjEmbeddedString(objPtr)) { \
+        ckfree((char *) (objPtr)->bytes); \
+    }
+
 #ifdef TCL_COMPILE_STATS
 #  define TclIncrObjsAllocated() \
     tclObjsAlloced++
@@ -3083,9 +3096,8 @@
     TclIncrObjsAllocated(); \
     TclAllocObjStorage(objPtr); \
     (objPtr)->refCount = 0; \
-    (objPtr)->bytes    = tclEmptyStringRep; \
-    (objPtr)->length   = 0; \
-    (objPtr)->typePtr  = NULL
+    (objPtr)->typePtr  = NULL; \
+    TclSetEmptyStringRep(objPtr)
 
 /*
  * Invalidate the string rep first so we can use the bytes value for our
@@ -3097,10 +3109,7 @@
 # define TclDecrRefCount(objPtr) \
     if (--(objPtr)->refCount > 0) ; else { \
 	if (!(objPtr)->typePtr || !(objPtr)->typePtr->freeIntRepProc) { \
-  	    if ((objPtr)->bytes \
-	            && ((objPtr)->bytes != tclEmptyStringRep)) { \
-	        ckfree((char *) (objPtr)->bytes); \
-	    } \
+  	    TclFreeStringRep(objPtr); \
             (objPtr)->length = -1; \
 	    TclFreeObjStorage(objPtr); \
 	    TclIncrObjsFreed(); \
@@ -3207,16 +3216,15 @@
  */
 
 #define TclInitStringRep(objPtr, bytePtr, len) \
-    if ((len) == 0) { \
-	(objPtr)->bytes	 = tclEmptyStringRep; \
-	(objPtr)->length = 0; \
+    if ((len) < TCL_OBJ_STRING_AREA_SIZE) { \
+	(objPtr)->bytes = (objPtr)->reserved; \
     } else { \
 	(objPtr)->bytes = (char *) ckalloc((unsigned) ((len) + 1)); \
-	memcpy((void *) (objPtr)->bytes, (void *) (bytePtr), \
-		(unsigned) (len)); \
-	(objPtr)->bytes[len] = '\0'; \
-	(objPtr)->length = (len); \
-    }
+    } \
+    memcpy((void *) (objPtr)->bytes, (void *) (bytePtr), \
+	     (unsigned) (len)); \
+    (objPtr)->bytes[len] = '\0'; \
+    (objPtr)->length = (len)
 
 /*
  *----------------------------------------------------------------
@@ -3260,9 +3268,7 @@
 
 #define TclInvalidateStringRep(objPtr) \
     if (objPtr->bytes != NULL) { \
-	if (objPtr->bytes != tclEmptyStringRep) {\
-	    ckfree((char *) objPtr->bytes);\
-	}\
+	TclFreeStringRep(objPtr);\
 	objPtr->bytes = NULL;\
     }\
 
Index: generic/tclListObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclListObj.c,v
retrieving revision 1.46
diff -u -r1.46 tclListObj.c
--- generic/tclListObj.c	24 Apr 2007 22:31:39 -0000	1.46
+++ generic/tclListObj.c	11 Aug 2007 13:27:00 -0000
@@ -337,8 +337,7 @@
 	objPtr->typePtr = &tclListType;
 	listRepPtr->refCount++;
     } else {
-	objPtr->bytes = tclEmptyStringRep;
-	objPtr->length = 0;
+	TclSetEmptyStringRep(objPtr);
     }
 }
 
Index: generic/tclNamesp.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclNamesp.c,v
retrieving revision 1.148
diff -u -r1.148 tclNamesp.c
--- generic/tclNamesp.c	3 Aug 2007 13:51:40 -0000	1.148
+++ generic/tclNamesp.c	11 Aug 2007 13:27:04 -0000
@@ -4800,13 +4800,13 @@
      */
 
     if (length == 0) {
-	objPtr->bytes = tclEmptyStringRep;
+	TclSetEmptyStringRep(objPtr);
     } else {
 	objPtr->bytes = (char *) ckalloc((unsigned) (length + 1));
 	memcpy(objPtr->bytes, name, (unsigned) length);
 	objPtr->bytes[length] = '\0';
+	objPtr->length = length;
     }
-    objPtr->length = length;
 }
 
 /*
Index: generic/tclObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclObj.c,v
retrieving revision 1.131
diff -u -r1.131 tclObj.c
--- generic/tclObj.c	31 Jul 2007 17:03:39 -0000	1.131
+++ generic/tclObj.c	11 Aug 2007 13:27:05 -0000
@@ -609,8 +609,7 @@
     register Tcl_Obj *objPtr)
 {
     objPtr->refCount = 0;
-    objPtr->bytes = tclEmptyStringRep;
-    objPtr->length = 0;
+    TclSetEmptyStringRep(objPtr);
     objPtr->typePtr = NULL;
 
 #ifdef TCL_THREADS
@@ -773,11 +772,14 @@
 
 #define OBJS_TO_ALLOC_EACH_TIME 100
 
+#define CACHE_ALIGNMENT 32
+#define CACHE_ALIGN(p) (char *) INT2PTR((PTR2INT(p)+ (CACHE_ALIGNMENT-1)) & ~(CACHE_ALIGNMENT-1))
+
 void
 TclAllocateFreeObjects(void)
 {
     size_t bytesToAlloc = (OBJS_TO_ALLOC_EACH_TIME * sizeof(Tcl_Obj));
-    char *basePtr;
+    char *basePtr, *basePtr0;
     register Tcl_Obj *prevPtr, *objPtr;
     register int i;
 
@@ -790,12 +792,23 @@
      * Purify apparently can't figure that out, and fires a false alarm.
      */
 
-    basePtr = (char *) ckalloc(bytesToAlloc);
+    basePtr0 = (char *) ckalloc(bytesToAlloc);
+
+    /*
+     * Insure that the first Tcl_Obj is cache-aligned, even if it requires
+     * sacrificing a few Tcl_Obj (at most one in typical cases: 1% loss).
+     */
+
+    basePtr = CACHE_ALIGN(basePtr0);
+    for (i = OBJS_TO_ALLOC_EACH_TIME;
+            basePtr+i*sizeof(Tcl_Obj) > basePtr0+bytesToAlloc; i--) {}
+    bytesToAlloc = i*sizeof(Tcl_Obj);
+
     memset(basePtr, 0, bytesToAlloc);
 
     prevPtr = NULL;
     objPtr = (Tcl_Obj *) basePtr;
-    for (i = 0; i < OBJS_TO_ALLOC_EACH_TIME; i++) {
+    while (i--) {
 	objPtr->internalRep.otherValuePtr = (void *) prevPtr;
 	prevPtr = objPtr;
 	objPtr++;
@@ -803,6 +816,9 @@
     tclFreeObjList = prevPtr;
 }
 #undef OBJS_TO_ALLOC_EACH_TIME
+#undef CACHE_ALIGNMENT
+#undef CACHE_ALIGN
+
 
 /*
  *----------------------------------------------------------------------
@@ -1014,7 +1030,7 @@
 
     if (objPtr->bytes == NULL) {
 	dupPtr->bytes = NULL;
-    } else if (objPtr->bytes != tclEmptyStringRep) {
+    } else {
 	TclInitStringRep(dupPtr, objPtr->bytes, objPtr->length);
     }
 
@@ -1777,10 +1793,7 @@
 
     Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, buffer);
     len = strlen(buffer);
-
-    objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
-    strcpy(objPtr->bytes, buffer);
-    objPtr->length = len;
+    TclInitStringRep(objPtr, buffer, len);
 }
 
 /*
@@ -1968,10 +1981,7 @@
     register int len;
 
     len = TclFormatInt(buffer, objPtr->internalRep.longValue);
-
-    objPtr->bytes = ckalloc((unsigned) len + 1);
-    strcpy(objPtr->bytes, buffer);
-    objPtr->length = len;
+    TclInitStringRep(objPtr, buffer, len);
 }
 
 /*
@@ -2272,9 +2282,7 @@
 
     sprintf(buffer, "%" TCL_LL_MODIFIER "d", wideVal);
     len = strlen(buffer);
-    objPtr->bytes = ckalloc((unsigned) len + 1);
-    memcpy(objPtr->bytes, buffer, len + 1);
-    objPtr->length = len;
+    TclInitStringRep(objPtr, buffer, len);
 }
 #endif /* !NO_WIDE_TYPE */
 
@@ -2767,7 +2775,7 @@
 		objPtr->internalRep.ptrAndLongRep.value = 0;
 		objPtr->typePtr = NULL;
 		if (objPtr->bytes == NULL) {
-		    TclInitStringRep(objPtr, tclEmptyStringRep, 0);
+		    TclSetEmptyStringRep(objPtr);		    
 		}
 	    }
 	    return TCL_OK;
Index: generic/tclPathObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclPathObj.c,v
retrieving revision 1.63
diff -u -r1.63 tclPathObj.c
--- generic/tclPathObj.c	2 May 2007 21:30:36 -0000	1.63
+++ generic/tclPathObj.c	11 Aug 2007 13:27:07 -0000
@@ -2624,8 +2624,7 @@
     Tcl_AppendObjToObj(copy, fsPathPtr->normPathPtr);
     pathPtr->bytes = Tcl_GetStringFromObj(copy, &cwdLen);
     pathPtr->length = cwdLen;
-    copy->bytes = tclEmptyStringRep;
-    copy->length = 0;
+    TclSetEmptyStringRep(copy);
     TclDecrRefCount(copy);
 }
 
Index: generic/tclResult.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclResult.c,v
retrieving revision 1.37
diff -u -r1.37 tclResult.c
--- generic/tclResult.c	5 Jun 2007 17:57:08 -0000	1.37
+++ generic/tclResult.c	11 Aug 2007 13:27:07 -0000
@@ -962,12 +962,8 @@
 	Tcl_IncrRefCount(objResultPtr);
 	iPtr->objResultPtr = objResultPtr;
     } else {
-	if ((objResultPtr->bytes != NULL)
-		&& (objResultPtr->bytes != tclEmptyStringRep)) {
-	    ckfree((char *) objResultPtr->bytes);
-	}
-	objResultPtr->bytes = tclEmptyStringRep;
-	objResultPtr->length = 0;
+	TclFreeStringRep(objResultPtr);
+	TclSetEmptyStringRep(objResultPtr);
 	TclFreeIntRep(objResultPtr);
 	objResultPtr->typePtr = NULL;
     }
Index: generic/tclStringObj.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclStringObj.c,v
retrieving revision 1.65
diff -u -r1.65 tclStringObj.c
--- generic/tclStringObj.c	28 Mar 2007 19:03:42 -0000	1.65
+++ generic/tclStringObj.c	11 Aug 2007 13:27:08 -0000
@@ -767,7 +767,7 @@
 	 * free the old string.
 	 */
 
-	if (objPtr->bytes != tclEmptyStringRep) {
+	if (!TclObjEmbeddedString(objPtr)) {
 	    objPtr->bytes = ckrealloc((char *)objPtr->bytes,
 		    (unsigned)(length+1));
 	} else {
@@ -790,13 +790,7 @@
 
     if (objPtr->bytes != NULL) {
 	objPtr->length = length;
-	if (objPtr->bytes != tclEmptyStringRep) {
-	    /*
-	     * Ensure the string is NUL-terminated.
-	     */
-
-	    objPtr->bytes[length] = 0;
-	}
+	objPtr->bytes[length] = 0;
 
 	/*
 	 * Invalidate the unicode data.
@@ -883,7 +877,7 @@
 	 * free the old string.
 	 */
 
-	if (objPtr->bytes != tclEmptyStringRep) {
+	if (!TclObjEmbeddedString(objPtr)) {
 	    new = attemptckrealloc(objPtr->bytes, (unsigned)(length+1));
 	    if (new == NULL) {
 		return 0;
@@ -911,13 +905,7 @@
 
     if (objPtr->bytes != NULL) {
 	objPtr->length = length;
-	if (objPtr->bytes != tclEmptyStringRep) {
-	    /*
-	     * Ensure the string is NULL-terminated.
-	     */
-
-	    objPtr->bytes[length] = 0;
-	}
+	objPtr->bytes[length] = 0;
 
 	/*
 	 * Invalidate the unicode data.
@@ -2825,8 +2813,7 @@
 	     * the string rep to an empty string.
 	     */
 
-	    objPtr->bytes = tclEmptyStringRep;
-	    objPtr->length = 0;
+	    TclSetEmptyStringRep(objPtr);
 	    return;
 	}
 
Index: generic/tclUtil.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclUtil.c,v
retrieving revision 1.82
diff -u -r1.82 tclUtil.c
--- generic/tclUtil.c	7 May 2007 19:45:33 -0000	1.82
+++ generic/tclUtil.c	11 Aug 2007 13:27:10 -0000
@@ -2417,9 +2417,7 @@
 	buffer[len++] = '-';
 	len += TclFormatInt(buffer+len, -(objPtr->internalRep.longValue));
     }
-    objPtr->bytes = ckalloc((unsigned) (len+1));
-    strcpy(objPtr->bytes, buffer);
-    objPtr->length = len;
+    TclInitStringRep(objPtr, buffer, len);
 }
 
 /*
