diff --git a/mypyc/codegen/emitmodule.py b/mypyc/codegen/emitmodule.py index a56083796e79..d724e7a52cdf 100644 --- a/mypyc/codegen/emitmodule.py +++ b/mypyc/codegen/emitmodule.py @@ -1087,6 +1087,7 @@ def emit_module_exec_func( declaration = f"int CPyExec_{exported_name(module_name)}(PyObject *module)" module_static = self.module_internal_static_name(module_name, emitter) emitter.emit_lines(declaration, "{") + emitter.emit_line("intern_strings();") if self.compiler_options.depends_on_librt_internal: emitter.emit_line("if (import_librt_internal() < 0) {") emitter.emit_line("return -1;") diff --git a/mypyc/codegen/emitwrapper.py b/mypyc/codegen/emitwrapper.py index 2e5d7efa4e98..9118f0d5bc25 100644 --- a/mypyc/codegen/emitwrapper.py +++ b/mypyc/codegen/emitwrapper.py @@ -452,9 +452,8 @@ def generate_bin_op_reverse_dunder_call(fn: FuncIR, emitter: Emitter, rmethod: s if fn.name in ("__pow__", "__rpow__"): # Ternary pow() will never call the reverse dunder. emitter.emit_line("if (obj_mod == Py_None) {") - emitter.emit_line(f"_Py_IDENTIFIER({rmethod});") emitter.emit_line( - 'return CPy_CallReverseOpMethod(obj_left, obj_right, "{}", &PyId_{});'.format( + 'return CPy_CallReverseOpMethod(obj_left, obj_right, "{}", mypyc_interned_str.{});'.format( op_methods_to_symbols[fn.name], rmethod ) ) diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index df251da13fe5..fc4906f41916 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -938,7 +938,7 @@ int CPyStatics_Initialize(PyObject **statics, const int *frozensets); PyObject *CPy_Super(PyObject *builtins, PyObject *self); PyObject *CPy_CallReverseOpMethod(PyObject *left, PyObject *right, const char *op, - _Py_Identifier *method); + PyObject *method); bool CPyImport_ImportMany(PyObject *modules, CPyModule **statics[], PyObject *globals, PyObject *tb_path, PyObject *tb_function, Py_ssize_t *tb_lines); diff --git a/mypyc/lib-rt/bytes_extra_ops.c b/mypyc/lib-rt/bytes_extra_ops.c index b5d2d9996d52..511ac0732976 100644 --- a/mypyc/lib-rt/bytes_extra_ops.c +++ b/mypyc/lib-rt/bytes_extra_ops.c @@ -41,10 +41,5 @@ PyObject *CPyBytes_Translate(PyObject *bytes, PyObject *table) { } // Fallback to Python method call for non-exact types or non-standard tables - _Py_IDENTIFIER(translate); - PyObject *name = _PyUnicode_FromId(&PyId_translate); - if (name == NULL) { - return NULL; - } - return PyObject_CallMethodOneArg(bytes, name, table); + return PyObject_CallMethodOneArg(bytes, mypyc_interned_str.translate, table); } diff --git a/mypyc/lib-rt/bytes_ops.c b/mypyc/lib-rt/bytes_ops.c index 25718b4603b3..a9b694116866 100644 --- a/mypyc/lib-rt/bytes_ops.c +++ b/mypyc/lib-rt/bytes_ops.c @@ -101,12 +101,7 @@ PyObject *CPyBytes_Join(PyObject *sep, PyObject *iter) { if (PyBytes_CheckExact(sep)) { return PyBytes_Join(sep, iter); } else { - _Py_IDENTIFIER(join); - PyObject *name = _PyUnicode_FromId(&PyId_join); /* borrowed */ - if (name == NULL) { - return NULL; - } - return PyObject_CallMethodOneArg(sep, name, iter); + return PyObject_CallMethodOneArg(sep, mypyc_interned_str.join, iter); } } @@ -193,12 +188,7 @@ int CPyBytes_Startswith(PyObject *self, PyObject *subobj) { return memcmp(self_buf, subobj_buf, (size_t)subobj_len) == 0 ? 1 : 0; } - _Py_IDENTIFIER(startswith); - PyObject *name = _PyUnicode_FromId(&PyId_startswith); - if (name == NULL) { - return 2; - } - PyObject *result = PyObject_CallMethodOneArg(self, name, subobj); + PyObject *result = PyObject_CallMethodOneArg(self, mypyc_interned_str.startswith, subobj); if (result == NULL) { return 2; } diff --git a/mypyc/lib-rt/dict_ops.c b/mypyc/lib-rt/dict_ops.c index b102aba57307..b4ae5ad01a38 100644 --- a/mypyc/lib-rt/dict_ops.c +++ b/mypyc/lib-rt/dict_ops.c @@ -77,12 +77,7 @@ PyObject *CPyDict_SetDefault(PyObject *dict, PyObject *key, PyObject *value) { Py_XINCREF(ret); return ret; } - _Py_IDENTIFIER(setdefault); - PyObject *name = _PyUnicode_FromId(&PyId_setdefault); /* borrowed */ - if (name == NULL) { - return NULL; - } - return PyObject_CallMethodObjArgs(dict, name, key, value, NULL); + return PyObject_CallMethodObjArgs(dict, mypyc_interned_str.setdefault, key, value, NULL); } PyObject *CPyDict_SetDefaultWithNone(PyObject *dict, PyObject *key) { @@ -136,12 +131,7 @@ static inline int CPy_ObjectToStatus(PyObject *obj) { } static int CPyDict_UpdateGeneral(PyObject *dict, PyObject *stuff) { - _Py_IDENTIFIER(update); - PyObject *name = _PyUnicode_FromId(&PyId_update); /* borrowed */ - if (name == NULL) { - return -1; - } - PyObject *res = PyObject_CallMethodOneArg(dict, name, stuff); + PyObject *res = PyObject_CallMethodOneArg(dict, mypyc_interned_str.update, stuff); return CPy_ObjectToStatus(res); } @@ -169,8 +159,7 @@ int CPyDict_Update(PyObject *dict, PyObject *stuff) { int CPyDict_UpdateFromAny(PyObject *dict, PyObject *stuff) { if (PyDict_CheckExact(dict)) { // Argh this sucks - _Py_IDENTIFIER(keys); - if (PyDict_Check(stuff) || _CPyObject_HasAttrId(stuff, &PyId_keys)) { + if (PyDict_Check(stuff) || _CPyObject_HasAttr(stuff, mypyc_interned_str.keys)) { return PyDict_Update(dict, stuff); } else { return PyDict_MergeFromSeq2(dict, stuff, 1); @@ -189,8 +178,7 @@ PyObject *CPyDict_FromAny(PyObject *obj) { if (!dict) { return NULL; } - _Py_IDENTIFIER(keys); - if (_CPyObject_HasAttrId(obj, &PyId_keys)) { + if (_CPyObject_HasAttr(obj, mypyc_interned_str.keys)) { res = PyDict_Update(dict, obj); } else { res = PyDict_MergeFromSeq2(dict, obj, 1); @@ -207,36 +195,21 @@ PyObject *CPyDict_KeysView(PyObject *dict) { if (PyDict_CheckExact(dict)){ return _CPyDictView_New(dict, &PyDictKeys_Type); } - _Py_IDENTIFIER(keys); - PyObject *name = _PyUnicode_FromId(&PyId_keys); /* borrowed */ - if (name == NULL) { - return NULL; - } - return PyObject_CallMethodNoArgs(dict, name); + return PyObject_CallMethodNoArgs(dict, mypyc_interned_str.keys); } PyObject *CPyDict_ValuesView(PyObject *dict) { if (PyDict_CheckExact(dict)){ return _CPyDictView_New(dict, &PyDictValues_Type); } - _Py_IDENTIFIER(values); - PyObject *name = _PyUnicode_FromId(&PyId_values); /* borrowed */ - if (name == NULL) { - return NULL; - } - return PyObject_CallMethodNoArgs(dict, name); + return PyObject_CallMethodNoArgs(dict, mypyc_interned_str.values); } PyObject *CPyDict_ItemsView(PyObject *dict) { if (PyDict_CheckExact(dict)){ return _CPyDictView_New(dict, &PyDictItems_Type); } - _Py_IDENTIFIER(items); - PyObject *name = _PyUnicode_FromId(&PyId_items); /* borrowed */ - if (name == NULL) { - return NULL; - } - return PyObject_CallMethodNoArgs(dict, name); + return PyObject_CallMethodNoArgs(dict, mypyc_interned_str.items); } PyObject *CPyDict_Keys(PyObject *dict) { @@ -245,12 +218,7 @@ PyObject *CPyDict_Keys(PyObject *dict) { } // Inline generic fallback logic to also return a list. PyObject *list = PyList_New(0); - _Py_IDENTIFIER(keys); - PyObject *name = _PyUnicode_FromId(&PyId_keys); /* borrowed */ - if (name == NULL) { - return NULL; - } - PyObject *view = PyObject_CallMethodNoArgs(dict, name); + PyObject *view = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.keys); if (view == NULL) { return NULL; } @@ -268,12 +236,7 @@ PyObject *CPyDict_Values(PyObject *dict) { } // Inline generic fallback logic to also return a list. PyObject *list = PyList_New(0); - _Py_IDENTIFIER(values); - PyObject *name = _PyUnicode_FromId(&PyId_values); /* borrowed */ - if (name == NULL) { - return NULL; - } - PyObject *view = PyObject_CallMethodNoArgs(dict, name); + PyObject *view = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.values); if (view == NULL) { return NULL; } @@ -291,12 +254,7 @@ PyObject *CPyDict_Items(PyObject *dict) { } // Inline generic fallback logic to also return a list. PyObject *list = PyList_New(0); - _Py_IDENTIFIER(items); - PyObject *name = _PyUnicode_FromId(&PyId_items); /* borrowed */ - if (name == NULL) { - return NULL; - } - PyObject *view = PyObject_CallMethodNoArgs(dict, name); + PyObject *view = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.items); if (view == NULL) { return NULL; } @@ -312,12 +270,7 @@ char CPyDict_Clear(PyObject *dict) { if (PyDict_CheckExact(dict)) { PyDict_Clear(dict); } else { - _Py_IDENTIFIER(clear); - PyObject *name = _PyUnicode_FromId(&PyId_clear); /* borrowed */ - if (name == NULL) { - return 0; - } - PyObject *res = PyObject_CallMethodNoArgs(dict, name); + PyObject *res = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.clear); if (res == NULL) { return 0; } @@ -329,12 +282,7 @@ PyObject *CPyDict_Copy(PyObject *dict) { if (PyDict_CheckExact(dict)) { return PyDict_Copy(dict); } - _Py_IDENTIFIER(copy); - PyObject *name = _PyUnicode_FromId(&PyId_copy); /* borrowed */ - if (name == NULL) { - return NULL; - } - return PyObject_CallMethodNoArgs(dict, name); + return PyObject_CallMethodNoArgs(dict, mypyc_interned_str.copy); } PyObject *CPyDict_GetKeysIter(PyObject *dict) { @@ -352,12 +300,7 @@ PyObject *CPyDict_GetItemsIter(PyObject *dict) { Py_INCREF(dict); return dict; } - _Py_IDENTIFIER(items); - PyObject *name = _PyUnicode_FromId(&PyId_items); /* borrowed */ - if (name == NULL) { - return NULL; - } - PyObject *view = PyObject_CallMethodNoArgs(dict, name); + PyObject *view = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.items); if (view == NULL) { return NULL; } @@ -372,12 +315,7 @@ PyObject *CPyDict_GetValuesIter(PyObject *dict) { Py_INCREF(dict); return dict; } - _Py_IDENTIFIER(values); - PyObject *name = _PyUnicode_FromId(&PyId_values); /* borrowed */ - if (name == NULL) { - return NULL; - } - PyObject *view = PyObject_CallMethodNoArgs(dict, name); + PyObject *view = PyObject_CallMethodNoArgs(dict, mypyc_interned_str.values); if (view == NULL) { return NULL; } diff --git a/mypyc/lib-rt/init.c b/mypyc/lib-rt/init.c index 9215c2d59019..4ec2adc79077 100644 --- a/mypyc/lib-rt/init.c +++ b/mypyc/lib-rt/init.c @@ -1,5 +1,6 @@ #include #include "CPy.h" +#include "static_data.c" struct ExcDummyStruct _CPy_ExcDummyStruct = { PyObject_HEAD_INIT(NULL) }; PyObject *_CPy_ExcDummy = (PyObject *)&_CPy_ExcDummyStruct; diff --git a/mypyc/lib-rt/list_ops.c b/mypyc/lib-rt/list_ops.c index c611907fb601..ebfdafdb2ef4 100644 --- a/mypyc/lib-rt/list_ops.c +++ b/mypyc/lib-rt/list_ops.c @@ -33,12 +33,7 @@ char CPyList_Clear(PyObject *list) { if (PyList_CheckExact(list)) { PyList_Clear(list); } else { - _Py_IDENTIFIER(clear); - PyObject *name = _PyUnicode_FromId(&PyId_clear); - if (name == NULL) { - return 0; - } - PyObject *res = PyObject_CallMethodNoArgs(list, name); + PyObject *res = PyObject_CallMethodNoArgs(list, mypyc_interned_str.clear); if (res == NULL) { return 0; } @@ -50,13 +45,7 @@ PyObject *CPyList_Copy(PyObject *list) { if(PyList_CheckExact(list)) { return PyList_GetSlice(list, 0, PyList_GET_SIZE(list)); } - _Py_IDENTIFIER(copy); - - PyObject *name = _PyUnicode_FromId(&PyId_copy); - if (name == NULL) { - return NULL; - } - return PyObject_CallMethodNoArgs(list, name); + return PyObject_CallMethodNoArgs(list, mypyc_interned_str.copy); } PyObject *CPyList_GetItemShort(PyObject *list, CPyTagged index) { diff --git a/mypyc/lib-rt/misc_ops.c b/mypyc/lib-rt/misc_ops.c index 8e5bfffba759..38472b33291f 100644 --- a/mypyc/lib-rt/misc_ops.c +++ b/mypyc/lib-rt/misc_ops.c @@ -29,12 +29,7 @@ PyObject *CPyIter_Send(PyObject *iter, PyObject *val) if (Py_IsNone(val)) { return CPyIter_Next(iter); } else { - _Py_IDENTIFIER(send); - PyObject *name = _PyUnicode_FromId(&PyId_send); /* borrowed */ - if (name == NULL) { - return NULL; - } - return PyObject_CallMethodOneArg(iter, name, val); + return PyObject_CallMethodOneArg(iter, mypyc_interned_str.send, val); } } @@ -50,8 +45,6 @@ PyObject *CPyIter_Send(PyObject *iter, PyObject *val) // Signals an error (2) if the an exception should be propagated. int CPy_YieldFromErrorHandle(PyObject *iter, PyObject **outp) { - _Py_IDENTIFIER(close); - _Py_IDENTIFIER(throw); PyObject *exc_type = (PyObject *)Py_TYPE(CPy_ExcState()->exc_value); PyObject *type, *value, *traceback; PyObject *_m; @@ -59,7 +52,7 @@ int CPy_YieldFromErrorHandle(PyObject *iter, PyObject **outp) *outp = NULL; if (PyErr_GivenExceptionMatches(exc_type, PyExc_GeneratorExit)) { - _m = _PyObject_GetAttrId(iter, &PyId_close); + _m = PyObject_GetAttr(iter, mypyc_interned_str.close_); if (_m) { res = PyObject_CallNoArgs(_m); Py_DECREF(_m); @@ -72,7 +65,7 @@ int CPy_YieldFromErrorHandle(PyObject *iter, PyObject **outp) return 2; } } else { - _m = _PyObject_GetAttrId(iter, &PyId_throw); + _m = PyObject_GetAttr(iter, mypyc_interned_str.throw_); if (_m) { _CPy_GetExcInfo(&type, &value, &traceback); res = PyObject_CallFunctionObjArgs(_m, type, value, traceback, NULL); @@ -877,9 +870,9 @@ PyObject * CPy_CallReverseOpMethod(PyObject *left, PyObject *right, const char *op, - _Py_Identifier *method) { + PyObject *method) { // Look up reverse method - PyObject *m = _PyObject_GetAttrId(right, method); + PyObject *m = PyObject_GetAttr(right, method); if (m == NULL) { // If reverse method not defined, generate TypeError instead AttributeError if (PyErr_ExceptionMatches(PyExc_AttributeError)) { @@ -1065,9 +1058,7 @@ PyObject *CPy_GetName(PyObject *obj) { if (PyType_Check(obj)) { return PyType_GetName((PyTypeObject *)obj); } - _Py_IDENTIFIER(__name__); - PyObject *name = _PyUnicode_FromId(&PyId___name__); /* borrowed */ - return PyObject_GetAttr(obj, name); + return PyObject_GetAttr(obj, mypyc_interned_str.__name__); } #endif diff --git a/mypyc/lib-rt/pythonsupport.h b/mypyc/lib-rt/pythonsupport.h index 7019c12cf59a..366d014cca73 100644 --- a/mypyc/lib-rt/pythonsupport.h +++ b/mypyc/lib-rt/pythonsupport.h @@ -11,6 +11,7 @@ #include "pythoncapi_compat.h" #include #include +#include "static_data.h" #include "mypyc_util.h" #if CPY_3_13_FEATURES @@ -35,7 +36,6 @@ extern "C" { ///////////////////////////////////////// // Adapted from bltinmodule.c in Python 3.7.0 -_Py_IDENTIFIER(__mro_entries__); static PyObject* update_bases(PyObject *bases) { @@ -57,7 +57,7 @@ update_bases(PyObject *bases) } continue; } - if (PyObject_GetOptionalAttrString(base, PyId___mro_entries__.string, &meth) < 0) { + if (PyObject_GetOptionalAttrString(base, "__mro_entries__", &meth) < 0) { goto error; } if (!meth) { @@ -110,7 +110,6 @@ update_bases(PyObject *bases) } // From Python 3.7's typeobject.c -_Py_IDENTIFIER(__init_subclass__); static int init_subclass(PyTypeObject *type, PyObject *kwds) { @@ -122,7 +121,7 @@ init_subclass(PyTypeObject *type, PyObject *kwds) return -1; } - func = _PyObject_GetAttrId(super, &PyId___init_subclass__); + func = PyObject_GetAttrString(super, "__init_subclass__"); Py_DECREF(super); if (func == NULL) { return -1; @@ -377,19 +376,15 @@ _CPyDictView_New(PyObject *dict, PyTypeObject *type) } #endif -#if PY_VERSION_HEX >= 0x030A0000 // 3.10 static int -_CPyObject_HasAttrId(PyObject *v, _Py_Identifier *name) { +_CPyObject_HasAttr(PyObject *v, PyObject *name) { PyObject *tmp = NULL; - int result = PyObject_GetOptionalAttrString(v, name->string, &tmp); + int result = PyObject_GetOptionalAttr(v, name, &tmp); if (tmp) { Py_DECREF(tmp); } return result; } -#else -#define _CPyObject_HasAttrId _PyObject_HasAttrId -#endif #if CPY_3_12_FEATURES diff --git a/mypyc/lib-rt/static_data.c b/mypyc/lib-rt/static_data.c new file mode 100644 index 000000000000..1fc93330bdc1 --- /dev/null +++ b/mypyc/lib-rt/static_data.c @@ -0,0 +1,58 @@ +#ifndef STATIC_DATA +#define STATIC_DATA + +#include "static_data.h" + +// Adopted from numpy 2.4.0: numpy/_core/src/multiarry/npy_static_data.c + +mypyc_interned_str_struct mypyc_interned_str; + +#define INTERN_STRING(struct_member, string) \ + assert(mypyc_interned_str.struct_member == NULL); \ + mypyc_interned_str.struct_member = PyUnicode_InternFromString(string); \ + if (mypyc_interned_str.struct_member == NULL) { \ + return -1; \ + } + +int +intern_strings(void) { + INTERN_STRING(__init_subclass__, "__init_subclass__"); + INTERN_STRING(__mro_entries__, "__mro_entries__"); + INTERN_STRING(__name__, "__name__"); + INTERN_STRING(__radd__, "__radd__"); + INTERN_STRING(__rsub__, "__rsub__"); + INTERN_STRING(__rmul__, "__rmul__"); + INTERN_STRING(__rtruediv__, "__rtruediv__"); + INTERN_STRING(__rmod__, "__rmod__"); + INTERN_STRING(__rdivmod__, "__rdivmod__"); + INTERN_STRING(__rfloordiv__, "__rfloordiv__"); + INTERN_STRING(__rpow__, "__rpow__"); + INTERN_STRING(__rmatmul__, "__rmatmul__"); + INTERN_STRING(__rand__, "__rand__"); + INTERN_STRING(__ror__, "__ror__"); + INTERN_STRING(__rxor__, "__rxor__"); + INTERN_STRING(__rlshift__, "__rlshift__"); + INTERN_STRING(__rrshift__, "__rrshift__"); + INTERN_STRING(__eq__, "__eq__"); + INTERN_STRING(__ne__, "__ne__"); + INTERN_STRING(__gt__, "__gt__"); + INTERN_STRING(__le__, "__le__"); + INTERN_STRING(__lt__, "__lt__"); + INTERN_STRING(__ge__, "__ge__"); + INTERN_STRING(clear, "clear"); + INTERN_STRING(close_, "close"); + INTERN_STRING(copy, "copy"); + INTERN_STRING(keys, "keys"); + INTERN_STRING(items, "items"); + INTERN_STRING(join, "join"); + INTERN_STRING(send, "send"); + INTERN_STRING(setdefault, "setdefault"); + INTERN_STRING(startswith, "startswith"); + INTERN_STRING(throw_, "throw"); + INTERN_STRING(translate, "translate"); + INTERN_STRING(update, "update"); + INTERN_STRING(values, "values"); + return 0; +} + +#endif diff --git a/mypyc/lib-rt/static_data.h b/mypyc/lib-rt/static_data.h new file mode 100644 index 000000000000..f779504b6c20 --- /dev/null +++ b/mypyc/lib-rt/static_data.h @@ -0,0 +1,59 @@ +#ifndef STATIC_DATA_H +#define STATIC_DATA_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Adopted from numpy 2.4.0: numpy/_core/src/multiarry/npy_static_data.h + +int intern_strings(void); + +typedef struct mypyc_interned_str_struct { + PyObject *__init_subclass__; + PyObject *__mro_entries__; + PyObject *__name__; + PyObject *__radd__; + PyObject *__rsub__; + PyObject *__rmul__; + PyObject *__rtruediv__; + PyObject *__rmod__; + PyObject *__rdivmod__; + PyObject *__rfloordiv__; + PyObject *__rpow__; + PyObject *__rmatmul__; + PyObject *__rand__; + PyObject *__ror__; + PyObject *__rxor__; + PyObject *__rlshift__; + PyObject *__rrshift__; + PyObject *__eq__; + PyObject *__ne__; + PyObject *__gt__; + PyObject *__le__; + PyObject *__lt__; + PyObject *__ge__; + PyObject *clear; + PyObject *close_; + PyObject *copy; + PyObject *keys; + PyObject *items; + PyObject *join; + PyObject *send; + PyObject *setdefault; + PyObject *startswith; + PyObject *throw_; + PyObject *translate; + PyObject *update; + PyObject *values; +} mypyc_interned_str_struct; + +extern mypyc_interned_str_struct mypyc_interned_str; + +#ifdef __cplusplus +} +#endif + +#endif