void hb_memvarGetRefer( PHB_ITEM pItem, PHB_SYMB pMemvarSymb ) { PHB_DYNS pDyn; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarGetRefer(%p, %p)", pItem, pMemvarSymb ) ); pDyn = ( PHB_DYNS ) pMemvarSymb->pDynSym; if( pDyn ) { PHB_ITEM pMemvar; pMemvar = hb_dynsymGetMemvar( pDyn ); HB_TRACE( HB_TR_INFO, ( "Memvar item (%p)(%s) referenced", pMemvar, pMemvarSymb->szName ) ); if( pMemvar ) { if( HB_IS_BYREF( pMemvar ) && ! HB_IS_ENUM( pMemvar ) ) hb_itemCopy( pItem, pMemvar ); else { /* value is already created */ pItem->type = HB_IT_BYREF | HB_IT_MEMVAR; pItem->item.asMemvar.value = pMemvar; hb_xRefInc( pMemvar ); } } else { /* Generate an error with retry possibility * (user created error handler can make this variable accessible) */ PHB_ITEM pError; pError = hb_errRT_New( ES_ERROR, NULL, EG_NOVAR, 1003, NULL, pMemvarSymb->szName, 0, EF_CANRETRY ); while( hb_errLaunch( pError ) == E_RETRY ) { pMemvar = hb_dynsymGetMemvar( pDyn ); if( pMemvar ) { if( HB_IS_BYREF( pMemvar ) && ! HB_IS_ENUM( pMemvar ) ) hb_itemCopy( pItem, pMemvar ); else { /* value is already created */ pItem->type = HB_IT_BYREF | HB_IT_MEMVAR; pItem->item.asMemvar.value = pMemvar; hb_xRefInc( pMemvar ); } break; } } hb_errRelease( pError ); } } else hb_errInternal( HB_EI_MVBADSYMBOL, NULL, pMemvarSymb->szName, NULL ); }
void hb_gcAttach( void * pBlock ) { PHB_GARBAGE pAlloc = HB_GC_PTR( pBlock ); if( pAlloc->locked ) { HB_GC_LOCK(); if( pAlloc->locked ) { if( --pAlloc->locked == 0 ) { pAlloc->used = s_uUsedFlag; hb_gcUnlink( &s_pLockedBlock, pAlloc ); hb_gcLink( &s_pCurrBlock, pAlloc ); HB_GC_AUTO_INC(); pAlloc = NULL; } } HB_GC_UNLOCK(); } if( pAlloc ) hb_xRefInc( pAlloc ); }
/* Creates the codeblock structure * * pBuffer -> the buffer with pcodes (without HB_P_PUSHBLOCK) * wLocals -> number of local variables referenced in a codeblock * pLocalPosTable -> a table with positions on eval stack for referenced variables * pSymbols -> a pointer to the module symbol table * * Note: pLocalPosTable cannot be used if uiLocals is ZERO */ PHB_CODEBLOCK hb_codeblockNew( const HB_BYTE * pBuffer, HB_USHORT uiLocals, const HB_BYTE * pLocalPosTable, PHB_SYMB pSymbols, HB_SIZE nLen ) { HB_STACK_TLS_PRELOAD PHB_CODEBLOCK pCBlock; PHB_ITEM pLocals, pBase; const HB_BYTE * pCode; HB_TRACE( HB_TR_DEBUG, ( "hb_codeblockNew(%p, %hu, %p, %p, %" HB_PFS "u)", pBuffer, uiLocals, pLocalPosTable, pSymbols, nLen ) ); /* Allocate memory for code block body and detach items hb_gcAllocRaw() * to be safe for automatic GC activation in hb_xgrab() without * calling hb_gcLock()/hb_gcUnlock(). [druzus] */ if( nLen ) { /* The codeblock pcode is stored in dynamically allocated memory that * can be deallocated after creation of a codeblock. We have to duplicate * the passed buffer */ pCode = ( const HB_BYTE * ) memcpy( hb_xgrab( nLen ), pBuffer, nLen ); } else { /* The codeblock pcode is stored in static segment. * The only allowed operation on a codeblock is evaluating it then * there is no need to duplicate its pcode - just store the pointer to it */ pCode = pBuffer; } if( uiLocals ) { /* NOTE: if a codeblock will be created by macro compiler then * uiLocal have to be ZERO * uiLocal will be also ZERO if it is a nested codeblock */ HB_USHORT ui = 1; PHB_ITEM pLocal; /* Create a table that will store the values of local variables * accessed in a codeblock * The element 0 is unused * NOTE: This table can be shared by codeblocks created during * evaluation of this codeblock */ pLocals = ( PHB_ITEM ) hb_xgrab( ( uiLocals + 1 ) * sizeof( HB_ITEM ) ); pLocals[ 0 ].type = HB_IT_NIL; do { /* Swap the current value of local variable with the reference to this * value. */ int iLocal = HB_PCODE_MKUSHORT( pLocalPosTable ); pLocal = hb_stackLocalVariable( iLocal ); pLocalPosTable += 2; pLocal = hb_memvarDetachLocal( pLocal ); hb_itemRawCpy( pLocals + ui, pLocal ); /* Increment the reference counter so this value will not be * released if other codeblock will be deleted */ hb_memvarValueIncRef( pLocal->item.asMemvar.value ); } while( ++ui <= uiLocals ); } else { /* Check if this codeblock is created during evaluation of another * codeblock - all inner codeblocks use the local variables table * created during creation of the outermost codeblock */ PHB_ITEM pLocal; pLocal = hb_stackSelfItem(); if( HB_IS_BLOCK( pLocal ) ) { PHB_CODEBLOCK pOwner = pLocal->item.asBlock.value; uiLocals = pOwner->uiLocals; pLocals = pOwner->pLocals; if( pLocals ) hb_xRefInc( pLocals ); } else pLocals = NULL; } pBase = hb_stackBaseItem(); pCBlock = ( PHB_CODEBLOCK ) hb_gcAllocRaw( sizeof( HB_CODEBLOCK ), &s_gcCodeblockFuncs ); pCBlock->pCode = pCode; pCBlock->dynBuffer = nLen != 0; pCBlock->pDefSymb = pBase->item.asSymbol.stackstate->uiClass ? hb_clsMethodSym( pBase ) : pBase->item.asSymbol.value; pCBlock->pSymbols = pSymbols; pCBlock->pStatics = hb_stackGetStaticsBase(); pCBlock->uiLocals = uiLocals; pCBlock->pLocals = pLocals; HB_TRACE( HB_TR_INFO, ( "codeblock created %p", pCBlock ) ); return pCBlock; }
/* * 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 * outside the scope (either by using RELEASE, CLEAR ALL, CLEAR MEMORY or by * an exit from the function/procedure) * */ static void hb_memvarAddPrivate( PHB_DYNS pDynSym, PHB_ITEM pValue ) { HB_STACK_TLS_PRELOAD PHB_PRIVATE_STACK pPrivateStack; PHB_ITEM pMemvar; HB_TRACE( HB_TR_DEBUG, ( "hb_memvarAddPrivate(%p,%p)", pDynSym, pValue ) ); pPrivateStack = hb_stackGetPrivateStack(); pMemvar = hb_dynsymGetMemvar( pDynSym ); /* If the variable with the same name exists already * and it's PRIVATE variable declared in this function then * do not push new memvar on PRIVATEs stack */ if( pMemvar ) { HB_SIZE nCount = pPrivateStack->count; while( nCount > pPrivateStack->base ) { if( pDynSym == pPrivateStack->stack[ nCount - 1 ].pDynSym ) break; --nCount; } if( nCount <= pPrivateStack->base ) pMemvar = NULL; } if( ! pMemvar ) { /* Allocate the value from the end of table */ if( pPrivateStack->count == pPrivateStack->size ) { /* No more free values in the table - expand the table */ if( pPrivateStack->size == 0 ) { pPrivateStack->stack = ( PHB_PRIVATE_ITEM ) hb_xgrab( sizeof( HB_PRIVATE_ITEM ) * TABLE_INITHB_VALUE ); pPrivateStack->size = TABLE_INITHB_VALUE; pPrivateStack->count = pPrivateStack->base = 0; } else { pPrivateStack->size += TABLE_EXPANDHB_VALUE; pPrivateStack->stack = ( PHB_PRIVATE_ITEM ) hb_xrealloc( pPrivateStack->stack, sizeof( HB_PRIVATE_ITEM ) * pPrivateStack->size ); } } pPrivateStack->stack[ pPrivateStack->count ].pDynSym = pDynSym; pPrivateStack->stack[ pPrivateStack->count++ ].pPrevMemvar = hb_dynsymGetMemvar( pDynSym ); if( pValue && HB_IS_MEMVAR( pValue ) ) { pMemvar = pValue->item.asMemvar.value; hb_xRefInc( pMemvar ); pValue = NULL; } else pMemvar = hb_memvarValueNew(); hb_dynsymSetMemvar( pDynSym, pMemvar ); } if( pValue ) { hb_itemCopy( pMemvar, pValue ); /* Remove MEMOFLAG if exists (assignment from field). */ pMemvar->type &= ~HB_IT_MEMOFLAG; } }
void hb_memvarValueIncRef( PHB_ITEM pMemvar ) { HB_TRACE( HB_TR_DEBUG, ( "hb_memvarValueIncRef(%p)", pMemvar ) ); hb_xRefInc( pMemvar ); }
void hb_gcRefInc( void * pBlock ) { hb_xRefInc( HB_GC_PTR( pBlock ) ); }