xo-gc stack: + request-gc-statistics() primitive
1. xo-gc now depends on xo-object2. 2. use genfacet for ICollector_DX1Collector 3. moves xo-gc utest previously in xo-object2 to more natural location in xo-gc/
This commit is contained in:
parent
7916971dc1
commit
f7c269a505
13 changed files with 74 additions and 11 deletions
|
|
@ -61,6 +61,15 @@
|
||||||
noexcept: true,
|
noexcept: true,
|
||||||
attributes: [],
|
attributes: [],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "error_allocator",
|
||||||
|
doc: [ "last-resort allocator for erros. e.g. regular allocator exhausted" ],
|
||||||
|
return_type: "obj<AAllocator>",
|
||||||
|
args: [],
|
||||||
|
const: true,
|
||||||
|
noexcept: true,
|
||||||
|
attributes: [],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "stringtable",
|
name: "stringtable",
|
||||||
doc: [ "stringtable for unique symbols" ],
|
doc: [ "stringtable for unique symbols" ],
|
||||||
|
|
|
||||||
|
|
@ -23,16 +23,19 @@ namespace xo {
|
||||||
using MemorySizeVisitor = xo::mm::MemorySizeVisitor;
|
using MemorySizeVisitor = xo::mm::MemorySizeVisitor;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DSimpleRcx(obj<AAllocator> mm, StringTable * st)
|
DSimpleRcx(obj<AAllocator> mm, obj<AAllocator> error_mm, StringTable * st)
|
||||||
: allocator_{mm}, stringtable_{st} {}
|
: allocator_{mm}, error_allocator_{error_mm},
|
||||||
|
stringtable_{st} {}
|
||||||
|
|
||||||
obj<AAllocator> allocator() const noexcept { return allocator_; }
|
obj<AAllocator> allocator() const noexcept { return allocator_; }
|
||||||
obj<ACollector> collector() const noexcept;
|
obj<ACollector> collector() const noexcept;
|
||||||
|
obj<AAllocator> error_allocator() const noexcept { return error_allocator_; }
|
||||||
StringTable * stringtable() const noexcept { return stringtable_; }
|
StringTable * stringtable() const noexcept { return stringtable_; }
|
||||||
void visit_pools(const MemorySizeVisitor & visitor) const;
|
void visit_pools(const MemorySizeVisitor & visitor) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
obj<AAllocator> allocator_;
|
obj<AAllocator> allocator_;
|
||||||
|
obj<AAllocator> error_allocator_;
|
||||||
StringTable * stringtable_ = nullptr;
|
StringTable * stringtable_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Primitive_gco_0.hpp"
|
||||||
#include "Primitive_gco_1_gco.hpp"
|
#include "Primitive_gco_1_gco.hpp"
|
||||||
|
|
||||||
namespace xo {
|
namespace xo {
|
||||||
|
|
@ -18,6 +19,10 @@ namespace xo {
|
||||||
using AAllocator = xo::mm::AAllocator;
|
using AAllocator = xo::mm::AAllocator;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/** create primitive: report gc statistics **/
|
||||||
|
static DPrimitive_gco_0 * make_report_gc_statistics_pm(obj<AAllocator> mm,
|
||||||
|
StringTable * stbl);
|
||||||
|
|
||||||
/** create primitive: request collection **/
|
/** create primitive: request collection **/
|
||||||
static DPrimitive_gco_1_gco * make_request_gc_pm(obj<AAllocator> mm,
|
static DPrimitive_gco_1_gco * make_request_gc_pm(obj<AAllocator> mm,
|
||||||
StringTable * stbl);
|
StringTable * stbl);
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,11 @@ public:
|
||||||
/** @defgroup scm-procedure-methods **/
|
/** @defgroup scm-procedure-methods **/
|
||||||
///@{
|
///@{
|
||||||
// const methods
|
// const methods
|
||||||
|
/** An uninitialized AProcedure instance will have zero vtable pointer (per {linux,osx} abi).
|
||||||
|
* Use case for this is narrow. We go to some lengths to avoid null vtable pointers. For example
|
||||||
|
* obj<AFacet> will have non-null vtable (via IFacet_Any) with all methods terminating.
|
||||||
|
**/
|
||||||
|
bool _has_null_vptr() const noexcept { return *reinterpret_cast<const void * const *>(this) == nullptr; }
|
||||||
/** RTTI: unique id# for actual runtime data representation **/
|
/** RTTI: unique id# for actual runtime data representation **/
|
||||||
virtual typeseq _typeseq() const noexcept = 0;
|
virtual typeseq _typeseq() const noexcept = 0;
|
||||||
/** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/
|
/** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,11 @@ public:
|
||||||
/** @defgroup scm-runtimecontext-methods **/
|
/** @defgroup scm-runtimecontext-methods **/
|
||||||
///@{
|
///@{
|
||||||
// const methods
|
// const methods
|
||||||
|
/** An uninitialized ARuntimeContext instance will have zero vtable pointer (per {linux,osx} abi).
|
||||||
|
* Use case for this is narrow. We go to some lengths to avoid null vtable pointers. For example
|
||||||
|
* obj<AFacet> will have non-null vtable (via IFacet_Any) with all methods terminating.
|
||||||
|
**/
|
||||||
|
bool _has_null_vptr() const noexcept { return *reinterpret_cast<const void * const *>(this) == nullptr; }
|
||||||
/** RTTI: unique id# for actual runtime data representation **/
|
/** RTTI: unique id# for actual runtime data representation **/
|
||||||
virtual typeseq _typeseq() const noexcept = 0;
|
virtual typeseq _typeseq() const noexcept = 0;
|
||||||
/** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/
|
/** destroy instance @p d; calls c++ dtor only for actual runtime type; does not recover memory **/
|
||||||
|
|
@ -59,6 +64,8 @@ public:
|
||||||
virtual obj<AAllocator> allocator(Copaque data) const noexcept = 0;
|
virtual obj<AAllocator> allocator(Copaque data) const noexcept = 0;
|
||||||
/** collector facet for allocator. If non-null, same data pointer as allocator **/
|
/** collector facet for allocator. If non-null, same data pointer as allocator **/
|
||||||
virtual obj<ACollector> collector(Copaque data) const noexcept = 0;
|
virtual obj<ACollector> collector(Copaque data) const noexcept = 0;
|
||||||
|
/** last-resort allocator for erros. e.g. regular allocator exhausted **/
|
||||||
|
virtual obj<AAllocator> error_allocator(Copaque data) const noexcept = 0;
|
||||||
/** stringtable for unique symbols **/
|
/** stringtable for unique symbols **/
|
||||||
virtual StringTable * stringtable(Copaque data) const noexcept = 0;
|
virtual StringTable * stringtable(Copaque data) const noexcept = 0;
|
||||||
/** invoke visitor for each distinct memory pool **/
|
/** invoke visitor for each distinct memory pool **/
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ namespace scm {
|
||||||
// const methods
|
// const methods
|
||||||
[[noreturn]] obj<AAllocator> allocator(Copaque) const noexcept override { _fatal(); }
|
[[noreturn]] obj<AAllocator> allocator(Copaque) const noexcept override { _fatal(); }
|
||||||
[[noreturn]] obj<ACollector> collector(Copaque) const noexcept override { _fatal(); }
|
[[noreturn]] obj<ACollector> collector(Copaque) const noexcept override { _fatal(); }
|
||||||
|
[[noreturn]] obj<AAllocator> error_allocator(Copaque) const noexcept override { _fatal(); }
|
||||||
[[noreturn]] StringTable * stringtable(Copaque) const noexcept override { _fatal(); }
|
[[noreturn]] StringTable * stringtable(Copaque) const noexcept override { _fatal(); }
|
||||||
[[noreturn]] void visit_pools(Copaque, MemorySizeVisitor) const override { _fatal(); }
|
[[noreturn]] void visit_pools(Copaque, MemorySizeVisitor) const override { _fatal(); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@ namespace xo {
|
||||||
static obj<AAllocator> allocator(const DSimpleRcx & self) noexcept;
|
static obj<AAllocator> allocator(const DSimpleRcx & self) noexcept;
|
||||||
/** collector facet for allocator. If non-null, same data pointer as allocator **/
|
/** collector facet for allocator. If non-null, same data pointer as allocator **/
|
||||||
static obj<ACollector> collector(const DSimpleRcx & self) noexcept;
|
static obj<ACollector> collector(const DSimpleRcx & self) noexcept;
|
||||||
|
/** last-resort allocator for erros. e.g. regular allocator exhausted **/
|
||||||
|
static obj<AAllocator> error_allocator(const DSimpleRcx & self) noexcept;
|
||||||
/** stringtable for unique symbols **/
|
/** stringtable for unique symbols **/
|
||||||
static StringTable * stringtable(const DSimpleRcx & self) noexcept;
|
static StringTable * stringtable(const DSimpleRcx & self) noexcept;
|
||||||
/** invoke visitor for each distinct memory pool **/
|
/** invoke visitor for each distinct memory pool **/
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,9 @@ namespace scm {
|
||||||
obj<ACollector> collector(Copaque data) const noexcept override {
|
obj<ACollector> collector(Copaque data) const noexcept override {
|
||||||
return I::collector(_dcast(data));
|
return I::collector(_dcast(data));
|
||||||
}
|
}
|
||||||
|
obj<AAllocator> error_allocator(Copaque data) const noexcept override {
|
||||||
|
return I::error_allocator(_dcast(data));
|
||||||
|
}
|
||||||
StringTable * stringtable(Copaque data) const noexcept override {
|
StringTable * stringtable(Copaque data) const noexcept override {
|
||||||
return I::stringtable(_dcast(data));
|
return I::stringtable(_dcast(data));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,9 @@ public:
|
||||||
obj<ACollector> collector() const noexcept {
|
obj<ACollector> collector() const noexcept {
|
||||||
return O::iface()->collector(O::data());
|
return O::iface()->collector(O::data());
|
||||||
}
|
}
|
||||||
|
obj<AAllocator> error_allocator() const noexcept {
|
||||||
|
return O::iface()->error_allocator(O::data());
|
||||||
|
}
|
||||||
StringTable * stringtable() const noexcept {
|
StringTable * stringtable() const noexcept {
|
||||||
return O::iface()->stringtable(O::data());
|
return O::iface()->stringtable(O::data());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,23 +21,35 @@ namespace xo {
|
||||||
|
|
||||||
// ----- report-gc-status -----
|
// ----- report-gc-status -----
|
||||||
|
|
||||||
#ifdef NOT_YET
|
|
||||||
obj<AGCObject>
|
obj<AGCObject>
|
||||||
xfer_report_gc_status(obj<ARuntimeContext> rcx)
|
xfer_report_gc_statistics(obj<ARuntimeContext> rcx)
|
||||||
{
|
{
|
||||||
bool have_gc = false;
|
|
||||||
|
|
||||||
if (rcx.collector()) {
|
if (rcx.collector()) {
|
||||||
// status currently only implemented for X1 collector
|
// status currently only implemented for X1 collector
|
||||||
|
|
||||||
auto gc = obj<ACollector,DX1Collector>::from(rcx.collector());
|
obj<AGCObject> stats;
|
||||||
|
bool ok = rcx.collector().report_statistics(rcx.allocator(),
|
||||||
|
rcx.error_allocator(),
|
||||||
|
&stats);
|
||||||
|
|
||||||
|
if (ok && stats)
|
||||||
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DBoolean::box(rcx.allocator(), false);
|
return DBoolean::box(rcx.allocator(), false);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
DPrimitive_gco_0 *
|
||||||
|
GcPrimitives::make_report_gc_statistics_pm(obj<AAllocator> mm,
|
||||||
|
StringTable * stbl)
|
||||||
|
{
|
||||||
|
(void)stbl;
|
||||||
|
|
||||||
|
auto any_ty = DAtomicType::make(mm, Metatype::t_any());
|
||||||
|
auto pm_ty = obj<AType,DFunctionType>(DFunctionType::_make(mm, any_ty));
|
||||||
|
|
||||||
|
return DPrimitive_gco_0::_make(mm, "report-gc-statistics", pm_ty, &xfer_report_gc_statistics);
|
||||||
|
}
|
||||||
|
|
||||||
// ----- request-gc -----
|
// ----- request-gc -----
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -130,6 +130,13 @@ namespace xo {
|
||||||
ObjectPrimitives::make_fn_n_args_pm(mm, stbl),
|
ObjectPrimitives::make_fn_n_args_pm(mm, stbl),
|
||||||
flags & InstallFlags::f_generalpurpose));
|
flags & InstallFlags::f_generalpurpose));
|
||||||
|
|
||||||
|
// ----- gc primitives -----
|
||||||
|
|
||||||
|
ok = ok & (PrimitiveRegistry::install_aux
|
||||||
|
(sink,
|
||||||
|
GcPrimitives::make_report_gc_statistics_pm(mm, stbl),
|
||||||
|
flags & InstallFlags::f_generalpurpose));
|
||||||
|
|
||||||
ok = ok & (PrimitiveRegistry::install_aux
|
ok = ok & (PrimitiveRegistry::install_aux
|
||||||
(sink,
|
(sink,
|
||||||
GcPrimitives::make_request_gc_pm(mm, stbl),
|
GcPrimitives::make_request_gc_pm(mm, stbl),
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,12 @@ namespace xo {
|
||||||
return self.collector();
|
return self.collector();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto
|
||||||
|
IRuntimeContext_DSimpleRcx::error_allocator(const DSimpleRcx & self) noexcept -> obj<AAllocator>
|
||||||
|
{
|
||||||
|
return self.error_allocator();
|
||||||
|
}
|
||||||
|
|
||||||
auto
|
auto
|
||||||
IRuntimeContext_DSimpleRcx::stringtable(const DSimpleRcx & self) noexcept -> StringTable *
|
IRuntimeContext_DSimpleRcx::stringtable(const DSimpleRcx & self) noexcept -> StringTable *
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ namespace xo {
|
||||||
auto stbl = StringTable(1024 /*hint_max_capacity*/,
|
auto stbl = StringTable(1024 /*hint_max_capacity*/,
|
||||||
false /*!debug_flag*/);
|
false /*!debug_flag*/);
|
||||||
|
|
||||||
DSimpleRcx rcx(alloc, &stbl);
|
DSimpleRcx rcx(alloc, alloc, &stbl);
|
||||||
|
|
||||||
REQUIRE((void*)rcx.allocator().data() == (void*)alloc.data());
|
REQUIRE((void*)rcx.allocator().data() == (void*)alloc.data());
|
||||||
REQUIRE(rcx.stringtable() == &stbl);
|
REQUIRE(rcx.stringtable() == &stbl);
|
||||||
|
|
@ -54,7 +54,7 @@ namespace xo {
|
||||||
auto stbl = StringTable(1024 /*hint_max_capacity*/,
|
auto stbl = StringTable(1024 /*hint_max_capacity*/,
|
||||||
false /*!debug_flag*/);
|
false /*!debug_flag*/);
|
||||||
|
|
||||||
DSimpleRcx rcx(alloc, &stbl);
|
DSimpleRcx rcx(alloc, alloc, &stbl);
|
||||||
obj<ARuntimeContext> rcx_obj = with_facet<ARuntimeContext>::mkobj(&rcx);
|
obj<ARuntimeContext> rcx_obj = with_facet<ARuntimeContext>::mkobj(&rcx);
|
||||||
|
|
||||||
// verify we can recover allocator from obj<ARuntimeContext>
|
// verify we can recover allocator from obj<ARuntimeContext>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue