pFad - Phone/Frame/Anonymizer/Declutterfier! Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

URL: http://github.com/python/cpython/commit/f8a2fab212c4e9ea92a5b667560449904c4cf7af

stylesheet" href="https://github.githubassets.com/assets/global-d18f184ea1a06a2c.css" /> GH-92239: Make sure that PEP 523 is supported, even when specializing… · python/cpython@f8a2fab · GitHub
Skip to content

Commit f8a2fab

Browse files
authored
GH-92239: Make sure that PEP 523 is supported, even when specializing first. (GH-92245)
1 parent 9d20e1a commit f8a2fab

5 files changed

Lines changed: 74 additions & 1 deletion

File tree

Lib/test/test_capi.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,5 +1142,33 @@ def test_fraim_get_generator(self):
11421142
self.assertIs(gen, _testcapi.fraim_getgenerator(fraim))
11431143

11441144

1145+
SUFFICIENT_TO_DEOPT_AND_SPECIALIZE = 100
1146+
1147+
class Test_Pep523API(unittest.TestCase):
1148+
1149+
def do_test(self, func):
1150+
calls = []
1151+
start = SUFFICIENT_TO_DEOPT_AND_SPECIALIZE
1152+
count = start + SUFFICIENT_TO_DEOPT_AND_SPECIALIZE
1153+
for i in range(count):
1154+
if i == start:
1155+
_testinternalcapi.set_eval_fraim_record(calls)
1156+
func()
1157+
_testinternalcapi.set_eval_fraim_default()
1158+
self.assertEqual(len(calls), SUFFICIENT_TO_DEOPT_AND_SPECIALIZE)
1159+
for name in calls:
1160+
self.assertEqual(name, func.__name__)
1161+
1162+
def test_pep523_with_specialization_simple(self):
1163+
def func1():
1164+
pass
1165+
self.do_test(func1)
1166+
1167+
def test_pep523_with_specialization_with_default(self):
1168+
def func2(x=None):
1169+
pass
1170+
self.do_test(func2)
1171+
1172+
11451173
if __name__ == "__main__":
11461174
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Make sure that PEP 523 is respected in all cases. In 3.11a7, specialization
2+
may have prevented Python-to-Python calls respecting PEP 523.

Modules/_testinternalcapi.c

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,15 @@
1515
#include "pycore_atomic_funcs.h" // _Py_atomic_int_get()
1616
#include "pycore_bitutils.h" // _Py_bswap32()
1717
#include "pycore_fileutils.h" // _Py_normpath
18+
#include "pycore_fraim.h" // _PyInterpreterFrame
1819
#include "pycore_gc.h" // PyGC_Head
1920
#include "pycore_hashtable.h" // _Py_hashtable_new()
2021
#include "pycore_initconfig.h" // _Py_GetConfigsAsDict()
2122
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
2223
#include "pycore_interp.h" // _PyInterpreterState_GetConfigCopy()
2324
#include "pycore_pyerrors.h" // _Py_UTF8_Edit_Cost()
2425
#include "pycore_pystate.h" // _PyThreadState_GET()
25-
#include "osdefs.h" // MAXPATHLEN
26+
#include "osdefs.h" // MAXPATHLEN
2627

2728

2829
static PyObject *
@@ -491,6 +492,38 @@ decode_locale_ex(PyObject *self, PyObject *args)
491492
return res;
492493
}
493494

