diff --git a/Lib/test/test_peepholer.py b/Lib/test/test_peepholer.py index c7da151dce3b37..48d9469e8547e9 100644 --- a/Lib/test/test_peepholer.py +++ b/Lib/test/test_peepholer.py @@ -240,6 +240,7 @@ def test_folding_of_binops_on_constants(self): ('a = 2+3', 5), # binary add ('a = 13-4', 9), # binary subtract ('a = (12,13)[1]', 13), # binary subscr + ('a = (12,13)[:1]', (12,)), # binary subscr (slice) ('a = 13 << 2', 52), # binary lshift ('a = 13 >> 2', 3), # binary rshift ('a = 13 & 7', 5), # binary and @@ -282,11 +283,17 @@ def test_binary_subscr_on_unicode(self): self.assertInBytecode(code, 'LOAD_CONST', 'f') self.assertNotInBytecode(code, 'BINARY_SUBSCR') self.check_lnotab(code) + code = compile('"\u0061\uffff"[1]', '', 'single') self.assertInBytecode(code, 'LOAD_CONST', '\uffff') self.assertNotInBytecode(code,'BINARY_SUBSCR') self.check_lnotab(code) + code = compile('"\u0061\uffffxx"[1::2]', '', 'single') + self.assertInBytecode(code, 'LOAD_CONST', '\uffffx') + self.assertNotInBytecode(code,'BINARY_SUBSCR') + self.check_lnotab(code) + # With PEP 393, non-BMP char get optimized code = compile('"\U00012345"[0]', '', 'single') self.assertInBytecode(code, 'LOAD_CONST', '\U00012345') diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 01e208b88eca8b..5f111fbd9d1b9a 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -586,6 +586,26 @@ fold_subscr(expr_ty node, PyArena *arena, _PyASTOptimizeState *state) return make_const(node, newval, arena); } +static int +fold_slice(expr_ty node, PyArena *arena, _PyASTOptimizeState *state) +{ + expr_ty lower = node->v.Slice.lower; + expr_ty upper = node->v.Slice.upper; + expr_ty step = node->v.Slice.step; + if ((lower && lower->kind != Constant_kind) || + (upper && upper->kind != Constant_kind) || + (step && step->kind != Constant_kind)) + { + return 1; + } + + PyObject *newval = PySlice_New( + lower ? lower->v.Constant.value : Py_None, + upper ? upper->v.Constant.value : Py_None, + step ? step->v.Constant.value : Py_None); + return make_const(node, newval, arena); +} + /* Change literal list or set of constants into constant tuple or frozenset respectively. Change literal list of non-constants into tuple. @@ -831,6 +851,7 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state) CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.lower); CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.upper); CALL_OPT(astfold_expr, expr_ty, node_->v.Slice.step); + CALL(fold_slice, expr_ty, node_); break; case List_kind: CALL_SEQ(astfold_expr, expr, node_->v.List.elts); diff --git a/Python/codegen.c b/Python/codegen.c index bce3b94b27a45d..c8d619b55ed94b 100644 --- a/Python/codegen.c +++ b/Python/codegen.c @@ -5039,23 +5039,10 @@ codegen_visit_expr(compiler *c, expr_ty e) return SUCCESS; } -static bool -is_constant_slice(expr_ty s) -{ - return s->kind == Slice_kind && - (s->v.Slice.lower == NULL || - s->v.Slice.lower->kind == Constant_kind) && - (s->v.Slice.upper == NULL || - s->v.Slice.upper->kind == Constant_kind) && - (s->v.Slice.step == NULL || - s->v.Slice.step->kind == Constant_kind); -} - static bool should_apply_two_element_slice_optimization(expr_ty s) { - return !is_constant_slice(s) && - s->kind == Slice_kind && + return s->kind == Slice_kind && s->v.Slice.step == NULL; } @@ -5312,27 +5299,6 @@ codegen_slice(compiler *c, expr_ty s) int n = 2; assert(s->kind == Slice_kind); - if (is_constant_slice(s)) { - PyObject *start = NULL; - if (s->v.Slice.lower) { - start = s->v.Slice.lower->v.Constant.value; - } - PyObject *stop = NULL; - if (s->v.Slice.upper) { - stop = s->v.Slice.upper->v.Constant.value; - } - PyObject *step = NULL; - if (s->v.Slice.step) { - step = s->v.Slice.step->v.Constant.value; - } - PyObject *slice = PySlice_New(start, stop, step); - if (slice == NULL) { - return ERROR; - } - ADDOP_LOAD_CONST_NEW(c, LOC(s), slice); - return SUCCESS; - } - RETURN_IF_ERROR(codegen_slice_two_parts(c, s)); if (s->v.Slice.step) {