Commit 03cd0cbc authored by Rudi Chen's avatar Rudi Chen

Make gc visitors (gcHandler) static methods on the type being visited.

This serves two purposes.
1) Improve naming consistency (follow the format TYPENAME::gcHandler)
2) In the source file, the visit function declaration is closer to the
   fields of the objects. If a field is added, hopefully it will be
   easier to remember to update the GC visit function.
parent 7ca763c7
......@@ -682,7 +682,24 @@ extern "C" Box* dictInit(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
return None;
}
static void BoxedDictIterator:::gcHandler(GCVisitor* v, Box* b) {
void BoxedDict::gcHandler(GCVisitor* v, Box* b) {
assert(isSubclass(b->cls, dict_cls));
boxGCHandler(v, b);
BoxedDict* d = (BoxedDict*)b;
// This feels like a cludge, but we need to find anything that
// the unordered_map might have allocated.
// Another way to handle this would be to rt_alloc the unordered_map
// as well, though that incurs extra memory dereferences which would
// be nice to avoid.
void** start = (void**)&d->d;
void** end = start + (sizeof(d->d) / 8);
v->visitPotentialRange(start, end);
}
void BoxedDictIterator::gcHandler(GCVisitor* v, Box* b) {
assert(b->cls == dict_iterator_cls);
boxGCHandler(v, b);
......@@ -690,7 +707,7 @@ static void BoxedDictIterator:::gcHandler(GCVisitor* v, Box* b) {
v->visit(it->d);
}
static void BoxedDictView::gcHandler(GCVisitor* v, Box* b) {
void BoxedDictView::gcHandler(GCVisitor* v, Box* b) {
assert(b->cls == dict_items_cls);
boxGCHandler(v, b);
......@@ -723,12 +740,12 @@ void setupDict() {
dict_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedDictIterator::gcHandler, 0, 0,
sizeof(BoxedDictIterator), false, "dictionary-itemiterator");
dict_keys_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedDictView::gcHandler, 0, 0, sizeof(BoxedDictView), false,
"dict_keys");
dict_values_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedDictView::gcHandler, 0, 0, sizeof(BoxedDictView),
false, "dict_values");
dict_items_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedDictView::gcHandler, 0, 0, sizeof(BoxedDictView),
false, "dict_items");
dict_keys_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedDictView::gcHandler, 0, 0, sizeof(BoxedDictView),
false, "dict_keys");
dict_values_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedDictView::gcHandler, 0, 0,
sizeof(BoxedDictView), false, "dict_values");
dict_items_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedDictView::gcHandler, 0, 0,
sizeof(BoxedDictView), false, "dict_items");
dict_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)dictLen, BOXED_INT, 1)));
dict_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)dictNew, UNKNOWN, 1, 0, true, true)));
......
......@@ -378,7 +378,7 @@ extern "C" BoxedGenerator::BoxedGenerator(BoxedFunctionBase* function, Box* arg1
context = makeContext(stack_begin, (void (*)(intptr_t))generatorEntry);
}
extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
void BoxedGenerator::gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedGenerator* g = (BoxedGenerator*)b;
......@@ -434,8 +434,8 @@ void generatorDestructor(Box* b) {
void setupGenerator() {
generator_cls
= BoxedHeapClass::create(type_cls, object_cls, &generatorGCHandler, 0, offsetof(BoxedGenerator, weakreflist),
sizeof(BoxedGenerator), false, "generator");
= BoxedHeapClass::create(type_cls, object_cls, &BoxedGenerator::gcHandler, 0,
offsetof(BoxedGenerator, weakreflist), sizeof(BoxedGenerator), false, "generator");
generator_cls->tp_dealloc = generatorDestructor;
generator_cls->has_safe_tp_dealloc = true;
generator_cls->giveAttr("__iter__",
......
......@@ -118,7 +118,7 @@ public:
return boxInt(xrangeIteratorNextUnboxed(s));
}
static void xrangeIteratorGCHandler(GCVisitor* v, Box* b) {
static void gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedXrangeIterator* it = (BoxedXrangeIterator*)b;
......@@ -195,8 +195,8 @@ Box* xrangeLen(Box* self) {
void setupXrange() {
xrange_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedXrange), false, "xrange");
xrange_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedXrangeIterator::xrangeIteratorGCHandler, 0,
0, sizeof(BoxedXrangeIterator), false, "rangeiterator");
xrange_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedXrangeIterator::gcHandler, 0, 0,
sizeof(BoxedXrangeIterator), false, "rangeiterator");
xrange_cls->giveAttr(
"__new__",
......
......@@ -112,7 +112,7 @@ Box* seqiterNext(Box* s) {
return r;
}
static void seqiterGCVisit(GCVisitor* v, Box* b) {
void BoxedSeqIter::gcHandler(GCVisitor* v, Box* b) {
assert(b->cls == seqiter_cls || b->cls == seqreviter_cls);
boxGCHandler(v, b);
......@@ -122,7 +122,7 @@ static void seqiterGCVisit(GCVisitor* v, Box* b) {
v->visit(si->next);
}
static void iterwrapperGCVisit(GCVisitor* v, Box* b) {
void BoxedIterWrapper::gcHandler(GCVisitor* v, Box* b) {
assert(b->cls == iterwrapper_cls);
boxGCHandler(v, b);
......@@ -182,8 +182,8 @@ bool calliter_hasnext(Box* b) {
void setupIter() {
seqiter_cls
= BoxedHeapClass::create(type_cls, object_cls, seqiterGCVisit, 0, 0, sizeof(BoxedSeqIter), false, "iterator");
seqiter_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedSeqIter::gcHandler, 0, 0, sizeof(BoxedSeqIter),
false, "iterator");
seqiter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)seqiterNext, UNKNOWN, 1)));
seqiter_cls->giveAttr("__hasnext__", new BoxedFunction(boxRTFunction((void*)seqiterHasnext, BOXED_BOOL, 1)));
......@@ -192,8 +192,8 @@ void setupIter() {
seqiter_cls->freeze();
seqiter_cls->tpp_hasnext = seqiterHasnextUnboxed;
seqreviter_cls
= BoxedHeapClass::create(type_cls, object_cls, seqiterGCVisit, 0, 0, sizeof(BoxedSeqIter), false, "reversed");
seqreviter_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedSeqIter::gcHandler, 0, 0, sizeof(BoxedSeqIter),
false, "reversed");
seqreviter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)seqiterNext, UNKNOWN, 1)));
seqreviter_cls->giveAttr("__hasnext__", new BoxedFunction(boxRTFunction((void*)seqreviterHasnext, BOXED_BOOL, 1)));
......@@ -201,8 +201,8 @@ void setupIter() {
seqreviter_cls->freeze();
iterwrapper_cls = BoxedHeapClass::create(type_cls, object_cls, iterwrapperGCVisit, 0, 0, sizeof(BoxedIterWrapper),
false, "iterwrapper");
iterwrapper_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedIterWrapper::gcHandler, 0, 0,
sizeof(BoxedIterWrapper), false, "iterwrapper");
iterwrapper_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)iterwrapperNext, UNKNOWN, 1)));
iterwrapper_cls->giveAttr("__hasnext__",
......
......@@ -36,6 +36,8 @@ public:
BoxedSeqIter(Box* b, int64_t start) : b(b), idx(start), next(NULL) {}
DEFAULT_CLASS(seqiter_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
extern BoxedClass* iterwrapper_cls;
......@@ -49,6 +51,8 @@ public:
BoxedIterWrapper(Box* iter) : iter(iter), next(NULL) {}
DEFAULT_CLASS(iterwrapper_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
bool calliter_hasnext(Box* b);
......
......@@ -917,12 +917,6 @@ Box* listRemove(BoxedList* self, Box* elt) {
BoxedClass* list_iterator_cls = NULL;
BoxedClass* list_reverse_iterator_cls = NULL;
extern "C" void listIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedListIterator* it = (BoxedListIterator*)b;
v->visit(it->l);
}
Box* listNew(BoxedClass* cls, Box* container) {
assert(isSubclass(cls->cls, type_cls));
assert(isSubclass(cls, list_cls));
......@@ -1097,10 +1091,31 @@ extern "C" int PyList_SetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, P
}
}
void BoxedListIterator::gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedListIterator* it = (BoxedListIterator*)b;
v->visit(it->l);
}
void BoxedList::gcHandler(GCVisitor* v, Box* b) {
assert(isSubclass(b->cls, list_cls));
boxGCHandler(v, b);
BoxedList* l = (BoxedList*)b;
int size = l->size;
int capacity = l->capacity;
assert(capacity >= size);
if (capacity)
v->visit(l->elts);
if (size)
v->visitRange((void**)&l->elts->elts[0], (void**)&l->elts->elts[size]);
}
void setupList() {
list_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &listIteratorGCHandler, 0, 0,
list_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedListIterator::gcHandler, 0, 0,
sizeof(BoxedListIterator), false, "listiterator");
list_reverse_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &listIteratorGCHandler, 0, 0,
list_reverse_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedListIterator::gcHandler, 0, 0,
sizeof(BoxedListIterator), false, "listreverseiterator");
list_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)listLen, BOXED_INT, 1)));
......
......@@ -29,6 +29,8 @@ public:
BoxedListIterator(BoxedList* l, int start);
DEFAULT_CLASS(list_iterator_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
Box* listIter(Box* self) noexcept;
......
......@@ -25,6 +25,21 @@ extern "C" Box* createSet() {
return new BoxedSet();
}
void BoxedSet::gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedSet* s = (BoxedSet*)b;
// This feels like a cludge, but we need to find anything that
// the unordered_map might have allocated.
// Another way to handle this would be to rt_alloc the unordered_map
// as well, though that incurs extra memory dereferences which would
// be nice to avoid.
void** start = (void**)&s->s;
void** end = start + (sizeof(s->s) / 8);
v->visitPotentialRange(start, end);
}
namespace set {
class BoxedSetIterator : public Box {
......@@ -43,15 +58,15 @@ public:
++it;
return rtn;
}
};
extern "C" void setIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
static void gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedSetIterator* it = (BoxedSetIterator*)b;
BoxedSetIterator* it = (BoxedSetIterator*)b;
v->visit(it->s);
}
v->visit(it->s);
}
};
Box* setiteratorHasnext(BoxedSetIterator* self) {
RELEASE_ASSERT(self->cls == set_iterator_cls, "");
......@@ -509,7 +524,7 @@ extern "C" PyObject* PyFrozenSet_New(PyObject* iterable) noexcept {
using namespace pyston::set;
void setupSet() {
set_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &setIteratorGCHandler, 0, 0,
set_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedSetIterator::gcHandler, 0, 0,
sizeof(BoxedSetIterator), false, "setiterator");
set_iterator_cls->giveAttr(
"__iter__", new BoxedFunction(boxRTFunction((void*)setiteratorIter, typeFromClass(set_iterator_cls), 1)));
......
......@@ -38,6 +38,8 @@ public:
template <typename T> __attribute__((visibility("default"))) BoxedSet(T&& s) : s(std::forward<T>(s)) {}
DEFAULT_CLASS(set_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
}
......
......@@ -2311,13 +2311,13 @@ public:
++self->it;
return characters[c & UCHAR_MAX];
}
};
extern "C" void strIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedStringIterator* it = (BoxedStringIterator*)b;
v->visit(it->s);
}
static void gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedStringIterator* it = (BoxedStringIterator*)b;
v->visit(it->s);
}
};
Box* strIter(BoxedString* self) noexcept {
assert(PyString_Check(self));
......@@ -2698,7 +2698,7 @@ static PyMethodDef string_methods[] = {
void setupStr() {
str_cls->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
str_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &strIteratorGCHandler, 0, 0,
str_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedStringIterator::gcHandler, 0, 0,
sizeof(BoxedStringIterator), false, "striterator");
str_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, BOXED_BOOL, 1)));
......
......@@ -412,12 +412,6 @@ extern "C" PyObject* PyTuple_New(Py_ssize_t size) noexcept {
BoxedClass* tuple_iterator_cls = NULL;
extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedTupleIterator* it = (BoxedTupleIterator*)b;
v->visit(it->t);
}
static int64_t tuple_hash(BoxedTuple* v) noexcept {
long x, y;
Py_ssize_t len = Py_SIZE(v);
......@@ -564,8 +558,21 @@ static Py_ssize_t tuplelength(PyTupleObject* a) {
return Py_SIZE(a);
}
void BoxedTuple::gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedTuple* t = (BoxedTuple*)b;
v->visitRange((void* const*)&t->elts[0], (void* const*)&t->elts[t->size()]);
}
extern "C" void BoxedTupleIterator::gcHandler(GCVisitor* v, Box* b) {
boxGCHandler(v, b);
BoxedTupleIterator* it = (BoxedTupleIterator*)b;
v->visit(it->t);
}
void setupTuple() {
tuple_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &tupleIteratorGCHandler, 0, 0,
tuple_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedTupleIterator::gcHandler, 0, 0,
sizeof(BoxedTupleIterator), false, "tuple");
tuple_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)tupleNew, UNKNOWN, 1, 0, true, true)));
......
......@@ -28,6 +28,8 @@ public:
BoxedTupleIterator(BoxedTuple* t);
DEFAULT_CLASS(tuple_iterator_cls);
static void gcHandler(GCVisitor* v, Box* _o);
};
Box* tupleIter(Box* self) noexcept;
......
This diff is collapsed.
......@@ -298,6 +298,8 @@ public:
static BoxedHeapClass* create(BoxedClass* metatype, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
int weaklist_offset, int instance_size, bool is_user_defined, llvm::StringRef name);
static void gcHandler(GCVisitor* v, Box* b);
private:
// These functions are not meant for external callers and will mostly just be called
// by BoxedHeapClass::create(), but setupRuntime() also needs to do some manual class
......@@ -471,6 +473,8 @@ public:
: in_weakreflist(NULL), obj(obj), func(func), im_class(im_class) {}
DEFAULT_CLASS_SIMPLE(instancemethod_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
class GCdArray {
......@@ -505,6 +509,8 @@ public:
static const int INITIAL_CAPACITY;
DEFAULT_CLASS_SIMPLE(list_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
static_assert(sizeof(BoxedList) <= sizeof(PyListObject), "");
static_assert(sizeof(BoxedList) >= sizeof(PyListObject), "");
......@@ -639,6 +645,8 @@ public:
return rtn;
}
static void gcHandler(GCVisitor* v, Box* b);
private:
BoxedTuple() {}
......@@ -697,6 +705,8 @@ public:
return p->second;
return NULL;
}
static void gcHandler(GCVisitor* v, Box* b);
};
static_assert(sizeof(BoxedDict) == sizeof(PyDictObject), "");
......@@ -737,6 +747,8 @@ public:
Box* globals = NULL);
DEFAULT_CLASS(function_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
class BoxedBuiltinFunctionOrMethod : public BoxedFunctionBase {
......@@ -790,6 +802,8 @@ public:
BoxedSlice(Box* lower, Box* upper, Box* step) : start(lower), stop(upper), step(step) {}
DEFAULT_CLASS_SIMPLE(slice_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
static_assert(sizeof(BoxedSlice) == sizeof(PySliceObject), "");
static_assert(offsetof(BoxedSlice, start) == offsetof(PySliceObject, start), "");
......@@ -855,6 +869,8 @@ public:
: prop_get(get), prop_set(set), prop_del(del), prop_doc(doc) {}
DEFAULT_CLASS_SIMPLE(property_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
class BoxedStaticmethod : public Box {
......@@ -864,6 +880,8 @@ public:
BoxedStaticmethod(Box* callable) : sm_callable(callable){};
DEFAULT_CLASS_SIMPLE(staticmethod_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
class BoxedClassmethod : public Box {
......@@ -873,6 +891,8 @@ public:
BoxedClassmethod(Box* callable) : cm_callable(callable){};
DEFAULT_CLASS_SIMPLE(classmethod_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
// TODO is there any particular reason to make this a Box, i.e. a python-level object?
......@@ -896,6 +916,8 @@ public:
memset((void*)rtn->elts, 0, sizeof(Box*) * nelts);
return rtn;
}
static void gcHandler(GCVisitor* v, Box* b);
};
class BoxedGenerator : public Box {
......@@ -923,6 +945,8 @@ public:
BoxedGenerator(BoxedFunctionBase* function, Box* arg1, Box* arg2, Box* arg3, Box** args);
DEFAULT_CLASS(generator_cls);
static void gcHandler(GCVisitor* v, Box* b);
};
struct wrapper_def {
......
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