mirror of https://github.com/python/cpython.git
GH-126599: Remove the "counter" optimizer/executor (GH-126853)
This commit is contained in:
parent
27494dd9ad
commit
b44ff6d0df
|
@ -98,11 +98,6 @@ struct _PyOptimizerObject {
|
|||
};
|
||||
|
||||
/** Test support **/
|
||||
typedef struct {
|
||||
_PyOptimizerObject base;
|
||||
int64_t count;
|
||||
} _PyCounterOptimizerObject;
|
||||
|
||||
_PyOptimizerObject *_Py_SetOptimizer(PyInterpreterState *interp, _PyOptimizerObject* optimizer);
|
||||
|
||||
|
||||
|
@ -119,7 +114,6 @@ PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj);
|
|||
// Export for '_testinternalcapi' shared extension.
|
||||
PyAPI_FUNC(_PyOptimizerObject *) _Py_GetOptimizer(void);
|
||||
PyAPI_FUNC(int) _Py_SetTier2Optimizer(_PyOptimizerObject* optimizer);
|
||||
PyAPI_FUNC(PyObject *) _PyOptimizer_NewCounter(void);
|
||||
PyAPI_FUNC(PyObject *) _PyOptimizer_NewUOpOptimizer(void);
|
||||
|
||||
#define _Py_MAX_ALLOWED_BUILTINS_MODIFICATIONS 3
|
||||
|
@ -150,8 +144,6 @@ int _Py_uop_analyze_and_optimize(struct _PyInterpreterFrame *frame,
|
|||
_PyUOpInstruction *trace, int trace_len, int curr_stackentries,
|
||||
_PyBloomFilter *dependencies);
|
||||
|
||||
extern PyTypeObject _PyCounterExecutor_Type;
|
||||
extern PyTypeObject _PyCounterOptimizer_Type;
|
||||
extern PyTypeObject _PyDefaultOptimizer_Type;
|
||||
extern PyTypeObject _PyUOpExecutor_Type;
|
||||
extern PyTypeObject _PyUOpOptimizer_Type;
|
||||
|
|
|
@ -164,144 +164,143 @@ extern "C" {
|
|||
#define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE
|
||||
#define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE
|
||||
#define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE
|
||||
#define _INTERNAL_INCREMENT_OPT_COUNTER 399
|
||||
#define _IS_NONE 400
|
||||
#define _IS_NONE 399
|
||||
#define _IS_OP IS_OP
|
||||
#define _ITER_CHECK_LIST 401
|
||||
#define _ITER_CHECK_RANGE 402
|
||||
#define _ITER_CHECK_TUPLE 403
|
||||
#define _ITER_JUMP_LIST 404
|
||||
#define _ITER_JUMP_RANGE 405
|
||||
#define _ITER_JUMP_TUPLE 406
|
||||
#define _ITER_NEXT_LIST 407
|
||||
#define _ITER_NEXT_RANGE 408
|
||||
#define _ITER_NEXT_TUPLE 409
|
||||
#define _JUMP_TO_TOP 410
|
||||
#define _ITER_CHECK_LIST 400
|
||||
#define _ITER_CHECK_RANGE 401
|
||||
#define _ITER_CHECK_TUPLE 402
|
||||
#define _ITER_JUMP_LIST 403
|
||||
#define _ITER_JUMP_RANGE 404
|
||||
#define _ITER_JUMP_TUPLE 405
|
||||
#define _ITER_NEXT_LIST 406
|
||||
#define _ITER_NEXT_RANGE 407
|
||||
#define _ITER_NEXT_TUPLE 408
|
||||
#define _JUMP_TO_TOP 409
|
||||
#define _LIST_APPEND LIST_APPEND
|
||||
#define _LIST_EXTEND LIST_EXTEND
|
||||
#define _LOAD_ATTR 411
|
||||
#define _LOAD_ATTR_CLASS 412
|
||||
#define _LOAD_ATTR_CLASS_0 413
|
||||
#define _LOAD_ATTR_CLASS_1 414
|
||||
#define _LOAD_ATTR 410
|
||||
#define _LOAD_ATTR_CLASS 411
|
||||
#define _LOAD_ATTR_CLASS_0 412
|
||||
#define _LOAD_ATTR_CLASS_1 413
|
||||
#define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN
|
||||
#define _LOAD_ATTR_INSTANCE_VALUE 415
|
||||
#define _LOAD_ATTR_INSTANCE_VALUE_0 416
|
||||
#define _LOAD_ATTR_INSTANCE_VALUE_1 417
|
||||
#define _LOAD_ATTR_METHOD_LAZY_DICT 418
|
||||
#define _LOAD_ATTR_METHOD_NO_DICT 419
|
||||
#define _LOAD_ATTR_METHOD_WITH_VALUES 420
|
||||
#define _LOAD_ATTR_MODULE 421
|
||||
#define _LOAD_ATTR_MODULE_FROM_KEYS 422
|
||||
#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 423
|
||||
#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 424
|
||||
#define _LOAD_ATTR_PROPERTY_FRAME 425
|
||||
#define _LOAD_ATTR_SLOT 426
|
||||
#define _LOAD_ATTR_SLOT_0 427
|
||||
#define _LOAD_ATTR_SLOT_1 428
|
||||
#define _LOAD_ATTR_WITH_HINT 429
|
||||
#define _LOAD_ATTR_INSTANCE_VALUE 414
|
||||
#define _LOAD_ATTR_INSTANCE_VALUE_0 415
|
||||
#define _LOAD_ATTR_INSTANCE_VALUE_1 416
|
||||
#define _LOAD_ATTR_METHOD_LAZY_DICT 417
|
||||
#define _LOAD_ATTR_METHOD_NO_DICT 418
|
||||
#define _LOAD_ATTR_METHOD_WITH_VALUES 419
|
||||
#define _LOAD_ATTR_MODULE 420
|
||||
#define _LOAD_ATTR_MODULE_FROM_KEYS 421
|
||||
#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 422
|
||||
#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 423
|
||||
#define _LOAD_ATTR_PROPERTY_FRAME 424
|
||||
#define _LOAD_ATTR_SLOT 425
|
||||
#define _LOAD_ATTR_SLOT_0 426
|
||||
#define _LOAD_ATTR_SLOT_1 427
|
||||
#define _LOAD_ATTR_WITH_HINT 428
|
||||
#define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS
|
||||
#define _LOAD_BYTECODE 430
|
||||
#define _LOAD_BYTECODE 429
|
||||
#define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT
|
||||
#define _LOAD_CONST LOAD_CONST
|
||||
#define _LOAD_CONST_IMMORTAL LOAD_CONST_IMMORTAL
|
||||
#define _LOAD_CONST_INLINE 431
|
||||
#define _LOAD_CONST_INLINE_BORROW 432
|
||||
#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 433
|
||||
#define _LOAD_CONST_INLINE_WITH_NULL 434
|
||||
#define _LOAD_CONST_INLINE 430
|
||||
#define _LOAD_CONST_INLINE_BORROW 431
|
||||
#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 432
|
||||
#define _LOAD_CONST_INLINE_WITH_NULL 433
|
||||
#define _LOAD_CONST_MORTAL LOAD_CONST_MORTAL
|
||||
#define _LOAD_DEREF LOAD_DEREF
|
||||
#define _LOAD_FAST 435
|
||||
#define _LOAD_FAST_0 436
|
||||
#define _LOAD_FAST_1 437
|
||||
#define _LOAD_FAST_2 438
|
||||
#define _LOAD_FAST_3 439
|
||||
#define _LOAD_FAST_4 440
|
||||
#define _LOAD_FAST_5 441
|
||||
#define _LOAD_FAST_6 442
|
||||
#define _LOAD_FAST_7 443
|
||||
#define _LOAD_FAST 434
|
||||
#define _LOAD_FAST_0 435
|
||||
#define _LOAD_FAST_1 436
|
||||
#define _LOAD_FAST_2 437
|
||||
#define _LOAD_FAST_3 438
|
||||
#define _LOAD_FAST_4 439
|
||||
#define _LOAD_FAST_5 440
|
||||
#define _LOAD_FAST_6 441
|
||||
#define _LOAD_FAST_7 442
|
||||
#define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR
|
||||
#define _LOAD_FAST_CHECK LOAD_FAST_CHECK
|
||||
#define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST
|
||||
#define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF
|
||||
#define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS
|
||||
#define _LOAD_GLOBAL 444
|
||||
#define _LOAD_GLOBAL_BUILTINS 445
|
||||
#define _LOAD_GLOBAL_BUILTINS_FROM_KEYS 446
|
||||
#define _LOAD_GLOBAL_MODULE 447
|
||||
#define _LOAD_GLOBAL_MODULE_FROM_KEYS 448
|
||||
#define _LOAD_GLOBAL 443
|
||||
#define _LOAD_GLOBAL_BUILTINS 444
|
||||
#define _LOAD_GLOBAL_BUILTINS_FROM_KEYS 445
|
||||
#define _LOAD_GLOBAL_MODULE 446
|
||||
#define _LOAD_GLOBAL_MODULE_FROM_KEYS 447
|
||||
#define _LOAD_LOCALS LOAD_LOCALS
|
||||
#define _LOAD_NAME LOAD_NAME
|
||||
#define _LOAD_SMALL_INT 449
|
||||
#define _LOAD_SMALL_INT_0 450
|
||||
#define _LOAD_SMALL_INT_1 451
|
||||
#define _LOAD_SMALL_INT_2 452
|
||||
#define _LOAD_SMALL_INT_3 453
|
||||
#define _LOAD_SMALL_INT 448
|
||||
#define _LOAD_SMALL_INT_0 449
|
||||
#define _LOAD_SMALL_INT_1 450
|
||||
#define _LOAD_SMALL_INT_2 451
|
||||
#define _LOAD_SMALL_INT_3 452
|
||||
#define _LOAD_SPECIAL LOAD_SPECIAL
|
||||
#define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR
|
||||
#define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD
|
||||
#define _MAKE_CALLARGS_A_TUPLE 454
|
||||
#define _MAKE_CALLARGS_A_TUPLE 453
|
||||
#define _MAKE_CELL MAKE_CELL
|
||||
#define _MAKE_FUNCTION MAKE_FUNCTION
|
||||
#define _MAKE_WARM 455
|
||||
#define _MAKE_WARM 454
|
||||
#define _MAP_ADD MAP_ADD
|
||||
#define _MATCH_CLASS MATCH_CLASS
|
||||
#define _MATCH_KEYS MATCH_KEYS
|
||||
#define _MATCH_MAPPING MATCH_MAPPING
|
||||
#define _MATCH_SEQUENCE MATCH_SEQUENCE
|
||||
#define _MAYBE_EXPAND_METHOD 456
|
||||
#define _MAYBE_EXPAND_METHOD_KW 457
|
||||
#define _MONITOR_CALL 458
|
||||
#define _MONITOR_JUMP_BACKWARD 459
|
||||
#define _MONITOR_RESUME 460
|
||||
#define _MAYBE_EXPAND_METHOD 455
|
||||
#define _MAYBE_EXPAND_METHOD_KW 456
|
||||
#define _MONITOR_CALL 457
|
||||
#define _MONITOR_JUMP_BACKWARD 458
|
||||
#define _MONITOR_RESUME 459
|
||||
#define _NOP NOP
|
||||
#define _POP_EXCEPT POP_EXCEPT
|
||||
#define _POP_JUMP_IF_FALSE 461
|
||||
#define _POP_JUMP_IF_TRUE 462
|
||||
#define _POP_JUMP_IF_FALSE 460
|
||||
#define _POP_JUMP_IF_TRUE 461
|
||||
#define _POP_TOP POP_TOP
|
||||
#define _POP_TOP_LOAD_CONST_INLINE_BORROW 463
|
||||
#define _POP_TOP_LOAD_CONST_INLINE_BORROW 462
|
||||
#define _PUSH_EXC_INFO PUSH_EXC_INFO
|
||||
#define _PUSH_FRAME 464
|
||||
#define _PUSH_FRAME 463
|
||||
#define _PUSH_NULL PUSH_NULL
|
||||
#define _PY_FRAME_GENERAL 465
|
||||
#define _PY_FRAME_KW 466
|
||||
#define _QUICKEN_RESUME 467
|
||||
#define _REPLACE_WITH_TRUE 468
|
||||
#define _PY_FRAME_GENERAL 464
|
||||
#define _PY_FRAME_KW 465
|
||||
#define _QUICKEN_RESUME 466
|
||||
#define _REPLACE_WITH_TRUE 467
|
||||
#define _RESUME_CHECK RESUME_CHECK
|
||||
#define _RETURN_GENERATOR RETURN_GENERATOR
|
||||
#define _RETURN_VALUE RETURN_VALUE
|
||||
#define _SAVE_RETURN_OFFSET 469
|
||||
#define _SEND 470
|
||||
#define _SEND_GEN_FRAME 471
|
||||
#define _SAVE_RETURN_OFFSET 468
|
||||
#define _SEND 469
|
||||
#define _SEND_GEN_FRAME 470
|
||||
#define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS
|
||||
#define _SET_ADD SET_ADD
|
||||
#define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE
|
||||
#define _SET_UPDATE SET_UPDATE
|
||||
#define _START_EXECUTOR 472
|
||||
#define _STORE_ATTR 473
|
||||
#define _STORE_ATTR_INSTANCE_VALUE 474
|
||||
#define _STORE_ATTR_SLOT 475
|
||||
#define _STORE_ATTR_WITH_HINT 476
|
||||
#define _START_EXECUTOR 471
|
||||
#define _STORE_ATTR 472
|
||||
#define _STORE_ATTR_INSTANCE_VALUE 473
|
||||
#define _STORE_ATTR_SLOT 474
|
||||
#define _STORE_ATTR_WITH_HINT 475
|
||||
#define _STORE_DEREF STORE_DEREF
|
||||
#define _STORE_FAST 477
|
||||
#define _STORE_FAST_0 478
|
||||
#define _STORE_FAST_1 479
|
||||
#define _STORE_FAST_2 480
|
||||
#define _STORE_FAST_3 481
|
||||
#define _STORE_FAST_4 482
|
||||
#define _STORE_FAST_5 483
|
||||
#define _STORE_FAST_6 484
|
||||
#define _STORE_FAST_7 485
|
||||
#define _STORE_FAST 476
|
||||
#define _STORE_FAST_0 477
|
||||
#define _STORE_FAST_1 478
|
||||
#define _STORE_FAST_2 479
|
||||
#define _STORE_FAST_3 480
|
||||
#define _STORE_FAST_4 481
|
||||
#define _STORE_FAST_5 482
|
||||
#define _STORE_FAST_6 483
|
||||
#define _STORE_FAST_7 484
|
||||
#define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST
|
||||
#define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST
|
||||
#define _STORE_GLOBAL STORE_GLOBAL
|
||||
#define _STORE_NAME STORE_NAME
|
||||
#define _STORE_SLICE 486
|
||||
#define _STORE_SUBSCR 487
|
||||
#define _STORE_SLICE 485
|
||||
#define _STORE_SUBSCR 486
|
||||
#define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT
|
||||
#define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT
|
||||
#define _SWAP SWAP
|
||||
#define _TIER2_RESUME_CHECK 488
|
||||
#define _TO_BOOL 489
|
||||
#define _TIER2_RESUME_CHECK 487
|
||||
#define _TO_BOOL 488
|
||||
#define _TO_BOOL_BOOL TO_BOOL_BOOL
|
||||
#define _TO_BOOL_INT TO_BOOL_INT
|
||||
#define _TO_BOOL_LIST TO_BOOL_LIST
|
||||
|
@ -311,13 +310,13 @@ extern "C" {
|
|||
#define _UNARY_NEGATIVE UNARY_NEGATIVE
|
||||
#define _UNARY_NOT UNARY_NOT
|
||||
#define _UNPACK_EX UNPACK_EX
|
||||
#define _UNPACK_SEQUENCE 490
|
||||
#define _UNPACK_SEQUENCE 489
|
||||
#define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST
|
||||
#define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE
|
||||
#define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE
|
||||
#define _WITH_EXCEPT_START WITH_EXCEPT_START
|
||||
#define _YIELD_VALUE YIELD_VALUE
|
||||
#define MAX_UOP_ID 490
|
||||
#define MAX_UOP_ID 489
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -288,7 +288,6 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
|
|||
[_LOAD_GLOBAL_MODULE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
|
||||
[_LOAD_GLOBAL_BUILTINS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
|
||||
[_LOAD_ATTR_MODULE] = HAS_ARG_FLAG | HAS_DEOPT_FLAG,
|
||||
[_INTERNAL_INCREMENT_OPT_COUNTER] = 0,
|
||||
[_DYNAMIC_EXIT] = HAS_ESCAPES_FLAG,
|
||||
[_START_EXECUTOR] = HAS_ESCAPES_FLAG,
|
||||
[_MAKE_WARM] = 0,
|
||||
|
@ -445,7 +444,6 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
|
|||
[_INIT_CALL_PY_EXACT_ARGS_2] = "_INIT_CALL_PY_EXACT_ARGS_2",
|
||||
[_INIT_CALL_PY_EXACT_ARGS_3] = "_INIT_CALL_PY_EXACT_ARGS_3",
|
||||
[_INIT_CALL_PY_EXACT_ARGS_4] = "_INIT_CALL_PY_EXACT_ARGS_4",
|
||||
[_INTERNAL_INCREMENT_OPT_COUNTER] = "_INTERNAL_INCREMENT_OPT_COUNTER",
|
||||
[_IS_NONE] = "_IS_NONE",
|
||||
[_IS_OP] = "_IS_OP",
|
||||
[_ITER_CHECK_LIST] = "_ITER_CHECK_LIST",
|
||||
|
@ -1127,8 +1125,6 @@ int _PyUop_num_popped(int opcode, int oparg)
|
|||
return 0;
|
||||
case _LOAD_ATTR_MODULE:
|
||||
return 1;
|
||||
case _INTERNAL_INCREMENT_OPT_COUNTER:
|
||||
return 1;
|
||||
case _DYNAMIC_EXIT:
|
||||
return 0;
|
||||
case _START_EXECUTOR:
|
||||
|
|
|
@ -35,90 +35,6 @@ def clear_executors(func):
|
|||
func.__code__ = func.__code__.replace()
|
||||
|
||||
|
||||
@requires_specialization
|
||||
@unittest.skipIf(Py_GIL_DISABLED, "optimizer not yet supported in free-threaded builds")
|
||||
@unittest.skipUnless(hasattr(_testinternalcapi, "get_optimizer"),
|
||||
"Requires optimizer infrastructure")
|
||||
class TestOptimizerAPI(unittest.TestCase):
|
||||
|
||||
def test_new_counter_optimizer_dealloc(self):
|
||||
# See gh-108727
|
||||
def f():
|
||||
_testinternalcapi.new_counter_optimizer()
|
||||
|
||||
f()
|
||||
|
||||
def test_get_set_optimizer(self):
|
||||
old = _testinternalcapi.get_optimizer()
|
||||
opt = _testinternalcapi.new_counter_optimizer()
|
||||
try:
|
||||
_testinternalcapi.set_optimizer(opt)
|
||||
self.assertEqual(_testinternalcapi.get_optimizer(), opt)
|
||||
_testinternalcapi.set_optimizer(None)
|
||||
self.assertEqual(_testinternalcapi.get_optimizer(), None)
|
||||
finally:
|
||||
_testinternalcapi.set_optimizer(old)
|
||||
|
||||
|
||||
def test_counter_optimizer(self):
|
||||
# Generate a new function at each call
|
||||
ns = {}
|
||||
exec(textwrap.dedent(f"""
|
||||
def loop():
|
||||
for _ in range({TIER2_THRESHOLD + 1000}):
|
||||
pass
|
||||
"""), ns, ns)
|
||||
loop = ns['loop']
|
||||
|
||||
for repeat in range(5):
|
||||
opt = _testinternalcapi.new_counter_optimizer()
|
||||
with temporary_optimizer(opt):
|
||||
self.assertEqual(opt.get_count(), 0)
|
||||
with clear_executors(loop):
|
||||
loop()
|
||||
self.assertEqual(opt.get_count(), 1001)
|
||||
|
||||
def test_long_loop(self):
|
||||
"Check that we aren't confused by EXTENDED_ARG"
|
||||
|
||||
# Generate a new function at each call
|
||||
ns = {}
|
||||
exec(textwrap.dedent(f"""
|
||||
def nop():
|
||||
pass
|
||||
|
||||
def long_loop():
|
||||
for _ in range({TIER2_THRESHOLD + 20}):
|
||||
nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
|
||||
nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
|
||||
nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
|
||||
nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
|
||||
nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
|
||||
nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
|
||||
nop(); nop(); nop(); nop(); nop(); nop(); nop(); nop();
|
||||
"""), ns, ns)
|
||||
long_loop = ns['long_loop']
|
||||
|
||||
opt = _testinternalcapi.new_counter_optimizer()
|
||||
with temporary_optimizer(opt):
|
||||
self.assertEqual(opt.get_count(), 0)
|
||||
long_loop()
|
||||
self.assertEqual(opt.get_count(), 21) # Need iterations to warm up
|
||||
|
||||
def test_code_restore_for_ENTER_EXECUTOR(self):
|
||||
def testfunc(x):
|
||||
i = 0
|
||||
while i < x:
|
||||
i += 1
|
||||
|
||||
opt = _testinternalcapi.new_counter_optimizer()
|
||||
with temporary_optimizer(opt):
|
||||
testfunc(1000)
|
||||
code, replace_code = testfunc.__code__, testfunc.__code__.replace()
|
||||
self.assertEqual(code, replace_code)
|
||||
self.assertEqual(hash(code), hash(replace_code))
|
||||
|
||||
|
||||
def get_first_executor(func):
|
||||
code = func.__code__
|
||||
co_code = code.co_code
|
||||
|
@ -145,14 +61,6 @@ def get_opnames(ex):
|
|||
"Requires optimizer infrastructure")
|
||||
class TestExecutorInvalidation(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.old = _testinternalcapi.get_optimizer()
|
||||
self.opt = _testinternalcapi.new_counter_optimizer()
|
||||
_testinternalcapi.set_optimizer(self.opt)
|
||||
|
||||
def tearDown(self):
|
||||
_testinternalcapi.set_optimizer(self.old)
|
||||
|
||||
def test_invalidate_object(self):
|
||||
# Generate a new set of functions at each call
|
||||
ns = {}
|
||||
|
@ -167,8 +75,10 @@ def f{n}():
|
|||
funcs = [ ns[f'f{n}'] for n in range(5)]
|
||||
objects = [object() for _ in range(5)]
|
||||
|
||||
for f in funcs:
|
||||
f()
|
||||
opt = _testinternalcapi.new_uop_optimizer()
|
||||
with temporary_optimizer(opt):
|
||||
for f in funcs:
|
||||
f()
|
||||
executors = [get_first_executor(f) for f in funcs]
|
||||
# Set things up so each executor depends on the objects
|
||||
# with an equal or lower index.
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
import test.support
|
||||
from test.support import requires_specialization_ft, script_helper
|
||||
from test.support.import_helper import import_module
|
||||
|
||||
_testcapi = test.support.import_helper.import_module("_testcapi")
|
||||
|
||||
|
@ -2087,20 +2086,6 @@ def callback(code, instruction_offset):
|
|||
|
||||
class TestOptimizer(MonitoringTestBase, unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
_testinternalcapi = import_module("_testinternalcapi")
|
||||
if hasattr(_testinternalcapi, "get_optimizer"):
|
||||
self.old_opt = _testinternalcapi.get_optimizer()
|
||||
opt = _testinternalcapi.new_counter_optimizer()
|
||||
_testinternalcapi.set_optimizer(opt)
|
||||
super(TestOptimizer, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
super(TestOptimizer, self).tearDown()
|
||||
import _testinternalcapi
|
||||
if hasattr(_testinternalcapi, "get_optimizer"):
|
||||
_testinternalcapi.set_optimizer(self.old_opt)
|
||||
|
||||
def test_for_loop(self):
|
||||
def test_func(x):
|
||||
i = 0
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Remove some internal test APIs for the experimental JIT compiler.
|
|
@ -989,12 +989,6 @@ get_co_framesize(PyObject *self, PyObject *arg)
|
|||
|
||||
#ifdef _Py_TIER2
|
||||
|
||||
static PyObject *
|
||||
new_counter_optimizer(PyObject *self, PyObject *arg)
|
||||
{
|
||||
return _PyOptimizer_NewCounter();
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
new_uop_optimizer(PyObject *self, PyObject *arg)
|
||||
{
|
||||
|
@ -1034,12 +1028,6 @@ add_executor_dependency(PyObject *self, PyObject *args)
|
|||
if (!PyArg_ParseTuple(args, "OO", &exec, &obj)) {
|
||||
return NULL;
|
||||
}
|
||||
/* No way to tell in general if exec is an executor, so we only accept
|
||||
* counting_executor */
|
||||
if (strcmp(Py_TYPE(exec)->tp_name, "counting_executor")) {
|
||||
PyErr_SetString(PyExc_TypeError, "argument must be a counting_executor");
|
||||
return NULL;
|
||||
}
|
||||
_Py_Executor_DependsOn((_PyExecutorObject *)exec, obj);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@ -2101,7 +2089,6 @@ static PyMethodDef module_functions[] = {
|
|||
#ifdef _Py_TIER2
|
||||
{"get_optimizer", get_optimizer, METH_NOARGS, NULL},
|
||||
{"set_optimizer", set_optimizer, METH_O, NULL},
|
||||
{"new_counter_optimizer", new_counter_optimizer, METH_NOARGS, NULL},
|
||||
{"new_uop_optimizer", new_uop_optimizer, METH_NOARGS, NULL},
|
||||
{"add_executor_dependency", add_executor_dependency, METH_VARARGS, NULL},
|
||||
{"invalidate_executors", invalidate_executors, METH_O, NULL},
|
||||
|
|
|
@ -2380,8 +2380,6 @@ static PyTypeObject* static_types[] = {
|
|||
&_PyContextTokenMissing_Type,
|
||||
&_PyCoroWrapper_Type,
|
||||
#ifdef _Py_TIER2
|
||||
&_PyCounterExecutor_Type,
|
||||
&_PyCounterOptimizer_Type,
|
||||
&_PyDefaultOptimizer_Type,
|
||||
#endif
|
||||
&_Py_GenericAliasIterType,
|
||||
|
|
|
@ -5076,13 +5076,6 @@ dummy_func(
|
|||
DECREF_INPUTS();
|
||||
}
|
||||
|
||||
/* Internal -- for testing executors */
|
||||
op(_INTERNAL_INCREMENT_OPT_COUNTER, (opt --)) {
|
||||
_PyCounterOptimizerObject *exe = (_PyCounterOptimizerObject *)PyStackRef_AsPyObjectBorrow(opt);
|
||||
exe->count++;
|
||||
DEAD(opt);
|
||||
}
|
||||
|
||||
tier2 op(_DYNAMIC_EXIT, (exit_p/4 --)) {
|
||||
tstate->previous_executor = (PyObject *)current_executor;
|
||||
_PyExitData *exit = (_PyExitData *)exit_p;
|
||||
|
|
|
@ -6209,16 +6209,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _INTERNAL_INCREMENT_OPT_COUNTER: {
|
||||
_PyStackRef opt;
|
||||
opt = stack_pointer[-1];
|
||||
_PyCounterOptimizerObject *exe = (_PyCounterOptimizerObject *)PyStackRef_AsPyObjectBorrow(opt);
|
||||
exe->count++;
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
|
||||
case _DYNAMIC_EXIT: {
|
||||
PyObject *exit_p = (PyObject *)CURRENT_OPERAND0();
|
||||
tstate->previous_executor = (PyObject *)current_executor;
|
||||
|
|
|
@ -132,8 +132,6 @@ _Py_GetOptimizer(void)
|
|||
static _PyExecutorObject *
|
||||
make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFilter *dependencies);
|
||||
|
||||
static const _PyBloomFilter EMPTY_FILTER = { 0 };
|
||||
|
||||
_PyOptimizerObject *
|
||||
_Py_SetOptimizer(PyInterpreterState *interp, _PyOptimizerObject *optimizer)
|
||||
{
|
||||
|
@ -251,13 +249,6 @@ get_oparg(PyObject *self, PyObject *Py_UNUSED(ignored))
|
|||
return PyLong_FromUnsignedLong(((_PyExecutorObject *)self)->vm_data.oparg);
|
||||
}
|
||||
|
||||
static PyMethodDef executor_methods[] = {
|
||||
{ "is_valid", is_valid, METH_NOARGS, NULL },
|
||||
{ "get_opcode", get_opcode, METH_NOARGS, NULL },
|
||||
{ "get_oparg", get_oparg, METH_NOARGS, NULL },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
///////////////////// Experimental UOp Optimizer /////////////////////
|
||||
|
||||
static int executor_clear(_PyExecutorObject *executor);
|
||||
|
@ -1332,96 +1323,6 @@ _PyOptimizer_NewUOpOptimizer(void)
|
|||
return (PyObject *)opt;
|
||||
}
|
||||
|
||||
static void
|
||||
counter_dealloc(_PyExecutorObject *self) {
|
||||
/* The optimizer is the operand of the second uop. */
|
||||
PyObject *opt = (PyObject *)self->trace[1].operand0;
|
||||
Py_DECREF(opt);
|
||||
uop_dealloc(self);
|
||||
}
|
||||
|
||||
PyTypeObject _PyCounterExecutor_Type = {
|
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||
.tp_name = "counting_executor",
|
||||
.tp_basicsize = offsetof(_PyExecutorObject, exits),
|
||||
.tp_itemsize = 1,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION | Py_TPFLAGS_HAVE_GC,
|
||||
.tp_dealloc = (destructor)counter_dealloc,
|
||||
.tp_methods = executor_methods,
|
||||
.tp_traverse = executor_traverse,
|
||||
.tp_clear = (inquiry)executor_clear,
|
||||
};
|
||||
|
||||
static int
|
||||
counter_optimize(
|
||||
_PyOptimizerObject* self,
|
||||
_PyInterpreterFrame *frame,
|
||||
_Py_CODEUNIT *instr,
|
||||
_PyExecutorObject **exec_ptr,
|
||||
int Py_UNUSED(curr_stackentries),
|
||||
bool Py_UNUSED(progress_needed)
|
||||
)
|
||||
{
|
||||
PyCodeObject *code = _PyFrame_GetCode(frame);
|
||||
int oparg = instr->op.arg;
|
||||
while (instr->op.code == EXTENDED_ARG) {
|
||||
instr++;
|
||||
oparg = (oparg << 8) | instr->op.arg;
|
||||
}
|
||||
if (instr->op.code != JUMP_BACKWARD) {
|
||||
/* Counter optimizer can only handle backward edges */
|
||||
return 0;
|
||||
}
|
||||
_Py_CODEUNIT *target = instr + 1 + _PyOpcode_Caches[JUMP_BACKWARD] - oparg;
|
||||
_PyUOpInstruction buffer[4] = {
|
||||
{ .opcode = _START_EXECUTOR, .jump_target = 3, .format=UOP_FORMAT_JUMP },
|
||||
{ .opcode = _LOAD_CONST_INLINE, .operand0 = (uintptr_t)self },
|
||||
{ .opcode = _INTERNAL_INCREMENT_OPT_COUNTER },
|
||||
{ .opcode = _EXIT_TRACE, .target = (uint32_t)(target - _PyCode_CODE(code)), .format=UOP_FORMAT_TARGET }
|
||||
};
|
||||
_PyExecutorObject *executor = make_executor_from_uops(buffer, 4, &EMPTY_FILTER);
|
||||
if (executor == NULL) {
|
||||
return -1;
|
||||
}
|
||||
Py_INCREF(self);
|
||||
Py_SET_TYPE(executor, &_PyCounterExecutor_Type);
|
||||
*exec_ptr = executor;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
counter_get_counter(PyObject *self, PyObject *args)
|
||||
{
|
||||
return PyLong_FromLongLong(((_PyCounterOptimizerObject *)self)->count);
|
||||
}
|
||||
|
||||
static PyMethodDef counter_optimizer_methods[] = {
|
||||
{ "get_count", counter_get_counter, METH_NOARGS, NULL },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
PyTypeObject _PyCounterOptimizer_Type = {
|
||||
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
||||
.tp_name = "Counter optimizer",
|
||||
.tp_basicsize = sizeof(_PyCounterOptimizerObject),
|
||||
.tp_itemsize = 0,
|
||||
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
|
||||
.tp_methods = counter_optimizer_methods,
|
||||
.tp_dealloc = (destructor)PyObject_Free,
|
||||
};
|
||||
|
||||
PyObject *
|
||||
_PyOptimizer_NewCounter(void)
|
||||
{
|
||||
_PyCounterOptimizerObject *opt = (_PyCounterOptimizerObject *)_PyObject_New(&_PyCounterOptimizer_Type);
|
||||
if (opt == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
opt->base.optimize = counter_optimize;
|
||||
opt->count = 0;
|
||||
return (PyObject *)opt;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************
|
||||
* Executor management
|
||||
|
|
|
@ -2667,12 +2667,6 @@
|
|||
break;
|
||||
}
|
||||
|
||||
case _INTERNAL_INCREMENT_OPT_COUNTER: {
|
||||
stack_pointer += -1;
|
||||
assert(WITHIN_STACK_BOUNDS());
|
||||
break;
|
||||
}
|
||||
|
||||
case _DYNAMIC_EXIT: {
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -386,8 +386,6 @@ Python/sysmodule.c - _PySys_ImplCacheTag -
|
|||
Python/sysmodule.c - _PySys_ImplName -
|
||||
Python/sysmodule.c - whatstrings -
|
||||
Python/optimizer.c - _PyDefaultOptimizer_Type -
|
||||
Python/optimizer.c - _PyCounterExecutor_Type -
|
||||
Python/optimizer.c - _PyCounterOptimizer_Type -
|
||||
Python/optimizer.c - _PyUOpExecutor_Type -
|
||||
Python/optimizer.c - _PyUOpOptimizer_Type -
|
||||
Python/optimizer.c - _PyOptimizer_Default -
|
||||
|
|
Can't render this file because it has a wrong number of fields in line 4.
|
Loading…
Reference in New Issue