Commit d5ba641b authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'getitem'

parents 15e86e4f 01a0b1a7
......@@ -142,6 +142,7 @@ COMMON_CXXFLAGS += -fexceptions -fno-rtti
COMMON_CXXFLAGS += -Wno-invalid-offsetof # allow the use of "offsetof", and we'll just have to make sure to only use it legally.
COMMON_CXXFLAGS += -DENABLE_INTEL_JIT_EVENTS=$(ENABLE_INTEL_JIT_EVENTS)
COMMON_CXXFLAGS += -I$(DEPS_DIR)/pypa-install/include
COMMON_CXXFLAGS += -Wno-comment
ifeq ($(ENABLE_VALGRIND),0)
COMMON_CXXFLAGS += -DNVALGRIND
......
......@@ -32,24 +32,160 @@ namespace pyston {
#define FLAG_SIZE_T 1
static PyObject* va_build_value(const char* fmt, va_list va, int flags) {
int len = strlen(fmt);
if (len == 0)
return None;
static int countformat(const char* format, int endchar) {
int count = 0;
int level = 0;
while (level > 0 || *format != endchar) {
switch (*format) {
case '\0':
/* Premature end */
PyErr_SetString(PyExc_SystemError, "unmatched paren in format");
return -1;
case '(':
case '[':
case '{':
if (level == 0)
count++;
level++;
break;
case ')':
case ']':
case '}':
level--;
break;
case '#':
case '&':
case ',':
case ':':
case ' ':
case '\t':
break;
default:
if (level == 0)
count++;
}
format++;
}
return count;
}
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_mkdict(const char**, va_list *, int, int, int) noexcept;
static PyObject* do_mkvalue(const char**, va_list*, int) noexcept;
static PyObject* do_mkvalue(const char** p_format, va_list* p_va, int flags) noexcept {
for (;;) {
switch (*(*p_format)++) {
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);
case '{':
return do_mkdict(p_format, p_va, '}', countformat(*p_format, '}'), flags);
#endif
if (len == 1) {
switch (*fmt) {
case 'b':
case 'B':
case 'h':
case 'i':
return PyInt_FromLong((long)va_arg(va, int));
return PyInt_FromLong((long)va_arg(*p_va, int));
case 'H':
return PyInt_FromLong((long)va_arg(*p_va, unsigned int));
case 'N':
case 'S':
case 'O':
if (**p_format == '&') {
typedef PyObject* (*converter)(void*);
converter func = va_arg(*p_va, converter);
void* arg = va_arg(*p_va, void*);
++*p_format;
return (*func)(arg);
} else {
PyObject* v;
v = va_arg(*p_va, PyObject*);
if (v != NULL) {
if (*(*p_format - 1) != 'N')
Py_INCREF(v);
} else if (!PyErr_Occurred())
/* If a NULL was passed
* because a call that should
* have constructed a value
* failed, that's OK, and we
* pass the error on; but if
* no error occurred it's not
* clear that the caller knew
* what she was doing. */
PyErr_SetString(PyExc_SystemError, "NULL object passed to Py_BuildValue");
return v;
}
default:
RELEASE_ASSERT(0, "%c", *fmt);
RELEASE_ASSERT(0, "%c", *((*p_format) - 1));
}
}
abort();
}
static PyObject* do_mktuple(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;
if ((v = PyTuple_New(n)) == 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;
}
PyTuple_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) {
int n = countformat(fmt, '\0');
if (n < 0)
return NULL;
if (n == 0)
return None;
va_list lva;
__va_copy(lva, va);
if (n == 1)
return do_mkvalue(&fmt, &lva, flags);
return do_mktuple(&fmt, &lva, '\0', n, flags);
}
RELEASE_ASSERT(0, "");
extern "C" PyObject* Py_VaBuildValue(const char* format, va_list va) {
return va_build_value(format, va, 0);
}
extern "C" PyObject* _Py_BuildValue_SizeT(const char* fmt, ...) {
......
This diff is collapsed.
......@@ -27,7 +27,7 @@ struct wrapper_def {
int offset;
void* function; // "generic" handler that gets put in the tp_* slot which proxies to the python version
wrapperfunc wrapper; // "wrapper" that ends up getting called by the Python-visible WrapperDescr
// exists in CPython: const char* doc
const char* doc;
int flags;
// exists in CPython: PyObject *name_strobj
};
......@@ -83,8 +83,9 @@ class BoxedWrapperDescriptor : public Box {
public:
const wrapper_def* wrapper;
BoxedClass* type;
BoxedWrapperDescriptor(const wrapper_def* wrapper, BoxedClass* type)
: Box(wrapperdescr_cls), wrapper(wrapper), type(type) {}
void* wrapped;
BoxedWrapperDescriptor(const wrapper_def* wrapper, BoxedClass* type, void* wrapped)
: Box(wrapperdescr_cls), wrapper(wrapper), type(type), wrapped(wrapped) {}
static Box* __get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner);
};
......@@ -104,14 +105,12 @@ public:
int flags = self->descr->wrapper->flags;
wrapperfunc wrapper = self->descr->wrapper->wrapper;
assert(self->descr->wrapper->offset > 0);
char* ptr = (char*)self->descr->type + self->descr->wrapper->offset;
void* wrapped = *reinterpret_cast<void**>(ptr);
if (flags & PyWrapperFlag_KEYWORDS) {
wrapperfunc_kwds wk = (wrapperfunc_kwds)wrapper;
return (*wk)(self->obj, args, wrapped, kwds);
return (*wk)(self->obj, args, self->descr->wrapped, kwds);
} else {
return (*wrapper)(self->obj, args, wrapped);
return (*wrapper)(self->obj, args, self->descr->wrapped);
}
abort();
}
......
......@@ -497,7 +497,7 @@ Box* exceptionRepr(Box* b) {
static BoxedClass* makeBuiltinException(BoxedClass* base, const char* name) {
BoxedClass* cls
= new BoxedClass(type_cls, base, NULL, offsetof(BoxedException, attrs), sizeof(BoxedException), false);
= new BoxedHeapClass(type_cls, base, NULL, offsetof(BoxedException, attrs), sizeof(BoxedException), false);
cls->giveAttr("__name__", boxStrConstant(name));
cls->giveAttr("__module__", boxStrConstant("exceptions"));
......@@ -521,7 +521,7 @@ extern "C" PyObject* PyErr_NewException(char* name, PyObject* _base, PyObject* d
try {
BoxedClass* base = Exception;
BoxedClass* cls
= new BoxedClass(type_cls, base, NULL, offsetof(BoxedException, attrs), sizeof(BoxedException), true);
= new BoxedHeapClass(type_cls, base, NULL, offsetof(BoxedException, attrs), sizeof(BoxedException), true);
char* dot_pos = strchr(name, '.');
RELEASE_ASSERT(dot_pos, "");
......@@ -702,7 +702,7 @@ void setupBuiltins() {
builtins_module->giveAttr("print", new BoxedFunction(boxRTFunction((void*)print, NONE, 0, 0, true, true)));
notimplemented_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(Box), false);
notimplemented_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(Box), false);
notimplemented_cls->giveAttr("__name__", boxStrConstant("NotImplementedType"));
notimplemented_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)notimplementedRepr, STR, 1)));
notimplemented_cls->freeze();
......@@ -795,7 +795,8 @@ void setupBuiltins() {
builtins_module->giveAttr("issubclass", issubclass_obj);
enumerate_cls = new BoxedClass(type_cls, object_cls, &BoxedEnumerate::gcHandler, 0, sizeof(BoxedEnumerate), false);
enumerate_cls
= new BoxedHeapClass(type_cls, object_cls, &BoxedEnumerate::gcHandler, 0, sizeof(BoxedEnumerate), false);
enumerate_cls->giveAttr("__name__", boxStrConstant("enumerate"));
enumerate_cls->giveAttr(
"__new__",
......
......@@ -126,7 +126,7 @@ void setupSys() {
sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX));
sys_flags_cls = new BoxedClass(type_cls, object_cls, BoxedSysFlags::gcHandler, 0, sizeof(BoxedSysFlags), false);
sys_flags_cls = new BoxedHeapClass(type_cls, object_cls, BoxedSysFlags::gcHandler, 0, sizeof(BoxedSysFlags), false);
sys_flags_cls->giveAttr("__name__", boxStrConstant("flags"));
sys_flags_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)BoxedSysFlags::__new__, UNKNOWN, 1, 0, true, true)));
......
......@@ -322,7 +322,10 @@ extern "C" int PyObject_Not(PyObject* o) {
extern "C" PyObject* PyObject_Call(PyObject* callable_object, PyObject* args, PyObject* kw) {
try {
return runtimeCall(callable_object, ArgPassSpec(0, 0, true, true), args, kw, NULL, NULL, NULL);
if (kw)
return runtimeCall(callable_object, ArgPassSpec(0, 0, true, true), args, kw, NULL, NULL, NULL);
else
return runtimeCall(callable_object, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
} catch (Box* b) {
Py_FatalError("unimplemented");
}
......@@ -699,7 +702,12 @@ extern "C" PyObject* PyNumber_ToBase(PyObject* n, int base) {
}
extern "C" Py_ssize_t PyNumber_AsSsize_t(PyObject* o, PyObject* exc) {
Py_FatalError("unimplemented");
RELEASE_ASSERT(o->cls != long_cls, "unhandled");
RELEASE_ASSERT(o->cls == int_cls, "??");
int64_t n = static_cast<BoxedInt*>(o)->n;
static_assert(sizeof(n) == sizeof(Py_ssize_t), "");
return n;
}
extern "C" Py_ssize_t PyUnicode_GET_SIZE(PyObject*) {
......@@ -753,7 +761,7 @@ BoxedModule* importTestExtension(const std::string& name) {
}
void setupCAPI() {
capifunc_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedCApiFunction), false);
capifunc_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedCApiFunction), false);
capifunc_cls->giveAttr("__name__", boxStrConstant("capifunc"));
capifunc_cls->giveAttr("__repr__",
......@@ -765,7 +773,7 @@ void setupCAPI() {
capifunc_cls->freeze();
method_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedMethodDescriptor), false);
method_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedMethodDescriptor), false);
method_cls->giveAttr("__name__", boxStrConstant("method"));
method_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3)));
......@@ -773,13 +781,13 @@ void setupCAPI() {
0, true, true)));
method_cls->freeze();
wrapperdescr_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedWrapperDescriptor), false);
wrapperdescr_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedWrapperDescriptor), false);
wrapperdescr_cls->giveAttr("__name__", boxStrConstant("wrapper_descriptor"));
wrapperdescr_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__get__, UNKNOWN, 3)));
wrapperdescr_cls->freeze();
wrapperobject_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedWrapperObject), false);
wrapperobject_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedWrapperObject), false);
wrapperobject_cls->giveAttr("__name__", boxStrConstant("method-wrapper"));
wrapperobject_cls->giveAttr(
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true)));
......
......@@ -241,10 +241,10 @@ Box* instanceSetitem(Box* _inst, Box* key, Box* value) {
}
void setupClassobj() {
classobj_cls = new BoxedClass(type_cls, object_cls, &BoxedClassobj::gcHandler, offsetof(BoxedClassobj, attrs),
sizeof(BoxedClassobj), false);
instance_cls = new BoxedClass(type_cls, object_cls, &BoxedInstance::gcHandler, offsetof(BoxedInstance, attrs),
sizeof(BoxedInstance), false);
classobj_cls = new BoxedHeapClass(type_cls, object_cls, &BoxedClassobj::gcHandler, offsetof(BoxedClassobj, attrs),
sizeof(BoxedClassobj), false);
instance_cls = new BoxedHeapClass(type_cls, object_cls, &BoxedInstance::gcHandler, offsetof(BoxedInstance, attrs),
sizeof(BoxedInstance), false);
classobj_cls->giveAttr("__name__", boxStrConstant("classobj"));
......
......@@ -378,7 +378,7 @@ extern "C" void dictIteratorGCHandler(GCVisitor* v, Box* b) {
}
void setupDict() {
dict_iterator_cls = new BoxedClass(type_cls, object_cls, &dictIteratorGCHandler, 0, sizeof(BoxedDict), false);
dict_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &dictIteratorGCHandler, 0, sizeof(BoxedDict), false);
dict_cls->giveAttr("__name__", boxStrConstant("dict"));
dict_cls->giveAttr("__len__", new BoxedFunction(boxRTFunction((void*)dictLen, BOXED_INT, 1)));
......
......@@ -177,8 +177,8 @@ extern "C" void generatorGCHandler(GCVisitor* v, Box* b) {
void setupGenerator() {
generator_cls = new BoxedClass(type_cls, object_cls, &generatorGCHandler, offsetof(BoxedGenerator, attrs),
sizeof(BoxedGenerator), false);
generator_cls = new BoxedHeapClass(type_cls, object_cls, &generatorGCHandler, offsetof(BoxedGenerator, attrs),
sizeof(BoxedGenerator), false);
generator_cls->giveAttr("__name__", boxStrConstant("generator"));
generator_cls->giveAttr("__iter__",
new BoxedFunction(boxRTFunction((void*)generatorIter, typeFromClass(generator_cls), 1)));
......
......@@ -113,10 +113,10 @@ Box* xrangeIter(Box* self) {
}
void setupXrange() {
xrange_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedXrange), false);
xrange_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedXrange), false);
xrange_cls->giveAttr("__name__", boxStrConstant("xrange"));
xrange_iterator_cls = new BoxedClass(type_cls, object_cls, &BoxedXrangeIterator::xrangeIteratorGCHandler, 0,
sizeof(BoxedXrangeIterator), false);
xrange_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &BoxedXrangeIterator::xrangeIteratorGCHandler, 0,
sizeof(BoxedXrangeIterator), false);
xrange_iterator_cls->giveAttr("__name__", boxStrConstant("rangeiterator"));
xrange_cls->giveAttr(
......
......@@ -57,7 +57,7 @@ Box* seqiterNext(Box* s) {
}
void setupIter() {
seqiter_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedSeqIter), false);
seqiter_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedSeqIter), false);
seqiter_cls->giveAttr("__name__", boxStrConstant("iterator"));
seqiter_cls->giveAttr("next", new BoxedFunction(boxRTFunction((void*)seqiterNext, UNKNOWN, 1)));
......
......@@ -553,7 +553,7 @@ Box* listEq(BoxedList* self, Box* rhs) {
}
void setupList() {
list_iterator_cls = new BoxedClass(type_cls, object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), false);
list_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &listIteratorGCHandler, 0, sizeof(BoxedList), false);
list_cls->giveAttr("__name__", boxStrConstant("list"));
......
......@@ -389,6 +389,20 @@ BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_
gc::registerPermanentRoot(this);
}
BoxedHeapClass::BoxedHeapClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset,
int instance_size, bool is_user_defined)
: BoxedClass(metaclass, base, gc_visit, attrs_offset, instance_size, is_user_defined), ht_name(NULL),
ht_slots(NULL) {
tp_as_number = &as_number;
tp_as_mapping = &as_mapping;
tp_as_sequence = &as_sequence;
tp_as_buffer = &as_buffer;
// just make sure these get zero-initialized:
assert(as_sequence.sq_item == NULL);
}
std::string getFullNameOfClass(BoxedClass* cls) {
Box* b = cls->getattr("__name__");
assert(b);
......@@ -3272,10 +3286,10 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
BoxedClass* made;
if (base->instancesHaveAttrs()) {
made = new BoxedClass(cls, base, NULL, base->attrs_offset, base->tp_basicsize, true);
made = new BoxedHeapClass(cls, base, NULL, base->attrs_offset, base->tp_basicsize, true);
} else {
assert(base->tp_basicsize % sizeof(void*) == 0);
made = new BoxedClass(cls, base, NULL, base->tp_basicsize, base->tp_basicsize + sizeof(HCAttrs), true);
made = new BoxedHeapClass(cls, base, NULL, base->tp_basicsize, base->tp_basicsize + sizeof(HCAttrs), true);
}
made->giveAttr("__module__", boxString(getCurrentModule()->name()));
......
......@@ -216,7 +216,7 @@ void setupSet() {
set_cls->giveAttr("__name__", boxStrConstant("set"));
frozenset_cls->giveAttr("__name__", boxStrConstant("frozenset"));
set_iterator_cls = new BoxedClass(type_cls, object_cls, &setIteratorGCHandler, 0, sizeof(BoxedSet), false);
set_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &setIteratorGCHandler, 0, sizeof(BoxedSet), false);
set_iterator_cls->giveAttr("__name__", boxStrConstant("setiterator"));
set_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)setiteratorHasnext, BOXED_BOOL, 1)));
......
......@@ -1037,7 +1037,7 @@ static PyBufferProcs string_as_buffer = {
};
void setupStr() {
str_iterator_cls = new BoxedClass(type_cls, object_cls, &strIteratorGCHandler, 0, sizeof(BoxedString), false);
str_iterator_cls = new BoxedHeapClass(type_cls, object_cls, &strIteratorGCHandler, 0, sizeof(BoxedString), false);
str_iterator_cls->giveAttr("__name__", boxStrConstant("striterator"));
str_iterator_cls->giveAttr("__hasnext__",
new BoxedFunction(boxRTFunction((void*)BoxedStringIterator::hasnext, BOXED_BOOL, 1)));
......
......@@ -125,7 +125,7 @@ Box* superNew(Box* _cls, Box* _type, Box* obj) {
}
void setupSuper() {
super_cls = new BoxedClass(type_cls, object_cls, &BoxedSuper::gcHandler, 0, sizeof(BoxedSuper), false);
super_cls = new BoxedHeapClass(type_cls, object_cls, &BoxedSuper::gcHandler, 0, sizeof(BoxedSuper), false);
super_cls->giveAttr("__name__", boxStrConstant("super"));
......
......@@ -382,7 +382,8 @@ extern "C" void tupleIteratorGCHandler(GCVisitor* v, Box* b) {
void setupTuple() {
tuple_iterator_cls = new BoxedClass(type_cls, object_cls, &tupleIteratorGCHandler, 0, sizeof(BoxedTuple), false);
tuple_iterator_cls
= new BoxedHeapClass(type_cls, object_cls, &tupleIteratorGCHandler, 0, sizeof(BoxedTuple), false);
tuple_cls->giveAttr("__name__", boxStrConstant("tuple"));
......
......@@ -780,21 +780,22 @@ void setupRuntime() {
root_hcls = HiddenClass::makeRoot();
gc::registerPermanentRoot(root_hcls);
object_cls = new BoxedClass(NULL, NULL, &boxGCHandler, 0, sizeof(Box), false);
type_cls = new BoxedClass(NULL, object_cls, &typeGCHandler, offsetof(BoxedClass, attrs), sizeof(BoxedClass), false);
object_cls = new BoxedHeapClass(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;
object_cls->cls = type_cls;
none_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(Box), false);
none_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(Box), false);
None = new Box(none_cls);
gc::registerPermanentRoot(None);
// You can't actually have an instance of basestring
basestring_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(Box), false);
basestring_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(Box), false);
// TODO we leak all the string data!
str_cls = new BoxedClass(type_cls, basestring_cls, NULL, 0, sizeof(BoxedString), false);
unicode_cls = new BoxedClass(type_cls, basestring_cls, NULL, 0, sizeof(BoxedUnicode), false);
str_cls = new BoxedHeapClass(type_cls, basestring_cls, NULL, 0, sizeof(BoxedString), false);
unicode_cls = new BoxedHeapClass(type_cls, basestring_cls, NULL, 0, sizeof(BoxedUnicode), false);
// It wasn't safe to add __base__ attributes until object+type+str are set up, so do that now:
type_cls->giveAttr("__base__", object_cls);
......@@ -804,40 +805,42 @@ void setupRuntime() {
object_cls->giveAttr("__base__", None);
tuple_cls = new BoxedClass(type_cls, object_cls, &tupleGCHandler, 0, sizeof(BoxedTuple), false);
tuple_cls = new BoxedHeapClass(type_cls, object_cls, &tupleGCHandler, 0, sizeof(BoxedTuple), false);
EmptyTuple = new BoxedTuple({});
gc::registerPermanentRoot(EmptyTuple);
module_cls = new BoxedClass(type_cls, object_cls, NULL, offsetof(BoxedModule, attrs), sizeof(BoxedModule), false);
module_cls
= new BoxedHeapClass(type_cls, object_cls, NULL, offsetof(BoxedModule, attrs), sizeof(BoxedModule), false);
// TODO it'd be nice to be able to do these in the respective setupType methods,
// but those setup methods probably want access to these objects.
// We could have a multi-stage setup process, but that seems overkill for now.
bool_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedBool), false);
int_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedInt), false);
complex_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedComplex), false);
bool_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedBool), false);
int_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedInt), false);
complex_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedComplex), false);
// TODO we're leaking long memory!
long_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedLong), false);
float_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedFloat), false);
function_cls = new BoxedClass(type_cls, object_cls, &functionGCHandler, offsetof(BoxedFunction, attrs),
sizeof(BoxedFunction), false);
long_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedLong), false);
float_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedFloat), false);
function_cls = new BoxedHeapClass(type_cls, object_cls, &functionGCHandler, offsetof(BoxedFunction, attrs),
sizeof(BoxedFunction), false);
instancemethod_cls
= new BoxedClass(type_cls, object_cls, &instancemethodGCHandler, 0, sizeof(BoxedInstanceMethod), false);
list_cls = new BoxedClass(type_cls, object_cls, &listGCHandler, 0, sizeof(BoxedList), false);
slice_cls = new BoxedClass(type_cls, object_cls, &sliceGCHandler, 0, sizeof(BoxedSlice), false);
dict_cls = new BoxedClass(type_cls, object_cls, &dictGCHandler, 0, sizeof(BoxedDict), false);
file_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedFile), false);
set_cls = new BoxedClass(type_cls, object_cls, &setGCHandler, 0, sizeof(BoxedSet), false);
frozenset_cls = new BoxedClass(type_cls, object_cls, &setGCHandler, 0, sizeof(BoxedSet), false);
member_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedMemberDescriptor), false);
closure_cls = new BoxedClass(type_cls, object_cls, &closureGCHandler, offsetof(BoxedClosure, attrs),
sizeof(BoxedClosure), false);
property_cls = new BoxedClass(type_cls, object_cls, &propertyGCHandler, 0, sizeof(BoxedProperty), false);
= new BoxedHeapClass(type_cls, object_cls, &instancemethodGCHandler, 0, sizeof(BoxedInstanceMethod), false);
list_cls = new BoxedHeapClass(type_cls, object_cls, &listGCHandler, 0, sizeof(BoxedList), false);
slice_cls = new BoxedHeapClass(type_cls, object_cls, &sliceGCHandler, 0, sizeof(BoxedSlice), false);
dict_cls = new BoxedHeapClass(type_cls, object_cls, &dictGCHandler, 0, sizeof(BoxedDict), false);
file_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedFile), false);
set_cls = new BoxedHeapClass(type_cls, object_cls, &setGCHandler, 0, sizeof(BoxedSet), false);
frozenset_cls = new BoxedHeapClass(type_cls, object_cls, &setGCHandler, 0, sizeof(BoxedSet), false);
member_cls = new BoxedHeapClass(type_cls, object_cls, NULL, 0, sizeof(BoxedMemberDescriptor), false);
closure_cls = new BoxedHeapClass(type_cls, object_cls, &closureGCHandler, offsetof(BoxedClosure, attrs),
sizeof(BoxedClosure), false);
property_cls = new BoxedHeapClass(type_cls, object_cls, &propertyGCHandler, 0, sizeof(BoxedProperty), false);
staticmethod_cls
= new BoxedClass(type_cls, object_cls, &staticmethodGCHandler, 0, sizeof(BoxedStaticmethod), false);
classmethod_cls = new BoxedClass(type_cls, object_cls, &classmethodGCHandler, 0, sizeof(BoxedClassmethod), false);
attrwrapper_cls = new BoxedClass(type_cls, object_cls, &AttrWrapper::gcHandler, 0, sizeof(AttrWrapper), false);
= new BoxedHeapClass(type_cls, object_cls, &staticmethodGCHandler, 0, sizeof(BoxedStaticmethod), false);
classmethod_cls
= new BoxedHeapClass(type_cls, object_cls, &classmethodGCHandler, 0, sizeof(BoxedClassmethod), false);
attrwrapper_cls = new BoxedHeapClass(type_cls, object_cls, &AttrWrapper::gcHandler, 0, sizeof(AttrWrapper), false);
STR = typeFromClass(str_cls);
BOXED_INT = typeFromClass(int_cls);
......
......@@ -172,6 +172,13 @@ class conservative_unordered_map
: public std::unordered_map<K, V, Hash, KeyEqual, StlCompatAllocator<std::pair<const K, V> > > {};
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;
......@@ -195,7 +202,6 @@ public:
// Is NULL iff this is object_cls
BoxedClass* base;
typedef void (*gcvisit_func)(GCVisitor*, Box*);
gcvisit_func gc_visit;
// Offset of the HCAttrs object or 0 if there are no hcattrs.
......@@ -217,12 +223,21 @@ public:
// will need to update this once we support tp_getattr-style overriding:
bool hasGenericGetattr() { return true; }
BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size,
bool is_user_defined);
void freeze();
};
class BoxedHeapClass : public BoxedClass {
public:
PyNumberMethods as_number;
PyMappingMethods as_mapping;
PySequenceMethods as_sequence;
PyBufferProcs as_buffer;
PyObject* ht_name, *ht_slots;
BoxedHeapClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_visit, int attrs_offset, int instance_size,
bool is_user_defined);
};
static_assert(sizeof(pyston::Box) == sizeof(struct _object), "");
static_assert(offsetof(pyston::Box, cls) == offsetof(struct _object, ob_type), "");
......@@ -234,6 +249,13 @@ static_assert(offsetof(pyston::BoxedClass, base) == offsetof(struct _typeobject,
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), "");
static_assert(offsetof(pyston::BoxedHeapClass, as_buffer) == offsetof(PyHeapTypeObject, as_buffer), "");
static_assert(sizeof(pyston::BoxedHeapClass) == sizeof(PyHeapTypeObject), "");
class HiddenClass : public ConservativeGCObject {
private:
......
......@@ -29,7 +29,7 @@ slots_tester_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
}
static PyObject *
slots_tester_repr(slots_tester_object *obj)
slots_tester_seq_repr(slots_tester_object *obj)
{
char buf[80];
snprintf(buf, sizeof(buf), "<my custom repr: %d>", obj->n);
......@@ -37,7 +37,7 @@ slots_tester_repr(slots_tester_object *obj)
}
static PyObject *
slots_tester_call(slots_tester_object *obj, PyObject *args, PyObject *kw)
slots_tester_seq_call(slots_tester_object *obj, PyObject *args, PyObject *kw)
{
if (!PyArg_ParseTuple(args, ""))
return NULL;
......@@ -45,11 +45,33 @@ slots_tester_call(slots_tester_object *obj, PyObject *args, PyObject *kw)
return PyInt_FromLong(obj->n);
}
PyDoc_STRVAR(slots_tester_doc, "slots_tester doc");
static PyObject*
slots_tester_seq_item(slots_tester_object *obj, Py_ssize_t i)
{
if (i < 0 || i >= 5) {
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
return NULL;
}
return PyInt_FromLong(i + obj->n);
}
PyDoc_STRVAR(slots_tester_seq_doc, "slots_tester_seq doc");
static PyTypeObject slots_tester = {
static PySequenceMethods slots_tester_seq_as_sequence = {
(lenfunc)0,
(binaryfunc)0, /* sq_concat */
(ssizeargfunc)0, /* sq_repeat */
(ssizeargfunc)slots_tester_seq_item, /* sq_item */
(ssizessizeargfunc)0, /* sq_slice */
0, /* sq_ass_item */
0, /* sq_ass_slice */
(objobjproc)0, /* sq_contains */
};
static PyTypeObject slots_tester_seq = {
PyVarObject_HEAD_INIT(NULL, 0)
"slots_test.slots_tester", /* tp_name */
"slots_test.slots_tester_seq", /* tp_name */
sizeof(slots_tester_object), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
......@@ -58,18 +80,83 @@ static PyTypeObject slots_tester = {
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
(reprfunc)slots_tester_repr, /* tp_repr */
(reprfunc)slots_tester_seq_repr, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
&slots_tester_seq_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
(ternaryfunc)slots_tester_call, /* tp_call */
(ternaryfunc)slots_tester_seq_call, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
slots_tester_seq_doc, /* 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 */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
slots_tester_new, /* tp_new */
0, /* tp_free */
};
static Py_ssize_t slots_tester_map_length(slots_tester_object* obj) {
return obj->n;
}
static PyObject* slots_tester_map_subscript(slots_tester_object* obj, PyObject* key) {
int n2 = PyInt_AsLong(key);
return PyInt_FromLong(n2 + obj->n);
}
static int slots_tester_map_ass_sub(slots_tester_object* obj, PyObject* key, PyObject* value) {
int n2 = PyInt_AsLong(key);
printf("Assigning to subscript for object with n=%d, key=%d, set/delete=%d\n", obj->n, n2, !!value);
return 0;
}
static PyMappingMethods slots_tester_map_asmapping = {
(lenfunc)slots_tester_map_length, /*mp_length*/
(binaryfunc)slots_tester_map_subscript, /*mp_subscript*/
(objobjargproc)slots_tester_map_ass_sub, /*mp_ass_subscript*/
};
static PyTypeObject slots_tester_map= {
PyVarObject_HEAD_INIT(NULL, 0)
"slots_test.slots_tester_map", /* tp_name */
sizeof(slots_tester_object), /* 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 */
&slots_tester_map_asmapping, /* 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, /* tp_flags */
slots_tester_doc, /* tp_doc */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
......@@ -120,6 +207,44 @@ call_funcs(PyObject* _module, PyObject* args) {
printf("tp_call doesnt exist\n");
}
if (cls->tp_as_mapping) {
printf("tp_as_mapping exists\n");
PyMappingMethods* map = cls->tp_as_mapping;
if (map->mp_subscript) {
PyObject* rtn = map->mp_subscript(obj, PyInt_FromLong(1));
printf("mp_subscript exists and returned\n");
Py_DECREF(rtn);
} else {
printf("mp_subscript does not exist\n");
}
if (map->mp_length) {
Py_ssize_t rtn = map->mp_length(obj);
printf("mp_length exists and returned %ld\n", rtn);
}
} else {
printf("tp_as_mapping doesnt exist\n");
}
if (cls->tp_as_sequence) {
printf("tp_as_sequence exists\n");
PySequenceMethods* seq = cls->tp_as_sequence;
if (seq->sq_length) {
Py_ssize_t rtn = seq->sq_length(obj);
printf("sq_length exists and returned %ld\n", rtn);
}
if (seq->sq_item) {
PyObject* rtn = cls->tp_as_sequence->sq_item(obj, 1);
printf("sq_item exists and returned\n");
Py_DECREF(rtn);
}
} else {
printf("tp_as_sequence doesnt exist\n");
}
Py_DECREF(obj);
Py_RETURN_NONE;
......@@ -139,12 +264,17 @@ initslots_test(void)
if (m == NULL)
return;
int res = PyType_Ready(&slots_tester);
int res = PyType_Ready(&slots_tester_seq);
if (res < 0)
return;
res = PyType_Ready(&slots_tester_map);
if (res < 0)
return;
// Not sure if the result of PyInt_FromLong needs to be decref'd
PyDict_SetItemString(slots_tester.tp_dict, "set_through_tpdict", PyInt_FromLong(123));
PyDict_SetItemString(slots_tester_seq.tp_dict, "set_through_tpdict", PyInt_FromLong(123));
PyModule_AddObject(m, "SlotsTester", (PyObject *)&slots_tester);
PyModule_AddObject(m, "SlotsTesterSeq", (PyObject *)&slots_tester_seq);
PyModule_AddObject(m, "SlotsTesterMap", (PyObject *)&slots_tester_map);
}
import slots_test
for i in xrange(3):
t = slots_test.SlotsTester(i + 5)
print t, repr(t), t()
t = slots_test.SlotsTesterSeq(i + 5)
print t, repr(t), t(), t[2]
print slots_test.SlotsTester.set_through_tpdict, slots_test.SlotsTester(5).set_through_tpdict
# print slots_test.SlotsTesterSeq.__doc__
print slots_test.SlotsTesterSeq.set_through_tpdict, slots_test.SlotsTesterSeq(5).set_through_tpdict
for i in xrange(3):
t = slots_test.SlotsTesterMap(i + 5)
print len(t), t[2]
t[1] = 5
del t[2]
class C(object):
def __repr__(self):
print "__repr__()"
return "<C object>"
def __getitem__(self, idx):
print "__getitem__", idx
return idx - 5
def __len__(self):
print "__len__"
return 3
slots_test.call_funcs(C())
# Test to make sure that updating an existing class also updates the tp_* slots:
def repr2(self):
return "repr2()"
C.repr2 = repr2
C.__repr__ = repr2
slots_test.call_funcs(C())
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