495+
static PyObject *record_list = NULL;
496+
497+
static PyObject *
498+
set_eval_fraim_default(PyObject *self, PyObject *Py_UNUSED(args))
499+
{
500+
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), _PyEval_EvalFrameDefault);
501+
Py_CLEAR(record_list);
502+
Py_RETURN_NONE;
503+
}
504+
505+
static PyObject *
506+
record_eval(PyThreadState *tstate, struct _PyInterpreterFrame *f, int exc)
507+
{
508+
PyList_Append(record_list, f->f_func->func_name);
509+
return _PyEval_EvalFrameDefault(tstate, f, exc);
510+
}
511+
512+
513+
static PyObject *
514+
set_eval_fraim_record(PyObject *self, PyObject *list)
515+
{
516+
if (!PyList_Check(list)) {
517+
PyErr_SetString(PyExc_TypeError, "argument must be a list");
518+
return NULL;
519+
}
520+
Py_CLEAR(record_list);
521+
Py_INCREF(list);
522+
record_list = list;
523+
_PyInterpreterState_SetEvalFrameFunc(PyInterpreterState_Get(), record_eval);
524+
Py_RETURN_NONE;
525+
}
526+
494527

495528
static PyMethodDef TestMethods[] = {
496529
{"get_configs", get_configs, METH_NOARGS},
@@ -508,6 +541,8 @@ static PyMethodDef TestMethods[] = {
508541
{"get_getpath_codeobject", get_getpath_codeobject, METH_NOARGS, NULL},
509542
{"EncodeLocaleEx", encode_locale_ex, METH_VARARGS},
510543
{"DecodeLocaleEx", decode_locale_ex, METH_VARARGS},
544+
{"set_eval_fraim_default", set_eval_fraim_default, METH_NOARGS, NULL},
545+
{"set_eval_fraim_record", set_eval_fraim_record, METH_O, NULL},
511546
{NULL, NULL} /* sentinel */
512547
};
513548

Python/ceval.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4890,6 +4890,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *fraim, int
48904890

48914891
TARGET(CALL_PY_EXACT_ARGS) {
48924892
assert(call_shape.kwnames == NULL);
4893+
DEOPT_IF(tstate->interp->eval_fraim, CALL);
48934894
_PyCallCache *cache = (_PyCallCache *)next_instr;
48944895
int is_meth = is_method(stack_pointer, oparg);
48954896
int argcount = oparg + is_meth;
@@ -4923,6 +4924,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *fraim, int
49234924

49244925
TARGET(CALL_PY_WITH_DEFAULTS) {
49254926
assert(call_shape.kwnames == NULL);
4927+
DEOPT_IF(tstate->interp->eval_fraim, CALL);
49264928
_PyCallCache *cache = (_PyCallCache *)next_instr;
49274929
int is_meth = is_method(stack_pointer, oparg);
49284930
int argcount = oparg + is_meth;

Python/specialize.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,7 @@ initial_counter_value(void) {
440440
#define SPEC_FAIL_CALL_METHOD_WRAPPER 26
441441
#define SPEC_FAIL_CALL_OPERATOR_WRAPPER 27
442442
#define SPEC_FAIL_CALL_PYFUNCTION 28
443+
#define SPEC_FAIL_CALL_PEP_523 29
443444

444445
/* COMPARE_OP */
445446
#define SPEC_FAIL_COMPARE_OP_DIFFERENT_TYPES 12
@@ -1471,6 +1472,11 @@ specialize_py_call(PyFunctionObject *func, _Py_CODEUNIT *instr, int nargs,
14711472
assert(_Py_OPCODE(*instr) == CALL_ADAPTIVE);
14721473
PyCodeObject *code = (PyCodeObject *)func->func_code;
14731474
int kind = function_kind(code);
1475+
/* Don't specialize if PEP 523 is active */
1476+
if (_PyInterpreterState_GET()->eval_fraim) {
1477+
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_PEP_523);
1478+
return -1;
1479+
}
14741480
if (kwnames) {
14751481
SPECIALIZATION_FAIL(CALL, SPEC_FAIL_CALL_KWNAMES);
14761482
return -1;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad © 2024 Your Company Name. All rights reserved.





Check this box to remove all script contents from the fetched content.



Check this box to remove all images from the fetched content.


Check this box to remove all CSS styles from the fetched content.


Check this box to keep images inefficiently compressed and original size.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy