Skip to content

Commit 56960c4

Browse files
committed
fix bugs && add tests
1 parent b42e939 commit 56960c4

File tree

8 files changed

+86
-65
lines changed

8 files changed

+86
-65
lines changed

Include/cpython/ceval.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ _PyEval_RequestCodeExtraIndex(freefunc f) {
2323

2424
PyAPI_FUNC(int) _PyEval_SliceIndex(PyObject *, Py_ssize_t *);
2525
PyAPI_FUNC(int) _PyEval_SliceIndexNotNone(PyObject *, Py_ssize_t *);
26+
PyAPI_FUNC(int) _PyEval_UnpackIndices(PyObject *, PyObject *,
27+
Py_ssize_t,
28+
Py_ssize_t *, Py_ssize_t *);
2629

2730

2831
// Trampoline API

Include/internal/pycore_uop_metadata.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_capi/test_opt.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3130,6 +3130,26 @@ def testfunc(n):
31303130
self.assertIn("_BINARY_SLICE_UNICODE", uops)
31313131
self.assertNotIn("_BINARY_SLICE", uops)
31323132

3133+
def test_binary_slice_deopt(self):
3134+
def testfunc(data, n):
3135+
a, b = 0, 1
3136+
for _ in range(n):
3137+
x = data[a:b]
3138+
return x
3139+
3140+
res = testfunc([1, 2], TIER2_THRESHOLD)
3141+
self.assertEqual(res, [1])
3142+
ex = get_first_executor(testfunc)
3143+
self.assertIsNotNone(ex)
3144+
uops = get_opnames(ex)
3145+
self.assertIn("_BINARY_SLICE_LIST", uops)
3146+
3147+
res2 = testfunc((10, 20), TIER2_THRESHOLD)
3148+
self.assertEqual(res2, (10,))
3149+
3150+
res3 = testfunc("ab", TIER2_THRESHOLD)
3151+
self.assertEqual(res3, "a")
3152+
31333153
def test_unary_invert_long_type(self):
31343154
def testfunc(n):
31353155
for _ in range(n):

Python/bytecodes.c

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -881,24 +881,19 @@ dummy_func(
881881
}
882882

883883
tier2 op(_UNPACK_INDICES, (container, start, stop -- container, sta, sto)) {
884-
Py_ssize_t istart = 0, istop = PY_SSIZE_T_MAX;
885-
int err = _PyEval_SliceIndex(PyStackRef_AsPyObjectBorrow(start), &istart);
884+
Py_ssize_t istart, istop;
885+
int err = _PyEval_UnpackIndices(
886+
PyStackRef_AsPyObjectBorrow(start),
887+
PyStackRef_AsPyObjectBorrow(stop),
888+
PyObject_Length(PyStackRef_AsPyObjectBorrow(container)),
889+
&istart, &istop);
886890
if (err == 0) {
887891
ERROR_NO_POP();
888892
}
889-
err = _PyEval_SliceIndex(PyStackRef_AsPyObjectBorrow(stop), &istop);
890-
if (err == 0) {
891-
ERROR_NO_POP();
892-
}
893-
Py_ssize_t len = PyObject_Length(PyStackRef_AsPyObjectBorrow(container));
894-
if (len < 0) {
895-
ERROR_NO_POP();
896-
}
897-
PySlice_AdjustIndices(len, &istart, &istop, 1);
898-
DEOPT_IF(!PyStackRef_CanTagInt(istart));
899-
DEOPT_IF(!PyStackRef_CanTagInt(istop));
900893
PyStackRef_CLOSE(stop);
901894
PyStackRef_CLOSE(start);
895+
assert(PyStackRef_CanTagInt(istart));
896+
assert(PyStackRef_CanTagInt(istop));
902897
sta = PyStackRef_TagInt((intptr_t)istart);
903898
sto = PyStackRef_TagInt((intptr_t)istop);
904899
}

Python/ceval.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,6 +2915,26 @@ _PyEval_SliceIndexNotNone(PyObject *v, Py_ssize_t *pi)
29152915
return 1;
29162916
}
29172917

