diff -r dd21522fd290 -r 7c90e6132015 webengine/osswebengine/MemoryManager/Src/MemoryPool.cpp --- a/webengine/osswebengine/MemoryManager/Src/MemoryPool.cpp Mon Mar 30 12:54:55 2009 +0300 +++ b/webengine/osswebengine/MemoryManager/Src/MemoryPool.cpp Fri May 08 08:25:06 2009 +0300 @@ -25,7 +25,9 @@ #include "MemoryPool.h" #include "StopScheduler.h" #include "fast_malloc.h" +#include "SymbianDlHeap.h" #include +#include // CONSTANTS @@ -390,11 +392,29 @@ // avoid small checkings if( aTotalSize < 1024 ) return ETrue; + // first check the application heap's max free block + TInt maxFreeBlock = 0; + User::Allocator().Available(maxFreeBlock); + if (aTotalSize < maxFreeBlock) + return ETrue; + + // free memory in Hal TMemoryInfoV1Buf info; UserHal::MemoryInfo( info ); TInt sizeNeeded = aTotalSize + iRescueBufferSize; - if( sizeNeeded > info().iFreeRamInBytes ) + + // check if there is enough space for the heap to grow + bool needSysCheck = EFalse; + if (info().iFreeRamInBytes > sizeNeeded) { + RHeap& heap = User::Heap(); + if (heap.MaxLength() - heap.Size() > sizeNeeded) + return ETrue; + + needSysCheck = ETrue; + } + + if(sizeNeeded > info().iFreeRamInBytes || needSysCheck) { CollectMemory(sizeNeeded); @@ -425,4 +445,215 @@ // do nothing here. } +#ifdef __NEW_ALLOCATOR__ +//----------------------------------------------------------------------------- +// CNewSymbianHeapPool::FreeMemory +//----------------------------------------------------------------------------- +TUint CNewSymbianHeapPool::FreeMemory(TFreeMem& /*aFree*/ ) + { + // TODO: implement free_memory + return KMaxTUint; +// return free_memory( aFree.iPool, aFree.iHeap, aFree.iHal ); + } + +//----------------------------------------------------------------------------- +// CNewSymbianHeapPool::DoAlloc +//----------------------------------------------------------------------------- +TAny* CNewSymbianHeapPool::DoAlloc( TUint aSize ) + { + return iAlloc->Alloc( aSize ); + } + +//----------------------------------------------------------------------------- +// CNewSymbianHeapPool::ReAllocate +//----------------------------------------------------------------------------- +TAny* CNewSymbianHeapPool::ReAllocate( TAny* aPtr, TUint aSize ) + { + // reset the status for next allocation + iMemStatus &= ~ERescueOOM; + + TAny* p = iAlloc->ReAlloc( aPtr, aSize ); + + // check memory manager status + if( !p || iMemStatus & ERescueOOM ) + { + if( !iIsCollecting ) + { + CollectMemory(); + } + + if( !p ) + p = iAlloc->ReAlloc( aPtr, aSize ); + + NotifyAndStop(); + } + + return p; + } + +//----------------------------------------------------------------------------- +// CNewSymbianHeapPool::PreCheck +//----------------------------------------------------------------------------- +TBool CNewSymbianHeapPool::PreCheck(TUint aTotalSize, TUint aMaxBufSize, + const TDesC8& /*aCheckerName*/) + { + /* aTotalSize - total amount desired + * aMaxBufSize - largest single allocation desired + */ + + // avoid small checkings + if (aTotalSize < 1024) + return ETrue; + + /* + * Browser fast_malloc implementation merges together total/max allocation requests and says YES if system free memory is >6MB + */ + // mirror existing size calculation + aTotalSize = aTotalSize > (aMaxBufSize * 2) ? aTotalSize + : (aMaxBufSize * 2); + + // if we have more than 6 MB of free mem, we + // should skip malloc_info call. + // free memory in Hal + TInt systemFreeMemory = 0; + if( HAL::Get(HALData::EMemoryRAMFree, systemFreeMemory) == KErrNone ) + { + const TUint checkThreshold = 6*1024*1024; + if(systemFreeMemory> checkThreshold && systemFreeMemory> aTotalSize) + return ETrue; + } + + /* For a proper implementation of RHeap, the stats available are: + * AllocSize Total number of allocated bytes + * Size Total number of bytes held from system + * Available Max block size and amount of bytes held but not allocated + */ + /* We don't have those bits of the heap implemented yet + */ + TInt freeSpace = 0; // be conservative, use 0 intead of 64<<10; + TInt req = freeSpace + systemFreeMemory - aTotalSize; + + if(req > 0) + return ETrue; + + // First, ask system for memory from other applications. + ROomMonitorSession oomMs; + if (oomMs.Connect() == KErrNone) + { + oomMs.RequestFreeMemory(aTotalSize); + oomMs.Close(); + } + + // We haven't altered our heap yet, so ask the system how much is free now... + HAL::Get(HALData::EMemoryRAMFree, systemFreeMemory); + req = freeSpace + systemFreeMemory - aTotalSize; + + if(req > 0) + return ETrue; + + // We haven't got the required amount free yet, try the browser heap. + CollectMemory(aTotalSize); + // ask the system how much is free now... + HAL::Get(HALData::EMemoryRAMFree, systemFreeMemory); + req = freeSpace + systemFreeMemory - aTotalSize; + + // if we still haven't got enough RAM, we should stop the browser from going any further just yet. + if (req < 0) + { + iMemStatus |= ECheckOOM; + NotifyAndStop(); + return EFalse; + } + + return ETrue; + } + +//----------------------------------------------------------------------------- +// CNewSymbianHeapPool::PostCheck +//----------------------------------------------------------------------------- +TUint CNewSymbianHeapPool::PostCheck() + { + return iMemStatus; + } + +//----------------------------------------------------------------------------- +// CNewSymbianHeapPool::Free +//----------------------------------------------------------------------------- +void CNewSymbianHeapPool::Free( TAny* aPtr ) + { + return iAlloc->Free( aPtr ); + } + +//----------------------------------------------------------------------------- +// CNewSymbianHeapPool::MemorySize +//----------------------------------------------------------------------------- +TUint CNewSymbianHeapPool::MemorySize( TAny* aPtr ) + { + return iAlloc->AllocLen( aPtr ); + } + +//----------------------------------------------------------------------------- +// CNewSymbianHeapPool::SetRescueBufferSize +//----------------------------------------------------------------------------- +void CNewSymbianHeapPool::SetRescueBufferSize( TInt /*aSize*/ ) + { + //fast_set_rescue_buffer_size( aSize ); + } + +//----------------------------------------------------------------------------- +// CNewSymbianHeapPool::RestoreRescueBuffer +//----------------------------------------------------------------------------- +void CNewSymbianHeapPool::RestoreRescueBuffer() + { + //alloc_rescue_buffer(); + } + +CNewSymbianHeapPool::CNewSymbianHeapPool() : CMemoryPool() + { + } + +CNewSymbianHeapPool::~CNewSymbianHeapPool() + { +// iAlloc->Close(); // TODO: Need to clean up here, but it's not implemented in the allocator yet. + // Not fatal anyway because all the handles are process local and we should only + // be deleting this object when we're closing the allocator - which we never do + // except at process end. + } + +const TInt KMaxHeapSize = 0x2000000; //32MB +const TInt KHeapGrowSize = 0x10000; //64KB + +TBool CNewSymbianHeapPool::Create() + { + // need to know system page size + TInt page_size; + UserHal::PageSizeInBytes(page_size); + + // Create the thread's heap chunk. + // + // The chunk needs reserve enough address space for twice the maximum allocation + // The heap object is instantiated exactly half way up the chunk, and initially is provided just 1 page of memory + // This memory can be committed as part of the call to creat the chunk + // + TInt maxChunkSize = 2 * KMaxHeapSize; + TInt offset = KMaxHeapSize; + TInt minLength = page_size; + RChunk c; + TInt r = c.CreateDisconnectedLocal(offset, offset+minLength, maxChunkSize, EOwnerProcess); + if (r!=KErrNone) + return EFalse; + + iAlloc = new (c.Base() + offset) RSymbianDLHeap(c.Handle(), offset, minLength, KMaxHeapSize, KHeapGrowSize, 8, EFalse /* not single threaded! */); + iAlloc->iHandles = &iAlloc->iChunkHandle; + iAlloc->iHandleCount = 2; + // chunk handle now 'owned' by iAlloc + r = iAlloc->iLock.CreateLocal(EOwnerProcess); + + if(r != KErrNone) + return EFalse; + + return CMemoryPool::Create(); + } + +#endif // END OF FILE