summaryrefslogtreecommitdiffstats
path: root/Python/specialize.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/specialize.c')
-rw-r--r--Python/specialize.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/Python/specialize.c b/Python/specialize.c
index 24fbe2f..70ccf68 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -8,6 +8,7 @@
#include "pycore_object.h"
#include "pycore_opcode.h" // _PyOpcode_Caches
#include "structmember.h" // struct PyMemberDef, T_OFFSET_EX
+#include "pycore_descrobject.h"
#include <stdlib.h> // rand()
@@ -331,6 +332,8 @@ miss_counter_start(void) {
return 53;
}
+#define SIMPLE_FUNCTION 0
+
/* Common */
#define SPEC_FAIL_OTHER 0
@@ -580,7 +583,9 @@ analyze_descriptor(PyTypeObject *type, PyObject *name, PyObject **descr, int sto
return DUNDER_CLASS;
}
}
- return OVERRIDING;
+ if (store) {
+ return OVERRIDING;
+ }
}
if (desc_cls->tp_descr_get) {
if (desc_cls->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR) {
@@ -650,6 +655,7 @@ specialize_dict_access(
static int specialize_attr_loadmethod(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name,
PyObject* descr, DescriptorClassification kind);
static int specialize_class_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name);
+static int function_kind(PyCodeObject *code);
int
_Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
@@ -696,8 +702,42 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name)
goto fail;
}
case PROPERTY:
- SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY);
- goto fail;
+ {
+ _PyLoadMethodCache *lm_cache = (_PyLoadMethodCache *)(instr + 1);
+ assert(Py_TYPE(descr) == &PyProperty_Type);
+ PyObject *fget = ((_PyPropertyObject *)descr)->prop_get;
+ if (fget == NULL) {
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_EXPECTED_ERROR);
+ goto fail;
+ }
+ if (Py_TYPE(fget) != &PyFunction_Type) {
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_ATTR_PROPERTY);
+ goto fail;
+ }
+ PyFunctionObject *func = (PyFunctionObject *)fget;
+ PyCodeObject *fcode = (PyCodeObject *)func->func_code;
+ int kind = function_kind(fcode);
+ if (kind != SIMPLE_FUNCTION) {
+ SPECIALIZATION_FAIL(LOAD_ATTR, kind);
+ goto fail;
+ }
+ if (fcode->co_argcount != 1) {
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_WRONG_NUMBER_ARGUMENTS);
+ goto fail;
+ }
+ int version = _PyFunction_GetVersionForCurrentState(func);
+ if (version == 0) {
+ SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OUT_OF_VERSIONS);
+ goto fail;
+ }
+ write_u32(lm_cache->keys_version, version);
+ assert(type->tp_version_tag != 0);
+ write_u32(lm_cache->type_version, type->tp_version_tag);
+ /* borrowed */
+ write_obj(lm_cache->descr, fget);
+ _Py_SET_OPCODE(*instr, LOAD_ATTR_PROPERTY);
+ goto success;
+ }
case OBJECT_SLOT:
{
PyMemberDescrObject *member = (PyMemberDescrObject *)descr;
@@ -1145,9 +1185,6 @@ binary_subscr_fail_kind(PyTypeObject *container_type, PyObject *sub)
}
#endif
-
-#define SIMPLE_FUNCTION 0
-
static int
function_kind(PyCodeObject *code) {
int flags = code->co_flags;