From 053e67ddebb5ea440456c31a369e3e783bf3e4ca Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Sat, 6 Oct 2007 10:45:13 +0000 Subject: [PATCH] 2007-10-06 12:45 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbsetup.h * harbour/source/rtl/hbffind.c * harbour/source/rtl/filesys.c * cleanup * harbour/source/vm/hvm.c % use extended reference for enumerator destructor - it eliminates 3 hb_itemNew() calls reducing the cost of creating FOR EACH envelope about 40% --- harbour/ChangeLog | 11 +++ harbour/include/hbsetup.h | 38 ++++----- harbour/source/rtl/filesys.c | 3 +- harbour/source/rtl/hbffind.c | 3 +- harbour/source/vm/hvm.c | 158 ++++++++++++++++++++++------------- 5 files changed, 132 insertions(+), 81 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 88392ac9ae..2acff06295 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,17 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2007-10-06 12:45 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbsetup.h + * harbour/source/rtl/hbffind.c + * harbour/source/rtl/filesys.c + * cleanup + + * harbour/source/vm/hvm.c + % use extended reference for enumerator destructor - it eliminates + 3 hb_itemNew() calls reducing the cost of creating FOR EACH envelope + about 40% + 2007-10-05 23:44 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbsetup.h * minor cleanup comment diff --git a/harbour/include/hbsetup.h b/harbour/include/hbsetup.h index 730524051b..df0ed76cdf 100644 --- a/harbour/include/hbsetup.h +++ b/harbour/include/hbsetup.h @@ -57,7 +57,7 @@ /* *********************************************************************** * Include settings common for .PRG and .C files -*/ + */ #include "hbsetup.ch" /* *********************************************************************** @@ -71,7 +71,7 @@ /* *********************************************************************** * NOTE: You can select the default language modul used by Harbour, by * defining this to a valid language modul identifier. -*/ + */ #ifndef HB_LANG_DEFAULT #define HB_LANG_DEFAULT EN @@ -93,7 +93,7 @@ * HB_CALL_ON_STARTUP that is defined in 'hbinit.h' * * By default we are using extensions to ANSI C (symbol is not defined) -*/ + */ /*#define HARBOUR_STRICT_ANSI_C */ /* *********************************************************************** @@ -103,7 +103,7 @@ * To use "pascal" mode, you should define this macro to "pascal". * * By default we are not using any special calling conventions. -*/ + */ /*#define HB_FUNC_CALLCONV*/ /* *********************************************************************** @@ -114,7 +114,7 @@ * * By default this is turned on. * TODO: This should be disabled, when the parser has matured. -*/ + */ /*#define HARBOUR_YYDEBUG*/ /* *********************************************************************** @@ -128,7 +128,7 @@ * and will consume more memory. * * By default this is turned on. Define HB_FM_STATISTICS_OFF to turn it off. -*/ + */ #ifndef HB_FM_STATISTICS_OFF #define HB_FM_STATISTICS #endif @@ -160,7 +160,7 @@ * Borland C/C++ compilers. * * By default it is disabled (symbol is not defined) -*/ + */ /*#define HARBOUR_OBJ_GENERATION*/ /* *********************************************************************** @@ -168,7 +168,7 @@ * application (main() or WinMain()). * * By default the standard C main() function will be used. -*/ + */ /*#define HARBOUR_MAIN_STD*/ /*#define HARBOUR_MAIN_WIN*/ @@ -177,7 +177,7 @@ * compiler and runtime. You can override this setting in the make process. * * By default this value is 63 -*/ + */ #ifndef HB_SYMBOL_NAME_LEN /* NOTE: For complete CA-Cl*pper compatibility you can set the maximum symbol name to 10. Sometimes this can be useful for compiling legacy @@ -202,7 +202,7 @@ * It's not Clipper compatible extension and it's not enabled by default * anyhow old Harbour PP worked in such way and people may have some code * which needs it -*/ + */ /* #define HB_PP_MULTILINE_STRING */ /* *********************************************************************** @@ -212,7 +212,7 @@ * disabled/enabled at runtime using HB_SETMACRO() function * * By default we do not support commands in the macro compiler. -*/ + */ /* #define HB_MACRO_STATEMENTS */ @@ -221,7 +221,7 @@ * beyond the destination array size * * By default we are 100% Clipper compatible -*/ + */ /* #define HB_FIX_ACOPY_BUG */ /* *********************************************************************** @@ -236,7 +236,7 @@ * items, just swapping) in this functions. * Using this option makes sorting *much* faster, but if you have a * problem, or the low level stuff changes, turn it off. [vszakats] -*/ + */ /* * It's not longer used - current code which uses hb_itemSwap() should * give similar performance (probably a little bit worser due to some small @@ -253,7 +253,7 @@ * There is no data validation if this is enabled. * * By default we are using secure method. -*/ + */ /* #define HB_FAST_STOD */ /* *********************************************************************** @@ -263,12 +263,12 @@ * * By default we are not using the strong typing because it is not * complete code and can be erratic now. -*/ + */ /* #define HB_COMP_STRONG_TYPES */ /* *********************************************************************** * Detect GCC/OS2 -*/ + */ #if defined(__EMX__) && ! defined(__RSXNT__) #define HARBOUR_GCC_OS2 #endif @@ -278,7 +278,7 @@ */ #if ( defined(__GNUC__) && \ ! ( defined(__DJGPP__) || defined(__EMX__) || defined(__RSXNT__) || \ - defined(_Windows) || defined(_WIN32) ) ) || \ + defined(_Windows) || defined(_WIN32) || defined(_WINCE) ) ) || \ ( defined(__WATCOMC__) && defined(__LINUX__) ) #define HOST_OS_UNIX_COMPATIBLE #define OS_UNIX_COMPATIBLE @@ -399,7 +399,7 @@ * Here you can force the EOL string to be CRLF * * By default, the EOL string depends upon the detected platform. -*/ + */ /* #define HB_EOL_CRLF */ #ifdef HB_EOL_CRLF #undef OS_EOL_LEN @@ -410,7 +410,7 @@ * See also the following files for task specific definitions/settings * * hbmath.h - math errors handling -*/ + */ /* *********************************************************************** * some fixes in compiler header files diff --git a/harbour/source/rtl/filesys.c b/harbour/source/rtl/filesys.c index 2f1de3ed2d..5bc58c8e26 100644 --- a/harbour/source/rtl/filesys.c +++ b/harbour/source/rtl/filesys.c @@ -183,7 +183,8 @@ #elif defined( HB_WIN32_IO ) #include - #if ( defined(__DMC__) || defined( _MSC_VER ) || defined( __LCC__ ) ) && !defined( INVALID_SET_FILE_POINTER ) + #if !defined( INVALID_SET_FILE_POINTER ) && \ + ( defined(__DMC__) || defined( _MSC_VER ) || defined( __LCC__ ) ) #define INVALID_SET_FILE_POINTER ((DWORD)-1) #endif #endif diff --git a/harbour/source/rtl/hbffind.c b/harbour/source/rtl/hbffind.c index 50ed85f53d..f32826cc18 100644 --- a/harbour/source/rtl/hbffind.c +++ b/harbour/source/rtl/hbffind.c @@ -717,8 +717,7 @@ static BOOL hb_fsFindNextLow( PHB_FFIND ffind ) #else { - HB_SYMBOL_UNUSED( ffind ); - HB_SYMBOL_UNUSED( info ); + /* HB_SYMBOL_UNUSED( ffind ); */ HB_SYMBOL_UNUSED( nYear ); HB_SYMBOL_UNUSED( nMonth ); diff --git a/harbour/source/vm/hvm.c b/harbour/source/vm/hvm.c index af79f449b1..3aff01923a 100644 --- a/harbour/source/vm/hvm.c +++ b/harbour/source/vm/hvm.c @@ -3553,21 +3553,6 @@ static void hb_vmWithObjectStart( void ) hb_stackWithObjectSetOffset( hb_stackTopOffset() - 2 ); } -typedef struct _HB_ENUMHOLDER -{ - PHB_ITEM pOldValue; - PHB_ITEM pEnumRef; -} HB_ENUMHOLDER, * PHB_ENUMHOLDER; - -static HB_GARBAGE_FUNC( hb_enumHolderRelease ) -{ - PHB_ENUMHOLDER pHolder = ( PHB_ENUMHOLDER ) Cargo; - - hb_itemMove( hb_itemUnRefOnce( pHolder->pEnumRef ), pHolder->pOldValue ); - hb_itemRelease( pHolder->pOldValue ); - hb_itemRelease( pHolder->pEnumRef ); -} - /* * Relase enumerator items - called from hb_itemClear() */ @@ -3588,8 +3573,81 @@ void hb_vmEnumRelease( PHB_ITEM pBase, PHB_ITEM pValue ) hb_stackPop(); hb_stackPopReturn(); } +} - hb_itemRelease( pBase ); +/* + * extended reference used as enumerator destructor + */ +typedef struct +{ + HB_ITEM basevalue; + HB_ITEM oldvalue; + HB_ITEM enumref; +} HB_ENUMREF, * PHB_ENUMREF; + +static PHB_ITEM hb_vmEnumRefRead( PHB_ITEM pRefer ) +{ + return &( ( PHB_ENUMREF ) pRefer->item.asExtRef.value )->oldvalue; +} + +static PHB_ITEM hb_vmEnumRefWrite( PHB_ITEM pRefer, PHB_ITEM pSource ) +{ + HB_SYMBOL_UNUSED( pRefer ); + HB_SYMBOL_UNUSED( pSource ); + return NULL; +} + +static void hb_vmEnumRefCopy( PHB_ITEM pDest ) +{ + pDest->type = HB_IT_NIL; +} + +static void hb_vmEnumRefClear( void * value ) +{ + hb_itemMove( hb_itemUnRefOnce( &( ( PHB_ENUMREF ) value )->enumref ), + &( ( PHB_ENUMREF ) value )->oldvalue ); + if( HB_IS_COMPLEX( &( ( PHB_ENUMREF ) value )->basevalue ) ) + hb_itemClear( &( ( PHB_ENUMREF ) value )->basevalue ); + if( HB_IS_COMPLEX( &( ( PHB_ENUMREF ) value )->enumref ) ) + hb_itemClear( &( ( PHB_ENUMREF ) value )->enumref ); + + hb_xfree( value ); +} + +static void hb_vmEnumRefMark( void * value ) +{ + if( HB_IS_GCITEM( &( ( PHB_ENUMREF ) value )->basevalue ) ) + hb_gcItemRef( &( ( PHB_ENUMREF ) value )->basevalue ); + if( HB_IS_GCITEM( &( ( PHB_ENUMREF ) value )->oldvalue ) ) + hb_gcItemRef( &( ( PHB_ENUMREF ) value )->oldvalue ); + if( HB_IS_GCITEM( &( ( PHB_ENUMREF ) value )->enumref ) ) + hb_gcItemRef( &( ( PHB_ENUMREF ) value )->enumref ); +} + +/* + * create extended reference for enumerator destructor + */ +static void hb_vmEnumReference( PHB_ITEM pBase ) +{ + static const HB_EXTREF s_EnumExtRef = { + hb_vmEnumRefRead, + hb_vmEnumRefWrite, + hb_vmEnumRefCopy, + hb_vmEnumRefClear, + hb_vmEnumRefMark }; + + PHB_ENUMREF pEnumExtRef; + + HB_TRACE(HB_TR_DEBUG, ("hb_vmEnumReference(%p)", pEnumRef)); + + pEnumExtRef = ( PHB_ENUMREF ) hb_xgrab( sizeof( HB_ENUMREF ) ); + pEnumExtRef->basevalue.type = HB_IT_NIL; + pEnumExtRef->oldvalue.type = HB_IT_NIL; + pEnumExtRef->enumref.type = HB_IT_NIL; + hb_itemMove( &pEnumExtRef->basevalue, pBase ); + pBase->type = HB_IT_BYREF | HB_IT_EXTREF; + pBase->item.asExtRef.value = ( void * ) pEnumExtRef; + pBase->item.asExtRef.func = &s_EnumExtRef; } /* At this moment the eval stack should store: @@ -3599,7 +3657,6 @@ void hb_vmEnumRelease( PHB_ITEM pBase, PHB_ITEM pValue ) /* Test to check the start point of the FOR EACH loop */ static void hb_vmEnumStart( BYTE nVars, BYTE nDescend ) { - HB_ITEM_PTR pItem; BOOL fStart = TRUE; int i; @@ -3614,97 +3671,80 @@ static void hb_vmEnumStart( BYTE nVars, BYTE nDescend ) for( i = ( int ) nVars << 1; i > 0 && fStart; i -= 2 ) { - HB_ITEM_PTR pValue, pOldValue, pEnum, pEnumRef; - PHB_ENUMHOLDER pHolder; + HB_ITEM_PTR pBase, pValue, pEnumRef, pEnum; pValue = hb_stackItemFromTop( -i ); - /* copy value to iterate and clear the stack item for enumerator destructor */ - pItem = hb_itemNew( pValue ); - if( HB_IS_COMPLEX( pValue ) ) - hb_itemClear( pValue ); - + /* create extended reference for enumerator destructor */ + hb_vmEnumReference( pValue ); + pBase = &( ( PHB_ENUMREF ) pValue->item.asExtRef.value )->basevalue; /* store the reference to control variable */ - pEnumRef = hb_itemNew( hb_stackItemFromTop( -i + 1 ) ); + pEnumRef = hb_stackItemFromTop( -i + 1 ); + hb_itemCopy( &( ( PHB_ENUMREF ) pValue->item.asExtRef.value )->enumref, + pEnumRef ); /* the control variable */ pEnum = hb_itemUnRefOnce( pEnumRef ); /* store the old value of control variable and clear it */ - pOldValue = hb_itemNew( NULL ); - hb_itemMove( pOldValue, pEnum ); - - /* create enumerator destructor */ - /* - * Here is a place for optimization - instead of allocating three new - * items we can keep them all in GC block and add mark/sweep function. - * I'll do that in the future when we will have final interface for it - * in our GC and mark/swap functions registered for extended - * HB_IT_POINTER items not allocated for each memory block. [druzus] - */ - pHolder = ( PHB_ENUMHOLDER ) hb_gcAlloc( sizeof( HB_ENUMHOLDER ), hb_enumHolderRelease ); - pHolder->pOldValue = pOldValue; - pHolder->pEnumRef = pEnumRef; - pValue->type = HB_IT_POINTER; - pValue->item.asPointer.value = pHolder; - pValue->item.asPointer.collect = pValue->item.asPointer.single = TRUE; - + hb_itemMove( &( ( PHB_ENUMREF ) pValue->item.asExtRef.value )->oldvalue, + pEnum ); /* set the iterator value */ pEnum->type = HB_IT_BYREF | HB_IT_ENUM; - pEnum->item.asEnum.basePtr = pItem; + pEnum->item.asEnum.basePtr = pBase; pEnum->item.asEnum.valuePtr = NULL; - if( HB_IS_BYREF( pItem ) ) - pItem = hb_itemUnRef( pItem ); + if( HB_IS_BYREF( pBase ) ) + pBase = hb_itemUnRef( pBase ); - if( HB_IS_OBJECT( pItem ) && hb_objHasOperator( pItem, HB_OO_OP_ENUMSTART ) ) + if( HB_IS_OBJECT( pBase ) && hb_objHasOperator( pBase, HB_OO_OP_ENUMSTART ) ) { pEnum->item.asEnum.offset = 0; pEnum->item.asEnum.valuePtr = hb_itemNew( NULL ); hb_vmPushNil(); hb_vmPushLogical( nDescend == 0 ); hb_objOperatorCall( HB_OO_OP_ENUMSTART, hb_stackItemFromTop( -2 ), - pItem, pEnumRef, hb_stackItemFromTop( -1 ) ); + pBase, pEnumRef, hb_stackItemFromTop( -1 ) ); hb_stackPop(); if( hb_vmRequestQuery() != 0 || ! hb_vmPopLogical() ) { fStart = FALSE; break; } - else if( hb_objHasOperator( pItem, HB_OO_OP_ENUMSKIP ) ) + else if( hb_objHasOperator( pBase, HB_OO_OP_ENUMSKIP ) ) continue; hb_itemRelease( pEnum->item.asEnum.valuePtr ); pEnum->item.asEnum.valuePtr = NULL; } - if( HB_IS_ARRAY( pItem ) ) + if( HB_IS_ARRAY( pBase ) ) { /* the index into an array */ pEnum->item.asEnum.offset = ( nDescend > 0 ) ? 1 : - pItem->item.asArray.value->ulLen; - if( pItem->item.asArray.value->ulLen == 0 ) + pBase->item.asArray.value->ulLen; + if( pBase->item.asArray.value->ulLen == 0 ) fStart = FALSE; } - else if( HB_IS_HASH( pItem ) ) + else if( HB_IS_HASH( pBase ) ) { - ULONG ulLen = hb_hashLen( pItem ); + ULONG ulLen = hb_hashLen( pBase ); /* the index into a hash */ pEnum->item.asEnum.offset = ( nDescend > 0 ) ? 1 : ulLen; if( ulLen == 0 ) fStart = FALSE; } - else if( HB_IS_STRING( pItem ) ) + else if( HB_IS_STRING( pBase ) ) { /* storage item for single characters */ pEnum->item.asEnum.offset = ( nDescend > 0 ) ? 1 : - pItem->item.asString.length; - if( pItem->item.asString.length ) + pBase->item.asString.length; + if( pBase->item.asString.length ) pEnum->item.asEnum.valuePtr = - hb_itemPutCL( NULL, pItem->item.asString.value + + hb_itemPutCL( NULL, pBase->item.asString.value + pEnum->item.asEnum.offset - 1, 1 ); else fStart = FALSE; } else { - hb_errRT_BASE( EG_ARG, 1068, NULL, hb_langDGetErrorDesc( EG_ARRACCESS ), 1, pItem ); + hb_errRT_BASE( EG_ARG, 1068, NULL, hb_langDGetErrorDesc( EG_ARRACCESS ), 1, pBase ); return; } }