os/persistentdata/persistentstorage/sqlite3api/TEST/TCL/tcldistribution/generic/tclLiteral.c
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 /* 
     2  * tclLiteral.c --
     3  *
     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.
     9  *
    10  * Copyright (c) 1997-1998 Sun Microsystems, Inc.
    11  *
    12  * See the file "license.terms" for information on usage and redistribution
    13  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
    14  *
    15  * RCS: @(#) $Id: tclLiteral.c,v 1.11 2001/10/11 22:28:01 msofer Exp $
    16  */
    17 
    18 #include "tclInt.h"
    19 #include "tclCompile.h"
    20 #include "tclPort.h"
    21 /*
    22  * When there are this many entries per bucket, on average, rebuild
    23  * a literal's hash table to make it larger.
    24  */
    25 
    26 #define REBUILD_MULTIPLIER	3
    27 
    28 /*
    29  * Procedure prototypes for static procedures in this file:
    30  */
    31 
    32 static int		AddLocalLiteralEntry _ANSI_ARGS_((
    33 			    CompileEnv *envPtr, LiteralEntry *globalPtr,
    34 			    int localHash));
    35 static void		ExpandLocalLiteralArray _ANSI_ARGS_((
    36 			    CompileEnv *envPtr));
    37 static unsigned int	HashString _ANSI_ARGS_((CONST char *bytes,
    38 			    int length));
    39 static void		RebuildLiteralTable _ANSI_ARGS_((
    40 			    LiteralTable *tablePtr));
    41 
    42 /*
    43  *----------------------------------------------------------------------
    44  *
    45  * TclInitLiteralTable --
    46  *
    47  *	This procedure is called to initialize the fields of a literal table
    48  *	structure for either an interpreter or a compilation's CompileEnv
    49  *	structure.
    50  *
    51  * Results:
    52  *	None.
    53  *
    54  * Side effects: 
    55  *	The literal table is made ready for use.
    56  *
    57  *----------------------------------------------------------------------
    58  */
    59 
    60 void
    61 TclInitLiteralTable(tablePtr)
    62     register LiteralTable *tablePtr; /* Pointer to table structure, which
    63 				      * is supplied by the caller. */
    64 {
    65 #if (TCL_SMALL_HASH_TABLE != 4) 
    66     panic("TclInitLiteralTable: TCL_SMALL_HASH_TABLE is %d, not 4\n",
    67 	    TCL_SMALL_HASH_TABLE);
    68 #endif
    69     
    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;
    76     tablePtr->mask = 3;
    77 }
    78 
    79 /*
    80  *----------------------------------------------------------------------
    81  *
    82  * TclDeleteLiteralTable --
    83  *
    84  *	This procedure frees up everything associated with a literal table
    85  *	except for the table's structure itself.
    86  *
    87  * Results:
    88  *	None.
    89  *
    90  * Side effects:
    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
    94  *	freed.
    95  *
    96  *----------------------------------------------------------------------
    97  */
    98 
    99 void
   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. */
   104 {
   105     LiteralEntry *entryPtr;
   106     int i, start;
   107 
   108     /*
   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.
   112      */
   113 
   114 #ifdef TCL_COMPILE_DEBUG
   115     TclVerifyGlobalLiteralTable((Interp *) interp);
   116 #endif /*TCL_COMPILE_DEBUG*/
   117 
   118     start = 0;
   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);
   124 		start = i;
   125 		break;
   126 	    }
   127 	}
   128     }
   129 
   130     /*
   131      * Free up the table's bucket array if it was dynamically allocated.
   132      */
   133 
   134     if (tablePtr->buckets != tablePtr->staticBuckets) {
   135 	ckfree((char *) tablePtr->buckets);
   136     }
   137 }
   138 
   139 /*
   140  *----------------------------------------------------------------------
   141  *
   142  * TclRegisterLiteral --
   143  *
   144  *	Find, or if necessary create, an object in a CompileEnv literal
   145  *	array that has a string representation matching the argument string.
   146  *
   147  * Results:
   148  *	The index in the CompileEnv's literal array that references a
   149  *	shared literal matching the string. The object is created if
   150  *	necessary.
   151  *
   152  * Side effects:
   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. 
   157  *
   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.
   163  *
   164  *----------------------------------------------------------------------
   165  */
   166 
   167 int
   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
   173 				 * array. */
   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
   179 				 * procedure. */
   180 {
   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;
   186     unsigned int hash;
   187     int localHash, globalHash, objIndex;
   188     long n;
   189     char buf[TCL_INTEGER_SPACE];
   190 
   191     if (length < 0) {
   192 	length = (bytes? strlen(bytes) : 0);
   193     }
   194     hash = HashString(bytes, length);
   195 
   196     /*
   197      * Is the literal already in the CompileEnv's local literal array?
   198      * If so, just return its index.
   199      */
   200 
   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)
   208 				== 0)))) {
   209 	    if (onHeap) {
   210 		ckfree(bytes);
   211 	    }
   212 	    objIndex = (localPtr - envPtr->literalArrayPtr);
   213 #ifdef TCL_COMPILE_DEBUG
   214 	    TclVerifyLocalLiteralTable(envPtr);
   215 #endif /*TCL_COMPILE_DEBUG*/
   216 
   217 	    return objIndex;
   218 	}
   219     }
   220 
   221     /*
   222      * The literal is new to this CompileEnv. Is it in the interpreter's
   223      * global literal table?
   224      */
   225 
   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)
   233 				== 0)))) {
   234 	    /*
   235 	     * A global literal was found. Add an entry to the CompileEnv's
   236 	     * local literal array.
   237 	     */
   238 	    
   239 	    if (onHeap) {
   240 		ckfree(bytes);
   241 	    }
   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);
   248 	    }
   249 	    TclVerifyLocalLiteralTable(envPtr);
   250 #endif /*TCL_COMPILE_DEBUG*/ 
   251 	    return objIndex;
   252 	}
   253     }
   254 
   255     /*
   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.
   259      */
   260 
   261     TclNewObj(objPtr);
   262     Tcl_IncrRefCount(objPtr);
   263     if (onHeap) {
   264 	objPtr->bytes = bytes;
   265 	objPtr->length = length;
   266     } else {
   267 	TclInitStringRep(objPtr, bytes, length);
   268     }
   269 
   270     if (TclLooksLikeInt(bytes, length)) {
   271 	/*
   272 	 * From here we use the objPtr, because it is NULL terminated
   273 	 */
   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;
   279 	    }
   280 	}
   281     }
   282     
   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);
   287     }
   288 #endif
   289 
   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++;
   296 
   297     /*
   298      * If the global literal table has exceeded a decent size, rebuild it
   299      * with more buckets.
   300      */
   301 
   302     if (globalTablePtr->numEntries >= globalTablePtr->rebuildSize) {
   303 	RebuildLiteralTable(globalTablePtr);
   304     }
   305     objIndex = AddLocalLiteralEntry(envPtr, globalPtr, localHash);
   306 
   307 #ifdef TCL_COMPILE_DEBUG
   308     TclVerifyGlobalLiteralTable(iPtr);
   309     TclVerifyLocalLiteralTable(envPtr);
   310     {
   311 	LiteralEntry *entryPtr;
   312 	int found, i;
   313 	found = 0;
   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)) {
   319 		    found = 1;
   320 		}
   321 	    }
   322 	}
   323 	if (!found) {
   324 	    panic("TclRegisterLiteral: literal \"%.*s\" wasn't global",
   325 	            (length>60? 60 : length), bytes);
   326 	}
   327     }
   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*/
   335     return objIndex;
   336 }
   337 
   338 /*
   339  *----------------------------------------------------------------------
   340  *
   341  * TclLookupLiteralEntry --
   342  *
   343  *	Finds the LiteralEntry that corresponds to a literal Tcl object
   344  *      holding a literal.
   345  *
   346  * Results:
   347  *      Returns the matching LiteralEntry if found, otherwise NULL.
   348  *
   349  * Side effects:
   350  *      None.
   351  *
   352  *----------------------------------------------------------------------
   353  */
   354 
   355 LiteralEntry *
   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. */
   362 {
   363     Interp *iPtr = (Interp *) interp;
   364     LiteralTable *globalTablePtr = &(iPtr->literalTable);
   365     register LiteralEntry *entryPtr;
   366     char *bytes;
   367     int length, globalHash;
   368 
   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) {
   374             return entryPtr;
   375         }
   376     }
   377     return NULL;
   378 }
   379 
   380 /*
   381  *----------------------------------------------------------------------
   382  *
   383  * TclHideLiteral --
   384  *
   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.
   389  *
   390  * Results:
   391  *	None.
   392  *
   393  * Side effects:
   394  *	Removes the literal from the local hash table and decrements the
   395  *	global hash entry's reference count.
   396  *
   397  *----------------------------------------------------------------------
   398  */
   399 
   400 void
   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
   407 				  * array. */
   408 {
   409     LiteralEntry **nextPtrPtr, *entryPtr, *lPtr;
   410     LiteralTable *localTablePtr = &(envPtr->localLitTable);
   411     int localHash, length;
   412     char *bytes;
   413     Tcl_Obj *newObjPtr;
   414 
   415     lPtr = &(envPtr->literalArrayPtr[index]);
   416 
   417     /*
   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.
   422      */
   423 
   424     newObjPtr = Tcl_DuplicateObj(lPtr->objPtr);
   425     Tcl_IncrRefCount(newObjPtr);
   426     TclReleaseLiteral(interp, lPtr->objPtr);
   427     lPtr->objPtr = newObjPtr;
   428 
   429     bytes = Tcl_GetStringFromObj(newObjPtr, &length);
   430     localHash = (HashString(bytes, length) & localTablePtr->mask);
   431     nextPtrPtr = &localTablePtr->buckets[localHash];
   432 
   433     for (entryPtr = *nextPtrPtr; entryPtr != NULL; entryPtr = *nextPtrPtr) {
   434 	if (entryPtr == lPtr) {
   435 	    *nextPtrPtr = lPtr->nextPtr;
   436 	    lPtr->nextPtr = NULL;
   437 	    localTablePtr->numEntries--;
   438 	    break;
   439 	}
   440 	nextPtrPtr = &entryPtr->nextPtr;
   441     }
   442 }
   443 
   444 /*
   445  *----------------------------------------------------------------------
   446  *
   447  * TclAddLiteralObj --
   448  *
   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.
   453  *
   454  * Results:
   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.
   458  *
   459  * Side effects:
   460  *	Expands the literal array if necessary.  Increments the refcount
   461  *	on the literal object.
   462  *
   463  *----------------------------------------------------------------------
   464  */
   465 
   466 int
   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.
   473 				  * May be NULL. */
   474 {
   475     register LiteralEntry *lPtr;
   476     int objIndex;
   477 
   478     if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) {
   479 	ExpandLocalLiteralArray(envPtr);
   480     }
   481     objIndex = envPtr->literalArrayNext;
   482     envPtr->literalArrayNext++;
   483 
   484     lPtr = &(envPtr->literalArrayPtr[objIndex]);
   485     lPtr->objPtr = objPtr;
   486     Tcl_IncrRefCount(objPtr);
   487     lPtr->refCount = -1;	/* i.e., unused */
   488     lPtr->nextPtr = NULL;
   489 
   490     if (litPtrPtr) {
   491 	*litPtrPtr = lPtr;
   492     }
   493 
   494     return objIndex;
   495 }
   496 
   497 /*
   498  *----------------------------------------------------------------------
   499  *
   500  * AddLocalLiteralEntry --
   501  *
   502  *	Insert a new literal into a CompileEnv's local literal array.
   503  *
   504  * Results:
   505  *	The index in the CompileEnv's literal array that references the
   506  *	literal.
   507  *
   508  * Side effects:
   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.
   513  *
   514  *----------------------------------------------------------------------
   515  */
   516 
   517 static int
   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. */
   524 {
   525     register LiteralTable *localTablePtr = &(envPtr->localLitTable);
   526     LiteralEntry *localPtr;
   527     int objIndex;
   528     
   529     objIndex = TclAddLiteralObj(envPtr, globalPtr->objPtr, &localPtr);
   530 
   531     /*
   532      * Add the literal to the local table.
   533      */
   534 
   535     localPtr->nextPtr = localTablePtr->buckets[localHash];
   536     localTablePtr->buckets[localHash] = localPtr;
   537     localTablePtr->numEntries++;
   538 
   539     globalPtr->refCount++;
   540 
   541     /*
   542      * If the CompileEnv's local literal table has exceeded a decent size,
   543      * rebuild it with more buckets.
   544      */
   545 
   546     if (localTablePtr->numEntries >= localTablePtr->rebuildSize) {
   547 	RebuildLiteralTable(localTablePtr);
   548     }
   549 
   550 #ifdef TCL_COMPILE_DEBUG
   551     TclVerifyLocalLiteralTable(envPtr);
   552     {
   553 	char *bytes;
   554 	int length, found, i;
   555 	found = 0;
   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) {
   560 		    found = 1;
   561 		}
   562 	    }
   563 	}
   564 	if (!found) {
   565 	    bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
   566 	    panic("AddLocalLiteralEntry: literal \"%.*s\" wasn't found locally",
   567 	            (length>60? 60 : length), bytes);
   568 	}
   569     }
   570 #endif /*TCL_COMPILE_DEBUG*/
   571     return objIndex;
   572 }
   573 
   574 /*
   575  *----------------------------------------------------------------------
   576  *
   577  * ExpandLocalLiteralArray --
   578  *
   579  *	Procedure that uses malloc to allocate more storage for a
   580  *	CompileEnv's local literal array.
   581  *
   582  * Results:
   583  *	None.
   584  *
   585  * Side effects:
   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
   590  *	the new entries.
   591  *
   592  *----------------------------------------------------------------------
   593  */
   594 
   595 static void
   596 ExpandLocalLiteralArray(envPtr)
   597     register CompileEnv *envPtr; /* Points to the CompileEnv whose object
   598 				  * array must be enlarged. */
   599 {
   600     /*
   601      * The current allocated local literal entries are stored between
   602      * elements 0 and (envPtr->literalArrayNext - 1) [inclusive].
   603      */
   604 
   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));
   611     int i;
   612     
   613     /*
   614      * Copy from the old literal array to the new, then update the local
   615      * literal table's bucket array.
   616      */
   617 
   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;
   622 	} else {
   623 	    newArrayPtr[i].nextPtr = newArrayPtr
   624 		    + (currArrayPtr[i].nextPtr - currArrayPtr);
   625 	}
   626     }
   627     for (i = 0;  i < localTablePtr->numBuckets;  i++) {
   628 	if (localTablePtr->buckets[i] != NULL) {
   629 	    localTablePtr->buckets[i] = newArrayPtr
   630 	            + (localTablePtr->buckets[i] - currArrayPtr);
   631 	}
   632     }
   633 
   634     /*
   635      * Free the old literal array if needed, and mark the new literal
   636      * array as malloced.
   637      */
   638     
   639     if (envPtr->mallocedLiteralArray) {
   640 	ckfree((char *) currArrayPtr);
   641     }
   642     envPtr->literalArrayPtr = newArrayPtr;
   643     envPtr->literalArrayEnd = (2 * currElems);
   644     envPtr->mallocedLiteralArray = 1;
   645 }
   646 
   647 /*
   648  *----------------------------------------------------------------------
   649  *
   650  * TclReleaseLiteral --
   651  *
   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.
   656  *
   657  * Results:
   658  *	None.
   659  *
   660  * Side effects:
   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.
   664  *
   665  *----------------------------------------------------------------------
   666  */
   667 
   668 void
   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. */
   675 {
   676     Interp *iPtr = (Interp *) interp;
   677     LiteralTable *globalTablePtr = &(iPtr->literalTable);
   678     register LiteralEntry *entryPtr, *prevPtr;
   679     ByteCode* codePtr;
   680     char *bytes;
   681     int length, index;
   682 
   683     bytes = Tcl_GetStringFromObj(objPtr, &length);
   684     index = (HashString(bytes, length) & globalTablePtr->mask);
   685 
   686     /*
   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.
   690      */
   691 
   692     for (prevPtr = NULL, entryPtr = globalTablePtr->buckets[index];
   693 	    entryPtr != NULL;
   694 	    prevPtr = entryPtr, entryPtr = entryPtr->nextPtr) {
   695 	if (entryPtr->objPtr == objPtr) {
   696 	    entryPtr->refCount--;
   697 
   698 	    /*
   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 
   702 	     * of the object).
   703 	     */
   704 		
   705 	    if (entryPtr->refCount == 0) {
   706 		if (prevPtr == NULL) {
   707 		    globalTablePtr->buckets[index] = entryPtr->nextPtr;
   708 		} else {
   709 		    prevPtr->nextPtr = entryPtr->nextPtr;
   710 		}
   711 		ckfree((char *) entryPtr);
   712 		globalTablePtr->numEntries--;
   713 
   714 		TclDecrRefCount(objPtr);
   715 
   716 		/*
   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.
   722 		 */
   723 	    
   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;
   729 		    }
   730 		}
   731 
   732 #ifdef TCL_COMPILE_STATS
   733 		iPtr->stats.currentLitStringBytes -= (double) (length + 1);
   734 #endif /*TCL_COMPILE_STATS*/
   735 	    }
   736 	    break;
   737 	}
   738     }
   739     
   740     /*
   741      * Remove the reference corresponding to the local literal table
   742      * entry.
   743      */
   744 
   745     Tcl_DecrRefCount(objPtr);
   746 }
   747 
   748 /*
   749  *----------------------------------------------------------------------
   750  *
   751  * HashString --
   752  *
   753  *	Compute a one-word summary of a text string, which can be
   754  *	used to generate a hash index.
   755  *
   756  * Results:
   757  *	The return value is a one-word summary of the information in
   758  *	string.
   759  *
   760  * Side effects:
   761  *	None.
   762  *
   763  *----------------------------------------------------------------------
   764  */
   765 
   766 static unsigned int
   767 HashString(bytes, length)
   768     register CONST char *bytes; /* String for which to compute hash
   769 				 * value. */
   770     int length;			/* Number of bytes in the string. */
   771 {
   772     register unsigned int result;
   773     register int i;
   774 
   775     /*
   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:
   781      *
   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.
   789      */
   790 
   791     result = 0;
   792     for (i = 0;  i < length;  i++) {
   793 	result += (result<<3) + *bytes++;
   794     }
   795     return result;
   796 }
   797 
   798 /*
   799  *----------------------------------------------------------------------
   800  *
   801  * RebuildLiteralTable --
   802  *
   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.
   806  *
   807  * Results:
   808  *	None.
   809  *
   810  * Side effects:
   811  *	Memory gets reallocated and entries get rehashed into new buckets.
   812  *
   813  *----------------------------------------------------------------------
   814  */
   815 
   816 static void
   817 RebuildLiteralTable(tablePtr)
   818     register LiteralTable *tablePtr; /* Local or global table to enlarge. */
   819 {
   820     LiteralEntry **oldBuckets;
   821     register LiteralEntry **oldChainPtr, **newChainPtr;
   822     register LiteralEntry *entryPtr;
   823     LiteralEntry **bucketPtr;
   824     char *bytes;
   825     int oldSize, count, index, length;
   826 
   827     oldSize = tablePtr->numBuckets;
   828     oldBuckets = tablePtr->buckets;
   829 
   830     /*
   831      * Allocate and initialize the new bucket array, and set up
   832      * hashing constants for new array size.
   833      */
   834 
   835     tablePtr->numBuckets *= 4;
   836     tablePtr->buckets = (LiteralEntry **) ckalloc((unsigned)
   837 	    (tablePtr->numBuckets * sizeof(LiteralEntry *)));
   838     for (count = tablePtr->numBuckets, newChainPtr = tablePtr->buckets;
   839 	    count > 0;
   840 	    count--, newChainPtr++) {
   841 	*newChainPtr = NULL;
   842     }
   843     tablePtr->rebuildSize *= 4;
   844     tablePtr->mask = (tablePtr->mask << 2) + 3;
   845 
   846     /*
   847      * Rehash all of the existing entries into the new bucket array.
   848      */
   849 
   850     for (oldChainPtr = oldBuckets;
   851 	    oldSize > 0;
   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);
   857 	    
   858 	    *oldChainPtr = entryPtr->nextPtr;
   859 	    bucketPtr = &(tablePtr->buckets[index]);
   860 	    entryPtr->nextPtr = *bucketPtr;
   861 	    *bucketPtr = entryPtr;
   862 	}
   863     }
   864 
   865     /*
   866      * Free up the old bucket array, if it was dynamically allocated.
   867      */
   868 
   869     if (oldBuckets != tablePtr->staticBuckets) {
   870 	ckfree((char *) oldBuckets);
   871     }
   872 }
   873 
   874 #ifdef TCL_COMPILE_STATS
   875 /*
   876  *----------------------------------------------------------------------
   877  *
   878  * TclLiteralStats --
   879  *
   880  *	Return statistics describing the layout of the hash table
   881  *	in its hash buckets.
   882  *
   883  * Results:
   884  *	The return value is a malloc-ed string containing information
   885  *	about tablePtr.  It is the caller's responsibility to free
   886  *	this string.
   887  *
   888  * Side effects:
   889  *	None.
   890  *
   891  *----------------------------------------------------------------------
   892  */
   893 
   894 char *
   895 TclLiteralStats(tablePtr)
   896     LiteralTable *tablePtr;	/* Table for which to produce stats. */
   897 {
   898 #define NUM_COUNTERS 10
   899     int count[NUM_COUNTERS], overflow, i, j;
   900     double average, tmp;
   901     register LiteralEntry *entryPtr;
   902     char *result, *p;
   903 
   904     /*
   905      * Compute a histogram of bucket usage. For each bucket chain i,
   906      * j is the number of entries in the chain.
   907      */
   908 
   909     for (i = 0;  i < NUM_COUNTERS;  i++) {
   910 	count[i] = 0;
   911     }
   912     overflow = 0;
   913     average = 0.0;
   914     for (i = 0;  i < tablePtr->numBuckets;  i++) {
   915 	j = 0;
   916 	for (entryPtr = tablePtr->buckets[i];  entryPtr != NULL;
   917 	        entryPtr = entryPtr->nextPtr) {
   918 	    j++;
   919 	}
   920 	if (j < NUM_COUNTERS) {
   921 	    count[j]++;
   922 	} else {
   923 	    overflow++;
   924 	}
   925 	tmp = j;
   926 	average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
   927     }
   928 
   929     /*
   930      * Print out the histogram and a few other pieces of information.
   931      */
   932 
   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",
   939 		i, count[i]);
   940 	p += strlen(p);
   941     }
   942     sprintf(p, "number of buckets with %d or more entries: %d\n",
   943 	    NUM_COUNTERS, overflow);
   944     p += strlen(p);
   945     sprintf(p, "average search distance for entry: %.1f", average);
   946     return result;
   947 }
   948 #endif /*TCL_COMPILE_STATS*/
   949 
   950 #ifdef TCL_COMPILE_DEBUG
   951 /*
   952  *----------------------------------------------------------------------
   953  *
   954  * TclVerifyLocalLiteralTable --
   955  *
   956  *	Check a CompileEnv's local literal table for consistency.
   957  *
   958  * Results:
   959  *	None.
   960  *
   961  * Side effects:
   962  *	Panics if problems are found.
   963  *
   964  *----------------------------------------------------------------------
   965  */
   966 
   967 void
   968 TclVerifyLocalLiteralTable(envPtr)
   969     CompileEnv *envPtr;		/* Points to CompileEnv whose literal
   970 				 * table is to be validated. */
   971 {
   972     register LiteralTable *localTablePtr = &(envPtr->localLitTable);
   973     register LiteralEntry *localPtr;
   974     char *bytes;
   975     register int i;
   976     int length, count;
   977 
   978     count = 0;
   979     for (i = 0;  i < localTablePtr->numBuckets;  i++) {
   980 	for (localPtr = localTablePtr->buckets[i];
   981 	        localPtr != NULL;  localPtr = localPtr->nextPtr) {
   982 	    count++;
   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,
   987 		        localPtr->refCount);
   988 	    }
   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);
   994 	    }
   995 	    if (localPtr->objPtr->bytes == NULL) {
   996 		panic("TclVerifyLocalLiteralTable: literal has NULL string rep");
   997 	    }
   998 	}
   999     }
  1000     if (count != localTablePtr->numEntries) {
  1001 	panic("TclVerifyLocalLiteralTable: local literal table had %d entries, should be %d",
  1002 	      count, localTablePtr->numEntries);
  1003     }
  1004 }
  1005 
  1006 /*
  1007  *----------------------------------------------------------------------
  1008  *
  1009  * TclVerifyGlobalLiteralTable --
  1010  *
  1011  *	Check an interpreter's global literal table literal for consistency.
  1012  *
  1013  * Results:
  1014  *	None.
  1015  *
  1016  * Side effects:
  1017  *	Panics if problems are found.
  1018  *
  1019  *----------------------------------------------------------------------
  1020  */
  1021 
  1022 void
  1023 TclVerifyGlobalLiteralTable(iPtr)
  1024     Interp *iPtr;		/* Points to interpreter whose global
  1025 				 * literal table is to be validated. */
  1026 {
  1027     register LiteralTable *globalTablePtr = &(iPtr->literalTable);
  1028     register LiteralEntry *globalPtr;
  1029     char *bytes;
  1030     register int i;
  1031     int length, count;
  1032 
  1033     count = 0;
  1034     for (i = 0;  i < globalTablePtr->numBuckets;  i++) {
  1035 	for (globalPtr = globalTablePtr->buckets[i];
  1036 	        globalPtr != NULL;  globalPtr = globalPtr->nextPtr) {
  1037 	    count++;
  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);
  1043 	    }
  1044 	    if (globalPtr->objPtr->bytes == NULL) {
  1045 		panic("TclVerifyGlobalLiteralTable: literal has NULL string rep");
  1046 	    }
  1047 	}
  1048     }
  1049     if (count != globalTablePtr->numEntries) {
  1050 	panic("TclVerifyGlobalLiteralTable: global literal table had %d entries, should be %d",
  1051 	      count, globalTablePtr->numEntries);
  1052     }
  1053 }
  1054 #endif /*TCL_COMPILE_DEBUG*/