Commit df261ea5 authored by Kevin Modzelewski's avatar Kevin Modzelewski

GC is working

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