mirror of
https://github.com/python/cpython.git
synced 2026-02-06 01:45:25 +00:00
gh-144145: Revert PR#144122 for performance and potential bugs. (GH-144391)
Revert "gh-144145: Track nullness of properties in the Tier 2 JIT optimizer (GH-144122)"
This reverts commit 1dc12b2883.
This commit is contained in:
parent
c3b61ef73d
commit
ebbb2ca81f
11 changed files with 902 additions and 1589 deletions
|
|
@ -2671,23 +2671,6 @@ dummy_func(
|
|||
Py_XDECREF(old_value);
|
||||
}
|
||||
|
||||
op(_STORE_ATTR_INSTANCE_VALUE_NULL, (offset/1, value, owner -- o)) {
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
assert(_PyObject_GetManagedDict(owner_o) == NULL);
|
||||
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
|
||||
PyObject *old_value = *value_ptr;
|
||||
DEOPT_IF(old_value != NULL);
|
||||
FT_ATOMIC_STORE_PTR_RELEASE(*value_ptr, PyStackRef_AsPyObjectSteal(value));
|
||||
PyDictValues *values = _PyObject_InlineValues(owner_o);
|
||||
Py_ssize_t index = value_ptr - values->values;
|
||||
_PyDictValues_AddToInsertionOrder(values, index);
|
||||
UNLOCK_OBJECT(owner_o);
|
||||
INPUTS_DEAD();
|
||||
o = owner;
|
||||
}
|
||||
|
||||
macro(STORE_ATTR_INSTANCE_VALUE) =
|
||||
unused/1 +
|
||||
_GUARD_TYPE_VERSION_AND_LOCK +
|
||||
|
|
@ -2750,20 +2733,6 @@ dummy_func(
|
|||
Py_XDECREF(old_value);
|
||||
}
|
||||
|
||||
op(_STORE_ATTR_SLOT_NULL, (index/1, value, owner -- o)) {
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
|
||||
DEOPT_IF(!LOCK_OBJECT(owner_o));
|
||||
char *addr = (char *)owner_o + index;
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyObject *old_value = *(PyObject **)addr;
|
||||
DEOPT_IF(old_value != NULL);
|
||||
FT_ATOMIC_STORE_PTR_RELEASE(*(PyObject **)addr, PyStackRef_AsPyObjectSteal(value));
|
||||
UNLOCK_OBJECT(owner_o);
|
||||
INPUTS_DEAD();
|
||||
o = owner;
|
||||
}
|
||||
|
||||
macro(STORE_ATTR_SLOT) =
|
||||
unused/1 +
|
||||
_GUARD_TYPE_VERSION +
|
||||
|
|
|
|||
292
Python/executor_cases.c.h
generated
292
Python/executor_cases.c.h
generated
|
|
@ -9782,147 +9782,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_INSTANCE_VALUE_NULL_r01: {
|
||||
CHECK_CURRENT_CACHED_VALUES(0);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef value;
|
||||
_PyStackRef o;
|
||||
owner = stack_pointer[-1];
|
||||
value = stack_pointer[-2];
|
||||
uint16_t offset = (uint16_t)CURRENT_OPERAND0_16();
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
assert(_PyObject_GetManagedDict(owner_o) == NULL);
|
||||
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
|
||||
PyObject *old_value = *value_ptr;
|
||||
if (old_value != NULL) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
FT_ATOMIC_STORE_PTR_RELEASE(*value_ptr, PyStackRef_AsPyObjectSteal(value));
|
||||
PyDictValues *values = _PyObject_InlineValues(owner_o);
|
||||
Py_ssize_t index = value_ptr - values->values;
|
||||
_PyDictValues_AddToInsertionOrder(values, index);
|
||||
UNLOCK_OBJECT(owner_o);
|
||||
o = owner;
|
||||
_tos_cache0 = o;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
stack_pointer += -2;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_INSTANCE_VALUE_NULL_r11: {
|
||||
CHECK_CURRENT_CACHED_VALUES(1);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef value;
|
||||
_PyStackRef o;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
owner = _stack_item_0;
|
||||
value = stack_pointer[-1];
|
||||
uint16_t offset = (uint16_t)CURRENT_OPERAND0_16();
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
assert(_PyObject_GetManagedDict(owner_o) == NULL);
|
||||
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
|
||||
PyObject *old_value = *value_ptr;
|
||||
if (old_value != NULL) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
FT_ATOMIC_STORE_PTR_RELEASE(*value_ptr, PyStackRef_AsPyObjectSteal(value));
|
||||
PyDictValues *values = _PyObject_InlineValues(owner_o);
|
||||
Py_ssize_t index = value_ptr - values->values;
|
||||
_PyDictValues_AddToInsertionOrder(values, index);
|
||||
UNLOCK_OBJECT(owner_o);
|
||||
o = owner;
|
||||
_tos_cache0 = o;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_INSTANCE_VALUE_NULL_r21: {
|
||||
CHECK_CURRENT_CACHED_VALUES(2);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef value;
|
||||
_PyStackRef o;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
_PyStackRef _stack_item_1 = _tos_cache1;
|
||||
owner = _stack_item_1;
|
||||
value = _stack_item_0;
|
||||
uint16_t offset = (uint16_t)CURRENT_OPERAND0_16();
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
assert(_PyObject_GetManagedDict(owner_o) == NULL);
|
||||
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
|
||||
PyObject *old_value = *value_ptr;
|
||||
if (old_value != NULL) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache1 = owner;
|
||||
_tos_cache0 = value;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
FT_ATOMIC_STORE_PTR_RELEASE(*value_ptr, PyStackRef_AsPyObjectSteal(value));
|
||||
PyDictValues *values = _PyObject_InlineValues(owner_o);
|
||||
Py_ssize_t index = value_ptr - values->values;
|
||||
_PyDictValues_AddToInsertionOrder(values, index);
|
||||
UNLOCK_OBJECT(owner_o);
|
||||
o = owner;
|
||||
_tos_cache0 = o;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_INSTANCE_VALUE_NULL_r32: {
|
||||
CHECK_CURRENT_CACHED_VALUES(3);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef value;
|
||||
_PyStackRef o;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
_PyStackRef _stack_item_1 = _tos_cache1;
|
||||
_PyStackRef _stack_item_2 = _tos_cache2;
|
||||
owner = _stack_item_2;
|
||||
value = _stack_item_1;
|
||||
uint16_t offset = (uint16_t)CURRENT_OPERAND0_16();
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
assert(_PyObject_GetManagedDict(owner_o) == NULL);
|
||||
PyObject **value_ptr = (PyObject**)(((char *)owner_o) + offset);
|
||||
PyObject *old_value = *value_ptr;
|
||||
if (old_value != NULL) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache2 = owner;
|
||||
_tos_cache1 = value;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
FT_ATOMIC_STORE_PTR_RELEASE(*value_ptr, PyStackRef_AsPyObjectSteal(value));
|
||||
PyDictValues *values = _PyObject_InlineValues(owner_o);
|
||||
Py_ssize_t index = value_ptr - values->values;
|
||||
_PyDictValues_AddToInsertionOrder(values, index);
|
||||
UNLOCK_OBJECT(owner_o);
|
||||
o = owner;
|
||||
_tos_cache1 = o;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_WITH_HINT_r21: {
|
||||
CHECK_CURRENT_CACHED_VALUES(2);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
|
|
@ -10055,157 +9914,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_SLOT_NULL_r01: {
|
||||
CHECK_CURRENT_CACHED_VALUES(0);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef value;
|
||||
_PyStackRef o;
|
||||
owner = stack_pointer[-1];
|
||||
value = stack_pointer[-2];
|
||||
uint16_t index = (uint16_t)CURRENT_OPERAND0_16();
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
if (!LOCK_OBJECT(owner_o)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
char *addr = (char *)owner_o + index;
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyObject *old_value = *(PyObject **)addr;
|
||||
if (old_value != NULL) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
SET_CURRENT_CACHED_VALUES(0);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
FT_ATOMIC_STORE_PTR_RELEASE(*(PyObject **)addr, PyStackRef_AsPyObjectSteal(value));
|
||||
UNLOCK_OBJECT(owner_o);
|
||||
o = owner;
|
||||
_tos_cache0 = o;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
stack_pointer += -2;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_SLOT_NULL_r11: {
|
||||
CHECK_CURRENT_CACHED_VALUES(1);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef value;
|
||||
_PyStackRef o;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
owner = _stack_item_0;
|
||||
value = stack_pointer[-1];
|
||||
uint16_t index = (uint16_t)CURRENT_OPERAND0_16();
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
if (!LOCK_OBJECT(owner_o)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
char *addr = (char *)owner_o + index;
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyObject *old_value = *(PyObject **)addr;
|
||||
if (old_value != NULL) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache0 = owner;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
FT_ATOMIC_STORE_PTR_RELEASE(*(PyObject **)addr, PyStackRef_AsPyObjectSteal(value));
|
||||
UNLOCK_OBJECT(owner_o);
|
||||
o = owner;
|
||||
_tos_cache0 = o;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_SLOT_NULL_r21: {
|
||||
CHECK_CURRENT_CACHED_VALUES(2);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef value;
|
||||
_PyStackRef o;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
_PyStackRef _stack_item_1 = _tos_cache1;
|
||||
owner = _stack_item_1;
|
||||
value = _stack_item_0;
|
||||
uint16_t index = (uint16_t)CURRENT_OPERAND0_16();
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
if (!LOCK_OBJECT(owner_o)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache1 = owner;
|
||||
_tos_cache0 = value;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
char *addr = (char *)owner_o + index;
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyObject *old_value = *(PyObject **)addr;
|
||||
if (old_value != NULL) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache1 = owner;
|
||||
_tos_cache0 = value;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
FT_ATOMIC_STORE_PTR_RELEASE(*(PyObject **)addr, PyStackRef_AsPyObjectSteal(value));
|
||||
UNLOCK_OBJECT(owner_o);
|
||||
o = owner;
|
||||
_tos_cache0 = o;
|
||||
SET_CURRENT_CACHED_VALUES(1);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_SLOT_NULL_r32: {
|
||||
CHECK_CURRENT_CACHED_VALUES(3);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
_PyStackRef owner;
|
||||
_PyStackRef value;
|
||||
_PyStackRef o;
|
||||
_PyStackRef _stack_item_0 = _tos_cache0;
|
||||
_PyStackRef _stack_item_1 = _tos_cache1;
|
||||
_PyStackRef _stack_item_2 = _tos_cache2;
|
||||
owner = _stack_item_2;
|
||||
value = _stack_item_1;
|
||||
uint16_t index = (uint16_t)CURRENT_OPERAND0_16();
|
||||
PyObject *owner_o = PyStackRef_AsPyObjectBorrow(owner);
|
||||
if (!LOCK_OBJECT(owner_o)) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache2 = owner;
|
||||
_tos_cache1 = value;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
char *addr = (char *)owner_o + index;
|
||||
STAT_INC(STORE_ATTR, hit);
|
||||
PyObject *old_value = *(PyObject **)addr;
|
||||
if (old_value != NULL) {
|
||||
UOP_STAT_INC(uopcode, miss);
|
||||
_tos_cache2 = owner;
|
||||
_tos_cache1 = value;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(3);
|
||||
JUMP_TO_JUMP_TARGET();
|
||||
}
|
||||
FT_ATOMIC_STORE_PTR_RELEASE(*(PyObject **)addr, PyStackRef_AsPyObjectSteal(value));
|
||||
UNLOCK_OBJECT(owner_o);
|
||||
o = owner;
|
||||
_tos_cache1 = o;
|
||||
_tos_cache0 = _stack_item_0;
|
||||
SET_CURRENT_CACHED_VALUES(2);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
break;
|
||||
}
|
||||
|
||||
case _COMPARE_OP_r21: {
|
||||
CHECK_CURRENT_CACHED_VALUES(2);
|
||||
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
|
||||
|
|
|
|||
|
|
@ -269,9 +269,6 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr,
|
|||
#define sym_is_compact_int _Py_uop_sym_is_compact_int
|
||||
#define sym_new_compact_int _Py_uop_sym_new_compact_int
|
||||
#define sym_new_truthiness _Py_uop_sym_new_truthiness
|
||||
#define sym_new_descr_object _Py_uop_sym_new_descr_object
|
||||
#define sym_get_attr _Py_uop_sym_get_attr
|
||||
#define sym_set_attr _Py_uop_sym_set_attr
|
||||
#define sym_new_predicate _Py_uop_sym_new_predicate
|
||||
#define sym_apply_predicate_narrowing _Py_uop_sym_apply_predicate_narrowing
|
||||
|
||||
|
|
@ -506,6 +503,7 @@ optimize_uops(
|
|||
|
||||
int oparg = this_instr->oparg;
|
||||
opcode = this_instr->opcode;
|
||||
|
||||
if (!CURRENT_FRAME_IS_INIT_SHIM()) {
|
||||
stack_pointer = ctx->frame->stack_pointer;
|
||||
}
|
||||
|
|
@ -526,15 +524,9 @@ optimize_uops(
|
|||
if (ctx->out_buffer.next == out_ptr) {
|
||||
*(ctx->out_buffer.next++) = *this_instr;
|
||||
}
|
||||
// Track escapes - but skip when from init shim frame, since self hasn't escaped yet
|
||||
bool is_init_shim = CURRENT_FRAME_IS_INIT_SHIM();
|
||||
if ((_PyUop_Flags[out_ptr->opcode] & HAS_ESCAPES_FLAG) && !is_init_shim)
|
||||
{
|
||||
ctx->last_escape_index = uop_buffer_length(&ctx->out_buffer) - 1;
|
||||
}
|
||||
assert(ctx->frame != NULL);
|
||||
DUMP_UOP(ctx, "out", uop_buffer_length(&ctx->out_buffer) - 1, out_ptr, stack_pointer);
|
||||
if (!is_init_shim && !ctx->done) {
|
||||
if (!CURRENT_FRAME_IS_INIT_SHIM() && !ctx->done) {
|
||||
DPRINTF(3, " stack_level %d\n", STACK_LEVEL());
|
||||
ctx->frame->stack_pointer = stack_pointer;
|
||||
assert(STACK_LEVEL() >= 0);
|
||||
|
|
|
|||
|
|
@ -38,9 +38,6 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
|
|||
#define sym_new_compact_int _Py_uop_sym_new_compact_int
|
||||
#define sym_is_compact_int _Py_uop_sym_is_compact_int
|
||||
#define sym_new_truthiness _Py_uop_sym_new_truthiness
|
||||
#define sym_new_descr_object _Py_uop_sym_new_descr_object
|
||||
#define sym_get_attr _Py_uop_sym_get_attr
|
||||
#define sym_set_attr _Py_uop_sym_set_attr
|
||||
#define sym_new_predicate _Py_uop_sym_new_predicate
|
||||
#define sym_apply_predicate_narrowing _Py_uop_sym_apply_predicate_narrowing
|
||||
|
||||
|
|
@ -106,14 +103,6 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_STORE_ATTR_INSTANCE_VALUE, (offset/1, value, owner -- o)) {
|
||||
JitOptRef old_value = sym_set_attr(ctx, owner, (uint16_t)offset, value);
|
||||
if (sym_is_null(old_value)) {
|
||||
ADD_OP(_STORE_ATTR_INSTANCE_VALUE_NULL, 0, offset);
|
||||
}
|
||||
o = owner;
|
||||
}
|
||||
|
||||
op(_STORE_ATTR_INSTANCE_VALUE_NULL, (offset/1, value, owner -- o)) {
|
||||
(void)value;
|
||||
o = owner;
|
||||
}
|
||||
|
|
@ -136,14 +125,7 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_STORE_ATTR_SLOT, (index/1, value, owner -- o)) {
|
||||
JitOptRef old_value = sym_set_attr(ctx, owner, (uint16_t)index, value);
|
||||
if (sym_is_null(old_value)) {
|
||||
ADD_OP(_STORE_ATTR_SLOT_NULL, 0, index);
|
||||
}
|
||||
o = owner;
|
||||
}
|
||||
|
||||
op(_STORE_ATTR_SLOT_NULL, (index/1, value, owner -- o)) {
|
||||
(void)index;
|
||||
(void)value;
|
||||
o = owner;
|
||||
}
|
||||
|
|
@ -767,7 +749,8 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_LOAD_ATTR_SLOT, (index/1, owner -- attr, o)) {
|
||||
attr = sym_get_attr(ctx, owner, (uint16_t)index);
|
||||
attr = sym_new_not_null(ctx);
|
||||
(void)index;
|
||||
o = owner;
|
||||
}
|
||||
|
||||
|
|
@ -951,14 +934,10 @@ dummy_func(void) {
|
|||
}
|
||||
|
||||
op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
|
||||
(void)type_version;
|
||||
(void)args;
|
||||
callable = sym_new_not_null(ctx);
|
||||
PyTypeObject *tp = _PyType_LookupByVersion(type_version);
|
||||
if (tp != NULL) {
|
||||
self_or_null = sym_new_descr_object(ctx, type_version);
|
||||
} else {
|
||||
self_or_null = sym_new_not_null(ctx);
|
||||
}
|
||||
self_or_null = sym_new_not_null(ctx);
|
||||
}
|
||||
|
||||
op(_CREATE_INIT_FRAME, (init, self, args[oparg] -- init_frame)) {
|
||||
|
|
|
|||
50
Python/optimizer_cases.c.h
generated
50
Python/optimizer_cases.c.h
generated
|
|
@ -1936,7 +1936,8 @@
|
|||
JitOptRef o;
|
||||
owner = stack_pointer[-1];
|
||||
uint16_t index = (uint16_t)this_instr->operand0;
|
||||
attr = sym_get_attr(ctx, owner, (uint16_t)index);
|
||||
attr = sym_new_not_null(ctx);
|
||||
(void)index;
|
||||
o = owner;
|
||||
CHECK_STACK_BOUNDS(1);
|
||||
stack_pointer[-1] = attr;
|
||||
|
|
@ -2005,25 +2006,6 @@
|
|||
}
|
||||
|
||||
case _STORE_ATTR_INSTANCE_VALUE: {
|
||||
JitOptRef owner;
|
||||
JitOptRef value;
|
||||
JitOptRef o;
|
||||
owner = stack_pointer[-1];
|
||||
value = stack_pointer[-2];
|
||||
uint16_t offset = (uint16_t)this_instr->operand0;
|
||||
JitOptRef old_value = sym_set_attr(ctx, owner, (uint16_t)offset, value);
|
||||
if (sym_is_null(old_value)) {
|
||||
ADD_OP(_STORE_ATTR_INSTANCE_VALUE_NULL, 0, offset);
|
||||
}
|
||||
o = owner;
|
||||
CHECK_STACK_BOUNDS(-1);
|
||||
stack_pointer[-2] = o;
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_INSTANCE_VALUE_NULL: {
|
||||
JitOptRef owner;
|
||||
JitOptRef value;
|
||||
JitOptRef o;
|
||||
|
|
@ -2062,25 +2044,7 @@
|
|||
owner = stack_pointer[-1];
|
||||
value = stack_pointer[-2];
|
||||
uint16_t index = (uint16_t)this_instr->operand0;
|
||||
JitOptRef old_value = sym_set_attr(ctx, owner, (uint16_t)index, value);
|
||||
if (sym_is_null(old_value)) {
|
||||
ADD_OP(_STORE_ATTR_SLOT_NULL, 0, index);
|
||||
}
|
||||
o = owner;
|
||||
CHECK_STACK_BOUNDS(-1);
|
||||
stack_pointer[-2] = o;
|
||||
stack_pointer += -1;
|
||||
ASSERT_WITHIN_STACK_BOUNDS(__FILE__, __LINE__);
|
||||
break;
|
||||
}
|
||||
|
||||
case _STORE_ATTR_SLOT_NULL: {
|
||||
JitOptRef owner;
|
||||
JitOptRef value;
|
||||
JitOptRef o;
|
||||
owner = stack_pointer[-1];
|
||||
value = stack_pointer[-2];
|
||||
uint16_t index = (uint16_t)this_instr->operand0;
|
||||
(void)index;
|
||||
(void)value;
|
||||
o = owner;
|
||||
CHECK_STACK_BOUNDS(-1);
|
||||
|
|
@ -3228,15 +3192,11 @@
|
|||
self_or_null = stack_pointer[-1 - oparg];
|
||||
callable = stack_pointer[-2 - oparg];
|
||||
uint32_t type_version = (uint32_t)this_instr->operand0;
|
||||
(void)type_version;
|
||||
(void)args;
|
||||
callable = sym_new_not_null(ctx);
|
||||
self_or_null = sym_new_not_null(ctx);
|
||||
stack_pointer[-2 - oparg] = callable;
|
||||
PyTypeObject *tp = _PyType_LookupByVersion(type_version);
|
||||
if (tp != NULL) {
|
||||
self_or_null = sym_new_descr_object(ctx, type_version);
|
||||
} else {
|
||||
self_or_null = sym_new_not_null(ctx);
|
||||
}
|
||||
stack_pointer[-1 - oparg] = self_or_null;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -116,15 +116,6 @@ _PyUOpSymPrint(JitOptRef ref)
|
|||
case JIT_SYM_PREDICATE_TAG:
|
||||
printf("<predicate at %p>", (void *)sym);
|
||||
break;
|
||||
case JIT_SYM_DESCR_TAG: {
|
||||
PyTypeObject *descr_type = _PyType_LookupByVersion(sym->descr.type_version);
|
||||
if (descr_type) {
|
||||
printf("<%s descr[%d] v%u at %p>", descr_type->tp_name, sym->descr.num_descrs, sym->descr.type_version, (void *)sym);
|
||||
} else {
|
||||
printf("<descr[%d] v%u at %p>", sym->descr.num_descrs, sym->descr.type_version, (void *)sym);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("<tag=%d at %p>", sym->tag, (void *)sym);
|
||||
break;
|
||||
|
|
@ -332,11 +323,6 @@ _Py_uop_sym_set_type(JitOptContext *ctx, JitOptRef ref, PyTypeObject *typ)
|
|||
sym_set_bottom(ctx, sym);
|
||||
}
|
||||
return;
|
||||
case JIT_SYM_DESCR_TAG:
|
||||
if (typ->tp_version_tag != sym->descr.type_version) {
|
||||
sym_set_bottom(ctx, sym);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -401,12 +387,6 @@ _Py_uop_sym_set_type_version(JitOptContext *ctx, JitOptRef ref, unsigned int ver
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
case JIT_SYM_DESCR_TAG:
|
||||
if (version != sym->descr.type_version) {
|
||||
sym_set_bottom(ctx, sym);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
|
|
@ -506,9 +486,6 @@ _Py_uop_sym_set_const(JitOptContext *ctx, JitOptRef ref, PyObject *const_val)
|
|||
sym_set_bottom(ctx, sym);
|
||||
}
|
||||
return;
|
||||
case JIT_SYM_DESCR_TAG:
|
||||
sym_set_bottom(ctx, sym);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -629,8 +606,7 @@ _Py_uop_sym_get_type(JitOptRef ref)
|
|||
return &PyBool_Type;
|
||||
case JIT_SYM_COMPACT_INT:
|
||||
return &PyLong_Type;
|
||||
case JIT_SYM_DESCR_TAG:
|
||||
return _PyType_LookupByVersion(sym->descr.type_version);
|
||||
|
||||
}
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
|
|
@ -659,8 +635,6 @@ _Py_uop_sym_get_type_version(JitOptRef ref)
|
|||
return PyBool_Type.tp_version_tag;
|
||||
case JIT_SYM_COMPACT_INT:
|
||||
return PyLong_Type.tp_version_tag;
|
||||
case JIT_SYM_DESCR_TAG:
|
||||
return sym->descr.type_version;
|
||||
}
|
||||
Py_UNREACHABLE();
|
||||
}
|
||||
|
|
@ -696,7 +670,6 @@ _Py_uop_sym_truthiness(JitOptContext *ctx, JitOptRef ref)
|
|||
case JIT_SYM_UNKNOWN_TAG:
|
||||
case JIT_SYM_COMPACT_INT:
|
||||
case JIT_SYM_PREDICATE_TAG:
|
||||
case JIT_SYM_DESCR_TAG:
|
||||
return -1;
|
||||
case JIT_SYM_KNOWN_CLASS_TAG:
|
||||
/* TODO :
|
||||
|
|
@ -854,7 +827,6 @@ _Py_uop_sym_set_compact_int(JitOptContext *ctx, JitOptRef ref)
|
|||
case JIT_SYM_TUPLE_TAG:
|
||||
case JIT_SYM_PREDICATE_TAG:
|
||||
case JIT_SYM_TRUTHINESS_TAG:
|
||||
case JIT_SYM_DESCR_TAG:
|
||||
sym_set_bottom(ctx, sym);
|
||||
return;
|
||||
case JIT_SYM_BOTTOM_TAG:
|
||||
|
|
@ -969,116 +941,6 @@ _Py_uop_sym_new_compact_int(JitOptContext *ctx)
|
|||
return PyJitRef_Wrap(sym);
|
||||
}
|
||||
|
||||
JitOptRef
|
||||
_Py_uop_sym_new_descr_object(JitOptContext *ctx, unsigned int type_version)
|
||||
{
|
||||
JitOptSymbol *res = sym_new(ctx);
|
||||
if (res == NULL) {
|
||||
return out_of_space_ref(ctx);
|
||||
}
|
||||
res->tag = JIT_SYM_DESCR_TAG;
|
||||
res->descr.num_descrs = 0;
|
||||
res->descr.descrs = NULL;
|
||||
res->descr.type_version = type_version;
|
||||
res->descr.last_modified_index = uop_buffer_length(&ctx->out_buffer);
|
||||
return PyJitRef_Wrap(res);
|
||||
}
|
||||
|
||||
JitOptRef
|
||||
_Py_uop_sym_get_attr(JitOptContext *ctx, JitOptRef ref, uint16_t slot_index)
|
||||
{
|
||||
JitOptSymbol *sym = PyJitRef_Unwrap(ref);
|
||||
|
||||
switch (sym->tag) {
|
||||
case JIT_SYM_DESCR_TAG:
|
||||
// Only return tracked slot values if:
|
||||
// 1. Symbol has mappings allocated
|
||||
// 2. No escape has occurred since last modification (state is fresh)
|
||||
if (sym->descr.descrs != NULL &&
|
||||
sym->descr.last_modified_index >= ctx->last_escape_index)
|
||||
{
|
||||
for (int i = 0; i < sym->descr.num_descrs; i++) {
|
||||
if (sym->descr.descrs[i].slot_index == slot_index) {
|
||||
return PyJitRef_Wrap(allocation_base(ctx) + sym->descr.descrs[i].symbol);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return _Py_uop_sym_new_not_null(ctx);
|
||||
}
|
||||
|
||||
static JitOptDescrMapping *
|
||||
descr_arena_alloc(JitOptContext *ctx)
|
||||
{
|
||||
if (ctx->d_arena.descr_curr_number + MAX_SYMBOLIC_DESCR_SIZE > ctx->d_arena.descr_max_number) {
|
||||
return NULL;
|
||||
}
|
||||
JitOptDescrMapping *descrs = &ctx->d_arena.arena[ctx->d_arena.descr_curr_number];
|
||||
ctx->d_arena.descr_curr_number += MAX_SYMBOLIC_DESCR_SIZE;
|
||||
return descrs;
|
||||
}
|
||||
|
||||
JitOptRef
|
||||
_Py_uop_sym_set_attr(JitOptContext *ctx, JitOptRef ref, uint16_t slot_index, JitOptRef value)
|
||||
{
|
||||
JitOptSymbol *sym = PyJitRef_Unwrap(ref);
|
||||
int curr_index = uop_buffer_length(&ctx->out_buffer);
|
||||
|
||||
switch (sym->tag) {
|
||||
case JIT_SYM_DESCR_TAG:
|
||||
break;
|
||||
default:
|
||||
return _Py_uop_sym_new_not_null(ctx);
|
||||
}
|
||||
|
||||
// Check escape
|
||||
if (sym->descr.last_modified_index < ctx->last_escape_index) {
|
||||
sym->descr.num_descrs = 0;
|
||||
}
|
||||
|
||||
// Get old value before updating
|
||||
JitOptRef old_value = PyJitRef_NULL;
|
||||
if (sym->descr.descrs != NULL) {
|
||||
for (int i = 0; i < sym->descr.num_descrs; i++) {
|
||||
if (sym->descr.descrs[i].slot_index == slot_index) {
|
||||
old_value = PyJitRef_Wrap(allocation_base(ctx) + sym->descr.descrs[i].symbol);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update the last modified timestamp
|
||||
sym->descr.last_modified_index = curr_index;
|
||||
|
||||
// Check if have arena space allocated
|
||||
if (sym->descr.descrs == NULL) {
|
||||
sym->descr.descrs = descr_arena_alloc(ctx);
|
||||
if (sym->descr.descrs == NULL) {
|
||||
return PyJitRef_IsNull(old_value) ? _Py_uop_sym_new_not_null(ctx) : old_value;
|
||||
}
|
||||
}
|
||||
// Check if the slot already exists
|
||||
for (int i = 0; i < sym->descr.num_descrs; i++) {
|
||||
if (sym->descr.descrs[i].slot_index == slot_index) {
|
||||
sym->descr.descrs[i].symbol = (uint16_t)(PyJitRef_Unwrap(value) - allocation_base(ctx));
|
||||
assert(!PyJitRef_IsNull(old_value));
|
||||
return old_value;
|
||||
}
|
||||
}
|
||||
// Add new mapping if there's space
|
||||
if (sym->descr.num_descrs < MAX_SYMBOLIC_DESCR_SIZE) {
|
||||
int idx = sym->descr.num_descrs++;
|
||||
sym->descr.descrs[idx].slot_index = slot_index;
|
||||
sym->descr.descrs[idx].symbol = (uint16_t)(PyJitRef_Unwrap(value) - allocation_base(ctx));
|
||||
}
|
||||
|
||||
return PyJitRef_IsNull(old_value) ? PyJitRef_Borrow(_Py_uop_sym_new_null(ctx)) : old_value;
|
||||
}
|
||||
|
||||
// 0 on success, -1 on error.
|
||||
_Py_UOpsAbstractFrame *
|
||||
_Py_uop_frame_new(
|
||||
|
|
@ -1168,10 +1030,6 @@ _Py_uop_abstractcontext_init(JitOptContext *ctx)
|
|||
ctx->t_arena.ty_curr_number = 0;
|
||||
ctx->t_arena.ty_max_number = TY_ARENA_SIZE;
|
||||
|
||||
// Setup the arena for descriptor mappings.
|
||||
ctx->d_arena.descr_curr_number = 0;
|
||||
ctx->d_arena.descr_max_number = DESCR_ARENA_SIZE;
|
||||
|
||||
// Frame setup
|
||||
ctx->curr_frame_depth = 0;
|
||||
|
||||
|
|
@ -1182,7 +1040,6 @@ _Py_uop_abstractcontext_init(JitOptContext *ctx)
|
|||
ctx->out_of_space = false;
|
||||
ctx->contradiction = false;
|
||||
ctx->builtins_watched = false;
|
||||
ctx->last_escape_index = 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -1664,61 +1521,6 @@ _Py_uop_symbols_test(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
|
|||
TEST_PREDICATE(_Py_uop_sym_matches_type(ref_int, &PyLong_Type), "43 is not an int");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, ref_int) == val_43, "43 isn't 43");
|
||||
|
||||
JitOptRef descr_obj = _Py_uop_sym_new_descr_object(ctx, 42);
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_null(descr_obj), "descr object is NULL");
|
||||
TEST_PREDICATE(_Py_uop_sym_is_not_null(descr_obj), "descr object is not not-null");
|
||||
TEST_PREDICATE(_Py_uop_sym_get_type_version(descr_obj) == 42,
|
||||
"descr object has wrong type version");
|
||||
|
||||
JitOptRef slot_val = _Py_uop_sym_new_const(ctx, val_42);
|
||||
JitOptRef old_val = _Py_uop_sym_set_attr(ctx, descr_obj, 0, slot_val);
|
||||
TEST_PREDICATE(_Py_uop_sym_is_null(old_val), "set_attr on new slot should return NULL");
|
||||
JitOptRef retrieved = _Py_uop_sym_get_attr(ctx, descr_obj, 0);
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, retrieved) == val_42,
|
||||
"descr getattr(0) didn't return val_42");
|
||||
|
||||
JitOptRef missing = _Py_uop_sym_get_attr(ctx, descr_obj, 99);
|
||||
TEST_PREDICATE(_Py_uop_sym_is_not_null(missing), "missing slot is not not-null");
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_const(ctx, missing), "missing slot is const");
|
||||
|
||||
JitOptRef slot_val2 = _Py_uop_sym_new_const(ctx, val_43);
|
||||
old_val = _Py_uop_sym_set_attr(ctx, descr_obj, 0, slot_val2);
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, old_val) == val_42,
|
||||
"set_attr should return old value (val_42)");
|
||||
retrieved = _Py_uop_sym_get_attr(ctx, descr_obj, 0);
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, retrieved) == val_43,
|
||||
"descr getattr(0) didn't return val_43 after update");
|
||||
|
||||
// Test multiple slots
|
||||
JitOptRef slot_val3 = _Py_uop_sym_new_const(ctx, val_42);
|
||||
_Py_uop_sym_set_attr(ctx, descr_obj, 1, slot_val3);
|
||||
retrieved = _Py_uop_sym_get_attr(ctx, descr_obj, 1);
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, retrieved) == val_42,
|
||||
"descr getattr(1) didn't return val_42");
|
||||
retrieved = _Py_uop_sym_get_attr(ctx, descr_obj, 0);
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, retrieved) == val_43,
|
||||
"descr getattr(0) changed unexpectedly");
|
||||
|
||||
// Test escape invalidation
|
||||
JitOptRef descr_obj3 = _Py_uop_sym_new_descr_object(ctx, 100);
|
||||
JitOptRef escape_val = _Py_uop_sym_new_const(ctx, val_42);
|
||||
_Py_uop_sym_set_attr(ctx, descr_obj3, 0, escape_val);
|
||||
retrieved = _Py_uop_sym_get_attr(ctx, descr_obj3, 0);
|
||||
TEST_PREDICATE(_Py_uop_sym_get_const(ctx, retrieved) == val_42,
|
||||
"descr getattr before escape didn't return val_42");
|
||||
// Simulate escape by setting last_escape_index higher
|
||||
ctx->last_escape_index = INT_MAX;
|
||||
retrieved = _Py_uop_sym_get_attr(ctx, descr_obj3, 0);
|
||||
TEST_PREDICATE(!_Py_uop_sym_is_const(ctx, retrieved),
|
||||
"descr getattr after escape should not return const");
|
||||
TEST_PREDICATE(_Py_uop_sym_is_not_null(retrieved),
|
||||
"descr getattr after escape should return not-null");
|
||||
ctx->last_escape_index = 0;
|
||||
|
||||
JitOptRef descr_obj2 = _Py_uop_sym_new_descr_object(ctx, 42);
|
||||
_Py_uop_sym_set_type_version(ctx, descr_obj2, 43);
|
||||
TEST_PREDICATE(_Py_uop_sym_is_bottom(descr_obj2),
|
||||
"descr object with wrong type version isn't bottom");
|
||||
_Py_uop_abstractcontext_fini(ctx);
|
||||
Py_DECREF(val_42);
|
||||
Py_DECREF(val_43);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue