Tcl Source Code

Check-in [0148c7fff1]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:slightly faster inUse computation
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | mig-alloc-reform
Files: files | file ages | folders
SHA1: 0148c7fff1647218ef6134b861135dffe6e244f8
User & Date: mig 2011-03-24 20:23:20
Context
2011-03-24
22:06
add finalization code; needed? check-in: 5a869d1e11 user: mig tags: mig-alloc-reform
20:23
slightly faster inUse computation check-in: 0148c7fff1 user: mig tags: mig-alloc-reform
19:24
merge trunk into feature branch check-in: 7649a6b239 user: mig tags: mig-alloc-reform
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclAlloc.c.

126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142

typedef struct Block {
    union {
	struct Block *next;		/* Next in free list. */
	struct {
	    unsigned char magic1;	/* First magic number. */
	    unsigned char bucket;	/* Bucket block allocated from. */
	    unsigned char inUse;	/* Block memory currently in use, as
					 * a fraction of the block size, in
					 * 255ths*/ 
	    unsigned char magic2;	/* Second magic number. */
	} s;
    } u;
    long refCount;
} Block;

#define OFFSET      ALIGN(sizeof(Block))







|
|
<







126
127
128
129
130
131
132
133
134

135
136
137
138
139
140
141

typedef struct Block {
    union {
	struct Block *next;		/* Next in free list. */
	struct {
	    unsigned char magic1;	/* First magic number. */
	    unsigned char bucket;	/* Bucket block allocated from. */
	    unsigned char inUse;	/* Block memory currently in use, see
					 * details in TclpAlloc/Realloc. */

	    unsigned char magic2;	/* Second magic number. */
	} s;
    } u;
    long refCount;
} Block;

#define OFFSET      ALIGN(sizeof(Block))
187
188
189
190
191
192
193

194
195
196
197
198
199
200
/*
 * The following array specifies various per-bucket limits and locks. The
 * values are statically initialized to avoid calculating them repeatedly.
 */

static struct {
    size_t blockSize;		/* Bucket blocksize. */

#if defined(TCL_THREADS)
    int maxBlocks;		/* Max blocks before move to share. */
    int numMove;		/* Num blocks to move to share. */
    Tcl_Mutex *lockPtr;		/* Share bucket lock. */
#endif
} bucketInfo[NBUCKETS];








>







186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/*
 * The following array specifies various per-bucket limits and locks. The
 * values are statically initialized to avoid calculating them repeatedly.
 */

static struct {
    size_t blockSize;		/* Bucket blocksize. */
    int shift;
#if defined(TCL_THREADS)
    int maxBlocks;		/* Max blocks before move to share. */
    int numMove;		/* Num blocks to move to share. */
    Tcl_Mutex *lockPtr;		/* Share bucket lock. */
#endif
} bucketInfo[NBUCKETS];

341
342
343
344
345
346
347

348
349
350




351
352
353
354
355
356
357
 */

