summaryrefslogtreecommitdiffstats
path: root/Python/specialize.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/specialize.c')
-rw-r--r--Python/specialize.c92
1 files changed, 56 insertions, 36 deletions
diff --git a/Python/specialize.c b/Python/specialize.c
index fd182e7..6eb2982 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -738,22 +738,16 @@ unspecialize(_Py_CODEUNIT *instr)
}
static int function_kind(PyCodeObject *code);
+#ifndef Py_GIL_DISABLED
static bool function_check_args(PyObject *o, int expected_argcount, int opcode);
static uint32_t function_get_version(PyObject *o, int opcode);
+#endif
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((Py_TYPE(owner)->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);
return -1;
@@ -773,19 +767,35 @@ specialize_module_load_attr(
SPEC_FAIL_OUT_OF_RANGE);
return -1;
}
- uint32_t keys_version = _PyDictKeys_GetVersionForCurrentState(
- _PyInterpreterState_GET(), dict->ma_keys);
+ uint32_t keys_version = _PyDict_GetKeysVersionForCurrentState(
+ _PyInterpreterState_GET(), dict);
if (keys_version == 0) {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
return -1;
}
write_u32(cache->version, keys_version);
cache->index = (uint16_t)index;
- instr->op.code = LOAD_ATTR_MODULE;
+ specialize(instr, LOAD_ATTR_MODULE);
return 0;
}
-
+static int
+specialize_module_load_attr(
+ PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
+{
+ PyModuleObject *m = (PyModuleObject *)owner;
+ assert((Py_TYPE(owner)->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 result;
+ Py_BEGIN_CRITICAL_SECTION(dict);
+ result = specialize_module_load_attr_lock_held(dict, instr, name);
+ Py_END_CRITICAL_SECTION();
+ return result;
+}
/* Attribute specialization */
@@ -968,7 +978,7 @@ specialize_dict_access(
}
write_u32(cache->version, type->tp_version_tag);
cache->index = (uint16_t)offset;
- instr->op.code = values_op;
+ specialize(instr, values_op);
}
else {
PyDictObject *dict = _PyObject_GetManagedDict(owner);
@@ -992,11 +1002,12 @@ specialize_dict_access(
}
cache->index = (uint16_t)index;
write_u32(cache->version, type->tp_version_tag);
- instr->op.code = hint_op;
+ specialize(instr, hint_op);
}
return 1;
}
+#ifndef Py_GIL_DISABLED
static int specialize_attr_loadclassattr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name,
PyObject* descr, DescriptorClassification kind, bool is_method);
static int specialize_class_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name);
@@ -1093,7 +1104,7 @@ specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* na
write_u32(lm_cache->type_version, type->tp_version_tag);
/* borrowed */
write_obj(lm_cache->descr, fget);
- instr->op.code = LOAD_ATTR_PROPERTY;
+ specialize(instr, LOAD_ATTR_PROPERTY);
return 0;
}
case OBJECT_SLOT:
@@ -1117,7 +1128,7 @@ specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* na
assert(offset > 0);
cache->index = (uint16_t)offset;
write_u32(cache->version, type->tp_version_tag);
- instr->op.code = LOAD_ATTR_SLOT;
+ specialize(instr, LOAD_ATTR_SLOT);
return 0;
}
case DUNDER_CLASS:
@@ -1126,7 +1137,7 @@ specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* na
assert(offset == (uint16_t)offset);
cache->index = (uint16_t)offset;
write_u32(cache->version, type->tp_version_tag);
- instr->op.code = LOAD_ATTR_SLOT;
+ specialize(instr, LOAD_ATTR_SLOT);
return 0;
}
case OTHER_SLOT:
@@ -1162,7 +1173,7 @@ specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* na
/* borrowed */
write_obj(lm_cache->descr, descr);
write_u32(lm_cache->type_version, type->tp_version_tag);
- instr->op.code = LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN;
+ specialize(instr, LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN);
return 0;
}
case BUILTIN_CLASSMETHOD:
@@ -1186,6 +1197,7 @@ specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* na
if (shadow) {
goto try_instance;
}
+ set_counter((_Py_BackoffCounter*)instr + 1, adaptive_counter_cooldown());
return 0;
}
Py_UNREACHABLE();
@@ -1197,14 +1209,14 @@ try_instance:
}
return -1;
}
+#endif // Py_GIL_DISABLED
void
_Py_Specialize_LoadAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *name)
{
- _PyAttrCache *cache = (_PyAttrCache *)(instr + 1);
PyObject *owner = PyStackRef_AsPyObjectBorrow(owner_st);
- assert(ENABLE_SPECIALIZATION);
+ assert(ENABLE_SPECIALIZATION_FT);
assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR);
PyTypeObject *type = Py_TYPE(owner);
bool fail;
@@ -1219,22 +1231,24 @@ _Py_Specialize_LoadAttr(_PyStackRef owner_st, _Py_CODEUNIT *instr, PyObject *nam
fail = specialize_module_load_attr(owner, instr, name);
}
else if (PyType_Check(owner)) {
+ #ifdef Py_GIL_DISABLED
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
+ fail = true;
+ #else
fail = specialize_class_load_attr(owner, instr, name);
+ #endif
}
else {
+ #ifdef Py_GIL_DISABLED
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
+ fail = true;
+ #else
fail = specialize_instance_load_attr(owner, instr, name);
+ #endif
}
if (fail) {
- STAT_INC(LOAD_ATTR, failure);
- assert(!PyErr_Occurred());
- instr->op.code = LOAD_ATTR;
- cache->counter = adaptive_counter_backoff(cache->counter);
- }
- else {
- STAT_INC(LOAD_ATTR, success);
- assert(!PyErr_Occurred());
- cache->counter = adaptive_counter_cooldown();
+ unspecialize(instr);
}
}
@@ -1339,6 +1353,7 @@ success:
cache->counter = adaptive_counter_cooldown();
}
+#ifndef Py_GIL_DISABLED
#ifdef Py_STATS
static int
@@ -1422,10 +1437,10 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr,
write_obj(cache->descr, descr);
if (metaclass_check) {
write_u32(cache->keys_version, Py_TYPE(cls)->tp_version_tag);
- instr->op.code = LOAD_ATTR_CLASS_WITH_METACLASS_CHECK;
+ specialize(instr, LOAD_ATTR_CLASS_WITH_METACLASS_CHECK);
}
else {
- instr->op.code = LOAD_ATTR_CLASS;
+ specialize(instr, LOAD_ATTR_CLASS);
}
return 0;
#ifdef Py_STATS
@@ -1461,7 +1476,7 @@ PyObject *descr, DescriptorClassification kind, bool is_method)
return 0;
}
write_u32(cache->keys_version, keys_version);
- instr->op.code = is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES;
+ specialize(instr, is_method ? LOAD_ATTR_METHOD_WITH_VALUES : LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES);
}
else {
Py_ssize_t dictoffset;
@@ -1476,7 +1491,7 @@ PyObject *descr, DescriptorClassification kind, bool is_method)
}
}
if (dictoffset == 0) {
- instr->op.code = is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT;
+ specialize(instr, is_method ? LOAD_ATTR_METHOD_NO_DICT : LOAD_ATTR_NONDESCRIPTOR_NO_DICT);
}
else if (is_method) {
PyObject *dict = *(PyObject **) ((char *)owner + dictoffset);
@@ -1490,7 +1505,7 @@ PyObject *descr, DescriptorClassification kind, bool is_method)
dictoffset -= MANAGED_DICT_OFFSET;
assert(((uint16_t)dictoffset) == dictoffset);
cache->dict_offset = (uint16_t)dictoffset;
- instr->op.code = LOAD_ATTR_METHOD_LAZY_DICT;
+ specialize(instr, LOAD_ATTR_METHOD_LAZY_DICT);
}
else {
SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_CLASS_ATTR_SIMPLE);
@@ -1516,6 +1531,9 @@ PyObject *descr, DescriptorClassification kind, bool is_method)
return 1;
}
+#endif // Py_GIL_DISABLED
+
+
static void
specialize_load_global_lock_held(
PyObject *globals, PyObject *builtins,
@@ -1661,6 +1679,7 @@ function_kind(PyCodeObject *code) {
return SIMPLE_FUNCTION;
}
+#ifndef Py_GIL_DISABLED
/* Returning false indicates a failure. */
static bool
function_check_args(PyObject *o, int expected_argcount, int opcode)
@@ -1693,6 +1712,7 @@ function_get_version(PyObject *o, int opcode)
}
return version;
}
+#endif // Py_GIL_DISABLED
/* Returning 0 indicates a failure. */
static uint32_t