Skip to content

Commit e25709a

Browse files
committed
Add test case for interpreter generator w/ overridden opcodes
1 parent 6e625f8 commit e25709a

File tree

18 files changed

+14023
-719
lines changed

18 files changed

+14023
-719
lines changed

Include/internal/pycore_instruments.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ _Py_call_instrumentation_exc2(PyThreadState *tstate, int event,
6767
extern int
6868
_Py_Instrumentation_GetLine(PyCodeObject *code, int index);
6969

70-
extern PyObject _PyInstrumentation_MISSING;
71-
extern PyObject _PyInstrumentation_DISABLE;
70+
PyAPI_DATA(PyObject) _PyInstrumentation_MISSING;
71+
PyAPI_DATA(PyObject) _PyInstrumentation_DISABLE;
7272

7373

7474
/* Total tool ids available */

Include/internal/pycore_interpframe.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ _PyThreadState_GetFrame(PyThreadState *tstate)
279279

280280
/* For use by _PyFrame_GetFrameObject
281281
Do not call directly. */
282-
PyFrameObject *
282+
PyAPI_FUNC(PyFrameObject *)
283283
_PyFrame_MakeAndSetFrameObject(_PyInterpreterFrame *frame);
284284

285285
/* Gets the PyFrameObject for this frame, lazily

Include/internal/pycore_opcode_metadata.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_pyerrors.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ extern "C" {
1111

1212
/* Error handling definitions */
1313

14-
extern _PyErr_StackItem* _PyErr_GetTopmostException(PyThreadState *tstate);
15-
extern PyObject* _PyErr_GetHandledException(PyThreadState *);
14+
PyAPI_FUNC(_PyErr_StackItem*) _PyErr_GetTopmostException(PyThreadState *tstate);
15+
PyAPI_FUNC(PyObject*) _PyErr_GetHandledException(PyThreadState *);
1616
extern void _PyErr_SetHandledException(PyThreadState *, PyObject *);
1717
extern void _PyErr_GetExcInfo(PyThreadState *, PyObject **, PyObject **, PyObject **);
1818

@@ -108,7 +108,7 @@ extern void _PyErr_Restore(
108108
PyObject *value,
109109
PyObject *traceback);
110110

111-
extern void _PyErr_SetObject(
111+
PyAPI_FUNC(void) _PyErr_SetObject(
112112
PyThreadState *tstate,
113113
PyObject *type,
114114
PyObject *value);

Include/internal/pycore_sliceobject.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ extern "C" {
1010

1111

1212
/* runtime lifecycle */
13-
1413
PyAPI_FUNC(PyObject *)
1514
_PyBuildSlice_ConsumeRefs(PyObject *start, PyObject *stop);
1615

Lib/test/test_capi/test_misc.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2781,7 +2781,6 @@ def test_line(self):
27812781
SUFFICIENT_TO_DEOPT_AND_SPECIALIZE = 100
27822782

27832783
class Test_Pep523API(unittest.TestCase):
2784-
27852784
def do_test(self, func, names):
27862785
actual_calls = []
27872786
start = SUFFICIENT_TO_DEOPT_AND_SPECIALIZE
@@ -2857,6 +2856,24 @@ def func():
28572856
names = ["func", "outer", "outer", "inner", "inner", "outer", "inner"]
28582857
self.do_test(func, names)
28592858

2859+
def test_replaced_interpreter(self):
2860+
def inner():
2861+
yield 'abc'
2862+
def outer():
2863+
yield from inner()
2864+
def func():
2865+
list(outer())
2866+
_testinternalcapi.set_eval_frame_interp()
2867+
try:
2868+
func()
2869+
finally:
2870+
_testinternalcapi.set_eval_frame_default()
2871+
2872+
stats = _testinternalcapi.get_eval_frame_stats()
2873+
2874+
self.assertEqual(stats["resumes"], 5)
2875+
self.assertEqual(stats["loads"], 5)
2876+
28602877

28612878
@unittest.skipUnless(support.Py_GIL_DISABLED, 'need Py_GIL_DISABLED')
28622879
class TestPyThreadId(unittest.TestCase):

Makefile.pre.in

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2150,7 +2150,7 @@ Objects/mimalloc/page.o: $(srcdir)/Objects/mimalloc/page-queue.c
21502150
regen-cases: \
21512151
regen-opcode-ids regen-opcode-targets regen-uop-ids regen-opcode-metadata-py \
21522152
regen-generated-cases regen-executor-cases regen-optimizer-cases \
2153-
regen-opcode-metadata regen-uop-metadata
2153+
regen-opcode-metadata regen-uop-metadata regen-test-cases regen-test-opcode-targets
21542154

21552155
.PHONY: regen-opcode-ids
21562156
regen-opcode-ids:
@@ -2182,6 +2182,20 @@ regen-generated-cases:
21822182
-o $(srcdir)/Python/generated_cases.c.h.new $(srcdir)/Python/bytecodes.c
21832183
$(UPDATE_FILE) $(srcdir)/Python/generated_cases.c.h $(srcdir)/Python/generated_cases.c.h.new
21842184

2185+
.PHONY: regen-test-cases
2186+
regen-test-cases:
2187+
$(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/tier1_generator.py \
2188+
-o $(srcdir)/Modules/_testinternalcapi/test_cases.c.h.new $(srcdir)/Python/bytecodes.c \
2189+
$(srcdir)/Modules/_testinternalcapi/testbytecodes.c
2190+
$(UPDATE_FILE) $(srcdir)/Modules/_testinternalcapi/test_cases.c.h $(srcdir)/Modules/_testinternalcapi/test_cases.c.h.new
2191+
2192+
.PHONY: regen-test-opcode-targets
2193+
regen-test-opcode-targets:
2194+
$(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/target_generator.py \
2195+
-o $(srcdir)/Modules/_testinternalcapi/test_targets.h.new $(srcdir)/Python/bytecodes.c \
2196+
$(srcdir)/Modules/_testinternalcapi/testbytecodes.c
2197+
$(UPDATE_FILE) $(srcdir)/Modules/_testinternalcapi/test_targets.h $(srcdir)/Modules/_testinternalcapi/test_targets.h.new
2198+
21852199
.PHONY: regen-executor-cases
21862200
regen-executor-cases:
21872201
$(PYTHON_FOR_REGEN) $(srcdir)/Tools/cases_generator/tier2_generator.py \
@@ -3428,7 +3442,7 @@ MODULE__SOCKET_DEPS=$(srcdir)/Modules/socketmodule.h $(srcdir)/Modules/addrinfo.
34283442
MODULE__SSL_DEPS=$(srcdir)/Modules/_ssl.h $(srcdir)/Modules/_ssl/cert.c $(srcdir)/Modules/_ssl/debughelpers.c $(srcdir)/Modules/_ssl/misc.c $(srcdir)/Modules/_ssl_data_111.h $(srcdir)/Modules/_ssl_data_300.h $(srcdir)/Modules/socketmodule.h
34293443
MODULE__TESTCAPI_DEPS=$(srcdir)/Modules/_testcapi/parts.h $(srcdir)/Modules/_testcapi/util.h
34303444
MODULE__TESTLIMITEDCAPI_DEPS=$(srcdir)/Modules/_testlimitedcapi/testcapi_long.h $(srcdir)/Modules/_testlimitedcapi/parts.h $(srcdir)/Modules/_testlimitedcapi/util.h
3431-
MODULE__TESTINTERNALCAPI_DEPS=$(srcdir)/Modules/_testinternalcapi/parts.h
3445+
MODULE__TESTINTERNALCAPI_DEPS=$(srcdir)/Modules/_testinternalcapi/parts.h $(srcdir)/Python/ceval.h $(srcdir)/Modules/_testinternalcapi/test_targets.h $(srcdir)/Modules/_testinternalcapi/test_cases.c.h
34323446
MODULE__SQLITE3_DEPS=$(srcdir)/Modules/_sqlite/connection.h $(srcdir)/Modules/_sqlite/cursor.h $(srcdir)/Modules/_sqlite/microprotocols.h $(srcdir)/Modules/_sqlite/module.h $(srcdir)/Modules/_sqlite/prepare_protocol.h $(srcdir)/Modules/_sqlite/row.h $(srcdir)/Modules/_sqlite/util.h
34333447
MODULE__ZSTD_DEPS=$(srcdir)/Modules/_zstd/_zstdmodule.h $(srcdir)/Modules/_zstd/buffer.h $(srcdir)/Modules/_zstd/zstddict.h
34343448

Modules/Setup.stdlib.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@
174174
@MODULE_XXSUBTYPE_TRUE@xxsubtype xxsubtype.c
175175
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
176176
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
177-
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/complex.c
177+
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/complex.c _testinternalcapi/interpreter.c
178178
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/modsupport.c _testcapi/monitoring.c _testcapi/config.c _testcapi/import.c _testcapi/frame.c _testcapi/type.c _testcapi/function.c _testcapi/module.c
179179
@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/sys.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.c
180180
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c

Modules/_testinternalcapi.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,39 @@ set_eval_frame_record(PyObject *self, PyObject *list)
693693
Py_RETURN_NONE;
694694
}
695695

696+
// Defined in interpreter.c
697+
extern PyObject*
698+
Test_EvalFrame(PyThreadState *tstate, _PyInterpreterFrame *frame, int throwflag);
699+
extern int Test_EvalFrame_Resumes, Test_EvalFrame_Loads;
700+
701+
static PyObject *
702+
get_eval_frame_stats(PyObject *self, PyObject *Py_UNUSED(args))
703+
{
704+
PyObject *res = PyDict_New();
705+
if (res == NULL) {
706+
return NULL;
707+
}
708+
PyObject *resumes = PyLong_FromLong(Test_EvalFrame_Resumes);
709+
if (resumes == NULL || PyDict_SetItemString(res, "resumes", resumes) < 0) {
710+
Py_XDECREF(resumes);
711+
return NULL;
712+
}
713+
PyObject *loads = PyLong_FromLong(Test_EvalFrame_Loads);
714+
if (loads == NULL || PyDict_SetItemString(res, "loads", loads) < 0) {
715+
Py_XDECREF(loads);
716+
return NULL;
717+
}
718+
Test_EvalFrame_Resumes = Test_EvalFrame_Loads = 0;
719+
return res;
720+
}
721+
722+
static PyObject *
723+
set_eval_frame_interp(PyObject *self, PyObject *Py_UNUSED(args))
724+
{
725+
_PyInterpreterState_SetEvalFrameFunc(_PyInterpreterState_GET(), Test_EvalFrame);
726+
Py_RETURN_NONE;
727+
}
728+
696729
/*[clinic input]
697730
698731
_testinternalcapi.compiler_cleandoc -> object
@@ -2507,6 +2540,7 @@ test_threadstate_set_stack_protection(PyObject *self, PyObject *Py_UNUSED(args))
25072540

25082541
static PyMethodDef module_functions[] = {
25092542
{"get_configs", get_configs, METH_NOARGS},
2543+
{"get_eval_frame_stats", get_eval_frame_stats, METH_NOARGS, NULL},
25102544
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
25112545
{"get_c_recursion_remaining", get_c_recursion_remaining, METH_NOARGS},
25122546
{"get_stack_pointer", get_stack_pointer, METH_NOARGS},
@@ -2523,6 +2557,7 @@ static PyMethodDef module_functions[] = {
25232557
{"EncodeLocaleEx", encode_locale_ex, METH_VARARGS},
25242558
{"DecodeLocaleEx", decode_locale_ex, METH_VARARGS},
25252559
{"set_eval_frame_default", set_eval_frame_default, METH_NOARGS, NULL},
2560+
{"set_eval_frame_interp", set_eval_frame_interp, METH_NOARGS, NULL},
25262561
{"set_eval_frame_record", set_eval_frame_record, METH_O, NULL},
25272562
_TESTINTERNALCAPI_COMPILER_CLEANDOC_METHODDEF
25282563
_TESTINTERNALCAPI_NEW_INSTRUCTION_SEQUENCE_METHODDEF

0 commit comments

Comments
 (0)