2918+
int
2919+
_PyEval_UnpackIndices(PyObject *start, PyObject *stop,
2920+
Py_ssize_t len,
2921+
Py_ssize_t *istart, Py_ssize_t *istop)
2922+
{
2923+
if (len < 0) {
2924+
return 0;
2925+
}
2926+
*istart = 0;
2927+
*istop = PY_SSIZE_T_MAX;
2928+
if (!_PyEval_SliceIndex(start, istart)) {
2929+
return 0;
2930+
}
2931+
if (!_PyEval_SliceIndex(stop, istop)) {
2932+
return 0;
2933+
}
2934+
PySlice_AdjustIndices(len, istart, istop, 1);
2935+
return 1;
2936+
}
2937+
29182938
PyObject *
29192939
_PyEval_ImportName(PyThreadState *tstate, _PyInterpreterFrame *frame,
29202940
PyObject *name, PyObject *fromlist, PyObject *level)

Python/executor_cases.c.h

Lines changed: 8 additions & 39 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/optimizer_bytecodes.c

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1493,21 +1493,28 @@ dummy_func(void) {
14931493

14941494
op(_BINARY_SLICE, (container, start, stop -- res)) {
14951495
// Slicing a string/list/tuple always returns the same type.
1496-
PyTypeObject *type = sym_get_probable_type(container);
1496+
PyTypeObject *known_type = sym_get_type(container);
1497+
PyTypeObject *type = known_type ? known_type : sym_get_probable_type(container);
14971498
if (type == &PyList_Type) {
1498-
ADD_OP(_GUARD_3OS_TYPE, 0, (uintptr_t)type);
1499+
if (!known_type) {
1500+
ADD_OP(_GUARD_3OS_TYPE, 0, (uintptr_t)type);
1501+
}
14991502
ADD_OP(_UNPACK_INDICES, 0, 0);
15001503
ADD_OP(_BINARY_SLICE_LIST, 0, 0);
15011504
res = sym_new_type(ctx, type);
15021505
}
15031506
else if (type == &PyTuple_Type) {
1504-
ADD_OP(_GUARD_3OS_TYPE, 0, (uintptr_t)type);
1507+
if (!known_type) {
1508+
ADD_OP(_GUARD_3OS_TYPE, 0, (uintptr_t)type);
1509+
}
15051510
ADD_OP(_UNPACK_INDICES, 0, 0);
15061511
ADD_OP(_BINARY_SLICE_TUPLE, 0, 0);
15071512
res = sym_new_type(ctx, type);
15081513
}
15091514
else if (type == &PyUnicode_Type) {
1510-
ADD_OP(_GUARD_3OS_TYPE, 0, (uintptr_t)type);
1515+
if (!known_type) {
1516+
ADD_OP(_GUARD_3OS_TYPE, 0, (uintptr_t)type);
1517+
}
15111518
ADD_OP(_UNPACK_INDICES, 0, 0);
15121519
ADD_OP(_BINARY_SLICE_UNICODE, 0, 0);
15131520
res = sym_new_type(ctx, type);
@@ -1519,8 +1526,8 @@ dummy_func(void) {
15191526

15201527
op(_UNPACK_INDICES, (container, start, stop -- container, sta, sto)) {
15211528
(void)container;
1522-
sta = sym_new_compact_int(ctx);
1523-
sto = sym_new_compact_int(ctx);
1529+
sta = sym_new_type(ctx, &PyLong_Type);
1530+
sto = sym_new_type(ctx, &PyLong_Type);
15241531
}
15251532

15261533
op(_GUARD_GLOBALS_VERSION, (version/1 --)) {

Python/optimizer_cases.c.h

Lines changed: 13 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)