Commit 251f417a authored by Kevin Modzelewski's avatar Kevin Modzelewski

Import and switch to the CPython way of handling some inheritance functionality

parent 49ee07fa
......@@ -412,7 +412,7 @@ typedef PyObject *(*allocfunc)(PyTypeObject *, Py_ssize_t);
struct PyMethodDef *tp_methods;\
struct PyMemberDef *tp_members;\
struct PyGetSetDef *tp_getset;\
struct _typeobject *tp_base;\
PyTypeObject *tp_base;\
PyObject *tp_dict;\
descrgetfunc tp_descr_get;\
descrsetfunc tp_descr_set;\
......@@ -456,7 +456,6 @@ struct _typeobject {
void* _hcattrs;
char _dep_getattrs[56]; // FIXME: this is hardcoding the size of this particular implementation of std::unordered_map
char _ics[32];
void* _base;
void* _gcvisit_func;
int _attrs_offset;
bool _flags[2];
......
This diff is collapsed.
......@@ -40,6 +40,7 @@ MAKE_CHECK(List, list_cls)
MAKE_CHECK(Tuple, tuple_cls)
MAKE_CHECK(Dict, dict_cls)
MAKE_CHECK(Slice, slice_cls)
MAKE_CHECK(Type, type_cls)
#ifdef Py_USING_UNICODE
MAKE_CHECK(Unicode, unicode_cls)
......
......@@ -253,7 +253,7 @@ extern "C" bool isSubclass(BoxedClass* child, BoxedClass* parent) {
while (child) {
if (child == parent)
return true;
child = child->base;
child = child->tp_base;
}
return false;
}
......@@ -345,7 +345,7 @@ void BoxedClass::freeze() {
BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
int instance_size, bool is_user_defined)
: BoxVar(metaclass, 0), base(base), gc_visit(gc_visit), attrs_offset(attrs_offset), is_constant(false),
: BoxVar(metaclass, 0), gc_visit(gc_visit), attrs_offset(attrs_offset), is_constant(false),
is_user_defined(is_user_defined) {
// Zero out the CPython tp_* slots:
......@@ -355,6 +355,8 @@ BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_
tp_flags |= Py_TPFLAGS_HEAPTYPE;
tp_flags |= Py_TPFLAGS_CHECKTYPES;
tp_base = base;
if (metaclass == NULL) {
assert(type_cls == NULL);
} else {
......@@ -639,16 +641,16 @@ Box* typeLookup(BoxedClass* cls, const std::string& attr, GetattrRewriteArgs* re
val = cls->getattr(attr, rewrite_args);
assert(rewrite_args->out_success);
if (!val and cls->base) {
if (!val and cls->tp_base) {
rewrite_args->out_success = false;
rewrite_args->obj = obj_saved->getAttr(offsetof(BoxedClass, base));
val = typeLookup(cls->base, attr, rewrite_args);
rewrite_args->obj = obj_saved->getAttr(offsetof(BoxedClass, tp_base));
val = typeLookup(cls->tp_base, attr, rewrite_args);
}
return val;
} else {
val = cls->getattr(attr, NULL);
if (!val and cls->base)
return typeLookup(cls->base, attr, NULL);
if (!val and cls->tp_base)
return typeLookup(cls->tp_base, attr, NULL);
return val;
}
}
......
......@@ -66,7 +66,7 @@ Box* superGetattribute(Box* _s, Box* _attr) {
if (!skip) {
// We don't support multiple inheritance yet, so the lookup order is simple:
Box* r = typeLookup(s->type->base, attr->s, NULL);
Box* r = typeLookup(s->type->tp_base, attr->s, NULL);
if (r) {
return processDescriptor(r, (s->obj == s->obj_type ? None : s->obj), s->obj_type);
......
......@@ -284,8 +284,8 @@ extern "C" void typeGCHandler(GCVisitor* v, Box* b) {
BoxedClass* cls = (BoxedClass*)b;
if (cls->base)
v->visit(cls->base);
if (cls->tp_base)
v->visit(cls->tp_base);
if (cls->tp_dict)
v->visit(cls->tp_dict);
}
......@@ -804,7 +804,7 @@ void setupRuntime() {
root_hcls = HiddenClass::makeRoot();
gc::registerPermanentRoot(root_hcls);
object_cls = new BoxedHeapClass(NULL, NULL, &boxGCHandler, 0, sizeof(Box), false);
object_cls = new BoxedClass(NULL, NULL, &boxGCHandler, 0, sizeof(Box), false);
type_cls
= new BoxedHeapClass(NULL, object_cls, &typeGCHandler, offsetof(BoxedClass, attrs), sizeof(BoxedClass), false);
type_cls->cls = type_cls;
......
......@@ -174,10 +174,6 @@ class BoxedClass : public BoxVar {
public:
typedef void (*gcvisit_func)(GCVisitor*, Box*);
protected:
BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size,
bool is_user_defined);
public:
PyTypeObject_BODY;
......@@ -197,10 +193,6 @@ public:
Box* callReprIC(Box* obj);
bool callNonzeroIC(Box* obj);
// Only a single base supported for now.
// Is NULL iff this is object_cls
BoxedClass* base;
gcvisit_func gc_visit;
// Offset of the HCAttrs object or 0 if there are no hcattrs.
......@@ -223,6 +215,9 @@ public:
bool hasGenericGetattr() { return true; }
void freeze();
BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size,
bool is_user_defined);
};
class BoxedHeapClass : public BoxedClass {
......@@ -244,11 +239,9 @@ static_assert(offsetof(pyston::BoxedClass, cls) == offsetof(struct _typeobject,
static_assert(offsetof(pyston::BoxedClass, tp_name) == offsetof(struct _typeobject, tp_name), "");
static_assert(offsetof(pyston::BoxedClass, attrs) == offsetof(struct _typeobject, _hcls), "");
static_assert(offsetof(pyston::BoxedClass, dependent_icgetattrs) == offsetof(struct _typeobject, _dep_getattrs), "");
static_assert(offsetof(pyston::BoxedClass, base) == offsetof(struct _typeobject, _base), "");
static_assert(offsetof(pyston::BoxedClass, gc_visit) == offsetof(struct _typeobject, _gcvisit_func), "");
static_assert(sizeof(pyston::BoxedClass) == sizeof(struct _typeobject), "");
static_assert(offsetof(pyston::BoxedHeapClass, base) == offsetof(PyHeapTypeObject, ht_type._base), "");
static_assert(offsetof(pyston::BoxedHeapClass, as_number) == offsetof(PyHeapTypeObject, as_number), "");
static_assert(offsetof(pyston::BoxedHeapClass, as_mapping) == offsetof(PyHeapTypeObject, as_mapping), "");
static_assert(offsetof(pyston::BoxedHeapClass, as_sequence) == offsetof(PyHeapTypeObject, as_sequence), "");
......
......@@ -347,6 +347,56 @@ static PyTypeObject slots_tester_num = {
0, /* tp_free */
};
typedef struct {
slots_tester_object base;
int n2;
} slots_tester_object_sub;
static PyTypeObject slots_tester_sub = {
PyVarObject_HEAD_INIT(NULL, 0)
"slots_test.slots_tester_sub", /* tp_name */
sizeof(slots_tester_object_sub), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
0, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
&slots_tester_seq, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
};
// Tests the correctness of the CAPI slots when the attributes get set in Python code:
static PyObject *
call_funcs(PyObject* _module, PyObject* args) {
......@@ -519,10 +569,15 @@ initslots_test(void)
if (res < 0)
return;
res = PyType_Ready(&slots_tester_sub);
if (res < 0)
return;
// Not sure if the result of PyInt_FromLong needs to be decref'd
PyDict_SetItemString(slots_tester_seq.tp_dict, "set_through_tpdict", PyInt_FromLong(123));
PyModule_AddObject(m, "SlotsTesterSeq", (PyObject *)&slots_tester_seq);
PyModule_AddObject(m, "SlotsTesterMap", (PyObject *)&slots_tester_map);
PyModule_AddObject(m, "SlotsTesterNum", (PyObject *)&slots_tester_num);
PyModule_AddObject(m, "SlotsTesterSub", (PyObject *)&slots_tester_sub);
}
......@@ -39,6 +39,9 @@ for i in xrange(3):
print hex(t)
print oct(t)
su = slots_test.SlotsTesterSub(5)
print su
class C(object):
def __repr__(self):
print "__repr__()"
......
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