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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user