Commit dfeff147 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Templatize getattrInternal

parent eb8e5c4d
...@@ -534,7 +534,7 @@ extern "C" int PyObject_SetAttrString(PyObject* v, const char* name, PyObject* w ...@@ -534,7 +534,7 @@ extern "C" int PyObject_SetAttrString(PyObject* v, const char* name, PyObject* w
extern "C" PyObject* PyObject_GetAttrString(PyObject* o, const char* attr) noexcept { extern "C" PyObject* PyObject_GetAttrString(PyObject* o, const char* attr) noexcept {
try { try {
Box* r = getattrInternal(o, internStringMortal(attr), NULL); Box* r = getattrInternal<ExceptionStyle::CXX>(o, internStringMortal(attr), NULL);
if (!r) if (!r)
PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name, attr); PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name, attr);
return r; return r;
......
...@@ -68,6 +68,13 @@ enum class EffortLevel { ...@@ -68,6 +68,13 @@ enum class EffortLevel {
MAXIMAL = 3, MAXIMAL = 3,
}; };
namespace ExceptionStyle {
enum ExceptionStyle {
CAPI,
CXX,
};
};
class CompilerType; class CompilerType;
template <class V> class ValuedCompilerType; template <class V> class ValuedCompilerType;
typedef ValuedCompilerType<llvm::Value*> ConcreteCompilerType; typedef ValuedCompilerType<llvm::Value*> ConcreteCompilerType;
......
...@@ -452,24 +452,14 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) { ...@@ -452,24 +452,14 @@ Box* getattrFunc(Box* obj, Box* _str, Box* default_value) {
raiseExcHelper(TypeError, "getattr(): attribute name must be string"); raiseExcHelper(TypeError, "getattr(): attribute name must be string");
} }
BoxedString* str = static_cast<BoxedString*>(_str); Box* rtn = PyObject_GetAttr(obj, _str);
internStringMortalInplace(str); if (rtn == NULL && default_value != NULL && PyErr_ExceptionMatches(AttributeError)) {
PyErr_Clear();
Box* rtn = NULL; return default_value;
try {
rtn = getattrInternal(obj, str, NULL);
} catch (ExcInfo e) {
if (!e.matches(AttributeError))
throw e;
}
if (!rtn) {
if (default_value)
return default_value;
else
raiseExcHelper(AttributeError, "'%s' object has no attribute '%s'", getTypeName(obj), str->data());
} }
if (!rtn)
throwCAPIException();
return rtn; return rtn;
} }
...@@ -499,7 +489,7 @@ Box* hasattr(Box* obj, Box* _str) { ...@@ -499,7 +489,7 @@ Box* hasattr(Box* obj, Box* _str) {
Box* attr; Box* attr;
try { try {
attr = getattrInternal(obj, str, NULL); attr = getattrInternal<ExceptionStyle::CXX>(obj, str, NULL);
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (e.matches(Exception)) if (e.matches(Exception))
return False; return False;
......
...@@ -204,13 +204,29 @@ done: ...@@ -204,13 +204,29 @@ done:
} }
extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr_name) noexcept { extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr) noexcept {
try { if (!PyString_Check(attr)) {
return getattrMaybeNonstring(o, attr_name); if (PyUnicode_Check(attr)) {
} catch (ExcInfo e) { attr = _PyUnicode_AsDefaultEncodedString(attr, NULL);
setCAPIException(e); if (attr == NULL)
return NULL; return NULL;
} else {
PyErr_Format(TypeError, "attribute name must be string, not '%.200s'", Py_TYPE(attr)->tp_name);
return NULL;
}
} }
BoxedString* s = static_cast<BoxedString*>(attr);
internStringMortalInplace(s);
Box* r = getattrInternal<ExceptionStyle::CAPI>(o, s, NULL);
if (!r && !PyErr_Occurred()) {
PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name,
PyString_AS_STRING(attr));
}
return r;
} }
extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexcept { extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexcept {
......
...@@ -46,7 +46,7 @@ static void propertyDocCopy(BoxedProperty* prop, Box* fget) { ...@@ -46,7 +46,7 @@ static void propertyDocCopy(BoxedProperty* prop, Box* fget) {
static BoxedString* doc_str = internStringImmortal("__doc__"); static BoxedString* doc_str = internStringImmortal("__doc__");
try { try {
get_doc = getattrInternal(fget, doc_str, NULL); get_doc = getattrInternal<ExceptionStyle::CXX>(fget, doc_str, NULL);
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (!e.matches(Exception)) { if (!e.matches(Exception)) {
throw e; throw e;
......
...@@ -588,7 +588,7 @@ Box* dictUpdate(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) { ...@@ -588,7 +588,7 @@ Box* dictUpdate(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) {
if (args->size()) { if (args->size()) {
Box* arg = args->elts[0]; Box* arg = args->elts[0];
static BoxedString* keys_str = internStringImmortal("keys"); static BoxedString* keys_str = internStringImmortal("keys");
if (getattrInternal(arg, keys_str, NULL)) { if (getattrInternal<ExceptionStyle::CXX>(arg, keys_str, NULL)) {
dictMerge(self, arg); dictMerge(self, arg);
} else { } else {
dictMergeFromSeq2(self, arg); dictMergeFromSeq2(self, arg);
......
...@@ -382,7 +382,7 @@ static Box* importSub(const std::string& name, const std::string& full_name, Box ...@@ -382,7 +382,7 @@ static Box* importSub(const std::string& name, const std::string& full_name, Box
path_list = NULL; path_list = NULL;
} else { } else {
static BoxedString* path_str = internStringImmortal("__path__"); static BoxedString* path_str = internStringImmortal("__path__");
path_list = static_cast<BoxedList*>(getattrInternal(parent_module, path_str, NULL)); path_list = static_cast<BoxedList*>(getattrInternal<ExceptionStyle::CXX>(parent_module, path_str, NULL));
if (path_list == NULL || path_list->cls != list_cls) { if (path_list == NULL || path_list->cls != list_cls) {
return None; return None;
} }
...@@ -562,7 +562,7 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re ...@@ -562,7 +562,7 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re
static BoxedString* path_str = internStringImmortal("__path__"); static BoxedString* path_str = internStringImmortal("__path__");
Box* pathlist = NULL; Box* pathlist = NULL;
try { try {
pathlist = getattrInternal(module, path_str, NULL); pathlist = getattrInternal<ExceptionStyle::CXX>(module, path_str, NULL);
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (!e.matches(AttributeError)) if (!e.matches(AttributeError))
throw e; throw e;
...@@ -584,14 +584,14 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re ...@@ -584,14 +584,14 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re
continue; continue;
static BoxedString* all_str = internStringImmortal("__all__"); static BoxedString* all_str = internStringImmortal("__all__");
Box* all = getattrInternal(module, all_str, NULL); Box* all = getattrInternal<ExceptionStyle::CXX>(module, all_str, NULL);
if (all) { if (all) {
ensureFromlist(module, all, buf, true); ensureFromlist(module, all, buf, true);
} }
continue; continue;
} }
Box* attr = getattrInternal(module, s, NULL); Box* attr = getattrInternal<ExceptionStyle::CXX>(module, s, NULL);
if (attr != NULL) if (attr != NULL)
continue; continue;
......
...@@ -59,6 +59,9 @@ ...@@ -59,6 +59,9 @@
namespace pyston { namespace pyston {
using namespace pyston::ExceptionStyle;
using pyston::ExceptionStyle::ExceptionStyle;
static const std::string delitem_str("__delitem__"); static const std::string delitem_str("__delitem__");
static const std::string getattribute_str("__getattribute__"); static const std::string getattribute_str("__getattribute__");
static const std::string getattr_str("__getattr__"); static const std::string getattr_str("__getattr__");
...@@ -196,7 +199,7 @@ extern "C" bool softspace(Box* b, bool newval) { ...@@ -196,7 +199,7 @@ extern "C" bool softspace(Box* b, bool newval) {
bool r; bool r;
Box* gotten = NULL; Box* gotten = NULL;
try { try {
Box* gotten = getattrInternal(b, softspace_str, NULL); Box* gotten = getattrInternal<CXX>(b, softspace_str, NULL);
if (!gotten) { if (!gotten) {
r = 0; r = 0;
} else { } else {
...@@ -1470,10 +1473,16 @@ Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedS ...@@ -1470,10 +1473,16 @@ Box* dataDescriptorInstanceSpecialCases(GetattrRewriteArgs* rewrite_args, BoxedS
return NULL; return NULL;
} }
template <enum ExceptionStyle S>
Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args, bool cls_only, bool for_call, Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args, bool cls_only, bool for_call,
Box** bind_obj_out, RewriterVar** r_bind_obj_out) { Box** bind_obj_out, RewriterVar** r_bind_obj_out) {
assert(gc::isValidGCObject(attr)); assert(gc::isValidGCObject(attr));
if (S == CAPI) {
assert(!rewrite_args && "implement me");
rewrite_args = NULL;
}
if (!cls_only) { if (!cls_only) {
BoxedClass* cls = obj->cls; BoxedClass* cls = obj->cls;
...@@ -1486,10 +1495,20 @@ Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_ ...@@ -1486,10 +1495,20 @@ Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_
STAT_TIMER(t0, "us_timer_slowpath_tpgetattro", 10); STAT_TIMER(t0, "us_timer_slowpath_tpgetattro", 10);
if (obj->cls->tp_getattro == slot_tp_getattr_hook) { if (obj->cls->tp_getattro == slot_tp_getattr_hook) {
return slotTpGetattrHookInternal(obj, attr, rewrite_args); if (S == CAPI) {
assert(!rewrite_args && "implement me");
return obj->cls->tp_getattro(obj, attr);
} else {
return slotTpGetattrHookInternal(obj, attr, rewrite_args);
}
} }
Box* r = obj->cls->tp_getattro(obj, attr); Box* r = obj->cls->tp_getattro(obj, attr);
if (S == CAPI) {
assert(!rewrite_args && "implement me");
return r;
}
if (!r) if (!r)
throwCAPIException(); throwCAPIException();
...@@ -1517,20 +1536,35 @@ Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_ ...@@ -1517,20 +1536,35 @@ Box* getattrInternalEx(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_
STAT_TIMER(t0, "us_timer_slowpath_tpgetattr", 10); STAT_TIMER(t0, "us_timer_slowpath_tpgetattr", 10);
assert(attr->data()[attr->size()] == '\0'); assert(attr->data()[attr->size()] == '\0');
Box* r = obj->cls->tp_getattr(obj, const_cast<char*>(attr->data())); Box* r = obj->cls->tp_getattr(obj, const_cast<char*>(attr->data()));
if (!r)
throwCAPIException(); if (S == CAPI) {
return r; return r;
} else {
if (!r)
throwCAPIException();
return r;
}
} }
} }
return getattrInternalGeneric(obj, attr, rewrite_args, cls_only, for_call, bind_obj_out, r_bind_obj_out); if (S == CAPI) {
try {
return getattrInternalGeneric(obj, attr, rewrite_args, cls_only, for_call, bind_obj_out, r_bind_obj_out);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} else {
return getattrInternalGeneric(obj, attr, rewrite_args, cls_only, for_call, bind_obj_out, r_bind_obj_out);
}
} }
inline Box* getclsattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) { inline Box* getclsattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) {
return getattrInternalEx(obj, attr, rewrite_args, return getattrInternalEx<CXX>(obj, attr, rewrite_args,
/* cls_only */ true, /* cls_only */ true,
/* for_call */ false, NULL, NULL); /* for_call */ false, NULL, NULL);
} }
extern "C" Box* getclsattr(Box* obj, BoxedString* attr) { extern "C" Box* getclsattr(Box* obj, BoxedString* attr) {
...@@ -1935,8 +1969,8 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -1935,8 +1969,8 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
// TODO this shouldn't go here; it should be in instancemethod_cls->tp_getattr[o] // TODO this shouldn't go here; it should be in instancemethod_cls->tp_getattr[o]
if (obj->cls == instancemethod_cls) { if (obj->cls == instancemethod_cls) {
assert(!rewrite_args || !rewrite_args->out_success); assert(!rewrite_args || !rewrite_args->out_success);
return getattrInternalEx(static_cast<BoxedInstanceMethod*>(obj)->func, attr, NULL, cls_only, for_call, return getattrInternalEx<CXX>(static_cast<BoxedInstanceMethod*>(obj)->func, attr, NULL, cls_only, for_call,
bind_obj_out, NULL); bind_obj_out, NULL);
} }
if (rewrite_args) { if (rewrite_args) {
...@@ -1945,12 +1979,16 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew ...@@ -1945,12 +1979,16 @@ Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rew
return NULL; return NULL;
} }
Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) { template <enum ExceptionStyle S> Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) {
return getattrInternalEx(obj, attr, rewrite_args, return getattrInternalEx<S>(obj, attr, rewrite_args,
/* cls_only */ false, /* cls_only */ false,
/* for_call */ false, NULL, NULL); /* for_call */ false, NULL, NULL);
} }
// Force instantiation of the template
template Box* getattrInternal<CAPI>(Box*, BoxedString*, GetattrRewriteArgs*);
template Box* getattrInternal<CXX>(Box*, BoxedString*, GetattrRewriteArgs*);
Box* getattrMaybeNonstring(Box* obj, Box* attr) { Box* getattrMaybeNonstring(Box* obj, Box* attr) {
if (!PyString_Check(attr)) { if (!PyString_Check(attr)) {
if (PyUnicode_Check(attr)) { if (PyUnicode_Check(attr)) {
...@@ -1964,7 +2002,11 @@ Box* getattrMaybeNonstring(Box* obj, Box* attr) { ...@@ -1964,7 +2002,11 @@ Box* getattrMaybeNonstring(Box* obj, Box* attr) {
BoxedString* s = static_cast<BoxedString*>(attr); BoxedString* s = static_cast<BoxedString*>(attr);
internStringMortalInplace(s); internStringMortalInplace(s);
return getattr(obj, s);
Box* r = getattrInternal<CXX>(obj, s, NULL);
if (!r)
raiseAttributeError(obj, s->s());
return r;
} }
extern "C" Box* getattr(Box* obj, BoxedString* attr) { extern "C" Box* getattr(Box* obj, BoxedString* attr) {
...@@ -2018,7 +2060,7 @@ extern "C" Box* getattr(Box* obj, BoxedString* attr) { ...@@ -2018,7 +2060,7 @@ extern "C" Box* getattr(Box* obj, BoxedString* attr) {
else else
dest = rewriter->getReturnDestination(); dest = rewriter->getReturnDestination();
GetattrRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), dest); GetattrRewriteArgs rewrite_args(rewriter.get(), rewriter->getArg(0), dest);
val = getattrInternal(obj, attr, &rewrite_args); val = getattrInternal<CXX>(obj, attr, &rewrite_args);
if (rewrite_args.out_success) { if (rewrite_args.out_success) {
if (!val) { if (!val) {
...@@ -2040,7 +2082,7 @@ extern "C" Box* getattr(Box* obj, BoxedString* attr) { ...@@ -2040,7 +2082,7 @@ extern "C" Box* getattr(Box* obj, BoxedString* attr) {
} }
} }
} else { } else {
val = getattrInternal(obj, attr, NULL); val = getattrInternal<CXX>(obj, attr, NULL);
} }
if (val) { if (val) {
...@@ -2885,14 +2927,14 @@ extern "C" Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope, ...@@ -2885,14 +2927,14 @@ extern "C" Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope scope,
RewriterVar* r_val = NULL; RewriterVar* r_val = NULL;
if (rewrite_args) { if (rewrite_args) {
GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, rewrite_args->obj, Location::any()); GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, rewrite_args->obj, Location::any());
val = getattrInternalEx(obj, attr, &grewrite_args, scope == CLASS_ONLY, true, &bind_obj, &r_bind_obj); val = getattrInternalEx<CXX>(obj, attr, &grewrite_args, scope == CLASS_ONLY, true, &bind_obj, &r_bind_obj);
if (!grewrite_args.out_success) { if (!grewrite_args.out_success) {
rewrite_args = NULL; rewrite_args = NULL;
} else if (val) { } else if (val) {
r_val = grewrite_args.out_rtn; r_val = grewrite_args.out_rtn;
} }
} else { } else {
val = getattrInternalEx(obj, attr, NULL, scope == CLASS_ONLY, true, &bind_obj, &r_bind_obj); val = getattrInternalEx<CXX>(obj, attr, NULL, scope == CLASS_ONLY, true, &bind_obj, &r_bind_obj);
} }
if (val == NULL) { if (val == NULL) {
...@@ -5370,7 +5412,7 @@ void setGlobal(Box* globals, BoxedString* name, Box* value) { ...@@ -5370,7 +5412,7 @@ void setGlobal(Box* globals, BoxedString* name, Box* value) {
extern "C" Box* importFrom(Box* _m, BoxedString* name) { extern "C" Box* importFrom(Box* _m, BoxedString* name) {
STAT_TIMER(t0, "us_timer_importFrom", 10); STAT_TIMER(t0, "us_timer_importFrom", 10);
Box* r = getattrInternal(_m, name, NULL); Box* r = getattrInternal<CXX>(_m, name, NULL);
if (r) if (r)
return r; return r;
......
...@@ -134,6 +134,7 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit ...@@ -134,6 +134,7 @@ Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrit
// This is the equivalent of PyObject_GetAttr. Unlike getattrInternalGeneric, it checks for custom __getattr__ or // This is the equivalent of PyObject_GetAttr. Unlike getattrInternalGeneric, it checks for custom __getattr__ or
// __getattribute__ methods. // __getattribute__ methods.
template <ExceptionStyle::ExceptionStyle S>
Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args); Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args);
// This is the equivalent of PyObject_GenericGetAttr, which performs the default lookup rules for getattr() (check for // This is the equivalent of PyObject_GenericGetAttr, which performs the default lookup rules for getattr() (check for
......
...@@ -1654,7 +1654,7 @@ static Box* instancemethodRepr(Box* b) { ...@@ -1654,7 +1654,7 @@ static Box* instancemethodRepr(Box* b) {
const char* sfuncname = "?", * sklassname = "?"; const char* sfuncname = "?", * sklassname = "?";
static BoxedString* name_str = internStringImmortal("__name__"); static BoxedString* name_str = internStringImmortal("__name__");
funcname = getattrInternal(func, name_str, NULL); funcname = getattrInternal<ExceptionStyle::CXX>(func, name_str, NULL);
if (funcname != NULL) { if (funcname != NULL) {
if (!PyString_Check(funcname)) { if (!PyString_Check(funcname)) {
...@@ -1666,7 +1666,7 @@ static Box* instancemethodRepr(Box* b) { ...@@ -1666,7 +1666,7 @@ static Box* instancemethodRepr(Box* b) {
if (klass == NULL) { if (klass == NULL) {
klassname = NULL; klassname = NULL;
} else { } else {
klassname = getattrInternal(klass, name_str, NULL); klassname = getattrInternal<ExceptionStyle::CXX>(klass, name_str, NULL);
if (klassname != NULL) { if (klassname != NULL) {
if (!PyString_Check(klassname)) { if (!PyString_Check(klassname)) {
klassname = NULL; klassname = NULL;
......
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