diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 4b669106d4..8abb62293f 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,104 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2006-08-19 01:10 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbapi.h + * moved HB_STACK_STATE declaration from hbstack.h to hbapi.h + it's covered by _HB_API_INTERNAL_ macro so it should not + effect 3-rd party code + * modified hb_struSymbol structure: + LONG stackbase + replaced by: + PHB_STACK_STATE stackstate + this modification allows to keepadditional information bound with + function call stack accessible from different HVM modules. + Now it's used by memvars code to keep/update PRIVATE variables + stack pointers. I plan to store in HB_STACK_STATE structure + information additional information for classes code like super + casting or instance variables offsets in new OOP model I'm working on. + It can be also used by debugger code to retrieve some informations + about executed functions without active updating by main HVM loop. + + added hb_memvarsClear() - cleanly clears all PRIVATE and PUBLIC + variables + + added hb_memvarUpdatePrivatesBase() - updates PRIVATE stack base + offset so PRIVATE variables created in current function/procedure + will not be removed when it returns + - removed hb_memvarsRelease() and hb_memvarValueNew() + + * harbour/include/hbstack.h + + added hb_stackClearMevarsBase() - helper function for hb_memvarsClear() + clears PRIVATE stack offsets in executed functions + * changed to static offset from int to long - in different places we + were using int or long in HVM so I cleaned the HVM code to always + operate on the same type + + * harbour/source/vm/estack.c + * set/restore PRIVATE stack base offset in hb_stackNewFrame()/ + hb_stackOldFrame() + * updated for new HB_IT_SYMBOL structure + + * harbour/source/vm/hvm.c + ! removed setting/restoring PRIVATE stack base offset in hb_vmExecute() + It make code like: + eval(&("{||VAR:=1}")) + Clipper compatible + * updated for new HB_IT_SYMBOL structure + * changed order of execution exit procedures for clean memvars removing + and future destructors execution. I'll describe it better when I'll + add destructors. + + * harbour/source/vm/memvars.c + ! fixed CLEAR MEMORY - now this function should be safe in Harbour + It's not exactly compatible with Clipper because I intentionally + didn't replicated some Clipper bugs like possible memory corruption. + + added hb_memvarsClear() - cleanly clears all PRIVATE and PUBLIC + variables + + added hb_memvarUpdatePrivatesBase() - updates PRIVATE stack base + offset so PRIVATE variables created in current function/procedure + will not be removed when it returns + ! fixed releasing PUBLIC and PRIVATE variables which were passed by + reference and are still active on HVM stack or in codeblocks as + detached locals (see: hb_memvarDetachDynSym()) + * modified hb_memvarFindSymbol() to be more Clipper compatible + % optimized hb_memvarRelease() to operate or PHB_DYNS instead of + string comparison and not make linear dynamic symbol scan for + PUBLIC or not existing symbols + - removed hb_memvarReleasePublic() + + * harbour/include/hbvmpub.h + * harbour/include/hbxvm.h + * harbour/source/compiler/gencc.c + * harbour/source/vm/classes.c + * harbour/source/vm/debug.c + * harbour/source/vm/itemapi.c + * harbour/source/vm/pcount.c + * harbour/source/vm/proc.c + * harbour/source/vm/pvalue.c + * updated for the above modifications + + * harbour/source/rtl/memvarbl.prg + * harbour/source/rtl/menuto.prg + * use __mvEXIST( cMemvar ) instead of __mvSCOPE( cMemvar ) > HB_MV_ERROR + __mvEXIST() is much faster function + + * harbour/source/rtl/type.c + * execute hb_memvarUpdatePrivatesBase() after macro type checking. + This should not be necessary but we are not Clipper compatible here + and this is work around for difference in our TYPE() implementation. + Clipper for: + ? TYPE("VAR:=1") + create PUBLIC variable VAR when [x]Harbour PRIVATE one. + Should we try to make it Clipper compatible? + + The above should fix problems reported with memvars. We are not 100% + Clipper compatible but unlike in Clipper we cannot break VM internals + using some operation on references to memvars and detached locals + and/or RELEASE.../ CLEAR MEMORY. This modifications should be intensively + tested. If you will find any problems with current code please inform me. + I'd like to hear your opinions about memvars created by TYPE() (see above). + Should we change it? It may not be very easy operation - we will have to + change macro compiler and add new PCODE for that. + 2006-08-17 12:40 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/contrib/rdd_ads/ads1.c * harbour/include/hbapi.h diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index dcdc3a74c7..f131e59946 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -224,6 +224,14 @@ struct _HB_BASEARRAY; struct _HB_ITEM; struct _HB_VALUE; +typedef struct _HB_STACK_STATE +{ + LONG lBaseItem; /* stack base offset of previous func/proc */ + LONG lStatics; /* statics offset of previous func/proc */ + ULONG ulPrivateBase; /* memvars base offset of previous func/proc */ +} HB_STACK_STATE, * PHB_STACK_STATE; /* used to save/restore stack state in hb_vmDo)_ */ + + /* Internal structures that holds data */ struct hb_struArray { @@ -308,10 +316,10 @@ struct hb_struString struct hb_struSymbol { - LONG stackbase; - USHORT lineno; - USHORT paramcnt; - PHB_SYMB value; + PHB_SYMB value; + PHB_STACK_STATE stackstate; /* function stack state */ + USHORT lineno; + USHORT paramcnt; }; /* items hold at the virtual machine stack */ @@ -717,9 +725,8 @@ extern PHB_ITEM hb_codeblockGetRef( HB_CODEBLOCK_PTR pCBlock, PHB_ITEM p extern void hb_codeblockEvaluate( HB_ITEM_PTR pItem ); /* evaluate a codeblock */ /* memvars subsystem */ -extern HB_HANDLE hb_memvarValueNew( HB_ITEM_PTR pSource, BOOL bTrueMemvar ); /* create a new global value */ extern void hb_memvarsInit( void ); /* initialize the memvar API system */ -extern void hb_memvarsRelease( void ); /* clear all PUBLIC and PRIVATE variables */ +extern void hb_memvarsClear( void ); /* clear all PUBLIC and PRIVATE variables */ extern void hb_memvarsFree( void ); /* release the memvar API system */ extern void hb_memvarValueIncRef( HB_HANDLE hValue ); /* increase the reference count of a global value */ extern void hb_memvarValueDecRef( HB_HANDLE hValue ); /* decrease the reference count of a global value */ @@ -729,6 +736,7 @@ extern void hb_memvarGetValue( HB_ITEM_PTR pItem, PHB_SYMB pMemvarSymb ); extern void hb_memvarGetRefer( HB_ITEM_PTR pItem, PHB_SYMB pMemvarSymb ); /* copy a reference to a symbol value into an item, with error trapping */ extern ULONG hb_memvarGetPrivatesBase( void ); /* retrieve current PRIVATE variables stack base */ extern void hb_memvarSetPrivatesBase( ULONG ulBase ); /* release PRIVATE variables created after specified base */ +extern void hb_memvarUpdatePrivatesBase( void ); /* Update PRIVATE base ofsset so they will not be removed when function return */ 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 ); diff --git a/harbour/include/hbstack.h b/harbour/include/hbstack.h index d74b50d873..26cec89460 100644 --- a/harbour/include/hbstack.h +++ b/harbour/include/hbstack.h @@ -74,19 +74,13 @@ typedef struct HB_ITEM Return; /* latest returned value */ PHB_ITEM * pBase; /* stack frame position for the current function call */ PHB_ITEM * pEvalBase; /* stack frame position for the evaluated codeblock */ - int iStatics; /* statics base for the current function call */ + LONG lStatics; /* statics base for the current function call */ LONG lWithObject; /* stack offset to base current WITH OBJECT item */ char szDate[ 9 ]; /* last returned date from _pards() yyyymmdd format */ } HB_STACK; extern HB_STACK hb_stack; -typedef struct -{ - LONG lBaseItem; - LONG iStatics; -} HB_STACK_STATE; /* used to save/restore stack state in hb_vmDo)_ */ - #endif extern HB_ITEM_PTR hb_stackItemFromTop( int nFromTop ); @@ -99,8 +93,8 @@ extern HB_ITEM_PTR hb_stackSelfItem( void ); extern HB_ITEM_PTR hb_stackItem( LONG iItemPos ); extern HB_ITEM_PTR hb_stackReturnItem( void ); extern char * hb_stackDateBuffer( void ); -extern void hb_stackSetStaticsBase( int iBase ); -extern int hb_stackGetStaticsBase( void ); +extern void hb_stackSetStaticsBase( LONG lBase ); +extern LONG hb_stackGetStaticsBase( void ); extern PHB_ITEM ** hb_stackItemBasePtr( void ); extern PHB_ITEM hb_stackWithObjectItem( void ); extern LONG hb_stackWithObjectOffset( void ); @@ -128,6 +122,7 @@ extern void hb_stackIncrease( void ); /* increase the stack size */ extern void hb_stackDecrease( ULONG ulItems ); extern HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams ); extern void hb_stackOldFrame( HB_STACK_STATE * pStack ); +extern void hb_stackClearMevarsBase( void ); #endif #if defined(HB_STACK_MACROS) @@ -142,8 +137,8 @@ extern void hb_stackOldFrame( HB_STACK_STATE * pStack ); #define hb_stackItem( iItemPos ) ( * ( hb_stack.pItems + ( iItemPos ) ) ) #define hb_stackReturnItem( ) ( &hb_stack.Return ) #define hb_stackDateBuffer( ) ( hb_stack.szDate ) -#define hb_stackGetStaticsBase( ) ( hb_stack.iStatics ) -#define hb_stackSetStaticsBase( n ) do { hb_stack.iStatics = ( n ); } while ( 0 ) +#define hb_stackGetStaticsBase( ) ( hb_stack.lStatics ) +#define hb_stackSetStaticsBase( n ) do { hb_stack.lStatics = ( n ); } while ( 0 ) #define hb_stackItemBasePtr( ) ( &hb_stack.pItems ) #define hb_stackWithObjectItem( ) ( hb_stack.lWithObject ? * ( hb_stack.pItems + hb_stack.lWithObject ) : NULL ) #define hb_stackWithObjectOffset( ) ( hb_stack.lWithObject ) diff --git a/harbour/include/hbvmpub.h b/harbour/include/hbvmpub.h index 3b7c4f7e61..34542cbb23 100644 --- a/harbour/include/hbvmpub.h +++ b/harbour/include/hbvmpub.h @@ -167,7 +167,7 @@ typedef struct _HB_SYMB { PHB_FUNC pFunPtr; /* machine code function address for function symbol table entries */ PHB_PCODEFUNC pCodeFunc; /* PCODE function address */ - int iStaticsBase; /* base offset to array of statics */ + LONG lStaticsBase; /* base offset to array of statics */ } value; PHB_DYNS pDynSym; /* pointer to its dynamic symbol if defined */ } HB_SYMB, * PHB_SYMB; diff --git a/harbour/include/hbxvm.h b/harbour/include/hbxvm.h index f0b126e56c..2414b117fe 100644 --- a/harbour/include/hbxvm.h +++ b/harbour/include/hbxvm.h @@ -73,7 +73,7 @@ HB_EXTERN_BEGIN * to check HVM state so they are simply declared as void. */ -extern HB_EXPORT void hb_xvmExitProc( ULONG ulPrivateBase ); +extern HB_EXPORT void hb_xvmExitProc( void ); extern HB_EXPORT void hb_xvmSeqBegin( void ); extern HB_EXPORT BOOL hb_xvmSeqEnd( void ); extern HB_EXPORT BOOL hb_xvmSeqEndTest( void ); diff --git a/harbour/source/compiler/gencc.c b/harbour/source/compiler/gencc.c index 6547472645..afc3c4cc7f 100644 --- a/harbour/source/compiler/gencc.c +++ b/harbour/source/compiler/gencc.c @@ -1742,7 +1742,6 @@ void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc ) } fprintf( yyc, "{\n" ); - fprintf( yyc, " ULONG ulPrivateBase = hb_memvarGetPrivatesBase();\n" ); if( label_info.fCondJump ) fprintf( yyc, " BOOL fValue;\n" ); fprintf( yyc, " do {\n" ); @@ -1750,7 +1749,7 @@ void hb_compGenCRealCode( PFUNCTION pFunc, FILE * yyc ) hb_compPCodeEval( pFunc, ( HB_PCODE_FUNC_PTR * ) s_verbose_table, ( void * ) &label_info ); fprintf( yyc, " } while ( 0 );\n" ); - fprintf( yyc, " hb_xvmExitProc( ulPrivateBase );\n" ); + fprintf( yyc, " hb_xvmExitProc();\n" ); fprintf( yyc, "}\n" ); if( label_info.pulLabels ) diff --git a/harbour/source/rtl/memvarbl.prg b/harbour/source/rtl/memvarbl.prg index 6d41789085..de62022c34 100644 --- a/harbour/source/rtl/memvarbl.prg +++ b/harbour/source/rtl/memvarbl.prg @@ -56,7 +56,7 @@ FUNCTION MEMVARBLOCK( cMemvar ) - IF ISCHARACTER( cMemvar ) .AND. __mvSCOPE( cMemvar ) > HB_MV_ERROR + IF ISCHARACTER( cMemvar ) .AND. __mvEXIST( cMemvar ) RETURN {| x | iif( x == NIL, __mvGET( cMemvar ), __mvPUT( cMemvar, x ) ) } ENDIF diff --git a/harbour/source/rtl/menuto.prg b/harbour/source/rtl/menuto.prg index 01c7261330..ba44a60bbb 100644 --- a/harbour/source/rtl/menuto.prg +++ b/harbour/source/rtl/menuto.prg @@ -67,12 +67,9 @@ function __MenuTo( bBlock, cVariable ) local cFrontColor // Detect if a memvar was passed - - if __mvSCOPE( cVariable ) <= HB_MV_ERROR + lDeclared := !__mvEXIST( cVariable ) + if lDeclared __mvPUBLIC( cVariable ) - lDeclared := .T. - else - lDeclared := .F. endif n := eval( bBlock ) diff --git a/harbour/source/rtl/type.c b/harbour/source/rtl/type.c index 641174d105..8e0fa16574 100644 --- a/harbour/source/rtl/type.c +++ b/harbour/source/rtl/type.c @@ -58,7 +58,10 @@ HB_FUNC( TYPE ) HB_ITEM_PTR pItem = hb_param( 1, HB_IT_STRING ); if( pItem ) + { hb_retc( hb_macroGetType( pItem ) ); + hb_memvarUpdatePrivatesBase(); + } else hb_errRT_BASE_SubstR( EG_ARG, 1121, NULL, "TYPE", 1, hb_paramError( 1 ) ); } diff --git a/harbour/source/vm/classes.c b/harbour/source/vm/classes.c index 0ef02131f3..b144824d2f 100644 --- a/harbour/source/vm/classes.c +++ b/harbour/source/vm/classes.c @@ -510,28 +510,28 @@ static void hb_clsScope( PHB_ITEM pObject, PMETHOD pMethod ) szSelfNameRealClass = hb_objGetRealClsName( pObject, pMessage->pSymbol->szName ); while( iLevel-- > 0 && lOffset > 1 ) - lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackbase + 1; + lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1; szCallerNameMsg = hb_stackItem( lOffset - 1 )->item.asSymbol.value->szName; /* Is it an inline ? if so back one more ... */ if( strcmp( szCallerNameMsg, "__EVAL" ) == 0 && lOffset > 1 ) { - lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackbase + 1; + lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1; szCallerNameMsg = hb_stackItem( lOffset - 1 )->item.asSymbol.value->szName; } /* Is it an eval ? if so back another one more ... */ if( ( strcmp( szCallerNameMsg, "EVAL" ) == 0 ) && lOffset > 1 ) { - lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackbase + 1; + lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1; szCallerNameMsg = hb_stackItem( lOffset - 1 )->item.asSymbol.value->szName; } /* Is it an Aeval ? if so back another one more ... */ if ( ( strcmp( szCallerNameMsg, "AEVAL" ) == 0 ) && lOffset > 1 ) { - lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackbase + 1; + lOffset = hb_stackItem( lOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1; szCallerNameMsg = hb_stackItem( lOffset - 1 )->item.asSymbol.value->szName; } @@ -2234,7 +2234,7 @@ HB_FUNC( __CLASSSEL ) /* to be used from Classes ERROR HANDLER method */ HB_FUNC( __GETMESSAGE ) { - hb_retc( hb_stackItem( hb_stackBaseItem()->item.asSymbol.stackbase )->item.asSymbol.value->szName ); + hb_retc( hb_stackItem( hb_stackBaseItem()->item.asSymbol.stackstate->lBaseItem )->item.asSymbol.value->szName ); } HB_FUNC( __CLSPARENT ) @@ -2250,7 +2250,7 @@ HB_FUNC( __SENDER ) while( iLevel > 0 && lOffset > 1 ) { - lOffset = hb_stackItem( lOffset )->item.asSymbol.stackbase; + lOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem; oSender = hb_stackItem( lOffset + 1 ); if( ( iLevel-- == 2 && oSender->type != HB_IT_BLOCK ) || oSender->type == HB_IT_NIL ) @@ -2270,11 +2270,9 @@ HB_FUNC( __SENDER ) */ HB_FUNC( __CLASSH ) { - PHB_ITEM pObject = hb_itemParam( 1 ); + PHB_ITEM pObject = hb_param( 1, HB_IT_OBJECT ); - hb_retni( HB_IS_OBJECT( pObject ) ? pObject->item.asArray.value->uiClass : 0 ); - - hb_itemRelease( pObject ); + hb_retni( pObject ? pObject->item.asArray.value->uiClass : 0 ); } /* diff --git a/harbour/source/vm/debug.c b/harbour/source/vm/debug.c index f591d37bc7..3d7b24ae95 100644 --- a/harbour/source/vm/debug.c +++ b/harbour/source/vm/debug.c @@ -120,11 +120,11 @@ static LONG hb_stackLen( int iLevel ) lBaseOffset = hb_stackBaseOffset(); while( --iLevel > 0 && lBaseOffset > 1 ) - lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackbase + 1; + lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1; if( lBaseOffset > 1 ) { - lPrevOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackbase; + lPrevOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackstate->lBaseItem; lLen = lBaseOffset - lPrevOffset - 3; } else @@ -160,7 +160,7 @@ HB_FUNC( HB_DBG_VMSTKLLIST ) LONG lBaseOffset, lPrevOffset; lBaseOffset = hb_stackBaseOffset(); - lPrevOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackbase; + lPrevOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackstate->lBaseItem; ulLen = lBaseOffset - lPrevOffset - 3; pReturn = hb_itemArrayNew( ulLen ); /* Create a transfer array */ @@ -190,7 +190,7 @@ HB_FUNC( HB_DBG_VMVARLGET ) lBaseOffset = hb_stackBaseOffset(); while( iLevel-- > 0 && lBaseOffset > 1 ) - lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackbase + 1; + lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1; if( iLevel < 0 ) { @@ -215,7 +215,7 @@ HB_FUNC( HB_DBG_VMVARLSET ) lBaseOffset = hb_stackBaseOffset(); while( iLevel-- > 0 && lBaseOffset > 1 ) - lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackbase + 1; + lBaseOffset = hb_stackItem( lBaseOffset - 1 )->item.asSymbol.stackstate->lBaseItem + 1; if( iLevel < 0 ) { diff --git a/harbour/source/vm/estack.c b/harbour/source/vm/estack.c index 139c2f2033..555504ed4e 100644 --- a/harbour/source/vm/estack.c +++ b/harbour/source/vm/estack.c @@ -229,8 +229,10 @@ void hb_stackRemove( LONG lUntilPos ) HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams ) { - HB_ITEM_PTR pItem; - pItem = hb_stackItemFromTop( - uiParams - 2 ); /* procedure name */ + HB_ITEM_PTR * pBase, pItem; + + pBase = hb_stack.pPos - uiParams - 2; + pItem = * pBase; /* procedure symbol */ if( ! HB_IS_SYMBOL( pItem ) ) { @@ -240,12 +242,12 @@ HB_ITEM_PTR hb_stackNewFrame( HB_STACK_STATE * pStack, USHORT uiParams ) } pStack->lBaseItem = hb_stack.pBase - hb_stack.pItems; - pStack->iStatics = hb_stack.iStatics; - + pStack->lStatics = hb_stack.lStatics; + pStack->ulPrivateBase = hb_memvarGetPrivatesBase(); + pItem->item.asSymbol.stackstate = pStack; pItem->item.asSymbol.lineno = 0; pItem->item.asSymbol.paramcnt = uiParams; - hb_stack.pBase = hb_stack.pItems + pItem->item.asSymbol.stackbase; - pItem->item.asSymbol.stackbase = pStack->lBaseItem; + hb_stack.pBase = pBase; return pItem; } @@ -260,7 +262,8 @@ void hb_stackOldFrame( HB_STACK_STATE * pStack ) } hb_stack.pBase = hb_stack.pItems + pStack->lBaseItem; - hb_stack.iStatics = pStack->iStatics; + hb_stack.lStatics = pStack->lStatics; + hb_memvarSetPrivatesBase( pStack->ulPrivateBase ); } #undef hb_stackItem @@ -278,7 +281,7 @@ HB_ITEM_PTR hb_stackItemFromTop( int nFromTop ) if( nFromTop > 0 ) hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); - return ( * ( hb_stack.pPos + nFromTop ) ); + return * ( hb_stack.pPos + nFromTop ); } #undef hb_stackItemFromBase @@ -287,7 +290,7 @@ HB_ITEM_PTR hb_stackItemFromBase( int nFromBase ) if( nFromBase <= 0 ) hb_errInternal( HB_EI_STACKUFLOW, NULL, NULL, NULL ); - return ( * ( hb_stack.pBase + nFromBase + 1 ) ); + return * ( hb_stack.pBase + nFromBase + 1 ); } #undef hb_stackBaseItem @@ -337,15 +340,15 @@ char * hb_stackDateBuffer( void ) } #undef hb_stackGetStaticsBase -int hb_stackGetStaticsBase( void ) +LONG hb_stackGetStaticsBase( void ) { - return hb_stack.iStatics; + return hb_stack.lStatics; } #undef hb_stackSetStaticsBase -void hb_stackSetStaticsBase( int iBase ) +void hb_stackSetStaticsBase( LONG lBase ) { - hb_stack.iStatics = iBase; + hb_stack.lStatics = lBase; } #undef hb_stackWithObjectItem @@ -373,6 +376,22 @@ PHB_ITEM ** hb_stackItemBasePtr( void ) return &hb_stack.pItems; } +void hb_stackClearMevarsBase( void ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_stackClearMevarsBase()")); + + if( hb_stack.pBase > hb_stack.pPos ) + { + PHB_ITEM pBase = * hb_stack.pBase; + + while( pBase->item.asSymbol.stackstate->ulPrivateBase != 0 ) + { + pBase->item.asSymbol.stackstate->ulPrivateBase = 0; + pBase = * ( hb_stack.pItems + pBase->item.asSymbol.stackstate->lBaseItem ); + } + } +} + int hb_stackCallDepth( void ) { LONG lOffset = hb_stack.pBase - hb_stack.pItems; @@ -380,7 +399,7 @@ int hb_stackCallDepth( void ) while( lOffset > 0 ) { - lOffset = ( * ( hb_stack.pItems + lOffset ) )->item.asSymbol.stackbase; + lOffset = ( * ( hb_stack.pItems + lOffset ) )->item.asSymbol.stackstate->lBaseItem; ++iLevel; } @@ -392,7 +411,7 @@ LONG hb_stackBaseProcOffset( int iLevel ) LONG lOffset = hb_stack.pBase - hb_stack.pItems; while( iLevel-- > 0 && lOffset > 0 ) - lOffset = ( * ( hb_stack.pItems + lOffset ) )->item.asSymbol.stackbase; + lOffset = ( * ( hb_stack.pItems + lOffset ) )->item.asSymbol.stackstate->lBaseItem; if( iLevel < 0 ) return lOffset; @@ -503,7 +522,7 @@ void hb_stackDispCall( void ) { char buffer[ HB_SYMBOL_NAME_LEN + HB_SYMBOL_NAME_LEN + 32 ]; - pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackbase; + pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackstate->lBaseItem; if( ( *( pBase + 1 ) )->type == HB_IT_ARRAY ) sprintf( buffer, HB_I_("Called from %s:%s(%i)"), hb_objGetClsName( *(pBase + 1) ), @@ -573,7 +592,7 @@ LONG WINAPI hb_UnhandledExceptionFilter( struct _EXCEPTION_POINTERS * ExceptionI strcat( msg, buffer ); - pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackbase; + pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackstate->lBaseItem; } while( pBase != hb_stack.pItems ); @@ -617,7 +636,7 @@ ULONG _System OS2TermHandler(PEXCEPTIONREPORTRECORD p1, ( *pBase )->item.asSymbol.value->szName, ( *pBase )->item.asSymbol.lineno ); - pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackbase; + pBase = hb_stack.pItems + ( *pBase )->item.asSymbol.stackstate->lBaseItem; } while( pBase != hb_stack.pItems ); } diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index c203713cb4..ac61d28aaf 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -538,24 +538,28 @@ HB_EXPORT int hb_vmQuit( void ) hb_vmCleanModuleFunctions(); /* release all known items stored in subsystems */ + hb_itemClear( hb_stackReturnItem() ); + hb_stackRemove( 0 ); /* clear stack items */ + hb_memvarsClear(); /* clear all PUBLIC (and PRIVATE if any) variables */ + + /* intentionally here to allow executing object destructors for all + * cross references items before we release classy subsystem + */ + hb_gcCollectAll(); + hb_rddShutDown(); hb_idleShutDown(); hb_errExit(); hb_clsReleaseAll(); - hb_vmReleaseLocalSymbols(); /* releases the local modules linked list */ - hb_dynsymRelease(); /* releases the dynamic symbol table */ - hb_conRelease(); /* releases Console */ - hb_setRelease(); /* releases Sets */ - hb_cdpReleaseAll(); /* releases codepages */ + hb_itemClear( &s_aStatics ); /* release all remaining items */ - hb_stackRemove( 0 ); - hb_itemClear( hb_stackReturnItem() ); - hb_itemClear( &s_aStatics ); - hb_memvarsRelease(); /* clear all PUBLIC variables */ - /* release all known garbage */ - /* hb_gcReleaseAll(); */ + hb_conRelease(); /* releases Console */ + hb_setRelease(); /* releases Sets */ + hb_vmReleaseLocalSymbols(); /* releases the local modules linked list */ + hb_dynsymRelease(); /* releases the dynamic symbol table */ + hb_cdpReleaseAll(); /* releases codepages */ /* release all known garbage */ if( hb_xquery( HB_MEM_USEDMAX ) ) /* check if fmstat is ON */ @@ -575,7 +579,6 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) { LONG w = 0; BOOL bCanRecover = FALSE; - ULONG ulPrivateBase; BOOL bDynCode = pSymbols == NULL || ( pSymbols->scope.value & HB_FS_DYNCODE ) != 0; #ifndef HB_NO_PROFILER ULONG ulLastOpcode = 0; /* opcodes profiler support */ @@ -587,14 +590,6 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) HB_TRACE(HB_TR_DEBUG, ("hb_vmExecute(%p, %p)", pCode, pSymbols)); - /* NOTE: if pSymbols == NULL then hb_vmExecute is called from macro - * evaluation. In this case all PRIVATE variables created during - * macro evaluation belong to a function/procedure where macro - * compiler was called. - */ - /* NOTE: Initialization with 0 is needed to avoid GCC -O2 warning */ - ulPrivateBase = pSymbols ? hb_memvarGetPrivatesBase() : 0; - #ifndef HB_NO_PROFILER if( hb_bProfiler ) ulPastClock = ( ULONG ) clock(); @@ -1864,9 +1859,6 @@ HB_EXPORT void hb_vmExecute( const BYTE * pCode, PHB_SYMB pSymbols ) } } } - - if( pSymbols ) - hb_memvarSetPrivatesBase( ulPrivateBase ); } /* ------------------------------- */ @@ -4298,7 +4290,7 @@ static void hb_vmSFrame( PHB_SYMB pSym ) /* sets the statics frame for a fu HB_TRACE(HB_TR_DEBUG, ("hb_vmSFrame(%p)", pSym)); /* _INITSTATICS is now the statics frame. Statics() changed it! */ - hb_stackSetStaticsBase( pSym->value.iStaticsBase ); + hb_stackSetStaticsBase( pSym->value.lStaticsBase ); } static void hb_vmStatics( PHB_SYMB pSym, USHORT uiStatics ) /* initializes the global aStatics array or redimensionates it */ @@ -4307,13 +4299,13 @@ static void hb_vmStatics( PHB_SYMB pSym, USHORT uiStatics ) /* initializes the g if( HB_IS_NIL( &s_aStatics ) ) { - pSym->value.iStaticsBase = 0; /* statics frame for this PRG */ + pSym->value.lStaticsBase = 0; /* statics frame for this PRG */ hb_arrayNew( &s_aStatics, uiStatics ); } else { - pSym->value.iStaticsBase = hb_arrayLen( &s_aStatics ); - hb_arraySize( &s_aStatics, ( ULONG ) pSym->value.iStaticsBase + uiStatics ); + pSym->value.lStaticsBase = hb_arrayLen( &s_aStatics ); + hb_arraySize( &s_aStatics, ( ULONG ) pSym->value.lStaticsBase + uiStatics ); } } @@ -4616,7 +4608,7 @@ HB_EXPORT void hb_vmPushSymbol( PHB_SYMB pSym ) pItem->type = HB_IT_SYMBOL; pItem->item.asSymbol.value = pSym; - pItem->item.asSymbol.stackbase = hb_stackTopOffset() - 1; + pItem->item.asSymbol.stackstate = NULL; } /* -3 -> HB_P_PUSHBLOCK @@ -5950,12 +5942,10 @@ ULONG hb_vmFlagEnabled( ULONG flags ) #define HB_XVM_RETURN return ( s_uiActionRequest & \ ( HB_ENDPROC_REQUESTED | HB_BREAK_REQUESTED | HB_QUIT_REQUESTED ) ) != 0; -HB_EXPORT void hb_xvmExitProc( ULONG ulPrivateBase ) +HB_EXPORT void hb_xvmExitProc( void ) { if( s_uiActionRequest & HB_ENDPROC_REQUESTED ) s_uiActionRequest = 0; - - hb_memvarSetPrivatesBase( ulPrivateBase ); } @@ -6281,7 +6271,7 @@ HB_EXPORT void hb_xvmPushFuncSymbol( PHB_SYMB pSym ) pItem = hb_stackAllocItem(); pItem->type = HB_IT_SYMBOL; pItem->item.asSymbol.value = pSym; - pItem->item.asSymbol.stackbase = hb_stackTopOffset() - 1; + pItem->item.asSymbol.stackstate = NULL; hb_stackAllocItem()->type = HB_IT_NIL; } diff --git a/harbour/source/vm/itemapi.c b/harbour/source/vm/itemapi.c index 8ddcfd186d..7549bf28d0 100644 --- a/harbour/source/vm/itemapi.c +++ b/harbour/source/vm/itemapi.c @@ -1135,10 +1135,10 @@ HB_EXPORT PHB_ITEM hb_itemPutSymbol( PHB_ITEM pItem, PHB_SYMB pSym ) pItem = hb_itemNew( NULL ); pItem->type = HB_IT_SYMBOL; - pItem->item.asSymbol.stackbase = 0; - pItem->item.asSymbol.lineno = 0; - pItem->item.asSymbol.paramcnt = 0; - pItem->item.asSymbol.value = pSym; + pItem->item.asSymbol.value = pSym; + pItem->item.asSymbol.stackstate = NULL; + pItem->item.asSymbol.lineno = 0; + pItem->item.asSymbol.paramcnt = 0; return pItem; } diff --git a/harbour/source/vm/memvars.c b/harbour/source/vm/memvars.c index 154d8cba41..ac5a6b64cd 100644 --- a/harbour/source/vm/memvars.c +++ b/harbour/source/vm/memvars.c @@ -98,9 +98,6 @@ struct mv_PUBLIC_var_info }; static void hb_memvarCreateFromDynSymbol( PHB_DYNS, BYTE, PHB_ITEM ); -static void hb_memvarAddPrivate( PHB_DYNS ); -static void hb_memvarReleasePublic( PHB_ITEM pMemVar ); -static HB_DYNS_PTR hb_memvarFindSymbol( char *, ULONG ); void hb_memvarsInit( void ) { @@ -116,29 +113,6 @@ void hb_memvarsInit( void ) s_privateStackCnt = s_privateStackBase = 0; } -/* clear all variables except the detached ones - * Should be called at application exit only -*/ -void hb_memvarsRelease( void ) -{ - ULONG ulCnt = s_globalLastFree; - - HB_TRACE(HB_TR_DEBUG, ("hb_memvarsClear()")); - - if( s_globalTable ) - { - while( --ulCnt ) - { - if( s_globalTable[ ulCnt ].counter && s_globalTable[ ulCnt ].hPrevMemvar != ( HB_HANDLE )-1 ) - { - hb_itemClear( s_globalTable[ ulCnt ].pVarItem ); - hb_xfree( s_globalTable[ ulCnt ].pVarItem ); - s_globalTable[ ulCnt ].counter = 0; - } - } - } -} - void hb_memvarsFree( void ) { if( s_globalTable ) @@ -160,25 +134,27 @@ HB_VALUE_PTR *hb_memvarValueBaseAddress( void ) * This function creates new global value. * * pSource = item value that have to be stored or NULL - * bTrueMemvar = TRUE | FALSE - * FALSE if function is called to create memvar variable for a codeblock + * hPrevMemvar + * -1 if function is called to create memvar variable for a codeblock * (to store detached local variable) - in this case we have to do * exact copy of passed item (without duplicating its value and * without reference decrementing) - * TRUE if we are creating regular memvar variable (PUBLI or PRIVATE) + * else we are creating regular memvar variable (PUBLIC or PRIVATE) * In this case we have to do normal item coping. + * hPrevMemvar > 0 is old memvar value which will be hidden by + * new PRIVATE variable * * Returns: * handle to variable memory or fails * */ -HB_HANDLE hb_memvarValueNew( HB_ITEM_PTR pSource, BOOL bTrueMemvar ) +static HB_HANDLE hb_memvarValueNew( HB_ITEM_PTR pSource, HB_HANDLE hPrevMemvar ) { HB_VALUE_PTR pValue; HB_HANDLE hValue; /* handle 0 is reserved */ /* = 1 removed, since it's initialized in all branches. Caused a warning with Borland C++ */ - HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueNew(%p, %d)", pSource, (int) bTrueMemvar)); + HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueNew(%p, %lu)", pSource, hPrevMemvar)); if( s_globalFirstFree ) { @@ -208,28 +184,104 @@ 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->pVarItem->type = HB_IT_NIL; + pValue->hPrevMemvar = hPrevMemvar; + pValue->counter = 1; if( pSource ) { - if( bTrueMemvar ) - hb_itemCopy( pValue->pVarItem, pSource ); - else + if( hPrevMemvar == ( HB_HANDLE ) -1 ) /* detached local - copy its body only */ memcpy( pValue->pVarItem, pSource, sizeof( HB_ITEM ) ); + else + hb_itemCopy( pValue->pVarItem, pSource ); } - if( bTrueMemvar ) - pValue->hPrevMemvar = 0; - else - pValue->hPrevMemvar = ( HB_HANDLE ) -1; /* detached variable */ - HB_TRACE(HB_TR_INFO, ("hb_memvarValueNew: memvar item created with handle %i", hValue)); return hValue; } -/* Detach local variable (swap current value with a memvar handle) -*/ +static void hb_memvarRecycle( HB_HANDLE hValue ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_memvarRecycle(%lu)", hValue)); + + s_globalTable[ hValue ].hPrevMemvar = s_globalFirstFree; + s_globalFirstFree = hValue; +} + +/* + * This function increases the number of references to passed global value + */ +void hb_memvarValueIncRef( HB_HANDLE hValue ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueIncRef(%lu)", hValue)); + + s_globalTable[ hValue ].counter++; + + HB_TRACE(HB_TR_INFO, ("Memvar item (%i) increment refCounter=%li", hValue, s_globalTable[ hValue ].counter)); +} + +/* + * This function decreases the number of references to passed global value. + * If it is the last reference then this value is deleted. + */ +void hb_memvarValueDecRef( HB_HANDLE hValue ) +{ + HB_VALUE_PTR pValue; + + HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueDecRef(%lu)", hValue)); + + pValue = s_globalTable + hValue; + + HB_TRACE(HB_TR_INFO, ("Memvar item (%i) decrement refCounter=%li", hValue, pValue->counter-1)); + + if( --pValue->counter == 0 ) + { + if( HB_IS_COMPLEX( pValue->pVarItem ) ) + hb_itemClear( pValue->pVarItem ); + hb_xfree( pValue->pVarItem ); + hb_memvarRecycle( hValue ); + + HB_TRACE(HB_TR_INFO, ("Memvar item (%i) deleted", hValue)); + } +} + +/* + * Detach local variable (swap current value with a memvar handle) + */ +static void hb_memvarDetachDynSym( PHB_DYNS pDynSym, BOOL fRestore ) +{ + HB_VALUE_PTR pValue; + HB_HANDLE hValue; + + HB_TRACE(HB_TR_DEBUG, ("hb_memvarDetachDynSym(%p, %d)", pDynSym, fRestore)); + + hValue = pDynSym->hMemvar; + pValue = s_globalTable + hValue; + pDynSym->hMemvar = fRestore ? pValue->hPrevMemvar : 0; + + if( --pValue->counter == 0 ) + { + if( HB_IS_COMPLEX( pValue->pVarItem ) ) + hb_itemClear( pValue->pVarItem ); + hb_xfree( pValue->pVarItem ); + hb_memvarRecycle( hValue ); + + HB_TRACE(HB_TR_INFO, ("Memvar item (%i) deleted", hValue)); + } + else + { + /* memvar is still accessible by active references on HVM stack + * and/or as detached local in codeblocks - so we have to mark it + * as detached or it will be scanned in GC mark pass and if some + * cross references exists it will never be freed. + */ + pValue->hPrevMemvar = ( HB_HANDLE ) -1; + } +} + +/* + * Detach local variable (swap current value with a memvar handle) + */ HB_ITEM_PTR hb_memvarDetachLocal( HB_ITEM_PTR pLocal ) { HB_TRACE(HB_TR_DEBUG, ("hb_memvarDetachLocal(%p, %d)", pLocal, pLocal->type )); @@ -250,9 +302,9 @@ HB_ITEM_PTR hb_memvarDetachLocal( HB_ITEM_PTR pLocal ) * 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_MEMVAR( pLocal ) ) + if( ! HB_IS_MEMVAR( pLocal ) ) { - HB_HANDLE hMemvar = hb_memvarValueNew( pLocal, FALSE ); + HB_HANDLE hMemvar = hb_memvarValueNew( pLocal, ( HB_HANDLE ) -1 ); pLocal->type = HB_IT_BYREF | HB_IT_MEMVAR; pLocal->item.asMemvar.itemsbase = &s_globalTable; @@ -301,135 +353,34 @@ ULONG hb_memvarGetPrivatesBase( void ) /* * This function releases PRIVATE variables created after passed base - * */ void hb_memvarSetPrivatesBase( ULONG ulBase ) { - HB_HANDLE hVar, hOldValue; - HB_TRACE(HB_TR_DEBUG, ("hb_memvarSetPrivatesBase(%lu)", ulBase)); while( s_privateStackCnt > s_privateStackBase ) { - hVar = s_privateStack[ --s_privateStackCnt ]->hMemvar; - if( hVar ) + if( s_privateStack[ --s_privateStackCnt ]->hMemvar ) { - hOldValue = s_globalTable[ hVar ].hPrevMemvar; - hb_memvarValueDecRef( hVar ); - /* - * Restore previous value for variables that were overridden + /* Restore previous value for variables that were overridden */ - s_privateStack[ s_privateStackCnt ]->hMemvar = hOldValue; + hb_memvarDetachDynSym( s_privateStack[ s_privateStackCnt ], TRUE ); } } s_privateStackBase = ulBase; } /* - * This function increases the number of references to passed global value - * + * Update PRIVATE base ofsset so they will not be removed + * when function return */ -void hb_memvarValueIncRef( HB_HANDLE hValue ) +void hb_memvarUpdatePrivatesBase( void ) { - HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueIncRef(%lu)", hValue)); + HB_TRACE(HB_TR_DEBUG, ("hb_memvarUpdatePrivatesBase()")); - s_globalTable[ hValue ].counter++; - - HB_TRACE(HB_TR_INFO, ("Memvar item (%i) increment refCounter=%li", hValue, s_globalTable[ hValue ].counter)); + s_privateStackBase = s_privateStackCnt; } -static void hb_memvarRecycle( HB_HANDLE hValue ) -{ - HB_TRACE(HB_TR_DEBUG, ("hb_memvarRecycle(%lu)", hValue)); - - if( s_globalFirstFree ) - { - s_globalTable[ hValue ].hPrevMemvar = s_globalFirstFree; - s_globalFirstFree = hValue; - } - else - { - /* first free value in the list */ - s_globalFirstFree = hValue; - s_globalTable[ hValue ].hPrevMemvar = 0; - } -} - -/* - * This function decreases the number of references to passed global value. - * If it is the last reference then this value is deleted. - * - */ -void hb_memvarValueDecRef( HB_HANDLE hValue ) -{ - HB_VALUE_PTR pValue; - - HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueDecRef(%lu)", hValue)); - - pValue = s_globalTable + hValue; - - HB_TRACE(HB_TR_INFO, ("Memvar item (%i) decrement refCounter=%li", hValue, pValue->counter-1)); - - if( pValue->counter > 0 ) - { - /* Notice that Counter can be equal to 0. - * This can happen if for example PUBLIC variable holds a codeblock - * with detached variable. When hb_memvarsRelease() is called then - * detached variable can be released before the codeblock. So if - * the codeblock will be released later then it will try to release - * again this detached variable. - */ - if( --pValue->counter == 0 ) - { - if( HB_IS_COMPLEX( pValue->pVarItem ) ) - hb_itemClear( pValue->pVarItem ); - hb_xfree( pValue->pVarItem ); - hb_memvarRecycle( hValue ); - - HB_TRACE(HB_TR_INFO, ("Memvar item (%i) deleted", hValue)); - } - } -} - -#if 0 -/* This function is called from releasing of detached local variables - * referenced in a codeblock that is wiped out by the Garbage Collector. - * Decrement the reference counter and clear a value stored in the memvar. - * Don't clear arrays or codeblocks to avoid loops - these values will be - * released by the garbage collector. - */ -void hb_memvarValueDecGarbageRef( HB_HANDLE hValue ) -{ - HB_VALUE_PTR pValue; - - HB_TRACE(HB_TR_DEBUG, ("hb_memvarValueDecRef(%lu)", hValue)); - - pValue = s_globalTable + hValue; - - HB_TRACE(HB_TR_INFO, ("Memvar item (%i) decrement refCounter=%li", hValue, pValue->counter-1)); - - if( pValue->counter > 0 ) - { - /* Notice that Counter can be equal to 0. - * This can happen if for example PUBLIC variable holds a codeblock - * with detached variable. When hb_memvarsRelease() is called then - * detached variable can be released before the codeblock. So if - * the codeblock will be released later then it will try to release - * again this detached variable. - */ - if( --pValue->counter == 0 ) - { - 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)); - } - } -} -#endif - /* * This functions copies passed item value into the memvar pointed * by symbol @@ -601,6 +552,50 @@ void hb_memvarNewParameter( PHB_SYMB pSymbol, PHB_ITEM pValue ) hb_memvarCreateFromDynSymbol( pSymbol->pDynSym, HB_MV_PRIVATE, pValue ); } +static HB_DYNS_PTR hb_memvarFindSymbol( char * szArg, ULONG ulLen ) +{ + HB_DYNS_PTR pDynSym = NULL; + + HB_TRACE(HB_TR_DEBUG, ("hb_memvarFindSymbol(%p,%lu)", szArg, ulLen)); + + if( szArg && *szArg && ulLen ) + { + char szUprName[ HB_SYMBOL_NAME_LEN + 1 ]; + int iSize = 0; + + do + { + char cChar = *szArg++; + + if( cChar >= 'a' && cChar <= 'z' ) + { + szUprName[ iSize++ ] = cChar - ( 'a' - 'A' ); + } + else if( cChar == ' ' || cChar == '\t' || cChar == '\n' ) + { + if( iSize ) + break; + } + else if( !cChar ) + { + break; + } + else + { + szUprName[ iSize++ ] = cChar; + } + } + while( --ulLen && iSize < HB_SYMBOL_NAME_LEN ); + + if( iSize ) + { + szUprName[ iSize ] = '\0'; + pDynSym = hb_dynsymFind( szUprName ); + } + } + return pDynSym; +} + char * hb_memvarGetStrValuePtr( char * szVarName, ULONG *pulLen ) { HB_DYNS_PTR pDynVar; @@ -638,7 +633,7 @@ char * hb_memvarGetStrValuePtr( char * szVarName, ULONG *pulLen ) * * pMemvar - an item that stores the name of variable - it can be either * the HB_IT_SYMBOL (if created by PUBLIC statement) or HB_IT_STRING - * (if created by direct call to __PUBLIC function) + * (if created by direct call to __MVPUBLIC function) * bScope - the scope of created variable - if a variable with the same name * exists already then it's value is hidden by new variable with * passed scope @@ -676,7 +671,7 @@ static void hb_memvarCreateFromDynSymbol( PHB_DYNS pDynVar, BYTE bScope, PHB_ITE */ if( ! pDynVar->hMemvar ) { - pDynVar->hMemvar = hb_memvarValueNew( pValue, TRUE ); + pDynVar->hMemvar = hb_memvarValueNew( pValue, 0 ); if( !pValue ) { /* new PUBLIC variable - initialize it to .F. @@ -701,10 +696,7 @@ static void hb_memvarCreateFromDynSymbol( PHB_DYNS pDynVar, BYTE bScope, PHB_ITE * visible at this moment so later we can restore this value when * the new variable will be released */ - HB_HANDLE hCurrentValue = pDynVar->hMemvar; - - pDynVar->hMemvar = hb_memvarValueNew( pValue, TRUE ); - s_globalTable[ pDynVar->hMemvar ].hPrevMemvar = hCurrentValue; + pDynVar->hMemvar = hb_memvarValueNew( pValue, pDynVar->hMemvar ); /* Add this variable to the PRIVATE variables stack */ @@ -722,31 +714,32 @@ static void hb_memvarRelease( HB_ITEM_PTR pMemvar ) if( HB_IS_STRING( pMemvar ) ) { - ULONG ulBase = s_privateStackCnt; - PHB_DYNS pDynVar; + PHB_DYNS pDynSymbol = hb_memvarFindSymbol( pMemvar->item.asString.value, + pMemvar->item.asString.length ); - /* Find the variable with a requested name that is currently visible - * Start from the top of the stack. - */ - while( ulBase > 0 ) + if( pDynSymbol && pDynSymbol->hMemvar ) { - pDynVar = s_privateStack[ --ulBase ]; + ULONG ulBase = s_privateStackCnt; - /* reset current value to NIL - the overriden variables will be - * visible after exit from current procedure + /* Find the variable with a requested name that is currently visible + * Start from the top of the stack. */ - if( pDynVar->hMemvar ) + while( ulBase > 0 ) { - if( hb_stricmp( pDynVar->pSymbol->szName, pMemvar->item.asString.value ) == 0 ) + if( pDynSymbol == s_privateStack[ --ulBase ] ) { - hb_itemClear( s_globalTable[ pDynVar->hMemvar ].pVarItem ); + /* reset current value to NIL - the overriden variables will be + * visible after exit from current procedure + */ + hb_itemClear( s_globalTable[ pDynSymbol->hMemvar ].pVarItem ); return; } } + + /* No match found for PRIVATEs - it's PUBLIC so let's remove it. + */ + hb_memvarDetachDynSym( pDynSymbol, FALSE ); } - /* No match found for PRIVATEs - try PUBLICs. - */ - hb_memvarReleasePublic( pMemvar ); } else hb_errRT_BASE( EG_ARG, 3008, NULL, "RELEASE", HB_ERR_ARGS_BASEPARAMS ); @@ -796,21 +789,18 @@ static int hb_memvarScopeGet( PHB_DYNS pDynVar ) else { ULONG ulBase = s_privateStackCnt; /* start from the top of the stack */ - int iMemvar = HB_MV_PUBLIC; while( ulBase ) { - --ulBase; - if( pDynVar == s_privateStack[ ulBase ] ) + if( pDynVar == s_privateStack[ --ulBase ] ) { if( ulBase >= s_privateStackBase ) - iMemvar = HB_MV_PRIVATE_LOCAL; + return HB_MV_PRIVATE_LOCAL; else - iMemvar = HB_MV_PRIVATE_GLOBAL; - ulBase = 0; + return HB_MV_PRIVATE_GLOBAL; } } - return iMemvar; + return HB_MV_PUBLIC; } } @@ -818,26 +808,16 @@ static int hb_memvarScopeGet( PHB_DYNS pDynVar ) */ int hb_memvarScope( char * szVarName, ULONG ulLength ) { - int iMemvar = HB_MV_ERROR; - char * szName; + PHB_DYNS pDynVar; HB_TRACE(HB_TR_DEBUG, ("hb_memvarScope(%s, %lu)", szVarName, ulLength)); - szName = ( char * ) hb_xalloc( ulLength ); - if( szName ) - { - PHB_DYNS pDynVar; + pDynVar = hb_memvarFindSymbol( szVarName, ulLength ); - memcpy( szName, szVarName, ulLength ); - pDynVar = hb_dynsymFind( hb_strUpper( szName, ulLength - 1 ) ); - if( pDynVar ) - iMemvar = hb_memvarScopeGet( pDynVar ); - else - iMemvar = HB_MV_NOT_FOUND; - hb_xfree( szName ); - } - - return iMemvar; + if( pDynVar ) + return hb_memvarScopeGet( pDynVar ); + else + return HB_MV_NOT_FOUND; } /* Releases memory occupied by a variable @@ -847,15 +827,22 @@ static HB_DYNS_FUNC( hb_memvarClear ) HB_SYMBOL_UNUSED( Cargo ); if( pDynSymbol->hMemvar ) - { - s_globalTable[ pDynSymbol->hMemvar ].counter = 1; - hb_memvarValueDecRef( pDynSymbol->hMemvar ); - pDynSymbol->hMemvar = 0; - } + hb_memvarDetachDynSym( pDynSymbol, FALSE ); return TRUE; } +/* Clear all memvar variables */ +void hb_memvarsClear( void ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_memvarsClear()")); + + hb_stackClearMevarsBase(); + s_privateStackBase = 0; + hb_memvarSetPrivatesBase( 0 ); + hb_dynsymEval( hb_memvarClear, NULL ); +} + /* Checks passed dynamic symbol if it is a PUBLIC variable and * increments the counter eventually */ @@ -867,34 +854,6 @@ static HB_DYNS_FUNC( hb_memvarCountPublics ) return TRUE; } -/* Checks passed dynamic symbol if it is a PUBLIC variable and - * released it eventually stoping the searching - */ -static HB_DYNS_FUNC( hb_memvarClearPublic ) -{ - if( hb_memvarScopeGet( pDynSymbol ) == HB_MV_PUBLIC && - hb_stricmp( pDynSymbol->pSymbol->szName, (char *) Cargo ) == 0 ) - { - s_globalTable[ pDynSymbol->hMemvar ].counter = 1; - hb_memvarValueDecRef( pDynSymbol->hMemvar ); - pDynSymbol->hMemvar = 0; - return FALSE; - } - - return TRUE; -} - -/* find and release if exists given public variable - */ -static void hb_memvarReleasePublic( PHB_ITEM pMemVar ) -{ - char *sPublic = pMemVar->item.asString.value; - - HB_TRACE(HB_TR_DEBUG, ("hb_memvarReleasePublic(%p)", pMemVar )); - - hb_dynsymEval( hb_memvarClearPublic, ( void * ) sPublic ); -} - /* Count the number of variables with given scope */ static int hb_memvarCount( int iScope ) @@ -979,29 +938,6 @@ static HB_ITEM_PTR hb_memvarDebugVariable( int iScope, int iPos, char * *pszName return pValue; } -static HB_DYNS_PTR hb_memvarFindSymbol( char * szArg, ULONG ulLen ) -{ - HB_DYNS_PTR pDynSym = NULL; - - HB_TRACE(HB_TR_DEBUG, ("hb_memvarFindSymbol(%p,%lu)", szArg, ulLen)); - - if( szArg && *szArg && ulLen ) - { - char * szName = ( char * ) hb_xgrab( ulLen + 1 ); - - szName[ ulLen ] = '\0'; - do - { - --ulLen; - szName[ ulLen ] = toupper( szArg[ ulLen ] ); - } while( ulLen ); - - pDynSym = hb_dynsymFind( szName ); - hb_xfree( szName ); - } - return pDynSym; -} - /* ************************************************************************** */ HB_FUNC( __MVPUBLIC ) @@ -1065,6 +1001,7 @@ HB_FUNC( __MVPRIVATE ) hb_memvarCreateFromItem( pMemvar, VS_PRIVATE, NULL ); } } + hb_memvarUpdatePrivatesBase(); } } @@ -1141,7 +1078,7 @@ HB_FUNC( __MVSCOPE ) HB_FUNC( __MVCLEAR ) { - hb_dynsymEval( hb_memvarClear, NULL ); + hb_memvarsClear(); } HB_FUNC( __MVDBGINFO ) @@ -1277,6 +1214,7 @@ HB_FUNC( __MVPUT ) * create the PRIVATE one */ hb_memvarCreateFromDynSymbol( hb_dynsymGet( pName->item.asString.value ), VS_PRIVATE, pValue ); + hb_memvarUpdatePrivatesBase(); } hb_itemReturn( pValue ); } @@ -1479,7 +1417,7 @@ HB_FUNC( __MVRESTORE ) /* Clear all memory variables if not ADDITIVE */ if( ! bAdditive ) - hb_dynsymEval( hb_memvarClear, NULL ); + hb_memvarsClear(); /* Generate filename */ @@ -1508,7 +1446,7 @@ HB_FUNC( __MVRESTORE ) if( fhnd != FS_ERROR ) { char * pszMask = ISCHAR( 3 ) ? hb_parc( 3 ) : ( char * ) "*"; - BOOL bIncludeMask = ISCHAR( 4 ) ? hb_parl( 4 ) : TRUE; + BOOL bIncludeMask = ISLOG( 4 ) ? hb_parl( 4 ) : TRUE; BYTE buffer[ HB_MEM_REC_LEN ]; while( hb_fsRead( fhnd, buffer, HB_MEM_REC_LEN ) == HB_MEM_REC_LEN ) @@ -1594,6 +1532,7 @@ HB_FUNC( __MVRESTORE ) } hb_fsClose( fhnd ); + hb_memvarUpdatePrivatesBase(); } else hb_retl( FALSE ); diff --git a/harbour/source/vm/pcount.c b/harbour/source/vm/pcount.c index 31419cce61..2ab94193cb 100644 --- a/harbour/source/vm/pcount.c +++ b/harbour/source/vm/pcount.c @@ -58,7 +58,7 @@ HB_FUNC( PCOUNT ) { /* Skip current function */ - PHB_ITEM pBase = hb_stackItem( ( hb_stackBaseItem() )->item.asSymbol.stackbase ); + PHB_ITEM pBase = hb_stackItem( hb_stackBaseItem()->item.asSymbol.stackstate->lBaseItem ); hb_retni( pBase->item.asSymbol.paramcnt ); } diff --git a/harbour/source/vm/proc.c b/harbour/source/vm/proc.c index 05395123bb..51041182a4 100644 --- a/harbour/source/vm/proc.c +++ b/harbour/source/vm/proc.c @@ -167,7 +167,7 @@ char * hb_procname( int iLevel, char * szName, BOOL bSkipBlock ) if( strcmp( szTstName, "__EVAL" ) == 0 ) { lPrevOffset = lOffset; - lOffset = hb_stackItem( lOffset )->item.asSymbol.stackbase; + lOffset = hb_stackItem( lOffset )->item.asSymbol.stackstate->lBaseItem; } } diff --git a/harbour/source/vm/pvalue.c b/harbour/source/vm/pvalue.c index f21289c195..84c6ff4853 100644 --- a/harbour/source/vm/pvalue.c +++ b/harbour/source/vm/pvalue.c @@ -58,7 +58,7 @@ HB_FUNC( HB_PVALUE ) { USHORT uiParam = hb_parni( 1 ); - LONG lOffset = hb_stackBaseItem()->item.asSymbol.stackbase; /* Skip function + self */ + LONG lOffset = hb_stackBaseItem()->item.asSymbol.stackstate->lBaseItem; /* Skip function + self */ PHB_ITEM pBase = hb_stackItem( lOffset ); if( uiParam && uiParam <= pBase->item.asSymbol.paramcnt ) /* Valid number */