Skip to content

Commit

Permalink
Lock dict when specializing module lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
DinoV committed Jan 31, 2024
1 parent dc4cd2c commit a857147
Showing 1 changed file with 40 additions and 12 deletions.
52 changes: 40 additions & 12 deletions Python/specialize.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "opcode.h"

#include "pycore_code.h"
#include "pycore_critical_section.h" // Py_BEGIN_CRITICAL_SECTION, Py_END_CRITICAL_SECTION
#include "pycore_descrobject.h" // _PyMethodWrapper_Type
#include "pycore_dict.h" // DICT_KEYS_UNICODE
#include "pycore_function.h" // _PyFunction_GetVersionForCurrentState()
Expand Down Expand Up @@ -600,17 +601,11 @@ static uint32_t function_get_version(PyObject *o, int opcode);
static uint32_t type_get_version(PyTypeObject *t, int opcode);

static int
specialize_module_load_attr(
PyObject *owner, _Py_CODEUNIT *instr, PyObject *name
) {
specialize_module_load_attr_lock_held(
PyDictObject *dict, _Py_CODEUNIT *instr, PyObject *name
)
{
_PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
PyModuleObject *m = (PyModuleObject *)owner;
assert((owner->ob_type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);
PyDictObject *dict = (PyDictObject *)m->md_dict;
if (dict == NULL) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_NO_DICT);
return -1;
}
if (dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_NON_STRING_OR_SPLIT);
return -1;
Expand Down Expand Up @@ -642,6 +637,23 @@ specialize_module_load_attr(
return 0;
}

static int
specialize_module_load_attr(
PyObject *owner, _Py_CODEUNIT *instr, PyObject *name
) {
PyModuleObject *m = (PyModuleObject *)owner;
assert((owner->ob_type->tp_flags & Py_TPFLAGS_MANAGED_DICT) == 0);
PyDictObject *dict = (PyDictObject *)m->md_dict;
if (dict == NULL) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_NO_DICT);
return -1;
}
int res;
Py_BEGIN_CRITICAL_SECTION(dict);
res = specialize_module_load_attr_lock_held(dict, instr, name);
Py_END_CRITICAL_SECTION();
return res;
}


/* Attribute specialization */
Expand Down Expand Up @@ -836,18 +848,34 @@ specialize_dict_access(
SPECIALIZATION_FAIL(base_op, SPEC_FAIL_ATTR_NON_STRING_OR_SPLIT);
return 0;
}

#ifdef Py_GIL_DISABLED
unsigned int version = _Py_atomic_load_uint(&type->tp_version_tag);
#else
unsigned int version = dict->ma_version_tag;

Check warning on line 855 in Python/specialize.c

View workflow job for this annotation

GitHub Actions / Windows / build and test (x64)

'initializing': conversion from 'uint64_t' to 'unsigned int', possible loss of data [D:\a\cpython\cpython\PCbuild\_freeze_module.vcxproj]

Check warning on line 855 in Python/specialize.c

View workflow job for this annotation

GitHub Actions / Windows / build and test (x64)

'initializing': conversion from 'uint64_t' to 'unsigned int', possible loss of data [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]

Check warning on line 855 in Python/specialize.c

View workflow job for this annotation

GitHub Actions / Windows / build (arm64)

'initializing': conversion from 'uint64_t' to 'unsigned int', possible loss of data [D:\a\cpython\cpython\PCbuild\_freeze_module.vcxproj]

Check warning on line 855 in Python/specialize.c

View workflow job for this annotation

GitHub Actions / Windows / build (arm64)

'initializing': conversion from 'uint64_t' to 'unsigned int', possible loss of data [D:\a\cpython\cpython\PCbuild\pythoncore.vcxproj]
#endif

int res;
Py_BEGIN_CRITICAL_SECTION(dict);

Py_ssize_t index =
_PyDict_LookupIndex(dict, name);
if (index != (uint16_t)index) {
SPECIALIZATION_FAIL(base_op,
index == DKIX_EMPTY ?
SPEC_FAIL_ATTR_NOT_IN_DICT :
SPEC_FAIL_OUT_OF_RANGE);
return 0;
res = 0;
goto exit;
}
cache->index = (uint16_t)index;
write_u32(cache->version, type->tp_version_tag);
write_u32(cache->version, version);
instr->op.code = hint_op;

res = 1;
exit:
Py_END_CRITICAL_SECTION();
return res;
}
return 1;
}
Expand Down

0 comments on commit a857147

Please sign in to comment.