Commit 8780a2bb authored by Kevin Modzelewski's avatar Kevin Modzelewski

A number of random improvements that will be needed for multiple inheritance

While most of this code is unexercised with just this commit, I wanted
to add it so that it's more clear what the multiple inheritance changes
actually are.
parent a635223f
......@@ -180,7 +180,13 @@ void RewriterVar::addAttrGuard(int offset, uint64_t val, bool negate) {
}
void Rewriter::_addAttrGuard(RewriterVar* var, int offset, uint64_t val, bool negate) {
assembler::Register var_reg = var->getInReg();
// TODO if var is a constant, we will end up emitting something like
// mov $0x123, %rax
// cmp $0x10(%rax), %rdi
// when we could just do
// cmp ($0x133), %rdi
assembler::Register var_reg = var->getInReg(Location::any(), /* allow_constant_in_reg */ true);
if (isLargeConstant(val)) {
assembler::Register reg = allocReg(Location::any(), /* otherThan */ var_reg);
assert(reg != var_reg);
......@@ -206,7 +212,12 @@ RewriterVar* RewriterVar::getAttr(int offset, Location dest, assembler::MovType
}
void Rewriter::_getAttr(RewriterVar* result, RewriterVar* ptr, int offset, Location dest, assembler::MovType type) {
assembler::Register ptr_reg = ptr->getInReg();
// TODO if var is a constant, we will end up emitting something like
// mov $0x123, %rax
// mov $0x10(%rax), %rdi
// when we could just do
// mov ($0x133), %rdi
assembler::Register ptr_reg = ptr->getInReg(Location::any(), /* allow_constant_in_reg */ true);
// It's okay to bump the use now, since it's fine to allocate the result
// in the same register as ptr
......
......@@ -293,15 +293,16 @@ extern "C" PyObject* PyObject_CallFunctionObjArgs(PyObject* callable, ...) noexc
}
extern "C" PyObject* PyObject_CallObject(PyObject* obj, PyObject* args) noexcept {
RELEASE_ASSERT(args, ""); // actually it looks like this is allowed to be NULL
RELEASE_ASSERT(args->cls == tuple_cls, "");
// TODO do something like this? not sure if this is safe; will people expect that calling into a known function
// won't end up doing a GIL check?
// threading::GLDemoteRegion _gil_demote;
try {
Box* r = runtimeCall(obj, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
Box* r;
if (args)
r = runtimeCall(obj, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
else
r = runtimeCall(obj, ArgPassSpec(0, 0, false, false), NULL, NULL, NULL, NULL, NULL);
return r;
} catch (ExcInfo e) {
Py_FatalError("unimplemented");
......
......@@ -82,7 +82,7 @@ static int _ustrlen(Py_UNICODE* u) {
#endif
static PyObject* do_mktuple(const char**, va_list*, int, int, int) noexcept;
// static PyObject *do_mklist(const char**, va_list *, int, int, int) noexcept;
static PyObject* do_mklist(const char**, va_list*, int, int, int) noexcept;
// static PyObject *do_mkdict(const char**, va_list *, int, int, int) noexcept;
static PyObject* do_mkvalue(const char**, va_list*, int) noexcept;
......@@ -92,10 +92,10 @@ static PyObject* do_mkvalue(const char** p_format, va_list* p_va, int flags) noe
case '(':
return do_mktuple(p_format, p_va, ')', countformat(*p_format, ')'), flags);
#if 0
case '[':
return do_mklist(p_format, p_va, ']', countformat(*p_format, ']'), flags);
#if 0
case '{':
return do_mkdict(p_format, p_va, '}', countformat(*p_format, '}'), flags);
#endif
......@@ -239,6 +239,43 @@ static PyObject* do_mktuple(const char** p_format, va_list* p_va, int endchar, i
return v;
}
static PyObject* do_mklist(const char** p_format, va_list* p_va, int endchar, int n, int flags) noexcept {
PyObject* v;
int i;
int itemfailed = 0;
if (n < 0)
return NULL;
v = PyList_New(n);
if (v == NULL)
return NULL;
/* Note that we can't bail immediately on error as this will leak
refcounts on any 'N' arguments. */
for (i = 0; i < n; i++) {
PyObject* w = do_mkvalue(p_format, p_va, flags);
if (w == NULL) {
itemfailed = 1;
Py_INCREF(Py_None);
w = Py_None;
}
PyList_SET_ITEM(v, i, w);
}
if (itemfailed) {
/* do_mkvalue() should have already set an error */
Py_DECREF(v);
return NULL;
}
if (**p_format != endchar) {
Py_DECREF(v);
PyErr_SetString(PyExc_SystemError, "Unmatched paren in format");
return NULL;
}
if (endchar)
++*p_format;
return v;
}
static PyObject* va_build_value(const char* fmt, va_list va, int flags) noexcept {
int n = countformat(fmt, '\0');
......
......@@ -630,8 +630,8 @@ LargeArena::LargeFreeChunk* LargeArena::get_from_size_list(LargeFreeChunk** list
section->free_chunk_map[i] = 0;
}
assert(section->num_free_chunks >= size >> CHUNK_BITS);
section->num_free_chunks -= size >> CHUNK_BITS;
assert(section->num_free_chunks >= 0);
return free_chunks;
}
......
......@@ -501,6 +501,8 @@ extern "C" Py_ssize_t PySequence_Index(PyObject* o, PyObject* value) noexcept {
extern "C" PyObject* PySequence_Tuple(PyObject* o) noexcept {
if (o->cls == tuple_cls)
return o;
if (PyList_Check(o))
return PyList_AsTuple(o);
Py_FatalError("unimplemented");
}
......
......@@ -49,6 +49,19 @@ extern "C" PyObject** PyList_Items(PyObject* op) noexcept {
return &static_cast<BoxedList*>(op)->elts->elts[0];
}
extern "C" PyObject* PyList_AsTuple(PyObject* v) noexcept {
PyObject* w;
PyObject** p, **q;
Py_ssize_t n;
if (v == NULL || !PyList_Check(v)) {
PyErr_BadInternalCall();
return NULL;
}
auto l = static_cast<BoxedList*>(v);
return new BoxedTuple(BoxedTuple::GCVector(l->elts->elts, l->elts->elts + l->size));
}
extern "C" Box* listRepr(BoxedList* self) {
LOCK_REGION(self->lock.asRead());
......
......@@ -406,6 +406,10 @@ extern "C" void typeGCHandler(GCVisitor* v, Box* b) {
v->visit(cls->tp_base);
if (cls->tp_dict)
v->visit(cls->tp_dict);
if (cls->tp_mro)
v->visit(cls->tp_mro);
if (cls->tp_bases)
v->visit(cls->tp_bases);
if (cls->tp_flags & Py_TPFLAGS_HEAPTYPE) {
BoxedHeapClass* hcls = static_cast<BoxedHeapClass*>(cls);
......
# expected: fail
# - wip
# Testing the basic multiple-inheritance rules and functionality:
class C(object):
n = 1
def c(self):
print "C.c()"
def f(self):
print "C.f()", self.n
class D(object):
n = 2
def d(self):
print "D.d()"
def f(self):
print "D.f()", self.n
class E(C, D):
pass
class F(D, C):
pass
class G(E, D):
pass
for o in [C(), D(), E(), F()]:
print type(o), type(o).mro(), type(o).__mro__
o.f()
try:
o.c()
except Exception, e:
print e
try:
o.d()
except Exception, e:
print e
# Testing invalid multiple inheritance hierarchies:
# Conflicting MRO:
try:
class G(E, F):
pass
except TypeError, e:
# This is silly but I think actually reasonable: the error message for this case is implementation-specific,
# since it depends on dict ordering rules (says either "for bases E, F" or "for bases F, E", depending on ordering).
# Canonicalize the error message by sorting the characters in it:
print ''.join(sorted(e.message)).strip()
# Conflicting MRO:
try:
class H(C, F):
pass
except TypeError, e:
print ''.join(sorted(e.message)).strip()
# "instance lay-out conflict"
try:
class I(str, int):
pass
except TypeError, e:
print e
# Testing the way super() behaves with multiple inheritance:
class S(C, D):
n = 3
def c(self):
print "S.c()"
super(S, self).c()
def d(self):
print "S.d()"
super(S, self).d()
def f(self):
print "S.f()"
print self.n, super(S, self).n, super(C, self).n
# TODO: Pyston doesn't support the full super.__getattribute__, so this will abort
# rather than throw an exception:
# try:
# print super(D, self).n
# except Exception as e:
# print e
super(S, self).f()
super(C, self).f()
s = S()
s.c()
s.d()
s.f()
......@@ -5,6 +5,9 @@ class B(object):
o.arg1 = arg1
return o
def f(self):
print "B.f()"
class C(B):
def __new__(cls, arg1, arg2):
print "C.__new__", arg2
......@@ -13,9 +16,14 @@ class C(B):
print super(C, cls), super(C, o)
return o
def f(self):
print "C.f()"
super(C, self).f()
c = C(1, 2)
print c.arg1
print c.arg2
c.f()
try:
super(1)
......
......@@ -413,16 +413,16 @@ if __name__ == "__main__":
]
tests += big_tests
LIB_DIR = os.path.join(sys.prefix, "lib/python2.7")
for t in tests:
bn = os.path.basename(t)
assert bn.endswith(".py")
module_name = bn[:-3]
try:
__import__(module_name)
if os.path.exists(os.path.join(LIB_DIR, module_name)) or \
os.path.exists(os.path.join(LIB_DIR, module_name + ".py")) or \
module_name in sys.builtin_module_names:
raise Exception("Error: %s hides builtin module '%s'" % (t, module_name))
except ImportError:
pass
# good
for t in TOSKIP:
assert t in ("%s/t.py" % TEST_DIR, "%s/t2.py" % TEST_DIR) or t in tests, t
......
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