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%
This commit is contained in:
Przemyslaw Czerpak
2007-10-06 10:45:13 +00:00
parent 0ce94714e6
commit 053e67ddeb
5 changed files with 132 additions and 81 deletions

View File

@@ -8,6 +8,17 @@
2002-12-01 13:30 UTC+0100 Foo Bar <foo.bar@foobar.org>
*/
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

View File

@@ -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

View File

@@ -183,7 +183,8 @@
#elif defined( HB_WIN32_IO )
#include <windows.h>
#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

View File

@@ -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 );

View File

@@ -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;
}
}