2
2
3
3
#include "Python.h"
4
4
5
+ #include "pycore_hashtable.h" // _Py_hashtable_new_full()
5
6
#include "pycore_import.h" // _PyImport_BootstrapImp()
6
7
#include "pycore_initconfig.h" // _PyStatus_OK()
7
8
#include "pycore_interp.h" // struct _import_runtime_state
8
9
#include "pycore_namespace.h" // _PyNamespace_Type
10
+ #include "pycore_object.h" // _Py_SetImmortal()
9
11
#include "pycore_pyerrors.h" // _PyErr_SetString()
10
12
#include "pycore_pyhash.h" // _Py_KeyedHash()
11
13
#include "pycore_pylifecycle.h"
@@ -905,172 +907,192 @@ extensions_lock_release(void)
905
907
dictionary, to avoid loading shared libraries twice.
906
908
*/
907
909
910
+ static void *
911
+ hashtable_key_from_2_strings (PyObject * str1 , PyObject * str2 , const char sep )
912
+ {
913
+ Py_ssize_t str1_len , str2_len ;
914
+ const char * str1_data = PyUnicode_AsUTF8AndSize (str1 , & str1_len );
915
+ const char * str2_data = PyUnicode_AsUTF8AndSize (str2 , & str2_len );
916
+ if (str1_data == NULL || str2_data == NULL ) {
917
+ return NULL ;
918
+ }
919
+ /* Make sure sep and the NULL byte won't cause an overflow. */
920
+ assert (SIZE_MAX - str1_len - str2_len > 2 );
921
+ size_t size = str1_len + 1 + str2_len + 1 ;
922
+
923
+ char * key = PyMem_RawMalloc (size );
924
+ if (key == NULL ) {
925
+ PyErr_NoMemory ();
926
+ return NULL ;
927
+ }
928
+
929
+ strncpy (key , str1_data , str1_len );
930
+ key [str1_len ] = sep ;
931
+ strncpy (key + str1_len + 1 , str2_data , str2_len + 1 );
932
+ assert (strlen (key ) == size - 1 );
933
+ return key ;
934
+ }
935
+
936
+ static Py_uhash_t
937
+ hashtable_hash_str (const void * key )
938
+ {
939
+ return _Py_HashBytes (key , strlen ((const char * )key ));
940
+ }
941
+
942
+ static int
943
+ hashtable_compare_str (const void * key1 , const void * key2 )
944
+ {
945
+ return strcmp ((const char * )key1 , (const char * )key2 ) == 0 ;
946
+ }
947
+
908
948
static void
909
- _extensions_cache_init (void )
949
+ hashtable_destroy_str (void * ptr )
910
950
{
911
- /* The runtime (i.e. main interpreter) must be initializing,
912
- so we don't need to worry about the lock. */
913
- _PyThreadState_InitDetached (& EXTENSIONS .main_tstate ,
914
- _PyInterpreterState_Main ());
951
+ PyMem_RawFree (ptr );
915
952
}
916
953
954
+ #define HTSEP ':'
955
+
917
956
static PyModuleDef *
918
957
_extensions_cache_get (PyObject * filename , PyObject * name )
919
958
{
920
959
PyModuleDef * def = NULL ;
960
+ void * key = NULL ;
921
961
extensions_lock_acquire ();
922
962
923
- PyObject * key = PyTuple_Pack (2 , filename , name );
924
- if (key == NULL ) {
963
+ if (EXTENSIONS .hashtable == NULL ) {
925
964
goto finally ;
926
965
}
927
966
928
- PyObject * extensions = EXTENSIONS .dict ;
929
- if (extensions == NULL ) {
967
+ key = hashtable_key_from_2_strings (filename , name , HTSEP );
968
+ if (key == NULL ) {
969
+ goto finally ;
970
+ }
971
+ _Py_hashtable_entry_t * entry = _Py_hashtable_get_entry (
972
+ EXTENSIONS .hashtable , key );
973
+ if (entry == NULL ) {
930
974
goto finally ;
931
975
}
932
- def = (PyModuleDef * )PyDict_GetItemWithError ( extensions , key ) ;
976
+ def = (PyModuleDef * )entry -> value ;
933
977
934
978
finally :
935
- Py_XDECREF (key );
936
979
extensions_lock_release ();
980
+ if (key != NULL ) {
981
+ PyMem_RawFree (key );
982
+ }
937
983
return def ;
938
984
}
939
985
940
986
static int
941
987
_extensions_cache_set (PyObject * filename , PyObject * name , PyModuleDef * def )
942
988
{
943
989
int res = -1 ;
944
- PyThreadState * oldts = NULL ;
945
990
extensions_lock_acquire ();
946
991
947
- /* Swap to the main interpreter, if necessary. This matters if
948
- the dict hasn't been created yet or if the item isn't in the
949
- dict yet. In both cases we must ensure the relevant objects
950
- are created using the main interpreter. */
951
- PyThreadState * main_tstate = & EXTENSIONS .main_tstate ;
952
- PyInterpreterState * interp = _PyInterpreterState_GET ();
953
- if (!_Py_IsMainInterpreter (interp )) {
954
- _PyThreadState_BindDetached (main_tstate );
955
- oldts = _PyThreadState_Swap (interp -> runtime , main_tstate );
956
- assert (!_Py_IsMainInterpreter (oldts -> interp ));
957
-
958
- /* Make sure the name and filename objects are owned
959
- by the main interpreter. */
960
- name = PyUnicode_InternFromString (PyUnicode_AsUTF8 (name ));
961
- assert (name != NULL );
962
- filename = PyUnicode_InternFromString (PyUnicode_AsUTF8 (filename ));
963
- assert (filename != NULL );
992
+ if (EXTENSIONS .hashtable == NULL ) {
993
+ _Py_hashtable_allocator_t alloc = {PyMem_RawMalloc , PyMem_RawFree };
994
+ EXTENSIONS .hashtable = _Py_hashtable_new_full (
995
+ hashtable_hash_str ,
996
+ hashtable_compare_str ,
997
+ hashtable_destroy_str , // key
998
+ /* There's no need to decref the def since it's immortal. */
999
+ NULL , // value
1000
+ & alloc
1001
+ );
1002
+ if (EXTENSIONS .hashtable == NULL ) {
1003
+ PyErr_NoMemory ();
1004
+ goto finally ;
1005
+ }
964
1006
}
965
1007
966
- PyObject * key = PyTuple_Pack ( 2 , filename , name );
1008
+ void * key = hashtable_key_from_2_strings ( filename , name , HTSEP );
967
1009
if (key == NULL ) {
968
1010
goto finally ;
969
1011
}
970
1012
971
- PyObject * extensions = EXTENSIONS .dict ;
972
- if (extensions == NULL ) {
973
- extensions = PyDict_New ();
974
- if (extensions == NULL ) {
1013
+ int already_set = 0 ;
1014
+ _Py_hashtable_entry_t * entry = _Py_hashtable_get_entry (
1015
+ EXTENSIONS .hashtable , key );
1016
+ if (entry == NULL ) {
1017
+ if (_Py_hashtable_set (EXTENSIONS .hashtable , key , def ) < 0 ) {
1018
+ PyMem_RawFree (key );
1019
+ PyErr_NoMemory ();
975
1020
goto finally ;
976
1021
}
977
- EXTENSIONS .dict = extensions ;
978
- }
979
-
980
- PyModuleDef * actual = (PyModuleDef * )PyDict_GetItemWithError (extensions , key );
981
- if (PyErr_Occurred ()) {
982
- goto finally ;
983
1022
}
984
- else if (actual != NULL ) {
985
- /* We expect it to be static, so it must be the same pointer. */
986
- assert (def == actual );
987
- res = 0 ;
988
- goto finally ;
1023
+ else {
1024
+ if (entry -> value == NULL ) {
1025
+ entry -> value = def ;
1026
+ }
1027
+ else {
1028
+ /* We expect it to be static, so it must be the same pointer. */
1029
+ assert ((PyModuleDef * )entry -> value == def );
1030
+ already_set = 1 ;
1031
+ }
1032
+ PyMem_RawFree (key );
989
1033
}
990
-
991
- /* This might trigger a resize, which is why we must switch
992
- to the main interpreter. */
993
- res = PyDict_SetItem (extensions , key , (PyObject * )def );
994
- if (res < 0 ) {
995
- res = -1 ;
996
- goto finally ;
1034
+ if (!already_set ) {
1035
+ /* We assume that all module defs are statically allocated
1036
+ and will never be freed. Otherwise, we would incref here. */
1037
+ _Py_SetImmortal (def );
997
1038
}
998
1039
res = 0 ;
999
1040
1000
1041
finally :
1001
- Py_XDECREF (key );
1002
- if (oldts != NULL ) {
1003
- _PyThreadState_Swap (interp -> runtime , oldts );
1004
- _PyThreadState_UnbindDetached (main_tstate );
1005
- Py_DECREF (name );
1006
- Py_DECREF (filename );
1007
- }
1008
1042
extensions_lock_release ();
1009
1043
return res ;
1010
1044
}
1011
1045
1012
- static int
1046
+ static void
1013
1047
_extensions_cache_delete (PyObject * filename , PyObject * name )
1014
1048
{
1015
- int res = -1 ;
1016
- PyThreadState * oldts = NULL ;
1049
+ void * key = NULL ;
1017
1050
extensions_lock_acquire ();
1018
1051
1019
- PyObject * key = PyTuple_Pack ( 2 , filename , name );
1020
- if ( key == NULL ) {
1052
+ if ( EXTENSIONS . hashtable == NULL ) {
1053
+ /* It was never added. */
1021
1054
goto finally ;
1022
1055
}
1023
1056
1024
- PyObject * extensions = EXTENSIONS .dict ;
1025
- if (extensions == NULL ) {
1026
- res = 0 ;
1057
+ key = hashtable_key_from_2_strings (filename , name , HTSEP );
1058
+ if (key == NULL ) {
1027
1059
goto finally ;
1028
1060
}
1029
1061
1030
- PyModuleDef * actual = (PyModuleDef * )PyDict_GetItemWithError (extensions , key );
1031
- if (PyErr_Occurred ()) {
1062
+ _Py_hashtable_entry_t * entry = _Py_hashtable_get_entry (
1063
+ EXTENSIONS .hashtable , key );
1064
+ if (entry == NULL ) {
1065
+ /* It was never added. */
1032
1066
goto finally ;
1033
1067
}
1034
- else if (actual == NULL ) {
1035
- /* It was already removed or never added. */
1036
- res = 0 ;
1068
+ if (entry -> value == NULL ) {
1069
+ /* It was already removed. */
1037
1070
goto finally ;
1038
1071
}
1039
-
1040
- /* Swap to the main interpreter, if necessary. */
1041
- PyThreadState * main_tstate = & EXTENSIONS .main_tstate ;
1042
- PyInterpreterState * interp = _PyInterpreterState_GET ();
1043
- if (!_Py_IsMainInterpreter (interp )) {
1044
- _PyThreadState_BindDetached (main_tstate );
1045
- oldts = _PyThreadState_Swap (interp -> runtime , main_tstate );
1046
- assert (!_Py_IsMainInterpreter (oldts -> interp ));
1047
- }
1048
-
1049
- if (PyDict_DelItem (extensions , key ) < 0 ) {
1050
- goto finally ;
1051
- }
1052
- res = 0 ;
1072
+ /* If we hadn't made the stored defs immortal, we would decref here.
1073
+ However, this decref would be problematic if the module def were
1074
+ dynamically allocated, it were the last ref, and this function
1075
+ were called with an interpreter other than the def's owner. */
1076
+ entry -> value = NULL ;
1053
1077
1054
1078
finally :
1055
- if (oldts != NULL ) {
1056
- _PyThreadState_Swap (interp -> runtime , oldts );
1057
- _PyThreadState_UnbindDetached (main_tstate );
1058
- }
1059
- Py_XDECREF (key );
1060
1079
extensions_lock_release ();
1061
- return res ;
1080
+ if (key != NULL ) {
1081
+ PyMem_RawFree (key );
1082
+ }
1062
1083
}
1063
1084
1064
1085
static void
1065
1086
_extensions_cache_clear_all (void )
1066
1087
{
1067
1088
/* The runtime (i.e. main interpreter) must be finalizing,
1068
1089
so we don't need to worry about the lock. */
1069
- // XXX assert(_Py_IsMainInterpreter(_PyInterpreterState_GET()));
1070
- Py_CLEAR (EXTENSIONS .dict );
1071
- _PyThreadState_ClearDetached (& EXTENSIONS .main_tstate );
1090
+ _Py_hashtable_destroy (EXTENSIONS .hashtable );
1091
+ EXTENSIONS .hashtable = NULL ;
1072
1092
}
1073
1093
1094
+ #undef HTSEP
1095
+
1074
1096
1075
1097
static bool
1076
1098
check_multi_interp_extensions (PyInterpreterState * interp )
@@ -1231,6 +1253,8 @@ import_find_extension(PyThreadState *tstate, PyObject *name,
1231
1253
PyObject * m_copy = def -> m_base .m_copy ;
1232
1254
/* Module does not support repeated initialization */
1233
1255
if (m_copy == NULL ) {
1256
+ /* It might be a core module (e.g. sys & builtins),
1257
+ for which we don't set m_copy. */
1234
1258
m_copy = get_core_module_dict (tstate -> interp , name , filename );
1235
1259
if (m_copy == NULL ) {
1236
1260
return NULL ;
@@ -1300,9 +1324,7 @@ clear_singlephase_extension(PyInterpreterState *interp,
1300
1324
}
1301
1325
1302
1326
/* Clear the cached module def. */
1303
- if (_extensions_cache_delete (filename , name ) < 0 ) {
1304
- return -1 ;
1305
- }
1327
+ _extensions_cache_delete (filename , name );
1306
1328
1307
1329
return 0 ;
1308
1330
}
@@ -3051,6 +3073,8 @@ void
3051
3073
_PyImport_Fini (void )
3052
3074
{
3053
3075
/* Destroy the database used by _PyImport_{Fixup,Find}Extension */
3076
+ // XXX Should we actually leave them (mostly) intact, since we don't
3077
+ // ever dlclose() the module files?
3054
3078
_extensions_cache_clear_all ();
3055
3079
3056
3080
/* Use the same memory allocator as _PyImport_Init(). */
@@ -3088,10 +3112,6 @@ _PyImport_Fini2(void)
3088
3112
PyStatus
3089
3113
_PyImport_InitCore (PyThreadState * tstate , PyObject * sysmod , int importlib )
3090
3114
{
3091
- if (_Py_IsMainInterpreter (tstate -> interp )) {
3092
- _extensions_cache_init ();
3093
- }
3094
-
3095
3115
// XXX Initialize here: interp->modules and interp->import_func.
3096
3116
// XXX Initialize here: sys.modules and sys.meta_path.
3097
3117
0 commit comments