@@ -1,118 +1,51 @@
/**
* Contains the external GC interface.
*
* Copyright: Copyright Digital Mars 2005 - 2013 .
* Copyright: Copyright Digital Mars 2005 - 2016 .
* License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
* Authors: Walter Bright, Sean Kelly
*/
/* Copyright Digital Mars 2005 - 2013 .
/* Copyright Digital Mars 2005 - 2016 .
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
module gc.proxy ;
import gc.gc;
import gc.impl.conservative.gc;
import gc.impl.manual.gc;
import gc.config;
import gc.stats;
import core.stdc.stdlib ;
import gc.gcinterface;
private
{
__gshared GC _gc;
static import core.memory ;
alias BlkInfo = core.memory.GC.BlkInfo ;
extern (C ) void thread_init();
extern (C ) void thread_term();
struct Proxy
{
extern (C )
{
void function () gc_enable;
void function () gc_disable;
nothrow :
void function () gc_collect;
void function () gc_minimize;
uint function (void * ) gc_getAttr;
uint function (void * , uint ) gc_setAttr;
uint function (void * , uint ) gc_clrAttr;
void * function (size_t , uint , const TypeInfo ) gc_malloc;
BlkInfo function (size_t , uint , const TypeInfo ) gc_qalloc;
void * function (size_t , uint , const TypeInfo ) gc_calloc;
void * function (void * , size_t , uint ba, const TypeInfo ) gc_realloc;
size_t function (void * , size_t , size_t , const TypeInfo ) gc_extend;
size_t function (size_t ) gc_reserve;
void function (void * ) gc_free;
void * function (void * ) gc_addrOf;
size_t function (void * ) gc_sizeOf;
BlkInfo function (void * ) gc_query;
void function (void * ) gc_addRoot;
void function (void * , size_t , const TypeInfo ti) gc_addRange;
void function (void * ) gc_removeRoot;
void function (void * ) gc_removeRange;
void function (in void []) gc_runFinalizers;
bool function () gc_inFinalizer;
}
}
__gshared Proxy pthis;
__gshared Proxy* proxy;
void initProxy ()
{
pthis.gc_enable = &gc_enable;
pthis.gc_disable = &gc_disable;
pthis.gc_collect = &gc_collect;
pthis.gc_minimize = &gc_minimize;
pthis.gc_getAttr = &gc_getAttr;
pthis.gc_setAttr = &gc_setAttr;
pthis.gc_clrAttr = &gc_clrAttr;
pthis.gc_malloc = &gc_malloc;
pthis.gc_qalloc = &gc_qalloc;
pthis.gc_calloc = &gc_calloc;
pthis.gc_realloc = &gc_realloc;
pthis.gc_extend = &gc_extend;
pthis.gc_reserve = &gc_reserve;
pthis.gc_free = &gc_free;
pthis.gc_addrOf = &gc_addrOf;
pthis.gc_sizeOf = &gc_sizeOf;
pthis.gc_query = &gc_query;
pthis.gc_addRoot = &gc_addRoot;
pthis.gc_addRange = &gc_addRange;
__gshared GC instance;
__gshared GC proxiedGC; // used to iterate roots of Windows DLLs
pthis.gc_removeRoot = &gc_removeRoot;
pthis.gc_removeRange = &gc_removeRange;
pthis.gc_runFinalizers = &gc_runFinalizers;
pthis.gc_inFinalizer = &gc_inFinalizer;
}
}
extern (C )
{
void gc_init ()
{
_gc.initialize();
config.initialize();
ManualGC.initialize(instance);
ConservativeGC.initialize(instance);
// NOTE: The GC must initialize the thread library
// before its first collection.
thread_init();
initProxy();
}
void gc_term ()
Expand All
@@ -126,229 +59,175 @@ extern (C)
//
// NOTE: Due to popular demand, this has been re-enabled. It still has
// the problems mentioned above though, so I guess we'll see.
_gc.fullCollectNoStack(); // not really a 'collect all' -- still scans
// static data area, roots, and ranges.
instance.collectNoStack(); // not really a 'collect all' -- still scans
// static data area, roots, and ranges.
thread_term();
_gc.Dtor();
ManualGC.finalize(instance);
ConservativeGC.finalize(instance);
}
void gc_enable ()
{
if ( proxy is null )
return _gc.enable();
return proxy.gc_enable();
instance.enable();
}
void gc_disable ()
{
if ( proxy is null )
return _gc.disable();
return proxy.gc_disable();
instance.disable();
}
void gc_collect () nothrow
{
if ( proxy is null )
{
_gc.fullCollect();
return ;
}
return proxy.gc_collect();
instance.collect();
}
void gc_minimize () nothrow
{
if ( proxy is null )
return _gc.minimize();
return proxy.gc_minimize();
instance.minimize();
}
uint gc_getAttr ( void * p ) nothrow
{
if ( proxy is null )
return _gc.getAttr( p );
return proxy.gc_getAttr( p );
return instance.getAttr(p);
}
uint gc_setAttr ( void * p, uint a ) nothrow
{
if ( proxy is null )
return _gc.setAttr( p, a );
return proxy.gc_setAttr( p, a );
return instance.setAttr(p, a);
}
uint gc_clrAttr ( void * p, uint a ) nothrow
{
if ( proxy is null )
return _gc.clrAttr( p, a );
return proxy.gc_clrAttr( p, a );
return instance.clrAttr(p, a);
}
void * gc_malloc ( size_t sz, uint ba = 0 , const TypeInfo ti = null ) nothrow
{
if ( proxy is null )
return _gc.malloc( sz, ba, null , ti );
return proxy.gc_malloc( sz, ba, ti );
return instance.malloc(sz, ba, ti);
}
BlkInfo gc_qalloc ( size_t sz, uint ba = 0 , const TypeInfo ti = null ) nothrow
{
if ( proxy is null )
{
BlkInfo retval;
retval.base = _gc.malloc( sz, ba, &retval.size, ti );
retval.attr = ba;
return retval;
}
return proxy.gc_qalloc( sz, ba, ti );
return instance.qalloc( sz, ba, ti );
}
void * gc_calloc ( size_t sz, uint ba = 0 , const TypeInfo ti = null ) nothrow
{
if ( proxy is null )
return _gc.calloc( sz, ba, null , ti );
return proxy.gc_calloc( sz, ba, ti );
return instance.calloc( sz, ba, ti );
}
void * gc_realloc ( void * p, size_t sz, uint ba = 0 , const TypeInfo ti = null ) nothrow
{
if ( proxy is null )
return _gc.realloc( p, sz, ba, null , ti );
return proxy.gc_realloc( p, sz, ba, ti );
return instance.realloc( p, sz, ba, ti );
}
size_t gc_extend ( void * p, size_t mx, size_t sz, const TypeInfo ti = null ) nothrow
{
if ( proxy is null )
return _gc.extend( p, mx, sz, ti );
return proxy.gc_extend( p, mx, sz,ti );
return instance.extend( p, mx, sz,ti );
}
size_t gc_reserve ( size_t sz ) nothrow
{
if ( proxy is null )
return _gc.reserve ( sz );
return proxy.gc_reserve( sz );
return instance.reserve ( sz );
}
void gc_free ( void * p ) nothrow
{
if ( proxy is null )
return _gc.free( p );
return proxy.gc_free( p );
return instance.free( p );
}
void * gc_addrOf ( void * p ) nothrow
{
if ( proxy is null )
return _gc.addrOf( p );
return proxy.gc_addrOf( p );
return instance.addrOf( p );
}
size_t gc_sizeOf ( void * p ) nothrow
{
if ( proxy is null )
return _gc.sizeOf( p );
return proxy.gc_sizeOf( p );
return instance.sizeOf( p );
}
BlkInfo gc_query ( void * p ) nothrow
{
if ( proxy is null )
return _gc.query( p );
return proxy.gc_query( p );
return instance.query( p );
}
// NOTE: This routine is experimental. The stats or function name may change
// before it is made officially available.
GCStats gc_stats () nothrow
{
if ( proxy is null )
{
GCStats stats = void ;
_gc.getStats( stats );
return stats;
}
// TODO: Add proxy support for this once the layout of GCStats is
// finalized.
// return proxy.gc_stats();
return GCStats .init;
return instance.stats();
}
void gc_addRoot ( void * p ) nothrow
{
if ( proxy is null )
return _gc.addRoot( p );
return proxy.gc_addRoot( p );
return instance.addRoot( p );
}
void gc_addRange ( void * p, size_t sz, const TypeInfo ti = null ) nothrow
{
if ( proxy is null )
return _gc.addRange( p, sz, ti );
return proxy.gc_addRange( p, sz, ti );
return instance.addRange( p, sz, ti );
}
void gc_removeRoot ( void * p ) nothrow
{
if ( proxy is null )
return _gc.removeRoot( p );
return proxy.gc_removeRoot( p );
return instance.removeRoot( p );
}
void gc_removeRange ( void * p ) nothrow
{
if ( proxy is null )
return _gc.removeRange( p );
return proxy.gc_removeRange( p );
return instance.removeRange( p );
}
void gc_runFinalizers ( in void [] segment ) nothrow
{
if ( proxy is null )
return _gc.runFinalizers( segment );
return proxy.gc_runFinalizers( segment );
return instance.runFinalizers( segment );
}
bool gc_inFinalizer () nothrow
{
if ( proxy is null )
return _gc.inFinalizer;
return proxy.gc_inFinalizer();
return instance.inFinalizer();
}
Proxy * gc_getProxy () nothrow
GC gc_getProxy () nothrow
{
return &pthis ;
return instance ;
}
export
{
void gc_setProxy ( Proxy * p )
void gc_setProxy ( GC proxy )
{
if ( proxy ! is null )
foreach (root; instance.rootIter)
{
proxy.addRoot(root);
}
foreach (range; instance.rangeIter)
{
// TODO: Decide if this is an error condition.
proxy.addRange(range.pbot, range.ptop - range.pbot, range.ti);
}
proxy = p;
foreach (r; _gc.rootIter)
proxy.gc_addRoot( r );
foreach (r; _gc.rangeIter)
proxy.gc_addRange( r.pbot, r.ptop - r.pbot, null ) ;
proxiedGC = instance; // remember initial GC to later remove roots
instance = proxy;
}
void gc_clrProxy ()
{
foreach (r; _gc.rangeIter)
proxy.gc_removeRange( r.pbot );
foreach (root; proxiedGC.rootIter)
{
instance.removeRoot(root);
}
foreach (r; _gc.rootIter)
proxy.gc_removeRoot( r );
foreach (range; proxiedGC.rangeIter)
{
instance.removeRange(range);
}
proxy = null ;
instance = proxiedGC;
proxiedGC = null ;
}
}
}