@@ -565,6 +565,7 @@ translate_bytecode_to_trace(
565
565
code -> co_firstlineno ,
566
566
2 * INSTR_IP (initial_instr , code ));
567
567
ADD_TO_TRACE (_START_EXECUTOR , 0 , (uintptr_t )instr , INSTR_IP (instr , code ));
568
+ ADD_TO_TRACE (_MAKE_WARM , 0 , 0 , 0 );
568
569
uint32_t target = 0 ;
569
570
570
571
for (;;) {
@@ -1194,6 +1195,9 @@ make_executor_from_uops(_PyUOpInstruction *buffer, int length, const _PyBloomFil
1194
1195
executor -> jit_code = NULL ;
1195
1196
executor -> jit_side_entry = NULL ;
1196
1197
executor -> jit_size = 0 ;
1198
+ // This is initialized to true so we can prevent the executor
1199
+ // from being immediately detected as cold and invalidated.
1200
+ executor -> vm_data .warm = true;
1197
1201
if (_PyJIT_Compile (executor , executor -> trace , length )) {
1198
1202
Py_DECREF (executor );
1199
1203
return NULL ;
@@ -1659,4 +1663,42 @@ _Py_Executors_InvalidateAll(PyInterpreterState *interp, int is_invalidation)
1659
1663
}
1660
1664
}
1661
1665
1666
+ void
1667
+ _Py_Executors_InvalidateCold (PyInterpreterState * interp )
1668
+ {
1669
+ /* Walk the list of executors */
1670
+ /* TO DO -- Use a tree to avoid traversing as many objects */
1671
+ PyObject * invalidate = PyList_New (0 );
1672
+ if (invalidate == NULL ) {
1673
+ goto error ;
1674
+ }
1675
+
1676
+ /* Clearing an executor can deallocate others, so we need to make a list of
1677
+ * executors to invalidate first */
1678
+ for (_PyExecutorObject * exec = interp -> executor_list_head ; exec != NULL ;) {
1679
+ assert (exec -> vm_data .valid );
1680
+ _PyExecutorObject * next = exec -> vm_data .links .next ;
1681
+
1682
+ if (!exec -> vm_data .warm && PyList_Append (invalidate , (PyObject * )exec ) < 0 ) {
1683
+ goto error ;
1684
+ }
1685
+ else {
1686
+ exec -> vm_data .warm = false;
1687
+ }
1688
+
1689
+ exec = next ;
1690
+ }
1691
+ for (Py_ssize_t i = 0 ; i < PyList_GET_SIZE (invalidate ); i ++ ) {
1692
+ _PyExecutorObject * exec = (_PyExecutorObject * )PyList_GET_ITEM (invalidate , i );
1693
+ executor_clear (exec );
1694
+ }
1695
+ Py_DECREF (invalidate );
1696
+ return ;
1697
+ error :
1698
+ PyErr_Clear ();
1699
+ Py_XDECREF (invalidate );
1700
+ // If we're truly out of memory, wiping out everything is a fine fallback
1701
+ _Py_Executors_InvalidateAll (interp , 0 );
1702
+ }
1703
+
1662
1704
#endif /* _Py_TIER2 */
0 commit comments