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
/* 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.º 3
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();
}