Attachment "alloc.patch" to
ticket [1851832fff]
added by
msofer
2007-12-17 04:27:10.
Index: generic/tclAlloc.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclAlloc.c,v
retrieving revision 1.26
diff -u -r1.26 tclAlloc.c
--- generic/tclAlloc.c 13 Dec 2007 15:23:14 -0000 1.26
+++ generic/tclAlloc.c 16 Dec 2007 21:25:33 -0000
@@ -44,16 +44,6 @@
#endif
/*
- * Alignment for allocated memory.
- */
-
-#if defined(__APPLE__)
-#define ALLOCALIGN 16
-#else
-#define ALLOCALIGN 8
-#endif
-
-/*
* The overhead on a block is at least 8 bytes. When free, this space contains
* a pointer to the next free block, and the bottom two bits must be zero.
* When in use, the first byte is set to MAGIC, and the second byte is the
@@ -66,7 +56,7 @@
union overhead {
union overhead *next; /* when free */
- unsigned char padding[ALLOCALIGN]; /* align struct to ALLOCALIGN bytes */
+ unsigned char padding[TCL_ALLOCALIGN]; /* align struct to TCL_ALLOCALIGN bytes */
struct {
unsigned char magic0; /* magic number */
unsigned char index; /* bucket # */
@@ -110,7 +100,7 @@
* precedes the data area returned to the user.
*/
-#define MINBLOCK ((sizeof(union overhead) + (ALLOCALIGN-1)) & ~(ALLOCALIGN-1))
+#define MINBLOCK ((sizeof(union overhead) + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1))
#define NBUCKETS (13 - (MINBLOCK >> 4))
#define MAXMALLOC (1<<(NBUCKETS+2))
static union overhead *nextf[NBUCKETS];
Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.357
diff -u -r1.357 tclExecute.c
--- generic/tclExecute.c 13 Dec 2007 15:23:16 -0000 1.357
+++ generic/tclExecute.c 16 Dec 2007 21:25:34 -0000
@@ -603,7 +603,7 @@
static const char * GetSrcInfoForPc(unsigned char *pc, ByteCode *codePtr,
int *lengthPtr);
static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, int growth,
- int move);
+ int move, int align);
static void IllegalExprOperandType(Tcl_Interp *interp,
unsigned char *pc, Tcl_Obj *opndPtr);
static void InitByteCodeExecution(Tcl_Interp *interp);
@@ -616,8 +616,8 @@
#endif /* TCL_COMPILE_DEBUG */
static void DeleteExecStack(ExecStack *esPtr);
/* Useful elsewhere, make available in tclInt.h or stubs? */
-static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, int numWords);
-static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, int numWords);
+static Tcl_Obj ** StackAllocWords(Tcl_Interp *interp, int numWords, int align);
+static Tcl_Obj ** StackReallocWords(Tcl_Interp *interp, int numWords, int align);
/*
*----------------------------------------------------------------------
@@ -854,37 +854,69 @@
*----------------------------------------------------------------------
*/
+#define WALLOCALIGN (TCL_ALLOCALIGN/sizeof(void *))
+
+
+/*
+ * This macro computes the correct offset to insure that the pointer returned
+ * is properly aligned.
+ * Note that we are only interested in the low bits of the address, so that
+ * the fact that PTR2INT may lose the high bits is irrelevant.
+ */
+
+#define COMPUTE_OFFSET(markerPtr, offset) \
+ {\
+ int base = (PTR2UINT(markerPtr) & (WALLOCALIGN-1));\
+ int new = (base + 2 + (WALLOCALIGN-1)) & ~(WALLOCALIGN-1);\
+ (offset) = (new - base); \
+ }
+
+
static Tcl_Obj **
GrowEvaluationStack(
ExecEnv *eePtr, /* Points to the ExecEnv with an evaluation
* stack to enlarge. */
int growth, /* How much larger than the current used
* size. */
- int move) /* 1 if move words since last marker. */
+ int move, /* 1 if move words since last marker. */
+ int align) /* 1 if word alignment is not enough, align
+ * according to TCL_ALLOCALIGN */
{
ExecStack *esPtr = eePtr->execStackPtr, *oldPtr = NULL;
int newBytes, newElems, currElems;
int needed = growth - (esPtr->endPtr - esPtr->tosPtr);
- Tcl_Obj **markerPtr = esPtr->markerPtr;
+ Tcl_Obj **markerPtr = esPtr->markerPtr, **newMarkerPtr;
+ int offset = 2; /* default value */
if (move) {
if (!markerPtr) {
Tcl_Panic("STACK: Reallocating with no previous alloc");
}
+ offset = PTR2INT(*(markerPtr+1));
if (needed <= 0) {
- return markerPtr + 1;
+ return markerPtr + offset;
+ }
+ } else if (needed < -1) {
+ newMarkerPtr = (esPtr->tosPtr + 1);
+ if (align) {
+ COMPUTE_OFFSET(newMarkerPtr, offset);
}
- } else if (needed < 0) {
- /*
- * Put a marker pointing to the previous marker in this stack, and
- * store it in esPtr as the current marker. Return a pointer to one
- * word past the marker.
- */
- esPtr->markerPtr = ++esPtr->tosPtr;
- *esPtr->markerPtr = (Tcl_Obj *) markerPtr;
- return esPtr->markerPtr + 1;
+ if (needed + offset <= 0) {
+ /*
+ * Put a marker pointing to the previous marker in this stack, and
+ * store it in esPtr as the current marker. Return a pointer to
+ * the word at (marker+offset).
+ */
+
+ esPtr->markerPtr = newMarkerPtr;
+ *newMarkerPtr = (Tcl_Obj *) markerPtr;
+ *(newMarkerPtr+1) = INT2PTR(offset);
+ esPtr->tosPtr += offset;
+ return newMarkerPtr + offset;
+ }
}
+ offset = 2; /* reset to default */
/*
* Reset move to hold the number of words to be moved to new stack (if
@@ -894,7 +926,14 @@
if (move) {
move = esPtr->tosPtr - markerPtr;
}
- needed = growth + move + 1; /* Add the marker. */
+
+ /*
+ * Add requirements for the marker and the offset; note that this is at
+ * most (WALLOCALIGN+1) words: one for the marker, one to store the
+ * offset, and at most an offset of (WALLOCALIGN-1)
+ */
+
+ needed = growth + move + (align? (WALLOCALIGN+1) : 2);
/*
* Check if there is enough room in the next stack (if there is one, it
@@ -942,6 +981,10 @@
newStackReady:
eePtr->execStackPtr = esPtr;
+ if (align) {
+ COMPUTE_OFFSET(&esPtr->stackWords[0], offset);
+ }
+
/*
* Store a NULL marker at the beginning of the stack, to indicate that
* this is the first marker in this stack and that rewinding to here
@@ -949,10 +992,12 @@
*/
esPtr->stackWords[0] = NULL;
- esPtr->markerPtr = esPtr->tosPtr = &esPtr->stackWords[0];
+ esPtr->stackWords[1] = INT2PTR(offset);
+ esPtr->markerPtr = &esPtr->stackWords[0];
+ esPtr->tosPtr = &esPtr->stackWords[offset-1];
if (move) {
- memcpy(&esPtr->stackWords[1], (markerPtr+1), move*sizeof(Tcl_Obj *));
+ memcpy(&esPtr->stackWords[offset], (markerPtr+PTR2INT(*(markerPtr+1))), move*sizeof(Tcl_Obj *));
esPtr->tosPtr += move;
oldPtr->markerPtr = (Tcl_Obj **) *markerPtr;
oldPtr->tosPtr = markerPtr-1;
@@ -966,7 +1011,7 @@
DeleteExecStack(oldPtr);
}
- return &esPtr->stackWords[1];
+ return &esPtr->stackWords[offset];
}
/*
@@ -990,7 +1035,8 @@
static Tcl_Obj **
StackAllocWords(
Tcl_Interp *interp,
- int numWords)
+ int numWords,
+ int align)
{
/*
* Note that GrowEvaluationStack sets a marker in the stack. This marker
@@ -999,7 +1045,7 @@
Interp *iPtr = (Interp *) interp;
ExecEnv *eePtr = iPtr->execEnvPtr;
- Tcl_Obj **resPtr = GrowEvaluationStack(eePtr, numWords, 0);
+ Tcl_Obj **resPtr = GrowEvaluationStack(eePtr, numWords, 0, align);
eePtr->execStackPtr->tosPtr += numWords;
return resPtr;
@@ -1008,11 +1054,12 @@
static Tcl_Obj **
StackReallocWords(
Tcl_Interp *interp,
- int numWords)
+ int numWords,
+ int align)
{
Interp *iPtr = (Interp *) interp;
ExecEnv *eePtr = iPtr->execEnvPtr;
- Tcl_Obj **resPtr = GrowEvaluationStack(eePtr, numWords, 1);
+ Tcl_Obj **resPtr = GrowEvaluationStack(eePtr, numWords, 1, align);
eePtr->execStackPtr->tosPtr += numWords;
return resPtr;
@@ -1043,7 +1090,7 @@
esPtr = eePtr->execStackPtr;
markerPtr = esPtr->markerPtr;
- if ((markerPtr+1) != (Tcl_Obj **)freePtr) {
+ if (markerPtr + PTR2INT(*(markerPtr+1)) != (Tcl_Obj **)freePtr) {
Tcl_Panic("TclStackFree: incorrect freePtr. Call out of sequence?");
}
@@ -1081,7 +1128,7 @@
return (void *) Tcl_Alloc(numBytes);
}
- return (void *) StackAllocWords(interp, numWords);
+ return (void *) StackAllocWords(interp, numWords, 1);
}
void *
@@ -1104,12 +1151,12 @@
esPtr = eePtr->execStackPtr;
markerPtr = esPtr->markerPtr;
- if ((markerPtr+1) != (Tcl_Obj **)ptr) {
+ if ((markerPtr+PTR2INT(*(markerPtr+1))) != (Tcl_Obj **)ptr) {
Tcl_Panic("TclStackRealloc: incorrect ptr. Call out of sequence?");
}
numWords = (numBytes + (sizeof(Tcl_Obj *) - 1))/sizeof(Tcl_Obj *);
- return (void *) StackReallocWords(interp, numWords);
+ return (void *) StackReallocWords(interp, numWords, 1);
}
/*
@@ -1617,7 +1664,7 @@
catchTop = initCatchTop = (ptrdiff_t *) (
GrowEvaluationStack(iPtr->execEnvPtr,
codePtr->maxExceptDepth + sizeof(CmdFrame) +
- codePtr->maxStackDepth, 0) - 1);
+ codePtr->maxStackDepth, 0, 0) - 1);
bcFramePtr = (CmdFrame *) (initCatchTop + codePtr->maxExceptDepth + 1);
tosPtr = initTosPtr = ((Tcl_Obj **) (bcFramePtr + 1)) - 1;
esPtr = iPtr->execEnvPtr->execStackPtr;
@@ -2100,7 +2147,7 @@
length = objc + (codePtr->maxStackDepth - TclGetInt4AtPtr(pc+1));
DECACHE_STACK_INFO();
- moved = (GrowEvaluationStack(iPtr->execEnvPtr, length, 1) - 1)
+ moved = (GrowEvaluationStack(iPtr->execEnvPtr, length, 1, 0) - 1)
- (Tcl_Obj **) initCatchTop;
if (moved) {
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.358
diff -u -r1.358 tclInt.h
--- generic/tclInt.h 13 Dec 2007 15:23:18 -0000 1.358
+++ generic/tclInt.h 16 Dec 2007 21:25:36 -0000
@@ -2034,6 +2034,17 @@
#define UCHAR(c) ((unsigned char) (c))
/*
+ * This macro is used to properly align the memory allocated by Tcl, giving
+ * the same alignment as the native malloc
+ */
+
+#if defined(__APPLE__)
+#define TCL_ALLOCALIGN 16
+#else
+#define TCL_ALLOCALIGN 8
+#endif
+
+/*
* This macro is used to determine the offset needed to safely allocate any
* data structure in memory. Given a starting offset or size, it "rounds up"
* or "aligns" the offset to the next 8-byte boundary so that any data
Index: generic/tclThreadAlloc.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclThreadAlloc.c,v
retrieving revision 1.24
diff -u -r1.24 tclThreadAlloc.c
--- generic/tclThreadAlloc.c 13 Dec 2007 15:23:20 -0000 1.24
+++ generic/tclThreadAlloc.c 16 Dec 2007 21:25:36 -0000
@@ -40,16 +40,6 @@
#define NOBJHIGH 1200
/*
- * Alignment for allocated memory.
- */
-
-#if defined(__APPLE__)
-#define ALLOCALIGN 16
-#else
-#define ALLOCALIGN 8
-#endif
-
-/*
* The following union stores accounting information for each block including
* two small magic numbers and a bucket number when in use or a next pointer
* when free. The original requested size (not including the Block overhead)
@@ -69,7 +59,7 @@
} u;
size_t reqSize; /* Requested allocation size. */
} b;
- unsigned char padding[ALLOCALIGN];
+ unsigned char padding[TCL_ALLOCALIGN];
} Block;
#define nextBlock b.u.next
#define sourceBucket b.u.s.bucket
@@ -83,7 +73,7 @@
* of buckets in the bucket cache.
*/
-#define MINALLOC ((sizeof(Block) + 8 + (ALLOCALIGN-1)) & ~(ALLOCALIGN-1))
+#define MINALLOC ((sizeof(Block) + 8 + (TCL_ALLOCALIGN-1)) & ~(TCL_ALLOCALIGN-1))
#define NBUCKETS (11 - (MINALLOC >> 5))
#define MAXALLOC (MINALLOC << (NBUCKETS - 1))