Skip to content

Commit 9dd70a0

Browse files
remove func version symbol altogether --- to buggy without watchers
1 parent ff29164 commit 9dd70a0

File tree

8 files changed

+18
-217
lines changed

8 files changed

+18
-217
lines changed

Include/internal/pycore_optimizer.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -424,8 +424,6 @@ extern PyCodeObject *_Py_uop_sym_get_probable_func_code(JitOptRef sym);
424424
extern PyObject *_Py_uop_sym_get_probable_value(JitOptRef sym);
425425
extern PyTypeObject *_Py_uop_sym_get_probable_type(JitOptRef sym);
426426
extern JitOptRef *_Py_uop_sym_set_stack_depth(JitOptContext *ctx, int stack_depth, JitOptRef *current_sp);
427-
extern uint32_t _Py_uop_sym_get_func_version(JitOptRef ref);
428-
bool _Py_uop_sym_set_func_version(JitOptContext *ctx, JitOptRef ref, uint32_t version);
429427

430428
extern void _Py_uop_abstractcontext_init(JitOptContext *ctx, _PyBloomFilter *dependencies);
431429
extern void _Py_uop_abstractcontext_fini(JitOptContext *ctx);

Include/internal/pycore_optimizer_types.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ typedef enum _JitSymType {
3636
JIT_SYM_NON_NULL_TAG = 3,
3737
JIT_SYM_BOTTOM_TAG = 4,
3838
JIT_SYM_TYPE_VERSION_TAG = 5,
39-
JIT_SYM_FUNC_VERSION_TAG = 6,
4039
JIT_SYM_KNOWN_CLASS_TAG = 7,
4140
JIT_SYM_KNOWN_VALUE_TAG = 8,
4241
JIT_SYM_TUPLE_TAG = 9,

Lib/test/test_capi/test_opt.py

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,9 +1622,8 @@ def testfunc(n):
16221622
self.assertEqual(uops.count("_PUSH_FRAME"), 2)
16231623
# Type version propagation: one guard covers both method lookups
16241624
self.assertEqual(uops.count("_GUARD_TYPE_VERSION"), 1)
1625-
# Function checks eliminated (type info resolves the callable)
1626-
self.assertNotIn("_CHECK_FUNCTION_VERSION", uops)
1627-
self.assertNotIn("_CHECK_FUNCTION_EXACT_ARGS", uops)
1625+
# Function checks cannot be eliminated for safety reasons.
1626+
self.assertIn("_CHECK_FUNCTION_VERSION", uops)
16281627

16291628
def test_method_chain_guard_elimination(self):
16301629
"""
@@ -1669,10 +1668,7 @@ def testfunc(n):
16691668
self.assertIsNotNone(ex)
16701669
uops = get_opnames(ex)
16711670
self.assertIn("_PUSH_FRAME", uops)
1672-
# Both should be not present, as this is a call
1673-
# to a simple function with a known function version.
1674-
self.assertNotIn("_CHECK_FUNCTION_VERSION_INLINE", uops)
1675-
self.assertNotIn("_CHECK_FUNCTION_VERSION", uops)
1671+
self.assertIn("_CHECK_FUNCTION_VERSION", uops)
16761672
# Removed guard
16771673
self.assertNotIn("_CHECK_FUNCTION_EXACT_ARGS", uops)
16781674

@@ -5178,28 +5174,6 @@ def g():
51785174
PYTHON_JIT="1", PYTHON_JIT_STRESS="1")
51795175
self.assertEqual(result[0].rc, 0, result)
51805176

5181-
def test_func_version_watched_and_invalidated(self):
5182-
def testfunc(n):
5183-
for i in range(n):
5184-
# Only works on functions promoted to constants
5185-
global_identity_code_will_be_modified(i)
5186-
5187-
testfunc(TIER2_THRESHOLD)
5188-
5189-
ex = get_first_executor(testfunc)
5190-
self.assertIsNotNone(ex)
5191-
uops = get_opnames(ex)
5192-
self.assertIn("_PUSH_FRAME", uops)
5193-
# Both should be not present, as this is a call
5194-
# to a simple function with a known function version.
5195-
self.assertNotIn("_CHECK_FUNCTION_VERSION_INLINE", uops)
5196-
self.assertNotIn("_CHECK_FUNCTION_VERSION", uops)
5197-
5198-
global_identity_code_will_be_modified.__code__ = (lambda a:a).__code__
5199-
ex = get_first_executor(testfunc)
5200-
# Invalidated and removed.
5201-
self.assertIsNone(ex)
5202-
52035177
def test_call_super(self):
52045178
class A:
52055179
def method1(self):

Objects/funcobject.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,6 @@ handle_func_event(PyFunction_WatchEvent event, PyFunctionObject *func,
6464
case PyFunction_EVENT_MODIFY_DEFAULTS:
6565
case PyFunction_EVENT_MODIFY_KWDEFAULTS:
6666
case PyFunction_EVENT_MODIFY_QUALNAME:
67-
#if _Py_TIER2
68-
_Py_Executors_InvalidateDependency(interp, func, 1);
69-
#endif
7067
RARE_EVENT_INTERP_INC(interp, func_modification);
7168
break;
7269
default:

Python/optimizer_analysis.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,6 @@ add_op(JitOptContext *ctx, _PyUOpInstruction *this_instr,
283283
#define sym_get_probable_func_code _Py_uop_sym_get_probable_func_code
284284
#define sym_get_probable_value _Py_uop_sym_get_probable_value
285285
#define sym_set_stack_depth(DEPTH, SP) _Py_uop_sym_set_stack_depth(ctx, DEPTH, SP)
286-
#define sym_get_func_version _Py_uop_sym_get_func_version
287-
#define sym_set_func_version _Py_uop_sym_set_func_version
288286

289287
/* Comparison oparg masks */
290288
#define COMPARE_LT_MASK 2

Python/optimizer_bytecodes.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1002,20 +1002,17 @@ dummy_func(void) {
10021002

10031003
op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
10041004
PyObject *func = sym_get_probable_value(callable);
1005-
if (func == NULL || !PyFunction_Check(func)) {
1005+
if (func == NULL || !PyFunction_Check(func) || ((PyFunctionObject *)func)->func_version != func_version) {
10061006
ctx->contradiction = true;
10071007
ctx->done = true;
10081008
break;
10091009
}
1010-
// This could pass due to a global promoted const.
1011-
// So we need to add it to the dependencies on both branches.
1012-
_Py_BloomFilter_Add(dependencies, func);
1013-
if (sym_get_func_version(callable) == func_version) {
1014-
REPLACE_OP(this_instr, _NOP, 0, 0);
1015-
}
1016-
else {
1017-
sym_set_func_version(ctx, callable, func_version);
1018-
}
1010+
// Guarded on this, so it can be promoted.
1011+
sym_set_const(callable, func);
1012+
// We do not need to add func to the bloom filter, as we never remove
1013+
// this guard. Note: we generally do not want to add functions to our dependencies,
1014+
// as we want to avoid having to invalidate all executors on every function
1015+
// deallocation, which is a common procedure (e.g. lambdas).
10191016
}
10201017

10211018
op(_CHECK_METHOD_VERSION, (func_version/2, callable, null, unused[oparg] -- callable, null, unused[oparg])) {

Python/optimizer_cases.c.h

Lines changed: 2 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)