Skip to content

Commit 46b423f

Browse files
committed
WIP
1 parent d5afe15 commit 46b423f

File tree

11 files changed

+130
-21
lines changed

11 files changed

+130
-21
lines changed

Include/internal/pycore_opcode_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: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import unittest
66
import gc
77
import os
8+
import random
9+
import string
810

911
import _opcode
1012

@@ -2362,6 +2364,23 @@ def testfunc(n):
23622364
self.assertNotIn("_GUARD_TOS_INT", uops)
23632365
self.assertNotIn("_GUARD_NOS_INT", uops)
23642366

2367+
def test_store_fast_pop_top_specialize_unicode(self):
2368+
def random_str(n):
2369+
return ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(n))
2370+
def testfunc(n):
2371+
y = random_str(32)
2372+
for _ in range(n):
2373+
x = y + y # _POP_TOP
2374+
x = None # _POP_TOP_NOP
2375+
2376+
testfunc(TIER2_THRESHOLD)
2377+
2378+
ex = get_first_executor(testfunc)
2379+
self.assertIsNotNone(ex)
2380+
uops = get_opnames(ex)
2381+
2382+
self.assertIn("_POP_TOP_NOP", uops)
2383+
23652384
def test_attr_promotion_failure(self):
23662385
# We're not testing for any specific uops here, just
23672386
# testing it doesn't crash.

Lib/test/test_sys.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1671,7 +1671,7 @@ def func():
16711671
INTERPRETER_FRAME = '9PihcP'
16721672
else:
16731673
INTERPRETER_FRAME = '9PhcP'
1674-
check(x, size('3PiccPPP' + INTERPRETER_FRAME + 'P'))
1674+
check(x, size('3PiccPPP' + INTERPRETER_FRAME + 'PP'))
16751675
# function
16761676
def func(): pass
16771677
check(func, size('16Pi'))
@@ -1688,7 +1688,7 @@ def bar(cls):
16881688
check(bar, size('PP'))
16891689
# generator
16901690
def get_gen(): yield 1
1691-
check(get_gen(), size('6P4c' + INTERPRETER_FRAME + 'P'))
1691+
check(get_gen(), size('6P4c' + INTERPRETER_FRAME + 'PP'))
16921692
# iterator
16931693
check(iter('abc'), size('lP'))
16941694
# callable-iterator

Programs/test_frozenmain.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.

