Commit 20ae648b authored by Kevin Modzelewski's avatar Kevin Modzelewski

Misc fixes trying to get random to work

Has been failing with weird segfaults; hunting them down
parent 382eb293
...@@ -630,6 +630,7 @@ void setupBuiltins() { ...@@ -630,6 +630,7 @@ void setupBuiltins() {
/*BytesWarning =*/makeBuiltinException(Warning, "BytesWarning"); /*BytesWarning =*/makeBuiltinException(Warning, "BytesWarning");
MemoryError = makeBuiltinException(StandardError, "MemoryError"); MemoryError = makeBuiltinException(StandardError, "MemoryError");
BufferError = makeBuiltinException(StandardError, "BufferError"); BufferError = makeBuiltinException(StandardError, "BufferError");
/*NotImplementedError=*/makeBuiltinException(RuntimeError, "NotImplementedError");
repr_obj = new BoxedFunction(boxRTFunction((void*)repr, UNKNOWN, 1)); repr_obj = new BoxedFunction(boxRTFunction((void*)repr, UNKNOWN, 1));
builtins_module->giveAttr("repr", repr_obj); builtins_module->giveAttr("repr", repr_obj);
......
...@@ -35,6 +35,15 @@ public: ...@@ -35,6 +35,15 @@ public:
BoxedMethodDescriptor(PyMethodDef* method) : Box(method_cls), method(method) {} BoxedMethodDescriptor(PyMethodDef* method) : Box(method_cls), method(method) {}
static Box* __get__(BoxedMethodDescriptor* self, Box* inst, Box* owner) {
RELEASE_ASSERT(self->cls == method_cls, "");
if (inst == None)
return self;
// CPython apparently returns a "builtin_function_or_method" object
return boxInstanceMethod(inst, self);
}
static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) { static Box* __call__(BoxedMethodDescriptor* self, Box* obj, BoxedTuple* varargs, Box** _args) {
BoxedDict* kwargs = static_cast<BoxedDict*>(_args[0]); BoxedDict* kwargs = static_cast<BoxedDict*>(_args[0]);
...@@ -119,10 +128,14 @@ extern "C" void conservativeGCHandler(GCVisitor* v, Box* b) { ...@@ -119,10 +128,14 @@ extern "C" void conservativeGCHandler(GCVisitor* v, Box* b) {
} }
extern "C" PyObject* PyType_GenericAlloc(PyTypeObject* cls, Py_ssize_t nitems) { extern "C" PyObject* PyType_GenericAlloc(PyTypeObject* cls, Py_ssize_t nitems) {
if (nitems == 0) RELEASE_ASSERT(nitems == 0, "unimplemented");
return _PyObject_New(cls); RELEASE_ASSERT(cls->tp_itemsize == 0, "unimplemented");
Py_FatalError("unimplemented");
return NULL; auto rtn = (PyObject*)gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
memset(rtn, 0, cls->tp_basicsize);
PyObject_Init(rtn, cls);
return rtn;
} }
extern "C" int PyType_Ready(PyTypeObject* cls) { extern "C" int PyType_Ready(PyTypeObject* cls) {
...@@ -294,12 +307,22 @@ extern "C" void _PyErr_BadInternalCall(const char* filename, int lineno) { ...@@ -294,12 +307,22 @@ extern "C" void _PyErr_BadInternalCall(const char* filename, int lineno) {
} }
extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) { extern "C" PyObject* PyObject_Init(PyObject* op, PyTypeObject* tp) {
RELEASE_ASSERT(op, "");
RELEASE_ASSERT(tp, "");
assert(gc::isValidGCObject(op)); assert(gc::isValidGCObject(op));
assert(gc::isValidGCObject(tp)); assert(gc::isValidGCObject(tp));
RELEASE_ASSERT(op, "");
RELEASE_ASSERT(tp, "");
Py_TYPE(op) = tp; Py_TYPE(op) = tp;
// I think CPython defers the dict creation (equivalent of our initUserAttrs) to the
// first time that an attribute gets set.
// Our HCAttrs object already includes this optimization of no-allocation-if-empty,
// but it's nice to initialize the hcls here so we don't have to check it on every getattr/setattr.
// TODO It does mean that anything not defering to this function will have to call
// initUserAttrs themselves, though.
initUserAttrs(op, tp);
return op; return op;
} }
...@@ -316,8 +339,11 @@ extern "C" PyVarObject* PyObject_InitVar(PyVarObject* op, PyTypeObject* tp, Py_s ...@@ -316,8 +339,11 @@ extern "C" PyVarObject* PyObject_InitVar(PyVarObject* op, PyTypeObject* tp, Py_s
extern "C" PyObject* _PyObject_New(PyTypeObject* cls) { extern "C" PyObject* _PyObject_New(PyTypeObject* cls) {
assert(cls->tp_itemsize == 0); assert(cls->tp_itemsize == 0);
auto rtn = (PyObject*)gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON); auto rtn = (PyObject*)gc_alloc(cls->tp_basicsize, gc::GCKind::PYTHON);
rtn->cls = cls; // no memset for this function
PyObject_Init(rtn, cls);
return rtn; return rtn;
} }
...@@ -421,8 +447,12 @@ extern "C" PyObject* PyObject_RichCompare(PyObject* o1, PyObject* o2, int opid) ...@@ -421,8 +447,12 @@ extern "C" PyObject* PyObject_RichCompare(PyObject* o1, PyObject* o2, int opid)
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
extern "C" long PyObject_Hash(PyObject*) { extern "C" long PyObject_Hash(PyObject* o) {
Py_FatalError("unimplemented"); try {
return hash(o)->n;
} catch (Box* b) {
Py_FatalError("unimplemented");
}
} }
extern "C" int PyObject_IsTrue(PyObject* o) { extern "C" int PyObject_IsTrue(PyObject* o) {
...@@ -851,6 +881,8 @@ void setupCAPI() { ...@@ -851,6 +881,8 @@ void setupCAPI() {
method_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedMethodDescriptor), false); method_cls = new BoxedClass(type_cls, object_cls, NULL, 0, sizeof(BoxedMethodDescriptor), false);
method_cls->giveAttr("__name__", boxStrConstant("method")); method_cls->giveAttr("__name__", boxStrConstant("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, method_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__call__, UNKNOWN, 2,
0, true, true))); 0, true, true)));
method_cls->freeze(); method_cls->freeze();
......
...@@ -394,6 +394,36 @@ Box* longLshift(BoxedLong* v1, Box* _v2) { ...@@ -394,6 +394,36 @@ Box* longLshift(BoxedLong* v1, Box* _v2) {
} }
} }
Box* longRshift(BoxedLong* v1, Box* _v2) {
if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__rshift__' requires a 'long' object but received a '%s'",
getTypeName(v1)->c_str());
if (isSubclass(_v2->cls, long_cls)) {
BoxedLong* v2 = static_cast<BoxedLong*>(_v2);
if (mpz_cmp_si(v2->n, 0) < 0)
raiseExcHelper(ValueError, "negative shift count");
uint64_t n = asUnsignedLong(v2);
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_div_2exp(r->n, v1->n, n);
return r;
} else if (isSubclass(_v2->cls, int_cls)) {
BoxedInt* v2 = static_cast<BoxedInt*>(_v2);
if (v2->n < 0)
raiseExcHelper(ValueError, "negative shift count");
BoxedLong* r = new BoxedLong(long_cls);
mpz_init(r->n);
mpz_div_2exp(r->n, v1->n, v2->n);
return r;
} else {
return NotImplemented;
}
}
Box* longSub(BoxedLong* v1, Box* _v2) { Box* longSub(BoxedLong* v1, Box* _v2) {
if (!isSubclass(v1->cls, long_cls)) if (!isSubclass(v1->cls, long_cls))
raiseExcHelper(TypeError, "descriptor '__sub__' requires a 'long' object but received a '%s'", raiseExcHelper(TypeError, "descriptor '__sub__' requires a 'long' object but received a '%s'",
...@@ -605,6 +635,7 @@ void setupLong() { ...@@ -605,6 +635,7 @@ void setupLong() {
long_cls->giveAttr("__ne__", new BoxedFunction(boxRTFunction((void*)longNe, UNKNOWN, 2))); long_cls->giveAttr("__ne__", new BoxedFunction(boxRTFunction((void*)longNe, UNKNOWN, 2)));
long_cls->giveAttr("__lshift__", new BoxedFunction(boxRTFunction((void*)longLshift, UNKNOWN, 2))); long_cls->giveAttr("__lshift__", new BoxedFunction(boxRTFunction((void*)longLshift, UNKNOWN, 2)));
long_cls->giveAttr("__rshift__", new BoxedFunction(boxRTFunction((void*)longRshift, UNKNOWN, 2)));
long_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)longRepr, STR, 1))); long_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)longRepr, STR, 1)));
long_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)longStr, STR, 1))); long_cls->giveAttr("__str__", new BoxedFunction(boxRTFunction((void*)longStr, STR, 1)));
......
...@@ -447,6 +447,28 @@ BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_ ...@@ -447,6 +447,28 @@ BoxedClass::BoxedClass(BoxedClass* metaclass, BoxedClass* base, gcvisit_func gc_
gc::registerPermanentRoot(this); gc::registerPermanentRoot(this);
} }
std::string getFullNameOfClass(BoxedClass* cls) {
Box* b = cls->getattr("__name__");
assert(b);
ASSERT(b->cls == str_cls, "%p", b->cls);
BoxedString* name = static_cast<BoxedString*>(b);
b = cls->getattr("__module__");
if (!b)
return name->s;
assert(b);
if (b->cls != str_cls)
return name->s;
BoxedString* module = static_cast<BoxedString*>(b);
return module->s + "." + name->s;
}
std::string getFullTypeName(Box* o) {
return getFullNameOfClass(o->cls);
}
extern "C" const std::string* getNameOfClass(BoxedClass* cls) { extern "C" const std::string* getNameOfClass(BoxedClass* cls) {
Box* b = cls->getattr("__name__"); Box* b = cls->getattr("__name__");
assert(b); assert(b);
...@@ -1788,9 +1810,14 @@ extern "C" void dump(void* p) { ...@@ -1788,9 +1810,14 @@ extern "C" void dump(void* p) {
if (al->kind_id == gc::GCKind::PYTHON) { if (al->kind_id == gc::GCKind::PYTHON) {
printf("Python object\n"); printf("Python object\n");
Box* b = (Box*)p; Box* b = (Box*)p;
printf("Class: %s\n", getTypeName(b)->c_str()); printf("Class: %s\n", getFullTypeName(b).c_str());
if (isSubclass(b->cls, type_cls)) { if (isSubclass(b->cls, type_cls)) {
printf("Type name: %s\n", getNameOfClass(static_cast<BoxedClass*>(b))->c_str()); printf("Type name: %s\n", getFullNameOfClass(static_cast<BoxedClass*>(b)).c_str());
}
if (isSubclass(b->cls, str_cls)) {
printf("String value: %s\n", static_cast<BoxedString*>(b)->s.c_str());
} }
return; return;
} }
...@@ -3324,6 +3351,10 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) { ...@@ -3324,6 +3351,10 @@ Box* typeNew(Box* _cls, Box* arg1, Box* arg2, Box** _args) {
// Note: make sure to do this after assigning the attrs, since it will overwrite any defined __name__ // Note: make sure to do this after assigning the attrs, since it will overwrite any defined __name__
made->setattr("__name__", name, NULL); made->setattr("__name__", name, NULL);
// TODO this function (typeNew) should probably call PyType_Ready
made->tp_alloc = reinterpret_cast<decltype(cls->tp_alloc)>(PyType_GenericAlloc);
return made; return made;
} }
......
...@@ -324,8 +324,6 @@ extern "C" Box* createUserClass(std::string* name, Box* _bases, Box* _attr_dict) ...@@ -324,8 +324,6 @@ extern "C" Box* createUserClass(std::string* name, Box* _bases, Box* _attr_dict)
} }
assert(metaclass); assert(metaclass);
BoxedClass* made;
Box* r = runtimeCall(metaclass, ArgPassSpec(3), boxStringPtr(name), _bases, _attr_dict, NULL, NULL); Box* r = runtimeCall(metaclass, ArgPassSpec(3), boxStringPtr(name), _bases, _attr_dict, NULL, NULL);
RELEASE_ASSERT(r, ""); RELEASE_ASSERT(r, "");
return r; return r;
...@@ -389,6 +387,12 @@ static Box* functionGet(BoxedFunction* self, Box* inst, Box* owner) { ...@@ -389,6 +387,12 @@ static Box* functionGet(BoxedFunction* self, Box* inst, Box* owner) {
return boxInstanceMethod(inst, self); return boxInstanceMethod(inst, self);
} }
static Box* memberGet(BoxedMemberDescriptor* self, Box* inst, Box* owner) {
RELEASE_ASSERT(self->cls == member_cls, "");
Py_FatalError("unimplemented");
}
static Box* functionCall(BoxedFunction* self, Box* args, Box* kwargs) { static Box* functionCall(BoxedFunction* self, Box* args, Box* kwargs) {
RELEASE_ASSERT(self->cls == function_cls, "%s", getTypeName(self)->c_str()); RELEASE_ASSERT(self->cls == function_cls, "%s", getTypeName(self)->c_str());
...@@ -753,6 +757,7 @@ void setupRuntime() { ...@@ -753,6 +757,7 @@ void setupRuntime() {
module_cls->freeze(); module_cls->freeze();
member_cls->giveAttr("__name__", boxStrConstant("member")); member_cls->giveAttr("__name__", boxStrConstant("member"));
member_cls->giveAttr("__get__", new BoxedFunction(boxRTFunction((void*)memberGet, UNKNOWN, 3)));
member_cls->freeze(); member_cls->freeze();
closure_cls->giveAttr("__name__", boxStrConstant("closure")); closure_cls->giveAttr("__name__", boxStrConstant("closure"));
......
# skip-if: IMAGE != 'pyston_dbg'
# fail-if: '-n' in EXTRA_JIT_ARGS or '-O' in EXTRA_JIT_ARGS
# - failing to rewrite
import _random
class Random(_random.Random):
def __init__(self, a=None):
super(Random, self).seed(a)
for i in xrange(100):
r = Random(i)
print r.getrandbits(100)
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