@@ -663,32 +663,33 @@ static int specialize_attr_loadmethod(PyObject* owner, _Py_CODEUNIT* instr, PyOb |
663 | 663 | PyObject* descr, DescriptorClassification kind); |
664 | 664 | static int specialize_class_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject* name); |
665 | 665 |
|
666 | | -int |
| 666 | +void |
667 | 667 | _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) |
668 | 668 | { |
669 | 669 | assert(_PyOpcode_Caches[LOAD_ATTR] == INLINE_CACHE_ENTRIES_LOAD_ATTR); |
670 | 670 | _PyAttrCache *cache = (_PyAttrCache *)(instr + 1); |
| 671 | + PyTypeObject *type = Py_TYPE(owner); |
| 672 | + if (!_PyType_IsReady(type)) { |
| 673 | + // We *might* not really need this check, but we inherited it from |
| 674 | + // PyObject_GenericGetAttr and friends... and this way we still do the |
| 675 | + // right thing if someone forgets to call PyType_Ready(type): |
| 676 | + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER); |
| 677 | + goto fail; |
| 678 | + } |
671 | 679 | if (PyModule_CheckExact(owner)) { |
672 | | - int err = specialize_module_load_attr(owner, instr, name, LOAD_ATTR, |
673 | | - LOAD_ATTR_MODULE); |
674 | | - if (err) { |
| 680 | + if (specialize_module_load_attr(owner, instr, name, LOAD_ATTR, |
| 681 | + LOAD_ATTR_MODULE)) |
| 682 | + { |
675 | 683 | goto fail; |
676 | 684 | } |
677 | 685 | goto success; |
678 | 686 | } |
679 | 687 | if (PyType_Check(owner)) { |
680 | | - int err = specialize_class_load_attr(owner, instr, name); |
681 | | - if (err) { |
| 688 | + if (specialize_class_load_attr(owner, instr, name)) { |
682 | 689 | goto fail; |
683 | 690 | } |
684 | 691 | goto success; |
685 | 692 | } |
686 | | - PyTypeObject *type = Py_TYPE(owner); |
687 | | - if (type->tp_dict == NULL) { |
688 | | - if (PyType_Ready(type) < 0) { |
689 | | - return -1; |
690 | | - } |
691 | | - } |
692 | 693 | PyObject *descr = NULL; |
693 | 694 | DescriptorClassification kind = analyze_descriptor(type, name, &descr, 0); |
694 | 695 | assert(descr != NULL || kind == ABSENT || kind == GETSET_OVERRIDDEN); |
@@ -803,35 +804,36 @@ _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) |
803 | 804 | case ABSENT: |
804 | 805 | break; |
805 | 806 | } |
806 | | - int err = specialize_dict_access( |
807 | | - owner, instr, type, kind, name, |
808 | | - LOAD_ATTR, LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT |
809 | | - ); |
810 | | - if (err < 0) { |
811 | | - return -1; |
812 | | - } |
813 | | - if (err) { |
| 807 | + if (specialize_dict_access(owner, instr, type, kind, name, LOAD_ATTR, |
| 808 | + LOAD_ATTR_INSTANCE_VALUE, LOAD_ATTR_WITH_HINT)) |
| 809 | + { |
814 | 810 | goto success; |
815 | 811 | } |
816 | 812 | fail: |
817 | 813 | STAT_INC(LOAD_ATTR, failure); |
818 | 814 | assert(!PyErr_Occurred()); |
819 | 815 | _Py_SET_OPCODE(*instr, LOAD_ATTR); |
820 | 816 | cache->counter = adaptive_counter_backoff(cache->counter); |
821 | | - return 0; |
| 817 | + return; |
822 | 818 | success: |
823 | 819 | STAT_INC(LOAD_ATTR, success); |
824 | 820 | assert(!PyErr_Occurred()); |
825 | 821 | cache->counter = adaptive_counter_cooldown(); |
826 | | - return 0; |
827 | 822 | } |
828 | 823 |
|
829 | | -int |
| 824 | +void |
830 | 825 | _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) |
831 | 826 | { |
832 | 827 | assert(_PyOpcode_Caches[STORE_ATTR] == INLINE_CACHE_ENTRIES_STORE_ATTR); |
833 | 828 | _PyAttrCache *cache = (_PyAttrCache *)(instr + 1); |
834 | 829 | PyTypeObject *type = Py_TYPE(owner); |
| 830 | + if (!_PyType_IsReady(type)) { |
| 831 | + // We *might* not really need this check, but we inherited it from |
| 832 | + // PyObject_GenericSetAttr and friends... and this way we still do the |
| 833 | + // right thing if someone forgets to call PyType_Ready(type): |
| 834 | + SPECIALIZATION_FAIL(LOAD_ATTR, SPEC_FAIL_OTHER); |
| 835 | + goto fail; |
| 836 | + } |
835 | 837 | if (PyModule_CheckExact(owner)) { |
836 | 838 | SPECIALIZATION_FAIL(STORE_ATTR, SPEC_FAIL_OVERRIDDEN); |
837 | 839 | goto fail; |
@@ -890,28 +892,21 @@ _Py_Specialize_StoreAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name) |
890 | 892 | case ABSENT: |
891 | 893 | break; |
892 | 894 | } |
893 | | - |
894 | | - int err = specialize_dict_access( |
895 | | - owner, instr, type, kind, name, |
896 | | - STORE_ATTR, STORE_ATTR_INSTANCE_VALUE, STORE_ATTR_WITH_HINT |
897 | | - ); |
898 | | - if (err < 0) { |
899 | | - return -1; |
900 | | - } |
901 | | - if (err) { |
| 895 | + if (specialize_dict_access(owner, instr, type, kind, name, STORE_ATTR, |
| 896 | + STORE_ATTR_INSTANCE_VALUE, STORE_ATTR_WITH_HINT)) |
| 897 | + { |
902 | 898 | goto success; |
903 | 899 | } |
904 | 900 | fail: |
905 | 901 | STAT_INC(STORE_ATTR, failure); |
906 | 902 | assert(!PyErr_Occurred()); |
907 | 903 | _Py_SET_OPCODE(*instr, STORE_ATTR); |
908 | 904 | cache->counter = adaptive_counter_backoff(cache->counter); |
909 | | - return 0; |
| 905 | + return; |
910 | 906 | success: |
911 | 907 | STAT_INC(STORE_ATTR, success); |
912 | 908 | assert(!PyErr_Occurred()); |
913 | 909 | cache->counter = adaptive_counter_cooldown(); |
914 | | - return 0; |
915 | 910 | } |
916 | 911 |
|
917 | 912 |
|
|