#if USE_ZIPPY
static void
InitBucketInfo ()
{
    int i;


    for (i = 0; i < NBUCKETS; ++i) {
	bucketInfo[i].blockSize = MINALLOC << i;    




#if defined(TCL_THREADS)
	/* TODO: clearer logic? Change move to keep? */
	bucketInfo[i].maxBlocks = 1 << (NBUCKETS - 1 - i);
	bucketInfo[i].numMove = i < NBUCKETS - 1 ?
	    1 << (NBUCKETS - 2 - i) : 1;
	bucketInfo[i].lockPtr = TclpNewAllocMutex();
#endif







>
|

|
>
>
>
>







341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
 */

#if USE_ZIPPY
static void
InitBucketInfo ()
{
    int i;
    int shift = 0;
    
    for (i = 0; i < NBUCKETS; ++i) {
	bucketInfo[i].blockSize = MINALLOC << i;
	while (((bucketInfo[i].blockSize -OFFSET) >> shift) > 255) {
	    ++shift;
	}
	bucketInfo[i].shift = shift;
#if defined(TCL_THREADS)
	/* TODO: clearer logic? Change move to keep? */
	bucketInfo[i].maxBlocks = 1 << (NBUCKETS - 1 - i);
	bucketInfo[i].numMove = i < NBUCKETS - 1 ?
	    1 << (NBUCKETS - 2 - i) : 1;
	bucketInfo[i].lockPtr = TclpNewAllocMutex();
#endif
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
{
    register void *ptr;
    
    blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC;
    if (bucket == NBUCKETS) {
	blockPtr->used = 255;
    } else {
	/*
	 * This relies on not overflowing, which will be the case if nobody
	 * makes NBUCKETS way too large.
	 */
	
	size_t maxSize = bucketInfo[bucket].blockSize - OFFSET;

	blockPtr->used = ((maxSize -1 + reqSize*255)/maxSize);
    }
    blockPtr->sourceBucket = bucket;
    ptr = (void *) (((char *)blockPtr) + OFFSET);
    blockPtr->refCount = 0;
    return (char *) ptr;
}








<
<
<
<
|
<
<
<







720
721
722
723
724
725
726




727



728
729
730
731
732
733
734
{
    register void *ptr;
    
    blockPtr->magicNum1 = blockPtr->magicNum2 = MAGIC;
    if (bucket == NBUCKETS) {
	blockPtr->used = 255;
    } else {




	blockPtr->used = (reqSize >> bucketInfo[bucket].shift);



    }
    blockPtr->sourceBucket = bucket;
    ptr = (void *) (((char *)blockPtr) + OFFSET);
    blockPtr->refCount = 0;
    return (char *) ptr;
}

939
940
941
942
943
944
945
946
947
948

949
950
951
952
953
954
955
	    /* Requested allocation exceeds memory */
	    return NULL;
	}
    }
#endif

    /*
     * If the block is not a system block and fits in place, simply return the
     * existing pointer. Otherwise, if the block is a system block and the new
     * size would also require a system block, call realloc() directly.

     */

    blockPtr = Ptr2Block(ptr);
    if (blockPtr->refCount != 0) {
	Tcl_Panic("trying to realloc a preserved pointer");
    }
    







|
|
|
>







937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
	    /* Requested allocation exceeds memory */
	    return NULL;
	}
    }
#endif

    /*
     * If the block is not a system block and belongs in the same block,
     * simply return the existing pointer. Otherwise, if the block is a system
     * block and the new size would also require a system block, call
     * realloc() directly. 
     */

    blockPtr = Ptr2Block(ptr);
    if (blockPtr->refCount != 0) {
	Tcl_Panic("trying to realloc a preserved pointer");
    }
    
975
976
977
978
979
980
981
982
983



984
985
986
987
988
989
990
    /*
     * Finally, perform an expensive malloc/copy/free.
     */

    newPtr = TclpAlloc(reqSize);
    if (newPtr != NULL) {
	size_t maxSize = bucketInfo[bucket].blockSize - OFFSET;
	size_t toCopy = ((blockPtr->used) * maxSize)/255;




	if (toCopy > reqSize) {
	    toCopy = reqSize;
	}
	
	memcpy(newPtr, ptr, toCopy);
	TclpFree(ptr);
    }







|

>
>
>







974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
    /*
     * Finally, perform an expensive malloc/copy/free.
     */

    newPtr = TclpAlloc(reqSize);
    if (newPtr != NULL) {
	size_t maxSize = bucketInfo[bucket].blockSize - OFFSET;
	size_t toCopy = ((blockPtr->used + 1) << bucketInfo[bucket].shift);

	if (toCopy > maxSize) {
	    toCopy = maxSize;
	}
	if (toCopy > reqSize) {
	    toCopy = reqSize;
	}
	
	memcpy(newPtr, ptr, toCopy);
	TclpFree(ptr);
    }
1419
1420
1421
1422
1423
1424
1425
1426

1427
1428
1429
1430
1431
1432
1433
	 * TclEventuallyFree has already been called on this with
	 * (freeProc != TCL_DYNAMIC)
	 */
	
	--blockPtr->refCount;
    } else {
	/*
	 * First preserve call: add one refcount for use by EventuallyFree 

	 */
  
	blockPtr->refCount = 2;
    }
}

/*







|
>







1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
	 * TclEventuallyFree has already been called on this with
	 * (freeProc != TCL_DYNAMIC)
	 */
	
	--blockPtr->refCount;
    } else {
	/*
	 * First preserve call: add one refcount to signal that EventuallyFree
	 * has not yet been called (role of the old '!mustFree')
	 */
  
	blockPtr->refCount = 2;
    }
}

/*