Commit f78c923d authored by Kevin Modzelewski's avatar Kevin Modzelewski

Fix some hacks around static classes

Or maybe it's just hacking it up some more.
parent ce233891
......@@ -653,6 +653,7 @@ init_io(void)
// Pyston change: during init we have to supply the module name by ourself.
_PyIO_unsupported_operation = PyObject_CallFunction((PyObject *)&PyType_Type, "s(OO){s:s}",
"UnsupportedOperation", PyExc_ValueError, PyExc_IOError, "__module__", "io");
PyGC_RegisterStaticConstant(_PyIO_unsupported_operation);
// _PyIO_unsupported_operation = PyObject_CallFunction(
// (PyObject *)&PyType_Type, "s(OO){}",
// "UnsupportedOperation", PyExc_ValueError, PyExc_IOError);
......
......@@ -519,6 +519,8 @@ static PyTypeObject* make_type(char *type, PyTypeObject* base, char**fields, int
}
result = PyObject_CallFunction((PyObject*)&PyType_Type, "s(O){sOss}",
type, base, "_fields", fnames, "__module__", "_ast");
// Pyston addition:
PyGC_RegisterStaticConstant(result);
Py_DECREF(fnames);
return (PyTypeObject*)result;
}
......
......@@ -593,6 +593,9 @@ PyErr_NewException(const char *name, PyObject *base, PyObject *dict)
/* Create a real new-style class. */
result = PyObject_CallFunction((PyObject *)&PyType_Type, "sOO",
dot+1, bases, dict);
// Pyston change:
// This should probably be the responsibility of the caller, but just do it here for now:
PyGC_RegisterStaticConstant(result);
failure:
Py_XDECREF(bases);
Py_XDECREF(mydict);
......
......@@ -6926,6 +6926,17 @@ Box* _typeNew(BoxedClass* metatype, BoxedString* name, BoxedTuple* bases, BoxedD
bases, total_slots);
made->tp_dictoffset = dict_offset;
// XXX Hack: the classes vector lists all classes that have untracked references to them.
// This is pretty much any class created in C code, since the C code will tend to hold on
// to a reference to the created class. So in the BoxedClass constructor we add the new class to
// "classes", which will cause the class to get decref'd at the end.
// But for classes created from Python, we don't have this extra untracked reference.
// Rather than fix up the plumbing for now, just reach into the other system and remove this
// class from the list.
// This hack also exists in BoxedHeapClass::create
RELEASE_ASSERT(classes.back() == made, "");
classes.pop_back();
if (boxedSlots) {
// Set ht_slots
BoxedTuple* slotsTuple = BoxedTuple::create(final_slot_names.size());
......
......@@ -633,6 +633,31 @@ static Box* typeCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args
return typeCallInner<S>(rewrite_args, argspec, arg1, arg2, arg3, args, keyword_names);
}
// This function only exists for the corner case in typeCallInternal that should get removed anyway:
Box* typeCall(Box* obj, BoxedTuple* vararg, BoxedDict* kwargs) {
assert(vararg->cls == tuple_cls);
bool pass_kwargs = (kwargs && kwargs->d.size());
int n = vararg->size();
int args_to_pass = n + 1 + (pass_kwargs ? 1 : 0); // 1 for obj, 1 for kwargs
Box** args = NULL;
if (args_to_pass > 3)
args = (Box**)alloca(sizeof(Box*) * (args_to_pass - 3));
Box* arg1, *arg2, *arg3;
arg1 = obj;
for (int i = 0; i < n; i++) {
getArg(i + 1, arg1, arg2, arg3, args) = vararg->elts[i];
}
if (pass_kwargs)
getArg(n + 1, arg1, arg2, arg3, args) = kwargs;
return typeCallInternal<CXX>(NULL, NULL, ArgPassSpec(n + 1, 0, false, pass_kwargs), arg1, arg2, arg3, args, NULL);
}
// For use on __init__ return values
static Box* assertInitNone(STOLEN(Box*) rtn, STOLEN(Box*) obj) {
AUTO_DECREF(rtn);
......@@ -1339,32 +1364,6 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
return made;
}
Box* typeCall(Box* obj, BoxedTuple* vararg, BoxedDict* kwargs) {
RELEASE_ASSERT(0, "this shouldn't get called any more");
assert(vararg->cls == tuple_cls);
bool pass_kwargs = (kwargs && kwargs->d.size());
int n = vararg->size();
int args_to_pass = n + 1 + (pass_kwargs ? 1 : 0); // 1 for obj, 1 for kwargs
Box** args = NULL;
if (args_to_pass > 3)
args = (Box**)alloca(sizeof(Box*) * (args_to_pass - 3));
Box* arg1, *arg2, *arg3;
arg1 = obj;
for (int i = 0; i < n; i++) {
getArg(i + 1, arg1, arg2, arg3, args) = vararg->elts[i];
}
if (pass_kwargs)
getArg(n + 1, arg1, arg2, arg3, args) = kwargs;
return typeCallInternal<CXX>(NULL, NULL, ArgPassSpec(n + 1, 0, false, pass_kwargs), arg1, arg2, arg3, args, NULL);
}
static Box* typeDict(Box* obj, void* context) {
if (obj->cls->instancesHaveHCAttrs())
return PyDictProxy_New(obj->getAttrWrapper());
......@@ -1445,18 +1444,8 @@ extern "C" Box* createUserClass(BoxedString* name, Box* _bases, Box* _attr_dict)
Box* r = runtimeCall(metaclass, ArgPassSpec(3), name, _bases, _attr_dict, NULL, NULL);
RELEASE_ASSERT(r, "");
// XXX Hack: the classes vector lists all classes that have untracked references to them.
// This is pretty much any class created in C code, since the C code will tend to hold on
// to a reference to the created class. So in the BoxedClass constructor we add the new class to
// "classes", which will cause the class to get decref'd at the end.
// But for classes created from Python, we don't have this extra untracked reference.
// Rather than fix up the plumbing for now, just reach into the other system and remove this
// class from the list.
// This hack also exists in BoxedHeapClass::create
if (isSubclass(r->cls, type_cls)) {
RELEASE_ASSERT(classes.back() == r, "");
classes.pop_back();
}
if (isSubclass(r->cls, type_cls))
assert(classes.back() != r);
return r;
} catch (ExcInfo e) {
......@@ -4073,6 +4062,12 @@ extern "C" PyObject* PyGC_RegisterStaticConstant(Box* b) noexcept {
return b;
}
extern "C" PyObject* PyGC_RegisterStaticClass(Box* b) noexcept {
assert(PyType_Check(b));
classes.push_back(static_cast<BoxedClass*>(b));
return b;
}
extern "C" void _PyUnicode_Fini(void);
static int _check_and_flush(FILE* stream) {
......
# expected: reffail
import gc
# Dynamically create new classes and instances of those classes in such a way
......
# expected: reffail
class MM(type):
def __new__(*args):
print "MM.__new__", args[:3]
......
# expected: reffail
# object.__new__ doesn't complain if __init__ is overridden:
class C1(object):
......
# expected: reffail
print 'basic test'
class C(object):
__slots__ = ['a', 'b', '__private_var']
......
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