Commit 5e89ecb7 authored by Rudi Chen's avatar Rudi Chen

Add infrastructure to call GC handler on stack-bound objects.

parent e44735cf
......@@ -56,6 +56,8 @@ private:
bool saved;
ucontext_t ucontext;
std::deque<gc::GCVisitable*> gc_objs_stacks;
public:
void* stack_start;
......@@ -99,6 +101,13 @@ public:
ucontext_t* getContext() { return &ucontext; }
void pushGCObject(gc::GCVisitable* obj) { gc_objs_stacks.push_back(obj); }
void popGCObject(gc::GCVisitable* obj) {
ASSERT(gc_objs_stacks.back() == obj, "push/pop of stack-bound object out of order");
gc_objs_stacks.pop_back();
}
void pushGenerator(BoxedGenerator* g, void* new_stack_start, void* old_stack_limit) {
previous_stacks.emplace_back(g, this->stack_start, old_stack_limit);
this->stack_start = new_stack_start;
......@@ -132,6 +141,10 @@ public:
v->visitPotentialRange((void**)stack_info.stack_start, (void**)stack_info.stack_limit);
#endif
}
for (auto& obj : gc_objs_stacks) {
obj->gc_visit(v);
}
}
};
static std::unordered_map<pthread_t, ThreadStateInternal*> current_threads;
......@@ -149,6 +162,14 @@ void popGenerator() {
current_internal_thread_state->popGenerator();
}
void pushGCObject(gc::GCVisitable* obj) {
current_internal_thread_state->pushGCObject(obj);
}
void popGCObject(gc::GCVisitable* obj) {
current_internal_thread_state->popGCObject(obj);
}
// These are guarded by threading_lock
static int signals_waiting(0);
static gc::GCVisitor* cur_visitor = NULL;
......
......@@ -31,6 +31,7 @@ class BoxedGenerator;
namespace gc {
class GCVisitor;
class GCVisitable;
}
#if ENABLE_SAMPLING_PROFILER
......@@ -61,6 +62,8 @@ void visitAllStacks(gc::GCVisitor* v);
void pushGenerator(BoxedGenerator* g, void* new_stack_start, void* old_stack_limit);
void popGenerator();
void pushGCObject(gc::GCVisitable* obj);
void popGCObject(gc::GCVisitable* obj);
#ifndef THREADING_USE_GIL
#define THREADING_USE_GIL 1
......
......@@ -128,16 +128,58 @@ bool isValidGCMemory(void* p);
// Whether p is valid gc memory and is set to have Python destructor semantics applied
bool isValidGCObject(void* p);
// Situation: Sometimes, we allocate an object on the stack (e.g. ASTInterpreter) who fields may be pointers
// to objects in the Pyston heap. These pointers need to be scanned by the GC. Since the GC scans the entire
// stack conservatively, these fields will be scanned. However, it is also possible that the stack-allocated
// object points to a non-Pyston heap object which contains pointers to Pyston heap objects. In that case, the
// conservative scanner won't get to those pointers.
//
// As such, objects who contain pointers to pointers to Pyston heap objects need a GC handler function.
// Runtime objects who need to be visited by the GC should inherit from this.
class GCVisitable {
public:
virtual ~GCVisitable() = default;
virtual void gc_visit(GCVisitor* visitor) = 0;
};
// Use this if a C++ object needs to be allocated in our heap.
class GCAllocatedRuntime {
class GCAllocatedRuntime : public GCVisitable {
public:
virtual ~GCAllocatedRuntime() {}
virtual ~GCAllocatedRuntime() = default;
void* operator new(size_t size) __attribute__((visibility("default"))) { return gc_alloc(size, GCKind::RUNTIME); }
void operator delete(void* ptr) __attribute__((visibility("default"))) { gc_free(ptr); }
virtual void gc_visit(GCVisitor* visitor) = 0;
};
// This is a way to call gc_visit on objects whose lifetime is bound to the stack,
// but may be contained within a unique_ptr or some other container.
class ScanningHandle {
GCVisitable* obj;
public:
void push();
void pop();
ScanningHandle(GCVisitable* obj) : obj(obj) {
#if MOVING_GC
if (obj) {
push();
}
#endif
}
~ScanningHandle() {
#if MOVING_GC
if (obj) {
pop();
}
#endif
}
};
} // namespace gc
}
......
......@@ -45,6 +45,14 @@ template <> void return_temporary_buffer<pyston::Box*>(pyston::Box** p) {
namespace pyston {
namespace gc {
void ScanningHandle::push() {
threading::pushGCObject(obj);
}
void ScanningHandle::pop() {
threading::popGCObject(obj);
}
bool _doFree(GCAllocation* al, std::vector<Box*>* weakly_referenced);
// lots of linked lists around here, so let's just use template functions for operations on them.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment