Commit d1c5d853 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge branch 'getattr'

Things are getting pretty messy, but it's an incremental step towards doing things more
like CPython which should ultimately make things simpler.

The use of the tp_getattro slots (even though they're the CAPI slots) seems to lead to
about a ~7% improvement in interpreter-only speed.
parents c5f22166 b42de323
...@@ -737,12 +737,15 @@ void Assembler::cmp(Indirect mem, Immediate imm) { ...@@ -737,12 +737,15 @@ void Assembler::cmp(Indirect mem, Immediate imm) {
emitRex(rex); emitRex(rex);
emitByte(0x81); emitByte(0x81);
assert(-0x80 <= mem.offset && mem.offset < 0x80);
if (mem.offset == 0) { if (mem.offset == 0) {
emitModRM(0b00, 7, src_idx); emitModRM(0b00, 7, src_idx);
} else { } else if (-0x80 <= mem.offset && mem.offset < 0x80) {
emitModRM(0b01, 7, src_idx); emitModRM(0b01, 7, src_idx);
emitByte(mem.offset); emitByte(mem.offset);
} else {
assert((-1L << 31) <= mem.offset && mem.offset < (1L << 31) - 1);
emitModRM(0b10, 7, src_idx);
emitInt(mem.offset, 4);
} }
emitInt(val, 4); emitInt(val, 4);
......
This diff is collapsed.
...@@ -22,6 +22,7 @@ namespace pyston { ...@@ -22,6 +22,7 @@ namespace pyston {
// Returns if a slot was updated // Returns if a slot was updated
bool update_slot(BoxedClass* self, const std::string& attr) noexcept; bool update_slot(BoxedClass* self, const std::string& attr) noexcept;
void add_operators(BoxedClass* self) noexcept;
void fixup_slot_dispatchers(BoxedClass* self) noexcept; void fixup_slot_dispatchers(BoxedClass* self) noexcept;
void commonClassSetup(BoxedClass* cls); void commonClassSetup(BoxedClass* cls);
......
...@@ -98,6 +98,7 @@ public: ...@@ -98,6 +98,7 @@ public:
DEFAULT_CLASS(wrapperdescr_cls); DEFAULT_CLASS(wrapperdescr_cls);
static Box* __get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner); static Box* __get__(BoxedWrapperDescriptor* self, Box* inst, Box* owner);
static Box* __call__(BoxedWrapperDescriptor* descr, PyObject* self, BoxedTuple* args, Box** _args);
}; };
class BoxedWrapperObject : public Box { class BoxedWrapperObject : public Box {
......
...@@ -93,12 +93,6 @@ void setupBool() { ...@@ -93,12 +93,6 @@ void setupBool() {
bool_cls->giveAttr("__xor__", new BoxedFunction(boxRTFunction((void*)boolXor, BOXED_BOOL, 2))); bool_cls->giveAttr("__xor__", new BoxedFunction(boxRTFunction((void*)boolXor, BOXED_BOOL, 2)));
bool_cls->freeze(); bool_cls->freeze();
True = new BoxedBool(true);
False = new BoxedBool(false);
gc::registerPermanentRoot(True);
gc::registerPermanentRoot(False);
} }
void teardownBool() { void teardownBool() {
......
...@@ -194,6 +194,7 @@ public: ...@@ -194,6 +194,7 @@ public:
BoxedSysFlags() { BoxedSysFlags() {
auto zero = boxInt(0); auto zero = boxInt(0);
assert(zero);
division_warning = zero; division_warning = zero;
bytes_warning = zero; bytes_warning = zero;
no_user_site = zero; no_user_site = zero;
...@@ -297,8 +298,8 @@ void setupSys() { ...@@ -297,8 +298,8 @@ void setupSys() {
sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX)); sys_module->giveAttr("maxint", boxInt(PYSTON_INT_MAX));
sys_flags_cls = BoxedHeapClass::create(type_cls, object_cls, BoxedSysFlags::gcHandler, 0, 0, sizeof(BoxedSysFlags), sys_flags_cls = new BoxedHeapClass(object_cls, BoxedSysFlags::gcHandler, 0, 0, sizeof(BoxedSysFlags), false,
false, "flags"); new BoxedString("flags"));
sys_flags_cls->giveAttr("__new__", sys_flags_cls->giveAttr("__new__",
new BoxedFunction(boxRTFunction((void*)BoxedSysFlags::__new__, UNKNOWN, 1, 0, true, true))); new BoxedFunction(boxRTFunction((void*)BoxedSysFlags::__new__, UNKNOWN, 1, 0, true, true)));
#define ADD(name) \ #define ADD(name) \
...@@ -309,6 +310,7 @@ void setupSys() { ...@@ -309,6 +310,7 @@ void setupSys() {
ADD(no_user_site); ADD(no_user_site);
#undef ADD #undef ADD
sys_flags_cls->tp_mro = new BoxedTuple({ sys_flags_cls, object_cls });
sys_flags_cls->freeze(); sys_flags_cls->freeze();
sys_module->giveAttr("flags", new BoxedSysFlags()); sys_module->giveAttr("flags", new BoxedSysFlags());
...@@ -324,5 +326,6 @@ void setupSysEnd() { ...@@ -324,5 +326,6 @@ void setupSysEnd() {
PyLt()); PyLt());
sys_module->giveAttr("builtin_module_names", new BoxedTuple(std::move(builtin_module_names))); sys_module->giveAttr("builtin_module_names", new BoxedTuple(std::move(builtin_module_names)));
sys_flags_cls->finishInitialization();
} }
} }
...@@ -88,6 +88,19 @@ Box* BoxedWrapperDescriptor::__get__(BoxedWrapperDescriptor* self, Box* inst, Bo ...@@ -88,6 +88,19 @@ Box* BoxedWrapperDescriptor::__get__(BoxedWrapperDescriptor* self, Box* inst, Bo
return new BoxedWrapperObject(self, inst); return new BoxedWrapperObject(self, inst);
} }
Box* BoxedWrapperDescriptor::__call__(BoxedWrapperDescriptor* descr, PyObject* self, BoxedTuple* args, Box** _args) {
RELEASE_ASSERT(descr->cls == wrapperdescr_cls, "");
BoxedDict* kw = static_cast<BoxedDict*>(_args[0]);
if (!isSubclass(self->cls, descr->type))
raiseExcHelper(TypeError, "descriptor '' requires a '%s' object but received a '%s'",
getFullNameOfClass(descr->type).c_str(), getFullTypeName(self).c_str());
auto wrapper = new BoxedWrapperObject(descr, self);
return BoxedWrapperObject::__call__(wrapper, args, kw);
}
extern "C" void _PyErr_BadInternalCall(const char* filename, int lineno) noexcept { extern "C" void _PyErr_BadInternalCall(const char* filename, int lineno) noexcept {
Py_FatalError("unimplemented"); Py_FatalError("unimplemented");
} }
...@@ -264,12 +277,11 @@ extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr_name) noexcept ...@@ -264,12 +277,11 @@ extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr_name) noexcept
} }
extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexcept { extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexcept {
try { Box* r = getattrInternalGeneric(o, static_cast<BoxedString*>(name)->s.c_str(), NULL, false, false, NULL, NULL);
return getattr(o, static_cast<BoxedString*>(name)->s.c_str()); if (!r)
} catch (ExcInfo e) { PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name,
setCAPIException(e); PyString_AS_STRING(name));
return NULL; return r;
}
} }
extern "C" PyObject* _PyObject_GenericGetAttrWithDict(PyObject* obj, PyObject* name, PyObject* dict) noexcept { extern "C" PyObject* _PyObject_GenericGetAttrWithDict(PyObject* obj, PyObject* name, PyObject* dict) noexcept {
...@@ -1279,9 +1291,6 @@ static Box* methodGetDoc(Box* b, void*) { ...@@ -1279,9 +1291,6 @@ static Box* methodGetDoc(Box* b, void*) {
} }
void setupCAPI() { void setupCAPI() {
capifunc_cls
= BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedCApiFunction), false, "capifunc");
capifunc_cls->giveAttr("__repr__", capifunc_cls->giveAttr("__repr__",
new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1))); new BoxedFunction(boxRTFunction((void*)BoxedCApiFunction::__repr__, UNKNOWN, 1)));
...@@ -1291,8 +1300,6 @@ void setupCAPI() { ...@@ -1291,8 +1300,6 @@ void setupCAPI() {
capifunc_cls->freeze(); capifunc_cls->freeze();
method_cls
= BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedMethodDescriptor), false, "method");
method_cls->giveAttr("__get__", method_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedMethodDescriptor::__get__, UNKNOWN, 3))); 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,
...@@ -1300,14 +1307,12 @@ void setupCAPI() { ...@@ -1300,14 +1307,12 @@ void setupCAPI() {
method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL)); method_cls->giveAttr("__doc__", new (pyston_getset_cls) BoxedGetsetDescriptor(methodGetDoc, NULL, NULL));
method_cls->freeze(); method_cls->freeze();
wrapperdescr_cls = BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedWrapperDescriptor), false,
"wrapper_descriptor");
wrapperdescr_cls->giveAttr("__get__", wrapperdescr_cls->giveAttr("__get__",
new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__get__, UNKNOWN, 3))); new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__get__, UNKNOWN, 3)));
wrapperdescr_cls->giveAttr("__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperDescriptor::__call__,
UNKNOWN, 2, 0, true, true)));
wrapperdescr_cls->freeze(); wrapperdescr_cls->freeze();
wrapperobject_cls
= BoxedHeapClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedWrapperObject), false, "method-wrapper");
wrapperobject_cls->giveAttr( wrapperobject_cls->giveAttr(
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true))); "__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, 0, true, true)));
wrapperobject_cls->freeze(); wrapperobject_cls->freeze();
......
This diff is collapsed.
...@@ -121,7 +121,7 @@ extern "C" void delattr_internal(Box* obj, const std::string& attr, bool allow_c ...@@ -121,7 +121,7 @@ extern "C" void delattr_internal(Box* obj, const std::string& attr, bool allow_c
struct CompareRewriteArgs; struct CompareRewriteArgs;
Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrite_args); Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrite_args);
Box* getattrInternal(Box* obj, const std::string& attr, GetattrRewriteArgs* rewrite_args); Box* getattrInternal(Box* obj, const std::string& attr, GetattrRewriteArgs* rewrite_args);
Box* getattrInternalGeneral(Box* obj, const std::string& attr, GetattrRewriteArgs* rewrite_args, bool cls_only, Box* getattrInternalGeneric(Box* obj, const std::string& attr, GetattrRewriteArgs* rewrite_args, bool cls_only,
bool for_call, Box** bind_obj_out, RewriterVar** r_bind_obj_out); bool for_call, Box** bind_obj_out, RewriterVar** r_bind_obj_out);
Box* typeLookup(BoxedClass* cls, const std::string& attr, GetattrRewriteArgs* rewrite_args); Box* typeLookup(BoxedClass* cls, const std::string& attr, GetattrRewriteArgs* rewrite_args);
......
...@@ -144,7 +144,11 @@ extern "C" void abort() { ...@@ -144,7 +144,11 @@ extern "C" void abort() {
// that object, _printStackTrace will hang waiting for the first construction // that object, _printStackTrace will hang waiting for the first construction
// to finish.) // to finish.)
alarm(1); alarm(1);
_printStacktrace(); try {
_printStacktrace();
} catch (ExcInfo) {
fprintf(stderr, "error printing stack trace during abort()");
}
// Cancel the alarm. // Cancel the alarm.
// This is helpful for when running in a debugger, since the debugger will catch the // This is helpful for when running in a debugger, since the debugger will catch the
......
This diff is collapsed.
...@@ -204,6 +204,7 @@ protected: ...@@ -204,6 +204,7 @@ protected:
bool is_user_defined); bool is_user_defined);
friend void setupRuntime(); friend void setupRuntime();
friend void setupSysEnd();
}; };
class BoxedHeapClass : public BoxedClass { class BoxedHeapClass : public BoxedClass {
...@@ -232,6 +233,7 @@ private: ...@@ -232,6 +233,7 @@ private:
bool is_user_defined, BoxedString* name); bool is_user_defined, BoxedString* name);
friend void setupRuntime(); friend void setupRuntime();
friend void setupSys();
DEFAULT_CLASS(type_cls); DEFAULT_CLASS(type_cls);
}; };
......
# expected: fail
# - object.__getattribute__ doesn't exist
# attr-getting resolution. # attr-getting resolution.
class M(type): class M(type):
......
...@@ -53,8 +53,6 @@ else: ...@@ -53,8 +53,6 @@ else:
print 'False' print 'False'
# __getattr__ and __setattr__ # __getattr__ and __setattr__
# Looks like __getattr__ and __setattr__ should *not* be looked up with
# the descriptor protocol
class DescriptorGetattr(object): class DescriptorGetattr(object):
def __get__(self, obj, type): def __get__(self, obj, type):
print 'getattr __get__ called' print 'getattr __get__ called'
...@@ -68,8 +66,8 @@ class DescriptorSetattr(object): ...@@ -68,8 +66,8 @@ class DescriptorSetattr(object):
def setattr(attr, val): def setattr(attr, val):
print 'setattr called for attr', attr, val print 'setattr called for attr', attr, val
class D(object): class D(object):
__getattr__ = DescriptorGetattr __getattr__ = DescriptorGetattr()
__setattr__ = DescriptorSetattr __setattr__ = DescriptorSetattr()
d = D() d = D()
try: try:
......
...@@ -6,8 +6,15 @@ class C(object): ...@@ -6,8 +6,15 @@ class C(object):
else: else:
object.__setattr__(self, attr, value) object.__setattr__(self, attr, value)
def __getattribute__(self, attr):
print "getattribute", attr
if attr.startswith("c"):
return "yum"
return object.__getattribute__(self, attr)
c = C() c = C()
c.a = 1 c.a = 1
c.b = 2 c.b = 2
c.c = 3 c.c = 3
print sorted(c.__dict__.items()) print sorted(c.__dict__.items())
print c.a, c.b, c.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