Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Doc/library/xmlrpc.client.rst
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ ServerProxy Objects
A :class:`ServerProxy` instance has a method corresponding to each remote
procedure call accepted by the XML-RPC server. Calling the method performs an
RPC, dispatched by both name and argument signature (e.g. the same method name
can be overloaded with multiple argument signatures). The RPC finishes by
returning a value, which may be either returned data in a conformant type or a
:class:`Fault` or :class:`ProtocolError` object indicating an error.
can be overloaded with multiple argument signatures). The RPC finishes either
by returning data in a conformant type or by raising a :class:`Fault` or
:class:`ProtocolError` exception indicating an error.

Servers that support the XML introspection API support some common methods
grouped under the reserved :attr:`~ServerProxy.system` attribute:
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_optimizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ PyAPI_FUNC(int) _PyDumpExecutors(FILE *out);
extern void _Py_ClearExecutorDeletionList(PyInterpreterState *interp);
#endif

int _PyJit_translate_single_bytecode_to_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr, bool stop_tracing);
int _PyJit_translate_single_bytecode_to_trace(PyThreadState *tstate, _PyInterpreterFrame *frame, _Py_CODEUNIT *next_instr, int stop_tracing_opcode);

int
_PyJit_TryInitializeTracing(PyThreadState *tstate, _PyInterpreterFrame *frame,
Expand Down
36 changes: 36 additions & 0 deletions Lib/test/test_capi/test_opt.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ def get_first_executor(func):
pass
return None

def get_all_executors(func):
code = func.__code__
co_code = code.co_code
executors = []
for i in range(0, len(co_code), 2):
try:
executors.append(_opcode.get_executor(code, i))
except ValueError:
pass
return executors


def iter_opnames(ex):
for item in ex:
Expand Down Expand Up @@ -2629,6 +2640,31 @@ def gen():
next(g)
""" % _testinternalcapi.SPECIALIZATION_THRESHOLD))

def test_executor_side_exits_create_another_executor(self):
def f():
for x in range(TIER2_THRESHOLD + 3):
for y in range(TIER2_THRESHOLD + 3):
z = x + y

f()
all_executors = get_all_executors(f)
# Inner loop warms up first.
# Outer loop warms up later, linking to the inner one.
# Therefore, we have at least two executors.
self.assertGreaterEqual(len(all_executors), 2)
for executor in all_executors:
opnames = list(get_opnames(executor))
# Assert all executors first terminator ends in
# _EXIT_TRACE or _JUMP_TO_TOP, not _DEOPT
for idx, op in enumerate(opnames):
if op == "_EXIT_TRACE" or op == "_JUMP_TO_TOP":
break
elif op == "_DEOPT":
self.fail(f"_DEOPT encountered first at executor"
f" {executor} at offset {idx} rather"
f" than expected _EXIT_TRACE")



def global_identity(x):
return x
Expand Down
5 changes: 3 additions & 2 deletions Modules/_testmultiphase.c
Original file line number Diff line number Diff line change
Expand Up @@ -1061,7 +1061,7 @@ PyModInit__test_from_modexport_exception(void)
}

static PyObject *
modexport_create_string(PyObject *spec, PyObject *def)
modexport_create_string(PyObject *spec, PyModuleDef *def)
{
assert(def == NULL);
return PyUnicode_FromString("is this \xf0\x9f\xa6\x8b... a module?");
Expand Down Expand Up @@ -1138,8 +1138,9 @@ modexport_get_empty_slots(PyObject *mod, PyObject *arg)
}

static void
modexport_smoke_free(PyObject *mod)
modexport_smoke_free(void *op)
{
PyObject *mod = (PyObject *)op;
int *state = PyModule_GetState(mod);
if (!state) {
PyErr_FormatUnraisable("Exception ignored in module %R free", mod);
Expand Down
4 changes: 2 additions & 2 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -5643,7 +5643,7 @@ dummy_func(
bool stop_tracing = (opcode == WITH_EXCEPT_START ||
opcode == RERAISE || opcode == CLEANUP_THROW ||
opcode == PUSH_EXC_INFO || opcode == INTERPRETER_EXIT);
int full = !_PyJit_translate_single_bytecode_to_trace(tstate, frame, next_instr, stop_tracing);
int full = !_PyJit_translate_single_bytecode_to_trace(tstate, frame, next_instr, stop_tracing ? _DEOPT : 0);
if (full) {
LEAVE_TRACING();
int err = stop_tracing_and_jit(tstate, frame);
Expand Down Expand Up @@ -5683,7 +5683,7 @@ dummy_func(
#if _Py_TIER2
assert(IS_JIT_TRACING());
int opcode = next_instr->op.code;
_PyJit_translate_single_bytecode_to_trace(tstate, frame, NULL, true);
_PyJit_translate_single_bytecode_to_trace(tstate, frame, NULL, _EXIT_TRACE);
LEAVE_TRACING();
int err = stop_tracing_and_jit(tstate, frame);
ERROR_IF(err < 0);
Expand Down
4 changes: 2 additions & 2 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Python/optimizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ _PyJit_translate_single_bytecode_to_trace(
PyThreadState *tstate,
_PyInterpreterFrame *frame,
_Py_CODEUNIT *next_instr,
bool stop_tracing)
int stop_tracing_opcode)
{

#ifdef Py_DEBUG
Expand Down Expand Up @@ -637,8 +637,8 @@ _PyJit_translate_single_bytecode_to_trace(
goto full;
}

if (stop_tracing) {
ADD_TO_TRACE(_DEOPT, 0, 0, target);
if (stop_tracing_opcode != 0) {
ADD_TO_TRACE(stop_tracing_opcode, 0, 0, target);
goto done;
}

Expand Down
Loading