Commit 5e33fe60 authored by Marius Wachtler's avatar Marius Wachtler

use runtime ic inside slot_tp_repr and slot_tp_str

parent 8c5a8657
...@@ -457,7 +457,7 @@ struct _typeobject { ...@@ -457,7 +457,7 @@ struct _typeobject {
void* _hcls; void* _hcls;
void* _hcattrs; void* _hcattrs;
char _ics[40]; char _ics[48];
int _attrs_offset; int _attrs_offset;
char _flags[7]; // These are bools in C++ char _flags[7]; // These are bools in C++
void* _tpp_descr_get; void* _tpp_descr_get;
......
...@@ -630,33 +630,28 @@ extern "C" int _PyObject_SlotCompare(PyObject* self, PyObject* other) noexcept { ...@@ -630,33 +630,28 @@ extern "C" int _PyObject_SlotCompare(PyObject* self, PyObject* other) noexcept {
static PyObject* slot_tp_repr(PyObject* self) noexcept { static PyObject* slot_tp_repr(PyObject* self) noexcept {
STAT_TIMER(t0, "us_timer_slot_tprepr", SLOT_AVOIDABILITY(self)); STAT_TIMER(t0, "us_timer_slot_tprepr", SLOT_AVOIDABILITY(self));
PyObject* func, *res; try {
static PyObject* repr_str; PyObject* res = self->reprIC();
if (res != NULL)
func = lookup_method(self, "__repr__", &repr_str);
if (func != NULL) {
res = PyEval_CallObject(func, NULL);
Py_DECREF(func);
return res; return res;
}
PyErr_Clear();
return PyString_FromFormat("<%s object at %p>", Py_TYPE(self)->tp_name, self); return PyString_FromFormat("<%s object at %p>", Py_TYPE(self)->tp_name, self);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
} }
static PyObject* slot_tp_str(PyObject* self) noexcept { static PyObject* slot_tp_str(PyObject* self) noexcept {
STAT_TIMER(t0, "us_timer_slot_tpstr", SLOT_AVOIDABILITY(self)); STAT_TIMER(t0, "us_timer_slot_tpstr", SLOT_AVOIDABILITY(self));
PyObject* func, *res; try {
static PyObject* str_str; PyObject* res = self->strIC();
if (res != NULL)
func = lookup_method(self, "__str__", &str_str);
if (func != NULL) {
res = PyEval_CallObject(func, NULL);
Py_DECREF(func);
return res; return res;
} else {
PyErr_Clear();
return slot_tp_repr(self); return slot_tp_repr(self);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
} }
} }
......
...@@ -890,7 +890,8 @@ public: ...@@ -890,7 +890,8 @@ public:
// Only valid for hc-backed instances: // Only valid for hc-backed instances:
BORROWED(Box*) getAttrWrapper(); BORROWED(Box*) getAttrWrapper();
Box* reprIC(); Box* reprIC(); // returns null on nonexistent!
Box* strIC(); // returns null on nonexistent!
BoxedString* reprICAsString(); BoxedString* reprICAsString();
bool nonzeroIC(); bool nonzeroIC();
Box* hasnextOrNullIC(); Box* hasnextOrNullIC();
......
...@@ -229,16 +229,31 @@ Box* BoxedClass::callReprIC(Box* obj) { ...@@ -229,16 +229,31 @@ Box* BoxedClass::callReprIC(Box* obj) {
assert(obj->cls == this); assert(obj->cls == this);
auto ic = repr_ic.get(); auto ic = repr_ic.get();
if (!ic) { if (unlikely(!ic)) {
ic = new CallattrIC(); ic = new CallattrIC();
repr_ic.reset(ic); repr_ic.reset(ic);
} }
static BoxedString* repr_str = getStaticString("__repr__"); static BoxedString* repr_str = getStaticString("__repr__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = false, .argspec = ArgPassSpec(0) }; CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
return ic->call(obj, repr_str, callattr_flags, nullptr, nullptr, nullptr, nullptr, nullptr); return ic->call(obj, repr_str, callattr_flags, nullptr, nullptr, nullptr, nullptr, nullptr);
} }
Box* BoxedClass::callStrIC(Box* obj) {
assert(obj->cls == this);
auto ic = str_ic.get();
if (unlikely(!ic)) {
ic = new CallattrIC();
str_ic.reset(ic);
}
static BoxedString* str_str = getStaticString("__str__");
CallattrFlags callattr_flags{.cls_only = true, .null_on_nonexistent = true, .argspec = ArgPassSpec(0) };
return ic->call(obj, str_str, callattr_flags, nullptr, nullptr, nullptr, nullptr, nullptr);
}
Box* BoxedClass::callIterIC(Box* obj) { Box* BoxedClass::callIterIC(Box* obj) {
assert(obj->cls == this); assert(obj->cls == this);
...@@ -269,8 +284,14 @@ Box* Box::reprIC() { ...@@ -269,8 +284,14 @@ Box* Box::reprIC() {
return this->cls->callReprIC(this); return this->cls->callReprIC(this);
} }
Box* Box::strIC() {
return this->cls->callStrIC(this);
}
BoxedString* Box::reprICAsString() { BoxedString* Box::reprICAsString() {
Box* r = this->reprIC(); Box* r = this->reprIC();
if (!r)
raiseAttributeError(this, "__repr__");
if (isSubclass(r->cls, unicode_cls)) { if (isSubclass(r->cls, unicode_cls)) {
r = PyUnicode_AsASCIIString(autoDecref(r)); r = PyUnicode_AsASCIIString(autoDecref(r));
...@@ -3083,7 +3104,7 @@ static PyObject* object_new(PyTypeObject* type, PyObject* args, PyObject* kwds) ...@@ -3083,7 +3104,7 @@ static PyObject* object_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
} }
static Box* type_name(Box* b, void*) noexcept; static Box* type_name(Box* b, void*) noexcept;
Box* objectRepr(Box* self) { Box* object_repr(Box* self) noexcept {
BoxedClass* type = self->cls; BoxedClass* type = self->cls;
DecrefHandle<Box, true> mod(NULL); DecrefHandle<Box, true> mod(NULL);
...@@ -3098,12 +3119,12 @@ Box* objectRepr(Box* self) { ...@@ -3098,12 +3119,12 @@ Box* objectRepr(Box* self) {
} }
static Box* object_str(Box* obj) noexcept { static Box* object_str(Box* obj) noexcept {
try { unaryfunc f;
return obj->reprIC();
} catch (ExcInfo e) { f = Py_TYPE(obj)->tp_repr;
setCAPIException(e); if (f == NULL)
return NULL; f = object_repr;
} return f(obj);
} }
Box* objectHash(Box* obj) { Box* objectHash(Box* obj) {
...@@ -4336,8 +4357,8 @@ void setupRuntime() { ...@@ -4336,8 +4357,8 @@ void setupRuntime() {
SET = typeFromClass(set_cls); SET = typeFromClass(set_cls);
FROZENSET = typeFromClass(frozenset_cls); FROZENSET = typeFromClass(frozenset_cls);
object_cls->giveAttr("__repr__", object_cls->giveAttr("__repr__", new BoxedFunction(FunctionMetadata::create((void*)object_repr, UNKNOWN, 1, false,
new BoxedFunction(FunctionMetadata::create((void*)objectRepr, UNKNOWN, 1, false, false))); false, ParamNames::empty(), CAPI)));
object_cls->giveAttr("__subclasshook__", object_cls->giveAttr("__subclasshook__",
boxInstanceMethod(object_cls, autoDecref(new BoxedFunction(FunctionMetadata::create( boxInstanceMethod(object_cls, autoDecref(new BoxedFunction(FunctionMetadata::create(
(void*)objectSubclasshook, UNKNOWN, 2))), (void*)objectSubclasshook, UNKNOWN, 2))),
......
...@@ -185,11 +185,12 @@ public: ...@@ -185,11 +185,12 @@ public:
// Any new ics here need to get reflected in BoxedClass::dealloc // Any new ics here need to get reflected in BoxedClass::dealloc
std::unique_ptr<CallattrCapiIC> next_ic; std::unique_ptr<CallattrCapiIC> next_ic;
std::unique_ptr<CallattrIC> hasnext_ic, repr_ic, iter_ic; std::unique_ptr<CallattrIC> hasnext_ic, iter_ic, repr_ic, str_ic;
std::unique_ptr<NonzeroIC> nonzero_ic; std::unique_ptr<NonzeroIC> nonzero_ic;
Box* callHasnextIC(Box* obj, bool null_on_nonexistent); Box* callHasnextIC(Box* obj, bool null_on_nonexistent);
Box* call_nextIC(Box* obj) noexcept; Box* call_nextIC(Box* obj) noexcept;
Box* callReprIC(Box* obj); Box* callReprIC(Box* obj); // returns null on nonexistent!
Box* callStrIC(Box* obj); // returns null on nonexistent!
Box* callIterIC(Box* obj); Box* callIterIC(Box* obj);
bool callNonzeroIC(Box* obj); bool callNonzeroIC(Box* obj);
......
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