Python/bytecodes.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,23 +773,23 @@ dummy_func(
773773
macro(BINARY_OP_SUBTRACT_FLOAT) =
774774
_GUARD_TOS_FLOAT + _GUARD_NOS_FLOAT + unused/5 + _BINARY_OP_SUBTRACT_FLOAT;
775775

776-
pure op(_BINARY_OP_ADD_UNICODE, (left, right -- res)) {
776+
pure op(_BINARY_OP_ADD_UNICODE, (left, right -- res, l, r)) {
777777
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
778778
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
779779
assert(PyUnicode_CheckExact(left_o));
780780
assert(PyUnicode_CheckExact(right_o));
781781

782782
STAT_INC(BINARY_OP, hit);
783783
PyObject *res_o = PyUnicode_Concat(left_o, right_o);
784-
PyStackRef_CLOSE_SPECIALIZED(right, _PyUnicode_ExactDealloc);
785-
PyStackRef_CLOSE_SPECIALIZED(left, _PyUnicode_ExactDealloc);
786784
INPUTS_DEAD();
787785
ERROR_IF(res_o == NULL);
786+
l = left;
787+
r = right;
788788
res = PyStackRef_FromPyObjectSteal(res_o);
789789
}
790790

791791
macro(BINARY_OP_ADD_UNICODE) =
792-
_GUARD_TOS_UNICODE + _GUARD_NOS_UNICODE + unused/5 + _BINARY_OP_ADD_UNICODE;
792+
_GUARD_TOS_UNICODE + _GUARD_NOS_UNICODE + unused/5 + _BINARY_OP_ADD_UNICODE + _POP_TOP_UNICODE + _POP_TOP_UNICODE;
793793

794794
// This is a subtle one. It's a super-instruction for
795795
// BINARY_OP_ADD_UNICODE followed by STORE_FAST

Python/compile.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,6 +1431,10 @@ optimize_and_assemble_code_unit(struct compiler_unit *u, PyObject *const_cache,
14311431
&optimized_instrs) < 0) {
14321432
goto error;
14331433
}
1434+
/* Reserve an extra word on the stack to ensure there is space for uops to
1435+
pass at least one item on the stack to a subsequent uop.
1436+
*/
1437+
stackdepth++;
14341438

14351439
/** Assembly **/
14361440
co = _PyAssemble_MakeCodeObject(&u->u_metadata, const_cache, consts,

Python/executor_cases.c.h

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

Python/generated_cases.c.h

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

Python/optimizer_analysis.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ remove_globals(_PyInterpreterFrame *frame, _PyUOpInstruction *buffer,
345345
#define sym_new_tuple _Py_uop_sym_new_tuple
346346
#define sym_tuple_getitem _Py_uop_sym_tuple_getitem
347347
#define sym_tuple_length _Py_uop_sym_tuple_length
348-
#define sym_is_immortal _Py_uop_sym_is_immortal
348+
#define sym_is_immortal _Py_uop_symbol_is_immortal
349349
#define sym_is_compact_int _Py_uop_sym_is_compact_int
350350
#define sym_new_compact_int _Py_uop_sym_new_compact_int
351351
#define sym_new_truthiness _Py_uop_sym_new_truthiness

Python/optimizer_bytecodes.c

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ typedef struct _Py_UOpsAbstractFrame _Py_UOpsAbstractFrame;
3434
#define sym_new_tuple _Py_uop_sym_new_tuple
3535
#define sym_tuple_getitem _Py_uop_sym_tuple_getitem
3636
#define sym_tuple_length _Py_uop_sym_tuple_length
37-
#define sym_is_immortal _Py_uop_sym_is_immortal
37+
#define sym_is_immortal _Py_uop_symbol_is_immortal
3838
#define sym_new_compact_int _Py_uop_sym_new_compact_int
3939
#define sym_is_compact_int _Py_uop_sym_is_compact_int
4040
#define sym_new_truthiness _Py_uop_sym_new_truthiness
@@ -318,7 +318,7 @@ dummy_func(void) {
318318
}
319319
}
320320

321-
op(_BINARY_OP_ADD_UNICODE, (left, right -- res)) {
321+
op(_BINARY_OP_ADD_UNICODE, (left, right -- res, l, r)) {
322322
if (sym_is_const(ctx, left) && sym_is_const(ctx, right)) {
323323
assert(PyUnicode_CheckExact(sym_get_const(ctx, left)));
324324
assert(PyUnicode_CheckExact(sym_get_const(ctx, right)));
@@ -327,10 +327,14 @@ dummy_func(void) {
327327
goto error;
328328
}
329329
res = sym_new_const(ctx, temp);
330+
l = left;
331+
r = right;
330332
Py_DECREF(temp);
331333
}
332334
else {
333335
res = sym_new_type(ctx, &PyUnicode_Type);
336+
l = left;
337+
r = right;
334338
}
335339
}
336340

@@ -561,11 +565,39 @@ dummy_func(void) {
561565
value = PyJitRef_Borrow(sym_new_const(ctx, ptr));
562566
}
563567

568+
op(_POP_TOP_UNICODE, (value -- )) {
569+
if (PyJitRef_IsBorrowed(value) ||
570+
sym_is_immortal(PyJitRef_Unwrap(value))) {
571+
REPLACE_OP(this_instr, _POP_TOP_NOP, 0, 0);
572+
}
573+
}
574+
564575
op(_COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) {
565576
assert(oparg > 0);
566577
top = bottom;
567578
}
568579

580+
op(_POP_TOP, (value -- )) {
581+
PyTypeObject *typ = sym_get_type(value);
582+
PyObject *const_val = sym_get_const(ctx, value);
583+
if (PyJitRef_IsBorrowed(value) ||
584+
(const_val != NULL && _Py_IsImmortal(const_val))) {
585+
REPLACE_OP(this_instr, _POP_TOP_NOP, 0, 0);
586+
}
587+
else if (typ == &PyLong_Type) {
588+
REPLACE_OP(this_instr, _POP_TOP_INT, 0, 0);
589+
}
590+
else if (typ == &PyFloat_Type) {
591+
REPLACE_OP(this_instr, _POP_TOP_FLOAT, 0, 0);
592+
}
593+
else if (typ == &PyUnicode_Type) {
594+
REPLACE_OP(this_instr, _POP_TOP_UNICODE, 0, 0);
595+
}
596+
else if (typ == &PyBool_Type) {
597+
REPLACE_OP(this_instr, _POP_TOP_NOP, 0, 0);
598+
}
599+
}
600+
569601
op(_SWAP, (bottom, unused[oparg-2], top -- bottom, unused[oparg-2], top)) {
570602
JitOptRef temp = bottom;
571603
bottom = top;
@@ -803,7 +835,7 @@ dummy_func(void) {
803835
}
804836

805837
op(_RETURN_VALUE, (retval -- res)) {
806-
JitOptRef temp = retval;
838+
JitOptRef temp = PyJitRef_Wrap(PyJitRef_Unwrap(retval));
807839
DEAD(retval);
808840
SAVE_STACK();
809841
ctx->frame->stack_pointer = stack_pointer;

0 commit comments

Comments
 (0)