#if !defined(__NEW_OPERATOR_IPP__)
#define __NEW_OPERATOR_IPP__
#include "new-operator.hpp"
#include "MemoryMonitor.hpp"
#include "Top.hpp"
#include "Debug.hpp"
#include "defines.h"
#include "platform/Platform.hpp"
long magicStart = 0xa1efc0fe;
long magicEnd = 0xc001deaf;
long magicDeleted = 0xb100ded7;
static const size_t shift = sizeof magicStart;
static const size_t doubleShift = 2 * shift;
#if defined( USE_ALLOC_CHAIN )
static long *firstInAllocatedChain = ( long * ) NULL;
static long *lastInAllocatedChain = ( long * ) NULL;
void dumpAllocatedByNew();
#endif
INLINE void *operator new( size_t aSize )
{
#if defined( USE_ALLOC_CHAIN )
aSize += doubleShift;
#endif
const size_t rSize = ( ( aSize - 1 ) / shift + 1 );
char *arena;
Platform *platform;
platform = Platform::getInstanceNow();
if( platform != ( Platform * ) NIL )
{
arena = ( char * ) platform -> allocateMemory( ( rSize + 3 ) * shift );
}
else
{
arena = ( char * ) platform -> allocateMemoryBootstrap( ( rSize + 3 ) * shift );
}
#if defined( PROFILE_MEM_ALLOC )
MemoryMonitor::inc( aSize, arena + doubleShift );
#endif
if( arena == NIL )
{
MemoryMonitor::release();
Debug::getLogger() -> log("Failed to allocate %i bytes. "
"(Totally allocated: %lu.) Cleaning up",
aSize, MemoryMonitor::amount() );
}
( ( long * ) arena )[ 0 ] = ( long ) aSize;
( ( long * ) arena )[ 1 ] = magicStart;
( ( long * ) arena )[ rSize + 2 ] = magicEnd;
#if defined( USE_ALLOC_CHAIN )
( ( long * ) arena )[ 2 ] = ( long ) lastInAllocatedChain;
( ( long * ) arena )[ 3 ] = ( long ) NULL;
if( ( ( long * ) arena )[ 2 ] != ( long ) NULL )
{
( ( long * )( ( ( long * ) arena )[ 2 ] ) )[ 1 ] = ( long ) &( ( long * ) arena )[ 2 ];
}
if( firstInAllocatedChain == ( long * ) NULL )
{
firstInAllocatedChain = &( ( long * ) arena )[ 2 ];
}
lastInAllocatedChain = &( ( long * ) arena )[ 2 ];
return ( void * )( arena + doubleShift + doubleShift );
#endif
return ( void * )( arena + doubleShift );
}
INLINE boolean checkForDelete( const void *aPointer )
{
if( aPointer == null )
{
Platform::getInstance() -> rawErrorPrintf( "delete null" );
return false;
}
else
{
long *arena = ( long * ) aPointer;
if( arena[ -1 ] != magicStart )
{
if( arena[ -1 ] == magicDeleted )
{
Platform::getInstance() -> rawErrorPrintf
( "double delete at %lx", ( long unsigned int ) aPointer );
}
else
{
Platform::getInstance() ->
rawErrorPrintf( "wrong delete at %lx", ( long unsigned int ) aPointer );
}
return false;
}
else
{
size_t len = ( size_t ) arena[ -2 ];
size_t rLen = ( len - 1 ) / shift + 1;
if( arena[ rLen ] != magicEnd )
{
Platform::getInstance() ->
rawErrorPrintf( "corrupted heap at %lx",
( long unsigned int ) aPointer );
return false;
}
}
}
return true;
}
#if !defined(__SUNPRO_CC)
INLINE void operator delete( void *aPointer ) throw()
#else
INLINE void operator delete( void *aPointer )
#endif
{
long *arena = ( long * ) aPointer;
#if defined( USE_ALLOC_CHAIN )
arena -= 2;
if( arena[ 1 ] != ( long ) NULL )
{
( ( long * )arena[ 1 ] )[ 0 ] = arena[ 0 ];
}
else
{
lastInAllocatedChain = ( long * ) arena[ 0 ];
}
if( arena[ 0 ] != ( long ) NULL )
{
( ( long * )arena[ 0 ] )[ 1 ] = arena[ 1 ];
}
else
{
firstInAllocatedChain = ( long * ) arena[ 1 ];
}
aPointer = ( void * ) arena;
#endif
#if defined( CHECK_DELETES )
if( checkForDelete( aPointer ) )
{
#endif
Platform *platform;
#if defined( PROFILE_MEM_ALLOC )
MemoryMonitor::dec( ( size_t ) arena[ -2 ], arena );
#endif
arena[ -1 ] = magicDeleted;
platform = Platform::getInstanceNow();
if( platform != ( Platform * ) NIL )
{
platform -> deallocateMemory( arena - 2 );
}
else
{
platform -> deallocateMemoryBootstrap( arena - 2 );
}
#if defined( CHECK_DELETES )
}
#endif
}
#if defined( USE_ALLOC_CHAIN )
void dumpAllocatedByNew()
{
long *end;
long *point;
Index count;
end = lastInAllocatedChain;
point = firstInAllocatedChain;
for( count = 0 ; ( point != ( long * ) NULL ) && ( point != end ) ;
point = ( long * ) ( point[ 1 ] ), ++count )
{
Debug::getLogger() -> log( "Allocated: %lx", point );
}
Debug::getLogger() -> log( "*** Totally allocated: %li, in %li chunks",
MemoryMonitor::amount(), count );
}
#endif
#if defined(_INLINE)
#include "../src/Debug.ipp"
#endif
#if defined(_INLINE)
#include "../src/Top.ipp"
#endif
#endif