Commit ce798520 authored by Benjamin Peterson's avatar Benjamin Peterson

use the static identifier api for looking up special methods

I had to move the static identifier code from unicodeobject.h to object.h in
order for this to work.
parent cd899125
...@@ -117,6 +117,35 @@ typedef struct { ...@@ -117,6 +117,35 @@ typedef struct {
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size) #define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
/********************* String Literals ****************************************/
/* This structure helps managing static strings. The basic usage goes like this:
Instead of doing
r = PyObject_CallMethod(o, "foo", "args", ...);
do
_Py_IDENTIFIER(foo);
...
r = _PyObject_CallMethodId(o, &PyId_foo, "args", ...);
PyId_foo is a static variable, either on block level or file level. On first
usage, the string "foo" is interned, and the structures are linked. On interpreter
shutdown, all strings are released (through _PyUnicode_ClearStaticStrings).
Alternatively, _Py_static_string allows to choose the variable name.
_PyUnicode_FromId returns a borrowed reference to the interned string.
_PyObject_{Get,Set,Has}AttrId are __getattr__ versions using _Py_Identifier*.
*/
typedef struct _Py_Identifier {
struct _Py_Identifier *next;
const char* string;
PyObject *object;
} _Py_Identifier;
#define _Py_static_string(varname, value) static _Py_Identifier varname = { 0, value, 0 }
#define _Py_IDENTIFIER(varname) _Py_static_string(PyId_##varname, #varname)
/* /*
Type objects contain a string containing the type name (to help somewhat Type objects contain a string containing the type name (to help somewhat
in debugging), the allocation parameters (see PyObject_New() and in debugging), the allocation parameters (see PyObject_New() and
...@@ -448,7 +477,7 @@ PyAPI_FUNC(PyObject *) PyType_GenericNew(PyTypeObject *, ...@@ -448,7 +477,7 @@ PyAPI_FUNC(PyObject *) PyType_GenericNew(PyTypeObject *,
PyObject *, PyObject *); PyObject *, PyObject *);
#ifndef Py_LIMITED_API #ifndef Py_LIMITED_API
PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *); PyAPI_FUNC(PyObject *) _PyType_Lookup(PyTypeObject *, PyObject *);
PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, char *, PyObject **); PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, _Py_Identifier *);
PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *); PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *);
#endif #endif
PyAPI_FUNC(unsigned int) PyType_ClearCache(void); PyAPI_FUNC(unsigned int) PyType_ClearCache(void);
......
...@@ -2120,35 +2120,6 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency( ...@@ -2120,35 +2120,6 @@ PyAPI_FUNC(int) _PyUnicode_CheckConsistency(
int check_content); int check_content);
#endif #endif
/********************* String Literals ****************************************/
/* This structure helps managing static strings. The basic usage goes like this:
Instead of doing
r = PyObject_CallMethod(o, "foo", "args", ...);
do
_Py_IDENTIFIER(foo);
...
r = _PyObject_CallMethodId(o, &PyId_foo, "args", ...);
PyId_foo is a static variable, either on block level or file level. On first
usage, the string "foo" is interned, and the structures are linked. On interpreter
shutdown, all strings are released (through _PyUnicode_ClearStaticStrings).
Alternatively, _Py_static_string allows to choose the variable name.
_PyUnicode_FromId returns a borrowed reference to the interned string.
_PyObject_{Get,Set,Has}AttrId are __getattr__ versions using _Py_Identifier*.
*/
typedef struct _Py_Identifier {
struct _Py_Identifier *next;
const char* string;
PyObject *object;
} _Py_Identifier;
#define _Py_static_string(varname, value) static _Py_Identifier varname = { 0, value, 0 }
#define _Py_IDENTIFIER(varname) _Py_static_string(PyId_##varname, #varname)
/* Return an interned Unicode object for an Identifier; may fail if there is no memory.*/ /* Return an interned Unicode object for an Identifier; may fail if there is no memory.*/
PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*); PyAPI_FUNC(PyObject*) _PyUnicode_FromId(_Py_Identifier*);
/* Clear all static strings. */ /* Clear all static strings. */
......
...@@ -887,10 +887,10 @@ FUNC1(atanh, m_atanh, 0, ...@@ -887,10 +887,10 @@ FUNC1(atanh, m_atanh, 0,
"atanh(x)\n\nReturn the hyperbolic arc tangent (measured in radians) of x.") "atanh(x)\n\nReturn the hyperbolic arc tangent (measured in radians) of x.")
static PyObject * math_ceil(PyObject *self, PyObject *number) { static PyObject * math_ceil(PyObject *self, PyObject *number) {
static PyObject *ceil_str = NULL; _Py_IDENTIFIER(__ceil__);
PyObject *method, *result; PyObject *method, *result;
method = _PyObject_LookupSpecial(number, "__ceil__", &ceil_str); method = _PyObject_LookupSpecial(number, &PyId___ceil__);
if (method == NULL) { if (method == NULL) {
if (PyErr_Occurred()) if (PyErr_Occurred())
return NULL; return NULL;
...@@ -925,10 +925,10 @@ FUNC1(fabs, fabs, 0, ...@@ -925,10 +925,10 @@ FUNC1(fabs, fabs, 0,
"fabs(x)\n\nReturn the absolute value of the float x.") "fabs(x)\n\nReturn the absolute value of the float x.")
static PyObject * math_floor(PyObject *self, PyObject *number) { static PyObject * math_floor(PyObject *self, PyObject *number) {
static PyObject *floor_str = NULL; _Py_IDENTIFIER(__floor__);
PyObject *method, *result; PyObject *method, *result;
method = _PyObject_LookupSpecial(number, "__floor__", &floor_str); method = _PyObject_LookupSpecial(number, &PyId___floor__);
if (method == NULL) { if (method == NULL) {
if (PyErr_Occurred()) if (PyErr_Occurred())
return NULL; return NULL;
...@@ -1462,7 +1462,7 @@ PyDoc_STRVAR(math_factorial_doc, ...@@ -1462,7 +1462,7 @@ PyDoc_STRVAR(math_factorial_doc,
static PyObject * static PyObject *
math_trunc(PyObject *self, PyObject *number) math_trunc(PyObject *self, PyObject *number)
{ {
static PyObject *trunc_str = NULL; _Py_IDENTIFIER(__trunc__);
PyObject *trunc, *result; PyObject *trunc, *result;
if (Py_TYPE(number)->tp_dict == NULL) { if (Py_TYPE(number)->tp_dict == NULL) {
...@@ -1470,7 +1470,7 @@ math_trunc(PyObject *self, PyObject *number) ...@@ -1470,7 +1470,7 @@ math_trunc(PyObject *self, PyObject *number)
return NULL; return NULL;
} }
trunc = _PyObject_LookupSpecial(number, "__trunc__", &trunc_str); trunc = _PyObject_LookupSpecial(number, &PyId___trunc__);
if (trunc == NULL) { if (trunc == NULL) {
if (!PyErr_Occurred()) if (!PyErr_Occurred())
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
......
...@@ -74,7 +74,7 @@ PyObject_Length(PyObject *o) ...@@ -74,7 +74,7 @@ PyObject_Length(PyObject *o)
Py_ssize_t Py_ssize_t
_PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue) _PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue)
{ {
static PyObject *hintstrobj = NULL; _Py_IDENTIFIER(__length_hint__);
PyObject *ro, *hintmeth; PyObject *ro, *hintmeth;
Py_ssize_t rv; Py_ssize_t rv;
...@@ -89,7 +89,7 @@ _PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue) ...@@ -89,7 +89,7 @@ _PyObject_LengthHint(PyObject *o, Py_ssize_t defaultvalue)
} }
/* try o.__length_hint__() */ /* try o.__length_hint__() */
hintmeth = _PyObject_LookupSpecial(o, "__length_hint__", &hintstrobj); hintmeth = _PyObject_LookupSpecial(o, &PyId___length_hint__);
if (hintmeth == NULL) { if (hintmeth == NULL) {
if (PyErr_Occurred()) if (PyErr_Occurred())
return -1; return -1;
...@@ -697,7 +697,7 @@ PyObject_Format(PyObject *obj, PyObject *format_spec) ...@@ -697,7 +697,7 @@ PyObject_Format(PyObject *obj, PyObject *format_spec)
PyObject *meth; PyObject *meth;
PyObject *empty = NULL; PyObject *empty = NULL;
PyObject *result = NULL; PyObject *result = NULL;
static PyObject *format_cache = NULL; _Py_IDENTIFIER(__format__);
/* If no format_spec is provided, use an empty string */ /* If no format_spec is provided, use an empty string */
if (format_spec == NULL) { if (format_spec == NULL) {
...@@ -706,7 +706,7 @@ PyObject_Format(PyObject *obj, PyObject *format_spec) ...@@ -706,7 +706,7 @@ PyObject_Format(PyObject *obj, PyObject *format_spec)
} }
/* Find the (unbound!) __format__ method (a borrowed reference) */ /* Find the (unbound!) __format__ method (a borrowed reference) */
meth = _PyObject_LookupSpecial(obj, "__format__", &format_cache); meth = _PyObject_LookupSpecial(obj, &PyId___format__);
if (meth == NULL) { if (meth == NULL) {
if (!PyErr_Occurred()) if (!PyErr_Occurred())
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
...@@ -2571,7 +2571,7 @@ recursive_isinstance(PyObject *inst, PyObject *cls) ...@@ -2571,7 +2571,7 @@ recursive_isinstance(PyObject *inst, PyObject *cls)
int int
PyObject_IsInstance(PyObject *inst, PyObject *cls) PyObject_IsInstance(PyObject *inst, PyObject *cls)
{ {
static PyObject *name = NULL; _Py_IDENTIFIER(__instancecheck__);
PyObject *checker; PyObject *checker;
/* Quick test for an exact match */ /* Quick test for an exact match */
...@@ -2597,7 +2597,7 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls) ...@@ -2597,7 +2597,7 @@ PyObject_IsInstance(PyObject *inst, PyObject *cls)
return r; return r;
} }
checker = _PyObject_LookupSpecial(cls, "__instancecheck__", &name); checker = _PyObject_LookupSpecial(cls, &PyId___instancecheck__);
if (checker != NULL) { if (checker != NULL) {
PyObject *res; PyObject *res;
int ok = -1; int ok = -1;
...@@ -2640,7 +2640,7 @@ recursive_issubclass(PyObject *derived, PyObject *cls) ...@@ -2640,7 +2640,7 @@ recursive_issubclass(PyObject *derived, PyObject *cls)
int int
PyObject_IsSubclass(PyObject *derived, PyObject *cls) PyObject_IsSubclass(PyObject *derived, PyObject *cls)
{ {
static PyObject *name = NULL; _Py_IDENTIFIER(__subclasscheck__);
PyObject *checker; PyObject *checker;
if (PyTuple_Check(cls)) { if (PyTuple_Check(cls)) {
...@@ -2662,7 +2662,7 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls) ...@@ -2662,7 +2662,7 @@ PyObject_IsSubclass(PyObject *derived, PyObject *cls)
return r; return r;
} }
checker = _PyObject_LookupSpecial(cls, "__subclasscheck__", &name); checker = _PyObject_LookupSpecial(cls, &PyId___subclasscheck__);
if (checker != NULL) { if (checker != NULL) {
PyObject *res; PyObject *res;
int ok = -1; int ok = -1;
......
...@@ -265,9 +265,9 @@ PyComplex_ImagAsDouble(PyObject *op) ...@@ -265,9 +265,9 @@ PyComplex_ImagAsDouble(PyObject *op)
static PyObject * static PyObject *
try_complex_special_method(PyObject *op) { try_complex_special_method(PyObject *op) {
PyObject *f; PyObject *f;
static PyObject *complexstr; _Py_IDENTIFIER(__complex__);
f = _PyObject_LookupSpecial(op, "__complex__", &complexstr); f = _PyObject_LookupSpecial(op, &PyId___complex__);
if (f) { if (f) {
PyObject *res = PyObject_CallFunctionObjArgs(f, NULL); PyObject *res = PyObject_CallFunctionObjArgs(f, NULL);
Py_DECREF(f); Py_DECREF(f);
......
...@@ -1142,10 +1142,8 @@ dict_subscript(PyDictObject *mp, register PyObject *key) ...@@ -1142,10 +1142,8 @@ dict_subscript(PyDictObject *mp, register PyObject *key)
if (!PyDict_CheckExact(mp)) { if (!PyDict_CheckExact(mp)) {
/* Look up __missing__ method if we're a subclass. */ /* Look up __missing__ method if we're a subclass. */
PyObject *missing, *res; PyObject *missing, *res;
static PyObject *missing_str = NULL; _Py_IDENTIFIER(__missing__);
missing = _PyObject_LookupSpecial((PyObject *)mp, missing = _PyObject_LookupSpecial((PyObject *)mp, &PyId___missing__);
"__missing__",
&missing_str);
if (missing != NULL) { if (missing != NULL) {
res = PyObject_CallFunctionObjArgs(missing, res = PyObject_CallFunctionObjArgs(missing,
key, NULL); key, NULL);
......
...@@ -224,8 +224,8 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -224,8 +224,8 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
Py_ssize_t n; Py_ssize_t n;
PyObject *seq, *reversed_meth; PyObject *seq, *reversed_meth;
static PyObject *reversed_cache = NULL;
reversedobject *ro; reversedobject *ro;
_Py_IDENTIFIER(__reversed__);
if (type == &PyReversed_Type && !_PyArg_NoKeywords("reversed()", kwds)) if (type == &PyReversed_Type && !_PyArg_NoKeywords("reversed()", kwds))
return NULL; return NULL;
...@@ -233,7 +233,7 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -233,7 +233,7 @@ reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq) ) if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq) )
return NULL; return NULL;
reversed_meth = _PyObject_LookupSpecial(seq, "__reversed__", &reversed_cache); reversed_meth = _PyObject_LookupSpecial(seq, &PyId___reversed__);
if (reversed_meth != NULL) { if (reversed_meth != NULL) {
PyObject *res = PyObject_CallFunctionObjArgs(reversed_meth, NULL); PyObject *res = PyObject_CallFunctionObjArgs(reversed_meth, NULL);
Py_DECREF(reversed_meth); Py_DECREF(reversed_meth);
......
...@@ -470,7 +470,7 @@ PyObject * ...@@ -470,7 +470,7 @@ PyObject *
PyObject_Bytes(PyObject *v) PyObject_Bytes(PyObject *v)
{ {
PyObject *result, *func; PyObject *result, *func;
static PyObject *bytesstring = NULL; _Py_IDENTIFIER(__bytes__);
if (v == NULL) if (v == NULL)
return PyBytes_FromString("<NULL>"); return PyBytes_FromString("<NULL>");
...@@ -480,7 +480,7 @@ PyObject_Bytes(PyObject *v) ...@@ -480,7 +480,7 @@ PyObject_Bytes(PyObject *v)
return v; return v;
} }
func = _PyObject_LookupSpecial(v, "__bytes__", &bytesstring); func = _PyObject_LookupSpecial(v, &PyId___bytes__);
if (func != NULL) { if (func != NULL) {
result = PyObject_CallFunctionObjArgs(func, NULL); result = PyObject_CallFunctionObjArgs(func, NULL);
Py_DECREF(func); Py_DECREF(func);
...@@ -1298,8 +1298,8 @@ static PyObject * ...@@ -1298,8 +1298,8 @@ static PyObject *
_dir_object(PyObject *obj) _dir_object(PyObject *obj)
{ {
PyObject *result, *sorted; PyObject *result, *sorted;
static PyObject *dir_str = NULL; _Py_IDENTIFIER(__dir__);
PyObject *dirfunc = _PyObject_LookupSpecial(obj, "__dir__", &dir_str); PyObject *dirfunc = _PyObject_LookupSpecial(obj, &PyId___dir__);
assert(obj); assert(obj);
if (dirfunc == NULL) { if (dirfunc == NULL) {
......
This diff is collapsed.
...@@ -138,7 +138,7 @@ static void format_exc_check_arg(PyObject *, const char *, PyObject *); ...@@ -138,7 +138,7 @@ static void format_exc_check_arg(PyObject *, const char *, PyObject *);
static void format_exc_unbound(PyCodeObject *co, int oparg); static void format_exc_unbound(PyCodeObject *co, int oparg);
static PyObject * unicode_concatenate(PyObject *, PyObject *, static PyObject * unicode_concatenate(PyObject *, PyObject *,
PyFrameObject *, unsigned char *); PyFrameObject *, unsigned char *);
static PyObject * special_lookup(PyObject *, char *, PyObject **); static PyObject * special_lookup(PyObject *, _Py_Identifier *);
#define NAME_ERROR_MSG \ #define NAME_ERROR_MSG \
"name '%.200s' is not defined" "name '%.200s' is not defined"
...@@ -2540,13 +2540,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) ...@@ -2540,13 +2540,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
TARGET(SETUP_WITH) TARGET(SETUP_WITH)
{ {
static PyObject *exit, *enter; _Py_IDENTIFIER(__exit__);
_Py_IDENTIFIER(__enter__);
w = TOP(); w = TOP();
x = special_lookup(w, "__exit__", &exit); x = special_lookup(w, &PyId___exit__);
if (!x) if (!x)
break; break;
SET_TOP(x); SET_TOP(x);
u = special_lookup(w, "__enter__", &enter); u = special_lookup(w, &PyId___enter__);
Py_DECREF(w); Py_DECREF(w);
if (!u) { if (!u) {
x = NULL; x = NULL;
...@@ -3440,12 +3441,12 @@ fail: /* Jump here from prelude on failure */ ...@@ -3440,12 +3441,12 @@ fail: /* Jump here from prelude on failure */
static PyObject * static PyObject *
special_lookup(PyObject *o, char *meth, PyObject **cache) special_lookup(PyObject *o, _Py_Identifier *id)
{ {
PyObject *res; PyObject *res;
res = _PyObject_LookupSpecial(o, meth, cache); res = _PyObject_LookupSpecial(o, id);
if (res == NULL && !PyErr_Occurred()) { if (res == NULL && !PyErr_Occurred()) {
PyErr_SetObject(PyExc_AttributeError, *cache); PyErr_SetObject(PyExc_AttributeError, id->object);
return NULL; return NULL;
} }
return res; return res;
......
...@@ -814,10 +814,11 @@ static PyObject * ...@@ -814,10 +814,11 @@ static PyObject *
sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds) sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds)
{ {
PyObject *res = NULL; PyObject *res = NULL;
static PyObject *str__sizeof__ = NULL, *gc_head_size = NULL; static PyObject *gc_head_size = NULL;
static char *kwlist[] = {"object", "default", 0}; static char *kwlist[] = {"object", "default", 0};
PyObject *o, *dflt = NULL; PyObject *o, *dflt = NULL;
PyObject *method; PyObject *method;
_Py_IDENTIFIER(__sizeof__);
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof", if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof",
kwlist, &o, &dflt)) kwlist, &o, &dflt))
...@@ -834,8 +835,7 @@ sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds) ...@@ -834,8 +835,7 @@ sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds)
if (PyType_Ready(Py_TYPE(o)) < 0) if (PyType_Ready(Py_TYPE(o)) < 0)
return NULL; return NULL;
method = _PyObject_LookupSpecial(o, "__sizeof__", method = _PyObject_LookupSpecial(o, &PyId___sizeof__);
&str__sizeof__);
if (method == NULL) { if (method == NULL) {
if (!PyErr_Occurred()) if (!PyErr_Occurred())
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
......
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