Ejemplo n.º 1
0
/*
 * Detach local variable (swap current value with a memvar handle)
 */
PHB_ITEM hb_memvarDetachLocal( PHB_ITEM pLocal )
{
   HB_TRACE( HB_TR_DEBUG, ( "hb_memvarDetachLocal(%p)", pLocal ) );

   if( HB_IS_BYREF( pLocal ) )
   {
      do
      {
         if( HB_IS_MEMVAR( pLocal ) || HB_IS_EXTREF( pLocal ) )
            break;
         else if( HB_IS_ENUM( pLocal ) )
         {
            if( ! pLocal->item.asEnum.valuePtr )
            {
               PHB_ITEM pBase = HB_IS_BYREF( pLocal->item.asEnum.basePtr ) ?
                               hb_itemUnRef( pLocal->item.asEnum.basePtr ) :
                                             pLocal->item.asEnum.basePtr;
               if( HB_IS_ARRAY( pBase ) )
               {
                  PHB_ITEM pItem = hb_itemNew( NULL );
                  hb_arrayGetItemRef( pBase, pLocal->item.asEnum.offset, pItem );
                  pLocal->item.asEnum.valuePtr = pItem;
                  pLocal = pItem;
                  break;
               }
            }
         }
         else if( pLocal->item.asRefer.value >= 0 &&
                  pLocal->item.asRefer.offset == 0 )
            break;
         pLocal = hb_itemUnRefOnce( pLocal );
      }
      while( HB_IS_BYREF( pLocal ) );
   }

   /* Change the value only if this variable is not referenced
    * by another codeblock yet.
    * 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 ) )
   {
      PHB_ITEM pMemvar = hb_memvarValueNew();

      hb_itemRawCpy( pMemvar, pLocal );
      pMemvar->type &= ~HB_IT_DEFAULT;

      pLocal->type = HB_IT_BYREF | HB_IT_MEMVAR;
      pLocal->item.asMemvar.value = pMemvar;
   }

   return pLocal;
}
Ejemplo n.º 2
0
/*
 * 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;
   }
}
Ejemplo n.º 3
0
/* Mark a passed item as used so it will be not released by the GC
 */
void hb_gcItemRef( PHB_ITEM pItem )
{
   while( HB_IS_BYREF( pItem ) )
   {
      if( HB_IS_ENUM( pItem ) )
         return;
      else if( HB_IS_EXTREF( pItem ) )
      {
         pItem->item.asExtRef.func->mark( pItem->item.asExtRef.value );
         return;
      }
      else if( ! HB_IS_MEMVAR( pItem ) &&
               pItem->item.asRefer.offset == 0 &&
               pItem->item.asRefer.value >= 0 )
      {
         /* array item reference */
         PHB_GARBAGE pAlloc = HB_GC_PTR( pItem->item.asRefer.BasePtr.array );
         if( ( pAlloc->used & ~HB_GC_DELETE ) == s_uUsedFlag )
         {
            /* mark this array as used */
            pAlloc->used ^= HB_GC_USED_FLAG;
            /* mark also all array elements */
            pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) );
         }
         return;
      }
      pItem = hb_itemUnRefOnce( pItem );
   }

   if( HB_IS_ARRAY( pItem ) )
   {
      PHB_GARBAGE pAlloc = HB_GC_PTR( pItem->item.asArray.value );

      /* Check this array only if it was not checked yet */
      if( ( pAlloc->used & ~HB_GC_DELETE ) == s_uUsedFlag )
      {
         /* mark this array as used so it will be no re-checked from
          * other references
          */
         pAlloc->used ^= HB_GC_USED_FLAG;
         /* mark also all array elements */
         pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) );
      }
   }
   else if( HB_IS_HASH( pItem ) )
   {
      PHB_GARBAGE pAlloc = HB_GC_PTR( pItem->item.asHash.value );

      /* Check this hash table only if it was not checked yet */
      if( ( pAlloc->used & ~HB_GC_DELETE ) == s_uUsedFlag )
      {
         /* mark this hash table as used */
         pAlloc->used ^= HB_GC_USED_FLAG;
         /* mark also all hash elements */
         pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) );
      }
   }
   else if( HB_IS_BLOCK( pItem ) )
   {
      PHB_GARBAGE pAlloc = HB_GC_PTR( pItem->item.asBlock.value );

      if( ( pAlloc->used & ~HB_GC_DELETE ) == s_uUsedFlag )
      {
         /* mark this codeblock as used */
         pAlloc->used ^= HB_GC_USED_FLAG;
         /* mark as used all detached variables in a codeblock */
         pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) );
      }
   }
   else if( HB_IS_POINTER( pItem ) )
   {
      if( pItem->item.asPointer.collect )
      {
         PHB_GARBAGE pAlloc = HB_GC_PTR( pItem->item.asPointer.value );

         if( ( pAlloc->used & ~HB_GC_DELETE ) == s_uUsedFlag )
         {
            /* mark this memory block as used */
            pAlloc->used ^= HB_GC_USED_FLAG;
            /* mark also all internal user blocks attached to this block */
            pAlloc->pFuncs->mark( HB_BLOCK_PTR( pAlloc ) );
         }
      }
   }
   /* all other data types don't need the GC */
}
Ejemplo n.º 4
0
/* Mark a passed item as used so it will be not released by the GC
*/
void hb_gcItemRef( HB_ITEM_PTR pItem )
{
   HB_THREAD_STUB

   ULONG ulSize;
   HB_ITEM FakedItem;
   PHB_ITEM pKey;
   PHB_ITEM pValue;
   HB_CODEBLOCK_PTR pCBlock;
   USHORT ui;

   #ifdef SIMULATE_ITEMREF_RECURSION
      PITEMREF_RESUMEINFO pResumeInfo = (PITEMREF_RESUMEINFO) hb_xgrab( sizeof( ITEMREF_RESUMEINFO ) );
      int iResumeCounter = 0;
   #endif

   FakedItem.type = HB_IT_ARRAY;

   ItemRef_Top:

   while( HB_IS_BYREF( pItem ) )
   {
      if( HB_IS_EXTREF( pItem ) )
      {
         pItem->item.asExtRef.func->mark( pItem->item.asExtRef.value );

         RETURN_OR_RESUME_ITEMREF();
      }

      if( HB_IS_MEMVAR( pItem ) == FALSE )
      {
         if( pItem->item.asRefer.offset == 0 )
         {
            FakedItem.item.asArray.value = pItem->item.asRefer.BasePtr.pBaseArray;

            //hb_gcItemRef( &FakedItem );
            NESTED_ITEMREF( &FakedItem, 1 );
            ItemRef_ResumePoint_1:

            // return;
            RETURN_OR_RESUME_ITEMREF();
         }
      }
      else
      {
         if( HB_VM_STACK.pPos == HB_VM_STACK.pItems )
         {
            //return;
            RETURN_OR_RESUME_ITEMREF();
         }
      }

      pItem = hb_itemUnRefOnce( pItem );
   }

   if( HB_IS_ARRAY( pItem ) )
   {
      HB_GARBAGE_PTR pAlloc = ( HB_GARBAGE_PTR ) pItem->item.asArray.value;

      //printf( "Array %p\n", pItem->item.asArray.value );
      --pAlloc;

      /* Check this array only if it was not checked yet */
      if( pAlloc->used == s_uUsedFlag )
      {
         ulSize = pItem->item.asArray.value->ulLen;
         /* mark this block as used so it will be no re-checked from
          * other references
          */
         pAlloc->used ^= HB_GC_USED_FLAG;

         /* mark also all array elements */
         pItem = pItem->item.asArray.value->pItems;
         //printf( "Items %p\n", pItem );

         while( ulSize )
         {
            //printf( "Item %p\n", pItem );

            //hb_gcItemRef( pItem );
            NESTED_ITEMREF( pItem, 2 );
            ItemRef_ResumePoint_2:

            ++pItem;
            --ulSize;
         }
      }
   }
   else if( HB_IS_HASH( pItem ) )
   {
      HB_GARBAGE_PTR pAlloc = ( HB_GARBAGE_PTR ) pItem->item.asHash.value;
      --pAlloc;

      /* Check this hash only if it was not checked yet */
      if( pAlloc->used == s_uUsedFlag )
      {
         ulSize = pItem->item.asHash.value->ulLen;
         pKey = pItem->item.asHash.value->pKeys;
         pValue = pItem->item.asHash.value->pValues;

         /* mark this block as used so it will be no re-checked from
          * other references
          */
         pAlloc->used ^= HB_GC_USED_FLAG;

         /* mark also all hash elements */
         while( ulSize )
         {
            //printf( "Kry %p Value: %p\n", pKey, pValue );

            //hb_gcItemRef( pKey );
            NESTED_ITEMREF( pKey, 3 );
            ItemRef_ResumePoint_3:

            //hb_gcItemRef( pValue );
            NESTED_ITEMREF( pValue, 4 );
            ItemRef_ResumePoint_4:

            ++pKey;
            ++pValue;
            --ulSize;
         }
      }
   }
   else if( HB_IS_BLOCK( pItem ) )
   {
      HB_GARBAGE_PTR pAlloc = ( HB_GARBAGE_PTR ) pItem->item.asBlock.value;
      --pAlloc;

      /* Check this block only if it was not checked yet */
      if( pAlloc->used == s_uUsedFlag )
      {
         pCBlock = pItem->item.asBlock.value;
         ui = 1;

         pAlloc->used ^= HB_GC_USED_FLAG;  /* mark this codeblock as used */

         /* mark as used all detached variables in a codeblock */
         while( ui <= pCBlock->uiLocals )
         {
            //hb_gcItemRef( &pCBlock->pLocals[ ui ] );
            NESTED_ITEMREF( &pCBlock->pLocals[ ui ] , 5 );
           ItemRef_ResumePoint_5:

            ++ui;
         }
      }
   }
   else if( HB_IS_POINTER( pItem ) )
   {
      /* check if this memory was allocated by a hb_gcAlloc() */
      if ( pItem->item.asPointer.collect )
      {
         HB_GARBAGE_PTR pAlloc = ( HB_GARBAGE_PTR ) pItem->item.asPointer.value;
         --pAlloc;

         /* Check this memory only if it was not checked yet */
         if( pAlloc->used == s_uUsedFlag )
         {
            /* mark this memory as used so it will be no re-checked from
             * other references
             */
            pAlloc->used ^= HB_GC_USED_FLAG;
         }
      }
   }

   /* all other data types don't need the GC */

   RETURN_OR_RESUME_ITEMREF();
}