aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python
diff options
context:
space:
mode:
Diffstat (limited to 'Python')
-rw-r--r--Python/Python-ast.c26
-rw-r--r--Python/ast_unparse.c39
-rw-r--r--Python/bytecodes.c38
-rw-r--r--Python/ceval_gil.c25
-rw-r--r--Python/crossinterp.c128
-rw-r--r--Python/crossinterp_data_lookup.h56
-rw-r--r--Python/dynload_win.c6
-rw-r--r--Python/executor_cases.c.h83
-rw-r--r--Python/fileutils.c37
-rw-r--r--Python/gc_free_threading.c11
-rw-r--r--Python/generated_cases.c.h101
-rw-r--r--Python/import.c8
-rw-r--r--Python/initconfig.c2
-rw-r--r--Python/marshal.c2
-rw-r--r--Python/optimizer_bytecodes.c135
-rw-r--r--Python/optimizer_cases.c.h186
-rw-r--r--Python/pathconfig.c20
-rw-r--r--Python/pylifecycle.c2
-rw-r--r--Python/pystate.c9
-rw-r--r--Python/pythonrun.c20
-rw-r--r--Python/specialize.c2
-rw-r--r--Python/stackrefs.c2
-rw-r--r--Python/symtable.c6
-rw-r--r--Python/sysmodule.c110
24 files changed, 718 insertions, 336 deletions
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
index df035568f84..f7625ab1205 100644
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -5528,6 +5528,32 @@ ast_type_replace_check(PyObject *self,
Py_DECREF(unused);
}
}
+
+ // Discard fields from 'expecting' that default to None
+ PyObject *field_types = NULL;
+ if (PyObject_GetOptionalAttr((PyObject*)Py_TYPE(self),
+ &_Py_ID(_field_types),
+ &field_types) < 0)
+ {
+ Py_DECREF(expecting);
+ return -1;
+ }
+ if (field_types != NULL) {
+ Py_ssize_t pos = 0;
+ PyObject *field_name, *field_type;
+ while (PyDict_Next(field_types, &pos, &field_name, &field_type)) {
+ if (_PyUnion_Check(field_type)) {
+ // optional field
+ if (PySet_Discard(expecting, field_name) < 0) {
+ Py_DECREF(expecting);
+ Py_DECREF(field_types);
+ return -1;
+ }
+ }
+ }
+ Py_DECREF(field_types);
+ }
+
// Now 'expecting' contains the fields or attributes
// that would not be filled inside ast_type_replace().
Py_ssize_t m = PySet_GET_SIZE(expecting);
diff --git a/Python/ast_unparse.c b/Python/ast_unparse.c
index c121ec096ae..557c12cfda6 100644
--- a/Python/ast_unparse.c
+++ b/Python/ast_unparse.c
@@ -702,6 +702,13 @@ append_templatestr(PyUnicodeWriter *writer, expr_ty e)
Py_ssize_t last_idx = 0;
Py_ssize_t len = asdl_seq_LEN(e->v.TemplateStr.values);
+ if (len == 0) {
+ int result = _write_values_subarray(writer, e->v.TemplateStr.values,
+ 0, len - 1, 't', arena);
+ _PyArena_Free(arena);
+ return result;
+ }
+
for (Py_ssize_t i = 0; i < len; i++) {
expr_ty value = asdl_seq_GET(e->v.TemplateStr.values, i);
@@ -742,6 +749,7 @@ append_templatestr(PyUnicodeWriter *writer, expr_ty e)
goto error;
}
}
+ _PyArena_Free(arena);
return 0;
@@ -774,33 +782,38 @@ append_joinedstr(PyUnicodeWriter *writer, expr_ty e, bool is_format_spec)
}
static int
-append_interpolation_value(PyUnicodeWriter *writer, expr_ty e)
+append_interpolation_str(PyUnicodeWriter *writer, PyObject *str)
{
const char *outer_brace = "{";
- /* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis
- around a lambda with ':' */
- PyObject *temp_fv_str = expr_as_unicode(e, PR_TEST + 1);
- if (!temp_fv_str) {
- return -1;
- }
- if (PyUnicode_Find(temp_fv_str, _Py_LATIN1_CHR('{'), 0, 1, 1) == 0) {
+ if (PyUnicode_Find(str, _Py_LATIN1_CHR('{'), 0, 1, 1) == 0) {
/* Expression starts with a brace, split it with a space from the outer
one. */
outer_brace = "{ ";
}
if (-1 == append_charp(writer, outer_brace)) {
- Py_DECREF(temp_fv_str);
return -1;
}
- if (-1 == PyUnicodeWriter_WriteStr(writer, temp_fv_str)) {
- Py_DECREF(temp_fv_str);
+ if (-1 == PyUnicodeWriter_WriteStr(writer, str)) {
return -1;
}
- Py_DECREF(temp_fv_str);
return 0;
}
static int
+append_interpolation_value(PyUnicodeWriter *writer, expr_ty e)
+{
+ /* Grammar allows PR_TUPLE, but use >PR_TEST for adding parenthesis
+ around a lambda with ':' */
+ PyObject *temp_fv_str = expr_as_unicode(e, PR_TEST + 1);
+ if (!temp_fv_str) {
+ return -1;
+ }
+ int result = append_interpolation_str(writer, temp_fv_str);
+ Py_DECREF(temp_fv_str);
+ return result;
+}
+
+static int
append_interpolation_conversion(PyUnicodeWriter *writer, int conversion)
{
if (conversion < 0) {
@@ -843,7 +856,7 @@ append_interpolation_format_spec(PyUnicodeWriter *writer, expr_ty e)
static int
append_interpolation(PyUnicodeWriter *writer, expr_ty e)
{
- if (-1 == append_interpolation_value(writer, e->v.Interpolation.value)) {
+ if (-1 == append_interpolation_str(writer, e->v.Interpolation.str)) {
return -1;
}
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 6a076662640..42e4f581894 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -4041,6 +4041,10 @@ dummy_func(
DEOPT_IF(!PyStackRef_IsNull(null));
}
+ op(_GUARD_THIRD_NULL, (null, unused, unused -- null, unused, unused)) {
+ DEOPT_IF(!PyStackRef_IsNull(null));
+ }
+
op(_GUARD_CALLABLE_TYPE_1, (callable, unused, unused -- callable, unused, unused)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
DEOPT_IF(callable_o != (PyObject *)&PyType_Type);
@@ -4359,31 +4363,37 @@ dummy_func(
res = PyStackRef_FromPyObjectSteal(res_o);
}
- inst(CALL_ISINSTANCE, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) {
- /* isinstance(o, o2) */
+ op(_GUARD_CALLABLE_ISINSTANCE, (callable, unused, unused, unused -- callable, unused, unused, unused)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
-
- int total_args = oparg;
- _PyStackRef *arguments = args;
- if (!PyStackRef_IsNull(self_or_null)) {
- arguments--;
- total_args++;
- }
- DEOPT_IF(total_args != 2);
PyInterpreterState *interp = tstate->interp;
DEOPT_IF(callable_o != interp->callable_cache.isinstance);
+ }
+
+ op(_CALL_ISINSTANCE, (callable, null, instance, cls -- res)) {
+ /* isinstance(o, o2) */
STAT_INC(CALL, hit);
- _PyStackRef cls_stackref = arguments[1];
- _PyStackRef inst_stackref = arguments[0];
- int retval = PyObject_IsInstance(PyStackRef_AsPyObjectBorrow(inst_stackref), PyStackRef_AsPyObjectBorrow(cls_stackref));
+ PyObject *inst_o = PyStackRef_AsPyObjectBorrow(instance);
+ PyObject *cls_o = PyStackRef_AsPyObjectBorrow(cls);
+ int retval = PyObject_IsInstance(inst_o, cls_o);
if (retval < 0) {
ERROR_NO_POP();
}
+ (void)null; // Silence compiler warnings about unused variables
+ PyStackRef_CLOSE(cls);
+ PyStackRef_CLOSE(instance);
+ DEAD(null);
+ PyStackRef_CLOSE(callable);
res = retval ? PyStackRef_True : PyStackRef_False;
assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL));
- DECREF_INPUTS();
}
+ macro(CALL_ISINSTANCE) =
+ unused/1 +
+ unused/2 +
+ _GUARD_THIRD_NULL +
+ _GUARD_CALLABLE_ISINSTANCE +
+ _CALL_ISINSTANCE;
+
// This is secretly a super-instruction
inst(CALL_LIST_APPEND, (unused/1, unused/2, callable, self, arg -- )) {
assert(oparg == 1);
diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c
index 5b5018a6373..6d2383ac7c1 100644
--- a/Python/ceval_gil.c
+++ b/Python/ceval_gil.c
@@ -1218,30 +1218,30 @@ static inline int run_remote_debugger_source(PyObject *source)
// Note that this function is inline to avoid creating a PLT entry
// that would be an easy target for a ROP gadget.
-static inline void run_remote_debugger_script(const char *path)
+static inline void run_remote_debugger_script(PyObject *path)
{
- if (0 != PySys_Audit("remote_debugger_script", "s", path)) {
+ if (0 != PySys_Audit("remote_debugger_script", "O", path)) {
PyErr_FormatUnraisable(
- "Audit hook failed for remote debugger script %s", path);
+ "Audit hook failed for remote debugger script %U", path);
return;
}
// Open the debugger script with the open code hook, and reopen the
// resulting file object to get a C FILE* object.
- PyObject* fileobj = PyFile_OpenCode(path);
+ PyObject* fileobj = PyFile_OpenCodeObject(path);
if (!fileobj) {
- PyErr_FormatUnraisable("Can't open debugger script %s", path);
+ PyErr_FormatUnraisable("Can't open debugger script %U", path);
return;
}
PyObject* source = PyObject_CallMethodNoArgs(fileobj, &_Py_ID(read));
if (!source) {
- PyErr_FormatUnraisable("Error reading debugger script %s", path);
+ PyErr_FormatUnraisable("Error reading debugger script %U", path);
}
PyObject* res = PyObject_CallMethodNoArgs(fileobj, &_Py_ID(close));
if (!res) {
- PyErr_FormatUnraisable("Error closing debugger script %s", path);
+ PyErr_FormatUnraisable("Error closing debugger script %U", path);
} else {
Py_DECREF(res);
}
@@ -1249,7 +1249,7 @@ static inline void run_remote_debugger_script(const char *path)
if (source) {
if (0 != run_remote_debugger_source(source)) {
- PyErr_FormatUnraisable("Error executing debugger script %s", path);
+ PyErr_FormatUnraisable("Error executing debugger script %U", path);
}
Py_DECREF(source);
}
@@ -1278,7 +1278,14 @@ int _PyRunRemoteDebugger(PyThreadState *tstate)
pathsz);
path[pathsz - 1] = '\0';
if (*path) {
- run_remote_debugger_script(path);
+ PyObject *path_obj = PyUnicode_DecodeFSDefault(path);
+ if (path_obj == NULL) {
+ PyErr_FormatUnraisable("Can't decode debugger script");
+ }
+ else {
+ run_remote_debugger_script(path_obj);
+ Py_DECREF(path_obj);
+ }
}
PyMem_Free(path);
}
diff --git a/Python/crossinterp.c b/Python/crossinterp.c
index 74ce02f1a26..725d6009f84 100644
--- a/Python/crossinterp.c
+++ b/Python/crossinterp.c
@@ -6,8 +6,11 @@
#include "osdefs.h" // MAXPATHLEN
#include "pycore_ceval.h" // _Py_simple_func
#include "pycore_crossinterp.h" // _PyXIData_t
+#include "pycore_function.h" // _PyFunction_VerifyStateless()
#include "pycore_initconfig.h" // _PyStatus_OK()
#include "pycore_namespace.h" // _PyNamespace_New()
+#include "pycore_pythonrun.h" // _Py_SourceAsString()
+#include "pycore_setobject.h" // _PySet_NextEntry()
#include "pycore_typeobject.h" // _PyStaticType_InitBuiltin()
@@ -784,6 +787,131 @@ _PyMarshal_GetXIData(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
}
+/* script wrapper */
+
+static int
+verify_script(PyThreadState *tstate, PyCodeObject *co, int checked, int pure)
+{
+ // Make sure it isn't a closure and (optionally) doesn't use globals.
+ PyObject *builtins = NULL;
+ if (pure) {
+ builtins = _PyEval_GetBuiltins(tstate);
+ assert(builtins != NULL);
+ }
+ if (checked) {
+ assert(_PyCode_VerifyStateless(tstate, co, NULL, NULL, builtins) == 0);
+ }
+ else if (_PyCode_VerifyStateless(tstate, co, NULL, NULL, builtins) < 0) {
+ return -1;
+ }
+ // Make sure it doesn't have args.
+ if (co->co_argcount > 0
+ || co->co_posonlyargcount > 0
+ || co->co_kwonlyargcount > 0
+ || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS))
+ {
+ _PyErr_SetString(tstate, PyExc_ValueError,
+ "code with args not supported");
+ return -1;
+ }
+ // Make sure it doesn't return anything.
+ if (!_PyCode_ReturnsOnlyNone(co)) {
+ _PyErr_SetString(tstate, PyExc_ValueError,
+ "code that returns a value is not a script");
+ return -1;
+ }
+ return 0;
+}
+
+static int
+get_script_xidata(PyThreadState *tstate, PyObject *obj, int pure,
+ _PyXIData_t *xidata)
+{
+ // Get the corresponding code object.
+ PyObject *code = NULL;
+ int checked = 0;
+ if (PyCode_Check(obj)) {
+ code = obj;
+ Py_INCREF(code);
+ }
+ else if (PyFunction_Check(obj)) {
+ code = PyFunction_GET_CODE(obj);
+ assert(code != NULL);
+ Py_INCREF(code);
+ if (pure) {
+ if (_PyFunction_VerifyStateless(tstate, obj) < 0) {
+ goto error;
+ }
+ checked = 1;
+ }
+ }
+ else {
+ const char *filename = "<script>";
+ int optimize = 0;
+ PyCompilerFlags cf = _PyCompilerFlags_INIT;
+ cf.cf_flags = PyCF_SOURCE_IS_UTF8;
+ PyObject *ref = NULL;
+ const char *script = _Py_SourceAsString(obj, "???", "???", &cf, &ref);
+ if (script == NULL) {
+ if (!_PyObject_SupportedAsScript(obj)) {
+ // We discard the raised exception.
+ _PyErr_Format(tstate, PyExc_TypeError,
+ "unsupported script %R", obj);
+ }
+ goto error;
+ }
+ code = Py_CompileStringExFlags(
+ script, filename, Py_file_input, &cf, optimize);
+ Py_XDECREF(ref);
+ if (code == NULL) {
+ goto error;
+ }
+ // Compiled text can't have args or any return statements,
+ // nor be a closure. It can use globals though.
+ if (!pure) {
+ // We don't need to check for globals either.
+ checked = 1;
+ }
+ }
+
+ // Make sure it's actually a script.
+ if (verify_script(tstate, (PyCodeObject *)code, checked, pure) < 0) {
+ goto error;
+ }
+
+ // Convert the code object.
+ int res = _PyCode_GetXIData(tstate, code, xidata);
+ Py_DECREF(code);
+ if (res < 0) {
+ return -1;
+ }
+ return 0;
+
+error:
+ Py_XDECREF(code);
+ PyObject *cause = _PyErr_GetRaisedException(tstate);
+ assert(cause != NULL);
+ _set_xid_lookup_failure(
+ tstate, NULL, "object not a valid script", cause);
+ Py_DECREF(cause);
+ return -1;
+}
+
+int
+_PyCode_GetScriptXIData(PyThreadState *tstate,
+ PyObject *obj, _PyXIData_t *xidata)
+{
+ return get_script_xidata(tstate, obj, 0, xidata);
+}
+
+int
+_PyCode_GetPureScriptXIData(PyThreadState *tstate,
+ PyObject *obj, _PyXIData_t *xidata)
+{
+ return get_script_xidata(tstate, obj, 1, xidata);
+}
+
+
/* using cross-interpreter data */
PyObject *
diff --git a/Python/crossinterp_data_lookup.h b/Python/crossinterp_data_lookup.h
index 231537c66d7..d69927dbcd3 100644
--- a/Python/crossinterp_data_lookup.h
+++ b/Python/crossinterp_data_lookup.h
@@ -677,6 +677,60 @@ _PyCode_GetXIData(PyThreadState *tstate, PyObject *obj, _PyXIData_t *xidata)
return 0;
}
+// function
+
+PyObject *
+_PyFunction_FromXIData(_PyXIData_t *xidata)
+{
+ // For now "stateless" functions are the only ones we must accommodate.
+
+ PyObject *code = _PyMarshal_ReadObjectFromXIData(xidata);
+ if (code == NULL) {
+ return NULL;
+ }
+ // Create a new function.
+ assert(PyCode_Check(code));
+ PyObject *globals = PyDict_New();
+ if (globals == NULL) {
+ Py_DECREF(code);
+ return NULL;
+ }
+ PyObject *func = PyFunction_New(code, globals);
+ Py_DECREF(code);
+ Py_DECREF(globals);
+ return func;
+}
+
+int
+_PyFunction_GetXIData(PyThreadState *tstate, PyObject *func,
+ _PyXIData_t *xidata)
+{
+ if (!PyFunction_Check(func)) {
+ const char *msg = "expected a function, got %R";
+ format_notshareableerror(tstate, NULL, 0, msg, func);
+ return -1;
+ }
+ if (_PyFunction_VerifyStateless(tstate, func) < 0) {
+ PyObject *cause = _PyErr_GetRaisedException(tstate);
+ assert(cause != NULL);
+ const char *msg = "only stateless functions are shareable";
+ set_notshareableerror(tstate, cause, 0, msg);
+ Py_DECREF(cause);
+ return -1;
+ }
+ PyObject *code = PyFunction_GET_CODE(func);
+
+ // Ideally code objects would be immortal and directly shareable.
+ // In the meantime, we use marshal.
+ if (_PyMarshal_GetXIData(tstate, code, xidata) < 0) {
+ return -1;
+ }
+ // Replace _PyMarshal_ReadObjectFromXIData.
+ // (_PyFunction_FromXIData() will call it.)
+ _PyXIData_SET_NEW_OBJECT(xidata, _PyFunction_FromXIData);
+ return 0;
+}
+
// registration
@@ -717,4 +771,6 @@ _register_builtins_for_crossinterpreter_data(dlregistry_t *xidregistry)
if (_xidregistry_add_type(xidregistry, &PyTuple_Type, _tuple_shared) != 0) {
Py_FatalError("could not register tuple for cross-interpreter sharing");
}
+
+ // For now, we do not register PyCode_Type or PyFunction_Type.
}
diff --git a/Python/dynload_win.c b/Python/dynload_win.c
index 6324063401e..de9b0a77817 100644
--- a/Python/dynload_win.c
+++ b/Python/dynload_win.c
@@ -108,7 +108,7 @@ static char *GetPythonImport (HINSTANCE hModule)
char *pch;
/* Don't claim that python3.dll is a Python DLL. */
-#ifdef _DEBUG
+#ifdef Py_DEBUG
if (strcmp(import_name, "python3_d.dll") == 0) {
#else
if (strcmp(import_name, "python3.dll") == 0) {
@@ -120,7 +120,7 @@ static char *GetPythonImport (HINSTANCE hModule)
/* Ensure python prefix is followed only
by numbers to the end of the basename */
pch = import_name + 6;
-#ifdef _DEBUG
+#ifdef Py_DEBUG
while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') {
#else
while (*pch && *pch != '.') {
@@ -300,7 +300,7 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix,
char buffer[256];
PyOS_snprintf(buffer, sizeof(buffer),
-#ifdef _DEBUG
+#ifdef Py_DEBUG
"python%d%d_d.dll",
#else
"python%d%d.dll",
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 3e51ac41fa3..41c9bd5ba70 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -5276,6 +5276,16 @@
break;
}
+ case _GUARD_THIRD_NULL: {
+ _PyStackRef null;
+ null = stack_pointer[-3];
+ if (!PyStackRef_IsNull(null)) {
+ UOP_STAT_INC(uopcode, miss);
+ JUMP_TO_JUMP_TARGET();
+ }
+ break;
+ }
+
case _GUARD_CALLABLE_TYPE_1: {
_PyStackRef callable;
callable = stack_pointer[-3];
@@ -5855,58 +5865,57 @@
break;
}
- case _CALL_ISINSTANCE: {
- _PyStackRef *args;
- _PyStackRef self_or_null;
+ case _GUARD_CALLABLE_ISINSTANCE: {
_PyStackRef callable;
- _PyStackRef res;
- oparg = CURRENT_OPARG();
- args = &stack_pointer[-oparg];
- self_or_null = stack_pointer[-1 - oparg];
- callable = stack_pointer[-2 - oparg];
+ callable = stack_pointer[-4];
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
- int total_args = oparg;
- _PyStackRef *arguments = args;
- if (!PyStackRef_IsNull(self_or_null)) {
- arguments--;
- total_args++;
- }
- if (total_args != 2) {
- UOP_STAT_INC(uopcode, miss);
- JUMP_TO_JUMP_TARGET();
- }
PyInterpreterState *interp = tstate->interp;
if (callable_o != interp->callable_cache.isinstance) {
UOP_STAT_INC(uopcode, miss);
JUMP_TO_JUMP_TARGET();
}
+ break;
+ }
+
+ case _CALL_ISINSTANCE: {
+ _PyStackRef cls;
+ _PyStackRef instance;
+ _PyStackRef null;
+ _PyStackRef callable;
+ _PyStackRef res;
+ cls = stack_pointer[-1];
+ instance = stack_pointer[-2];
+ null = stack_pointer[-3];
+ callable = stack_pointer[-4];
STAT_INC(CALL, hit);
- _PyStackRef cls_stackref = arguments[1];
- _PyStackRef inst_stackref = arguments[0];
+ PyObject *inst_o = PyStackRef_AsPyObjectBorrow(instance);
+ PyObject *cls_o = PyStackRef_AsPyObjectBorrow(cls);
_PyFrame_SetStackPointer(frame, stack_pointer);
- int retval = PyObject_IsInstance(PyStackRef_AsPyObjectBorrow(inst_stackref), PyStackRef_AsPyObjectBorrow(cls_stackref));
+ int retval = PyObject_IsInstance(inst_o, cls_o);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (retval < 0) {
JUMP_TO_ERROR();
}
- res = retval ? PyStackRef_True : PyStackRef_False;
- assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL));
+ (void)null;
+ stack_pointer += -1;
+ assert(WITHIN_STACK_BOUNDS());
_PyFrame_SetStackPointer(frame, stack_pointer);
- _PyStackRef tmp = callable;
- callable = res;
- stack_pointer[-2 - oparg] = callable;
- PyStackRef_CLOSE(tmp);
- for (int _i = oparg; --_i >= 0;) {
- tmp = args[_i];
- args[_i] = PyStackRef_NULL;
- PyStackRef_CLOSE(tmp);
- }
- tmp = self_or_null;
- self_or_null = PyStackRef_NULL;
- stack_pointer[-1 - oparg] = self_or_null;
- PyStackRef_XCLOSE(tmp);
+ PyStackRef_CLOSE(cls);
stack_pointer = _PyFrame_GetStackPointer(frame);
- stack_pointer += -1 - oparg;
+ stack_pointer += -1;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_CLOSE(instance);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ stack_pointer += -2;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_CLOSE(callable);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ res = retval ? PyStackRef_True : PyStackRef_False;
+ assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL));
+ stack_pointer[0] = res;
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
break;
}
diff --git a/Python/fileutils.c b/Python/fileutils.c
index 78603d40704..2a3f12d4e87 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -2784,6 +2784,43 @@ error:
return -1;
}
#else /* MS_WINDOWS */
+
+// The Windows Games API family doesn't expose GetNamedPipeHandleStateW so attempt
+// to load it directly from the Kernel32.dll
+#if !defined(MS_WINDOWS_APP) && !defined(MS_WINDOWS_SYSTEM)
+BOOL
+GetNamedPipeHandleStateW(HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount,
+ LPDWORD lpCollectDataTimeout, LPWSTR lpUserName, DWORD nMaxUserNameSize)
+{
+ static int initialized = 0;
+ typedef BOOL(__stdcall* PGetNamedPipeHandleStateW) (
+ HANDLE hNamedPipe, LPDWORD lpState, LPDWORD lpCurInstances, LPDWORD lpMaxCollectionCount,
+ LPDWORD lpCollectDataTimeout, LPWSTR lpUserName, DWORD nMaxUserNameSize);
+ static PGetNamedPipeHandleStateW _GetNamedPipeHandleStateW;
+
+ if (initialized == 0) {
+ HMODULE api = LoadLibraryExW(L"Kernel32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+ if (api) {
+ _GetNamedPipeHandleStateW = (PGetNamedPipeHandleStateW)GetProcAddress(
+ api, "GetNamedPipeHandleStateW");
+ }
+ else {
+ _GetNamedPipeHandleStateW = NULL;
+ }
+ initialized = 1;
+ }
+
+ if (!_GetNamedPipeHandleStateW) {
+ SetLastError(E_NOINTERFACE);
+ return FALSE;
+ }
+
+ return _GetNamedPipeHandleStateW(
+ hNamedPipe, lpState, lpCurInstances, lpMaxCollectionCount, lpCollectDataTimeout, lpUserName, nMaxUserNameSize
+ );
+}
+#endif /* !MS_WINDOWS_APP && !MS_WINDOWS_SYSTEM */
+
int
_Py_get_blocking(int fd)
{
diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c
index 757e9cb3227..d2ea5b5e06b 100644
--- a/Python/gc_free_threading.c
+++ b/Python/gc_free_threading.c
@@ -1927,8 +1927,7 @@ get_process_mem_usage(void)
}
#elif __linux__
- // Linux, use smaps_rollup (Kernel >= 4.4) for RSS + Swap
- FILE* fp = fopen("/proc/self/smaps_rollup", "r");
+ FILE* fp = fopen("/proc/self/status", "r");
if (fp == NULL) {
return -1;
}
@@ -1938,11 +1937,11 @@ get_process_mem_usage(void)
long long swap_kb = -1;
while (fgets(line_buffer, sizeof(line_buffer), fp) != NULL) {
- if (rss_kb == -1 && strncmp(line_buffer, "Rss:", 4) == 0) {
- sscanf(line_buffer + 4, "%lld", &rss_kb);
+ if (rss_kb == -1 && strncmp(line_buffer, "VmRSS:", 6) == 0) {
+ sscanf(line_buffer + 6, "%lld", &rss_kb);
}
- else if (swap_kb == -1 && strncmp(line_buffer, "Swap:", 5) == 0) {
- sscanf(line_buffer + 5, "%lld", &swap_kb);
+ else if (swap_kb == -1 && strncmp(line_buffer, "VmSwap:", 7) == 0) {
+ sscanf(line_buffer + 7, "%lld", &swap_kb);
}
if (rss_kb != -1 && swap_kb != -1) {
break; // Found both
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 7e8b05b747e..b3f2a2067f7 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -2777,60 +2777,67 @@
next_instr += 4;
INSTRUCTION_STATS(CALL_ISINSTANCE);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
+ _PyStackRef null;
_PyStackRef callable;
- _PyStackRef self_or_null;
- _PyStackRef *args;
+ _PyStackRef instance;
+ _PyStackRef cls;
_PyStackRef res;
/* Skip 1 cache entry */
/* Skip 2 cache entries */
- args = &stack_pointer[-oparg];
- self_or_null = stack_pointer[-1 - oparg];
- callable = stack_pointer[-2 - oparg];
- PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
- int total_args = oparg;
- _PyStackRef *arguments = args;
- if (!PyStackRef_IsNull(self_or_null)) {
- arguments--;
- total_args++;
- }
- if (total_args != 2) {
- UPDATE_MISS_STATS(CALL);
- assert(_PyOpcode_Deopt[opcode] == (CALL));
- JUMP_TO_PREDICTED(CALL);
- }
- PyInterpreterState *interp = tstate->interp;
- if (callable_o != interp->callable_cache.isinstance) {
- UPDATE_MISS_STATS(CALL);
- assert(_PyOpcode_Deopt[opcode] == (CALL));
- JUMP_TO_PREDICTED(CALL);
+ // _GUARD_THIRD_NULL
+ {
+ null = stack_pointer[-3];
+ if (!PyStackRef_IsNull(null)) {
+ UPDATE_MISS_STATS(CALL);
+ assert(_PyOpcode_Deopt[opcode] == (CALL));
+ JUMP_TO_PREDICTED(CALL);
+ }
}
- STAT_INC(CALL, hit);
- _PyStackRef cls_stackref = arguments[1];
- _PyStackRef inst_stackref = arguments[0];
- _PyFrame_SetStackPointer(frame, stack_pointer);
- int retval = PyObject_IsInstance(PyStackRef_AsPyObjectBorrow(inst_stackref), PyStackRef_AsPyObjectBorrow(cls_stackref));
- stack_pointer = _PyFrame_GetStackPointer(frame);
- if (retval < 0) {
- JUMP_TO_LABEL(error);
+ // _GUARD_CALLABLE_ISINSTANCE
+ {
+ callable = stack_pointer[-4];
+ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
+ PyInterpreterState *interp = tstate->interp;
+ if (callable_o != interp->callable_cache.isinstance) {
+ UPDATE_MISS_STATS(CALL);
+ assert(_PyOpcode_Deopt[opcode] == (CALL));
+ JUMP_TO_PREDICTED(CALL);
+ }
}
- res = retval ? PyStackRef_True : PyStackRef_False;
- assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL));
- _PyFrame_SetStackPointer(frame, stack_pointer);
- _PyStackRef tmp = callable;
- callable = res;
- stack_pointer[-2 - oparg] = callable;
- PyStackRef_CLOSE(tmp);
- for (int _i = oparg; --_i >= 0;) {
- tmp = args[_i];
- args[_i] = PyStackRef_NULL;
- PyStackRef_CLOSE(tmp);
+ // _CALL_ISINSTANCE
+ {
+ cls = stack_pointer[-1];
+ instance = stack_pointer[-2];
+ STAT_INC(CALL, hit);
+ PyObject *inst_o = PyStackRef_AsPyObjectBorrow(instance);
+ PyObject *cls_o = PyStackRef_AsPyObjectBorrow(cls);
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ int retval = PyObject_IsInstance(inst_o, cls_o);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ if (retval < 0) {
+ JUMP_TO_LABEL(error);
+ }
+ (void)null;
+ stack_pointer += -1;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_CLOSE(cls);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ stack_pointer += -1;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_CLOSE(instance);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ stack_pointer += -2;
+ assert(WITHIN_STACK_BOUNDS());
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ PyStackRef_CLOSE(callable);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ res = retval ? PyStackRef_True : PyStackRef_False;
+ assert((!PyStackRef_IsNull(res)) ^ (_PyErr_Occurred(tstate) != NULL));
}
- tmp = self_or_null;
- self_or_null = PyStackRef_NULL;
- stack_pointer[-1 - oparg] = self_or_null;
- PyStackRef_XCLOSE(tmp);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- stack_pointer += -1 - oparg;
+ stack_pointer[0] = res;
+ stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
diff --git a/Python/import.c b/Python/import.c
index afdc28eda31..e7be1b90751 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -3434,8 +3434,10 @@ PyImport_ImportModule(const char *name)
* ImportError instead of blocking.
*
* Returns the module object with incremented ref count.
+ *
+ * Removed in 3.15, but kept for stable ABI compatibility.
*/
-PyObject *
+PyAPI_FUNC(PyObject *)
PyImport_ImportModuleNoBlock(const char *name)
{
if (PyErr_WarnEx(PyExc_DeprecationWarning,
@@ -3852,15 +3854,17 @@ PyImport_ImportModuleLevelObject(PyObject *name, PyObject *globals,
}
final_mod = import_get_module(tstate, to_return);
- Py_DECREF(to_return);
if (final_mod == NULL) {
if (!_PyErr_Occurred(tstate)) {
_PyErr_Format(tstate, PyExc_KeyError,
"%R not in sys.modules as expected",
to_return);
}
+ Py_DECREF(to_return);
goto error;
}
+
+ Py_DECREF(to_return);
}
}
else {
diff --git a/Python/initconfig.c b/Python/initconfig.c
index e8270911721..25e30aa648e 100644
--- a/Python/initconfig.c
+++ b/Python/initconfig.c
@@ -2962,8 +2962,6 @@ config_parse_cmdline(PyConfig *config, PyWideStringList *warnoptions,
/* option handled by _PyPreCmdline_Read() */
break;
- /* case 'J': reserved for Jython */
-
case 'O':
config->optimization_level++;
break;
diff --git a/Python/marshal.c b/Python/marshal.c
index b39c1a5b1ad..afbef6ee679 100644
--- a/Python/marshal.c
+++ b/Python/marshal.c
@@ -38,7 +38,7 @@ module marshal
* On Windows PGO builds, the r_object function overallocates its stack and
* can cause a stack overflow. We reduce the maximum depth for all Windows
* releases to protect against this.
- * #if defined(MS_WINDOWS) && defined(_DEBUG)
+ * #if defined(MS_WINDOWS) && defined(Py_DEBUG)
*/
#if defined(MS_WINDOWS)
# define MAX_MARSHAL_STACK_DEPTH 1000
diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c
index e99421a3aff..7c160cdcb0c 100644
--- a/Python/optimizer_bytecodes.c
+++ b/Python/optimizer_bytecodes.c
@@ -104,18 +104,18 @@ dummy_func(void) {
res = sym_new_null(ctx);
}
- op(_GUARD_TOS_INT, (tos -- tos)) {
- if (sym_matches_type(tos, &PyLong_Type)) {
+ op(_GUARD_TOS_INT, (value -- value)) {
+ if (sym_matches_type(value, &PyLong_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
}
- sym_set_type(tos, &PyLong_Type);
+ sym_set_type(value, &PyLong_Type);
}
- op(_GUARD_NOS_INT, (nos, unused -- nos, unused)) {
- if (sym_matches_type(nos, &PyLong_Type)) {
+ op(_GUARD_NOS_INT, (left, unused -- left, unused)) {
+ if (sym_matches_type(left, &PyLong_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
}
- sym_set_type(nos, &PyLong_Type);
+ sym_set_type(left, &PyLong_Type);
}
op(_GUARD_TYPE_VERSION, (type_version/2, owner -- owner)) {
@@ -141,25 +141,25 @@ dummy_func(void) {
}
}
- op(_GUARD_TOS_FLOAT, (tos -- tos)) {
- if (sym_matches_type(tos, &PyFloat_Type)) {
+ op(_GUARD_TOS_FLOAT, (value -- value)) {
+ if (sym_matches_type(value, &PyFloat_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
}
- sym_set_type(tos, &PyFloat_Type);
+ sym_set_type(value, &PyFloat_Type);
}
- op(_GUARD_NOS_FLOAT, (nos, unused -- nos, unused)) {
- if (sym_matches_type(nos, &PyFloat_Type)) {
+ op(_GUARD_NOS_FLOAT, (left, unused -- left, unused)) {
+ if (sym_matches_type(left, &PyFloat_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
}
- sym_set_type(nos, &PyFloat_Type);
+ sym_set_type(left, &PyFloat_Type);
}
- op(_BINARY_OP, (left, right -- res)) {
- bool lhs_int = sym_matches_type(left, &PyLong_Type);
- bool rhs_int = sym_matches_type(right, &PyLong_Type);
- bool lhs_float = sym_matches_type(left, &PyFloat_Type);
- bool rhs_float = sym_matches_type(right, &PyFloat_Type);
+ op(_BINARY_OP, (lhs, rhs -- res)) {
+ bool lhs_int = sym_matches_type(lhs, &PyLong_Type);
+ bool rhs_int = sym_matches_type(rhs, &PyLong_Type);
+ bool lhs_float = sym_matches_type(lhs, &PyFloat_Type);
+ bool rhs_float = sym_matches_type(rhs, &PyFloat_Type);
if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) {
// There's something other than an int or float involved:
res = sym_new_unknown(ctx);
@@ -185,11 +185,11 @@ dummy_func(void) {
// Case C:
res = sym_new_type(ctx, &PyFloat_Type);
}
- else if (!sym_is_const(ctx, right)) {
+ else if (!sym_is_const(ctx, rhs)) {
// Case A or B... can't know without the sign of the RHS:
res = sym_new_unknown(ctx);
}
- else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, right))) {
+ else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, rhs))) {
// Case B:
res = sym_new_type(ctx, &PyFloat_Type);
}
@@ -366,7 +366,7 @@ dummy_func(void) {
ctx->done = true;
}
- op(_BINARY_OP_SUBSCR_STR_INT, (left, right -- res)) {
+ op(_BINARY_OP_SUBSCR_STR_INT, (str_st, sub_st -- res)) {
res = sym_new_type(ctx, &PyUnicode_Type);
}
@@ -398,11 +398,11 @@ dummy_func(void) {
}
}
- op(_TO_BOOL_BOOL, (value -- res)) {
- int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
+ op(_TO_BOOL_BOOL, (value -- value)) {
+ int already_bool = optimize_to_bool(this_instr, ctx, value, &value);
if (!already_bool) {
sym_set_type(value, &PyBool_Type);
- res = sym_new_truthiness(ctx, value, true);
+ value = sym_new_truthiness(ctx, value, true);
}
}
@@ -493,20 +493,20 @@ dummy_func(void) {
res = sym_new_type(ctx, &PyBool_Type);
}
- op(_IS_OP, (left, right -- res)) {
- res = sym_new_type(ctx, &PyBool_Type);
+ op(_IS_OP, (left, right -- b)) {
+ b = sym_new_type(ctx, &PyBool_Type);
}
- op(_CONTAINS_OP, (left, right -- res)) {
- res = sym_new_type(ctx, &PyBool_Type);
+ op(_CONTAINS_OP, (left, right -- b)) {
+ b = sym_new_type(ctx, &PyBool_Type);
}
- op(_CONTAINS_OP_SET, (left, right -- res)) {
- res = sym_new_type(ctx, &PyBool_Type);
+ op(_CONTAINS_OP_SET, (left, right -- b)) {
+ b = sym_new_type(ctx, &PyBool_Type);
}
- op(_CONTAINS_OP_DICT, (left, right -- res)) {
- res = sym_new_type(ctx, &PyBool_Type);
+ op(_CONTAINS_OP_DICT, (left, right -- b)) {
+ b = sym_new_type(ctx, &PyBool_Type);
}
op(_LOAD_CONST, (-- value)) {
@@ -707,10 +707,10 @@ dummy_func(void) {
}
}
- op(_MAYBE_EXPAND_METHOD, (callable, self_or_null, args[oparg] -- func, maybe_self, args[oparg])) {
+ op(_MAYBE_EXPAND_METHOD, (callable, self_or_null, args[oparg] -- callable, self_or_null, args[oparg])) {
(void)args;
- func = sym_new_not_null(ctx);
- maybe_self = sym_new_not_null(ctx);
+ callable = sym_new_not_null(ctx);
+ self_or_null = sym_new_not_null(ctx);
}
op(_PY_FRAME_GENERAL, (callable, self_or_null, args[oparg] -- new_frame: _Py_UOpsAbstractFrame *)) {
@@ -730,14 +730,14 @@ dummy_func(void) {
ctx->done = true;
}
- op(_CHECK_AND_ALLOCATE_OBJECT, (type_version/2, callable, null, args[oparg] -- self, init, args[oparg])) {
+ 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;
- self = sym_new_not_null(ctx);
- init = sym_new_not_null(ctx);
+ callable = sym_new_not_null(ctx);
+ self_or_null = sym_new_not_null(ctx);
}
- op(_CREATE_INIT_FRAME, (self, init, args[oparg] -- init_frame: _Py_UOpsAbstractFrame *)) {
+ op(_CREATE_INIT_FRAME, (init, self, args[oparg] -- init_frame: _Py_UOpsAbstractFrame *)) {
init_frame = NULL;
ctx->done = true;
}
@@ -789,21 +789,23 @@ dummy_func(void) {
}
}
- op(_YIELD_VALUE, (unused -- res)) {
- res = sym_new_unknown(ctx);
+ op(_YIELD_VALUE, (unused -- value)) {
+ value = sym_new_unknown(ctx);
}
- op(_FOR_ITER_GEN_FRAME, ( -- )) {
+ op(_FOR_ITER_GEN_FRAME, (unused -- unused, gen_frame: _Py_UOpsAbstractFrame*)) {
+ gen_frame = NULL;
/* We are about to hit the end of the trace */
ctx->done = true;
}
- op(_SEND_GEN_FRAME, ( -- )) {
+ op(_SEND_GEN_FRAME, (unused, unused -- unused, gen_frame: _Py_UOpsAbstractFrame *)) {
+ gen_frame = NULL;
// We are about to hit the end of the trace:
ctx->done = true;
}
- op(_CHECK_STACK_SPACE, ( --)) {
+ op(_CHECK_STACK_SPACE, (unused, unused, unused[oparg] -- unused, unused, unused[oparg])) {
assert(corresponding_check_stack == NULL);
corresponding_check_stack = this_instr;
}
@@ -848,14 +850,16 @@ dummy_func(void) {
corresponding_check_stack = NULL;
}
- op(_UNPACK_SEQUENCE, (seq -- values[oparg])) {
+ op(_UNPACK_SEQUENCE, (seq -- values[oparg], top[0])) {
+ (void)top;
/* This has to be done manually */
for (int i = 0; i < oparg; i++) {
values[i] = sym_new_unknown(ctx);
}
}
- op(_UNPACK_EX, (seq -- values[oparg & 0xFF], unused, unused[oparg >> 8])) {
+ op(_UNPACK_EX, (seq -- values[oparg & 0xFF], unused, unused[oparg >> 8], top[0])) {
+ (void)top;
/* This has to be done manually */
int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1;
for (int i = 0; i < totalargs; i++) {
@@ -904,27 +908,27 @@ dummy_func(void) {
sym_set_const(flag, Py_False);
}
- op(_GUARD_IS_NONE_POP, (flag -- )) {
- if (sym_is_const(ctx, flag)) {
- PyObject *value = sym_get_const(ctx, flag);
+ op(_GUARD_IS_NONE_POP, (val -- )) {
+ if (sym_is_const(ctx, val)) {
+ PyObject *value = sym_get_const(ctx, val);
assert(value != NULL);
eliminate_pop_guard(this_instr, !Py_IsNone(value));
}
- else if (sym_has_type(flag)) {
- assert(!sym_matches_type(flag, &_PyNone_Type));
+ else if (sym_has_type(val)) {
+ assert(!sym_matches_type(val, &_PyNone_Type));
eliminate_pop_guard(this_instr, true);
}
- sym_set_const(flag, Py_None);
+ sym_set_const(val, Py_None);
}
- op(_GUARD_IS_NOT_NONE_POP, (flag -- )) {
- if (sym_is_const(ctx, flag)) {
- PyObject *value = sym_get_const(ctx, flag);
+ op(_GUARD_IS_NOT_NONE_POP, (val -- )) {
+ if (sym_is_const(ctx, val)) {
+ PyObject *value = sym_get_const(ctx, val);
assert(value != NULL);
eliminate_pop_guard(this_instr, Py_IsNone(value));
}
- else if (sym_has_type(flag)) {
- assert(!sym_matches_type(flag, &_PyNone_Type));
+ else if (sym_has_type(val)) {
+ assert(!sym_matches_type(val, &_PyNone_Type));
eliminate_pop_guard(this_instr, false);
}
}
@@ -969,7 +973,7 @@ dummy_func(void) {
list = sym_new_type(ctx, &PyList_Type);
}
- op(_BUILD_SLICE, (values[oparg] -- slice)) {
+ op(_BUILD_SLICE, (args[oparg] -- slice)) {
slice = sym_new_type(ctx, &PySlice_Type);
}
@@ -977,7 +981,7 @@ dummy_func(void) {
map = sym_new_type(ctx, &PyDict_Type);
}
- op(_BUILD_STRING, (values[oparg] -- str)) {
+ op(_BUILD_STRING, (pieces[oparg] -- str)) {
str = sym_new_type(ctx, &PyUnicode_Type);
}
@@ -1063,6 +1067,13 @@ dummy_func(void) {
sym_set_null(null);
}
+ op(_GUARD_THIRD_NULL, (null, unused, unused -- null, unused, unused)) {
+ if (sym_is_null(null)) {
+ REPLACE_OP(this_instr, _NOP, 0, 0);
+ }
+ sym_set_null(null);
+ }
+
op(_GUARD_CALLABLE_TYPE_1, (callable, unused, unused -- callable, unused, unused)) {
if (sym_get_const(ctx, callable) == (PyObject *)&PyType_Type) {
REPLACE_OP(this_instr, _NOP, 0, 0);
@@ -1096,6 +1107,14 @@ dummy_func(void) {
sym_set_const(callable, len);
}
+ op(_GUARD_CALLABLE_ISINSTANCE, (callable, unused, unused, unused -- callable, unused, unused, unused)) {
+ PyObject *isinstance = _PyInterpreterState_GET()->callable_cache.isinstance;
+ if (sym_get_const(ctx, callable) == isinstance) {
+ REPLACE_OP(this_instr, _NOP, 0, 0);
+ }
+ sym_set_const(callable, isinstance);
+ }
+
// END BYTECODES //
}
diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h
index 56b4b9983fb..deb912662e4 100644
--- a/Python/optimizer_cases.c.h
+++ b/Python/optimizer_cases.c.h
@@ -171,14 +171,13 @@
case _TO_BOOL_BOOL: {
JitOptSymbol *value;
- JitOptSymbol *res;
value = stack_pointer[-1];
- int already_bool = optimize_to_bool(this_instr, ctx, value, &res);
+ int already_bool = optimize_to_bool(this_instr, ctx, value, &value);
if (!already_bool) {
sym_set_type(value, &PyBool_Type);
- res = sym_new_truthiness(ctx, value, true);
+ value = sym_new_truthiness(ctx, value, true);
}
- stack_pointer[-1] = res;
+ stack_pointer[-1] = value;
break;
}
@@ -292,22 +291,22 @@
}
case _GUARD_NOS_INT: {
- JitOptSymbol *nos;
- nos = stack_pointer[-2];
- if (sym_matches_type(nos, &PyLong_Type)) {
+ JitOptSymbol *left;
+ left = stack_pointer[-2];
+ if (sym_matches_type(left, &PyLong_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
}
- sym_set_type(nos, &PyLong_Type);
+ sym_set_type(left, &PyLong_Type);
break;
}
case _GUARD_TOS_INT: {
- JitOptSymbol *tos;
- tos = stack_pointer[-1];
- if (sym_matches_type(tos, &PyLong_Type)) {
+ JitOptSymbol *value;
+ value = stack_pointer[-1];
+ if (sym_matches_type(value, &PyLong_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
}
- sym_set_type(tos, &PyLong_Type);
+ sym_set_type(value, &PyLong_Type);
break;
}
@@ -396,22 +395,22 @@
}
case _GUARD_NOS_FLOAT: {
- JitOptSymbol *nos;
- nos = stack_pointer[-2];
- if (sym_matches_type(nos, &PyFloat_Type)) {
+ JitOptSymbol *left;
+ left = stack_pointer[-2];
+ if (sym_matches_type(left, &PyFloat_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
}
- sym_set_type(nos, &PyFloat_Type);
+ sym_set_type(left, &PyFloat_Type);
break;
}
case _GUARD_TOS_FLOAT: {
- JitOptSymbol *tos;
- tos = stack_pointer[-1];
- if (sym_matches_type(tos, &PyFloat_Type)) {
+ JitOptSymbol *value;
+ value = stack_pointer[-1];
+ if (sym_matches_type(value, &PyFloat_Type)) {
REPLACE_OP(this_instr, _NOP, 0, 0);
}
- sym_set_type(tos, &PyFloat_Type);
+ sym_set_type(value, &PyFloat_Type);
break;
}
@@ -811,14 +810,17 @@
/* _SEND is not a viable micro-op for tier 2 */
case _SEND_GEN_FRAME: {
+ _Py_UOpsAbstractFrame *gen_frame;
+ gen_frame = NULL;
ctx->done = true;
+ stack_pointer[-1] = (JitOptSymbol *)gen_frame;
break;
}
case _YIELD_VALUE: {
- JitOptSymbol *res;
- res = sym_new_unknown(ctx);
- stack_pointer[-1] = res;
+ JitOptSymbol *value;
+ value = sym_new_unknown(ctx);
+ stack_pointer[-1] = value;
break;
}
@@ -858,7 +860,10 @@
case _UNPACK_SEQUENCE: {
JitOptSymbol **values;
+ JitOptSymbol **top;
values = &stack_pointer[-1];
+ top = &stack_pointer[-1 + oparg];
+ (void)top;
for (int i = 0; i < oparg; i++) {
values[i] = sym_new_unknown(ctx);
}
@@ -907,7 +912,10 @@
case _UNPACK_EX: {
JitOptSymbol **values;
+ JitOptSymbol **top;
values = &stack_pointer[-1];
+ top = &stack_pointer[(oparg & 0xFF) + (oparg >> 8)];
+ (void)top;
int totalargs = (oparg & 0xFF) + (oparg >> 8) + 1;
for (int i = 0; i < totalargs; i++) {
values[i] = sym_new_unknown(ctx);
@@ -1376,18 +1384,18 @@
}
case _IS_OP: {
- JitOptSymbol *res;
- res = sym_new_type(ctx, &PyBool_Type);
- stack_pointer[-2] = res;
+ JitOptSymbol *b;
+ b = sym_new_type(ctx, &PyBool_Type);
+ stack_pointer[-2] = b;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _CONTAINS_OP: {
- JitOptSymbol *res;
- res = sym_new_type(ctx, &PyBool_Type);
- stack_pointer[-2] = res;
+ JitOptSymbol *b;
+ b = sym_new_type(ctx, &PyBool_Type);
+ stack_pointer[-2] = b;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -1405,18 +1413,18 @@
}
case _CONTAINS_OP_SET: {
- JitOptSymbol *res;
- res = sym_new_type(ctx, &PyBool_Type);
- stack_pointer[-2] = res;
+ JitOptSymbol *b;
+ b = sym_new_type(ctx, &PyBool_Type);
+ stack_pointer[-2] = b;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _CONTAINS_OP_DICT: {
- JitOptSymbol *res;
- res = sym_new_type(ctx, &PyBool_Type);
- stack_pointer[-2] = res;
+ JitOptSymbol *b;
+ b = sym_new_type(ctx, &PyBool_Type);
+ stack_pointer[-2] = b;
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
break;
@@ -1600,7 +1608,12 @@
}
case _FOR_ITER_GEN_FRAME: {
+ _Py_UOpsAbstractFrame *gen_frame;
+ gen_frame = NULL;
ctx->done = true;
+ stack_pointer[0] = (JitOptSymbol *)gen_frame;
+ stack_pointer += 1;
+ assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -1721,15 +1734,16 @@
case _MAYBE_EXPAND_METHOD: {
JitOptSymbol **args;
- JitOptSymbol *func;
- JitOptSymbol *maybe_self;
- args = &stack_pointer[-oparg];
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
args = &stack_pointer[-oparg];
+ self_or_null = stack_pointer[-1 - oparg];
+ callable = stack_pointer[-2 - oparg];
(void)args;
- func = sym_new_not_null(ctx);
- maybe_self = sym_new_not_null(ctx);
- stack_pointer[-2 - oparg] = func;
- stack_pointer[-1 - oparg] = maybe_self;
+ callable = sym_new_not_null(ctx);
+ self_or_null = sym_new_not_null(ctx);
+ stack_pointer[-2 - oparg] = callable;
+ stack_pointer[-1 - oparg] = self_or_null;
break;
}
@@ -1921,6 +1935,16 @@
break;
}
+ case _GUARD_THIRD_NULL: {
+ JitOptSymbol *null;
+ null = stack_pointer[-3];
+ if (sym_is_null(null)) {
+ REPLACE_OP(this_instr, _NOP, 0, 0);
+ }
+ sym_set_null(null);
+ break;
+ }
+
case _GUARD_CALLABLE_TYPE_1: {
JitOptSymbol *callable;
callable = stack_pointer[-3];
@@ -2001,17 +2025,18 @@
case _CHECK_AND_ALLOCATE_OBJECT: {
JitOptSymbol **args;
- JitOptSymbol *self;
- JitOptSymbol *init;
- args = &stack_pointer[-oparg];
+ JitOptSymbol *self_or_null;
+ JitOptSymbol *callable;
args = &stack_pointer[-oparg];
+ 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;
- self = sym_new_not_null(ctx);
- init = sym_new_not_null(ctx);
- stack_pointer[-2 - oparg] = self;
- stack_pointer[-1 - oparg] = init;
+ callable = sym_new_not_null(ctx);
+ self_or_null = sym_new_not_null(ctx);
+ stack_pointer[-2 - oparg] = callable;
+ stack_pointer[-1 - oparg] = self_or_null;
break;
}
@@ -2087,11 +2112,22 @@
break;
}
+ case _GUARD_CALLABLE_ISINSTANCE: {
+ JitOptSymbol *callable;
+ callable = stack_pointer[-4];
+ PyObject *isinstance = _PyInterpreterState_GET()->callable_cache.isinstance;
+ if (sym_get_const(ctx, callable) == isinstance) {
+ REPLACE_OP(this_instr, _NOP, 0, 0);
+ }
+ sym_set_const(callable, isinstance);
+ break;
+ }
+
case _CALL_ISINSTANCE: {
JitOptSymbol *res;
res = sym_new_not_null(ctx);
- stack_pointer[-2 - oparg] = res;
- stack_pointer += -1 - oparg;
+ stack_pointer[-4] = res;
+ stack_pointer += -3;
assert(WITHIN_STACK_BOUNDS());
break;
}
@@ -2270,15 +2306,15 @@
}
case _BINARY_OP: {
- JitOptSymbol *right;
- JitOptSymbol *left;
- JitOptSymbol *res;
- right = stack_pointer[-1];
- left = stack_pointer[-2];
- bool lhs_int = sym_matches_type(left, &PyLong_Type);
- bool rhs_int = sym_matches_type(right, &PyLong_Type);
- bool lhs_float = sym_matches_type(left, &PyFloat_Type);
- bool rhs_float = sym_matches_type(right, &PyFloat_Type);
+ JitOptSymbol *rhs;
+ JitOptSymbol *lhs;
+ JitOptSymbol *res;
+ rhs = stack_pointer[-1];
+ lhs = stack_pointer[-2];
+ bool lhs_int = sym_matches_type(lhs, &PyLong_Type);
+ bool rhs_int = sym_matches_type(rhs, &PyLong_Type);
+ bool lhs_float = sym_matches_type(lhs, &PyFloat_Type);
+ bool rhs_float = sym_matches_type(rhs, &PyFloat_Type);
if (!((lhs_int || lhs_float) && (rhs_int || rhs_float))) {
res = sym_new_unknown(ctx);
}
@@ -2289,10 +2325,10 @@
else if (lhs_float) {
res = sym_new_type(ctx, &PyFloat_Type);
}
- else if (!sym_is_const(ctx, right)) {
+ else if (!sym_is_const(ctx, rhs)) {
res = sym_new_unknown(ctx);
}
- else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, right))) {
+ else if (_PyLong_IsNegative((PyLongObject *)sym_get_const(ctx, rhs))) {
res = sym_new_type(ctx, &PyFloat_Type);
}
else {
@@ -2375,33 +2411,33 @@
}
case _GUARD_IS_NONE_POP: {
- JitOptSymbol *flag;
- flag = stack_pointer[-1];
- if (sym_is_const(ctx, flag)) {
- PyObject *value = sym_get_const(ctx, flag);
+ JitOptSymbol *val;
+ val = stack_pointer[-1];
+ if (sym_is_const(ctx, val)) {
+ PyObject *value = sym_get_const(ctx, val);
assert(value != NULL);
eliminate_pop_guard(this_instr, !Py_IsNone(value));
}
- else if (sym_has_type(flag)) {
- assert(!sym_matches_type(flag, &_PyNone_Type));
+ else if (sym_has_type(val)) {
+ assert(!sym_matches_type(val, &_PyNone_Type));
eliminate_pop_guard(this_instr, true);
}
- sym_set_const(flag, Py_None);
+ sym_set_const(val, Py_None);
stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS());
break;
}
case _GUARD_IS_NOT_NONE_POP: {
- JitOptSymbol *flag;
- flag = stack_pointer[-1];
- if (sym_is_const(ctx, flag)) {
- PyObject *value = sym_get_const(ctx, flag);
+ JitOptSymbol *val;
+ val = stack_pointer[-1];
+ if (sym_is_const(ctx, val)) {
+ PyObject *value = sym_get_const(ctx, val);
assert(value != NULL);
eliminate_pop_guard(this_instr, Py_IsNone(value));
}
- else if (sym_has_type(flag)) {
- assert(!sym_matches_type(flag, &_PyNone_Type));
+ else if (sym_has_type(val)) {
+ assert(!sym_matches_type(val, &_PyNone_Type));
eliminate_pop_guard(this_instr, false);
}
stack_pointer += -1;
diff --git a/Python/pathconfig.c b/Python/pathconfig.c
index 92360c1bb02..d034562c43f 100644
--- a/Python/pathconfig.c
+++ b/Python/pathconfig.c
@@ -272,7 +272,8 @@ Py_SetProgramName(const wchar_t *program_name)
}
-wchar_t *
+/* removed in 3.15, but kept for stable ABI compatibility */
+PyAPI_FUNC(wchar_t *)
Py_GetPath(void)
{
/* If the user has provided a path, return that */
@@ -284,7 +285,7 @@ Py_GetPath(void)
}
-wchar_t *
+PyAPI_FUNC(wchar_t *)
_Py_GetStdlibDir(void)
{
wchar_t *stdlib_dir = _Py_path_config.stdlib_dir;
@@ -295,35 +296,40 @@ _Py_GetStdlibDir(void)
}
-wchar_t *
+/* removed in 3.15, but kept for stable ABI compatibility */
+PyAPI_FUNC(wchar_t *)
Py_GetPrefix(void)
{
return _Py_path_config.prefix;
}
-wchar_t *
+/* removed in 3.15, but kept for stable ABI compatibility */
+PyAPI_FUNC(wchar_t *)
Py_GetExecPrefix(void)
{
return _Py_path_config.exec_prefix;
}
-wchar_t *
+/* removed in 3.15, but kept for stable ABI compatibility */
+PyAPI_FUNC(wchar_t *)
Py_GetProgramFullPath(void)
{
return _Py_path_config.program_full_path;
}
-wchar_t*
+/* removed in 3.15, but kept for stable ABI compatibility */
+PyAPI_FUNC(wchar_t *)
Py_GetPythonHome(void)
{
return _Py_path_config.home;
}
-wchar_t *
+/* removed in 3.15, but kept for stable ABI compatibility */
+PyAPI_FUNC(wchar_t *)
Py_GetProgramName(void)
{
return _Py_path_config.program_name;
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index c4c1d9fd9e1..8394245d373 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -3144,7 +3144,7 @@ static inline void _Py_NO_RETURN
fatal_error_exit(int status)
{
if (status < 0) {
-#if defined(MS_WINDOWS) && defined(_DEBUG)
+#if defined(MS_WINDOWS) && defined(Py_DEBUG)
DebugBreak();
#endif
abort();
diff --git a/Python/pystate.c b/Python/pystate.c
index 1ac13440085..14ae2748b0b 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -1908,9 +1908,14 @@ tstate_delete_common(PyThreadState *tstate, int release_gil)
static void
zapthreads(PyInterpreterState *interp)
{
+ PyThreadState *tstate;
/* No need to lock the mutex here because this should only happen
- when the threads are all really dead (XXX famous last words). */
- _Py_FOR_EACH_TSTATE_UNLOCKED(interp, tstate) {
+ when the threads are all really dead (XXX famous last words).
+
+ Cannot use _Py_FOR_EACH_TSTATE_UNLOCKED because we are freeing
+ the thread states here.
+ */
+ while ((tstate = interp->threads.head) != NULL) {
tstate_verify_not_active(tstate);
tstate_delete_common(tstate, 0);
free_threadstate((_PyThreadStateImpl *)tstate);
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 4ee287af72f..f67b72aa91f 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -1524,6 +1524,26 @@ Py_CompileStringExFlags(const char *str, const char *filename_str, int start,
return co;
}
+int
+_PyObject_SupportedAsScript(PyObject *cmd)
+{
+ if (PyUnicode_Check(cmd)) {
+ return 1;
+ }
+ else if (PyBytes_Check(cmd)) {
+ return 1;
+ }
+ else if (PyByteArray_Check(cmd)) {
+ return 1;
+ }
+ else if (PyObject_CheckBuffer(cmd)) {
+ return 1;
+ }
+ else {
+ return 0;
+ }
+}
+
const char *
_Py_SourceAsString(PyObject *cmd, const char *funcname, const char *what, PyCompilerFlags *cf, PyObject **cmd_copy)
{
diff --git a/Python/specialize.c b/Python/specialize.c
index bbe725c8ec8..06995d46d8b 100644
--- a/Python/specialize.c
+++ b/Python/specialize.c
@@ -2158,7 +2158,7 @@ specialize_c_call(PyObject *callable, _Py_CODEUNIT *instr, int nargs)
if (nargs == 2) {
/* isinstance(o1, o2) */
PyInterpreterState *interp = _PyInterpreterState_GET();
- if (callable == interp->callable_cache.isinstance) {
+ if (callable == interp->callable_cache.isinstance && instr->op.arg == 2) {
specialize(instr, CALL_ISINSTANCE);
return 0;
}
diff --git a/Python/stackrefs.c b/Python/stackrefs.c
index 979a6b1c628..69d4e8b9431 100644
--- a/Python/stackrefs.c
+++ b/Python/stackrefs.c
@@ -1,4 +1,3 @@
-
#include "Python.h"
#include "pycore_object.h"
@@ -34,6 +33,7 @@ make_table_entry(PyObject *obj, const char *filename, int linenumber)
result->filename = filename;
result->linenumber = linenumber;
result->filename_borrow = NULL;
+ result->linenumber_borrow = 0;
return result;
}
diff --git a/Python/symtable.c b/Python/symtable.c
index f633e281019..a3d0fff80d2 100644
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -380,8 +380,8 @@ static void dump_symtable(PySTEntryObject* ste)
}
#endif
-#define DUPLICATE_ARGUMENT \
-"duplicate argument '%U' in function definition"
+#define DUPLICATE_PARAMETER \
+"duplicate parameter '%U' in function definition"
static struct symtable *
symtable_new(void)
@@ -1494,7 +1494,7 @@ symtable_add_def_helper(struct symtable *st, PyObject *name, int flag, struct _s
}
if ((flag & DEF_PARAM) && (val & DEF_PARAM)) {
/* Is it better to use 'mangled' or 'name' here? */
- PyErr_Format(PyExc_SyntaxError, DUPLICATE_ARGUMENT, name);
+ PyErr_Format(PyExc_SyntaxError, DUPLICATE_PARAMETER, name);
SET_ERROR_LOCATION(st->st_filename, loc);
goto error;
}
diff --git a/Python/sysmodule.c b/Python/sysmodule.c
index 00dce4527fb..4ed045e3297 100644
--- a/Python/sysmodule.c
+++ b/Python/sysmodule.c
@@ -1643,6 +1643,7 @@ static PyObject *
_sys_getwindowsversion_from_kernel32(void)
{
#ifndef MS_WINDOWS_DESKTOP
+ PyErr_SetString(PyExc_OSError, "cannot read version info on this platform");
return NULL;
#else
HANDLE hKernel32;
@@ -1670,6 +1671,9 @@ _sys_getwindowsversion_from_kernel32(void)
!GetFileVersionInfoW(kernel32_path, 0, verblock_size, verblock) ||
!VerQueryValueW(verblock, L"", (LPVOID)&ffi, &ffi_len)) {
PyErr_SetFromWindowsErr(0);
+ if (verblock) {
+ PyMem_RawFree(verblock);
+ }
return NULL;
}
@@ -2448,26 +2452,58 @@ sys_is_remote_debug_enabled_impl(PyObject *module)
#endif
}
+/*[clinic input]
+sys.remote_exec
+
+ pid: int
+ script: object
+
+Executes a file containing Python code in a given remote Python process.
+
+This function returns immediately, and the code will be executed by the
+target process's main thread at the next available opportunity, similarly
+to how signals are handled. There is no interface to determine when the
+code has been executed. The caller is responsible for making sure that
+the file still exists whenever the remote process tries to read it and that
+it hasn't been overwritten.
+
+The remote process must be running a CPython interpreter of the same major
+and minor version as the local process. If either the local or remote
+interpreter is pre-release (alpha, beta, or release candidate) then the
+local and remote interpreters must be the same exact version.
+
+Args:
+ pid (int): The process ID of the target Python process.
+ script (str|bytes): The path to a file containing
+ the Python code to be executed.
+[clinic start generated code]*/
+
static PyObject *
-sys_remote_exec_unicode_path(PyObject *module, int pid, PyObject *script)
+sys_remote_exec_impl(PyObject *module, int pid, PyObject *script)
+/*[clinic end generated code: output=7d94c56afe4a52c0 input=39908ca2c5fe1eb0]*/
{
- const char *debugger_script_path = PyUnicode_AsUTF8(script);
- if (debugger_script_path == NULL) {
+ PyObject *path;
+ const char *debugger_script_path;
+
+ if (PyUnicode_FSConverter(script, &path) == 0) {
return NULL;
}
-
+ debugger_script_path = PyBytes_AS_STRING(path);
#ifdef MS_WINDOWS
+ PyObject *unicode_path;
+ if (PyUnicode_FSDecoder(path, &unicode_path) < 0) {
+ goto error;
+ }
// Use UTF-16 (wide char) version of the path for permission checks
- wchar_t *debugger_script_path_w = PyUnicode_AsWideCharString(script, NULL);
+ wchar_t *debugger_script_path_w = PyUnicode_AsWideCharString(unicode_path, NULL);
+ Py_DECREF(unicode_path);
if (debugger_script_path_w == NULL) {
- return NULL;
+ goto error;
}
-
- // Check file attributes using wide character version (W) instead of ANSI (A)
DWORD attr = GetFileAttributesW(debugger_script_path_w);
- PyMem_Free(debugger_script_path_w);
if (attr == INVALID_FILE_ATTRIBUTES) {
DWORD err = GetLastError();
+ PyMem_Free(debugger_script_path_w);
if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) {
PyErr_SetString(PyExc_FileNotFoundError, "Script file does not exist");
}
@@ -2475,11 +2511,12 @@ sys_remote_exec_unicode_path(PyObject *module, int pid, PyObject *script)
PyErr_SetString(PyExc_PermissionError, "Script file cannot be read");
}
else {
- PyErr_SetFromWindowsErr(0);
+ PyErr_SetFromWindowsErr(err);
}
- return NULL;
+ goto error;
}
-#else
+ PyMem_Free(debugger_script_path_w);
+#else // MS_WINDOWS
if (access(debugger_script_path, F_OK | R_OK) != 0) {
switch (errno) {
case ENOENT:
@@ -2491,54 +2528,19 @@ sys_remote_exec_unicode_path(PyObject *module, int pid, PyObject *script)
default:
PyErr_SetFromErrno(PyExc_OSError);
}
- return NULL;
+ goto error;
}
-#endif
-
+#endif // MS_WINDOWS
if (_PySysRemoteDebug_SendExec(pid, 0, debugger_script_path) < 0) {
- return NULL;
+ goto error;
}
+ Py_DECREF(path);
Py_RETURN_NONE;
-}
-
-/*[clinic input]
-sys.remote_exec
-
- pid: int
- script: object
-
-Executes a file containing Python code in a given remote Python process.
-
-This function returns immediately, and the code will be executed by the
-target process's main thread at the next available opportunity, similarly
-to how signals are handled. There is no interface to determine when the
-code has been executed. The caller is responsible for making sure that
-the file still exists whenever the remote process tries to read it and that
-it hasn't been overwritten.
-
-The remote process must be running a CPython interpreter of the same major
-and minor version as the local process. If either the local or remote
-interpreter is pre-release (alpha, beta, or release candidate) then the
-local and remote interpreters must be the same exact version.
-Args:
- pid (int): The process ID of the target Python process.
- script (str|bytes): The path to a file containing
- the Python code to be executed.
-[clinic start generated code]*/
-
-static PyObject *
-sys_remote_exec_impl(PyObject *module, int pid, PyObject *script)
-/*[clinic end generated code: output=7d94c56afe4a52c0 input=39908ca2c5fe1eb0]*/
-{
- PyObject *ret = NULL;
- PyObject *path;
- if (PyUnicode_FSDecoder(script, &path)) {
- ret = sys_remote_exec_unicode_path(module, pid, path);
- Py_DECREF(path);
- }
- return ret;
+error:
+ Py_DECREF(path);
+ return NULL;
}