@@ -139,12 +139,11 @@ dummy_func(void) {
139139 if (sym_matches_type_version (owner , type_version )) {
140140 ADD_OP (_NOP , 0 , 0 );
141141 } else {
142- PyTypeObject * type = _PyType_LookupByVersion (type_version );
143- if (type ) {
144- if (sym_set_type_version (owner , type_version )) {
145- PyType_Watch (TYPE_WATCHER_ID , (PyObject * )type );
146- _Py_BloomFilter_Add (dependencies , type );
147- }
142+ PyTypeObject * probable_type = sym_get_probable_type (owner );
143+ if (probable_type -> tp_version_tag == type_version && sym_set_type_version (owner , type_version )) {
144+ // Promote the probable type version to a known one.
145+ PyType_Watch (TYPE_WATCHER_ID , (PyObject * )probable_type );
146+ _Py_BloomFilter_Add (dependencies , probable_type );
148147 }
149148 }
150149 }
@@ -1043,20 +1042,22 @@ dummy_func(void) {
10431042
10441043 op (_CHECK_AND_ALLOCATE_OBJECT , (type_version /2 , callable , self_or_null , args [oparg ] -- callable , self_or_null , args [oparg ])) {
10451044 (void )args ;
1046- PyTypeObject * type = _PyType_LookupByVersion (type_version );
1047- if (type ) {
1048- PyHeapTypeObject * cls = (PyHeapTypeObject * )type ;
1049- PyObject * init = FT_ATOMIC_LOAD_PTR_ACQUIRE (cls -> _spec_cache .init );
1050- if (init != NULL && PyFunction_Check (init )) {
1051- // Propagate the __init__ function so _CREATE_INIT_FRAME can
1052- // resolve the code object and continue optimizing.
1053- callable = sym_new_const (ctx , init );
1054- PyType_Watch (TYPE_WATCHER_ID , (PyObject * )type );
1055- _Py_BloomFilter_Add (dependencies , type );
1056- }
1057- else {
1058- callable = sym_new_not_null (ctx );
1059- }
1045+ PyObject * probable_callable = sym_get_probable_value (callable );
1046+ assert (probable_callable != NULL );
1047+ assert (PyType_Check (probable_callable ));
1048+ PyTypeObject * tp = (PyTypeObject * )probable_callable ;
1049+ if (tp -> tp_version_tag == type_version ) {
1050+ // If the type version has not changed since we last saw it,
1051+ // then we know this __init__ is definitely the same one as in the cache.
1052+ // We can promote callable to a known constant. This does not need a
1053+ // type watcher, as we do not remove this _CHECK_AND_ALLOCATE_OBJECT guard.
1054+ // TODO: split up _CHECK_AND_ALLOCATE_OBJECT to the check then alloate, so we can
1055+ // eliminate the check.
1056+ PyHeapTypeObject * cls = (PyHeapTypeObject * )probable_callable ;
1057+ PyObject * init = cls -> _spec_cache .init ;
1058+ assert (init != NULL );
1059+ assert (PyFunction_Check (init ));
1060+ callable = sym_new_const (ctx , init );
10601061 }
10611062 else {
10621063 callable = sym_new_not_null (ctx );
0 commit comments