diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 5821bee514..cfe3759ff8 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -1,3 +1,19 @@ +2000-07-16 17:40 UTC+0100 Ryszard Glab + + *include/hbhash.h + *source/common/hash.c + * added ulCount and ulUsed members of HB_HASH_TABLE structure + * added hb_hashTableResize() function + + *source/compiler/hbident.c + *increased the hash table + + *source/vm/garbage.c + *source/vm/hvm.c + * all detached variables are scanned now correctly + * on exit the GC is called after cleaning all other internal + data structures + 2000-07-16 13:38 UTC+0100 Victor Szakats * source/rtl/binnum.c diff --git a/harbour/include/hbhash.h b/harbour/include/hbhash.h index d63e1ebdab..5547f36c67 100644 --- a/harbour/include/hbhash.h +++ b/harbour/include/hbhash.h @@ -48,18 +48,20 @@ typedef HB_HASH_FUNC_ *HB_HASH_FUNC_PTR; typedef struct HB_HASH_ITEM_ { - void *cargo; + void *cargo; /* value stored in the hash table */ ULONG key; struct HB_HASH_ITEM_ *next; } HB_HASH_ITEM, *HB_HASH_ITEM_PTR; typedef struct HB_HASH_TABLE_ { - HB_HASH_ITEM_PTR *pItems; - ULONG ulTableSize; - HB_HASH_FUNC_PTR pKeyFunc; - HB_HASH_FUNC_PTR pDeleteItemFunc; - HB_HASH_FUNC_PTR pCompFunc; + HB_HASH_ITEM_PTR *pItems; /* pointer to items */ + ULONG ulTableSize; /* the table size - number of slots */ + ULONG ulCount; /* number of items stored in the table */ + ULONG ulUsed; /* number of used slots */ + HB_HASH_FUNC_PTR pKeyFunc; /* pointer to func that returns key value */ + HB_HASH_FUNC_PTR pDeleteItemFunc; /* ptr to func that deletes value stured in the table */ + HB_HASH_FUNC_PTR pCompFunc; /* ptr to func that compares two itmes */ } HB_HASH_TABLE, *HB_HASH_TABLE_PTR; extern HB_HASH_TABLE_PTR hb_hashTableCreate( ULONG ulSize, @@ -69,8 +71,7 @@ extern HB_HASH_TABLE_PTR hb_hashTableCreate( ULONG ulSize, extern void hb_hashTableKill( HB_HASH_TABLE_PTR pTable ); /* release all items and the hash table */ extern BOOL hb_hashTableAdd( HB_HASH_TABLE_PTR pTable, void *pValue ); /* add a new item into the table */ extern void * hb_hashTableFind( HB_HASH_TABLE_PTR pTable, void *pValue ); /* return the pointer to item's value or NULL if not found */ -extern ULONG hb_hashTableBucket( HB_HASH_TABLE_PTR pTable ); /* return the size of the table */ - +extern HB_HASH_TABLE_PTR hb_hashTableResize( HB_HASH_TABLE_PTR pTable, ULONG ulNewSize ); /* resize the hash table */ #if defined(HB_EXTERN_C) } diff --git a/harbour/source/common/hash.c b/harbour/source/common/hash.c index 90c2109361..7a99c4dc76 100644 --- a/harbour/source/common/hash.c +++ b/harbour/source/common/hash.c @@ -35,10 +35,6 @@ #include "hbhash.h" -/* TODO: - * 1) add resize function - * 2) add better method of conflicts resolving -*/ static HB_HASH_ITEM_PTR hb_hashItemNew( ULONG ulKey, void * pValue ) { HB_HASH_ITEM_PTR pItem = (HB_HASH_ITEM_PTR) hb_xgrab( sizeof( HB_HASH_ITEM ) ); @@ -76,6 +72,7 @@ HB_HASH_TABLE_PTR hb_hashTableCreate( ULONG ulSize, pTable->pKeyFunc = pHashFunc; pTable->pDeleteItemFunc = pDelete; pTable->pCompFunc = pComp; + pTable->ulCount = pTable->ulUsed = 0; pTable->pItems = ( HB_HASH_ITEM_PTR * ) hb_xgrab( sizeof( HB_HASH_ITEM_PTR ) * ulSize ); memset( pTable->pItems, 0, sizeof( HB_HASH_ITEM_PTR ) * ulSize ); @@ -107,9 +104,63 @@ void hb_hashTableKill( HB_HASH_TABLE_PTR pTable ) } ++ulSize; } + hb_xfree( ( void * ) pTable->pItems ); hb_xfree( ( void * ) pTable ); } +/* resize table */ +HB_HASH_TABLE_PTR hb_hashTableResize( HB_HASH_TABLE_PTR pTable, ULONG ulNewSize ) +{ + HB_HASH_TABLE_PTR pNew; + ULONG ulSize = 0; + + if( ulNewSize == 0 ) + ulNewSize = 2 * pTable->ulTableSize + 1; + pNew = hb_hashTableCreate( ulNewSize, + pTable->pKeyFunc, + pTable->pDeleteItemFunc, + pTable->pCompFunc ); + + while( ulSize < pTable->ulTableSize ) + { + if( pTable->pItems[ ulSize ] ) + { + HB_HASH_ITEM_PTR pItem; + + pItem = pTable->pItems[ ulSize ]; + while( pItem ) + { + ULONG ulKey; + HB_HASH_ITEM_PTR pNewItem, pNext; + + pNext = pItem->next; + ulKey = ( pTable->pKeyFunc )( pItem->cargo, NULL ); + pNewItem = pNew->pItems[ ulKey ]; + if( pNewItem ) + { + while( pNewItem->next ) + pNewItem = pNewItem->next; + pNewItem->next = pItem; + } + else + { + pNew->pItems[ ulKey ] = pItem; + ++pNew->ulUsed; + } + pItem->key = ulKey; + pItem->next = NULL; + ++pNew->ulCount; + pItem = pNext; + } + } + ++ulSize; + } + hb_xfree( ( void * ) pTable->pItems ); + hb_xfree( ( void * ) pTable ); + + return pNew; +} + /* add a new value into th ehash table */ BOOL hb_hashTableAdd( HB_HASH_TABLE_PTR pTable, void *pValue ) { @@ -125,7 +176,11 @@ BOOL hb_hashTableAdd( HB_HASH_TABLE_PTR pTable, void *pValue ) pItem->next = hb_hashItemNew( ulKey, pValue ); } else + { pTable->pItems[ ulKey ] = hb_hashItemNew( ulKey, pValue ); + ++pTable->ulUsed; + } + ++pTable->ulCount; return TRUE; } @@ -172,10 +227,15 @@ BOOL hb_hashTableDel( HB_HASH_TABLE_PTR pTable, void *pValue ) if( pPrev ) pPrev->next = pItem->next; else + { pTable->pItems[ ulKey ] = pItem->next; + if( !pItem->next ) + --pTable->ulUsed; + } hb_hashItemDelete( pItem ); bFound = TRUE; + --pTable->ulCount; } else { @@ -188,7 +248,8 @@ BOOL hb_hashTableDel( HB_HASH_TABLE_PTR pTable, void *pValue ) } /* return the hash table size */ -ULONG hb_hashTableBucket( HB_HASH_TABLE_PTR pTable ) +ULONG hb_hashTableSize( HB_HASH_TABLE_PTR pTable ) { return pTable->ulTableSize; } + diff --git a/harbour/source/compiler/hbident.c b/harbour/source/compiler/hbident.c index b2b2b8d3f8..d44419d2e9 100644 --- a/harbour/source/compiler/hbident.c +++ b/harbour/source/compiler/hbident.c @@ -38,9 +38,9 @@ #include "hbhash.h" #include "hbcomp.h" -static HB_HASH_TABLE_PTR s_comp_Identifiers; /* table of identifiers for reuse */ +#define HB_IDENT_TABLE_SIZE 523UL -#define HB_IDENT_TABLE_SIZE 373UL +static HB_HASH_TABLE_PTR s_comp_Identifiers; /* table of identifiers for reuse */ /* create a new identifier or return the existing one */ @@ -55,7 +55,7 @@ char * hb_compIdentifierNew( char * szName, BOOL bCopy ) szIdent = hb_strdup( szName ); else szIdent = szName; - + hb_hashTableAdd( s_comp_Identifiers, (void *)szIdent ); } diff --git a/harbour/source/vm/garbage.c b/harbour/source/vm/garbage.c index 41034028f9..72449246a6 100644 --- a/harbour/source/vm/garbage.c +++ b/harbour/source/vm/garbage.c @@ -257,8 +257,21 @@ void hb_gcItemRef( HB_ITEM_PTR pItem ) { HB_GARBAGE_PTR pAlloc = ( HB_GARBAGE_PTR ) pItem->item.asBlock.value; --pAlloc; + if( pAlloc->used == s_uUsedFlag ) + { + HB_CODEBLOCK_PTR pCBlock = pItem->item.asBlock.value; + USHORT ui = 1; + pAlloc->used ^= HB_GC_USED_FLAG; /* mark this codeblock as used */ + + /* mark as used all detached variables in a codeblock */ + while( ui <= pCBlock->uiLocals ) + { + hb_gcItemRef( &pCBlock->pLocals[ ui ] ); + ++ui; + } + } } /* all other data types don't need the GC */ } diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index 6bf0bb3dfd..ce80dd7970 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -351,15 +351,15 @@ void hb_vmQuit( void ) hb_conRelease(); /* releases Console */ hb_setRelease(); /* releases Sets */ - /* release all known garbage */ - hb_gcCollectAll(); - /* release all remaining items */ while( hb_stack.pPos > hb_stack.pItems ) hb_stackPop(); hb_itemClear( &hb_stack.Return ); hb_arrayRelease( &s_aStatics ); hb_memvarsRelease(); + + /* release all known garbage */ + hb_gcCollectAll(); hb_stackFree(); /* hb_dynsymLog(); */ @@ -4385,6 +4385,6 @@ void hb_vmIsStaticRef( void ) HB_TRACE(HB_TR_DEBUG, ("hb_vmIsStaticRef()")); /* statics are stored as an item of array type */ - hb_gcItemRef( &s_aStatics ); + hb_gcItemRef( &s_aStatics ); }