summaryrefslogtreecommitdiffstats
path: root/Python/bytecodes.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/bytecodes.c')
-rw-r--r--Python/bytecodes.c133
1 files changed, 76 insertions, 57 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index ffa53bb..757c3f9 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -10,6 +10,7 @@
#include "pycore_abstract.h" // _PyIndex_Check()
#include "pycore_backoff.h"
#include "pycore_cell.h" // PyCell_GetRef()
+#include "pycore_ceval.h"
#include "pycore_code.h"
#include "pycore_emscripten_signal.h" // _Py_CHECK_EMSCRIPTEN_SIGNALS
#include "pycore_function.h"
@@ -146,36 +147,54 @@ dummy_func(
RESUME_CHECK,
};
- tier1 inst(RESUME, (--)) {
- assert(frame == tstate->current_frame);
+ op(_CHECK_PERIODIC, (--)) {
+ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY();
+ QSBR_QUIESCENT_STATE(tstate); \
+ if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
+ int err = _Py_HandlePending(tstate);
+ ERROR_IF(err != 0, error);
+ }
+ }
+
+ op(_CHECK_PERIODIC_IF_NOT_YIELD_FROM, (--)) {
+ if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
+ _Py_CHECK_EMSCRIPTEN_SIGNALS_PERIODICALLY();
+ QSBR_QUIESCENT_STATE(tstate); \
+ if (_Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & _PY_EVAL_EVENTS_MASK) {
+ int err = _Py_HandlePending(tstate);
+ ERROR_IF(err != 0, error);
+ }
+ }
+ }
+
+ op(_QUICKEN_RESUME, (--)) {
+ #if ENABLE_SPECIALIZATION
+ if (tstate->tracing == 0 && this_instr->op.code == RESUME) {
+ FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK);
+ }
+ #endif /* ENABLE_SPECIALIZATION */
+ }
+
+ tier1 op(_MAYBE_INSTRUMENT, (--)) {
if (tstate->tracing == 0) {
- uintptr_t global_version =
- _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) &
- ~_PY_EVAL_EVENTS_MASK;
- PyCodeObject* code = _PyFrame_GetCode(frame);
- uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(code->_co_instrumentation_version);
- assert((code_version & 255) == 0);
+ uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
+ uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version);
if (code_version != global_version) {
int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
- ERROR_IF(err, error);
+ if (err) {
+ ERROR_NO_POP();
+ }
next_instr = this_instr;
DISPATCH();
}
- assert(this_instr->op.code == RESUME ||
- this_instr->op.code == RESUME_CHECK ||
- this_instr->op.code == INSTRUMENTED_RESUME ||
- this_instr->op.code == ENTER_EXECUTOR);
- if (this_instr->op.code == RESUME) {
- #if ENABLE_SPECIALIZATION
- FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK);
- #endif /* ENABLE_SPECIALIZATION */
- }
- }
- if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
- CHECK_EVAL_BREAKER();
}
}
+ macro(RESUME) =
+ _MAYBE_INSTRUMENT +
+ _QUICKEN_RESUME +
+ _CHECK_PERIODIC_IF_NOT_YIELD_FROM;
+
inst(RESUME_CHECK, (--)) {
#if defined(__EMSCRIPTEN__)
DEOPT_IF(_Py_emscripten_signal_clock == 0);
@@ -187,33 +206,23 @@ dummy_func(
DEOPT_IF(eval_breaker != version);
}
- inst(INSTRUMENTED_RESUME, (--)) {
- uintptr_t global_version = _Py_atomic_load_uintptr_relaxed(&tstate->eval_breaker) & ~_PY_EVAL_EVENTS_MASK;
- uintptr_t code_version = FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version);
- if (code_version != global_version && tstate->tracing == 0) {
- int err = _Py_Instrument(_PyFrame_GetCode(frame), tstate->interp);
- if (err) {
- ERROR_NO_POP();
- }
- next_instr = this_instr;
- }
- else {
- if ((oparg & RESUME_OPARG_LOCATION_MASK) < RESUME_AFTER_YIELD_FROM) {
- CHECK_EVAL_BREAKER();
- }
- _PyFrame_SetStackPointer(frame, stack_pointer);
- int err = _Py_call_instrumentation(
- tstate, oparg > 0, frame, this_instr);
- stack_pointer = _PyFrame_GetStackPointer(frame);
- ERROR_IF(err, error);
- if (frame->instr_ptr != this_instr) {
- /* Instrumentation has jumped */
- next_instr = frame->instr_ptr;
- DISPATCH();
- }
+ op(_MONITOR_RESUME, (--)) {
+ _PyFrame_SetStackPointer(frame, stack_pointer);
+ int err = _Py_call_instrumentation(
+ tstate, oparg > 0, frame, this_instr);
+ stack_pointer = _PyFrame_GetStackPointer(frame);
+ ERROR_IF(err, error);
+ if (frame->instr_ptr != this_instr) {
+ /* Instrumentation has jumped */
+ next_instr = frame->instr_ptr;
}
}
+ macro(INSTRUMENTED_RESUME) =
+ _MAYBE_INSTRUMENT +
+ _CHECK_PERIODIC_IF_NOT_YIELD_FROM +
+ _MONITOR_RESUME;
+
pseudo(LOAD_CLOSURE, (-- unused)) = {
LOAD_FAST,
};
@@ -2486,8 +2495,7 @@ dummy_func(
JUMPBY(oparg);
}
- tier1 inst(JUMP_BACKWARD, (unused/1 --)) {
- CHECK_EVAL_BREAKER();
+ tier1 op(_JUMP_BACKWARD, (the_counter/1 --)) {
assert(oparg <= INSTR_OFFSET());
JUMPBY(-oparg);
#ifdef _Py_TIER2
@@ -2519,6 +2527,10 @@ dummy_func(
#endif /* _Py_TIER2 */
}
+ macro(JUMP_BACKWARD) =
+ _CHECK_PERIODIC +
+ _JUMP_BACKWARD;
+
pseudo(JUMP, (--)) = {
JUMP_FORWARD,
JUMP_BACKWARD,
@@ -3265,10 +3277,6 @@ dummy_func(
res = PyStackRef_FromPyObjectSteal(res_o);
}
- op(_CHECK_PERIODIC, (--)) {
- CHECK_EVAL_BREAKER();
- }
-
op(_MONITOR_CALL, (func, maybe_self, args[oparg] -- func, maybe_self, args[oparg])) {
int is_meth = !PyStackRef_IsNull(maybe_self);
PyObject *function = PyStackRef_AsPyObjectBorrow(func);
@@ -4012,7 +4020,7 @@ dummy_func(
GO_TO_INSTRUCTION(CALL_KW);
}
- inst(CALL_KW, (callable, self_or_null, args[oparg], kwnames -- res)) {
+ op(_DO_CALL_KW, (callable, self_or_null, args[oparg], kwnames -- res)) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyObject *self_or_null_o = PyStackRef_AsPyObjectBorrow(self_or_null);
PyObject *kwnames_o = PyStackRef_AsPyObjectBorrow(kwnames);
@@ -4094,14 +4102,17 @@ dummy_func(
}
ERROR_IF(res_o == NULL, error);
res = PyStackRef_FromPyObjectSteal(res_o);
- CHECK_EVAL_BREAKER();
}
+ macro(CALL_KW) =
+ _DO_CALL_KW +
+ _CHECK_PERIODIC;
+
inst(INSTRUMENTED_CALL_FUNCTION_EX, ( -- )) {
GO_TO_INSTRUCTION(CALL_FUNCTION_EX);
}
- inst(CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st if (oparg & 1) -- result)) {
+ inst(_DO_CALL_FUNCTION_EX, (func_st, unused, callargs_st, kwargs_st if (oparg & 1) -- result)) {
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
PyObject *callargs = PyStackRef_AsPyObjectBorrow(callargs_st);
PyObject *kwargs = PyStackRef_AsPyObjectBorrow(kwargs_st);
@@ -4175,9 +4186,13 @@ dummy_func(
DECREF_INPUTS();
assert(PyStackRef_AsPyObjectBorrow(PEEK(2 + (oparg & 1))) == NULL);
ERROR_IF(PyStackRef_IsNull(result), error);
- CHECK_EVAL_BREAKER();
}
+ macro(CALL_FUNCTION_EX) =
+ _DO_CALL_FUNCTION_EX +
+ _CHECK_PERIODIC;
+
+
inst(MAKE_FUNCTION, (codeobj_st -- func)) {
PyObject *codeobj = PyStackRef_AsPyObjectBorrow(codeobj_st);
@@ -4381,11 +4396,15 @@ dummy_func(
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_JUMP);
}
- inst(INSTRUMENTED_JUMP_BACKWARD, (unused/1 -- )) {
- CHECK_EVAL_BREAKER();
+ op(_MONITOR_JUMP_BACKWARD, (-- )) {
INSTRUMENTED_JUMP(this_instr, next_instr - oparg, PY_MONITORING_EVENT_JUMP);
}
+ macro(INSTRUMENTED_JUMP_BACKWARD) =
+ unused/1 +
+ _CHECK_PERIODIC +
+ _MONITOR_JUMP_BACKWARD;
+
inst(INSTRUMENTED_POP_JUMP_IF_TRUE, (unused/1 -- )) {
_PyStackRef cond = POP();
assert(PyStackRef_BoolCheck(cond));