Commit 409bb389 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #338 from toshok/weakrefs-on-user-types

add weakref support for user defined subtypes (with inheritance) and 'type' instances
parents 2a035a20 9c4aacd8
......@@ -730,7 +730,8 @@ static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name, int
if (size == 0)
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"));
if (base == object_cls) {
......@@ -955,7 +956,7 @@ void setupBuiltins() {
builtins_module = createModule("__builtin__", "__builtin__");
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();
assert(Ellipsis->cls);
gc::registerPermanentRoot(Ellipsis);
......@@ -969,7 +970,7 @@ void setupBuiltins() {
"print", new BoxedBuiltinFunctionOrMethod(boxRTFunction((void*)print, NONE, 0, 0, true, true), "print"));
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->freeze();
NotImplemented = new (notimplemented_cls) Box();
......@@ -1048,8 +1049,8 @@ void setupBuiltins() {
builtins_module->giveAttr("__import__", new BoxedBuiltinFunctionOrMethod(import_func, "__import__",
{ None, None, None, new BoxedInt(-1) }));
enumerate_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedEnumerate::gcHandler, 0, sizeof(BoxedEnumerate),
false, "enumerate");
enumerate_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedEnumerate::gcHandler, 0, 0,
sizeof(BoxedEnumerate), false, "enumerate");
enumerate_cls->giveAttr(
"__new__",
new BoxedFunction(boxRTFunction((void*)BoxedEnumerate::new_, UNKNOWN, 3, 1, false, false), { boxInt(0) }));
......
......@@ -296,7 +296,7 @@ void setupSys() {
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");
sys_flags_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)BoxedSysFlags::__new__, UNKNOWN, 1, 0, true, true)));
......
......@@ -179,7 +179,7 @@ void setupThread() {
thread_module->giveAttr(
"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(
"acquire", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::acquire, BOXED_BOOL, 2, 1, false, false),
......@@ -191,13 +191,15 @@ void setupThread() {
thread_lock_cls->giveAttr("__exit__", new BoxedFunction(boxRTFunction((void*)BoxedThreadLock::exit, NONE, 4)));
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->freeze();
thread_module->giveAttr("_local", thread_local_cls);
BoxedClass* ThreadError = BoxedHeapClass::create(type_cls, Exception, NULL, Exception->attrs_offset,
Exception->tp_basicsize, false, "error");
BoxedClass* ThreadError
= BoxedHeapClass::create(type_cls, Exception, NULL, Exception->attrs_offset, Exception->tp_weaklistoffset,
Exception->tp_basicsize, false, "error");
ThreadError->giveAttr("__module__", boxStrConstant("thread"));
ThreadError->freeze();
......
......@@ -1545,7 +1545,8 @@ static Box* methodGetDoc(Box* b, void*) {
}
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__",
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1)));
......@@ -1556,7 +1557,8 @@ void setupCAPI() {
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__",
new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3)));
method_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2,
......@@ -1564,14 +1566,14 @@ void setupCAPI() {
method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL));
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");
wrapperdescr_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__get__, UNKNOWN, 3)));
wrapperdescr_cls->freeze();
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(
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true)));
wrapperobject_cls->freeze();
......
......@@ -271,9 +271,9 @@ Box* instanceSetitem(Box* _inst, Box* key, Box* value) {
void setupClassobj() {
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,
offsetof(BoxedInstance, attrs), sizeof(BoxedInstance), false, "instance");
offsetof(BoxedInstance, attrs), 0, sizeof(BoxedInstance), false, "instance");
classobj_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)classobjNew, UNKNOWN, 4, 0, false, false)));
......
......@@ -572,15 +572,15 @@ static Box* dict_repr(PyObject* self) noexcept {
}
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");
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_values_cls = BoxedHeapClass::create(type_cls, object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false,
"dict_values");
dict_items_cls = BoxedHeapClass::create(type_cls, object_cls, &dictViewGCHandler, 0, sizeof(BoxedDictView), false,
"dict_items");
dict_values_cls = BoxedHeapClass::create(type_cls, object_cls, &dictViewGCHandler, 0, 0, sizeof(BoxedDictView),
false, "dict_values");
dict_items_cls = BoxedHeapClass::create(type_cls, object_cls, &dictViewGCHandler, 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)));
......
......@@ -38,11 +38,9 @@ public:
int f_skipnextlf; /* Skip next \n */
PyObject* f_encoding;
PyObject* f_errors;
#if 0
PyObject* weakreflist; /* List of weak references */
#endif
int unlocked_count; /* Num. currently running sections of code
using f_fp with the GIL released. */
int unlocked_count; /* Num. currently running sections of code
using f_fp with the GIL released. */
int readable;
int writable;
......
......@@ -33,7 +33,7 @@
namespace pyston {
static uint64_t next_stack_addr = 0x3270000000L;
static uint64_t next_stack_addr = 0x4270000000L;
static std::deque<uint64_t> available_addrs;
// There should be a better way of getting this:
......@@ -298,8 +298,9 @@ void generatorDestructor(Box* b) {
}
void setupGenerator() {
generator_cls = BoxedHeapClass::create(type_cls, object_cls, &generatorGCHandler, offsetof(BoxedGenerator, attrs),
sizeof(BoxedGenerator), false, "generator");
generator_cls
= BoxedHeapClass::create(type_cls, object_cls, &generatorGCHandler, offsetof(BoxedGenerator, attrs),
offsetof(BoxedGenerator, weakreflist), sizeof(BoxedGenerator), false, "generator");
generator_cls->simple_destructor = generatorDestructor;
generator_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)generatorIter, typeFromClass(generator_cls), 1)));
......
......@@ -178,9 +178,9 @@ Box* xrangeReversed(Box* self) {
}
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,
sizeof(BoxedXrangeIterator), false, "rangeiterator");
0, sizeof(BoxedXrangeIterator), false, "rangeiterator");
xrange_cls->giveAttr(
"__new__",
......
......@@ -142,7 +142,7 @@ extern "C" PyObject* PySeqIter_New(PyObject* seq) noexcept {
void setupIter() {
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("__hasnext__", new BoxedFunction(boxRTFunction((void*)seqiterHasnext, BOXED_BOOL, 1)));
......@@ -150,7 +150,7 @@ void setupIter() {
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("__hasnext__", new BoxedFunction(boxRTFunction((void*)seqreviterHasnext, BOXED_BOOL, 1)));
......@@ -158,7 +158,7 @@ void setupIter() {
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");
iterwrapper_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)iterwrapperNext, UNKNOWN, 1)));
......
......@@ -625,7 +625,7 @@ extern "C" void listIteratorGCHandler(GCVisitor* v, Box* b) {
}
extern "C" Box* listNew(Box* cls, Box* container) {
assert(cls == list_cls);
assert(isSubclass(static_cast<BoxedClass*>(cls), list_cls));
if (container == None)
return new BoxedList();
......@@ -764,9 +764,9 @@ extern "C" int PyList_SetSlice(PyObject* a, Py_ssize_t ilow, Py_ssize_t ihigh, P
}
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");
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");
list_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)listLen, BOXED_INT, 1)));
......
......@@ -287,14 +287,15 @@ void BoxedClass::freeze() {
is_constant = true;
}
BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size,
bool is_user_defined)
BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset,
int instance_size, bool is_user_defined)
: 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) {
// Zero out the CPython tp_* slots:
memset(&tp_name, 0, (char*)(&tp_version_tag + 1) - (char*)(&tp_name));
tp_basicsize = instance_size;
tp_weaklistoffset = weaklist_offset;
tp_flags |= Py_TPFLAGS_CHECKTYPES;
tp_flags |= Py_TPFLAGS_BASETYPE;
......@@ -343,6 +344,15 @@ BoxedClass::BoxedClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset
if (base && cls && str_cls)
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
if (attrs_offset) {
assert(tp_basicsize >= attrs_offset + sizeof(HCAttrs));
......@@ -357,9 +367,10 @@ void BoxedClass::finishInitialization() {
commonClassSetup(this);
}
BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, 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) {
BoxedHeapClass::BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset,
int instance_size, bool is_user_defined, BoxedString* name)
: 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_mapping = &as_mapping;
......@@ -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,
int instance_size, bool is_user_defined, const std::string& name) {
return create(metaclass, base, gc_visit, attrs_offset, instance_size, is_user_defined, new BoxedString(name), NULL);
int weaklist_offset, int instance_size, bool is_user_defined,
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,
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(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
// expectations as to who was going to calculate them:
......@@ -3680,11 +3696,12 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
BoxedClass* made;
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 {
assert(base->tp_basicsize % sizeof(void*) == 0);
made = BoxedHeapClass::create(metatype, base, NULL, base->tp_basicsize, base->tp_basicsize + sizeof(HCAttrs),
true, name, bases);
made = BoxedHeapClass::create(metatype, base, NULL, base->tp_basicsize, base->tp_weaklistoffset,
base->tp_basicsize + sizeof(HCAttrs), true, name, bases);
}
// TODO: how much of these should be in BoxedClass::finishInitialization()?
......
......@@ -246,8 +246,8 @@ Box* setNonzero(BoxedSet* self) {
using namespace pyston::set;
void setupSet() {
set_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &setIteratorGCHandler, 0, sizeof(BoxedSet), false,
"setiterator");
set_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &setIteratorGCHandler, 0, 0, sizeof(BoxedSet),
false, "setiterator");
set_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1)));
set_iterator_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)setiteratorNext, UNKNOWN, 1)));
......
......@@ -33,6 +33,7 @@ class BoxedSet : public Box {
public:
typedef std::unordered_set<Box*, PyHasher, PyEq, StlCompatAllocator<Box*>> Set;
Set s;
Box** weakreflist; /* List of weak references */
BoxedSet() __attribute__((visibility("default"))) {}
......
......@@ -2218,7 +2218,7 @@ void setupStr() {
str_cls->simple_destructor = strDestructor;
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");
str_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, BOXED_BOOL, 1)));
......
......@@ -186,8 +186,8 @@ Box* superInit(Box* _self, Box* _type, Box* obj) {
}
void setupSuper() {
super_cls
= BoxedHeapClass::create(type_cls, object_cls, &BoxedSuper::gcHandler, 0, sizeof(BoxedSuper), false, "super");
super_cls = BoxedHeapClass::create(type_cls, object_cls, &BoxedSuper::gcHandler, 0, 0, sizeof(BoxedSuper), false,
"super");
super_cls->giveAttr("__getattribute__", new BoxedFunction(boxRTFunction((void*)superGetattribute, UNKNOWN, 2)));
super_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)superRepr, STR, 1)));
......
......@@ -107,8 +107,8 @@ Box* BoxedTraceback::getLines(Box* b) {
}
void setupTraceback() {
traceback_cls = BoxedHeapClass::create(type_cls, object_cls, BoxedTraceback::gcHandler, 0, sizeof(BoxedTraceback),
false, "traceback");
traceback_cls = BoxedHeapClass::create(type_cls, object_cls, BoxedTraceback::gcHandler, 0, 0,
sizeof(BoxedTraceback), false, "traceback");
traceback_cls->giveAttr("getLines", new BoxedFunction(boxRTFunction((void*)BoxedTraceback::getLines, UNKNOWN, 1)));
......
......@@ -386,8 +386,8 @@ extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) {
void setupTuple() {
tuple_iterator_cls
= BoxedHeapClass::create(type_cls, object_cls, &tupleIteratorGCHandler, 0, sizeof(BoxedTuple), false, "tuple");
tuple_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &tupleIteratorGCHandler, 0, 0, sizeof(BoxedTuple),
false, "tuple");
tuple_cls->giveAttr("__new__", new BoxedFunction(boxRTFunction((void*)tupleNew, UNKNOWN, 1, 0, true, true)));
CLFunction* getitem = createRTFunction(2, 0, 0, 0);
......
This diff is collapsed.
......@@ -198,7 +198,8 @@ protected:
// creation due to bootstrapping issues.
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();
};
......@@ -215,16 +216,18 @@ public:
// These functions are the preferred way to construct new types:
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,
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:
// 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
// creation due to bootstrapping issues.
BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size, bool is_user_defined,
BoxedString* name);
BoxedHeapClass(BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int weaklist_offset, int instance_size,
bool is_user_defined, BoxedString* name);
friend void setupRuntime();
......@@ -577,6 +580,9 @@ public:
class BoxedGenerator : public Box {
public:
HCAttrs attrs;
Box** weakreflist;
BoxedFunctionBase* function;
Box* arg1, *arg2, *arg3;
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 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:
r = weakref.ref(o)
print "passed", type(o)
print "passed", extra
return r
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():
1
pass
wr = test_wr(test)
print wr() == test
#print weakref.getweakrefs(test)[0] == wr
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