Commit df261ea5 authored by Kevin Modzelewski's avatar Kevin Modzelewski

GC is working

parent 08509b08
......@@ -175,6 +175,9 @@ extern PyTypeObject Scanner_Type;
extern PyTypeObject* Itertool_SafeDealloc_Types[];
// In CPython this is in frameobject.h:
PyAPI_FUNC(int) PyFrame_ClearFreeList(void) PYSTON_NOEXCEPT;
#define PyDoc_VAR(name) static char name[]
#define PyDoc_STRVAR(name, str) PyDoc_VAR(name) = PyDoc_STR(str)
#define PyDoc_STR(str) str
......
......@@ -10,6 +10,7 @@ extern "C" {
// Pyston addition: refcounting annotations:
#define BORROWED(T) T
#define STOLEN(T) T
#define WEAK(T) T
/* Object and type object interface */
......
......@@ -552,6 +552,9 @@ move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
for (gc = unreachable->gc.gc_next; gc != unreachable; gc = next) {
PyObject *op = FROM_GC(gc);
// Pyston addition: for now assert that the gc isn't freeing anything.
assert(0 && "something getting freed by the GC! check it out");
assert(IS_TENTATIVELY_UNREACHABLE(op));
next = gc->gc.gc_next;
......@@ -793,6 +796,7 @@ handle_finalizers(PyGC_Head *finalizers, PyGC_Head *old)
garbage = PyList_New(0);
if (garbage == NULL)
Py_FatalError("gc couldn't create gc.garbage list");
PyGC_RegisterStaticConstant(garbage);
}
for (; gc != finalizers; gc = gc->gc.gc_next) {
PyObject *op = FROM_GC(gc);
......@@ -848,8 +852,7 @@ static void
clear_freelists(void)
{
(void)PyMethod_ClearFreeList();
Py_FatalError("unimplemented");
//(void)PyFrame_ClearFreeList();
(void)PyFrame_ClearFreeList();
(void)PyCFunction_ClearFreeList();
(void)PyTuple_ClearFreeList();
#ifdef Py_USING_UNICODE
......@@ -896,6 +899,7 @@ collect(int generation)
delstr = PyString_InternFromString("__del__");
if (delstr == NULL)
Py_FatalError("gc couldn't allocate \"__del__\"");
PyGC_RegisterStaticConstant(delstr);
}
if (debug & DEBUG_STATS) {
......@@ -1032,8 +1036,10 @@ collect(int generation)
}
if (PyErr_Occurred()) {
if (gc_str == NULL)
if (gc_str == NULL) {
gc_str = PyString_FromString("garbage collection");
PyGC_RegisterStaticConstant(gc_str);
}
PyErr_WriteUnraisable(gc_str);
Py_FatalError("unexpected exception during garbage collection");
}
......@@ -1410,6 +1416,7 @@ initgc(void)
garbage = PyList_New(0);
if (garbage == NULL)
return;
PyGC_RegisterStaticConstant(garbage);
}
Py_INCREF(garbage);
if (PyModule_AddObject(m, "garbage", garbage) < 0)
......
......@@ -31,7 +31,10 @@ public:
public:
BoxedCApiFunction(PyMethodDef* method_def, Box* passthrough, Box* module = NULL)
: method_def(method_def), passthrough(passthrough), module(module) {}
: method_def(method_def), passthrough(passthrough), module(module) {
Py_XINCREF(passthrough);
Py_XINCREF(module);
}
DEFAULT_CLASS(capifunc_cls);
......
......@@ -1948,6 +1948,10 @@ extern "C" void _Py_FatalError(const char* fmt, const char* function, const char
abort();
}
extern "C" int PyCFunction_ClearFreeList() noexcept {
return 0; // number of entries cleared
}
void setupCAPI() {
capifunc_cls->giveAttr("__repr__",
new BoxedFunction(FunctionMetadata::create((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1)));
......
......@@ -1637,7 +1637,7 @@ extern "C" PyObject* PyMethod_Class(PyObject* im) noexcept {
}
extern "C" int PyMethod_ClearFreeList(void) noexcept {
Py_FatalError("unimplemented");
return 0; // number of entries cleared
}
void setupClassobj() {
......
......@@ -781,29 +781,18 @@ int BoxedDict::clear(PyObject* op) noexcept {
}
extern "C" void _PyDict_MaybeUntrack(PyObject* op) noexcept {
PyDictObject* mp;
PyObject* value;
Py_ssize_t mask, i;
if (!PyDict_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))
return;
Py_FatalError("unimplemented");
/*
PyDictEntry* ep;
mp = (PyDictObject *) op;
ep = mp->ma_table;
mask = mp->ma_mask;
for (i = 0; i <= mask; i++) {
if ((value = ep[i].me_value) == NULL)
continue;
if (_PyObject_GC_MAY_BE_TRACKED(value) ||
_PyObject_GC_MAY_BE_TRACKED(ep[i].me_key))
BoxedDict* d = static_cast<BoxedDict*>(op);
for (auto&& p : d->d) {
if (_PyObject_GC_MAY_BE_TRACKED(p.second) ||
_PyObject_GC_MAY_BE_TRACKED(p.first.value))
return;
}
DECREASE_TRACK_COUNT
_PyObject_GC_UNTRACK(op);
*/
}
void setupDict() {
......
......@@ -1639,6 +1639,10 @@ static PyMethodDef float_methods[] = { { "hex", (PyCFunction)float_hex, METH_NOA
{ "is_integer", (PyCFunction)float_is_integer, METH_NOARGS, NULL },
{ "__format__", (PyCFunction)float__format__, METH_VARARGS, NULL } };
extern "C" int PyFloat_ClearFreeList() noexcept {
return 0; // number of entries cleared
}
void setupFloat() {
static PyNumberMethods float_as_number;
float_cls->tp_as_number = &float_as_number;
......
......@@ -142,6 +142,10 @@ public:
}
};
extern "C" int PyFrame_ClearFreeList(void) noexcept {
return 0; // number of entries cleared
}
Box* getFrame(int depth) {
auto it = getPythonFrame(depth);
if (!it.exists())
......
......@@ -1161,6 +1161,10 @@ static PyObject* int_getnewargs(BoxedInt* v) noexcept {
return Py_BuildValue("(l)", v->n);
}
extern "C" int PyInt_ClearFreeList() noexcept {
return 0; // number of entries cleared
}
void setupInt() {
static PyNumberMethods int_as_number;
int_cls->tp_as_number = &int_as_number;
......
......@@ -669,6 +669,10 @@ _PyTuple_MaybeUntrack(PyObject *op) noexcept
_PyObject_GC_UNTRACK(op);
}
extern "C" int PyTuple_ClearFreeList() noexcept {
return 0; // number of entries cleared
}
void setupTuple() {
static PySequenceMethods tuple_as_sequence;
tuple_cls->tp_as_sequence = &tuple_as_sequence;
......
......@@ -2074,7 +2074,7 @@ public:
// or PyModule_GetDict to return real dicts.
class AttrWrapper : public Box {
private:
Box* b;
WEAK(Box*) b; // The parent object ('b') will keep the attrwrapper alive (forever)
void convertToDictBacked() {
HCAttrs* attrs = this->b->getHCAttrsPtr();
......@@ -2470,16 +2470,6 @@ public:
static Box* ne(Box* _self, Box* _other) { return eq(_self, _other) == True ? False : True; }
static void tp_dealloc(Box* self) noexcept {
Py_FatalError("unimplemented");
}
static int tp_traverse(Box* self, visitproc visit, void *arg) noexcept {
Py_FatalError("unimplemented");
}
static int tp_clear(Box* self) noexcept {
Py_FatalError("unimplemented");
}
friend class AttrWrapperIter;
};
......@@ -3327,7 +3317,7 @@ void Box::clearAttrs() {
if (unlikely(hcls->type == HiddenClass::DICT_BACKED)) {
Box* d = attrs->attr_list->attrs[0];
PyDict_Clear(d);
Py_DECREF(d);
return;
}
......@@ -3446,6 +3436,7 @@ void BoxedClass::dealloc(Box* b) noexcept {
Py_XDECREF(type->tp_subclasses);
//Py_XDECREF(type->tp_mro); // XXX was done manually
// Copied in the CPython implementation for reference:
#if 0
/* Assert this is a heap-allocated type object */
assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
......@@ -3472,6 +3463,10 @@ static void object_dealloc(PyObject* self) {
Py_TYPE(self)->tp_free(self);
}
static int type_is_gc(BoxedClass* type) {
return type->is_pyston_class || (type->tp_flags & Py_TPFLAGS_HEAPTYPE);
}
static int
type_traverse(PyTypeObject *type, visitproc visit, void *arg)
{
......@@ -3537,7 +3532,11 @@ type_clear(PyTypeObject *type)
}
int HCAttrs::traverse(visitproc visit, void* arg) noexcept {
Py_FatalError("unimplemented");
int nattrs = hcls->attributeArraySize();
for (int i = 0; i < nattrs; i++) {
Py_VISIT(attr_list->attrs[i]);
}
return 0;
}
void AttrWrapperIter::dealloc(Box* _o) noexcept {
......@@ -3606,14 +3605,17 @@ void setupRuntime() {
// We have to do a little dance to get object_cls and type_cls set up, since the normal
// object-creation routines look at the class to see the allocation size.
object_cls = static_cast<BoxedClass*>(PyObject_MALLOC(sizeof(BoxedClass)));
type_cls = static_cast<BoxedClass*>(PyObject_MALLOC(sizeof(BoxedClass)));
object_cls = static_cast<BoxedClass*>(_PyObject_GC_Malloc(sizeof(BoxedClass)));
type_cls = static_cast<BoxedClass*>(_PyObject_GC_Malloc(sizeof(BoxedClass)));
PyObject_INIT(object_cls, type_cls);
PyObject_INIT(type_cls, type_cls);
::new (object_cls) BoxedClass(NULL, 0, 0, sizeof(Box), false, "object", object_dealloc, PyObject_Del, /* is_gc */ false);
::new (type_cls) BoxedClass(object_cls, offsetof(BoxedClass, attrs), offsetof(BoxedClass, tp_weaklist),
sizeof(BoxedHeapClass), false, "type", BoxedClass::dealloc, PyObject_GC_Del, true,
(traverseproc)type_traverse, (inquiry)type_clear);
_PyObject_GC_TRACK(object_cls);
_PyObject_GC_TRACK(type_cls);
type_cls->tp_is_gc = (inquiry)type_is_gc;
type_cls->has_safe_tp_dealloc = false;
type_cls->tp_flags |= Py_TPFLAGS_TYPE_SUBCLASS;
......@@ -3672,8 +3674,7 @@ void setupRuntime() {
pyston_getset_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedGetsetDescriptor), false, "getset_descriptor",
NULL, NULL, false);
attrwrapper_cls = new (0)
BoxedClass(object_cls, 0, 0, sizeof(AttrWrapper), false, "attrwrapper", AttrWrapper::tp_dealloc, NULL, true,
AttrWrapper::tp_traverse, AttrWrapper::tp_clear);
BoxedClass(object_cls, 0, 0, sizeof(AttrWrapper), false, "attrwrapper", NULL, NULL, false);
dict_cls = new (0) BoxedClass(object_cls, 0, 0, sizeof(BoxedDict), false, "dict", BoxedDict::dealloc, NULL, true,
BoxedDict::traverse, BoxedDict::clear);
dict_cls->tp_flags |= Py_TPFLAGS_DICT_SUBCLASS;
......
......@@ -1135,7 +1135,7 @@ public:
PyMethodDef* method;
BoxedClass* type;
BoxedMethodDescriptor(PyMethodDef* method, BoxedClass* type) : method(method), type(type) {}
BoxedMethodDescriptor(PyMethodDef* method, BoxedClass* type) : method(method), type(type) { Py_INCREF(type); }
DEFAULT_CLASS(method_cls);
......
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