xo-gc: bugfix + mutation log test passes
This commit is contained in:
parent
39b1ad1b21
commit
362dcf73fc
6 changed files with 310 additions and 117 deletions
|
|
@ -35,6 +35,7 @@ namespace xo {
|
|||
**/
|
||||
void init_mlogs(std::size_t page_z);
|
||||
|
||||
const MutationLogConfig & config() const noexcept { return config_; }
|
||||
MutationLog * get_mlog(Role r, Generation g) noexcept { return mlog_[r][g]; }
|
||||
const MutationLog * get_mlog(Role r, Generation g) const noexcept { return mlog_[r][g]; }
|
||||
/** reminder: abusing Role because we need one additional mlog **/
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ namespace xo {
|
|||
|
||||
for (std::uint32_t mlog_role = 0; mlog_role < c_n_role + 1; ++mlog_role) {
|
||||
this->mlog_storage_[mlog_role][igen]
|
||||
= _make_mlog(igen,
|
||||
label_v[mlog_role],
|
||||
config_.mutation_log_z_,
|
||||
page_z);
|
||||
= this->_make_mlog(igen,
|
||||
label_v[mlog_role],
|
||||
config_.mutation_log_z_,
|
||||
page_z);
|
||||
|
||||
this->mlog_[mlog_role][igen]
|
||||
= &(mlog_storage_[mlog_role][igen]);
|
||||
|
|
@ -152,6 +152,8 @@ namespace xo {
|
|||
*p_lhs = rhs;
|
||||
|
||||
if (!config_.enabled_flag_) {
|
||||
log && log(xtag("msg", "noop b/c incremental gc disabled"));
|
||||
|
||||
// only need to log mutations when incremental gc is enabled
|
||||
return;
|
||||
}
|
||||
|
|
@ -163,6 +165,8 @@ namespace xo {
|
|||
Generation src_g = gco_store->generation_of(Role::to_space(), p_lhs);
|
||||
|
||||
if (src_g.is_sentinel()) {
|
||||
log && log(xtag("msg", "noop because src not gc-owned"));
|
||||
|
||||
// only need mlog entries for gc-owned pointers.
|
||||
// In this case pointer does not originate in gc-owned space
|
||||
return;
|
||||
|
|
@ -171,11 +175,15 @@ namespace xo {
|
|||
Generation dest_g = gco_store->generation_of(Role::to_space(), rhs.data());
|
||||
|
||||
if (dest_g.is_sentinel()) {
|
||||
log && log(xtag("msg", "noop because dest not gc-owned"));
|
||||
|
||||
// similarly, don't need mlog entry to non-gc-owned destination
|
||||
return;
|
||||
}
|
||||
|
||||
if (src_g < dest_g) {
|
||||
log && log(xtag("msg", "noop because src gen younger than dest gen"));
|
||||
|
||||
// young-to-old pointers don't need to be remembered,
|
||||
// since a GC cycle that collects an (old) generation is guarnatted
|
||||
// to also collect all younger generations.
|
||||
|
|
@ -194,6 +202,8 @@ namespace xo {
|
|||
assert(src_hdr && dest_hdr);
|
||||
|
||||
if (gco_store->header2age(*src_hdr) <= gco_store->header2age(*dest_hdr)) {
|
||||
log && log(xtag("msg", "noop because src age no older than dest age"));
|
||||
|
||||
// source and destination have the same age;
|
||||
// therefore are always collected on the same set of GC cycles
|
||||
// -> no need to remember separately.
|
||||
|
|
@ -258,7 +268,7 @@ namespace xo {
|
|||
// - to_mlog, triage_mlog are empty
|
||||
|
||||
for (Generation child_gen{0};
|
||||
child_gen + 2 < config_.n_generation_;
|
||||
child_gen + 1 < config_.n_generation_;
|
||||
++child_gen) {
|
||||
|
||||
MutationLog * from_mlog = this->mlog_[Role::from_space()][child_gen];
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@ namespace ut {
|
|||
|
||||
// construct, extend, and/or modify object graphs in {x1_v, x2_v}
|
||||
|
||||
GcosTestutil::gcos_construct_ab_object_graphs(nullptr /*cmd_seq*/,
|
||||
GcosTestutil::gcos_construct_ab_object_graphs(TestSequence{} /*test_seq*/,
|
||||
tc.obj_graph_type_,
|
||||
tc.n_i0_test_obj_,
|
||||
tc.n_i0_test_assign_,
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ namespace ut {
|
|||
using xo::mm::ACollector;
|
||||
using xo::mm::DMockCollector;
|
||||
using xo::mm::X1VerifyStats;
|
||||
using xo::mm::MutationLog;
|
||||
using xo::mm::GCObjectStore;
|
||||
using xo::mm::AGCObject;
|
||||
using xo::mm::AAllocator;
|
||||
|
|
@ -316,7 +317,7 @@ namespace ut {
|
|||
* @p loop_index counts iteration with one gc-like phase.
|
||||
**/
|
||||
void
|
||||
GcosTestutil::gcos_construct_ab_object_graphs(Step * cmd_seq,
|
||||
GcosTestutil::gcos_construct_ab_object_graphs(TestSequence test_seq,
|
||||
TestGraphType obj_graph_type,
|
||||
uint32_t n_i0_test_obj,
|
||||
uint32_t n_i0_test_assign,
|
||||
|
|
@ -331,104 +332,185 @@ namespace ut {
|
|||
std::vector<Recd> * p_x2_v,
|
||||
xoshiro256ss * p_rgen)
|
||||
{
|
||||
if (cmd_seq && (loop_index == 0)) {
|
||||
// do scripted sequence only
|
||||
/** TestSequence memory layout
|
||||
*
|
||||
* test_seq
|
||||
* |
|
||||
* v
|
||||
* TestSequence
|
||||
* +-----------+ cmd_seq_[] (shared, sentinel-terminated)
|
||||
* | cmd_seq_ |---> +-------+-------+-------+-------+-------+-------+
|
||||
* +-----------+ | step0 | step1 | step2 | step3 | step4 | SENTL |
|
||||
* | phases_ |-\ +-------+-------+-------+-------+-------+-------+
|
||||
* +-----------+ | ix: 0 1 2 3 4 5
|
||||
* |
|
||||
* | phases_[] (sentinel-terminated)
|
||||
* \-> +-----------+-----------+
|
||||
* | Phase 0 | SENTINEL |
|
||||
* | lo_ix_=0 | lo_ix_=-1 |
|
||||
* | hi_ix_=5 | hi_ix_=-1 |
|
||||
* | mlog_new_ | mlog_new_ |
|
||||
* +-----------+-----------+
|
||||
*
|
||||
* Phase.lo_ix_ / hi_ix_ index into test_seq->cmd_seq_[].
|
||||
* Phase 0 executes cmd_seq_[lo_ix_ .. hi_ix_), i.e. steps 0..4.
|
||||
* Sentinel phase has lo_ix_ == -1.
|
||||
*
|
||||
* Each Step has {cmd_, arg0_ix_, arg1_ix_}.
|
||||
* arg0_ix_ and arg1_ix_ index into x1_v[] / x2_v[],
|
||||
* referring to objects created by earlier steps.
|
||||
*
|
||||
* Example (seq1):
|
||||
* step0: {make_bool, 0, 0} -> x1_v[0] = #f
|
||||
* step1: {make_bool, 1, 0} -> x1_v[1] = #t
|
||||
* step2: {make_nil, 0, 0} -> x1_v[2] = ()
|
||||
* step3: {make_cons, 0, 2} -> x1_v[3] = cons(x1_v[0], x1_v[2]) = (#f)
|
||||
* step4: {assign_head, 3, 1} -> set-car!(x1_v[3], x1_v[1]) => (#t)
|
||||
**/
|
||||
|
||||
auto alloc = obj<AAllocator,DArena>(p_gcos->new_space());
|
||||
auto alloc2 = obj<AAllocator,DArena>(p_arena2);
|
||||
DMockCollector mock(p_mls, p_gcos);
|
||||
auto mockgc = obj<ACollector,DMockCollector>(&mock);
|
||||
if (!test_seq.is_sentinel()) {
|
||||
// Explicit command sequence.
|
||||
// Each command creates a new node or modifies an existing one
|
||||
|
||||
while (cmd_seq->is_command()) {
|
||||
bool is_alloc = false;
|
||||
obj<AGCObject> xi;
|
||||
obj<AGCObject> xi2;
|
||||
uint64_t alloc_z = 0;
|
||||
typeseq tseq;
|
||||
// 1. Sequence of commands for this call.
|
||||
// Will be phases[loop_index] if well-defined.
|
||||
// 2. Expected effect on mutation log
|
||||
//
|
||||
Phase * phase_expect = nullptr;
|
||||
{
|
||||
Phase * p_phase = test_seq.phases_;
|
||||
|
||||
switch (cmd_seq->cmd_) {
|
||||
case Step::Cmd::sentinel:
|
||||
assert(false); // unreachable
|
||||
break;
|
||||
case Step::Cmd::make_nil:
|
||||
// TODO combine with code in random_object_graph()
|
||||
{
|
||||
is_alloc = true;
|
||||
|
||||
xi = ListOps::nil();
|
||||
alloc_z = 0; // not in gcos space
|
||||
tseq = typeseq::id<DList>();
|
||||
|
||||
xi2 = ListOps::nil();
|
||||
|
||||
REQUIRE(xi._typeseq() == tseq);
|
||||
REQUIRE(xi2._typeseq() == tseq);
|
||||
if (test_seq.phases_) {
|
||||
for (uint32_t i = 0; i < loop_index; ++i) {
|
||||
if (!p_phase->is_sentinel())
|
||||
++p_phase;
|
||||
else
|
||||
p_phase = nullptr;
|
||||
}
|
||||
break;
|
||||
case Step::Cmd::make_cons:
|
||||
// TODO combine with code in random_object_graph()
|
||||
{
|
||||
auto h1 = p_x1_v->at(cmd_seq->arg0_ix_).gco_;
|
||||
auto r1 = obj<AGCObject,DList>::from(p_x1_v->at(cmd_seq->arg1_ix_).gco_);
|
||||
auto h2 = p_x2_v->at(cmd_seq->arg0_ix_).gco_;
|
||||
auto r2 = obj<AGCObject,DList>::from(p_x2_v->at(cmd_seq->arg1_ix_).gco_);
|
||||
|
||||
is_alloc = true;
|
||||
|
||||
xi = ListOps::cons(alloc, h1, r1);
|
||||
alloc_z = sizeof(DList);
|
||||
tseq = typeseq::id<DList>();
|
||||
|
||||
xi2 = ListOps::cons(alloc2, h2, r2);
|
||||
}
|
||||
break;
|
||||
case Step::Cmd::make_bool:
|
||||
// TODO combine with code in random_object_graph()
|
||||
{
|
||||
bool value = (cmd_seq->arg0_ix_ > 0);
|
||||
|
||||
is_alloc = true;
|
||||
|
||||
xi = DBoolean::box(alloc, value);
|
||||
alloc_z = sizeof(DBoolean);
|
||||
tseq = typeseq::id<DBoolean>();
|
||||
|
||||
xi2 = DBoolean::box(alloc2, value);
|
||||
}
|
||||
break;
|
||||
case Step::Cmd::assign_head:
|
||||
{
|
||||
is_alloc = false;
|
||||
|
||||
auto lhs1 = obj<AGCObject,DList>::from(p_x1_v->at(cmd_seq->arg0_ix_).gco_);
|
||||
auto rhs1 = p_x2_v->at(cmd_seq->arg1_ix_).gco_;
|
||||
auto lhs2 = obj<AGCObject,DList>::from(p_x2_v->at(cmd_seq->arg0_ix_).gco_);
|
||||
auto rhs2 = p_x2_v->at(cmd_seq->arg1_ix_).gco_;
|
||||
|
||||
assert(lhs1);
|
||||
assert(!lhs1->is_empty());
|
||||
|
||||
assert(lhs2);
|
||||
assert(!lhs2->is_empty());
|
||||
|
||||
assert(p_mls);
|
||||
assert(mockgc);
|
||||
|
||||
lhs1->assign_head(mockgc, rhs1);
|
||||
// alloc2 is ord arena -> no mlog
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_alloc) {
|
||||
p_x1_v->push_back(Recd(xi, alloc_z, tseq));
|
||||
p_x2_v->push_back(Recd(xi2, alloc_z, tseq));
|
||||
phase_expect = p_phase;
|
||||
}
|
||||
|
||||
Step * cmd_seq = test_seq.cmd_seq_;
|
||||
|
||||
if (phase_expect && cmd_seq) {
|
||||
// Do scripted sequence only.
|
||||
// For this phases that is
|
||||
// cmd_seq[ix]
|
||||
// for
|
||||
// phase_expect->lo_ix_ <= ix < phase_expect->hi_ix_
|
||||
|
||||
auto alloc = obj<AAllocator,DArena>(p_gcos->new_space());
|
||||
auto alloc2 = obj<AAllocator,DArena>(p_arena2);
|
||||
DMockCollector mock(p_mls, p_gcos);
|
||||
auto mockgc = obj<ACollector,DMockCollector>(&mock);
|
||||
|
||||
for (int32_t ix = phase_expect->lo_ix_, hi = phase_expect->hi_ix_; ix < hi; ++ix) {
|
||||
const Step & cmd = cmd_seq[ix];
|
||||
|
||||
bool is_alloc = false;
|
||||
obj<AGCObject> xi;
|
||||
obj<AGCObject> xi2;
|
||||
uint64_t alloc_z = 0;
|
||||
typeseq tseq;
|
||||
|
||||
switch (cmd.cmd_) {
|
||||
case Step::Cmd::sentinel:
|
||||
assert(false); // unreachable
|
||||
break;
|
||||
case Step::Cmd::make_nil:
|
||||
// TODO combine with code in random_object_graph()
|
||||
{
|
||||
is_alloc = true;
|
||||
|
||||
xi = ListOps::nil();
|
||||
alloc_z = 0; // not in gcos space
|
||||
tseq = typeseq::id<DList>();
|
||||
|
||||
xi2 = ListOps::nil();
|
||||
|
||||
REQUIRE(xi._typeseq() == tseq);
|
||||
REQUIRE(xi2._typeseq() == tseq);
|
||||
}
|
||||
break;
|
||||
case Step::Cmd::make_cons:
|
||||
// TODO combine with code in random_object_graph()
|
||||
{
|
||||
auto h1 = p_x1_v->at(cmd.arg0_ix_).gco_;
|
||||
auto r1 = obj<AGCObject,DList>::from(p_x1_v->at(cmd.arg1_ix_).gco_);
|
||||
auto h2 = p_x2_v->at(cmd.arg0_ix_).gco_;
|
||||
auto r2 = obj<AGCObject,DList>::from(p_x2_v->at(cmd.arg1_ix_).gco_);
|
||||
|
||||
is_alloc = true;
|
||||
|
||||
xi = ListOps::cons(alloc, h1, r1);
|
||||
alloc_z = sizeof(DList);
|
||||
tseq = typeseq::id<DList>();
|
||||
|
||||
xi2 = ListOps::cons(alloc2, h2, r2);
|
||||
}
|
||||
break;
|
||||
case Step::Cmd::make_bool:
|
||||
// TODO combine with code in random_object_graph()
|
||||
{
|
||||
bool value = (cmd.arg0_ix_ > 0);
|
||||
|
||||
is_alloc = true;
|
||||
|
||||
xi = DBoolean::box(alloc, value);
|
||||
alloc_z = sizeof(DBoolean);
|
||||
tseq = typeseq::id<DBoolean>();
|
||||
|
||||
xi2 = DBoolean::box(alloc2, value);
|
||||
}
|
||||
break;
|
||||
case Step::Cmd::assign_head:
|
||||
{
|
||||
is_alloc = false;
|
||||
|
||||
auto lhs1 = obj<AGCObject,DList>::from(p_x1_v->at(cmd.arg0_ix_).gco_);
|
||||
auto rhs1 = p_x1_v->at(cmd.arg1_ix_).gco_;
|
||||
|
||||
auto lhs2 = obj<AGCObject,DList>::from(p_x2_v->at(cmd.arg0_ix_).gco_);
|
||||
auto rhs2 = p_x2_v->at(cmd.arg1_ix_).gco_;
|
||||
|
||||
assert(lhs1);
|
||||
assert(!lhs1->is_empty());
|
||||
|
||||
assert(lhs2);
|
||||
assert(!lhs2->is_empty());
|
||||
|
||||
assert(p_mls);
|
||||
assert(mockgc);
|
||||
|
||||
lhs1->assign_head(mockgc, rhs1);
|
||||
// alloc2 is ord arena -> no mlog
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_alloc) {
|
||||
p_x1_v->push_back(Recd(xi, alloc_z, tseq));
|
||||
p_x2_v->push_back(Recd(xi2, alloc_z, tseq));
|
||||
}
|
||||
}
|
||||
|
||||
++cmd_seq;
|
||||
// check expected results
|
||||
|
||||
for (Generation gi{0}; gi + 1 < Generation(p_mls->config().n_generation_); ++gi) {
|
||||
MutationLog * mlog = p_mls->get_mlog(Role::to_space(), gi);
|
||||
|
||||
REQUIRE(mlog);
|
||||
REQUIRE(mlog->size() == phase_expect->mlog_new_z_[gi]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
switch (obj_graph_type) {
|
||||
case TestGraphType::fixed:
|
||||
assert(false); // unreachable
|
||||
break;
|
||||
|
||||
case TestGraphType::selfcycle:
|
||||
if (loop_index == 0) {
|
||||
GcosTestutil::selfcycle_object_graph(p_x1_v,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include <xo/alloc2/Generation.hpp>
|
||||
#include <xo/arena/DArena.hpp>
|
||||
#include <xo/randomgen/xoshiro256.hpp>
|
||||
#include <array>
|
||||
|
||||
namespace ut {
|
||||
using xo::mm::Generation;
|
||||
|
|
@ -46,6 +47,54 @@ namespace ut {
|
|||
uint32_t arg1_ix_;
|
||||
};
|
||||
|
||||
/** a phase comprises:
|
||||
* 1. start with {gcos,mls} in known + valid state.
|
||||
* 2. perform a sequence of commands
|
||||
* (in general a mix of allocs and mutations)
|
||||
* command sequence in @ref cmd_seq_, null-terminated
|
||||
* 3. verify mlog state after sequence
|
||||
* 4. run instrumented collection phase
|
||||
* 4a. swap roles (i.e. from- and to- spaces)
|
||||
* 4b. move roots, see gcos_move_roots_and_verify()
|
||||
* 4c. update mutation log, see forward_mutation_log()
|
||||
* 4d. cleanup (reset from- spaces)
|
||||
* 5. re-verify {gcos,mls} in valid state
|
||||
**/
|
||||
struct Phase {
|
||||
bool is_sentinel() const noexcept { return lo_ix_ == -1; }
|
||||
|
||||
/** Command sequence for this phase.
|
||||
* See TestSequence.cmd_seq_
|
||||
* Phase comprises commands cmd_seq_[ix] for lo_ix <= ix < hi_ix
|
||||
**/
|
||||
int32_t lo_ix_ = -1;
|
||||
int32_t hi_ix_ = -1;
|
||||
/** expected number of new entries in
|
||||
* to-space mutation log after executing @ref cmd_seq_
|
||||
**/
|
||||
std::array<uint32_t, xo::mm::c_max_generation - 1> mlog_new_z_;
|
||||
};
|
||||
|
||||
struct TestSequence {
|
||||
bool is_sentinel() const noexcept { return cmd_seq_ == nullptr; }
|
||||
|
||||
/** shared null-terminated command sequence.
|
||||
* references are taken relative to cmd_seq_[0].
|
||||
* A step
|
||||
* {make_cons, x, y} -> make a cons cell.
|
||||
* head from value ~ cmd_seq_[x]
|
||||
* rest from value ~ cmd_seq_[y]
|
||||
*
|
||||
**/
|
||||
Step * cmd_seq_ = nullptr;
|
||||
|
||||
/** array of phases.
|
||||
* One gc cycle per phase.
|
||||
* Sentinel phase has {lo_ix_ = -1, hi_ix_ = -1};
|
||||
**/
|
||||
Phase * phases_ = nullptr;
|
||||
};
|
||||
|
||||
enum class TestGraphType {
|
||||
/* spelled out sequence of Steps */
|
||||
fixed,
|
||||
|
|
@ -110,9 +159,11 @@ namespace ut {
|
|||
const GCObjectStore & gcos);
|
||||
|
||||
/** sequence of steps. if non-null, ends with step s: s.cmd_ == Step::Cmd::Sentinel
|
||||
*
|
||||
* @p p_cmd_seq pointer to null-terminated array of Step[] arrays
|
||||
**/
|
||||
static void
|
||||
gcos_construct_ab_object_graphs(Step * cmd_seq,
|
||||
gcos_construct_ab_object_graphs(TestSequence test_seq,
|
||||
TestGraphType obj_graph_type,
|
||||
uint32_t n_i0_test_obj,
|
||||
uint32_t n_i0_test_assign,
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ namespace ut {
|
|||
size_t gc_z,
|
||||
uint32_t type_z,
|
||||
bool do_type_registration,
|
||||
Step * cmd_seq,
|
||||
TestSequence test_seq,
|
||||
uint32_t mlog_z,
|
||||
bool mlog_enabled_flag,
|
||||
TestGraphType obj_graph_type,
|
||||
|
|
@ -57,7 +57,7 @@ namespace ut {
|
|||
do_type_registration_{do_type_registration},
|
||||
mutation_log_z_{mlog_z},
|
||||
mlog_enabled_flag_{mlog_enabled_flag},
|
||||
cmd_seq_{cmd_seq},
|
||||
test_seq_{test_seq},
|
||||
obj_graph_type_{obj_graph_type},
|
||||
n_gc_loop_{n_gc_loop},
|
||||
n_i0_test_obj_{n_i0_test_obj},
|
||||
|
|
@ -83,8 +83,8 @@ namespace ut {
|
|||
* (load-bearing for incremental gc)
|
||||
**/
|
||||
bool mlog_enabled_flag_ = false;
|
||||
/** first loop: explicit cell alloc/assign **/
|
||||
Step * cmd_seq_ = nullptr;
|
||||
/** if non-null; run contents of cmd_seq_[i] on loop #i **/
|
||||
TestSequence test_seq_;
|
||||
/** object graph type **/
|
||||
TestGraphType obj_graph_type_ = TestGraphType::random;
|
||||
/** #of gc-like "move all the roots" phases to perform **/
|
||||
|
|
@ -107,47 +107,96 @@ namespace ut {
|
|||
|
||||
using Cmd = Step::Cmd;
|
||||
|
||||
static Step seq0[] = {
|
||||
static Step step_0[] = {
|
||||
{Cmd::make_bool, 0, 0}, // #f
|
||||
{Cmd::make_nil, 0, 0}, // #nil
|
||||
{Cmd::make_nil, 0, 0}, // #nil
|
||||
{Cmd::make_cons, 0, 1}, // cons(#f,#nil)
|
||||
{Cmd::sentinel, 0, 0},
|
||||
{Cmd::sentinel, 0, 0},
|
||||
};
|
||||
|
||||
static Step seq1[] = {
|
||||
{Cmd::make_bool, 0, 0}, // #f
|
||||
{Cmd::make_bool, 1, 0}, // #t
|
||||
{Cmd::make_nil, 0, 0}, // #nil
|
||||
{Cmd::make_cons, 0, 2}, // cons(#f,#nil)
|
||||
{Cmd::assign_head, 3, 1}, // set-car(cons(#f,#nil),#t)
|
||||
{Cmd::sentinel, 0, 0},
|
||||
static Phase phase_0[] = {
|
||||
//
|
||||
// lo hi mlog_new_z_[]
|
||||
// v v v
|
||||
{ 0, 3, {0} },
|
||||
{ -1, -1, {0} },
|
||||
};
|
||||
|
||||
static TestSequence seq_0 { step_0, phase_0 };
|
||||
|
||||
// seq1: side effect on head of cons cell.
|
||||
// But no mlog entry b/c all object ages are equal
|
||||
// -> no x-age pointers
|
||||
//
|
||||
static Step step_1[] = {
|
||||
{Cmd::make_bool, 0, 0}, // [0]: #f
|
||||
{Cmd::make_bool, 1, 0}, // [1]: #t
|
||||
{Cmd::make_nil, 0, 0}, // [2]: #nil
|
||||
{Cmd::make_cons, 0, 2}, // [3]: cons(#f,#nil)
|
||||
{Cmd::assign_head, 3, 1}, // set-car(cons(#f,#nil),#t)
|
||||
{Cmd::sentinel, 0, 0},
|
||||
};
|
||||
|
||||
static Phase phase_1[] = {
|
||||
//
|
||||
// lo hi mlog_new_z_[]
|
||||
// v v v
|
||||
{ 0, 5, {0} },
|
||||
{ -1, -1, {0} },
|
||||
};
|
||||
|
||||
static TestSequence seq_1 { step_1, phase_1 };
|
||||
|
||||
static Step step_2[] = {
|
||||
// ----- phase 0 -----
|
||||
{Cmd::make_bool, 0, 0}, // [0]: #f
|
||||
{Cmd::make_bool, 1, 0}, // [1]: #t
|
||||
{Cmd::make_nil, 0, 0}, // [2]: #nil
|
||||
{Cmd::make_cons, 0, 2}, // [3]: cons(#f,#nil)
|
||||
// ----- phase 1 -----
|
||||
{Cmd::make_bool, 1, 0}, // [4]: #t
|
||||
{Cmd::assign_head, 3, 4}, // set-car(cons(#f,#nil),#t)
|
||||
{Cmd::sentinel, 0, 0},
|
||||
};
|
||||
|
||||
static Phase phase_2[] = {
|
||||
//
|
||||
// lo hi mlog_new_z_[]
|
||||
// v v v
|
||||
{ 0, 4, {0} }, // phase 0
|
||||
{ 4, 6, {1} }, // phase 1. set-car makes 1x xgen ptr from g1->g0
|
||||
{ -1, -1, {0} },
|
||||
};
|
||||
|
||||
static TestSequence seq_2 { step_2, phase_2 };
|
||||
|
||||
# define seq_nil TestSequence{}
|
||||
# define nil nullptr
|
||||
# define T true
|
||||
# define F false
|
||||
|
||||
static std::vector<Testcase> s_testcase_v = {
|
||||
/**
|
||||
* debug_flag
|
||||
* n_i1_test_assign |
|
||||
* n_i1_test_obj | |
|
||||
* n_i0_test_assign | | |
|
||||
* n_i0_test_obj | | | |
|
||||
* n_gc_loop | | | | |
|
||||
* obj_graph_type | | | | | |
|
||||
* mlog_enabled_flag | | | | | | |
|
||||
* mutation_log_z | | | | | | | |
|
||||
* cmd_seq | | | | | | | | |
|
||||
* do_type_registration | | | | | | | | | |
|
||||
* n_survive object_type_z | | | | | | | | | | |
|
||||
* n_gen | gc_size | | | | | | | | | | | |
|
||||
* v v v v v v v v v v v v v v v
|
||||
* debug_flag
|
||||
* n_i1_test_assign |
|
||||
* n_i1_test_obj | |
|
||||
* n_i0_test_assign | | |
|
||||
* n_i0_test_obj | | | |
|
||||
* n_gc_loop | | | | |
|
||||
* obj_graph_type | | | | | |
|
||||
* mlog_enabled_flag | | | | | | |
|
||||
* mutation_log_z | | | | | | | |
|
||||
* cmd_seq | | | | | | | | |
|
||||
* do_type_registration | | | | | | | | | |
|
||||
* n_survive object_type_z | | | | | | | | | | |
|
||||
* n_gen | gc_size | | | | | | | | | | | |
|
||||
* v v v v v v v v v v v v v v v
|
||||
**/
|
||||
Testcase(2, 4, 16 * 1024, 8 * 128, F, nil, 0, F, c_random, 1, 0, 0, 0, 0, F),
|
||||
Testcase(2, 4, 16 * 1024, 8 * 128, T, nil, 0, F, c_selfcycle, 1, 1, 0, 0, 0, F),
|
||||
Testcase(2, 4, 16 * 1024, 8 * 128, T, seq0, 0, F, c_fixed, 1, 0, 0, 0, 0, F),
|
||||
Testcase(2, 4, 16 * 1024, 8 * 128, T, seq1, 0, F, c_fixed, 1, 0, 0, 0, 0, T),
|
||||
Testcase(2, 4, 16 * 1024, 8 * 128, F, seq_nil, 0, F, c_random, 1, 0, 0, 0, 0, F),
|
||||
Testcase(2, 4, 16 * 1024, 8 * 128, T, seq_nil, 0, F, c_selfcycle, 1, 1, 0, 0, 0, F),
|
||||
Testcase(2, 4, 16 * 1024, 8 * 128, T, seq_0, 0, F, c_fixed, 1, 0, 0, 0, 0, F),
|
||||
Testcase(2, 4, 16 * 1024, 8 * 128, T, seq_1, 0, F, c_fixed, 1, 0, 0, 0, 0, F),
|
||||
Testcase(2, 1, 16 * 1024, 8 * 128, T, seq_2, 128, T, c_fixed, 2, 0, 0, 0, 0, T),
|
||||
};
|
||||
|
||||
# undef T
|
||||
|
|
@ -284,7 +333,7 @@ namespace ut {
|
|||
for (uint32_t loop_index = 0; loop_index < tc.n_gc_loop_; ++loop_index) {
|
||||
scope log2(XO_DEBUG(tc.debug_flag_), "gc loop", xtag("loop_index", loop_index));
|
||||
|
||||
GcosTestutil::gcos_construct_ab_object_graphs(tc.cmd_seq_,
|
||||
GcosTestutil::gcos_construct_ab_object_graphs(tc.test_seq_,
|
||||
tc.obj_graph_type_,
|
||||
tc.n_i0_test_obj_,
|
||||
tc.n_i0_test_assign_,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue