mirror of
https://github.com/python/cpython.git
synced 2026-04-20 02:40:59 +00:00
gh-131798: Split _CHECK_AND_ALLOCATE_OBJECT into smaller uops (GH-148433)
Co-authored-by: Hai Zhu <haiizhu@outlook.com> Co-authored-by: Ken Jin <kenjin4096@gmail.com>
This commit is contained in:
parent
6f7bb297db
commit
18d7d90ef9
10 changed files with 1413 additions and 1289 deletions
|
|
@ -4499,15 +4499,23 @@ dummy_func(
|
|||
POP_TOP +
|
||||
_CHECK_PERIODIC_AT_END;
|
||||
|
||||
op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
|
||||
op(_CHECK_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
|
||||
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
|
||||
EXIT_IF(!PyStackRef_IsNull(self_or_null));
|
||||
EXIT_IF(!PyType_Check(callable_o));
|
||||
PyTypeObject *tp = (PyTypeObject *)callable_o;
|
||||
EXIT_IF(FT_ATOMIC_LOAD_UINT32_RELAXED(tp->tp_version_tag) != type_version);
|
||||
}
|
||||
|
||||
op(_ALLOCATE_OBJECT, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
|
||||
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
|
||||
assert(PyStackRef_IsNull(self_or_null));
|
||||
assert(PyType_Check(callable_o));
|
||||
PyTypeObject *tp = (PyTypeObject *)callable_o;
|
||||
assert(tp->tp_new == PyBaseObject_Type.tp_new);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
|
||||
assert(tp->tp_alloc == PyType_GenericAlloc);
|
||||
|
||||
PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o;
|
||||
PyFunctionObject *init_func = (PyFunctionObject *)FT_ATOMIC_LOAD_PTR_ACQUIRE(cls->_spec_cache.init);
|
||||
PyCodeObject *code = (PyCodeObject *)init_func->func_code;
|
||||
|
|
@ -4552,7 +4560,8 @@ dummy_func(
|
|||
_RECORD_CALLABLE +
|
||||
unused/1 +
|
||||
_CHECK_PEP_523 +
|
||||
_CHECK_AND_ALLOCATE_OBJECT +
|
||||
_CHECK_OBJECT +
|
||||
_ALLOCATE_OBJECT +
|
||||
_CREATE_INIT_FRAME +
|
||||
_PUSH_FRAME;
|
||||
|
||||
|
|
|
|||
19
Python/executor_cases.c.h
generated
19
Python/executor_cases.c.h
generated
|
|
@ -16298,7 +16298,7 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _CHECK_AND_ALLOCATE_OBJECT_r00: {
|
||||
case _CHECK_OBJECT_r00: {
|
||||
CHECK_CURRENT_CACHED_VALUES(0);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef self_or_null;
|
||||
|
|
@ -16324,6 +16324,23 @@
|
|||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _ALLOCATE_OBJECT_r00: {
|
||||
CHECK_CURRENT_CACHED_VALUES(0);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef self_or_null;
|
||||
_PyStackRef callable;
|
||||
oparg = CURRENT_OPARG();
|
||||
self_or_null = stack_pointer[-1 - oparg];
|
||||
callable = stack_pointer[-2 - oparg];
|
||||
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
|
||||
assert(PyStackRef_IsNull(self_or_null));
|
||||
assert(PyType_Check(callable_o));
|
||||
PyTypeObject *tp = (PyTypeObject *)callable_o;
|
||||
assert(tp->tp_new == PyBaseObject_Type.tp_new);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
|
||||
assert(tp->tp_alloc == PyType_GenericAlloc);
|
||||
|
|
|
|||
9
Python/generated_cases.c.h
generated
9
Python/generated_cases.c.h
generated
|
|
@ -1897,7 +1897,7 @@
|
|||
JUMP_TO_PREDICTED(CALL);
|
||||
}
|
||||
}
|
||||
// _CHECK_AND_ALLOCATE_OBJECT
|
||||
// _CHECK_OBJECT
|
||||
{
|
||||
self_or_null = stack_pointer[-1 - oparg];
|
||||
callable = stack_pointer[-2 - oparg];
|
||||
|
|
@ -1919,6 +1919,13 @@
|
|||
assert(_PyOpcode_Deopt[opcode] == (CALL));
|
||||
JUMP_TO_PREDICTED(CALL);
|
||||
}
|
||||
}
|
||||
// _ALLOCATE_OBJECT
|
||||
{
|
||||
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
|
||||
assert(PyStackRef_IsNull(self_or_null));
|
||||
assert(PyType_Check(callable_o));
|
||||
PyTypeObject *tp = (PyTypeObject *)callable_o;
|
||||
assert(tp->tp_new == PyBaseObject_Type.tp_new);
|
||||
assert(tp->tp_flags & Py_TPFLAGS_HEAPTYPE);
|
||||
assert(tp->tp_alloc == PyType_GenericAlloc);
|
||||
|
|
|
|||
|
|
@ -1075,28 +1075,39 @@ dummy_func(void) {
|
|||
ex_frame = PyJitRef_WrapInvalid(frame_new_from_symbol(ctx, func_st, NULL, 0));
|
||||
}
|
||||
|
||||
op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
|
||||
(void)args;
|
||||
op(_CHECK_OBJECT, (type_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
|
||||
PyObject *probable_callable = sym_get_probable_value(callable);
|
||||
assert(probable_callable != NULL);
|
||||
assert(PyType_Check(probable_callable));
|
||||
PyTypeObject *tp = (PyTypeObject *)probable_callable;
|
||||
if (tp->tp_version_tag == type_version) {
|
||||
// If the type version has not changed since we last saw it,
|
||||
// then we know this __init__ is definitely the same one as in the cache.
|
||||
// We can promote callable to a known constant. This does not need a
|
||||
// type watcher, as we do not remove this _CHECK_AND_ALLOCATE_OBJECT guard.
|
||||
// TODO: split up _CHECK_AND_ALLOCATE_OBJECT to the check then alloate, so we can
|
||||
// eliminate the check.
|
||||
PyHeapTypeObject *cls = (PyHeapTypeObject *)probable_callable;
|
||||
PyObject *const_callable = sym_get_const(ctx, callable);
|
||||
bool is_probable = const_callable == NULL && probable_callable != NULL;
|
||||
PyObject *callable_o = const_callable != NULL ? const_callable : probable_callable;
|
||||
if (sym_is_null(self_or_null) &&
|
||||
callable_o != NULL &&
|
||||
PyType_Check(callable_o) &&
|
||||
((PyTypeObject *)callable_o)->tp_version_tag == type_version) {
|
||||
// Probable types need the guard.
|
||||
if (!is_probable) {
|
||||
ADD_OP(_NOP, 0, 0);
|
||||
}
|
||||
else {
|
||||
// Promote the probable type, as we have
|
||||
// guarded on it.
|
||||
sym_set_const(callable, callable_o);
|
||||
}
|
||||
PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o;
|
||||
PyObject *init = cls->_spec_cache.init;
|
||||
assert(init != NULL);
|
||||
assert(PyFunction_Check(init));
|
||||
callable = sym_new_const(ctx, init);
|
||||
PyType_Watch(TYPE_WATCHER_ID, callable_o);
|
||||
_Py_BloomFilter_Add(dependencies, callable_o);;
|
||||
}
|
||||
else {
|
||||
callable = sym_new_not_null(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
op(_ALLOCATE_OBJECT, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
|
||||
self_or_null = sym_new_not_null(ctx);
|
||||
}
|
||||
|
||||
|
|
|
|||
34
Python/optimizer_cases.c.h
generated
34
Python/optimizer_cases.c.h
generated
|
|
@ -3917,31 +3917,47 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _CHECK_AND_ALLOCATE_OBJECT: {
|
||||
JitOptRef *args;
|
||||
case _CHECK_OBJECT: {
|
||||
JitOptRef self_or_null;
|
||||
JitOptRef callable;
|
||||
args = &stack_pointer[-oparg];
|
||||
self_or_null = stack_pointer[-1 - oparg];
|
||||
callable = stack_pointer[-2 - oparg];
|
||||
uint32_t type_version = (uint32_t)this_instr->operand0;
|
||||
(void)args;
|
||||
PyObject *probable_callable = sym_get_probable_value(callable);
|
||||
assert(probable_callable != NULL);
|
||||
assert(PyType_Check(probable_callable));
|
||||
PyTypeObject *tp = (PyTypeObject *)probable_callable;
|
||||
if (tp->tp_version_tag == type_version) {
|
||||
PyHeapTypeObject *cls = (PyHeapTypeObject *)probable_callable;
|
||||
PyObject *const_callable = sym_get_const(ctx, callable);
|
||||
bool is_probable = const_callable == NULL && probable_callable != NULL;
|
||||
PyObject *callable_o = const_callable != NULL ? const_callable : probable_callable;
|
||||
if (sym_is_null(self_or_null) &&
|
||||
callable_o != NULL &&
|
||||
PyType_Check(callable_o) &&
|
||||
((PyTypeObject *)callable_o)->tp_version_tag == type_version) {
|
||||
if (!is_probable) {
|
||||
ADD_OP(_NOP, 0, 0);
|
||||
}
|
||||
else {
|
||||
sym_set_const(callable, callable_o);
|
||||
}
|
||||
PyHeapTypeObject *cls = (PyHeapTypeObject *)callable_o;
|
||||
PyObject *init = cls->_spec_cache.init;
|
||||
assert(init != NULL);
|
||||
assert(PyFunction_Check(init));
|
||||
callable = sym_new_const(ctx, init);
|
||||
stack_pointer[-2 - oparg] = callable;
|
||||
PyType_Watch(TYPE_WATCHER_ID, callable_o);
|
||||
_Py_BloomFilter_Add(dependencies, callable_o);;
|
||||
}
|
||||
else {
|
||||
callable = sym_new_not_null(ctx);
|
||||
}
|
||||
self_or_null = sym_new_not_null(ctx);
|
||||
stack_pointer[-2 - oparg] = callable;
|
||||
break;
|
||||
}
|
||||
|
||||
case _ALLOCATE_OBJECT: {
|
||||
JitOptRef self_or_null;
|
||||
self_or_null = stack_pointer[-1 - oparg];
|
||||
self_or_null = sym_new_not_null(ctx);
|
||||
stack_pointer[-1 - oparg] = self_or_null;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue