diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 8c8ee7a5c8..1ca2c6a9e1 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,19 @@ 2002-12-01 23:12 UTC+0100 Foo Bar */ +2004-12-24 07:47 UTC+0100 Ryszard Glab + * include/hbapi.h + * source/vm/codebloc.c + * source/vm/itemapi.c + * source/vm/memvars.c + * fixed memvars and detached locals handling related to reallocation + of memvar's buffer and detaching of locals in a loop + - thanks to Przemek + + * source/vm/debug.c + *removed diagnostic hb_dbgstop() + + 2004-12-20 05:00 UTC-0500 David G. Holm * config/global.cf * config/bsd/gcc.cf diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index 593ff6c973..5740b42e83 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -293,7 +293,7 @@ typedef struct _HB_CODEBLOCK typedef struct _HB_VALUE { - HB_ITEM item; + HB_ITEM_PTR pVarItem; ULONG counter; HB_HANDLE hPrevMemvar; } HB_VALUE, * PHB_VALUE, * HB_VALUE_PTR; @@ -574,7 +574,7 @@ extern void hb_memvarNewParameter( PHB_SYMB pSymbol, PHB_ITEM pValue ); extern char * hb_memvarGetStrValuePtr( char * szVarName, ULONG *pulLen ); extern void hb_memvarCreateFromItem( PHB_ITEM pMemvar, BYTE bScope, PHB_ITEM pValue ); extern int hb_memvarScope( char * szVarName, ULONG ulLength ); /* retrieve scope of a dynamic variable symbol */ -extern void hb_memvarDetachLocal( HB_ITEM_PTR pLocal ); /* Detach a local variable from the eval stack */ +extern HB_ITEM_PTR hb_memvarDetachLocal( HB_ITEM_PTR pLocal ); /* Detach a local variable from the eval stack */ /* console I/O subsystem */ extern void hb_conInit( void ); /* initialize the console API system */ diff --git a/harbour/source/vm/codebloc.c b/harbour/source/vm/codebloc.c index 4854d73337..fc7cd9f948 100644 --- a/harbour/source/vm/codebloc.c +++ b/harbour/source/vm/codebloc.c @@ -110,35 +110,18 @@ HB_CODEBLOCK_PTR hb_codeblockNew( BYTE * pBuffer, pLocal = hb_stackItemFromBase( HB_PCODE_MKUSHORT( pLocalPosTable ) ); pLocalPosTable += 2; - if( ! HB_IS_MEMVAR( pLocal ) ) - { - /* Change the value only if this variable is not referenced - * by another codeblock yet. - * In this case we have to copy the current value to a global memory - * pool so it can be shared by codeblocks - */ - - if( HB_IS_BYREF( pLocal ) ) - { - pLocal = hb_itemUnRef( pLocal ); - } - - hb_memvarDetachLocal( pLocal ); - memcpy( pCBlock->pLocals + ui, pLocal, sizeof( HB_ITEM ) ); - } - else - { - /* This variable is already detached (by another codeblock) - * - copy the reference to a value - */ - /* Increment the reference counter so this value will not be - * released if other codeblock will be deleted - */ - memcpy( pCBlock->pLocals + ui, pLocal, sizeof( HB_ITEM ) ); - } + pLocal = hb_memvarDetachLocal( pLocal ); + /* Increment the reference counter so this value will not be + * released if other codeblock will be deleted + */ + memcpy( pCBlock->pLocals + ui, pLocal, sizeof( HB_ITEM ) ); + /* Increment the reference counter so this value will not be + * released if other codeblock will be deleted + */ hb_memvarValueIncRef( pLocal->item.asMemvar.value ); ++ui; } + } else { diff --git a/harbour/source/vm/debug.c b/harbour/source/vm/debug.c index 25ff136eea..a1c54d0f80 100644 --- a/harbour/source/vm/debug.c +++ b/harbour/source/vm/debug.c @@ -212,10 +212,6 @@ HB_FUNC( HB_DBG_VMPARLLIST ) hb_itemRelease( hb_itemReturn( pReturn ) ); } -static void hb_dbgStop() -{ -} - HB_FUNC( HB_DBG_VMVARLGET ) { int iLevel = hb_parni( 1 ) + 1; @@ -227,7 +223,6 @@ HB_FUNC( HB_DBG_VMVARLGET ) if( iLocal > SHRT_MAX ) { - hb_dbgStop(); iLocal -= USHRT_MAX; iLocal--; } diff --git a/harbour/source/vm/itemapi.c b/harbour/source/vm/itemapi.c index 7b04b80cca..c7602dac4d 100644 --- a/harbour/source/vm/itemapi.c +++ b/harbour/source/vm/itemapi.c @@ -1236,7 +1236,7 @@ PHB_ITEM hb_itemUnRefOnce( PHB_ITEM pItem ) pValue = *( pItem->item.asMemvar.itemsbase ) + pItem->item.asMemvar.value; - pItem = &pValue->item; + pItem = pValue->pVarItem; } else { diff --git a/harbour/source/vm/memvars.c b/harbour/source/vm/memvars.c index d1730721e1..4b660b5aff 100644 --- a/harbour/source/vm/memvars.c +++ b/harbour/source/vm/memvars.c @@ -129,7 +129,8 @@ void hb_memvarsRelease( void ) { if( s_globalTable[ ulCnt ].counter && s_globalTable[ ulCnt ].hPrevMemvar != ( HB_HANDLE )-1 ) { - hb_itemClear( &s_globalTable[ ulCnt ].item ); + hb_itemClear( s_globalTable[ ulCnt ].pVarItem ); + hb_xfree( s_globalTable[ ulCnt ].pVarItem ); s_globalTable[ ulCnt ].counter = 0; } } @@ -220,14 +221,15 @@ HB_HANDLE hb_memvarValueNew( HB_ITEM_PTR pSource, BOOL bTrueMemvar ) } pValue = s_globalTable + hValue; + pValue->pVarItem = ( HB_ITEM_PTR ) hb_xgrab( sizeof( HB_ITEM ) ); pValue->counter = 1; - pValue->item.type = HB_IT_NIL; + pValue->pVarItem->type = HB_IT_NIL; if( pSource ) { if( bTrueMemvar ) - hb_itemCopy( &pValue->item, pSource ); + hb_itemCopy( pValue->pVarItem, pSource ); else - memcpy( &pValue->item, pSource, sizeof(HB_ITEM) ); + memcpy( pValue->pVarItem, pSource, sizeof(HB_ITEM) ); } if( bTrueMemvar ) @@ -242,15 +244,38 @@ HB_HANDLE hb_memvarValueNew( HB_ITEM_PTR pSource, BOOL bTrueMemvar ) /* Detach local variable (swap current value with a memvar handle) */ -void hb_memvarDetachLocal( HB_ITEM_PTR pLocal ) +HB_ITEM_PTR hb_memvarDetachLocal( HB_ITEM_PTR pLocal ) { - HB_HANDLE hMemvar = hb_memvarValueNew( pLocal, FALSE ); + HB_TRACE(HB_TR_DEBUG, ("hb_memvarDetachLocal(%p, %d)", pLocal, pLocal->type )); + + if( HB_IS_BYREF( pLocal ) && ! HB_IS_MEMVAR( pLocal ) ) + { + /* Change the value only if this variable is not referenced + * by another codeblock yet. + * In this case we have to copy the current value to a global memory + * pool so it can be shared by codeblocks + */ + HB_ITEM_PTR pItem; - pLocal->type = HB_IT_BYREF | HB_IT_MEMVAR; - pLocal->item.asMemvar.itemsbase = &s_globalTable; - pLocal->item.asMemvar.value = hMemvar; + do + { + pLocal = hb_itemUnRefOnce( pLocal ); + } + while( HB_IS_BYREF( pLocal ) && ! HB_IS_MEMVAR( pLocal ) && ( pLocal != pItem ) ); + } + + if( ! HB_IS_MEMVAR( pLocal ) ) + { + HB_HANDLE hMemvar = hb_memvarValueNew( pLocal, FALSE ); + + pLocal->type = HB_IT_BYREF | HB_IT_MEMVAR; + pLocal->item.asMemvar.itemsbase = &s_globalTable; + pLocal->item.asMemvar.value = hMemvar; + } + return pLocal; } + /* * This function pushes passed dynamic symbol that belongs to PRIVATE variable * into the stack. The value will be popped from it if the variable falls @@ -372,7 +397,8 @@ void hb_memvarValueDecRef( HB_HANDLE hValue ) */ if( --pValue->counter == 0 ) { - hb_itemClear( &pValue->item ); + hb_itemClear( pValue->pVarItem ); + hb_xfree( pValue->pVarItem ); hb_memvarRecycle( hValue ); HB_TRACE(HB_TR_INFO, ("Memvar item (%i) deleted", hValue)); @@ -407,8 +433,9 @@ void hb_memvarValueDecGarbageRef( HB_HANDLE hValue ) */ if( --pValue->counter == 0 ) { - if( HB_IS_STRING( &pValue->item ) ) - hb_itemClear( &pValue->item ); + if( HB_IS_STRING( pValue->pVarItem ) ) + hb_itemClear( pValue->pVarItem ); + hb_xfree( pValue->pVarItem ); hb_memvarRecycle( hValue ); HB_TRACE(HB_TR_INFO, ("Memvar item (%i) deleted", hValue)); @@ -438,7 +465,7 @@ void hb_memvarSetValue( PHB_SYMB pMemvarSymb, HB_ITEM_PTR pItem ) if( pDyn->hMemvar ) { /* value is already created */ - HB_ITEM_PTR pSetItem = &s_globalTable[ pDyn->hMemvar ].item; + HB_ITEM_PTR pSetItem = s_globalTable[ pDyn->hMemvar ].pVarItem; if( HB_IS_BYREF( pSetItem ) ) hb_itemCopy( hb_itemUnRef( pSetItem ), pItem ); else @@ -450,7 +477,7 @@ void hb_memvarSetValue( PHB_SYMB pMemvarSymb, HB_ITEM_PTR pItem ) */ hb_memvarCreateFromDynSymbol( pDyn, VS_PRIVATE, pItem ); } - s_globalTable[ pDyn->hMemvar ].item.type &= ~HB_IT_MEMOFLAG; + s_globalTable[ pDyn->hMemvar ].pVarItem->type &= ~HB_IT_MEMOFLAG; } else hb_errInternal( HB_EI_MVBADSYMBOL, NULL, pMemvarSymb->szName, NULL ); @@ -472,7 +499,7 @@ ERRCODE hb_memvarGet( HB_ITEM_PTR pItem, PHB_SYMB pMemvarSymb ) { /* value is already created */ - HB_ITEM_PTR pGetItem = &s_globalTable[ pDyn->hMemvar ].item; + HB_ITEM_PTR pGetItem = s_globalTable[ pDyn->hMemvar ].pVarItem; if( HB_IS_BYREF( pGetItem ) ) hb_itemCopy( pItem, hb_itemUnRef( pGetItem ) ); else @@ -598,7 +625,7 @@ char * hb_memvarGetStrValuePtr( char * szVarName, ULONG *pulLen ) { /* variable contains some data */ - HB_ITEM_PTR pItem = &s_globalTable[ pDynVar->hMemvar ].item; + HB_ITEM_PTR pItem = s_globalTable[ pDynVar->hMemvar ].pVarItem; if( HB_IS_BYREF( pItem ) ) pItem = hb_itemUnRef( pItem ); /* it is a PARAMETER variable */ if( HB_IS_STRING( pItem ) ) @@ -660,16 +687,16 @@ static void hb_memvarCreateFromDynSymbol( PHB_DYNS pDynVar, BYTE bScope, PHB_ITE /* new PUBLIC variable - initialize it to .F. */ - s_globalTable[ pDynVar->hMemvar ].item.type = HB_IT_LOGICAL; + s_globalTable[ pDynVar->hMemvar ].pVarItem->type = HB_IT_LOGICAL; /* NOTE: PUBLIC variables named CLIPPER and HARBOUR are initialized */ /* to .T., this is normal Clipper behaviour. [vszakats] */ if( strcmp( pDynVar->pSymbol->szName, "HARBOUR" ) == 0 || strcmp( pDynVar->pSymbol->szName, "CLIPPER" ) == 0 ) - s_globalTable[ pDynVar->hMemvar ].item.item.asLogical.value = TRUE; + s_globalTable[ pDynVar->hMemvar ].pVarItem->item.asLogical.value = TRUE; else - s_globalTable[ pDynVar->hMemvar ].item.item.asLogical.value = FALSE; + s_globalTable[ pDynVar->hMemvar ].pVarItem->item.asLogical.value = FALSE; } } } @@ -720,7 +747,7 @@ static void hb_memvarRelease( HB_ITEM_PTR pMemvar ) { if( hb_stricmp( pDynVar->pSymbol->szName, pMemvar->item.asString.value ) == 0 ) { - hb_itemClear( &s_globalTable[ pDynVar->hMemvar ].item ); + hb_itemClear( s_globalTable[ pDynVar->hMemvar ].pVarItem ); ulBase = 0; } } @@ -730,7 +757,7 @@ static void hb_memvarRelease( HB_ITEM_PTR pMemvar ) { pDynVar = hb_dynsymGet( pMemvar->item.asString.value ); if( pDynVar && pDynVar->hMemvar ) - hb_itemClear( &s_globalTable[ pDynVar->hMemvar ].item ); + hb_itemClear( s_globalTable[ pDynVar->hMemvar ].pVarItem ); } } else @@ -762,10 +789,10 @@ static void hb_memvarReleaseWithMask( char *szMask, BOOL bInclude ) if( bInclude ) { if( ( szMask[ 0 ] == '*') || hb_strMatchRegExp( pDynVar->pSymbol->szName, szMask ) ) - hb_itemClear( &s_globalTable[ pDynVar->hMemvar ].item ); + hb_itemClear( s_globalTable[ pDynVar->hMemvar ].pVarItem ); } else if( ! hb_strMatchRegExp( pDynVar->pSymbol->szName, szMask ) ) - hb_itemClear( &s_globalTable[ pDynVar->hMemvar ].item ); + hb_itemClear( s_globalTable[ pDynVar->hMemvar ].pVarItem ); } } } @@ -917,7 +944,7 @@ static HB_ITEM_PTR hb_memvarDebugVariable( int iScope, int iPos, char * *pszName hb_dynsymEval( hb_memvarFindPublicByPos, ( void * ) &struPub ); if( struPub.bFound ) { - pValue =&s_globalTable[ struPub.pDynSym->hMemvar ].item; + pValue =s_globalTable[ struPub.pDynSym->hMemvar ].pVarItem; *pszName =struPub.pDynSym->pSymbol->szName; } } @@ -927,7 +954,7 @@ static HB_ITEM_PTR hb_memvarDebugVariable( int iScope, int iPos, char * *pszName { HB_DYNS_PTR pDynSym = s_privateStack[ iPos ]; - pValue =&s_globalTable[ pDynSym->hMemvar ].item; + pValue =s_globalTable[ pDynSym->hMemvar ].pVarItem; *pszName = pDynSym->pSymbol->szName; } } @@ -1312,7 +1339,7 @@ static HB_DYNS_FUNC( hb_memvarSave ) { BOOL bMatch = ( pszMask[ 0 ] == '*' || hb_strMatchRegExp( pDynSymbol->pSymbol->szName, pszMask ) ); - PHB_ITEM pItem = &s_globalTable[ pDynSymbol->hMemvar ].item; + PHB_ITEM pItem = s_globalTable[ pDynSymbol->hMemvar ].pVarItem; /* Process it if it matches the passed mask */ if( bIncludeMask ? bMatch : ! bMatch ) @@ -1614,7 +1641,7 @@ void hb_memvarsIsMemvarRef( void ) */ if( s_globalTable[ ulCnt ].counter && s_globalTable[ ulCnt ].hPrevMemvar != ( HB_HANDLE )-1 ) { - hb_gcItemRef( &s_globalTable[ ulCnt ].item ); + hb_gcItemRef( s_globalTable[ ulCnt ].pVarItem ); } } } @@ -1633,7 +1660,7 @@ HB_HANDLE hb_memvarGetVarHandle( char *szName ) PHB_ITEM hb_memvarGetValueByHandle( HB_HANDLE hMemvar ) { if( hMemvar && hMemvar < s_globalTableSize ) - return &s_globalTable[ hMemvar ].item; + return s_globalTable[ hMemvar ].pVarItem; else return NULL; }