os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclLiteral.c
Update contrib.
4 * Implementation of the global and ByteCode-local literal tables
5 * used to manage the Tcl objects created for literal values during
6 * compilation of Tcl scripts. This implementation borrows heavily
7 * from the more general hashtable implementation of Tcl hash tables
8 * that appears in tclHash.c.
10 * Copyright (c) 1997-1998 Sun Microsystems, Inc.
12 * See the file "license.terms" for information on usage and redistribution
13 * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
15 * RCS: @(#) $Id: tclLiteral.c,v 1.11 2001/10/11 22:28:01 msofer Exp $
19 #include "tclCompile.h"
22 * When there are this many entries per bucket, on average, rebuild
23 * a literal's hash table to make it larger.
26 #define REBUILD_MULTIPLIER 3
29 * Procedure prototypes for static procedures in this file:
32 static int AddLocalLiteralEntry _ANSI_ARGS_((
33 CompileEnv *envPtr, LiteralEntry *globalPtr,
35 static void ExpandLocalLiteralArray _ANSI_ARGS_((
37 static unsigned int HashString _ANSI_ARGS_((CONST char *bytes,
39 static void RebuildLiteralTable _ANSI_ARGS_((
40 LiteralTable *tablePtr));
43 *----------------------------------------------------------------------
45 * TclInitLiteralTable --
47 * This procedure is called to initialize the fields of a literal table
48 * structure for either an interpreter or a compilation's CompileEnv
55 * The literal table is made ready for use.
57 *----------------------------------------------------------------------
61 TclInitLiteralTable(tablePtr)
62 register LiteralTable *tablePtr; /* Pointer to table structure, which
63 * is supplied by the caller. */
65 #if (TCL_SMALL_HASH_TABLE != 4)
66 panic("TclInitLiteralTable: TCL_SMALL_HASH_TABLE is %d, not 4\n",
67 TCL_SMALL_HASH_TABLE);
70 tablePtr->buckets = tablePtr->staticBuckets;
71 tablePtr->staticBuckets[0] = tablePtr->staticBuckets[1] = 0;
72 tablePtr->staticBuckets[2] = tablePtr->staticBuckets[3] = 0;
73 tablePtr->numBuckets = TCL_SMALL_HASH_TABLE;
74 tablePtr->numEntries = 0;
75 tablePtr->rebuildSize = TCL_SMALL_HASH_TABLE*REBUILD_MULTIPLIER;
80 *----------------------------------------------------------------------
82 * TclDeleteLiteralTable --
84 * This procedure frees up everything associated with a literal table
85 * except for the table's structure itself.
91 * Each literal in the table is released: i.e., its reference count
92 * in the global literal table is decremented and, if it becomes zero,
93 * the literal is freed. In addition, the table's bucket array is
96 *----------------------------------------------------------------------
100 TclDeleteLiteralTable(interp, tablePtr)
101 Tcl_Interp *interp; /* Interpreter containing shared literals
102 * referenced by the table to delete. */
103 LiteralTable *tablePtr; /* Points to the literal table to delete. */
105 LiteralEntry *entryPtr;
109 * Release remaining literals in the table. Note that releasing a
110 * literal might release other literals, modifying the table, so we
111 * restart the search from the bucket chain we last found an entry.
114 #ifdef TCL_COMPILE_DEBUG
115 TclVerifyGlobalLiteralTable((Interp *) interp);
116 #endif /*TCL_COMPILE_DEBUG*/
119 while (tablePtr->numEntries > 0) {
120 for (i = start; i < tablePtr->numBuckets; i++) {
121 entryPtr = tablePtr->buckets[i];
122 if (entryPtr != NULL) {
123 TclReleaseLiteral(interp, entryPtr->objPtr);
131 * Free up the table's bucket array if it was dynamically allocated.
134 if (tablePtr->buckets != tablePtr->staticBuckets) {
135 ckfree((char *) tablePtr->buckets);
140 *----------------------------------------------------------------------
142 * TclRegisterLiteral --
144 * Find, or if necessary create, an object in a CompileEnv literal
145 * array that has a string representation matching the argument string.
148 * The index in the CompileEnv's literal array that references a
149 * shared literal matching the string. The object is created if
153 * To maximize sharing, we look up the string in the interpreter's
154 * global literal table. If not found, we create a new shared literal
155 * in the global table. We then add a reference to the shared
156 * literal in the CompileEnv's literal array.
158 * If onHeap is 1, this procedure is given ownership of the string: if
159 * an object is created then its string representation is set directly
160 * from string, otherwise the string is freed. Typically, a caller sets
161 * onHeap 1 if "string" is an already heap-allocated buffer holding the
162 * result of backslash substitutions.
164 *----------------------------------------------------------------------
168 TclRegisterLiteral(envPtr, bytes, length, onHeap)
169 CompileEnv *envPtr; /* Points to the CompileEnv in whose object
170 * array an object is found or created. */
171 register char *bytes; /* Points to string for which to find or
172 * create an object in CompileEnv's object
174 int length; /* Number of bytes in the string. If < 0,
175 * the string consists of all bytes up to
176 * the first null character. */
177 int onHeap; /* If 1 then the caller already malloc'd
178 * bytes and ownership is passed to this
181 Interp *iPtr = envPtr->iPtr;
182 LiteralTable *globalTablePtr = &(iPtr->literalTable);
183 LiteralTable *localTablePtr = &(envPtr->localLitTable);
184 register LiteralEntry *globalPtr, *localPtr;
185 register Tcl_Obj *objPtr;
187 int localHash, globalHash, objIndex;
189 char buf[TCL_INTEGER_SPACE];
192 length = (bytes? strlen(bytes) : 0);
194 hash = HashString(bytes, length);
197 * Is the literal already in the CompileEnv's local literal array?
198 * If so, just return its index.
201 localHash = (hash & localTablePtr->mask);
202 for (localPtr = localTablePtr->buckets[localHash];
203 localPtr != NULL; localPtr = localPtr->nextPtr) {
204 objPtr = localPtr->objPtr;
205 if ((objPtr->length == length) && ((length == 0)
206 || ((objPtr->bytes[0] == bytes[0])
207 && (memcmp(objPtr->bytes, bytes, (unsigned) length)
212 objIndex = (localPtr - envPtr->literalArrayPtr);
213 #ifdef TCL_COMPILE_DEBUG
214 TclVerifyLocalLiteralTable(envPtr);
215 #endif /*TCL_COMPILE_DEBUG*/
222 * The literal is new to this CompileEnv. Is it in the interpreter's
223 * global literal table?
226 globalHash = (hash & globalTablePtr->mask);
227 for (globalPtr = globalTablePtr->buckets[globalHash];
228 globalPtr != NULL; globalPtr = globalPtr->nextPtr) {
229 objPtr = globalPtr->objPtr;
230 if ((objPtr->length == length) && ((length == 0)
231 || ((objPtr->bytes[0] == bytes[0])
232 && (memcmp(objPtr->bytes, bytes, (unsigned) length)
235 * A global literal was found. Add an entry to the CompileEnv's
236 * local literal array.
242 objIndex = AddLocalLiteralEntry(envPtr, globalPtr, localHash);
243 #ifdef TCL_COMPILE_DEBUG
244 if (globalPtr->refCount < 1) {
245 panic("TclRegisterLiteral: global literal \"%.*s\" had bad refCount %d",
246 (length>60? 60 : length), bytes,
247 globalPtr->refCount);
249 TclVerifyLocalLiteralTable(envPtr);
250 #endif /*TCL_COMPILE_DEBUG*/
256 * The literal is new to the interpreter. Add it to the global literal
257 * table then add an entry to the CompileEnv's local literal array.
258 * Convert the object to an integer object if possible.
262 Tcl_IncrRefCount(objPtr);
264 objPtr->bytes = bytes;
265 objPtr->length = length;
267 TclInitStringRep(objPtr, bytes, length);
270 if (TclLooksLikeInt(bytes, length)) {
272 * From here we use the objPtr, because it is NULL terminated
274 if (TclGetLong((Tcl_Interp *) NULL, objPtr->bytes, &n) == TCL_OK) {
275 TclFormatInt(buf, n);
276 if (strcmp(objPtr->bytes, buf) == 0) {
277 objPtr->internalRep.longValue = n;
278 objPtr->typePtr = &tclIntType;
283 #ifdef TCL_COMPILE_DEBUG
284 if (TclLookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
285 panic("TclRegisterLiteral: literal \"%.*s\" found globally but shouldn't be",
286 (length>60? 60 : length), bytes);
290 globalPtr = (LiteralEntry *) ckalloc((unsigned) sizeof(LiteralEntry));
291 globalPtr->objPtr = objPtr;
292 globalPtr->refCount = 0;
293 globalPtr->nextPtr = globalTablePtr->buckets[globalHash];
294 globalTablePtr->buckets[globalHash] = globalPtr;
295 globalTablePtr->numEntries++;
298 * If the global literal table has exceeded a decent size, rebuild it
302 if (globalTablePtr->numEntries >= globalTablePtr->rebuildSize) {
303 RebuildLiteralTable(globalTablePtr);
305 objIndex = AddLocalLiteralEntry(envPtr, globalPtr, localHash);
307 #ifdef TCL_COMPILE_DEBUG
308 TclVerifyGlobalLiteralTable(iPtr);
309 TclVerifyLocalLiteralTable(envPtr);
311 LiteralEntry *entryPtr;
314 for (i = 0; i < globalTablePtr->numBuckets; i++) {
315 for (entryPtr = globalTablePtr->buckets[i];
316 entryPtr != NULL; entryPtr = entryPtr->nextPtr) {
317 if ((entryPtr == globalPtr)
318 && (entryPtr->objPtr == objPtr)) {
324 panic("TclRegisterLiteral: literal \"%.*s\" wasn't global",
325 (length>60? 60 : length), bytes);
328 #endif /*TCL_COMPILE_DEBUG*/
329 #ifdef TCL_COMPILE_STATS
330 iPtr->stats.numLiteralsCreated++;
331 iPtr->stats.totalLitStringBytes += (double) (length + 1);
332 iPtr->stats.currentLitStringBytes += (double) (length + 1);
333 iPtr->stats.literalCount[TclLog2(length)]++;
334 #endif /*TCL_COMPILE_STATS*/
339 *----------------------------------------------------------------------
341 * TclLookupLiteralEntry --
343 * Finds the LiteralEntry that corresponds to a literal Tcl object
347 * Returns the matching LiteralEntry if found, otherwise NULL.
352 *----------------------------------------------------------------------
356 TclLookupLiteralEntry(interp, objPtr)
357 Tcl_Interp *interp; /* Interpreter for which objPtr was created
358 * to hold a literal. */
359 register Tcl_Obj *objPtr; /* Points to a Tcl object holding a
360 * literal that was previously created by a
361 * call to TclRegisterLiteral. */
363 Interp *iPtr = (Interp *) interp;
364 LiteralTable *globalTablePtr = &(iPtr->literalTable);
365 register LiteralEntry *entryPtr;
367 int length, globalHash;
369 bytes = Tcl_GetStringFromObj(objPtr, &length);
370 globalHash = (HashString(bytes, length) & globalTablePtr->mask);
371 for (entryPtr = globalTablePtr->buckets[globalHash];
372 entryPtr != NULL; entryPtr = entryPtr->nextPtr) {
373 if (entryPtr->objPtr == objPtr) {
381 *----------------------------------------------------------------------
385 * Remove a literal entry from the literal hash tables, leaving it in
386 * the literal array so existing references continue to function.
387 * This makes it possible to turn a shared literal into a private
388 * literal that cannot be shared.
394 * Removes the literal from the local hash table and decrements the
395 * global hash entry's reference count.
397 *----------------------------------------------------------------------
401 TclHideLiteral(interp, envPtr, index)
402 Tcl_Interp *interp; /* Interpreter for which objPtr was created
403 * to hold a literal. */
404 register CompileEnv *envPtr; /* Points to CompileEnv whose literal array
405 * contains the entry being hidden. */
406 int index; /* The index of the entry in the literal
409 LiteralEntry **nextPtrPtr, *entryPtr, *lPtr;
410 LiteralTable *localTablePtr = &(envPtr->localLitTable);
411 int localHash, length;
415 lPtr = &(envPtr->literalArrayPtr[index]);
418 * To avoid unwanted sharing we need to copy the object and remove it from
419 * the local and global literal tables. It still has a slot in the literal
420 * array so it can be referred to by byte codes, but it will not be matched
421 * by literal searches.
424 newObjPtr = Tcl_DuplicateObj(lPtr->objPtr);
425 Tcl_IncrRefCount(newObjPtr);
426 TclReleaseLiteral(interp, lPtr->objPtr);
427 lPtr->objPtr = newObjPtr;
429 bytes = Tcl_GetStringFromObj(newObjPtr, &length);
430 localHash = (HashString(bytes, length) & localTablePtr->mask);
431 nextPtrPtr = &localTablePtr->buckets[localHash];
433 for (entryPtr = *nextPtrPtr; entryPtr != NULL; entryPtr = *nextPtrPtr) {
434 if (entryPtr == lPtr) {
435 *nextPtrPtr = lPtr->nextPtr;
436 lPtr->nextPtr = NULL;
437 localTablePtr->numEntries--;
440 nextPtrPtr = &entryPtr->nextPtr;
445 *----------------------------------------------------------------------
447 * TclAddLiteralObj --
449 * Add a single literal object to the literal array. This
450 * function does not add the literal to the local or global
451 * literal tables. The caller is expected to add the entry
452 * to whatever tables are appropriate.
455 * The index in the CompileEnv's literal array that references the
456 * literal. Stores the pointer to the new literal entry in the
457 * location referenced by the localPtrPtr argument.
460 * Expands the literal array if necessary. Increments the refcount
461 * on the literal object.
463 *----------------------------------------------------------------------
467 TclAddLiteralObj(envPtr, objPtr, litPtrPtr)
468 register CompileEnv *envPtr; /* Points to CompileEnv in whose literal
469 * array the object is to be inserted. */
470 Tcl_Obj *objPtr; /* The object to insert into the array. */
471 LiteralEntry **litPtrPtr; /* The location where the pointer to the
472 * new literal entry should be stored.
475 register LiteralEntry *lPtr;
478 if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) {
479 ExpandLocalLiteralArray(envPtr);
481 objIndex = envPtr->literalArrayNext;
482 envPtr->literalArrayNext++;
484 lPtr = &(envPtr->literalArrayPtr[objIndex]);
485 lPtr->objPtr = objPtr;
486 Tcl_IncrRefCount(objPtr);
487 lPtr->refCount = -1; /* i.e., unused */
488 lPtr->nextPtr = NULL;
498 *----------------------------------------------------------------------
500 * AddLocalLiteralEntry --
502 * Insert a new literal into a CompileEnv's local literal array.
505 * The index in the CompileEnv's literal array that references the
509 * Increments the ref count of the global LiteralEntry since the
510 * CompileEnv now refers to the literal. Expands the literal array
511 * if necessary. May rebuild the hash bucket array of the CompileEnv's
512 * literal array if it becomes too large.
514 *----------------------------------------------------------------------
518 AddLocalLiteralEntry(envPtr, globalPtr, localHash)
519 register CompileEnv *envPtr; /* Points to CompileEnv in whose literal
520 * array the object is to be inserted. */
521 LiteralEntry *globalPtr; /* Points to the global LiteralEntry for
522 * the literal to add to the CompileEnv. */
523 int localHash; /* Hash value for the literal's string. */
525 register LiteralTable *localTablePtr = &(envPtr->localLitTable);
526 LiteralEntry *localPtr;
529 objIndex = TclAddLiteralObj(envPtr, globalPtr->objPtr, &localPtr);
532 * Add the literal to the local table.
535 localPtr->nextPtr = localTablePtr->buckets[localHash];
536 localTablePtr->buckets[localHash] = localPtr;
537 localTablePtr->numEntries++;
539 globalPtr->refCount++;
542 * If the CompileEnv's local literal table has exceeded a decent size,
543 * rebuild it with more buckets.
546 if (localTablePtr->numEntries >= localTablePtr->rebuildSize) {
547 RebuildLiteralTable(localTablePtr);
550 #ifdef TCL_COMPILE_DEBUG
551 TclVerifyLocalLiteralTable(envPtr);
554 int length, found, i;
556 for (i = 0; i < localTablePtr->numBuckets; i++) {
557 for (localPtr = localTablePtr->buckets[i];
558 localPtr != NULL; localPtr = localPtr->nextPtr) {
559 if (localPtr->objPtr == globalPtr->objPtr) {
565 bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
566 panic("AddLocalLiteralEntry: literal \"%.*s\" wasn't found locally",
567 (length>60? 60 : length), bytes);
570 #endif /*TCL_COMPILE_DEBUG*/
575 *----------------------------------------------------------------------
577 * ExpandLocalLiteralArray --
579 * Procedure that uses malloc to allocate more storage for a
580 * CompileEnv's local literal array.
586 * The literal array in *envPtr is reallocated to a new array of
587 * double the size, and if envPtr->mallocedLiteralArray is non-zero
588 * the old array is freed. Entries are copied from the old array
589 * to the new one. The local literal table is updated to refer to
592 *----------------------------------------------------------------------
596 ExpandLocalLiteralArray(envPtr)
597 register CompileEnv *envPtr; /* Points to the CompileEnv whose object
598 * array must be enlarged. */
601 * The current allocated local literal entries are stored between
602 * elements 0 and (envPtr->literalArrayNext - 1) [inclusive].
605 LiteralTable *localTablePtr = &(envPtr->localLitTable);
606 int currElems = envPtr->literalArrayNext;
607 size_t currBytes = (currElems * sizeof(LiteralEntry));
608 register LiteralEntry *currArrayPtr = envPtr->literalArrayPtr;
609 register LiteralEntry *newArrayPtr =
610 (LiteralEntry *) ckalloc((unsigned) (2 * currBytes));
614 * Copy from the old literal array to the new, then update the local
615 * literal table's bucket array.
618 memcpy((VOID *) newArrayPtr, (VOID *) currArrayPtr, currBytes);
619 for (i = 0; i < currElems; i++) {
620 if (currArrayPtr[i].nextPtr == NULL) {
621 newArrayPtr[i].nextPtr = NULL;
623 newArrayPtr[i].nextPtr = newArrayPtr
624 + (currArrayPtr[i].nextPtr - currArrayPtr);
627 for (i = 0; i < localTablePtr->numBuckets; i++) {
628 if (localTablePtr->buckets[i] != NULL) {
629 localTablePtr->buckets[i] = newArrayPtr
630 + (localTablePtr->buckets[i] - currArrayPtr);
635 * Free the old literal array if needed, and mark the new literal
639 if (envPtr->mallocedLiteralArray) {
640 ckfree((char *) currArrayPtr);
642 envPtr->literalArrayPtr = newArrayPtr;
643 envPtr->literalArrayEnd = (2 * currElems);
644 envPtr->mallocedLiteralArray = 1;
648 *----------------------------------------------------------------------
650 * TclReleaseLiteral --
652 * This procedure releases a reference to one of the shared Tcl objects
653 * that hold literals. It is called to release the literals referenced
654 * by a ByteCode that is being destroyed, and it is also called by
655 * TclDeleteLiteralTable.
661 * The reference count for the global LiteralTable entry that
662 * corresponds to the literal is decremented. If no other reference
663 * to a global literal object remains, it is freed.
665 *----------------------------------------------------------------------
669 TclReleaseLiteral(interp, objPtr)
670 Tcl_Interp *interp; /* Interpreter for which objPtr was created
671 * to hold a literal. */
672 register Tcl_Obj *objPtr; /* Points to a literal object that was
673 * previously created by a call to
674 * TclRegisterLiteral. */
676 Interp *iPtr = (Interp *) interp;
677 LiteralTable *globalTablePtr = &(iPtr->literalTable);
678 register LiteralEntry *entryPtr, *prevPtr;
683 bytes = Tcl_GetStringFromObj(objPtr, &length);
684 index = (HashString(bytes, length) & globalTablePtr->mask);
687 * Check to see if the object is in the global literal table and
688 * remove this reference. The object may not be in the table if
689 * it is a hidden local literal.
692 for (prevPtr = NULL, entryPtr = globalTablePtr->buckets[index];
694 prevPtr = entryPtr, entryPtr = entryPtr->nextPtr) {
695 if (entryPtr->objPtr == objPtr) {
696 entryPtr->refCount--;
699 * If the literal is no longer being used by any ByteCode,
700 * delete the entry then remove the reference corresponding
701 * to the global literal table entry (decrement the ref count
705 if (entryPtr->refCount == 0) {
706 if (prevPtr == NULL) {
707 globalTablePtr->buckets[index] = entryPtr->nextPtr;
709 prevPtr->nextPtr = entryPtr->nextPtr;
711 ckfree((char *) entryPtr);
712 globalTablePtr->numEntries--;
714 TclDecrRefCount(objPtr);
717 * Check if the LiteralEntry is only being kept alive by
718 * a circular reference from a ByteCode stored as its
719 * internal rep. In that case, set the ByteCode object array
720 * entry NULL to signal to TclCleanupByteCode to not try to
721 * release this about to be freed literal again.
724 if (objPtr->typePtr == &tclByteCodeType) {
725 codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;
726 if ((codePtr->numLitObjects == 1)
727 && (codePtr->objArrayPtr[0] == objPtr)) {
728 codePtr->objArrayPtr[0] = NULL;
732 #ifdef TCL_COMPILE_STATS
733 iPtr->stats.currentLitStringBytes -= (double) (length + 1);
734 #endif /*TCL_COMPILE_STATS*/
741 * Remove the reference corresponding to the local literal table
745 Tcl_DecrRefCount(objPtr);
749 *----------------------------------------------------------------------
753 * Compute a one-word summary of a text string, which can be
754 * used to generate a hash index.
757 * The return value is a one-word summary of the information in
763 *----------------------------------------------------------------------
767 HashString(bytes, length)
768 register CONST char *bytes; /* String for which to compute hash
770 int length; /* Number of bytes in the string. */
772 register unsigned int result;
776 * I tried a zillion different hash functions and asked many other
777 * people for advice. Many people had their own favorite functions,
778 * all different, but no-one had much idea why they were good ones.
779 * I chose the one below (multiply by 9 and add new character)
780 * because of the following reasons:
782 * 1. Multiplying by 10 is perfect for keys that are decimal strings,
783 * and multiplying by 9 is just about as good.
784 * 2. Times-9 is (shift-left-3) plus (old). This means that each
785 * character's bits hang around in the low-order bits of the
786 * hash value for ever, plus they spread fairly rapidly up to
787 * the high-order bits to fill out the hash value. This seems
788 * works well both for decimal and non-decimal strings.
792 for (i = 0; i < length; i++) {
793 result += (result<<3) + *bytes++;
799 *----------------------------------------------------------------------
801 * RebuildLiteralTable --
803 * This procedure is invoked when the ratio of entries to hash buckets
804 * becomes too large in a local or global literal table. It allocates
805 * a larger bucket array and moves the entries into the new buckets.
811 * Memory gets reallocated and entries get rehashed into new buckets.
813 *----------------------------------------------------------------------
817 RebuildLiteralTable(tablePtr)
818 register LiteralTable *tablePtr; /* Local or global table to enlarge. */
820 LiteralEntry **oldBuckets;
821 register LiteralEntry **oldChainPtr, **newChainPtr;
822 register LiteralEntry *entryPtr;
823 LiteralEntry **bucketPtr;
825 int oldSize, count, index, length;
827 oldSize = tablePtr->numBuckets;
828 oldBuckets = tablePtr->buckets;
831 * Allocate and initialize the new bucket array, and set up
832 * hashing constants for new array size.
835 tablePtr->numBuckets *= 4;
836 tablePtr->buckets = (LiteralEntry **) ckalloc((unsigned)
837 (tablePtr->numBuckets * sizeof(LiteralEntry *)));
838 for (count = tablePtr->numBuckets, newChainPtr = tablePtr->buckets;
840 count--, newChainPtr++) {
843 tablePtr->rebuildSize *= 4;
844 tablePtr->mask = (tablePtr->mask << 2) + 3;
847 * Rehash all of the existing entries into the new bucket array.
850 for (oldChainPtr = oldBuckets;
852 oldSize--, oldChainPtr++) {
853 for (entryPtr = *oldChainPtr; entryPtr != NULL;
854 entryPtr = *oldChainPtr) {
855 bytes = Tcl_GetStringFromObj(entryPtr->objPtr, &length);
856 index = (HashString(bytes, length) & tablePtr->mask);
858 *oldChainPtr = entryPtr->nextPtr;
859 bucketPtr = &(tablePtr->buckets[index]);
860 entryPtr->nextPtr = *bucketPtr;
861 *bucketPtr = entryPtr;
866 * Free up the old bucket array, if it was dynamically allocated.
869 if (oldBuckets != tablePtr->staticBuckets) {
870 ckfree((char *) oldBuckets);
874 #ifdef TCL_COMPILE_STATS
876 *----------------------------------------------------------------------
880 * Return statistics describing the layout of the hash table
881 * in its hash buckets.
884 * The return value is a malloc-ed string containing information
885 * about tablePtr. It is the caller's responsibility to free
891 *----------------------------------------------------------------------
895 TclLiteralStats(tablePtr)
896 LiteralTable *tablePtr; /* Table for which to produce stats. */
898 #define NUM_COUNTERS 10
899 int count[NUM_COUNTERS], overflow, i, j;
901 register LiteralEntry *entryPtr;
905 * Compute a histogram of bucket usage. For each bucket chain i,
906 * j is the number of entries in the chain.
909 for (i = 0; i < NUM_COUNTERS; i++) {
914 for (i = 0; i < tablePtr->numBuckets; i++) {
916 for (entryPtr = tablePtr->buckets[i]; entryPtr != NULL;
917 entryPtr = entryPtr->nextPtr) {
920 if (j < NUM_COUNTERS) {
926 average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
930 * Print out the histogram and a few other pieces of information.
933 result = (char *) ckalloc((unsigned) ((NUM_COUNTERS*60) + 300));
934 sprintf(result, "%d entries in table, %d buckets\n",
935 tablePtr->numEntries, tablePtr->numBuckets);
936 p = result + strlen(result);
937 for (i = 0; i < NUM_COUNTERS; i++) {
938 sprintf(p, "number of buckets with %d entries: %d\n",
942 sprintf(p, "number of buckets with %d or more entries: %d\n",
943 NUM_COUNTERS, overflow);
945 sprintf(p, "average search distance for entry: %.1f", average);
948 #endif /*TCL_COMPILE_STATS*/
950 #ifdef TCL_COMPILE_DEBUG
952 *----------------------------------------------------------------------
954 * TclVerifyLocalLiteralTable --
956 * Check a CompileEnv's local literal table for consistency.
962 * Panics if problems are found.
964 *----------------------------------------------------------------------
968 TclVerifyLocalLiteralTable(envPtr)
969 CompileEnv *envPtr; /* Points to CompileEnv whose literal
970 * table is to be validated. */
972 register LiteralTable *localTablePtr = &(envPtr->localLitTable);
973 register LiteralEntry *localPtr;
979 for (i = 0; i < localTablePtr->numBuckets; i++) {
980 for (localPtr = localTablePtr->buckets[i];
981 localPtr != NULL; localPtr = localPtr->nextPtr) {
983 if (localPtr->refCount != -1) {
984 bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
985 panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" had bad refCount %d",
986 (length>60? 60 : length), bytes,
989 if (TclLookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,
990 localPtr->objPtr) == NULL) {
991 bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
992 panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" is not global",
993 (length>60? 60 : length), bytes);
995 if (localPtr->objPtr->bytes == NULL) {
996 panic("TclVerifyLocalLiteralTable: literal has NULL string rep");
1000 if (count != localTablePtr->numEntries) {
1001 panic("TclVerifyLocalLiteralTable: local literal table had %d entries, should be %d",
1002 count, localTablePtr->numEntries);
1007 *----------------------------------------------------------------------
1009 * TclVerifyGlobalLiteralTable --
1011 * Check an interpreter's global literal table literal for consistency.
1017 * Panics if problems are found.
1019 *----------------------------------------------------------------------
1023 TclVerifyGlobalLiteralTable(iPtr)
1024 Interp *iPtr; /* Points to interpreter whose global
1025 * literal table is to be validated. */
1027 register LiteralTable *globalTablePtr = &(iPtr->literalTable);
1028 register LiteralEntry *globalPtr;
1034 for (i = 0; i < globalTablePtr->numBuckets; i++) {
1035 for (globalPtr = globalTablePtr->buckets[i];
1036 globalPtr != NULL; globalPtr = globalPtr->nextPtr) {
1038 if (globalPtr->refCount < 1) {
1039 bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
1040 panic("TclVerifyGlobalLiteralTable: global literal \"%.*s\" had bad refCount %d",
1041 (length>60? 60 : length), bytes,
1042 globalPtr->refCount);
1044 if (globalPtr->objPtr->bytes == NULL) {
1045 panic("TclVerifyGlobalLiteralTable: literal has NULL string rep");
1049 if (count != globalTablePtr->numEntries) {
1050 panic("TclVerifyGlobalLiteralTable: global literal table had %d entries, should be %d",
1051 count, globalTablePtr->numEntries);
1054 #endif /*TCL_COMPILE_DEBUG*/