@@ -358,6 +358,21 @@ static int function_kind(PyCodeObject *code);
358358static bool function_check_args (PyObject * o , int expected_argcount , int opcode );
359359static uint32_t function_get_version (PyObject * o , int opcode );
360360
361+ #ifdef Py_GIL_DISABLED
362+ static void
363+ maybe_enable_deferred_ref_count (PyObject * op )
364+ {
365+ if (!_Py_IsOwnedByCurrentThread (op )) {
366+ // For module level variables that are heavily used from multiple
367+ // threads, deferred reference counting provides good scaling
368+ // benefits. The downside is that the object will only be deallocated
369+ // by a GC run.
370+ PyUnstable_Object_EnableDeferredRefcount (op );
371+ }
372+ }
373+ #endif
374+
375+
361376static int
362377specialize_module_load_attr_lock_held (PyDictObject * dict , _Py_CODEUNIT * instr , PyObject * name )
363378{
@@ -366,7 +381,8 @@ specialize_module_load_attr_lock_held(PyDictObject *dict, _Py_CODEUNIT *instr, P
366381 SPECIALIZATION_FAIL (LOAD_ATTR , SPEC_FAIL_ATTR_NON_STRING );
367382 return -1 ;
368383 }
369- Py_ssize_t index = _PyDict_LookupIndex (dict , name );
384+ PyObject * value ;
385+ Py_ssize_t index = _PyDict_LookupIndexAndValue (dict , name , & value );
370386 assert (index != DKIX_ERROR );
371387 if (index != (uint16_t )index ) {
372388 SPECIALIZATION_FAIL (LOAD_ATTR ,
@@ -381,6 +397,9 @@ specialize_module_load_attr_lock_held(PyDictObject *dict, _Py_CODEUNIT *instr, P
381397 SPECIALIZATION_FAIL (LOAD_ATTR , SPEC_FAIL_OUT_OF_VERSIONS );
382398 return -1 ;
383399 }
400+ #ifdef Py_GIL_DISABLED
401+ maybe_enable_deferred_ref_count (value );
402+ #endif
384403 write_u32 (cache -> version , keys_version );
385404 cache -> index = (uint16_t )index ;
386405 specialize (instr , LOAD_ATTR_MODULE );
@@ -1269,7 +1288,6 @@ specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
12691288 return 1 ;
12701289}
12711290
1272-
12731291static void
12741292specialize_load_global_lock_held (
12751293 PyObject * globals , PyObject * builtins ,
@@ -1289,7 +1307,12 @@ specialize_load_global_lock_held(
12891307 SPECIALIZATION_FAIL (LOAD_GLOBAL , SPEC_FAIL_LOAD_GLOBAL_NON_STRING_OR_SPLIT );
12901308 goto fail ;
12911309 }
1310+ #ifdef Py_GIL_DISABLED
1311+ PyObject * value ;
1312+ Py_ssize_t index = _PyDict_LookupIndexAndValue ((PyDictObject * )globals , name , & value );
1313+ #else
12921314 Py_ssize_t index = _PyDictKeys_StringLookup (globals_keys , name );
1315+ #endif
12931316 if (index == DKIX_ERROR ) {
12941317 SPECIALIZATION_FAIL (LOAD_GLOBAL , SPEC_FAIL_EXPECTED_ERROR );
12951318 goto fail ;
@@ -1310,6 +1333,9 @@ specialize_load_global_lock_held(
13101333 SPECIALIZATION_FAIL (LOAD_GLOBAL , SPEC_FAIL_OUT_OF_RANGE );
13111334 goto fail ;
13121335 }
1336+ #ifdef Py_GIL_DISABLED
1337+ maybe_enable_deferred_ref_count (value );
1338+ #endif
13131339 cache -> index = (uint16_t )index ;
13141340 cache -> module_keys_version = (uint16_t )keys_version ;
13151341 specialize (instr , LOAD_GLOBAL_MODULE );
0 commit comments