summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorMark Shannon <mark@hotpy.org>2020-01-14 10:12:45 (GMT)
committerGitHub <noreply@github.com>2020-01-14 10:12:45 (GMT)
commit9af0e47b1705457bb6b327c197f2ec5737a1d8f6 (patch)
tree97378eee78d793d16bd19038d88371d776e720c3 /Python/ceval.c
parent62e3973395fb9fab2eb8f651bcd0fea4e695e1cf (diff)
downloadcpython-9af0e47b1705457bb6b327c197f2ec5737a1d8f6.zip
cpython-9af0e47b1705457bb6b327c197f2ec5737a1d8f6.tar.gz
cpython-9af0e47b1705457bb6b327c197f2ec5737a1d8f6.tar.bz2
bpo-39156: Break up COMPARE_OP into four logically distinct opcodes. (GH-17754)
Break up COMPARE_OP into four logically distinct opcodes: * COMPARE_OP for rich comparisons * IS_OP for 'is' and 'is not' tests * CONTAINS_OP for 'in' and 'is not' tests * JUMP_IF_NOT_EXC_MATCH for checking exceptions in 'try-except' statements.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c137
1 files changed, 78 insertions, 59 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index e8931c8..096645a 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -67,7 +67,6 @@ static void maybe_dtrace_line(PyFrameObject *, int *, int *, int *);
static void dtrace_function_entry(PyFrameObject *);
static void dtrace_function_return(PyFrameObject *);
-static PyObject * cmp_outcome(PyThreadState *, int, PyObject *, PyObject *);
static PyObject * import_name(PyThreadState *, PyFrameObject *,
PyObject *, PyObject *, PyObject *);
static PyObject * import_from(PyThreadState *, PyObject *, PyObject *);
@@ -2897,12 +2896,13 @@ main_loop:
}
case TARGET(COMPARE_OP): {
+ assert(oparg <= Py_GE);
PyObject *right = POP();
PyObject *left = TOP();
- PyObject *res = cmp_outcome(tstate, oparg, left, right);
+ PyObject *res = PyObject_RichCompare(left, right, oparg);
+ SET_TOP(res);
Py_DECREF(left);
Py_DECREF(right);
- SET_TOP(res);
if (res == NULL)
goto error;
PREDICT(POP_JUMP_IF_FALSE);
@@ -2910,6 +2910,81 @@ main_loop:
DISPATCH();
}
+ case TARGET(IS_OP): {
+ PyObject *right = POP();
+ PyObject *left = TOP();
+ int res = (left == right)^oparg;
+ PyObject *b = res ? Py_True : Py_False;
+ Py_INCREF(b);
+ SET_TOP(b);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ PREDICT(POP_JUMP_IF_FALSE);
+ PREDICT(POP_JUMP_IF_TRUE);
+ FAST_DISPATCH();
+ }
+
+ case TARGET(CONTAINS_OP): {
+ PyObject *right = POP();
+ PyObject *left = POP();
+ int res = PySequence_Contains(right, left);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ if (res < 0) {
+ goto error;
+ }
+ PyObject *b = (res^oparg) ? Py_True : Py_False;
+ Py_INCREF(b);
+ PUSH(b);
+ PREDICT(POP_JUMP_IF_FALSE);
+ PREDICT(POP_JUMP_IF_TRUE);
+ FAST_DISPATCH();
+ }
+
+#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\
+ "BaseException is not allowed"
+
+ case TARGET(JUMP_IF_NOT_EXC_MATCH): {
+ PyObject *right = POP();
+ PyObject *left = POP();
+ if (PyTuple_Check(right)) {
+ Py_ssize_t i, length;
+ length = PyTuple_GET_SIZE(right);
+ for (i = 0; i < length; i++) {
+ PyObject *exc = PyTuple_GET_ITEM(right, i);
+ if (!PyExceptionClass_Check(exc)) {
+ _PyErr_SetString(tstate, PyExc_TypeError,
+ CANNOT_CATCH_MSG);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ goto error;
+ }
+ }
+ }
+ else {
+ if (!PyExceptionClass_Check(right)) {
+ _PyErr_SetString(tstate, PyExc_TypeError,
+ CANNOT_CATCH_MSG);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ goto error;
+ }
+ }
+ int res = PyErr_GivenExceptionMatches(left, right);
+ Py_DECREF(left);
+ Py_DECREF(right);
+ if (res > 0) {
+ /* Exception matches -- Do nothing */;
+ }
+ else if (res == 0) {
+ JUMPTO(oparg);
+ }
+ else {
+ goto error;
+ }
+ DISPATCH();
+ }
+
case TARGET(IMPORT_NAME): {
PyObject *name = GETITEM(names, oparg);
PyObject *fromlist = POP();
@@ -4951,62 +5026,6 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
return 1;
}
-
-#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\
- "BaseException is not allowed"
-
-static PyObject *
-cmp_outcome(PyThreadState *tstate, int op, PyObject *v, PyObject *w)
-{
- int res = 0;
- switch (op) {
- case PyCmp_IS:
- res = (v == w);
- break;
- case PyCmp_IS_NOT:
- res = (v != w);
- break;
- case PyCmp_IN:
- res = PySequence_Contains(w, v);
- if (res < 0)
- return NULL;
- break;
- case PyCmp_NOT_IN:
- res = PySequence_Contains(w, v);
- if (res < 0)
- return NULL;
- res = !res;
- break;
- case PyCmp_EXC_MATCH:
- if (PyTuple_Check(w)) {
- Py_ssize_t i, length;
- length = PyTuple_Size(w);
- for (i = 0; i < length; i += 1) {
- PyObject *exc = PyTuple_GET_ITEM(w, i);
- if (!PyExceptionClass_Check(exc)) {
- _PyErr_SetString(tstate, PyExc_TypeError,
- CANNOT_CATCH_MSG);
- return NULL;
- }
- }
- }
- else {
- if (!PyExceptionClass_Check(w)) {
- _PyErr_SetString(tstate, PyExc_TypeError,
- CANNOT_CATCH_MSG);
- return NULL;
- }
- }
- res = PyErr_GivenExceptionMatches(v, w);
- break;
- default:
- return PyObject_RichCompare(v, w, op);
- }
- v = res ? Py_True : Py_False;
- Py_INCREF(v);
- return v;
-}
-
static PyObject *
import_name(PyThreadState *tstate, PyFrameObject *f,
PyObject *name, PyObject *fromlist, PyObject *level)