Commit 9c4aacd8 authored by Chris Toshok's avatar Chris Toshok

add weakref support for user defined subtypes, and also add support for more builtin types.

parent 38fdf541
...@@ -730,7 +730,8 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name, int ...@@ -730,7 +730,8 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name, int
if (size == 0) if (size == 0)
size = base->tp_basicsize; size = base->tp_basicsize;
BoxedClass* cls = BoxedHeapClass::create(type_cls, base, NULL, offsetof(BoxedException, attrs), size, false, name); BoxedClass* cls
= BoxedHeapClass::create(type_cls, base, NULL, offsetof(BoxedException, attrs), 0, size, false, name);
cls->giveAttr("__module__", boxStrConstant("exceptions")); cls->giveAttr("__module__", boxStrConstant("exceptions"));
if (base == object_cls) { if (base == object_cls) {
...@@ -955,7 +956,7 @@ void setupBuiltins() { ...@@ -955,7 +956,7 @@ void setupBuiltins() {
builtins_module = createModule("__builtin__", "__builtin__"); builtins_module = createModule("__builtin__", "__builtin__");
BoxedHeapClass* ellipsis_cls BoxedHeapClass* ellipsis_cls
= BoxedHeapClass::create(type_cls, object_cls, NULL, 0, sizeof(Box), false, "ellipsis"); = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(Box), false, "ellipsis");
Box* Ellipsis = new (ellipsis_cls) Box(); Box* Ellipsis = new (ellipsis_cls) Box();
assert(Ellipsis->cls); assert(Ellipsis->cls);
gc::registerPermanentRoot(Ellipsis); gc::registerPermanentRoot(Ellipsis);
...@@ -969,7 +970,7 @@ void setupBuiltins() { ...@@ -969,7 +970,7 @@ void setupBuiltins() {
"print", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)print, NONE, 0, 0, true, true), "print")); "print", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)print, NONE, 0, 0, true, true), "print"));
notimplemented_cls notimplemented_cls
= BoxedHeapClass::create(type_cls, object_cls, NULL, 0, sizeof(Box), false, "NotImplementedType"); = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(Box), false, "NotImplementedType");
notimplemented_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)notimplementedRepr, STR, 1))); notimplemented_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)notimplementedRepr, STR, 1)));
notimplemented_cls->freeze(); notimplemented_cls->freeze();
NotImplemented = new (notimplemented_cls) Box(); NotImplemented = new (notimplemented_cls) Box();
...@@ -1048,8 +1049,8 @@ void setupBuiltins() { ...@@ -1048,8 +1049,8 @@ void setupBuiltins() {
builtins_module->giveAttr("__import__", new BoxedBuiltinFunctionOrMethod(import_func, "__import__", builtins_module->giveAttr("__import__", new BoxedBuiltinFunctionOrMethod(import_func, "__import__",
{ None, None, None, new BoxedInt(-1) })); { None, None, None, new BoxedInt(-1) }));
enumerate_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedEnumerate::gcHandler, 0, sizeof(BoxedEnumerate), enumerate_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedEnumerate::gcHandler, 0, 0,
false, "enumerate"); sizeof(BoxedEnumerate), false, "enumerate");
enumerate_cls->giveAttr( enumerate_cls->giveAttr(
"__new__", "__new__",
new BoxedFunction(boxRTFunction((void*)BoxedEnumerate::new_, UNKNOWN, 3, 1, false, false), { boxInt(0) })); new BoxedFunction(boxRTFunction((void*)BoxedEnumerate::new_, UNKNOWN, 3, 1, false, false), { boxInt(0) }));
......
...@@ -294,7 +294,7 @@ void setupSys() { ...@@ -294,7 +294,7 @@ void setupSys() {
sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX)); sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX));
sys_flags_cls = BoxedHeapClass::create(type_cls, object_cls, BoxedSysFlags::gcHandler, 0, sizeof(BoxedSysFlags), sys_flags_cls = BoxedHeapClass::create(type_cls, object_cls, BoxedSysFlags::gcHandler, 0, 0, sizeof(BoxedSysFlags),
false, "flags"); false, "flags");
sys_flags_cls->giveAttr("__new__", sys_flags_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)BoxedSysFlags::__new__, UNKNOWN, 1, 0, true, true))); new BoxedFunction(boxRTFunction((void*)BoxedSysFlags::__new__, UNKNOWN, 1, 0, true, true)));
......
...@@ -179,7 +179,7 @@ void setupThread() { ...@@ -179,7 +179,7 @@ void setupThread() {
thread_module->giveAttr( thread_module->giveAttr(
"stack_size", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)stackSize, BOXED_INT, 0), "stack_size")); "stack_size", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)stackSize, BOXED_INT, 0), "stack_size"));
thread_lock_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, sizeof(BoxedThreadLock), false, "lock"); thread_lock_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedThreadLock), false, "lock");
thread_lock_cls->giveAttr("__module__", boxStrConstant("thread")); thread_lock_cls->giveAttr("__module__", boxStrConstant("thread"));
thread_lock_cls->giveAttr( thread_lock_cls->giveAttr(
"acquire", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::acquire, BOXED_BOOL, 2, 1, false, false), "acquire", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::acquire, BOXED_BOOL, 2, 1, false, false),
...@@ -191,13 +191,15 @@ void setupThread() { ...@@ -191,13 +191,15 @@ void setupThread() {
thread_lock_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::exit, NONE, 4))); thread_lock_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::exit, NONE, 4)));
thread_lock_cls->freeze(); thread_lock_cls->freeze();
thread_local_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, sizeof(BoxedThreadLocal), false, "_local"); thread_local_cls
= BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedThreadLocal), false, "_local");
thread_local_cls->giveAttr("__module__", boxStrConstant("thread")); thread_local_cls->giveAttr("__module__", boxStrConstant("thread"));
thread_local_cls->freeze(); thread_local_cls->freeze();
thread_module->giveAttr("_local", thread_local_cls); thread_module->giveAttr("_local", thread_local_cls);
BoxedClass* ThreadError = BoxedHeapClass::create(type_cls, Exception, NULL, Exception->attrs_offset, BoxedClass* ThreadError
Exception->tp_basicsize, false, "error"); = BoxedHeapClass::create(type_cls, Exception, NULL, Exception->attrs_offset, Exception->tp_weaklistoffset,
Exception->tp_basicsize, false, "error");
ThreadError->giveAttr("__module__", boxStrConstant("thread")); ThreadError->giveAttr("__module__", boxStrConstant("thread"));
ThreadError->freeze(); ThreadError->freeze();
......
...@@ -1545,7 +1545,8 @@ static Box* methodGetDoc(Box* b, void*) { ...@@ -1545,7 +1545,8 @@ static Box* methodGetDoc(Box* b, void*) {
} }
void setupCAPI() { void setupCAPI() {
capifunc_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, sizeof(BoxedCApiFunction), false, "capifunc"); capifunc_cls
= BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedCApiFunction), false, "capifunc");
capifunc_cls->giveAttr("__repr__", capifunc_cls->giveAttr("__repr__",
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1))); new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1)));
...@@ -1556,7 +1557,8 @@ void setupCAPI() { ...@@ -1556,7 +1557,8 @@ void setupCAPI() {
capifunc_cls->freeze(); capifunc_cls->freeze();
method_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, sizeof(BoxedMethodDescriptor), false, "method"); method_cls
= BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedMethodDescriptor), false, "method");
method_cls->giveAttr("__get__", method_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3))); new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3)));
method_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2, method_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2,
...@@ -1564,14 +1566,14 @@ void setupCAPI() { ...@@ -1564,14 +1566,14 @@ void setupCAPI() {
method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL)); method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL));
method_cls->freeze(); method_cls->freeze();
wrapperdescr_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, sizeof(BoxedWrapperDescriptor), false, wrapperdescr_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedWrapperDescriptor), false,
"wrapper_descriptor"); "wrapper_descriptor");
wrapperdescr_cls->giveAttr("__get__", wrapperdescr_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__get__, UNKNOWN, 3))); new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__get__, UNKNOWN, 3)));
wrapperdescr_cls->freeze(); wrapperdescr_cls->freeze();
wrapperobject_cls wrapperobject_cls
= BoxedHeapClass::create(type_cls, object_cls, NULL, 0, sizeof(BoxedWrapperObject), false, "method-wrapper"); = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedWrapperObject), false, "method-wrapper");
wrapperobject_cls->giveAttr( wrapperobject_cls->giveAttr(
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true))); "__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true)));
wrapperobject_cls->freeze(); wrapperobject_cls->freeze();
......
...@@ -271,9 +271,9 @@ Box* instanceSetitem(Box* _inst, Box* key, Box* value) { ...@@ -271,9 +271,9 @@ Box* instanceSetitem(Box* _inst, Box* key, Box* value) {
void setupClassobj() { void setupClassobj() {
classobj_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedClassobj::gcHandler, classobj_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedClassobj::gcHandler,
offsetof(BoxedClassobj, attrs), sizeof(BoxedClassobj), false, "classobj"); offsetof(BoxedClassobj, attrs), 0, sizeof(BoxedClassobj), false, "classobj");
instance_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedInstance::gcHandler, instance_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedInstance::gcHandler,
offsetof(BoxedInstance, attrs), sizeof(BoxedInstance), false, "instance"); offsetof(BoxedInstance, attrs), 0, sizeof(BoxedInstance), false, "instance");
classobj_cls->giveAttr("__new__", classobj_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)classobjNew, UNKNOWN, 4, 0, false, false))); new BoxedFunction(boxRTFunction((void*)classobjNew, UNKNOWN, 4, 0, false, false)));
......
...@@ -572,15 +572,15 @@ static Box* dict_repr(PyObject* self) noexcept { ...@@ -572,15 +572,15 @@ static Box* dict_repr(PyObject* self) noexcept {
} }
void setupDict() { void setupDict() {
dict_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &dictIteratorGCHandler, 0, sizeof(BoxedDict), dict_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &dictIteratorGCHandler, 0, 0, sizeof(BoxedDict),
false, "dictionary-itemiterator"); false, "dictionary-itemiterator");
dict_keys_cls = BoxedHeapClass::create(type_cls, object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false, dict_keys_cls = BoxedHeapClass::create(type_cls, object_cls, &dictViewGCHandler, 0, 0, sizeof(BoxedDictView), false,
"dict_keys"); "dict_keys");
dict_values_cls = BoxedHeapClass::create(type_cls, object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false, dict_values_cls = BoxedHeapClass::create(type_cls, object_cls, &dictViewGCHandler, 0, 0, sizeof(BoxedDictView),
"dict_values"); false, "dict_values");
dict_items_cls = BoxedHeapClass::create(type_cls, object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false, dict_items_cls = BoxedHeapClass::create(type_cls, object_cls, &dictViewGCHandler, 0, 0, sizeof(BoxedDictView),
"dict_items"); false, "dict_items");
dict_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)dictLen, BOXED_INT, 1))); 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))); dict_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)dictNew, UNKNOWN, 1, 0, true, true)));
......
...@@ -38,11 +38,9 @@ public: ...@@ -38,11 +38,9 @@ public:
int f_skipnextlf; /* Skip next \n */ int f_skipnextlf; /* Skip next \n */
PyObject* f_encoding; PyObject* f_encoding;
PyObject* f_errors; PyObject* f_errors;
#if 0
PyObject* weakreflist; /* List of weak references */ PyObject* weakreflist; /* List of weak references */
#endif int unlocked_count; /* Num. currently running sections of code
int unlocked_count; /* Num. currently running sections of code using f_fp with the GIL released. */
using f_fp with the GIL released. */
int readable; int readable;
int writable; int writable;
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
namespace pyston { namespace pyston {
static uint64_t next_stack_addr = 0x3270000000L; static uint64_t next_stack_addr = 0x4270000000L;
static std::deque<uint64_t> available_addrs; static std::deque<uint64_t> available_addrs;
// There should be a better way of getting this: // There should be a better way of getting this:
...@@ -298,8 +298,9 @@ void generatorDestructor(Box* b) { ...@@ -298,8 +298,9 @@ void generatorDestructor(Box* b) {
} }
void setupGenerator() { void setupGenerator() {
generator_cls = BoxedHeapClass::create(type_cls, object_cls, &generatorGCHandler, offsetof(BoxedGenerator, attrs), generator_cls
sizeof(BoxedGenerator), false, "generator"); = BoxedHeapClass::create(type_cls, object_cls, &generatorGCHandler, offsetof(BoxedGenerator, attrs),
offsetof(BoxedGenerator, weakreflist), sizeof(BoxedGenerator), false, "generator");
generator_cls->simple_destructor = generatorDestructor; generator_cls->simple_destructor = generatorDestructor;
generator_cls->giveAttr("__iter__", generator_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)generatorIter, typeFromClass(generator_cls), 1))); new BoxedFunction(boxRTFunction((void*)generatorIter, typeFromClass(generator_cls), 1)));
......
...@@ -178,9 +178,9 @@ Box* xrangeReversed(Box* self) { ...@@ -178,9 +178,9 @@ Box* xrangeReversed(Box* self) {
} }
void setupXrange() { void setupXrange() {
xrange_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, sizeof(BoxedXrange), false, "xrange"); 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, xrange_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedXrangeIterator::xrangeIteratorGCHandler, 0,
sizeof(BoxedXrangeIterator), false, "rangeiterator"); 0, sizeof(BoxedXrangeIterator), false, "rangeiterator");
xrange_cls->giveAttr( xrange_cls->giveAttr(
"__new__", "__new__",
......
...@@ -142,7 +142,7 @@ extern "C" PyObject* PySeqIter_New(PyObject* seq) noexcept { ...@@ -142,7 +142,7 @@ extern "C" PyObject* PySeqIter_New(PyObject* seq) noexcept {
void setupIter() { void setupIter() {
seqiter_cls seqiter_cls
= BoxedHeapClass::create(type_cls, object_cls, seqiterGCVisit, 0, sizeof(BoxedSeqIter), false, "iterator"); = BoxedHeapClass::create(type_cls, object_cls, seqiterGCVisit, 0, 0, sizeof(BoxedSeqIter), false, "iterator");
seqiter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)seqiterNext, UNKNOWN, 1))); seqiter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)seqiterNext, UNKNOWN, 1)));
seqiter_cls->giveAttr("__hasnext__", new BoxedFunction(boxRTFunction((void*)seqiterHasnext, BOXED_BOOL, 1))); seqiter_cls->giveAttr("__hasnext__", new BoxedFunction(boxRTFunction((void*)seqiterHasnext, BOXED_BOOL, 1)));
...@@ -150,7 +150,7 @@ void setupIter() { ...@@ -150,7 +150,7 @@ void setupIter() {
seqiter_cls->freeze(); seqiter_cls->freeze();
seqreviter_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, sizeof(BoxedSeqIter), false, "reversed"); seqreviter_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedSeqIter), false, "reversed");
seqreviter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)seqiterNext, UNKNOWN, 1))); seqreviter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)seqiterNext, UNKNOWN, 1)));
seqreviter_cls->giveAttr("__hasnext__", new BoxedFunction(boxRTFunction((void*)seqreviterHasnext, BOXED_BOOL, 1))); seqreviter_cls->giveAttr("__hasnext__", new BoxedFunction(boxRTFunction((void*)seqreviterHasnext, BOXED_BOOL, 1)));
...@@ -158,7 +158,7 @@ void setupIter() { ...@@ -158,7 +158,7 @@ void setupIter() {
seqreviter_cls->freeze(); seqreviter_cls->freeze();
iterwrapper_cls = BoxedHeapClass::create(type_cls, object_cls, iterwrapperGCVisit, 0, sizeof(BoxedIterWrapper), iterwrapper_cls = BoxedHeapClass::create(type_cls, object_cls, iterwrapperGCVisit, 0, 0, sizeof(BoxedIterWrapper),
false, "iterwrapper"); false, "iterwrapper");
iterwrapper_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)iterwrapperNext, UNKNOWN, 1))); iterwrapper_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)iterwrapperNext, UNKNOWN, 1)));
......
...@@ -625,7 +625,7 @@ extern "C" void listIteratorGCHandler(GCVisitor* v, Box* b) { ...@@ -625,7 +625,7 @@ extern "C" void listIteratorGCHandler(GCVisitor* v, Box* b) {
} }
extern "C" Box* listNew(Box* cls, Box* container) { extern "C" Box* listNew(Box* cls, Box* container) {
assert(cls == list_cls); assert(isSubclass(static_cast<BoxedClass*>(cls), list_cls));
if (container == None) if (container == None)
return new BoxedList(); return new BoxedList();
...@@ -764,9 +764,9 @@ extern "C" int PyList_SetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, P ...@@ -764,9 +764,9 @@ extern "C" int PyList_SetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, P
} }
void setupList() { void setupList() {
list_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), list_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &listIteratorGCHandler, 0, 0, sizeof(BoxedList),
false, "listiterator"); false, "listiterator");
list_reverse_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &listIteratorGCHandler, 0, list_reverse_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &listIteratorGCHandler, 0, 0,
sizeof(BoxedListIterator), false, "listreverseiterator"); sizeof(BoxedListIterator), false, "listreverseiterator");
list_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)listLen, BOXED_INT, 1))); list_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)listLen, BOXED_INT, 1)));
......
...@@ -287,14 +287,15 @@ void BoxedClass::freeze() { ...@@ -287,14 +287,15 @@ void BoxedClass::freeze() {
is_constant = true; is_constant = true;
} }
BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset,
bool is_user_defined) int instance_size, bool is_user_defined)
: BoxVar(0), gc_visit(gc_visit), simple_destructor(NULL), attrs_offset(attrs_offset), is_constant(false), : BoxVar(0), gc_visit(gc_visit), simple_destructor(NULL), attrs_offset(attrs_offset), is_constant(false),
is_user_defined(is_user_defined), is_pyston_class(true) { is_user_defined(is_user_defined), is_pyston_class(true) {
// Zero out the CPython tp_* slots: // Zero out the CPython tp_* slots:
memset(&tp_name, 0, (char*)(&tp_version_tag + 1) - (char*)(&tp_name)); memset(&tp_name, 0, (char*)(&tp_version_tag + 1) - (char*)(&tp_name));
tp_basicsize = instance_size; tp_basicsize = instance_size;
tp_weaklistoffset = weaklist_offset;
tp_flags |= Py_TPFLAGS_CHECKTYPES; tp_flags |= Py_TPFLAGS_CHECKTYPES;
tp_flags |= Py_TPFLAGS_BASETYPE; tp_flags |= Py_TPFLAGS_BASETYPE;
...@@ -343,6 +344,15 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset ...@@ -343,6 +344,15 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
if (base && cls && str_cls) if (base && cls && str_cls)
giveAttr("__base__", base); giveAttr("__base__", base);
// this isn't strictly correct, as it permits subclasses from
// e.g. Tuples/Longs to have weakrefs, which cpython disallows.
if (tp_weaklistoffset == 0 && base)
tp_weaklistoffset = base->tp_weaklistoffset;
if (is_user_defined && tp_weaklistoffset == 0) {
tp_weaklistoffset = tp_basicsize;
tp_basicsize += sizeof(Box**);
}
assert(tp_basicsize % sizeof(void*) == 0); // Not critical I suppose, but probably signals a bug assert(tp_basicsize % sizeof(void*) == 0); // Not critical I suppose, but probably signals a bug
if (attrs_offset) { if (attrs_offset) {
assert(tp_basicsize >= attrs_offset + sizeof(HCAttrs)); assert(tp_basicsize >= attrs_offset + sizeof(HCAttrs));
...@@ -357,9 +367,10 @@ void BoxedClass::finishInitialization() { ...@@ -357,9 +367,10 @@ void BoxedClass::finishInitialization() {
commonClassSetup(this); commonClassSetup(this);
} }
BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset,
bool is_user_defined, BoxedString* name) int instance_size, bool is_user_defined, BoxedString* name)
: BoxedClass(base, gc_visit, attrs_offset, instance_size, is_user_defined), ht_name(name), ht_slots(NULL) { : BoxedClass(base, gc_visit, attrs_offset, weaklist_offset, instance_size, is_user_defined), ht_name(name),
ht_slots(NULL) {
tp_as_number = &as_number; tp_as_number = &as_number;
tp_as_mapping = &as_mapping; tp_as_mapping = &as_mapping;
...@@ -378,14 +389,19 @@ BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attr ...@@ -378,14 +389,19 @@ BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attr
} }
BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
int instance_size, bool is_user_defined, const std::string& name) { int weaklist_offset, int instance_size, bool is_user_defined,
return create(metaclass, base, gc_visit, attrs_offset, instance_size, is_user_defined, new BoxedString(name), NULL); const std::string& name) {
return create(metaclass, base, gc_visit, attrs_offset, weaklist_offset, instance_size, is_user_defined,
new BoxedString(name), NULL);
} }
BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, BoxedHeapClass* BoxedHeapClass::create(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
int instance_size, bool is_user_defined, BoxedString* name, BoxedTuple* bases) { int weaklist_offset, int instance_size, bool is_user_defined, BoxedString* name,
BoxedTuple* bases) {
BoxedHeapClass* made = new (metaclass) BoxedHeapClass* made = new (metaclass)
BoxedHeapClass(base, gc_visit, attrs_offset, instance_size, is_user_defined, name); BoxedHeapClass(base, gc_visit, attrs_offset, weaklist_offset, instance_size, is_user_defined, name);
assert((name || str_cls == NULL) && "name can only be NULL before str_cls has been initialized.");
// While it might be ok if these were set, it'd indicate a difference in // While it might be ok if these were set, it'd indicate a difference in
// expectations as to who was going to calculate them: // expectations as to who was going to calculate them:
...@@ -3680,11 +3696,12 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) { ...@@ -3680,11 +3696,12 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
BoxedClass* made; BoxedClass* made;
if (base->instancesHaveDictAttrs() || base->instancesHaveHCAttrs()) { if (base->instancesHaveDictAttrs() || base->instancesHaveHCAttrs()) {
made = BoxedHeapClass::create(metatype, base, NULL, base->attrs_offset, base->tp_basicsize, true, name, bases); made = BoxedHeapClass::create(metatype, base, NULL, base->attrs_offset, base->tp_weaklistoffset,
base->tp_basicsize, true, name, bases);
} else { } else {
assert(base->tp_basicsize % sizeof(void*) == 0); assert(base->tp_basicsize % sizeof(void*) == 0);
made = BoxedHeapClass::create(metatype, base, NULL, base->tp_basicsize, base->tp_basicsize + sizeof(HCAttrs), made = BoxedHeapClass::create(metatype, base, NULL, base->tp_basicsize, base->tp_weaklistoffset,
true, name, bases); base->tp_basicsize + sizeof(HCAttrs), true, name, bases);
} }
// TODO: how much of these should be in BoxedClass::finishInitialization()? // TODO: how much of these should be in BoxedClass::finishInitialization()?
......
...@@ -246,8 +246,8 @@ Box* setNonzero(BoxedSet* self) { ...@@ -246,8 +246,8 @@ Box* setNonzero(BoxedSet* self) {
using namespace pyston::set; using namespace pyston::set;
void setupSet() { void setupSet() {
set_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &setIteratorGCHandler, 0, sizeof(BoxedSet), false, set_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &setIteratorGCHandler, 0, 0, sizeof(BoxedSet),
"setiterator"); false, "setiterator");
set_iterator_cls->giveAttr("__hasnext__", set_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1))); new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1)));
set_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)setiteratorNext, UNKNOWN, 1))); set_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)setiteratorNext, UNKNOWN, 1)));
......
...@@ -33,6 +33,7 @@ class BoxedSet : public Box { ...@@ -33,6 +33,7 @@ class BoxedSet : public Box {
public: public:
typedef std::unordered_set<Box*, PyHasher, PyEq, StlCompatAllocator<Box*>> Set; typedef std::unordered_set<Box*, PyHasher, PyEq, StlCompatAllocator<Box*>> Set;
Set s; Set s;
Box** weakreflist; /* List of weak references */
BoxedSet() __attribute__((visibility("default"))) {} BoxedSet() __attribute__((visibility("default"))) {}
......
...@@ -2216,7 +2216,7 @@ void setupStr() { ...@@ -2216,7 +2216,7 @@ void setupStr() {
str_cls->simple_destructor = strDestructor; str_cls->simple_destructor = strDestructor;
str_cls->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER; str_cls->tp_flags |= Py_TPFLAGS_HAVE_NEWBUFFER;
str_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &strIteratorGCHandler, 0, str_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &strIteratorGCHandler, 0, 0,
sizeof(BoxedStringIterator), false, "striterator"); sizeof(BoxedStringIterator), false, "striterator");
str_iterator_cls->giveAttr("__hasnext__", str_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, BOXED_BOOL, 1))); new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, BOXED_BOOL, 1)));
......
...@@ -186,8 +186,8 @@ Box* superInit(Box* _self, Box* _type, Box* obj) { ...@@ -186,8 +186,8 @@ Box* superInit(Box* _self, Box* _type, Box* obj) {
} }
void setupSuper() { void setupSuper() {
super_cls super_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedSuper::gcHandler, 0, 0, sizeof(BoxedSuper), false,
= BoxedHeapClass::create(type_cls, object_cls, &BoxedSuper::gcHandler, 0, sizeof(BoxedSuper), false, "super"); "super");
super_cls->giveAttr("__getattribute__", new BoxedFunction(boxRTFunction((void*)superGetattribute, UNKNOWN, 2))); super_cls->giveAttr("__getattribute__", new BoxedFunction(boxRTFunction((void*)superGetattribute, UNKNOWN, 2)));
super_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)superRepr, STR, 1))); super_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)superRepr, STR, 1)));
......
...@@ -107,8 +107,8 @@ Box* BoxedTraceback::getLines(Box* b) { ...@@ -107,8 +107,8 @@ Box* BoxedTraceback::getLines(Box* b) {
} }
void setupTraceback() { void setupTraceback() {
traceback_cls = BoxedHeapClass::create(type_cls, object_cls, BoxedTraceback::gcHandler, 0, sizeof(BoxedTraceback), traceback_cls = BoxedHeapClass::create(type_cls, object_cls, BoxedTraceback::gcHandler, 0, 0,
false, "traceback"); sizeof(BoxedTraceback), false, "traceback");
traceback_cls->giveAttr("getLines", new BoxedFunction(boxRTFunction((void*)BoxedTraceback::getLines, UNKNOWN, 1))); traceback_cls->giveAttr("getLines", new BoxedFunction(boxRTFunction((void*)BoxedTraceback::getLines, UNKNOWN, 1)));
......
...@@ -386,8 +386,8 @@ extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) { ...@@ -386,8 +386,8 @@ extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) {
void setupTuple() { void setupTuple() {
tuple_iterator_cls tuple_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &tupleIteratorGCHandler, 0, 0, sizeof(BoxedTuple),
= BoxedHeapClass::create(type_cls, object_cls, &tupleIteratorGCHandler, 0, sizeof(BoxedTuple), false, "tuple"); false, "tuple");
tuple_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)tupleNew, UNKNOWN, 1, 0, true, true))); tuple_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)tupleNew, UNKNOWN, 1, 0, true, true)));
CLFunction* getitem = createRTFunction(2, 0, 0, 0); CLFunction* getitem = createRTFunction(2, 0, 0, 0);
......
This diff is collapsed.
...@@ -198,7 +198,8 @@ protected: ...@@ -198,7 +198,8 @@ protected:
// creation due to bootstrapping issues. // creation due to bootstrapping issues.
void finishInitialization(); void finishInitialization();
BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, bool is_user_defined); BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset, int instance_size,
bool is_user_defined);
friend void setupRuntime(); friend void setupRuntime();
}; };
...@@ -215,16 +216,18 @@ public: ...@@ -215,16 +216,18 @@ public:
// These functions are the preferred way to construct new types: // These functions are the preferred way to construct new types:
static BoxedHeapClass* create(BoxedClass* metatype, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, static BoxedHeapClass* create(BoxedClass* metatype, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
int instance_size, bool is_user_defined, BoxedString* name, BoxedTuple* bases); int weaklist_offset, int instance_size, bool is_user_defined, BoxedString* name,
BoxedTuple* bases);
static BoxedHeapClass* create(BoxedClass* metatype, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, static BoxedHeapClass* create(BoxedClass* metatype, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
int instance_size, bool is_user_defined, const std::string& name); int weaklist_offset, int instance_size, bool is_user_defined,
const std::string& name);
private: private:
// These functions are not meant for external callers and will mostly just be called // 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 // by BoxedHeapClass::create(), but setupRuntime() also needs to do some manual class
// creation due to bootstrapping issues. // creation due to bootstrapping issues.
BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, bool is_user_defined, BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset, int instance_size,
BoxedString* name); bool is_user_defined, BoxedString* name);
friend void setupRuntime(); friend void setupRuntime();
...@@ -577,6 +580,9 @@ public: ...@@ -577,6 +580,9 @@ public:
class BoxedGenerator : public Box { class BoxedGenerator : public Box {
public: public:
HCAttrs attrs; HCAttrs attrs;
Box** weakreflist;
BoxedFunctionBase* function; BoxedFunctionBase* function;
Box* arg1, *arg2, *arg3; Box* arg1, *arg2, *arg3;
GCdArray* args; GCdArray* args;
......
# expected: fail
# we aren't collecting everything we should, so wr_cleared isn't being called
import weakref
import gc
class Foo:
def wr_cleared(self, wr):
print "made it here!", wr
def meth(self):
1
def createCycle(self):
self.__bound_meth = self.meth
self.__wr = weakref.ref(self.__bound_meth, self.wr_cleared)
return self.__bound_meth
def bwr_cleared(wr):
print "made it here for b!", wr
f = Foo()
b = f.createCycle()
bwr = weakref.ref(b, bwr_cleared)
gc.collect()
print bwr
print "before setting f to None"
f = None
gc.collect()
print bwr
print "after setting f to None"
b = None
gc.collect()
print bwr
print "after setting b to None"
# expected: fail
# we aren't collecting everything we should, so wr_cleared isn't being called
import weakref
import gc
class Foo:
def wr_cleared(self, wr):
print "made it here!", wr
def meth(self):
1
def createCycle(self):
self.__bound_meth = self.meth
self.__wr = weakref.ref(self.__bound_meth, self.wr_cleared)
return self.__wr
f = Foo()
b = f.createCycle()
print b
print "before setting f to None"
f = None
print "after setting f to None"
b = None
print "after setting b to None"
gc.collect()
print "after calling gc.collect"
import weakref
import gc
def doStuff():
def meth():
pass
wr = weakref.ref(meth)
return wr
w = doStuff()
gc.collect()
print w()
# expected: fail
# we aren't collecting everything we should, so wr_cleared isn't being called
import weakref
import gc
class Foo:
def wr_cleared(self, wr):
print "made it here!", wr
def meth(self):
1
def doSomething(self):
bound_meth = self.meth
self.__wr = weakref.ref(bound_meth, self.wr_cleared)
return bound_meth
f = Foo()
b = f.doSomething()
gc.collect()
print "before setting f to None"
f = None
gc.collect()
print "after setting f to None"
b = None
gc.collect()
print "after setting b to None"
import weakref import weakref
import array
import re
def test_wr(o): # from https://docs.python.org/2/library/weakref.html:
#
# Not all objects can be weakly referenced; those objects which can include class instances, functions written in Python (but not in C), methods (both bound and unbound), sets, frozensets, file objects, generators, type objects, DBcursor objects from the bsddb module, sockets, arrays, deques, regular expression pattern objects, and code objects.
#
# Changed in version 2.4: Added support for files, sockets, arrays, and patterns.
#
# Changed in version 2.7: Added support for thread.lock, threading.Lock, and code objects
#
# Several built-in types such as list and dict do not directly support weak references but can add support through subclassing
#
# CPython implementation detail: Other built-in types such as tuple and long do not support weak references even when subclassed
#
def test_wr(o, extra=None):
if extra is None:
extra = type(o)
try: try:
r = weakref.ref(o) r = weakref.ref(o)
print "passed", type(o) print "passed", extra
return r return r
except: except:
print "failed", type(o) print "failed", extra
def test_subclass_wr(tp):
class test(tp): pass
test_wr(test(), "subclass of " + repr(tp))
def test(): def test():
1 pass
wr = test_wr(test) wr = test_wr(test)
print wr() == test print wr() == test
#print weakref.getweakrefs(test)[0] == wr
print weakref.getweakrefcount(test) print weakref.getweakrefcount(test)
test_wr(1)
test_wr(1.)
test_wr(1L)
test_wr("hello world")
test_wr([1,2,3])
test_wr((1,2,2))
test_wr(set())
test_wr(frozenset())
test_wr((i*i for i in range(1000000)))
test_wr(set)
test_wr(file("/etc/passwd"))
# missing: db cursor from the bsddb module
# missing: sockets
test_wr(array.array('d', [1.0, 2.0, 3.14]))
test_wr(re.compile('ab*'))
# compile isn't in pyston yet
#test_wr(compile('print "Hello, world"', '<string>', 'exec'))
# missing: thread.lock, threading.Lock
# skip these since we permit them, while cpython doesn't
#test_subclass_wr(long)
#test_subclass_wr(tuple)
#test_subclass_wr(list)
test_subclass_wr(int)
test_subclass_wr(float)
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