From 0e03a3cd1d1ac89ea3afe2cc40e8434d2ca09b7c Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Mon, 8 Jun 2020 12:01:37 +0100 Subject: [PATCH 1/3] Add test for #83 --- src/rt/test/func/freeze/freeze.cc | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/rt/test/func/freeze/freeze.cc b/src/rt/test/func/freeze/freeze.cc index 2e5c9c2ad..9911caf3a 100644 --- a/src/rt/test/func/freeze/freeze.cc +++ b/src/rt/test/func/freeze/freeze.cc @@ -249,6 +249,33 @@ void test4() snmalloc::current_alloc_pool()->debug_check_empty(); } +void test5() +{ + // Freeze with unreachable subregion + // Bug reported in #83 + // + // There are two regions, [1, 2], [3]. + // + // Freeze 1, + // Ptr from 2 to subregion 3 + auto* alloc = ThreadAlloc::get(); + + C1* o1 = new (alloc) C1; + C1* o2 = new (alloc, o1) C1; + C1* o3 = new (alloc) C1; + + o2->f1 = o3; + + Freeze::apply(alloc, o1); + + check(o1->debug_test_rc(1)); + + // Free immutable graph. + Immutable::release(alloc, o1); + + snmalloc::current_alloc_pool()->debug_check_empty(); +} + void freeze_weird_ring() { auto* alloc = ThreadAlloc::get(); @@ -455,6 +482,7 @@ int main(int, char**) test2(); test3(); test4(); + test5(); test_two_rings_1(); test_two_rings_2(); freeze_weird_ring(); From 5e9c1334509aa3b594a2fbcda1742c2b960e2dbf Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Fri, 6 Mar 2020 14:47:27 +0000 Subject: [PATCH 2/3] Modified finaliser to collect subregions The finaliser must return the subregions that this object owns that will require collection. This removes the need for the hacky `trace_possibly_iso` that was used during deallocation. This simplifies the ordering of deallocation. The most general semantics the runtime supports is > self is mutable, but any mutable object it > refers to is read-only This implementation still allows the extract to function during finalisation. We may wish the language to be more restrictive, i.e. everything read-only during finalisation. --- src/interpreter/object.cc | 30 ++++++++-- src/interpreter/object.h | 15 ++--- src/interpreter/value.cc | 25 ++++++++ src/interpreter/value.h | 6 ++ src/rt/cpp/vobject.h | 24 ++------ src/rt/object/object.h | 55 ++++++++---------- src/rt/region/freeze.h | 12 +++- src/rt/region/immutable.h | 9 ++- src/rt/region/region.h | 12 ++-- src/rt/region/region_arena.h | 17 +++--- src/rt/region/region_trace.h | 57 +++++++------------ src/rt/sched/cown.h | 4 +- src/rt/test/func/cowngc4/cowngc4.cc | 8 +-- src/rt/test/func/finalisers/finalisers.cc | 14 ++--- src/rt/test/func/freeze/freeze.cc | 19 ++++++- src/rt/test/func/memory/memory.h | 16 +++--- src/rt/test/func/memory/memory_iterator.h | 3 +- src/rt/test/func/memory/memory_subregion.h | 5 +- .../test/func/rememberedset/rememberedset.cc | 2 - 19 files changed, 186 insertions(+), 147 deletions(-) diff --git a/src/interpreter/object.cc b/src/interpreter/object.cc index 3215202b5..11fd96c24 100644 --- a/src/interpreter/object.cc +++ b/src/interpreter/object.cc @@ -30,10 +30,12 @@ namespace verona::interpreter // skip it. In that case, there are also obviously no iso fields. rt::Descriptor::destructor = field_count > 0 ? VMObject::destructor_fn : nullptr; - rt::Descriptor::trace_possibly_iso = - field_count > 0 ? VMObject::trace_fn : nullptr; + // In the VM object we always need a finaliser in case it has an iso field. + // The finaliser will collect the iso references that will be deallocated + // at the end of this phase. + // TODO: Can be optimised if we look at the types of all the fields rt::Descriptor::finaliser = - finaliser_ip > 0 ? VMObject::finaliser_fn : nullptr; + finaliser_ip > 0 ? VMObject::finaliser_fn : VMObject::collect_iso_fields; } VMObject::VMObject(VMObject* region, const VMDescriptor* desc) @@ -69,10 +71,30 @@ namespace verona::interpreter } } - void VMObject::finaliser_fn(rt::Object* base_object) + void VMObject::finaliser_fn( + rt::Object* base_object, rt::Object* region, rt::ObjectStack& sub_regions) { VMObject* object = static_cast(base_object); + VM::execute_finaliser(object); + + collect_iso_fields(base_object, region, sub_regions); + } + + void VMObject::collect_iso_fields( + rt::Object* base_object, rt::Object* region, rt::ObjectStack& sub_regions) + { + // The interpreter doesn't need the region, as the FieldValue type contains + // the ISO information in its fat pointers. + UNUSED(region); + + VMObject* object = static_cast(base_object); + const VMDescriptor* descriptor = object->descriptor(); + + for (size_t i = 0; i < descriptor->field_count; i++) + { + object->fields[i].add_isos(sub_regions); + } } void VMObject::destructor_fn(rt::Object* base_object) diff --git a/src/interpreter/object.h b/src/interpreter/object.h index add07544b..52fa9f62d 100644 --- a/src/interpreter/object.h +++ b/src/interpreter/object.h @@ -44,7 +44,14 @@ namespace verona::interpreter VMObject* region(); static void trace_fn(const rt::Object* base_object, rt::ObjectStack* stack); - static void finaliser_fn(rt::Object* base_object); + static void finaliser_fn( + rt::Object* base_object, + rt::Object* region, + rt::ObjectStack& sub_regions); + static void collect_iso_fields( + rt::Object* base_object, + rt::Object* region, + rt::ObjectStack& sub_regions); static void destructor_fn(rt::Object* base_object); private: @@ -86,11 +93,5 @@ namespace verona::interpreter if (contents != nullptr) stack->push(contents); } - - void trace_possibly_iso(rt::ObjectStack* stack) - { - if (contents != nullptr) - stack->push(contents); - } }; } diff --git a/src/interpreter/value.cc b/src/interpreter/value.cc index fa61dc1b3..b1825db56 100644 --- a/src/interpreter/value.cc +++ b/src/interpreter/value.cc @@ -325,6 +325,31 @@ namespace verona::interpreter } } + void FieldValue::add_isos(rt::ObjectStack& stack) const + { + switch (tag) + { + case Value::ISO: + stack.push(inner.object); + break; + + case Value::COWN: + case Value::MUT: + case Value::IMM: + case Value::UNINIT: + case Value::U64: + case Value::STRING: + case Value::DESCRIPTOR: + break; + + case Value::COWN_UNOWNED: + // Cannot be part of the heap. + abort(); + + EXHAUSTIVE_SWITCH + } + } + FieldValue::~FieldValue() { switch (tag) diff --git a/src/interpreter/value.h b/src/interpreter/value.h index 5f11f52ac..7fb24da82 100644 --- a/src/interpreter/value.h +++ b/src/interpreter/value.h @@ -192,6 +192,12 @@ namespace verona::interpreter void trace(rt::ObjectStack* stack) const; + /** + * If this Value contains an ISO, then add it to the stack + * Otherwise, do nothing. + **/ + void add_isos(rt::ObjectStack& stack) const; + friend fmt::formatter; private: diff --git a/src/rt/cpp/vobject.h b/src/rt/cpp/vobject.h index 9d1bc0571..564db8a6c 100644 --- a/src/rt/cpp/vobject.h +++ b/src/rt/cpp/vobject.h @@ -20,15 +20,6 @@ namespace verona::rt // // This is better than ignoring methods with the right name but the wrong // signature. - template - struct has_trace_possibly_iso : std::false_type - {}; - template - struct has_trace_possibly_iso< - T, - std::void_t> : std::true_type - {}; - template struct has_notified : std::false_type {}; @@ -71,22 +62,16 @@ namespace verona::rt ((T*)o)->trace(st); } - static void gc_trace_possibly_iso(const Object* o, ObjectStack* st) - { - if constexpr (has_trace_possibly_iso::value) - ((T*)o)->trace_possibly_iso(st); - } - static void gc_notified(Object* o) { if constexpr (has_notified::value) ((T*)o)->notified(o); } - static void gc_final(Object* o) + static void gc_final(Object* o, Object* region, ObjectStack& sub_regions) { if constexpr (has_finaliser::value) - ((T*)o)->finaliser(); + ((T*)o)->finaliser(region, sub_regions); } static void gc_destructor(Object* o) @@ -99,7 +84,6 @@ namespace verona::rt static constexpr Descriptor desc = { sizeof(T), gc_trace, - has_trace_possibly_iso::value ? gc_trace_possibly_iso : nullptr, has_finaliser::value ? gc_final : nullptr, has_notified::value ? gc_notified : nullptr, has_destructor::value ? gc_destructor : nullptr}; @@ -131,7 +115,7 @@ namespace verona::rt if constexpr (std::is_same_v) return RegionClass::template create(alloc, desc()); else - return ThreadAlloc::get()->alloc(); + return alloc->alloc(); } void* operator new(size_t, Object* region) @@ -148,7 +132,7 @@ namespace verona::rt if constexpr (std::is_same_v) return RegionClass::template alloc(alloc, region, desc()); else - return ThreadAlloc::get()->alloc(); + return alloc->alloc(); } void operator delete(void*) diff --git a/src/rt/object/object.h b/src/rt/object/object.h index d556a6a2b..282185805 100644 --- a/src/rt/object/object.h +++ b/src/rt/object/object.h @@ -86,7 +86,6 @@ namespace verona::rt // for field in o do // st.push(o.field) using TraceFunction = void (*)(const Object* o, ObjectStack* st); - using TraceIsoFunction = void (*)(const Object* o, ObjectStack* st); using NotifiedFunction = void (*)(Object* o); @@ -102,14 +101,15 @@ namespace verona::rt // invalid state ie. close file descriptors or deallocate some auxiliary // storage. // - // The finaliser can extract sub-regions and eg. send them in a - // multi-message. The destructor on the other hand may not do this. - using FinalFunction = void (*)(Object* o); + // The finaliser can must add all the subregions reachable from this object + // to the ObjectStack it is passed, so that they can be deallocated once + // this region has been deallocated. + using FinalFunction = void (*)(Object* o, Object* region, ObjectStack& st); + using DestructorFunction = void (*)(Object* o); size_t size; TraceFunction trace; - TraceIsoFunction trace_possibly_iso; FinalFunction finaliser; NotifiedFunction notified = nullptr; DestructorFunction destructor = nullptr; @@ -702,15 +702,9 @@ namespace verona::rt return get_descriptor()->destructor != nullptr; } - inline bool has_possibly_iso_fields() - { - return get_descriptor()->trace_possibly_iso != nullptr; - } - static inline bool is_trivial(const Descriptor* desc) { - return desc->destructor == nullptr && desc->finaliser == nullptr && - desc->trace_possibly_iso == nullptr; + return desc->destructor == nullptr && desc->finaliser == nullptr; } inline bool is_trivial() @@ -732,15 +726,10 @@ namespace verona::rt get_descriptor()->trace(this, &f); } - inline void trace_possibly_iso(ObjectStack& f) const - { - get_descriptor()->trace_possibly_iso(this, &f); - } - - inline void finalise() + inline void finalise(Object* region, ObjectStack& isos) { if (has_finaliser()) - get_descriptor()->finaliser(this); + get_descriptor()->finaliser(this, region, isos); } inline void notified() @@ -760,21 +749,23 @@ namespace verona::rt alloc->dealloc(this, size()); } - inline void - find_iso_fields(Object* region_entry, ObjectStack& f, ObjectStack& iso_st) + protected: + static void + add_sub_region(Object* obj, Object* region, ObjectStack& sub_regions) { - // Find all isolated fields in p other than some predecessor o. - if (!has_possibly_iso_fields()) - return; - - trace_possibly_iso(f); - - while (!f.empty()) + // Should be the entry-point of the region. + assert( + (region == nullptr) || (region->get_class() == Object::RegionMD::ISO)); + // Have to be careful about internal references to the entry point for the + // `region` i.e. when obj == region we are refering to the entry point + // from inside the region and should not treat this as a subregion + // pointer. + if ((obj != nullptr) && (obj != region)) { - Object* o = f.pop(); - - if ((o != region_entry) && (o->get_class() == Object::ISO)) - iso_st.push(o); + if (obj->get_class() == Object::RegionMD::ISO) + { + sub_regions.push(obj); + } } } }; diff --git a/src/rt/region/freeze.h b/src/rt/region/freeze.h index dc1e40794..bf2161abc 100644 --- a/src/rt/region/freeze.h +++ b/src/rt/region/freeze.h @@ -139,6 +139,7 @@ namespace verona::rt ObjectStack dfs(alloc); ObjectStack iso(alloc); ObjectStack pending(alloc); + ObjectStack dealloc_regions(alloc); iso.push(o); @@ -286,8 +287,17 @@ namespace verona::rt assert(p != reg); - p->finalise(); + // ISO marker has been dropped on entry point, so + // can pass nullptr here. + p->finalise(nullptr, dealloc_regions); to_dealloc.push(p); + // Deallocate unreachable sub-regions + while (!dealloc_regions.empty()) + { + Object* q = dealloc_regions.pop(); + Region::release(alloc, q); + } + p = next; continue; } diff --git a/src/rt/region/immutable.h b/src/rt/region/immutable.h index 070ddea27..e443aebfd 100644 --- a/src/rt/region/immutable.h +++ b/src/rt/region/immutable.h @@ -121,7 +121,10 @@ namespace verona::rt // Run all finalisers for this SCC before deallocating. fl.forall(); - v->finalise(); + + // We don't need the actual subregions here, as they have been frozen. + ObjectStack dummy(alloc); + v->finalise(nullptr, dummy); while (!fl.empty()) { @@ -146,7 +149,9 @@ namespace verona::rt static inline void run_finaliser(Object* o) { - o->finalise(); + // We don't need the actual subregions here, as they have been frozen. + ObjectStack dummy(ThreadAlloc::get_noncachable()); + o->finalise(nullptr, dummy); } static inline void scc_classify( diff --git a/src/rt/region/region.h b/src/rt/region/region.h index 353a8b513..7a7827c4b 100644 --- a/src/rt/region/region.h +++ b/src/rt/region/region.h @@ -168,14 +168,13 @@ namespace verona::rt { assert(o->debug_is_iso()); ObjectStack collect(alloc); - ObjectStack f(alloc); - Region::release_internal(alloc, o, f, collect); + Region::release_internal(alloc, o, collect); while (!collect.empty()) { o = collect.pop(); assert(o->debug_is_iso()); - Region::release_internal(alloc, o, f, collect); + Region::release_internal(alloc, o, collect); } } @@ -300,18 +299,17 @@ namespace verona::rt * * We dispatch based on the type of region represented by `o`. **/ - static void release_internal( - Alloc* alloc, Object* o, ObjectStack& f, ObjectStack& collect) + static void release_internal(Alloc* alloc, Object* o, ObjectStack& collect) { assert(o->debug_is_iso()); RegionBase* r = o->get_region(); switch (Region::get_type(r)) { case RegionType::Trace: - ((RegionTrace*)r)->release_internal(alloc, o, f, collect); + ((RegionTrace*)r)->release_internal(alloc, o, collect); return; case RegionType::Arena: - ((RegionArena*)r)->release_internal(alloc, o, f, collect); + ((RegionArena*)r)->release_internal(alloc, o, collect); return; default: abort(); diff --git a/src/rt/region/region_arena.h b/src/rt/region/region_arena.h index 749f7159e..ff0e7ad45 100644 --- a/src/rt/region/region_arena.h +++ b/src/rt/region/region_arena.h @@ -537,8 +537,7 @@ namespace verona::rt * * Note: this does not release subregions. Use Region::release instead. **/ - void release_internal( - Alloc* alloc, Object* o, ObjectStack& f, ObjectStack& collect) + void release_internal(Alloc* alloc, Object* o, ObjectStack& collect) { assert(o->debug_is_iso()); // Don't trace or finalise o, we'll do it when looping over the large @@ -548,16 +547,20 @@ namespace verona::rt // Clean up all the non-trivial objects, by running the finaliser and // destructor, and collecting iso regions. - // - // This must be done in two passes, as one object's finaliser may read - // another object's fields, or even extract sub-regions from it. + // Finalisers must provide all the isos of the current object that will + // need collecting. The language must guarantee that there are no isos + // left in this object that haven't been added to collect. Read-only + // views of objects during finalization are the easiest way to guarantee + // this. for (auto it = begin(); it != end(); ++it) { - (*it)->finalise(); + (*it)->finalise(o, collect); } + + // Destructors can invalidate the object's state, so all finalisers must + // run before any destructor runs, i.e. two separate passes are required. for (auto it = begin(); it != end(); ++it) { - (*it)->find_iso_fields(o, f, collect); (*it)->destructor(); } diff --git a/src/rt/region/region_trace.h b/src/rt/region/region_trace.h index 24c39de2f..38cb1caa4 100644 --- a/src/rt/region/region_trace.h +++ b/src/rt/region/region_trace.h @@ -232,7 +232,7 @@ namespace verona::rt size_t marked = 0; reg->mark(alloc, o, f, marked); - reg->sweep(alloc, o, f, collect, marked); + reg->sweep(alloc, o, collect, marked); // `collect` contains all the iso objects to unreachable subregions. // Since they are unreachable, we can just release them. @@ -251,9 +251,9 @@ namespace verona::rt // Unfortunately, we can't use Region::release_internal because of a // circular dependency between header files. if (RegionTrace::is_trace_region(r)) - ((RegionTrace*)r)->release_internal(alloc, o, f, collect); + ((RegionTrace*)r)->release_internal(alloc, o, collect); else if (RegionArena::is_arena_region(r)) - ((RegionArena*)r)->release_internal(alloc, o, f, collect); + ((RegionArena*)r)->release_internal(alloc, o, collect); else abort(); } @@ -403,12 +403,7 @@ namespace verona::rt * and the Iso object is collected as well. **/ template - void sweep( - Alloc* alloc, - Object* o, - ObjectStack& f, - ObjectStack& collect, - size_t marked) + void sweep(Alloc* alloc, Object* o, ObjectStack& collect, size_t marked) { current_memory_used = 0; @@ -417,8 +412,8 @@ namespace verona::rt // We sweep the non-trivial ring first, as finalisers in there could refer // to other objects. The ISO object o could be deallocated by either of // these two lines. - sweep_ring(alloc, o, primary_ring, f, collect); - sweep_ring(alloc, o, primary_ring, f, collect); + sweep_ring(alloc, o, primary_ring, collect); + sweep_ring(alloc, o, primary_ring, collect); hash_set->sweep_set(alloc, marked); previous_memory_used = size_to_sizeclass(current_memory_used); @@ -429,13 +424,21 @@ namespace verona::rt * deallocated immediately. Otherwise it is added to the `gc` linked list. */ template - void sweep_object(Alloc* alloc, Object* p, Object** gc) + void sweep_object( + Alloc* alloc, + Object* p, + Object* region, + Object** gc, + ObjectStack& sub_regions) { assert( p->get_class() == Object::ISO || p->get_class() == Object::UNMARKED); if constexpr (ring == TrivialRing) { UNUSED(gc); + UNUSED(sub_regions); + UNUSED(region); + assert(p->is_trivial()); // p is about to be collected; remove the entry for it in @@ -450,7 +453,7 @@ namespace verona::rt UNUSED(alloc); assert(!p->is_trivial()); - p->finalise(); + p->finalise(region, sub_regions); // We can't deallocate the object yet, as other objects' finalisers may // look at it. We build up a linked list of all objects to delete, we'll @@ -462,11 +465,7 @@ namespace verona::rt template void sweep_ring( - Alloc* alloc, - Object* o, - RingKind primary_ring, - ObjectStack& f, - ObjectStack& collect) + Alloc* alloc, Object* o, RingKind primary_ring, ObjectStack& collect) { Object* prev = this; Object* p = ring == primary_ring ? get_next() : next_not_root; @@ -488,7 +487,7 @@ namespace verona::rt // entire region anyway. if constexpr (sweep_all == SweepAll::Yes) { - sweep_object(alloc, p, &gc); + sweep_object(alloc, p, o, &gc, collect); } else { @@ -512,7 +511,7 @@ namespace verona::rt case Object::UNMARKED: { Object* q = p->get_next(); - sweep_object(alloc, p, &gc); + sweep_object(alloc, p, o, &gc, collect); if (ring != primary_ring && prev == this) next_not_root = q; @@ -531,19 +530,9 @@ namespace verona::rt } } - // We need to collect all sub-regions and then deallocate the objects. - // Unfortunately we can't do this as a single pass, as find_iso_fields - // looks at the referenced object's header to see if it points to the same - // region or to a different one. + // Deallocate the objects, if not done in first pass. if constexpr (ring == NonTrivialRing) { - p = gc; - while (p != nullptr) - { - p->find_iso_fields(o, f, collect); - p = p->get_next(); - } - p = gc; while (p != nullptr) { @@ -556,7 +545,6 @@ namespace verona::rt else { UNUSED(o); - UNUSED(f); UNUSED(collect); } } @@ -567,15 +555,14 @@ namespace verona::rt * * Note: this does not release subregions. Use Region::release instead. **/ - void release_internal( - Alloc* alloc, Object* o, ObjectStack& f, ObjectStack& collect) + void release_internal(Alloc* alloc, Object* o, ObjectStack& collect) { assert(o->debug_is_iso()); Systematic::cout() << "Region release: trace region: " << o << std::endl; // Sweep everything, including the entrypoint. - sweep(alloc, o, f, collect, 0); + sweep(alloc, o, collect, 0); dealloc(alloc); } diff --git a/src/rt/sched/cown.h b/src/rt/sched/cown.h index 8d16309a7..fdce0dc1d 100644 --- a/src/rt/sched/cown.h +++ b/src/rt/sched/cown.h @@ -942,8 +942,10 @@ namespace verona::rt #endif Systematic::cout() << "Collecting: " << this << std::endl; + ObjectStack dummy(alloc); // Run finaliser before releasing our data. - finalise(); + // Sub-regions handled by code below. + finalise(nullptr, dummy); // Release our data. ObjectStack f(alloc); diff --git a/src/rt/test/func/cowngc4/cowngc4.cc b/src/rt/test/func/cowngc4/cowngc4.cc index f48b075e2..2b1d3146a 100644 --- a/src/rt/test/func/cowngc4/cowngc4.cc +++ b/src/rt/test/func/cowngc4/cowngc4.cc @@ -109,12 +109,10 @@ struct O : public V, region_type> st->push(cown); } - void trace_possibly_iso(ObjectStack* st) + void finaliser(Object* region, ObjectStack& sub_regions) { - if (f1 != nullptr) - st->push(f1); - if (f2 != nullptr) - st->push(f2); + Object::add_sub_region(f1, region, sub_regions); + Object::add_sub_region(f2, region, sub_regions); } }; diff --git a/src/rt/test/func/finalisers/finalisers.cc b/src/rt/test/func/finalisers/finalisers.cc index e093d8269..fe9e95a4e 100644 --- a/src/rt/test/func/finalisers/finalisers.cc +++ b/src/rt/test/func/finalisers/finalisers.cc @@ -23,8 +23,6 @@ struct C1 : public V, region_type> if (f2 != nullptr) st->push(f2); } - - // Omit trace_possibly_iso as it would make this object non-trivial. }; template @@ -52,15 +50,11 @@ class C2 : public V, region_type> st->push(f1); } - void trace_possibly_iso(ObjectStack* st) - { - trace(st); - } - - void finaliser() + void finaliser(Object* region, ObjectStack& sub_regions) { check(state == LIVE); state = FINALISED; + Object::add_sub_region(f1, region, sub_regions); } ~C2() @@ -79,7 +73,7 @@ class F1 : public V, region_type> live_count++; } - void finaliser() + void finaliser(Object*, ObjectStack&) { live_count--; logger::cout() << "Finalised" << std::endl; @@ -103,7 +97,7 @@ class F2 : public V, region_type> live_count++; } - void finaliser() + void finaliser(Object*, ObjectStack&) { live_count--; logger::cout() << "Finalised: " << id << std::endl; diff --git a/src/rt/test/func/freeze/freeze.cc b/src/rt/test/func/freeze/freeze.cc index 9911caf3a..c5baa19fc 100644 --- a/src/rt/test/func/freeze/freeze.cc +++ b/src/rt/test/func/freeze/freeze.cc @@ -25,6 +25,18 @@ struct C1 : public V if (f2 != nullptr) st->push(f2); } + + void finaliser(Object* region, ObjectStack& st) + { + if (f1 != nullptr) + { + Object::add_sub_region(f1, region, st); + } + if (f2 != nullptr) + { + Object::add_sub_region(f2, region, st); + } + } }; class Foo : public V @@ -251,18 +263,21 @@ void test4() void test5() { - // Freeze with unreachable subregion + // Freeze with unreachable subregion // Bug reported in #83 // // There are two regions, [1, 2], [3]. // - // Freeze 1, + // Freeze 1, // Ptr from 2 to subregion 3 auto* alloc = ThreadAlloc::get(); C1* o1 = new (alloc) C1; + std::cout << "o1: " << o1 << std::endl; C1* o2 = new (alloc, o1) C1; + std::cout << "o2: " << o2 << std::endl; C1* o3 = new (alloc) C1; + std::cout << "o3: " << o3 << std::endl; o2->f1 = o3; diff --git a/src/rt/test/func/memory/memory.h b/src/rt/test/func/memory/memory.h index 3b2000ef1..aeeb5a4c5 100644 --- a/src/rt/test/func/memory/memory.h +++ b/src/rt/test/func/memory/memory.h @@ -23,8 +23,6 @@ struct C1 : public V, region_type> if (f2 != nullptr) st->push(f2); } - - // Omit trace_possibly_iso as it would make this object non-trivial. }; template @@ -42,9 +40,10 @@ struct F1 : public V, region_type> st->push(f2); } - void trace_possibly_iso(ObjectStack* st) + void finaliser(Object* region, ObjectStack& sub_regions) { - trace(st); + Object::add_sub_region(f1, region, sub_regions); + Object::add_sub_region(f2, region, sub_regions); } F1() @@ -106,8 +105,6 @@ struct C3 : public V, region_type> if (f2 != nullptr) st->push(f2); } - - // Omit trace_possibly_iso as it would make this object non-trivial. }; template @@ -133,9 +130,12 @@ struct F3 : public V, region_type> st->push(f2); } - void trace_possibly_iso(ObjectStack* st) + void finaliser(Object* region, ObjectStack& sub_regions) { - trace(st); + Object::add_sub_region(c1, region, sub_regions); + Object::add_sub_region(c2, region, sub_regions); + Object::add_sub_region(f1, region, sub_regions); + Object::add_sub_region(f2, region, sub_regions); } F3() diff --git a/src/rt/test/func/memory/memory_iterator.h b/src/rt/test/func/memory/memory_iterator.h index ac2b6eb2c..0b27e69a2 100644 --- a/src/rt/test/func/memory/memory_iterator.h +++ b/src/rt/test/func/memory/memory_iterator.h @@ -28,8 +28,7 @@ namespace memory_iterator Object* t = new (alloc, o) T; all.insert(t); - if constexpr ( - has_trace_possibly_iso::value || !std::is_trivially_destructible_v) + if constexpr (!std::is_trivially_destructible_v) non_trivial.insert(t); else trivial.insert(t); diff --git a/src/rt/test/func/memory/memory_subregion.h b/src/rt/test/func/memory/memory_subregion.h index dd594f320..eb5c36565 100644 --- a/src/rt/test/func/memory/memory_subregion.h +++ b/src/rt/test/func/memory/memory_subregion.h @@ -21,9 +21,10 @@ namespace memory_subregion st->push(f2); } - void trace_possibly_iso(ObjectStack* st) + void finaliser(Object* region, ObjectStack& sub_regions) { - trace(st); + Object::add_sub_region(f1, region, sub_regions); + Object::add_sub_region(f2, region, sub_regions); } }; diff --git a/src/rt/test/func/rememberedset/rememberedset.cc b/src/rt/test/func/rememberedset/rememberedset.cc index cc34bbd12..0eeb8fa21 100644 --- a/src/rt/test/func/rememberedset/rememberedset.cc +++ b/src/rt/test/func/rememberedset/rememberedset.cc @@ -20,8 +20,6 @@ struct C1 : public V, region_type> if (f2 != nullptr) st->push(f2); } - - // trace_possibly_iso would mean this object might need finalisation! }; /** From f13b01ef6d1bdf04266160e0c30eab23ef72cfc6 Mon Sep 17 00:00:00 2001 From: Matthew Parkinson Date: Mon, 8 Jun 2020 14:17:17 +0100 Subject: [PATCH 3/3] Use ObjectStack& --- src/interpreter/object.cc | 2 +- src/interpreter/object.h | 6 ++-- src/interpreter/value.cc | 6 ++-- src/interpreter/value.h | 4 +-- src/rt/cpp/vaction.h | 4 +-- src/rt/cpp/vobject.h | 4 +-- src/rt/object/object.h | 4 +-- src/rt/region/externalreference.h | 2 +- src/rt/sched/action.h | 4 +-- src/rt/sched/noticeboard.h | 6 ++-- .../test/func/cown_weak_ref/cown_weak_ref.cc | 6 ++-- src/rt/test/func/cowngc1/cowngc1.cc | 24 +++++++------- src/rt/test/func/cowngc2/cowngc2.cpp | 4 +-- src/rt/test/func/cowngc3/cowngc3.cc | 8 ++--- src/rt/test/func/cowngc4/cowngc4.cc | 28 ++++++++-------- .../func/diningphilosophers/diningphil.cc | 12 +++---- src/rt/test/func/ext_ref/ext_ref_basic.h | 10 +++--- src/rt/test/func/ext_ref/ext_ref_merge.h | 4 +-- .../func/ext_ref_freeze/ext_ref_freeze.cc | 10 +++--- src/rt/test/func/finalisers/finalisers.cc | 10 +++--- src/rt/test/func/freeze/freeze.cc | 16 +++++----- src/rt/test/func/memory/memory.h | 32 +++++++++---------- src/rt/test/func/memory/memory_subregion.h | 6 ++-- src/rt/test/func/multimessage/multimessage.cc | 6 ++-- .../test/func/noticeboard/noticeboard_basic.h | 14 ++++---- .../test/func/noticeboard/noticeboard_weak.h | 2 +- src/rt/test/func/notify/notify_coalesce.h | 4 +-- src/rt/test/func/notify/notify_interleave.h | 4 +-- .../test/func/rememberedset/rememberedset.cc | 6 ++-- src/rt/test/perf/linkedlist/linkedlist.cc | 6 ++-- 30 files changed, 127 insertions(+), 127 deletions(-) diff --git a/src/interpreter/object.cc b/src/interpreter/object.cc index 11fd96c24..6e1945785 100644 --- a/src/interpreter/object.cc +++ b/src/interpreter/object.cc @@ -60,7 +60,7 @@ namespace verona::interpreter } } - void VMObject::trace_fn(const rt::Object* base_object, rt::ObjectStack* stack) + void VMObject::trace_fn(const rt::Object* base_object, rt::ObjectStack& stack) { const VMObject* object = static_cast(base_object); const VMDescriptor* descriptor = object->descriptor(); diff --git a/src/interpreter/object.h b/src/interpreter/object.h index 52fa9f62d..98bd0a003 100644 --- a/src/interpreter/object.h +++ b/src/interpreter/object.h @@ -43,7 +43,7 @@ namespace verona::interpreter VMObject* region(); - static void trace_fn(const rt::Object* base_object, rt::ObjectStack* stack); + static void trace_fn(const rt::Object* base_object, rt::ObjectStack& stack); static void finaliser_fn( rt::Object* base_object, rt::Object* region, @@ -88,10 +88,10 @@ namespace verona::interpreter rt::VCown::schedule(); } - void trace(rt::ObjectStack* stack) + void trace(rt::ObjectStack& stack) { if (contents != nullptr) - stack->push(contents); + stack.push(contents); } }; } diff --git a/src/interpreter/value.cc b/src/interpreter/value.cc index b1825db56..202e0b16d 100644 --- a/src/interpreter/value.cc +++ b/src/interpreter/value.cc @@ -297,18 +297,18 @@ namespace verona::interpreter return result; } - void FieldValue::trace(rt::ObjectStack* stack) const + void FieldValue::trace(rt::ObjectStack& stack) const { switch (tag) { case Value::ISO: case Value::MUT: case Value::IMM: - stack->push(inner.object); + stack.push(inner.object); break; case Value::COWN: - stack->push(inner.cown); + stack.push(inner.cown); break; case Value::UNINIT: diff --git a/src/interpreter/value.h b/src/interpreter/value.h index 7fb24da82..d55c49ed6 100644 --- a/src/interpreter/value.h +++ b/src/interpreter/value.h @@ -145,7 +145,7 @@ namespace verona::interpreter return &inner; } - void trace(rt::ObjectStack* stack) const; + void trace(rt::ObjectStack& stack) const; static constexpr Tag UNINIT = Tag::UNINIT; static constexpr Tag ISO = Tag::ISO; @@ -190,7 +190,7 @@ namespace verona::interpreter */ Value exchange(rt::Alloc* alloc, rt::Object* region, Value&& value); - void trace(rt::ObjectStack* stack) const; + void trace(rt::ObjectStack& stack) const; /** * If this Value contains an ISO, then add it to the stack diff --git a/src/rt/cpp/vaction.h b/src/rt/cpp/vaction.h index 6435a23d8..06fc4a8d8 100644 --- a/src/rt/cpp/vaction.h +++ b/src/rt/cpp/vaction.h @@ -27,7 +27,7 @@ namespace verona::rt friend class Cown; private: - static void gc_trace(const Action* msg, ObjectStack* st) + static void gc_trace(const Action* msg, ObjectStack& st) { (static_cast(msg))->trace(st); } @@ -51,7 +51,7 @@ namespace verona::rt return &desc; } - void trace(ObjectStack*) const {} + void trace(ObjectStack&) const {} public: VAction() : Action(desc()) diff --git a/src/rt/cpp/vobject.h b/src/rt/cpp/vobject.h index 564db8a6c..edd87ef4c 100644 --- a/src/rt/cpp/vobject.h +++ b/src/rt/cpp/vobject.h @@ -57,7 +57,7 @@ namespace verona::rt using RegionClass = typename RegionType_to_class::T; - static void gc_trace(const Object* o, ObjectStack* st) + static void gc_trace(const Object* o, ObjectStack& st) { ((T*)o)->trace(st); } @@ -91,7 +91,7 @@ namespace verona::rt return &desc; } - void trace(ObjectStack*) {} + void trace(ObjectStack&) {} static EpochMark get_alloc_epoch() { diff --git a/src/rt/object/object.h b/src/rt/object/object.h index 282185805..b722cf165 100644 --- a/src/rt/object/object.h +++ b/src/rt/object/object.h @@ -85,7 +85,7 @@ namespace verona::rt { // for field in o do // st.push(o.field) - using TraceFunction = void (*)(const Object* o, ObjectStack* st); + using TraceFunction = void (*)(const Object* o, ObjectStack& st); using NotifiedFunction = void (*)(Object* o); @@ -723,7 +723,7 @@ namespace verona::rt private: inline void trace(ObjectStack& f) const { - get_descriptor()->trace(this, &f); + get_descriptor()->trace(this, f); } inline void finalise(Object* region, ObjectStack& isos) diff --git a/src/rt/region/externalreference.h b/src/rt/region/externalreference.h index f40f8785b..08576a9e1 100644 --- a/src/rt/region/externalreference.h +++ b/src/rt/region/externalreference.h @@ -33,7 +33,7 @@ namespace verona::rt // The object externally referred to Object* o; - static void gc_trace(const Object*, ObjectStack*) {} + static void gc_trace(const Object*, ObjectStack&) {} static const Descriptor* desc() { diff --git a/src/rt/sched/action.h b/src/rt/sched/action.h index c031c69ff..ab6d1433c 100644 --- a/src/rt/sched/action.h +++ b/src/rt/sched/action.h @@ -31,7 +31,7 @@ namespace verona::rt struct alignas(descriptor_alignment) Descriptor { using Function = void (*)(Action*); - using TraceFunction = void (*)(const Action*, ObjectStack*); + using TraceFunction = void (*)(const Action*, ObjectStack&); size_t size; @@ -69,7 +69,7 @@ namespace verona::rt inline void trace(ObjectStack& st) { - get_descriptor()->trace(this, &st); + get_descriptor()->trace(this, st); } inline const Descriptor* get_descriptor() diff --git a/src/rt/sched/noticeboard.h b/src/rt/sched/noticeboard.h index 1df3efef6..032fa14e8 100644 --- a/src/rt/sched/noticeboard.h +++ b/src/rt/sched/noticeboard.h @@ -22,19 +22,19 @@ namespace verona::rt put(content_); } - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if constexpr (!std::is_fundamental_v) { #ifdef USE_SYSTEMATIC_TESTING_WEAK_NOTICEBOARDS for (auto p : update_buffer) { - st->push((T)p); + st.push((T)p); } #endif auto p = get(); if (p) - st->push(p); + st.push(p); } else { diff --git a/src/rt/test/func/cown_weak_ref/cown_weak_ref.cc b/src/rt/test/func/cown_weak_ref/cown_weak_ref.cc index 57c955710..76c53e886 100644 --- a/src/rt/test/func/cown_weak_ref/cown_weak_ref.cc +++ b/src/rt/test/func/cown_weak_ref/cown_weak_ref.cc @@ -26,12 +26,12 @@ struct MyCown : VCown size_t up_count = 0; - void trace(ObjectStack* os) const + void trace(ObjectStack& os) const { if (left != nullptr) - os->push(left); + os.push(left); if (right != nullptr) - os->push(right); + os.push(right); // Do not push parent, as this is a weak reference. } diff --git a/src/rt/test/func/cowngc1/cowngc1.cc b/src/rt/test/func/cowngc1/cowngc1.cc index d722ef40d..674054525 100644 --- a/src/rt/test/func/cowngc1/cowngc1.cc +++ b/src/rt/test/func/cowngc1/cowngc1.cc @@ -86,10 +86,10 @@ struct CCown : public VCown CCown* child; CCown(CCown* child_) : child(child_) {} - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { if (child != nullptr) - fields->push(child); + fields.push(child); } }; @@ -99,12 +99,12 @@ struct O : public V, region_type> O* f1 = nullptr; CCown* cown = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f1 != nullptr) - st->push(f1); + st.push(f1); if (cown != nullptr) - st->push(cown); + st.push(cown); } }; using OTrace = O; @@ -216,28 +216,28 @@ struct RCown : public VCown Systematic::cout() << " next " << next << std::endl; } - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { for (uint64_t i = 0; i < others_count; i++) { if (array[i] != nullptr) - fields->push(array[i]); + fields.push(array[i]); } if (otrace != nullptr) - fields->push(otrace); + fields.push(otrace); if (oarena != nullptr) - fields->push(oarena); + fields.push(oarena); if (imm1 != nullptr) - fields->push(imm1); + fields.push(imm1); if (imm2 != nullptr) - fields->push(imm2); + fields.push(imm2); assert(next != nullptr); - fields->push(next); + fields.push(next); } }; diff --git a/src/rt/test/func/cowngc2/cowngc2.cpp b/src/rt/test/func/cowngc2/cowngc2.cpp index 470733684..cfcd6948f 100644 --- a/src/rt/test/func/cowngc2/cowngc2.cpp +++ b/src/rt/test/func/cowngc2/cowngc2.cpp @@ -7,10 +7,10 @@ struct CCown : public VCown CCown* child; CCown(CCown* child_) : child(child_) {} - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { if (child != nullptr) - fields->push(child); + fields.push(child); } }; diff --git a/src/rt/test/func/cowngc3/cowngc3.cc b/src/rt/test/func/cowngc3/cowngc3.cc index 5ffe413ef..615654c61 100644 --- a/src/rt/test/func/cowngc3/cowngc3.cc +++ b/src/rt/test/func/cowngc3/cowngc3.cc @@ -41,7 +41,7 @@ struct MyCown : public VCown { MyCown() {} - void trace(ObjectStack*) {} + void trace(ObjectStack&) {} }; /** @@ -62,7 +62,7 @@ struct Ping : public VAction Systematic::cout() << "Ping on " << c << std::endl; } - void trace(ObjectStack*) const {} + void trace(ObjectStack&) const {} }; void noise() @@ -131,10 +131,10 @@ struct M2 : public VAction } } - void trace(ObjectStack* ob) const + void trace(ObjectStack& ob) const { if (keep_alive != nullptr) - ob->push(keep_alive); + ob.push(keep_alive); } }; diff --git a/src/rt/test/func/cowngc4/cowngc4.cc b/src/rt/test/func/cowngc4/cowngc4.cc index 2b1d3146a..8279baa00 100644 --- a/src/rt/test/func/cowngc4/cowngc4.cc +++ b/src/rt/test/func/cowngc4/cowngc4.cc @@ -70,10 +70,10 @@ struct CCown : public VCown CCown* child; CCown(CCown* child_) : child(child_) {} - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { if (child != nullptr) - fields->push(child); + fields.push(child); } }; @@ -93,20 +93,20 @@ struct O : public V, region_type> O* imm2 = nullptr; CCown* cown = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f != nullptr) - st->push(f); + st.push(f); if (f1 != nullptr) - st->push(f1); + st.push(f1); if (f2 != nullptr) - st->push(f2); + st.push(f2); if (imm1 != nullptr) - st->push(imm1); + st.push(imm1); if (imm2 != nullptr) - st->push(imm2); + st.push(imm2); if (cown != nullptr) - st->push(cown); + st.push(cown); } void finaliser(Object* region, ObjectStack& sub_regions) @@ -244,19 +244,19 @@ struct RCown : public VCown> Systematic::cout() << " next " << next << std::endl; } - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { if (reg_with_graph != nullptr) - fields->push(reg_with_graph); + fields.push(reg_with_graph); if (reg_with_sub != nullptr) - fields->push(reg_with_sub); + fields.push(reg_with_sub); if (reg_with_imm != nullptr) - fields->push(reg_with_imm); + fields.push(reg_with_imm); assert(next != nullptr); - fields->push(next); + fields.push(next); } }; diff --git a/src/rt/test/func/diningphilosophers/diningphil.cc b/src/rt/test/func/diningphilosophers/diningphil.cc index b93649b96..be859d4c9 100644 --- a/src/rt/test/func/diningphilosophers/diningphil.cc +++ b/src/rt/test/func/diningphilosophers/diningphil.cc @@ -40,9 +40,9 @@ struct KeepAlive : public VAction Cown::schedule(c); } - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { - fields->push(c); + fields.push(c); } void f() @@ -61,11 +61,11 @@ struct Philosopher : public VCown : id(id_), forks(forks_), to_eat(to_eat_) {} - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { for (auto f : forks) { - fields->push(f); + fields.push(f); } } }; @@ -109,10 +109,10 @@ struct Eat : public VAction << p_->id << " " << p_ << std::endl; } - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { Systematic::cout() << "Calling custom trace" << std::endl; - fields->push(eater); + fields.push(eater); } }; diff --git a/src/rt/test/func/ext_ref/ext_ref_basic.h b/src/rt/test/func/ext_ref/ext_ref_basic.h index 895d4dbed..40f779753 100644 --- a/src/rt/test/func/ext_ref/ext_ref_basic.h +++ b/src/rt/test/func/ext_ref/ext_ref_basic.h @@ -44,12 +44,12 @@ namespace ext_ref_basic ext_node_alias = ExternalRef::create(region, node); } - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { assert(ext_node); - st->push(ext_node); + st.push(ext_node); assert(ext_node_alias); - st->push(ext_node_alias); + st.push(ext_node_alias); } }; @@ -102,10 +102,10 @@ namespace ext_ref_basic A(DList* list_) : list{list_} {} - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { assert(list); - st->push(list); + st.push(list); } }; diff --git a/src/rt/test/func/ext_ref/ext_ref_merge.h b/src/rt/test/func/ext_ref/ext_ref_merge.h index 326fb832f..f03ec7df6 100644 --- a/src/rt/test/func/ext_ref/ext_ref_merge.h +++ b/src/rt/test/func/ext_ref/ext_ref_merge.h @@ -11,10 +11,10 @@ namespace ext_ref_merge struct C : public V, region_type> { C* f1 = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f1 != nullptr) - st->push(f1); + st.push(f1); } }; diff --git a/src/rt/test/func/ext_ref_freeze/ext_ref_freeze.cc b/src/rt/test/func/ext_ref_freeze/ext_ref_freeze.cc index 9d57ae692..f2e551a15 100644 --- a/src/rt/test/func/ext_ref_freeze/ext_ref_freeze.cc +++ b/src/rt/test/func/ext_ref_freeze/ext_ref_freeze.cc @@ -16,12 +16,12 @@ struct C : public V { C* f1 = nullptr; B* b = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f1 != nullptr) - st->push(f1); + st.push(f1); if (b != nullptr) - st->push(b); + st.push(b); } }; @@ -49,10 +49,10 @@ struct A : public VCown int advance_epoch_count = 100; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (r != nullptr) - st->push(r); + st.push(r); } }; diff --git a/src/rt/test/func/finalisers/finalisers.cc b/src/rt/test/func/finalisers/finalisers.cc index fe9e95a4e..c98453eeb 100644 --- a/src/rt/test/func/finalisers/finalisers.cc +++ b/src/rt/test/func/finalisers/finalisers.cc @@ -15,13 +15,13 @@ struct C1 : public V, region_type> C1* f1 = nullptr; C1* f2 = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f1 != nullptr) - st->push(f1); + st.push(f1); if (f2 != nullptr) - st->push(f2); + st.push(f2); } }; @@ -41,13 +41,13 @@ class C2 : public V, region_type> C2() : state(LIVE) {} - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { // Tracing should never happen after destruction check(state == LIVE || state == FINALISED); if (f1 != nullptr) - st->push(f1); + st.push(f1); } void finaliser(Object* region, ObjectStack& sub_regions) diff --git a/src/rt/test/func/freeze/freeze.cc b/src/rt/test/func/freeze/freeze.cc index c5baa19fc..1b4489706 100644 --- a/src/rt/test/func/freeze/freeze.cc +++ b/src/rt/test/func/freeze/freeze.cc @@ -17,13 +17,13 @@ struct C1 : public V C1* f1 = nullptr; C1* f2 = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f1 != nullptr) - st->push(f1); + st.push(f1); if (f2 != nullptr) - st->push(f2); + st.push(f2); } void finaliser(Object* region, ObjectStack& st) @@ -70,13 +70,13 @@ class List : public V> } // Required by the library; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (head != nullptr) - st->push(head); + st.push(head); if (tail != nullptr) - st->push(tail); + st.push(tail); } }; @@ -320,11 +320,11 @@ struct Symbolic : public V size_t id; std::vector fields; - void trace(ObjectStack* s) const + void trace(ObjectStack& s) const { for (auto o : fields) { - s->push(o); + s.push(o); } } }; diff --git a/src/rt/test/func/memory/memory.h b/src/rt/test/func/memory/memory.h index aeeb5a4c5..6bcb9034f 100644 --- a/src/rt/test/func/memory/memory.h +++ b/src/rt/test/func/memory/memory.h @@ -15,13 +15,13 @@ struct C1 : public V, region_type> C1* f1 = nullptr; C1* f2 = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f1 != nullptr) - st->push(f1); + st.push(f1); if (f2 != nullptr) - st->push(f2); + st.push(f2); } }; @@ -31,13 +31,13 @@ struct F1 : public V, region_type> F1* f1 = nullptr; F1* f2 = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f1 != nullptr) - st->push(f1); + st.push(f1); if (f2 != nullptr) - st->push(f2); + st.push(f2); } void finaliser(Object* region, ObjectStack& sub_regions) @@ -91,19 +91,19 @@ struct C3 : public V, region_type> F3* f1 = nullptr; F3* f2 = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (c1 != nullptr) - st->push(c1); + st.push(c1); if (c2 != nullptr) - st->push(c2); + st.push(c2); if (f1 != nullptr) - st->push(f1); + st.push(f1); if (f2 != nullptr) - st->push(f2); + st.push(f2); } }; @@ -115,19 +115,19 @@ struct F3 : public V, region_type> F3* f1 = nullptr; F3* f2 = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (c1 != nullptr) - st->push(c1); + st.push(c1); if (c2 != nullptr) - st->push(c2); + st.push(c2); if (f1 != nullptr) - st->push(f1); + st.push(f1); if (f2 != nullptr) - st->push(f2); + st.push(f2); } void finaliser(Object* region, ObjectStack& sub_regions) diff --git a/src/rt/test/func/memory/memory_subregion.h b/src/rt/test/func/memory/memory_subregion.h index eb5c36565..62eba39df 100644 --- a/src/rt/test/func/memory/memory_subregion.h +++ b/src/rt/test/func/memory/memory_subregion.h @@ -12,13 +12,13 @@ namespace memory_subregion O* f1 = nullptr; O* f2 = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f1 != nullptr) - st->push(f1); + st.push(f1); if (f2 != nullptr) - st->push(f2); + st.push(f2); } void finaliser(Object* region, ObjectStack& sub_regions) diff --git a/src/rt/test/func/multimessage/multimessage.cc b/src/rt/test/func/multimessage/multimessage.cc index 0082dc6cd..16042b0b5 100644 --- a/src/rt/test/func/multimessage/multimessage.cc +++ b/src/rt/test/func/multimessage/multimessage.cc @@ -45,10 +45,10 @@ void test_multimessage(size_t cores) logger::cout() << "result = " << (a->i + b->i) << std::endl; } - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { - st->push(a); - st->push(b); + st.push(a); + st.push(b); } }; diff --git a/src/rt/test/func/noticeboard/noticeboard_basic.h b/src/rt/test/func/noticeboard/noticeboard_basic.h index e36de768e..b7dd7a89a 100644 --- a/src/rt/test/func/noticeboard/noticeboard_basic.h +++ b/src/rt/test/func/noticeboard/noticeboard_basic.h @@ -31,12 +31,12 @@ namespace noticeboard_basic C(int x_) : x(x_) {} - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (next != nullptr) - st->push(next); + st.push(next); if (alive != nullptr) - st->push(alive); + st.push(alive); } }; @@ -54,7 +54,7 @@ namespace noticeboard_basic #endif } - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { box.trace(fields); } @@ -82,14 +82,14 @@ namespace noticeboard_basic Peeker(DB* db_, Noticeboard* box_) : db(db_), box(box_) {} - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { if (alive != nullptr) { - fields->push(alive); + fields.push(alive); } assert(db); - fields->push(db); + fields.push(db); } }; diff --git a/src/rt/test/func/noticeboard/noticeboard_weak.h b/src/rt/test/func/noticeboard/noticeboard_weak.h index 0e8b4eaf0..b5cf4c6f6 100644 --- a/src/rt/test/func/noticeboard/noticeboard_weak.h +++ b/src/rt/test/func/noticeboard/noticeboard_weak.h @@ -24,7 +24,7 @@ namespace noticeboard_weak #endif } - void trace(ObjectStack* fields) const + void trace(ObjectStack& fields) const { box_0.trace(fields); box_1.trace(fields); diff --git a/src/rt/test/func/notify/notify_coalesce.h b/src/rt/test/func/notify/notify_coalesce.h index 164e7ff45..e8cae60b7 100644 --- a/src/rt/test/func/notify/notify_coalesce.h +++ b/src/rt/test/func/notify/notify_coalesce.h @@ -37,10 +37,10 @@ namespace notify_coalesce B(A* a_) : a{a_} {} - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { assert(a); - st->push(a); + st.push(a); } }; diff --git a/src/rt/test/func/notify/notify_interleave.h b/src/rt/test/func/notify/notify_interleave.h index bc28ce7e3..67fa0d302 100644 --- a/src/rt/test/func/notify/notify_interleave.h +++ b/src/rt/test/func/notify/notify_interleave.h @@ -35,10 +35,10 @@ namespace notify_interleave B(A* a_) : a{a_} {} - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { assert(a); - st->push(a); + st.push(a); } }; diff --git a/src/rt/test/func/rememberedset/rememberedset.cc b/src/rt/test/func/rememberedset/rememberedset.cc index 0eeb8fa21..847ff8d06 100644 --- a/src/rt/test/func/rememberedset/rememberedset.cc +++ b/src/rt/test/func/rememberedset/rememberedset.cc @@ -12,13 +12,13 @@ struct C1 : public V, region_type> C1* f1 = nullptr; C1* f2 = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f1 != nullptr) - st->push(f1); + st.push(f1); if (f2 != nullptr) - st->push(f2); + st.push(f2); } }; diff --git a/src/rt/test/perf/linkedlist/linkedlist.cc b/src/rt/test/perf/linkedlist/linkedlist.cc index 5b7fab039..5085ce0fa 100644 --- a/src/rt/test/perf/linkedlist/linkedlist.cc +++ b/src/rt/test/perf/linkedlist/linkedlist.cc @@ -13,13 +13,13 @@ struct C1 : public V C1* f1 = nullptr; C1* f2 = nullptr; - void trace(ObjectStack* st) const + void trace(ObjectStack& st) const { if (f1 != nullptr) - st->push(f1); + st.push(f1); if (f2 != nullptr) - st->push(f2); + st.push(f2); } };