Commit 711a3224 authored by Marius Wachtler's avatar Marius Wachtler

Merge pull request #950 from undingen/rewritable

use a template to remove rewriter checks inside our most important runtime funcs
parents 2a0955bb 83f68abd
...@@ -758,7 +758,7 @@ exit: ...@@ -758,7 +758,7 @@ exit:
} }
extern "C" Py_ssize_t PyObject_Size(PyObject* o) noexcept { extern "C" Py_ssize_t PyObject_Size(PyObject* o) noexcept {
BoxedInt* r = lenInternal<ExceptionStyle::CAPI>(o, NULL); BoxedInt* r = lenInternal<ExceptionStyle::CAPI, NOT_REWRITABLE>(o, NULL);
if (!r) if (!r)
return -1; return -1;
return r->n; return r->n;
...@@ -2252,7 +2252,7 @@ extern "C" PyObject* PyNumber_Int(PyObject* o) noexcept { ...@@ -2252,7 +2252,7 @@ extern "C" PyObject* PyNumber_Int(PyObject* o) noexcept {
// Pyston change: this should be an optimization // Pyston change: this should be an optimization
// PyObject* trunc_func = PyObject_GetAttrString(o, "__trunc__"); // PyObject* trunc_func = PyObject_GetAttrString(o, "__trunc__");
static BoxedString* trunc_str = internStringImmortal("__trunc__"); static BoxedString* trunc_str = internStringImmortal("__trunc__");
PyObject* trunc_func = getattrInternal<ExceptionStyle::CAPI>(o, trunc_str, NULL); PyObject* trunc_func = getattrInternal<ExceptionStyle::CAPI>(o, trunc_str);
if (trunc_func) { if (trunc_func) {
PyObject* truncated = PyEval_CallObject(trunc_func, NULL); PyObject* truncated = PyEval_CallObject(trunc_func, NULL);
......
...@@ -486,7 +486,7 @@ extern "C" int PyObject_GenericSetAttr(PyObject* obj, PyObject* name, PyObject* ...@@ -486,7 +486,7 @@ extern "C" int PyObject_GenericSetAttr(PyObject* obj, PyObject* name, PyObject*
if (value == NULL) if (value == NULL)
delattrGeneric(obj, str, NULL); delattrGeneric(obj, str, NULL);
else else
setattrGeneric(obj, str, value, NULL); setattrGeneric<NOT_REWRITABLE>(obj, str, value, NULL);
} catch (ExcInfo e) { } catch (ExcInfo e) {
setCAPIException(e); setCAPIException(e);
return -1; return -1;
...@@ -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<ExceptionStyle::CXX>(o, internStringMortal(attr), NULL); Box* r = getattrInternal<ExceptionStyle::CXX>(o, internStringMortal(attr));
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;
......
...@@ -484,7 +484,7 @@ static PyObject* lookup_maybe(PyObject* self, const char* attrstr, PyObject** at ...@@ -484,7 +484,7 @@ static PyObject* lookup_maybe(PyObject* self, const char* attrstr, PyObject** at
return NULL; return NULL;
} }
Box* obj = typeLookup(self->cls, (BoxedString*)*attrobj, NULL); Box* obj = typeLookup(self->cls, (BoxedString*)*attrobj);
if (obj) { if (obj) {
try { try {
return processDescriptor(obj, self, self->cls); return processDescriptor(obj, self, self->cls);
...@@ -809,7 +809,7 @@ static PyObject* slot_tp_descr_get(PyObject* self, PyObject* obj, PyObject* type ...@@ -809,7 +809,7 @@ static PyObject* slot_tp_descr_get(PyObject* self, PyObject* obj, PyObject* type
PyObject* get; PyObject* get;
static BoxedString* get_str = internStringImmortal("__get__"); static BoxedString* get_str = internStringImmortal("__get__");
get = typeLookup(tp, get_str, NULL); get = typeLookup(tp, get_str);
if (get == NULL) { if (get == NULL) {
/* Avoid further slowdowns */ /* Avoid further slowdowns */
if (tp->tp_descr_get == slot_tp_descr_get) if (tp->tp_descr_get == slot_tp_descr_get)
...@@ -883,11 +883,16 @@ static PyObject* call_attribute(PyObject* self, PyObject* attr, PyObject* name) ...@@ -883,11 +883,16 @@ static PyObject* call_attribute(PyObject* self, PyObject* attr, PyObject* name)
/* Pyston change: static */ PyObject* slot_tp_getattr_hook(PyObject* self, PyObject* name) noexcept { /* Pyston change: static */ PyObject* slot_tp_getattr_hook(PyObject* self, PyObject* name) noexcept {
assert(name->cls == str_cls); assert(name->cls == str_cls);
return slotTpGetattrHookInternal<CAPI>(self, (BoxedString*)name, NULL); return slotTpGetattrHookInternal<CAPI, NOT_REWRITABLE>(self, (BoxedString*)name, NULL);
} }
template <ExceptionStyle S> template <ExceptionStyle S, Rewritable rewritable>
Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* rewrite_args) noexcept(S == CAPI) { Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* rewrite_args) noexcept(S == CAPI) {
if (rewritable == NOT_REWRITABLE) {
assert(!rewrite_args);
rewrite_args = NULL;
}
STAT_TIMER(t0, "us_timer_slot_tpgetattrhook", SLOT_AVOIDABILITY(self)); STAT_TIMER(t0, "us_timer_slot_tpgetattrhook", SLOT_AVOIDABILITY(self));
PyObject* getattr, *getattribute, * res = NULL; PyObject* getattr, *getattribute, * res = NULL;
...@@ -905,7 +910,7 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* ...@@ -905,7 +910,7 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
// - if we never get to the "call __getattr__" portion and the "calling __getattribute__" // - if we never get to the "call __getattr__" portion and the "calling __getattribute__"
// portion still has its guards pass, then that section is still behaviorally correct, and // portion still has its guards pass, then that section is still behaviorally correct, and
// I think should be close to as fast as the normal rewritten version we would generate. // I think should be close to as fast as the normal rewritten version we would generate.
getattr = typeLookup(self->cls, _getattr_str, NULL); getattr = typeLookup(self->cls, _getattr_str);
if (getattr == NULL) { if (getattr == NULL) {
if (rewrite_args) { if (rewrite_args) {
...@@ -943,7 +948,7 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* ...@@ -943,7 +948,7 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
grewrite_args.assertReturnConvention(ReturnConvention::NO_RETURN); grewrite_args.assertReturnConvention(ReturnConvention::NO_RETURN);
} }
} else { } else {
getattribute = typeLookup(self->cls, _getattribute_str, NULL); getattribute = typeLookup(self->cls, _getattribute_str);
} }
// Not sure why CPython checks if getattribute is NULL since I don't think that should happen. // Not sure why CPython checks if getattribute is NULL since I don't think that should happen.
...@@ -966,7 +971,7 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* ...@@ -966,7 +971,7 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, rewrite_args->obj, rewrite_args->destination); GetattrRewriteArgs grewrite_args(rewrite_args->rewriter, rewrite_args->obj, rewrite_args->destination);
try { try {
assert(!PyType_Check(self)); // There would be a getattribute assert(!PyType_Check(self)); // There would be a getattribute
res = getattrInternalGeneric<false>(self, name, &grewrite_args, false, false, NULL, NULL); res = getattrInternalGeneric<false, rewritable>(self, name, &grewrite_args, false, false, NULL, NULL);
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (!e.matches(AttributeError)) { if (!e.matches(AttributeError)) {
if (S == CAPI) { if (S == CAPI) {
...@@ -1013,7 +1018,7 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* ...@@ -1013,7 +1018,7 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
} else { } else {
try { try {
assert(!PyType_Check(self)); // There would be a getattribute assert(!PyType_Check(self)); // There would be a getattribute
res = getattrInternalGeneric<false>(self, name, NULL, false, false, NULL, NULL); res = getattrInternalGeneric<false, rewritable>(self, name, NULL, false, false, NULL, NULL);
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (!e.matches(AttributeError)) { if (!e.matches(AttributeError)) {
if (S == CAPI) { if (S == CAPI) {
...@@ -1068,8 +1073,8 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* ...@@ -1068,8 +1073,8 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
assert(PyString_CHECK_INTERNED(name) == SSTATE_INTERNED_IMMORTAL); assert(PyString_CHECK_INTERNED(name) == SSTATE_INTERNED_IMMORTAL);
crewrite_args.arg1 = rewrite_args->rewriter->loadConst((intptr_t)name, Location::forArg(1)); crewrite_args.arg1 = rewrite_args->rewriter->loadConst((intptr_t)name, Location::forArg(1));
res = callattrInternal<S>(self, _getattr_str, LookupScope::CLASS_ONLY, &crewrite_args, ArgPassSpec(1), name, res = callattrInternal<S, REWRITABLE>(self, _getattr_str, LookupScope::CLASS_ONLY, &crewrite_args,
NULL, NULL, NULL, NULL); ArgPassSpec(1), name, NULL, NULL, NULL, NULL);
assert(res || S == CAPI); assert(res || S == CAPI);
if (!crewrite_args.isSuccessful()) if (!crewrite_args.isSuccessful())
...@@ -1083,16 +1088,22 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs* ...@@ -1083,16 +1088,22 @@ Box* slotTpGetattrHookInternal(Box* self, BoxedString* name, GetattrRewriteArgs*
// the rewrite_args and non-rewrite_args case the same. // the rewrite_args and non-rewrite_args case the same.
// Actually, we might have gotten to the point that doing a runtimeCall on an instancemethod is as // Actually, we might have gotten to the point that doing a runtimeCall on an instancemethod is as
// fast as a callattr, but that hasn't typically been the case. // fast as a callattr, but that hasn't typically been the case.
res = callattrInternal<S>(self, _getattr_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(1), name, NULL, NULL, res = callattrInternal<S, NOT_REWRITABLE>(self, _getattr_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(1),
NULL, NULL); name, NULL, NULL, NULL, NULL);
assert(res || S == CAPI); assert(res || S == CAPI);
} }
return res; return res;
} }
// Force instantiation of the template // Force instantiation of the template
template Box* slotTpGetattrHookInternal<CAPI>(Box* self, BoxedString* name, GetattrRewriteArgs* rewrite_args); template Box* slotTpGetattrHookInternal<CAPI, REWRITABLE>(Box* self, BoxedString* name,
template Box* slotTpGetattrHookInternal<CXX>(Box* self, BoxedString* name, GetattrRewriteArgs* rewrite_args); GetattrRewriteArgs* rewrite_args);
template Box* slotTpGetattrHookInternal<CXX, REWRITABLE>(Box* self, BoxedString* name,
GetattrRewriteArgs* rewrite_args);
template Box* slotTpGetattrHookInternal<CAPI, NOT_REWRITABLE>(Box* self, BoxedString* name,
GetattrRewriteArgs* rewrite_args);
template Box* slotTpGetattrHookInternal<CXX, NOT_REWRITABLE>(Box* self, BoxedString* name,
GetattrRewriteArgs* rewrite_args);
/* Pyston change: static */ PyObject* slot_tp_new(PyTypeObject* self, PyObject* args, PyObject* kwds) noexcept { /* Pyston change: static */ PyObject* slot_tp_new(PyTypeObject* self, PyObject* args, PyObject* kwds) noexcept {
STAT_TIMER(t0, "us_timer_slot_tpnew", SLOT_AVOIDABILITY(self)); STAT_TIMER(t0, "us_timer_slot_tpnew", SLOT_AVOIDABILITY(self));
...@@ -1100,7 +1111,7 @@ template Box* slotTpGetattrHookInternal<CXX>(Box* self, BoxedString* name, Getat ...@@ -1100,7 +1111,7 @@ template Box* slotTpGetattrHookInternal<CXX>(Box* self, BoxedString* name, Getat
try { try {
// TODO: runtime ICs? // TODO: runtime ICs?
static BoxedString* _new_str = internStringImmortal("__new__"); static BoxedString* _new_str = internStringImmortal("__new__");
Box* new_attr = typeLookup(self, _new_str, NULL); Box* new_attr = typeLookup(self, _new_str);
assert(new_attr); assert(new_attr);
new_attr = processDescriptor(new_attr, None, self); new_attr = processDescriptor(new_attr, None, self);
...@@ -1115,7 +1126,7 @@ static PyObject* slot_tp_del(PyObject* self) noexcept { ...@@ -1115,7 +1126,7 @@ static PyObject* slot_tp_del(PyObject* self) noexcept {
static BoxedString* del_str = internStringImmortal("__del__"); static BoxedString* del_str = internStringImmortal("__del__");
try { try {
// TODO: runtime ICs? // TODO: runtime ICs?
Box* del_attr = typeLookup(self->cls, del_str, NULL); Box* del_attr = typeLookup(self->cls, del_str);
assert(del_attr); assert(del_attr);
CallattrFlags flags{.cls_only = false, CallattrFlags flags{.cls_only = false,
...@@ -1155,7 +1166,7 @@ static PyObject* slot_tp_del(PyObject* self) noexcept { ...@@ -1155,7 +1166,7 @@ static PyObject* slot_tp_del(PyObject* self) noexcept {
PyObject* slot_sq_item(PyObject* self, Py_ssize_t i) noexcept { PyObject* slot_sq_item(PyObject* self, Py_ssize_t i) noexcept {
STAT_TIMER(t0, "us_timer_slot_sqitem", SLOT_AVOIDABILITY(self)); STAT_TIMER(t0, "us_timer_slot_sqitem", SLOT_AVOIDABILITY(self));
return getitemInternal<CAPI>(self, boxInt(i), NULL); return getitemInternal<CAPI>(self, boxInt(i));
} }
/* Pyston change: static */ Py_ssize_t slot_sq_length(PyObject* self) noexcept { /* Pyston change: static */ Py_ssize_t slot_sq_length(PyObject* self) noexcept {
...@@ -1823,7 +1834,7 @@ static const slotdef* update_one_slot(BoxedClass* type, const slotdef* p) noexce ...@@ -1823,7 +1834,7 @@ static const slotdef* update_one_slot(BoxedClass* type, const slotdef* p) noexce
} }
do { do {
descr = typeLookup(type, p->name_strobj, NULL); descr = typeLookup(type, p->name_strobj);
if (p->flags & PyWrapperFlag_BOOL) { if (p->flags & PyWrapperFlag_BOOL) {
// We are supposed to iterate over each slotdef; for now just assert that // We are supposed to iterate over each slotdef; for now just assert that
......
...@@ -55,7 +55,7 @@ PyObject* tp_new_wrapper(PyTypeObject* self, BoxedTuple* args, Box* kwds) noexce ...@@ -55,7 +55,7 @@ PyObject* tp_new_wrapper(PyTypeObject* self, BoxedTuple* args, Box* kwds) noexce
int slot_tp_init(PyObject* self, PyObject* args, PyObject* kwds) noexcept; int slot_tp_init(PyObject* self, PyObject* args, PyObject* kwds) noexcept;
class GetattrRewriteArgs; class GetattrRewriteArgs;
template <ExceptionStyle S> template <ExceptionStyle S, Rewritable rewritable>
Box* slotTpGetattrHookInternal(Box* self, BoxedString* attr, GetattrRewriteArgs* rewrite_args) noexcept(S == CAPI); Box* slotTpGetattrHookInternal(Box* self, BoxedString* attr, GetattrRewriteArgs* rewrite_args) noexcept(S == CAPI);
} }
......
...@@ -1563,7 +1563,7 @@ public: ...@@ -1563,7 +1563,7 @@ public:
CompilerType* getattrType(BoxedString* attr, bool cls_only) override { CompilerType* getattrType(BoxedString* attr, bool cls_only) override {
// Any changes here need to be mirrored in getattr() // Any changes here need to be mirrored in getattr()
if (canStaticallyResolveGetattrs()) { if (canStaticallyResolveGetattrs()) {
Box* rtattr = typeLookup(cls, attr, nullptr); Box* rtattr = typeLookup(cls, attr);
if (rtattr == NULL) if (rtattr == NULL)
return UNDEF; return UNDEF;
...@@ -1588,7 +1588,7 @@ public: ...@@ -1588,7 +1588,7 @@ public:
bool cls_only) override { bool cls_only) override {
// Any changes here need to be mirrored in getattrType() // Any changes here need to be mirrored in getattrType()
if (canStaticallyResolveGetattrs()) { if (canStaticallyResolveGetattrs()) {
Box* rtattr = typeLookup(cls, attr, nullptr); Box* rtattr = typeLookup(cls, attr);
if (rtattr == NULL) { if (rtattr == NULL) {
ExceptionStyle exception_style = info.preferredExceptionStyle(); ExceptionStyle exception_style = info.preferredExceptionStyle();
llvm::Value* raise_func = exception_style == CXX ? g.funcs.raiseAttributeErrorStr llvm::Value* raise_func = exception_style == CXX ? g.funcs.raiseAttributeErrorStr
......
...@@ -2625,7 +2625,7 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) { ...@@ -2625,7 +2625,7 @@ CFG* computeCFG(SourceInfo* source, std::vector<AST_stmt*> body) {
if (source->scoping->areGlobalsFromModule()) { if (source->scoping->areGlobalsFromModule()) {
static BoxedString* name_str = internStringImmortal("__name__"); static BoxedString* name_str = internStringImmortal("__name__");
Box* module_name = source->parent_module->getattr(name_str, NULL); Box* module_name = source->parent_module->getattr(name_str);
assert(module_name->cls == str_cls); assert(module_name->cls == str_cls);
module_assign->value = new AST_Str(static_cast<BoxedString*>(module_name)->s()); module_assign->value = new AST_Str(static_cast<BoxedString*>(module_name)->s());
} else { } else {
......
...@@ -51,6 +51,11 @@ enum ExceptionStyle { ...@@ -51,6 +51,11 @@ enum ExceptionStyle {
CXX, CXX,
}; };
enum Rewritable {
REWRITABLE,
NOT_REWRITABLE,
};
template <typename T> struct ExceptionSwitchable { template <typename T> struct ExceptionSwitchable {
public: public:
T capi_val; T capi_val;
...@@ -545,8 +550,9 @@ public: ...@@ -545,8 +550,9 @@ public:
// getattr() does the equivalent of PyDict_GetItem(obj->dict, attr): it looks up the attribute's value on the // getattr() does the equivalent of PyDict_GetItem(obj->dict, attr): it looks up the attribute's value on the
// object's attribute storage. it doesn't look at other objects or do any descriptor logic. // object's attribute storage. it doesn't look at other objects or do any descriptor logic.
template <Rewritable rewritable = REWRITABLE>
Box* getattr(BoxedString* attr, GetattrRewriteArgs* rewrite_args); Box* getattr(BoxedString* attr, GetattrRewriteArgs* rewrite_args);
Box* getattr(BoxedString* attr) { return getattr(attr, NULL); } Box* getattr(BoxedString* attr) { return getattr<NOT_REWRITABLE>(attr, NULL); }
bool hasattr(BoxedString* attr) { return getattr(attr) != NULL; } bool hasattr(BoxedString* attr) { return getattr(attr) != NULL; }
void delattr(BoxedString* attr, DelattrRewriteArgs* rewrite_args); void delattr(BoxedString* attr, DelattrRewriteArgs* rewrite_args);
......
...@@ -83,7 +83,7 @@ extern "C" Box* vars(Box* obj) { ...@@ -83,7 +83,7 @@ extern "C" Box* vars(Box* obj) {
return fastLocalsToBoxedLocals(); return fastLocalsToBoxedLocals();
static BoxedString* dict_str = internStringImmortal("__dict__"); static BoxedString* dict_str = internStringImmortal("__dict__");
Box* rtn = getattrInternal<ExceptionStyle::CAPI>(obj, dict_str, NULL); Box* rtn = getattrInternal<ExceptionStyle::CAPI>(obj, dict_str);
if (!rtn) if (!rtn)
raiseExcHelper(TypeError, "vars() argument must have __dict__ attribute"); raiseExcHelper(TypeError, "vars() argument must have __dict__ attribute");
return rtn; return rtn;
...@@ -580,7 +580,7 @@ Box* getattrFuncInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ...@@ -580,7 +580,7 @@ Box* getattrFuncInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args,
r_rtn = rewrite_args->rewriter->loadConst(0); r_rtn = rewrite_args->rewriter->loadConst(0);
} }
} else { } else {
rtn = getattrInternal<CAPI>(obj, str, NULL); rtn = getattrInternal<CAPI>(obj, str);
} }
if (rewrite_args) { if (rewrite_args) {
...@@ -691,7 +691,7 @@ Box* hasattrFuncInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ...@@ -691,7 +691,7 @@ Box* hasattrFuncInternal(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args,
r_rtn = rewrite_args->rewriter->loadConst(0); r_rtn = rewrite_args->rewriter->loadConst(0);
} }
} else { } else {
rtn = getattrInternal<CAPI>(obj, str, NULL); rtn = getattrInternal<CAPI>(obj, str);
} }
if (rewrite_args) { if (rewrite_args) {
...@@ -1252,7 +1252,7 @@ Box* ellipsisRepr(Box* self) { ...@@ -1252,7 +1252,7 @@ Box* ellipsisRepr(Box* self) {
return boxString("Ellipsis"); return boxString("Ellipsis");
} }
Box* divmod(Box* lhs, Box* rhs) { Box* divmod(Box* lhs, Box* rhs) {
return binopInternal(lhs, rhs, AST_TYPE::DivMod, false, NULL); return binopInternal<NOT_REWRITABLE>(lhs, rhs, AST_TYPE::DivMod, false, NULL);
} }
Box* powFunc(Box* x, Box* y, Box* z) { Box* powFunc(Box* x, Box* y, Box* z) {
...@@ -1326,7 +1326,7 @@ Box* getreversed(Box* o) { ...@@ -1326,7 +1326,7 @@ Box* getreversed(Box* o) {
return r; return r;
static BoxedString* getitem_str = internStringImmortal("__getitem__"); static BoxedString* getitem_str = internStringImmortal("__getitem__");
if (!typeLookup(o->cls, getitem_str, NULL)) { if (!typeLookup(o->cls, getitem_str)) {
raiseExcHelper(TypeError, "'%s' object is not iterable", getTypeName(o)); raiseExcHelper(TypeError, "'%s' object is not iterable", getTypeName(o));
} }
int64_t len = unboxedLen(o); // this will throw an exception if __len__ isn't there int64_t len = unboxedLen(o); // this will throw an exception if __len__ isn't there
......
...@@ -220,7 +220,7 @@ extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr) noexcept { ...@@ -220,7 +220,7 @@ extern "C" PyObject* PyObject_GetAttr(PyObject* o, PyObject* attr) noexcept {
BoxedString* s = static_cast<BoxedString*>(attr); BoxedString* s = static_cast<BoxedString*>(attr);
internStringMortalInplace(s); internStringMortalInplace(s);
Box* r = getattrInternal<ExceptionStyle::CAPI>(o, s, NULL); Box* r = getattrInternal<ExceptionStyle::CAPI>(o, s);
if (!r && !PyErr_Occurred()) { if (!r && !PyErr_Occurred()) {
PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name, PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name,
...@@ -234,7 +234,7 @@ extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexce ...@@ -234,7 +234,7 @@ extern "C" PyObject* PyObject_GenericGetAttr(PyObject* o, PyObject* name) noexce
try { try {
BoxedString* s = static_cast<BoxedString*>(name); BoxedString* s = static_cast<BoxedString*>(name);
internStringMortalInplace(s); internStringMortalInplace(s);
Box* r = getattrInternalGeneric<false>(o, s, NULL, false, false, NULL, NULL); Box* r = getattrInternalGeneric<false, NOT_REWRITABLE>(o, s, NULL, false, false, NULL, NULL);
if (!r) if (!r)
PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name, PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name,
PyString_AS_STRING(name)); PyString_AS_STRING(name));
...@@ -458,7 +458,7 @@ done: ...@@ -458,7 +458,7 @@ done:
extern "C" PyObject* PyObject_GetItem(PyObject* o, PyObject* key) noexcept { extern "C" PyObject* PyObject_GetItem(PyObject* o, PyObject* key) noexcept {
return getitemInternal<ExceptionStyle::CAPI>(o, key, NULL); return getitemInternal<ExceptionStyle::CAPI>(o, key);
} }
extern "C" int PyObject_SetItem(PyObject* o, PyObject* key, PyObject* v) noexcept { extern "C" int PyObject_SetItem(PyObject* o, PyObject* key, PyObject* v) noexcept {
...@@ -580,11 +580,11 @@ extern "C" int PyObject_Not(PyObject* o) noexcept { ...@@ -580,11 +580,11 @@ extern "C" int PyObject_Not(PyObject* o) noexcept {
extern "C" PyObject* PyObject_Call(PyObject* callable_object, PyObject* args, PyObject* kw) noexcept { extern "C" PyObject* PyObject_Call(PyObject* callable_object, PyObject* args, PyObject* kw) noexcept {
if (kw) if (kw)
return runtimeCallInternal<ExceptionStyle::CAPI>(callable_object, NULL, ArgPassSpec(0, 0, true, true), args, kw, return runtimeCallInternal<ExceptionStyle::CAPI, NOT_REWRITABLE>(
NULL, NULL, NULL); callable_object, NULL, ArgPassSpec(0, 0, true, true), args, kw, NULL, NULL, NULL);
else else
return runtimeCallInternal<ExceptionStyle::CAPI>(callable_object, NULL, ArgPassSpec(0, 0, true, false), args, return runtimeCallInternal<ExceptionStyle::CAPI, NOT_REWRITABLE>(
NULL, NULL, NULL, NULL); callable_object, NULL, ArgPassSpec(0, 0, true, false), args, NULL, NULL, NULL, NULL);
} }
extern "C" int PyObject_GetBuffer(PyObject* obj, Py_buffer* view, int flags) noexcept { extern "C" int PyObject_GetBuffer(PyObject* obj, Py_buffer* view, int flags) noexcept {
......
...@@ -29,12 +29,17 @@ extern "C" { ...@@ -29,12 +29,17 @@ extern "C" {
BoxedClass* classobj_cls, *instance_cls; BoxedClass* classobj_cls, *instance_cls;
} }
template <Rewritable rewritable>
static Box* classLookup(BoxedClassobj* cls, BoxedString* attr, GetattrRewriteArgs* rewrite_args) {
if (rewritable == NOT_REWRITABLE) {
assert(!rewrite_args);
rewrite_args = NULL;
}
static Box* classLookup(BoxedClassobj* cls, BoxedString* attr, GetattrRewriteArgs* rewrite_args = NULL) {
if (rewrite_args) if (rewrite_args)
assert(!rewrite_args->isSuccessful()); assert(!rewrite_args->isSuccessful());
Box* r = cls->getattr(attr, rewrite_args); Box* r = cls->getattr<rewritable>(attr, rewrite_args);
if (r) { if (r) {
if (rewrite_args) if (rewrite_args)
rewrite_args->assertReturnConvention(ReturnConvention::HAS_RETURN); rewrite_args->assertReturnConvention(ReturnConvention::HAS_RETURN);
...@@ -51,7 +56,7 @@ static Box* classLookup(BoxedClassobj* cls, BoxedString* attr, GetattrRewriteArg ...@@ -51,7 +56,7 @@ static Box* classLookup(BoxedClassobj* cls, BoxedString* attr, GetattrRewriteArg
for (auto b : *cls->bases) { for (auto b : *cls->bases) {
RELEASE_ASSERT(b->cls == classobj_cls, ""); RELEASE_ASSERT(b->cls == classobj_cls, "");
Box* r = classLookup(static_cast<BoxedClassobj*>(b), attr, rewrite_args); Box* r = classLookup<NOT_REWRITABLE>(static_cast<BoxedClassobj*>(b), attr, rewrite_args);
if (r) if (r)
return r; return r;
} }
...@@ -59,6 +64,10 @@ static Box* classLookup(BoxedClassobj* cls, BoxedString* attr, GetattrRewriteArg ...@@ -59,6 +64,10 @@ static Box* classLookup(BoxedClassobj* cls, BoxedString* attr, GetattrRewriteArg
return NULL; return NULL;
} }
static Box* classLookup(BoxedClassobj* cls, BoxedString* attr) {
return classLookup<NOT_REWRITABLE>(cls, attr, NULL);
}
extern "C" PyObject* _PyInstance_Lookup(PyObject* pinst, PyObject* pname) noexcept { extern "C" PyObject* _PyInstance_Lookup(PyObject* pinst, PyObject* pname) noexcept {
RELEASE_ASSERT(PyInstance_Check(pinst), ""); RELEASE_ASSERT(PyInstance_Check(pinst), "");
BoxedInstance* inst = (BoxedInstance*)pinst; BoxedInstance* inst = (BoxedInstance*)pinst;
...@@ -68,7 +77,7 @@ extern "C" PyObject* _PyInstance_Lookup(PyObject* pinst, PyObject* pname) noexce ...@@ -68,7 +77,7 @@ extern "C" PyObject* _PyInstance_Lookup(PyObject* pinst, PyObject* pname) noexce
try { try {
internStringMortalInplace(name); internStringMortalInplace(name);
Box* v = inst->getattr(name, NULL); Box* v = inst->getattr(name);
if (v == NULL) if (v == NULL)
v = classLookup(inst->inst_cls, name); v = classLookup(inst->inst_cls, name);
return v; return v;
...@@ -326,9 +335,15 @@ Box* classobjRepr(Box* _obj) { ...@@ -326,9 +335,15 @@ Box* classobjRepr(Box* _obj) {
} }
// Analogous to CPython's instance_getattr2 // Analogous to CPython's instance_getattr2
template <Rewritable rewritable>
static Box* instanceGetattributeSimple(BoxedInstance* inst, BoxedString* attr_str, static Box* instanceGetattributeSimple(BoxedInstance* inst, BoxedString* attr_str,
GetattrRewriteArgs* rewrite_args = NULL) { GetattrRewriteArgs* rewrite_args = NULL) {
Box* r = inst->getattr(attr_str, rewrite_args); if (rewritable == NOT_REWRITABLE) {
assert(!rewrite_args);
rewrite_args = NULL;
}
Box* r = inst->getattr<rewritable>(attr_str, rewrite_args);
if (r) { if (r) {
if (rewrite_args) if (rewrite_args)
rewrite_args->assertReturnConvention(ReturnConvention::HAS_RETURN); rewrite_args->assertReturnConvention(ReturnConvention::HAS_RETURN);
...@@ -350,7 +365,7 @@ static Box* instanceGetattributeSimple(BoxedInstance* inst, BoxedString* attr_st ...@@ -350,7 +365,7 @@ static Box* instanceGetattributeSimple(BoxedInstance* inst, BoxedString* attr_st
} }
GetattrRewriteArgs grewriter_inst_args(rewrite_args ? rewrite_args->rewriter : NULL, r_inst_cls, GetattrRewriteArgs grewriter_inst_args(rewrite_args ? rewrite_args->rewriter : NULL, r_inst_cls,
rewrite_args ? rewrite_args->rewriter->getReturnDestination() : Location()); rewrite_args ? rewrite_args->rewriter->getReturnDestination() : Location());
r = classLookup(inst->inst_cls, attr_str, rewrite_args ? &grewriter_inst_args : NULL); r = classLookup<rewritable>(inst->inst_cls, attr_str, rewrite_args ? &grewriter_inst_args : NULL);
if (!grewriter_inst_args.isSuccessful()) if (!grewriter_inst_args.isSuccessful())
rewrite_args = NULL; rewrite_args = NULL;
...@@ -371,9 +386,15 @@ static Box* instanceGetattributeSimple(BoxedInstance* inst, BoxedString* attr_st ...@@ -371,9 +386,15 @@ static Box* instanceGetattributeSimple(BoxedInstance* inst, BoxedString* attr_st
return NULL; return NULL;
} }
template <Rewritable rewritable>
static Box* instanceGetattributeWithFallback(BoxedInstance* inst, BoxedString* attr_str, static Box* instanceGetattributeWithFallback(BoxedInstance* inst, BoxedString* attr_str,
GetattrRewriteArgs* rewrite_args = NULL) { GetattrRewriteArgs* rewrite_args = NULL) {
Box* attr_obj = instanceGetattributeSimple(inst, attr_str, rewrite_args); if (rewritable == NOT_REWRITABLE) {
assert(!rewrite_args);
rewrite_args = NULL;
}
Box* attr_obj = instanceGetattributeSimple<rewritable>(inst, attr_str, rewrite_args);
if (attr_obj) { if (attr_obj) {
if (rewrite_args && rewrite_args->isSuccessful()) if (rewrite_args && rewrite_args->isSuccessful())
...@@ -399,14 +420,21 @@ static Box* instanceGetattributeWithFallback(BoxedInstance* inst, BoxedString* a ...@@ -399,14 +420,21 @@ static Box* instanceGetattributeWithFallback(BoxedInstance* inst, BoxedString* a
if (getattr) { if (getattr) {
getattr = processDescriptor(getattr, inst, inst->inst_cls); getattr = processDescriptor(getattr, inst, inst->inst_cls);
return runtimeCallInternal<CXX>(getattr, NULL, ArgPassSpec(1), attr_str, NULL, NULL, NULL, NULL); return runtimeCallInternal<CXX, NOT_REWRITABLE>(getattr, NULL, ArgPassSpec(1), attr_str, NULL, NULL, NULL,
NULL);
} }
return NULL; return NULL;
} }
template <Rewritable rewritable>
static Box* _instanceGetattribute(Box* _inst, BoxedString* attr_str, bool raise_on_missing, static Box* _instanceGetattribute(Box* _inst, BoxedString* attr_str, bool raise_on_missing,
GetattrRewriteArgs* rewrite_args = NULL) { GetattrRewriteArgs* rewrite_args) {
if (rewritable == NOT_REWRITABLE) {
assert(!rewrite_args);
rewrite_args = NULL;
}
RELEASE_ASSERT(_inst->cls == instance_cls, ""); RELEASE_ASSERT(_inst->cls == instance_cls, "");
BoxedInstance* inst = static_cast<BoxedInstance*>(_inst); BoxedInstance* inst = static_cast<BoxedInstance*>(_inst);
...@@ -419,7 +447,7 @@ static Box* _instanceGetattribute(Box* _inst, BoxedString* attr_str, bool raise_ ...@@ -419,7 +447,7 @@ static Box* _instanceGetattribute(Box* _inst, BoxedString* attr_str, bool raise_
return inst->inst_cls; return inst->inst_cls;
} }
Box* attr = instanceGetattributeWithFallback(inst, attr_str, rewrite_args); Box* attr = instanceGetattributeWithFallback<rewritable>(inst, attr_str, rewrite_args);
if (attr) { if (attr) {
return attr; return attr;
} else if (!raise_on_missing) { } else if (!raise_on_missing) {
...@@ -429,6 +457,9 @@ static Box* _instanceGetattribute(Box* _inst, BoxedString* attr_str, bool raise_ ...@@ -429,6 +457,9 @@ static Box* _instanceGetattribute(Box* _inst, BoxedString* attr_str, bool raise_
attr_str->data()); attr_str->data());
} }
} }
static Box* _instanceGetattribute(Box* _inst, BoxedString* attr_str, bool raise_on_missing) {
return _instanceGetattribute<NOT_REWRITABLE>(_inst, attr_str, raise_on_missing, NULL);
}
// Analogous to CPython's instance_getattr // Analogous to CPython's instance_getattr
Box* instance_getattro(Box* cls, Box* attr) noexcept { Box* instance_getattro(Box* cls, Box* attr) noexcept {
...@@ -444,13 +475,13 @@ Box* instanceGetattroInternal(Box* cls, Box* _attr, GetattrRewriteArgs* rewrite_ ...@@ -444,13 +475,13 @@ Box* instanceGetattroInternal(Box* cls, Box* _attr, GetattrRewriteArgs* rewrite_
if (S == CAPI) { if (S == CAPI) {
try { try {
return _instanceGetattribute(cls, attr, true, rewrite_args); return _instanceGetattribute<REWRITABLE>(cls, attr, true, rewrite_args);
} catch (ExcInfo e) { } catch (ExcInfo e) {
setCAPIException(e); setCAPIException(e);
return NULL; return NULL;
} }
} else { } else {
return _instanceGetattribute(cls, attr, true, rewrite_args); return _instanceGetattribute<REWRITABLE>(cls, attr, true, rewrite_args);
} }
} }
...@@ -1137,7 +1168,7 @@ static void instance_dealloc(Box* _inst) noexcept { ...@@ -1137,7 +1168,7 @@ static void instance_dealloc(Box* _inst) noexcept {
static BoxedString* del_str = internStringImmortal("__del__"); static BoxedString* del_str = internStringImmortal("__del__");
// TODO: any exceptions here should get caught + printed, instead of causing a std::terminate: // TODO: any exceptions here should get caught + printed, instead of causing a std::terminate:
Box* func = instanceGetattributeSimple(inst, del_str); Box* func = instanceGetattributeSimple<NOT_REWRITABLE>(inst, del_str, NULL);
if (func) if (func)
runtimeCall(func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); runtimeCall(func, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
} }
......
...@@ -842,7 +842,8 @@ template <ExceptionStyle S> static Box* try_special_method(Box* self) noexcept(S ...@@ -842,7 +842,8 @@ template <ExceptionStyle S> static Box* try_special_method(Box* self) noexcept(S
static BoxedString* float_str = internStringImmortal("__float__"); static BoxedString* float_str = internStringImmortal("__float__");
if (PyObject_HasAttr((PyObject*)self, float_str)) { if (PyObject_HasAttr((PyObject*)self, float_str)) {
Box* r_f = callattrInternal<S>(self, float_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); Box* r_f = callattrInternal<S, NOT_REWRITABLE>(self, float_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL,
NULL, NULL, NULL);
if (!PyFloat_Check(r_f)) { if (!PyFloat_Check(r_f)) {
if (S == CAPI) { if (S == CAPI) {
if (!PyErr_Occurred()) if (!PyErr_Occurred())
...@@ -857,8 +858,8 @@ template <ExceptionStyle S> static Box* try_special_method(Box* self) noexcept(S ...@@ -857,8 +858,8 @@ template <ExceptionStyle S> static Box* try_special_method(Box* self) noexcept(S
static BoxedString* complex_str = internStringImmortal("__complex__"); static BoxedString* complex_str = internStringImmortal("__complex__");
if (PyObject_HasAttr((PyObject*)self, complex_str)) { if (PyObject_HasAttr((PyObject*)self, complex_str)) {
Box* r Box* r = callattrInternal<S, NOT_REWRITABLE>(self, complex_str, CLASS_OR_INST, NULL, ArgPassSpec(0), NULL, NULL,
= callattrInternal<S>(self, complex_str, CLASS_OR_INST, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); NULL, NULL, NULL);
if (!r) { if (!r) {
if (S == CAPI) { if (S == CAPI) {
if (!PyErr_Occurred()) if (!PyErr_Occurred())
......
...@@ -47,7 +47,7 @@ static void propertyDocCopy(BoxedProperty* prop, Box* fget) { ...@@ -47,7 +47,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<ExceptionStyle::CXX>(fget, doc_str, NULL); get_doc = getattrInternal<ExceptionStyle::CXX>(fget, doc_str);
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (!e.matches(Exception)) { if (!e.matches(Exception)) {
throw e; throw e;
......
...@@ -327,12 +327,12 @@ extern "C" PyObject* PyDict_GetItem(PyObject* dict, PyObject* key) noexcept { ...@@ -327,12 +327,12 @@ extern "C" PyObject* PyDict_GetItem(PyObject* dict, PyObject* key) noexcept {
/* preserve the existing exception */ /* preserve the existing exception */
PyObject* err_type, *err_value, *err_tb; PyObject* err_type, *err_value, *err_tb;
PyErr_Fetch(&err_type, &err_value, &err_tb); PyErr_Fetch(&err_type, &err_value, &err_tb);
Box* b = getitemInternal<CAPI>(dict, key, NULL); Box* b = getitemInternal<CAPI>(dict, key);
/* ignore errors */ /* ignore errors */
PyErr_Restore(err_type, err_value, err_tb); PyErr_Restore(err_type, err_value, err_tb);
return b; return b;
} else { } else {
Box* b = getitemInternal<CAPI>(dict, key, NULL); Box* b = getitemInternal<CAPI>(dict, key);
if (b == NULL) if (b == NULL)
PyErr_Clear(); PyErr_Clear();
return b; return b;
...@@ -691,7 +691,7 @@ Box* dictUpdate(BoxedDict* self, BoxedTuple* args, BoxedDict* kwargs) { ...@@ -691,7 +691,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<ExceptionStyle::CXX>(arg, keys_str, NULL)) { if (getattrInternal<ExceptionStyle::CXX>(arg, keys_str)) {
dictMerge(self, arg); dictMerge(self, arg);
} else { } else {
dictMergeFromSeq2(self, arg); dictMergeFromSeq2(self, arg);
......
...@@ -794,7 +794,8 @@ template <ExceptionStyle S> static BoxedFloat* _floatNew(Box* a) noexcept(S == C ...@@ -794,7 +794,8 @@ template <ExceptionStyle S> static BoxedFloat* _floatNew(Box* a) noexcept(S == C
return res; return res;
} else { } else {
static BoxedString* float_str = internStringImmortal("__float__"); static BoxedString* float_str = internStringImmortal("__float__");
Box* r = callattrInternal<S>(a, float_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); Box* r = callattrInternal<S, NOT_REWRITABLE>(a, float_str, CLASS_ONLY, NULL, ArgPassSpec(0), NULL, NULL, NULL,
NULL, NULL);
if (!r) { if (!r) {
if (S == CAPI) { if (S == CAPI) {
......
...@@ -381,7 +381,7 @@ static Box* importSub(const std::string& name, BoxedString* full_name, Box* pare ...@@ -381,7 +381,7 @@ static Box* importSub(const std::string& name, BoxedString* full_name, Box* pare
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<ExceptionStyle::CXX>(parent_module, path_str, NULL)); path_list = static_cast<BoxedList*>(getattrInternal<ExceptionStyle::CXX>(parent_module, path_str));
if (path_list == NULL || path_list->cls != list_cls) { if (path_list == NULL || path_list->cls != list_cls) {
return None; return None;
} }
...@@ -558,7 +558,7 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re ...@@ -558,7 +558,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<ExceptionStyle::CXX>(module, path_str, NULL); pathlist = getattrInternal<ExceptionStyle::CXX>(module, path_str);
} catch (ExcInfo e) { } catch (ExcInfo e) {
if (!e.matches(AttributeError)) if (!e.matches(AttributeError))
throw e; throw e;
...@@ -580,14 +580,14 @@ static void ensureFromlist(Box* module, Box* fromlist, std::string& buf, bool re ...@@ -580,14 +580,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<ExceptionStyle::CXX>(module, all_str, NULL); Box* all = getattrInternal<ExceptionStyle::CXX>(module, all_str);
if (all) { if (all) {
ensureFromlist(module, all, buf, true); ensureFromlist(module, all, buf, true);
} }
continue; continue;
} }
Box* attr = getattrInternal<ExceptionStyle::CXX>(module, s, NULL); Box* attr = getattrInternal<ExceptionStyle::CXX>(module, s);
if (attr != NULL) if (attr != NULL)
continue; continue;
......
...@@ -837,7 +837,7 @@ private: ...@@ -837,7 +837,7 @@ private:
public: public:
PyCmpComparer(Box* cmp) : cmp(cmp) {} PyCmpComparer(Box* cmp) : cmp(cmp) {}
bool operator()(Box* lhs, Box* rhs) { bool operator()(Box* lhs, Box* rhs) {
Box* r = runtimeCallInternal<CXX>(cmp, NULL, ArgPassSpec(2), lhs, rhs, NULL, NULL, NULL); Box* r = runtimeCallInternal<CXX, NOT_REWRITABLE>(cmp, NULL, ArgPassSpec(2), lhs, rhs, NULL, NULL, NULL);
if (!PyInt_Check(r)) if (!PyInt_Check(r))
raiseExcHelper(TypeError, "comparison function must return int, not %.200s", r->cls->tp_name); raiseExcHelper(TypeError, "comparison function must return int, not %.200s", r->cls->tp_name);
return static_cast<BoxedInt*>(r)->n < 0; return static_cast<BoxedInt*>(r)->n < 0;
...@@ -1141,7 +1141,7 @@ Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) { ...@@ -1141,7 +1141,7 @@ Box* _listCmp(BoxedList* lhs, BoxedList* rhs, AST_TYPE::AST_TYPE op_type) {
} else if (op_type == AST_TYPE::NotEq) { } else if (op_type == AST_TYPE::NotEq) {
return boxBool(true); return boxBool(true);
} else { } else {
Box* r = compareInternal(lhs->elts->elts[i], rhs->elts->elts[i], op_type, NULL); Box* r = compareInternal<NOT_REWRITABLE>(lhs->elts->elts[i], rhs->elts->elts[i], op_type, NULL);
return r; return r;
} }
} }
......
This diff is collapsed.
...@@ -113,22 +113,28 @@ extern "C" Box* getiterHelper(Box* o); ...@@ -113,22 +113,28 @@ extern "C" Box* getiterHelper(Box* o);
extern "C" Box* createBoxedIterWrapperIfNeeded(Box* o); extern "C" Box* createBoxedIterWrapperIfNeeded(Box* o);
struct SetattrRewriteArgs; struct SetattrRewriteArgs;
template <Rewritable rewritable>
void setattrGeneric(Box* obj, BoxedString* attr, Box* val, SetattrRewriteArgs* rewrite_args); void setattrGeneric(Box* obj, BoxedString* attr, Box* val, SetattrRewriteArgs* rewrite_args);
struct BinopRewriteArgs; struct BinopRewriteArgs;
extern "C" Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args); template <Rewritable rewritable>
Box* binopInternal(Box* lhs, Box* rhs, int op_type, bool inplace, BinopRewriteArgs* rewrite_args);
struct CallRewriteArgs; struct CallRewriteArgs;
template <ExceptionStyle S> template <ExceptionStyle S, Rewritable rewritable>
Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3, Box* runtimeCallInternal(Box* obj, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* arg3,
Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI); Box** args, const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
struct GetitemRewriteArgs; struct GetitemRewriteArgs;
template <ExceptionStyle S> template <ExceptionStyle S, Rewritable rewritable = REWRITABLE>
Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) noexcept(S == CAPI); Box* getitemInternal(Box* target, Box* slice, GetitemRewriteArgs* rewrite_args) noexcept(S == CAPI);
template <ExceptionStyle S> inline Box* getitemInternal(Box* target, Box* slice) noexcept(S == CAPI) {
return getitemInternal<S, NOT_REWRITABLE>(target, slice, NULL);
}
struct LenRewriteArgs; struct LenRewriteArgs;
template <ExceptionStyle S> BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == CAPI); template <ExceptionStyle S, Rewritable rewritable>
BoxedInt* lenInternal(Box* obj, LenRewriteArgs* rewrite_args) noexcept(S == CAPI);
Box* lenCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2, Box* lenCallInternal(BoxedFunctionBase* f, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names); Box* arg3, Box** args, const std::vector<BoxedString*>* keyword_names);
...@@ -142,23 +148,27 @@ enum LookupScope { ...@@ -142,23 +148,27 @@ enum LookupScope {
CLASS_OR_INST = 3, CLASS_OR_INST = 3,
}; };
struct CallattrRewriteArgs; struct CallattrRewriteArgs;
template <ExceptionStyle S> template <ExceptionStyle S, Rewritable rewritable>
Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope, CallattrRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* callattrInternal(Box* obj, BoxedString* attr, LookupScope, CallattrRewriteArgs* rewrite_args, ArgPassSpec argspec,
Box* arg1, Box* arg2, Box* arg3, Box** args, Box* arg1, Box* arg2, Box* arg3, Box** args,
const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI); const std::vector<BoxedString*>* keyword_names) noexcept(S == CAPI);
extern "C" void delattr_internal(Box* obj, BoxedString* attr, bool allow_custom, DelattrRewriteArgs* rewrite_args); extern "C" void delattr_internal(Box* obj, BoxedString* attr, bool allow_custom, DelattrRewriteArgs* rewrite_args);
struct CompareRewriteArgs; struct CompareRewriteArgs;
template <Rewritable rewritable>
Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrite_args); Box* compareInternal(Box* lhs, Box* rhs, int op_type, CompareRewriteArgs* rewrite_args);
// 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 S> template <ExceptionStyle S, Rewritable rewritable = REWRITABLE>
Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) noexcept(S == CAPI); Box* getattrInternal(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args) noexcept(S == CAPI);
template <ExceptionStyle S> inline Box* getattrInternal(Box* obj, BoxedString* attr) noexcept(S == CAPI) {
return getattrInternal<S, NOT_REWRITABLE>(obj, attr, NULL);
}
// 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
// data descriptor, check for instance attribute, check for non-data descriptor). It does not check for __getattr__ or // data descriptor, check for instance attribute, check for non-data descriptor). It does not check for __getattr__ or
// __getattribute__. // __getattribute__.
template <bool IsType> template <bool IsType, Rewritable rewritable>
Box* getattrInternalGeneric(Box* obj, BoxedString* attr, GetattrRewriteArgs* rewrite_args, bool cls_only, bool for_call, Box* getattrInternalGeneric(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);
...@@ -166,7 +176,11 @@ extern "C" PyObject* type_getattro(PyObject* o, PyObject* name) noexcept; ...@@ -166,7 +176,11 @@ extern "C" PyObject* type_getattro(PyObject* o, PyObject* name) noexcept;
// This is the equivalent of _PyType_Lookup(), which calls Box::getattr() on each item in the object's MRO in the // This is the equivalent of _PyType_Lookup(), which calls Box::getattr() on each item in the object's MRO in the
// appropriate order. It does not do any descriptor logic. // appropriate order. It does not do any descriptor logic.
template <Rewritable rewritable = REWRITABLE>
Box* typeLookup(BoxedClass* cls, BoxedString* attr, GetattrRewriteArgs* rewrite_args); Box* typeLookup(BoxedClass* cls, BoxedString* attr, GetattrRewriteArgs* rewrite_args);
inline Box* typeLookup(BoxedClass* cls, BoxedString* attr) {
return typeLookup<NOT_REWRITABLE>(cls, attr, NULL);
}
extern "C" void raiseAttributeErrorStr(const char* typeName, llvm::StringRef attr) __attribute__((__noreturn__)); extern "C" void raiseAttributeErrorStr(const char* typeName, llvm::StringRef attr) __attribute__((__noreturn__));
extern "C" void raiseAttributeError(Box* obj, llvm::StringRef attr) __attribute__((__noreturn__)); extern "C" void raiseAttributeError(Box* obj, llvm::StringRef attr) __attribute__((__noreturn__));
......
...@@ -127,7 +127,7 @@ Box* superGetattribute(Box* _s, Box* _attr) { ...@@ -127,7 +127,7 @@ Box* superGetattribute(Box* _s, Box* _attr) {
} }
} }
Box* r = typeLookup(s->cls, attr, NULL); Box* r = typeLookup(s->cls, attr);
// TODO implement this // TODO implement this
RELEASE_ASSERT(r, "should call the equivalent of objectGetattr here"); RELEASE_ASSERT(r, "should call the equivalent of objectGetattr here");
return processDescriptor(r, s, s->cls); return processDescriptor(r, s, s->cls);
......
...@@ -770,8 +770,8 @@ static Box* objectNewNoArgs(BoxedClass* cls) noexcept { ...@@ -770,8 +770,8 @@ static Box* objectNewNoArgs(BoxedClass* cls) noexcept {
#ifndef NDEBUG #ifndef NDEBUG
static BoxedString* new_str = internStringImmortal("__new__"); static BoxedString* new_str = internStringImmortal("__new__");
static BoxedString* init_str = internStringImmortal("__init__"); static BoxedString* init_str = internStringImmortal("__init__");
assert(typeLookup(cls, new_str, NULL) == typeLookup(object_cls, new_str, NULL) assert(typeLookup(cls, new_str) == typeLookup(object_cls, new_str)
&& typeLookup(cls, init_str, NULL) != typeLookup(object_cls, init_str, NULL)); && typeLookup(cls, init_str) != typeLookup(object_cls, init_str));
#endif #endif
return new (cls) Box(); return new (cls) Box();
} }
...@@ -934,7 +934,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -934,7 +934,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
} }
} }
} else { } else {
new_attr = typeLookup(cls, new_str, NULL); new_attr = typeLookup(cls, new_str);
try { try {
if (new_attr->cls != function_cls) // optimization if (new_attr->cls != function_cls) // optimization
new_attr = processDescriptor(new_attr, None, cls); new_attr = processDescriptor(new_attr, None, cls);
...@@ -982,7 +982,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -982,7 +982,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
static std::vector<Box*> class_making_news; static std::vector<Box*> class_making_news;
if (class_making_news.empty()) { if (class_making_news.empty()) {
for (BoxedClass* allowed_cls : { object_cls, enumerate_cls, xrange_cls, tuple_cls, list_cls, dict_cls }) { for (BoxedClass* allowed_cls : { object_cls, enumerate_cls, xrange_cls, tuple_cls, list_cls, dict_cls }) {
auto new_obj = typeLookup(allowed_cls, new_str, NULL); auto new_obj = typeLookup(allowed_cls, new_str);
gc::registerPermanentRoot(new_obj, /* allow_duplicates= */ true); gc::registerPermanentRoot(new_obj, /* allow_duplicates= */ true);
class_making_news.push_back(new_obj); class_making_news.push_back(new_obj);
} }
...@@ -1062,7 +1062,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -1062,7 +1062,7 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
} }
} }
} else { } else {
init_attr = typeLookup(cls, init_str, NULL); init_attr = typeLookup(cls, init_str);
} }
} }
...@@ -1112,7 +1112,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -1112,7 +1112,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
if (new_npassed_args >= 4) if (new_npassed_args >= 4)
srewrite_args.args = rewrite_args->args; srewrite_args.args = rewrite_args->args;
made = runtimeCallInternal<S>(new_attr, &srewrite_args, new_argspec, cls, arg2, arg3, args, keyword_names); made = runtimeCallInternal<S, REWRITABLE>(new_attr, &srewrite_args, new_argspec, cls, arg2, arg3, args,
keyword_names);
if (!made) { if (!made) {
assert(S == CAPI); assert(S == CAPI);
...@@ -1135,7 +1136,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -1135,7 +1136,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
made = objectNewNoArgs(cls); made = objectNewNoArgs(cls);
assert(made); assert(made);
} else } else
made = runtimeCallInternal<S>(new_attr, NULL, new_argspec, cls, arg2, arg3, args, keyword_names); made = runtimeCallInternal<S, NOT_REWRITABLE>(new_attr, NULL, new_argspec, cls, arg2, arg3, args,
keyword_names);
if (!made) { if (!made) {
assert(S == CAPI); assert(S == CAPI);
...@@ -1248,8 +1250,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -1248,8 +1250,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
srewrite_args.args_guarded = rewrite_args->args_guarded; srewrite_args.args_guarded = rewrite_args->args_guarded;
srewrite_args.func_guarded = true; srewrite_args.func_guarded = true;
initrtn initrtn = runtimeCallInternal<S, REWRITABLE>(init_attr, &srewrite_args, argspec, made, arg2, arg3, args,
= runtimeCallInternal<S>(init_attr, &srewrite_args, argspec, made, arg2, arg3, args, keyword_names); keyword_names);
if (!srewrite_args.out_success) { if (!srewrite_args.out_success) {
rewrite_args = NULL; rewrite_args = NULL;
...@@ -1258,7 +1260,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -1258,7 +1260,8 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
rewrite_args->rewriter->call(true, (void*)assertInitNone, srewrite_args.out_rtn); rewrite_args->rewriter->call(true, (void*)assertInitNone, srewrite_args.out_rtn);
} }
} else { } else {
initrtn = runtimeCallInternal<S>(init_attr, NULL, argspec, made, arg2, arg3, args, keyword_names); initrtn = runtimeCallInternal<S, NOT_REWRITABLE>(init_attr, NULL, argspec, made, arg2, arg3, args,
keyword_names);
} }
if (!initrtn) { if (!initrtn) {
...@@ -1823,7 +1826,8 @@ extern "C" Box* sliceNew(Box* cls, Box* start, Box* stop, Box** args) { ...@@ -1823,7 +1826,8 @@ extern "C" Box* sliceNew(Box* cls, Box* start, Box* stop, Box** args) {
static Box* instancemethodCall(BoxedInstanceMethod* self, Box* args, Box* kwargs) { static Box* instancemethodCall(BoxedInstanceMethod* self, Box* args, Box* kwargs) {
// Not the most effficient, but it works: // Not the most effficient, but it works:
return runtimeCallInternal<CXX>(self, NULL, ArgPassSpec(0, 0, true, true), args, kwargs, NULL, NULL, NULL); return runtimeCallInternal<CXX, NOT_REWRITABLE>(self, NULL, ArgPassSpec(0, 0, true, true), args, kwargs, NULL, NULL,
NULL);
// TODO add a tpp_call // TODO add a tpp_call
} }
...@@ -1872,7 +1876,7 @@ static Box* instancemethodRepr(Box* b) { ...@@ -1872,7 +1876,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<CXX>(func, name_str, NULL); funcname = getattrInternal<CXX>(func, name_str);
if (funcname != NULL) { if (funcname != NULL) {
if (!PyString_Check(funcname)) { if (!PyString_Check(funcname)) {
...@@ -1884,7 +1888,7 @@ static Box* instancemethodRepr(Box* b) { ...@@ -1884,7 +1888,7 @@ static Box* instancemethodRepr(Box* b) {
if (klass == NULL) { if (klass == NULL) {
klassname = NULL; klassname = NULL;
} else { } else {
klassname = getattrInternal<CXX>(klass, name_str, NULL); klassname = getattrInternal<CXX>(klass, name_str);
if (klassname != NULL) { if (klassname != NULL) {
if (!PyString_Check(klassname)) { if (!PyString_Check(klassname)) {
klassname = NULL; klassname = NULL;
...@@ -1916,7 +1920,7 @@ Box* instancemethodEq(BoxedInstanceMethod* self, Box* rhs) { ...@@ -1916,7 +1920,7 @@ Box* instancemethodEq(BoxedInstanceMethod* self, Box* rhs) {
return boxBool(true); return boxBool(true);
} else { } else {
if (self->obj != NULL && rhs_im->obj != NULL) { if (self->obj != NULL && rhs_im->obj != NULL) {
return compareInternal(self->obj, rhs_im->obj, AST_TYPE::Eq, NULL); return compareInternal<NOT_REWRITABLE>(self->obj, rhs_im->obj, AST_TYPE::Eq, NULL);
} else { } else {
return boxBool(false); return boxBool(false);
} }
...@@ -2325,8 +2329,8 @@ public: ...@@ -2325,8 +2329,8 @@ public:
if (self->isDictBacked()) { if (self->isDictBacked()) {
static BoxedString* setitem_str = internStringImmortal("__setitem__"); static BoxedString* setitem_str = internStringImmortal("__setitem__");
return callattrInternal<CXX>(self->getDictBacking(), setitem_str, LookupScope::CLASS_ONLY, NULL, return callattrInternal<CXX, NOT_REWRITABLE>(self->getDictBacking(), setitem_str, LookupScope::CLASS_ONLY,
ArgPassSpec(2), _key, value, NULL, NULL, NULL); NULL, ArgPassSpec(2), _key, value, NULL, NULL, NULL);
} }
assert(_key->cls == str_cls); assert(_key->cls == str_cls);
...@@ -2362,8 +2366,9 @@ public: ...@@ -2362,8 +2366,9 @@ public:
if (self->isDictBacked()) { if (self->isDictBacked()) {
static BoxedString* setdefault_str = internStringImmortal("setdefault"); static BoxedString* setdefault_str = internStringImmortal("setdefault");
return callattrInternal<CXX>(self->getDictBacking(), setdefault_str, LookupScope::CLASS_ONLY, NULL, return callattrInternal<CXX, NOT_REWRITABLE>(self->getDictBacking(), setdefault_str,
ArgPassSpec(2), _key, value, NULL, NULL, NULL); LookupScope::CLASS_ONLY, NULL, ArgPassSpec(2), _key, value,
NULL, NULL, NULL);
} }
assert(_key->cls == str_cls); assert(_key->cls == str_cls);
...@@ -2649,8 +2654,8 @@ public: ...@@ -2649,8 +2654,8 @@ public:
if (self->isDictBacked()) { if (self->isDictBacked()) {
static BoxedString* iter_str = internStringImmortal("__iter__"); static BoxedString* iter_str = internStringImmortal("__iter__");
return callattrInternal<CXX>(self->getDictBacking(), iter_str, LookupScope::CLASS_ONLY, NULL, return callattrInternal<CXX, NOT_REWRITABLE>(self->getDictBacking(), iter_str, LookupScope::CLASS_ONLY,
ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL); NULL, ArgPassSpec(0), NULL, NULL, NULL, NULL, NULL);
} }
return new AttrWrapperIter(self); return new AttrWrapperIter(self);
...@@ -2664,8 +2669,8 @@ public: ...@@ -2664,8 +2669,8 @@ public:
BoxedDict* dict = (BoxedDict*)AttrWrapper::copy(_self); BoxedDict* dict = (BoxedDict*)AttrWrapper::copy(_self);
assert(dict->cls == dict_cls); assert(dict->cls == dict_cls);
static BoxedString* eq_str = internStringImmortal("__eq__"); static BoxedString* eq_str = internStringImmortal("__eq__");
return callattrInternal<CXX>(dict, eq_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(1), _other, NULL, NULL, return callattrInternal<CXX, NOT_REWRITABLE>(dict, eq_str, LookupScope::CLASS_ONLY, NULL, ArgPassSpec(1),
NULL, NULL); _other, NULL, NULL, NULL, NULL);
} }
static Box* ne(Box* _self, Box* _other) { return eq(_self, _other) == True ? False : True; } static Box* ne(Box* _self, Box* _other) { return eq(_self, _other) == True ? False : True; }
...@@ -2840,7 +2845,7 @@ Box* objectSetattr(Box* obj, Box* attr, Box* value) { ...@@ -2840,7 +2845,7 @@ Box* objectSetattr(Box* obj, Box* attr, Box* value) {
} }
BoxedString* attr_str = static_cast<BoxedString*>(attr); BoxedString* attr_str = static_cast<BoxedString*>(attr);
setattrGeneric(obj, attr_str, value, NULL); setattrGeneric<NOT_REWRITABLE>(obj, attr_str, value, NULL);
return None; return None;
} }
......
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