@@ -540,6 +540,47 @@ fold_binops_on_constants(unsigned char *codestr, PyObject *consts)
540540 return 1 ;
541541}
542542
543+ /* Replace LOAD_CONST tuple with LOAD_CONST frozenset in the context
544+ of a single-use constant for "in" and "not in" tests.
545+ */
546+ int
547+ try_set_conversion (unsigned char * codestr , PyObject * consts )
548+ {
549+ PyObject * newconst , * constant ;
550+ int arg , len_consts ;
551+
552+ /* Pre-conditions */
553+ assert (PyList_CheckExact (consts ));
554+ assert (codestr [0 ] == LOAD_CONST );
555+ assert (codestr [3 ] == COMPARE_OP );
556+ assert (GETARG (codestr , 3 ) == 6 || GETARG (codestr , 3 ) == 7 );
557+
558+ /* Attempt to convert constant to a frozenset. Bail-out with no
559+ changes if the tuple contains unhashable values. */
560+ arg = GETARG (codestr , 0 );
561+ constant = PyList_GET_ITEM (consts , arg );
562+ if (constant -> ob_type != & PyTuple_Type )
563+ return 0 ;
564+ newconst = PyObject_CallFunctionObjArgs (
565+ (PyObject * )& PyFrozenSet_Type , constant , NULL );
566+ if (newconst == NULL ) {
567+ PyErr_Clear ();
568+ return 0 ;
569+ }
570+
571+ /* Append new constant onto consts list.*/
572+ len_consts = PyList_GET_SIZE (consts );
573+ if (PyList_Append (consts , newconst )) {
574+ Py_DECREF (newconst );
575+ return 0 ;
576+ }
577+ Py_DECREF (newconst );
578+
579+ /* Write new LOAD_CONST newconst on top of LOAD_CONST oldconst */
580+ SETARG (codestr , 0 , len_consts );
581+ return 1 ;
582+ }
583+
543584static unsigned int *
544585markblocks (unsigned char * code , int len )
545586{
@@ -665,9 +706,15 @@ optimize_code(PyObject *code, PyObject* consts, PyObject *names, PyObject *linen
665706 /* not a is b --> a is not b
666707 not a in b --> a not in b
667708 not a is not b --> a is b
668- not a not in b --> a in b */
709+ not a not in b --> a in b
710+
711+ a in c --> a in frozenset(c)
712+ where c is a constant tuple of hashable values
713+ */
669714 case COMPARE_OP :
670715 j = GETARG (codestr , i );
716+ if (lastlc >= 1 && (j == 6 || j == 7 ) && ISBASICBLOCK (blocks ,i - 3 ,6 ))
717+ try_set_conversion (& codestr [i - 3 ], consts );
671718 if (j < 6 || j > 9 ||
672719 codestr [i + 3 ] != UNARY_NOT ||
673720 !ISBASICBLOCK (blocks ,i ,4 ))
0 commit comments