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