Commit 63ec21c9 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Speed up a number of runtime functions

callable(), str(), repr(), PySequence_GetItem(),
and PyObject_HasAttrString()

Mostly by bringing in the CPython versions.
parent a6a326e5
...@@ -749,15 +749,6 @@ extern "C" PyObject* PyObject_GetIter(PyObject* o) noexcept { ...@@ -749,15 +749,6 @@ extern "C" PyObject* PyObject_GetIter(PyObject* o) noexcept {
} }
} }
extern "C" PyObject* PyObject_Repr(PyObject* obj) noexcept {
try {
return repr(obj);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
static int recursive_issubclass(PyObject* derived, PyObject* cls) noexcept { static int recursive_issubclass(PyObject* derived, PyObject* cls) noexcept {
int retval; int retval;
...@@ -1454,14 +1445,26 @@ extern "C" PyObject* PySequence_InPlaceRepeat(PyObject* o, Py_ssize_t count) noe ...@@ -1454,14 +1445,26 @@ extern "C" PyObject* PySequence_InPlaceRepeat(PyObject* o, Py_ssize_t count) noe
return nullptr; return nullptr;
} }
extern "C" PyObject* PySequence_GetItem(PyObject* o, Py_ssize_t i) noexcept { extern "C" PyObject* PySequence_GetItem(PyObject* s, Py_ssize_t i) noexcept {
try { PySequenceMethods* m;
// Not sure if this is really the same:
return getitem(o, boxInt(i)); if (s == NULL)
} catch (ExcInfo e) { return null_error();
setCAPIException(e);
return NULL; m = s->cls->tp_as_sequence;
if (m && m->sq_item) {
if (i < 0) {
if (m->sq_length) {
Py_ssize_t l = (*m->sq_length)(s);
if (l < 0)
return NULL;
i += l;
}
}
return m->sq_item(s, i);
} }
return type_error("'%.200s' object does not support indexing", s);
} }
PyObject* _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop) { PyObject* _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop) {
......
...@@ -379,19 +379,80 @@ extern "C" PyObject* PyObject_Unicode(PyObject* v) noexcept { ...@@ -379,19 +379,80 @@ extern "C" PyObject* PyObject_Unicode(PyObject* v) noexcept {
return res; return res;
} }
extern "C" PyObject* _PyObject_Str(PyObject* v) noexcept { extern "C" PyObject* PyObject_Repr(PyObject* v) noexcept {
if (PyErr_CheckSignals())
return NULL;
#ifdef USE_STACKCHECK
if (PyOS_CheckStack()) {
PyErr_SetString(PyExc_MemoryError, "stack overflow");
return NULL;
}
#endif
if (v == NULL) if (v == NULL)
return boxString("<NULL>"); return PyString_FromString("<NULL>");
else if (Py_TYPE(v)->tp_repr == NULL)
return PyString_FromFormat("<%s object at %p>", Py_TYPE(v)->tp_name, v);
else {
PyObject* res;
res = (*Py_TYPE(v)->tp_repr)(v);
if (res == NULL)
return NULL;
#ifdef Py_USING_UNICODE
if (PyUnicode_Check(res)) {
PyObject* str;
str = PyUnicode_AsEncodedString(res, NULL, NULL);
Py_DECREF(res);
if (str)
res = str;
else
return NULL;
}
#endif
if (!PyString_Check(res)) {
PyErr_Format(PyExc_TypeError, "__repr__ returned non-string (type %.200s)", Py_TYPE(res)->tp_name);
Py_DECREF(res);
return NULL;
}
return res;
}
}
if (v->cls == str_cls) extern "C" PyObject* _PyObject_Str(PyObject* v) noexcept {
PyObject* res;
int type_ok;
if (v == NULL)
return PyString_FromString("<NULL>");
if (PyString_CheckExact(v)) {
Py_INCREF(v);
return v;
}
#ifdef Py_USING_UNICODE
if (PyUnicode_CheckExact(v)) {
Py_INCREF(v);
return v; return v;
}
#endif
if (Py_TYPE(v)->tp_str == NULL)
return PyObject_Repr(v);
try { /* It is possible for a type to have a tp_str representation that loops
return str(v); infinitely. */
} catch (ExcInfo e) { if (Py_EnterRecursiveCall(" while getting the str of an object"))
setCAPIException(e); return NULL;
res = (*Py_TYPE(v)->tp_str)(v);
Py_LeaveRecursiveCall();
if (res == NULL)
return NULL;
type_ok = PyString_Check(res);
#ifdef Py_USING_UNICODE
type_ok = type_ok || PyUnicode_Check(res);
#endif
if (!type_ok) {
PyErr_Format(PyExc_TypeError, "__str__ returned non-string (type %.200s)", Py_TYPE(res)->tp_name);
Py_DECREF(res);
return NULL; return NULL;
} }
return res;
} }
extern "C" PyObject* PyObject_Str(PyObject* v) noexcept { extern "C" PyObject* PyObject_Str(PyObject* v) noexcept {
...@@ -473,7 +534,10 @@ extern "C" int PyObject_SetAttrString(PyObject* v, const char* name, PyObject* w ...@@ -473,7 +534,10 @@ 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 {
return getattr(o, internStringMortal(attr)); Box* r = getattrInternal(o, internStringMortal(attr), NULL);
if (!r)
PyErr_Format(PyExc_AttributeError, "'%.50s' object has no attribute '%.400s'", o->cls->tp_name, attr);
return r;
} catch (ExcInfo e) { } catch (ExcInfo e) {
setCAPIException(e); setCAPIException(e);
return NULL; return NULL;
......
...@@ -854,9 +854,7 @@ Box* zip(BoxedTuple* containers) { ...@@ -854,9 +854,7 @@ Box* zip(BoxedTuple* containers) {
} }
static Box* callable(Box* obj) { static Box* callable(Box* obj) {
Box* r = PyBool_FromLong((long)PyCallable_Check(obj)); return PyBool_FromLong((long)PyCallable_Check(obj));
checkAndThrowCAPIException();
return r;
} }
BoxedClass* notimplemented_cls; BoxedClass* notimplemented_cls;
......
...@@ -638,9 +638,19 @@ extern "C" int PyObject_Print(PyObject* obj, FILE* fp, int flags) noexcept { ...@@ -638,9 +638,19 @@ extern "C" int PyObject_Print(PyObject* obj, FILE* fp, int flags) noexcept {
extern "C" int PyCallable_Check(PyObject* x) noexcept { extern "C" int PyCallable_Check(PyObject* x) noexcept {
if (x == NULL) if (x == NULL)
return 0; return 0;
if (PyInstance_Check(x)) {
static BoxedString* call_attr = internStringImmortal("__call__"); PyObject* call = PyObject_GetAttrString(x, "__call__");
return typeLookup(x->cls, call_attr, NULL) != NULL; if (call == NULL) {
PyErr_Clear();
return 0;
}
/* Could test recursively but don't, for fear of endless
recursion if some joker sets self.__call__ = self */
Py_DECREF(call);
return 1;
} else {
return x->cls->tp_call != NULL;
}
} }
extern "C" int Py_FlushLine(void) noexcept { extern "C" int Py_FlushLine(void) noexcept {
......
...@@ -1142,6 +1142,8 @@ void setupInt() { ...@@ -1142,6 +1142,8 @@ void setupInt() {
add_operators(int_cls); add_operators(int_cls);
int_cls->freeze(); int_cls->freeze();
int_cls->tp_repr = (reprfunc)int_to_decimal_string;
} }
void teardownInt() { void teardownInt() {
......
...@@ -1557,15 +1557,19 @@ extern "C" Box* strNonzero(BoxedString* self) { ...@@ -1557,15 +1557,19 @@ extern "C" Box* strNonzero(BoxedString* self) {
extern "C" Box* strNew(BoxedClass* cls, Box* obj) { extern "C" Box* strNew(BoxedClass* cls, Box* obj) {
assert(isSubclass(cls, str_cls)); assert(isSubclass(cls, str_cls));
Box* rtn = str(obj); if (cls != str_cls) {
assert(PyString_Check(rtn)); Box* tmp = strNew(str_cls, obj);
assert(isSubclass(tmp->cls, str_cls));
BoxedString* tmp_s = static_cast<BoxedString*>(tmp);
if (cls == str_cls) return new (cls, tmp_s->size()) BoxedString(tmp_s->s());
return rtn; }
BoxedString* _rtn = static_cast<BoxedString*>(rtn);
return new (cls, _rtn->size()) BoxedString(_rtn->s()); Box* r = PyObject_Str(obj);
if (!r)
throwCAPIException();
assert(PyString_Check(r));
return r;
} }
extern "C" Box* basestringNew(BoxedClass* cls, Box* args, Box* kwargs) { extern "C" Box* basestringNew(BoxedClass* cls, Box* args, Box* kwargs) {
......
...@@ -517,6 +517,19 @@ static PyObject* tupleslice(PyTupleObject* a, Py_ssize_t ilow, Py_ssize_t ihigh) ...@@ -517,6 +517,19 @@ static PyObject* tupleslice(PyTupleObject* a, Py_ssize_t ilow, Py_ssize_t ihigh)
return (PyObject*)np; return (PyObject*)np;
} }
static PyObject* tupleitem(register PyTupleObject* a, register Py_ssize_t i) {
if (i < 0 || i >= Py_SIZE(a)) {
PyErr_SetString(PyExc_IndexError, "tuple index out of range");
return NULL;
}
Py_INCREF(a->ob_item[i]);
return a->ob_item[i];
}
static Py_ssize_t tuplelength(PyTupleObject* a) {
return Py_SIZE(a);
}
void setupTuple() { void setupTuple() {
tuple_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &tupleIteratorGCHandler, 0, 0, tuple_iterator_cls = BoxedHeapClass::create(type_cls, object_cls, &tupleIteratorGCHandler, 0, 0,
sizeof(BoxedTupleIterator), false, "tuple"); sizeof(BoxedTupleIterator), false, "tuple");
...@@ -528,8 +541,6 @@ void setupTuple() { ...@@ -528,8 +541,6 @@ void setupTuple() {
addRTFunction(getitem, (void*)tupleGetitem, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, UNKNOWN }); addRTFunction(getitem, (void*)tupleGetitem, UNKNOWN, std::vector<ConcreteCompilerType*>{ UNKNOWN, UNKNOWN });
tuple_cls->giveAttr("__getitem__", new BoxedFunction(getitem)); tuple_cls->giveAttr("__getitem__", new BoxedFunction(getitem));
tuple_cls->tp_as_sequence->sq_slice = (ssizessizeargfunc)&tupleslice;
tuple_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)tupleContains, BOXED_BOOL, 2))); tuple_cls->giveAttr("__contains__", new BoxedFunction(boxRTFunction((void*)tupleContains, BOXED_BOOL, 2)));
tuple_cls->giveAttr("index", new BoxedFunction(boxRTFunction((void*)tupleIndex, BOXED_INT, 4, 2, false, false), tuple_cls->giveAttr("index", new BoxedFunction(boxRTFunction((void*)tupleIndex, BOXED_INT, 4, 2, false, false),
{ boxInt(0), boxInt(std::numeric_limits<Py_ssize_t>::max()) })); { boxInt(0), boxInt(std::numeric_limits<Py_ssize_t>::max()) }));
...@@ -550,10 +561,14 @@ void setupTuple() { ...@@ -550,10 +561,14 @@ void setupTuple() {
tuple_cls->giveAttr("__rmul__", new BoxedFunction(boxRTFunction((void*)tupleMul, BOXED_TUPLE, 2))); tuple_cls->giveAttr("__rmul__", new BoxedFunction(boxRTFunction((void*)tupleMul, BOXED_TUPLE, 2)));
tuple_cls->tp_hash = (hashfunc)tuple_hash; tuple_cls->tp_hash = (hashfunc)tuple_hash;
tuple_cls->tp_as_sequence->sq_slice = (ssizessizeargfunc)&tupleslice;
add_operators(tuple_cls); add_operators(tuple_cls);
tuple_cls->freeze(); tuple_cls->freeze();
tuple_cls->tp_as_sequence->sq_item = (ssizeargfunc)tupleitem;
tuple_cls->tp_as_sequence->sq_length = (lenfunc)tuplelength;
CLFunction* hasnext = boxRTFunction((void*)tupleiterHasnextUnboxed, BOOL, 1); CLFunction* hasnext = boxRTFunction((void*)tupleiterHasnextUnboxed, BOOL, 1);
addRTFunction(hasnext, (void*)tupleiterHasnext, BOXED_BOOL); addRTFunction(hasnext, (void*)tupleiterHasnext, BOXED_BOOL);
tuple_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext)); tuple_iterator_cls->giveAttr("__hasnext__", new BoxedFunction(hasnext));
......
...@@ -20,3 +20,5 @@ class C(object): ...@@ -20,3 +20,5 @@ class C(object):
return MyStr("hello world") return MyStr("hello world")
print type(str(C())) print type(str(C()))
m = MyStr(C())
print type(m), repr(m)
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