Skip to content

gh-159580: use _Py_INCREF_TYPE in object.__class__ - #160424

Merged
kumaraditya303 merged 1 commit into
python:mainfrom
kumaraditya303:__class__
Oct 23, 2026
Merged

kumaraditya303 merged 1 commit into
python:mainfrom
kumaraditya303:__class__

Conversation

@kumaraditya303

@kumaraditya303 kumaraditya303 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

@bedevere-app bedevere-app Bot added awaiting core review type-feature A feature request or enhancement labels Oct 23, 2026
@kumaraditya303 kumaraditya303 added skip news and removed type-feature A feature request or enhancement labels Oct 23, 2026
@kumaraditya303
kumaraditya303 enabled auto-merge (squash) October 23, 2026 08:33
@kumaraditya303
kumaraditya303 merged commit b1e32ff into python:main Oct 23, 2026
57 of 61 checks passed
@kumaraditya303
kumaraditya303 deleted the __class__ branch October 23, 2026 08:34
@eendebakpt

Copy link
Copy Markdown
Contributor

Looks good. I asked claude for more places where this is relevant:

  1. Objects/typeobject.c:5116 type_vectorcall, the one-argument type(x) call. CALL_TYPE_1 already borrows on the free-threaded build (heap types are deferred-refcounted), but this path is still hit by map(type, xs), partial, key=type and any C caller.
  2. Objects/typeobject.c:12681 supercheck. Every super().method() through _PySuper_Lookup does an incref/decref pair on Py_TYPE(obj) (lines 12681 and 12730). Both ends are visible, so this can use _Py_INCREF_TYPE / _Py_DECREF_TYPE as a pair.
  3. Python/errors.c:242 _PyErr_SetObject. Every exception raised from C does Py_NewRef(Py_TYPE(value)), and _PyErr_Restore stores only the value and then does Py_DECREF(type) (line 100). For user-defined exception classes this is a contended pair per raise. Calling _PyErr_SetRaisedException directly would remove the pair entirely. Same pattern at errors.c:536 (_PyErr_Fetch) and pythonrun.c:715, but those are cold.
  4. Objects/abstract.c:45 PyObject_Type. Public API, used by extensions.
  5. Objects/typeobject.c:2422 type_call one-argument path. Same as 1 but only reached through tp_call with a tuple.

(not in the hot path)

  1. Modules/_abc.c:639 and Modules/_pickle.c:4262. Fallbacks that only run when __class__ is missing; the common path goes through GetOptionalAttr(__class__), which this PR already covers.
  2. Modules/_functoolsmodule.c:1283 and :1288. lru_cache(typed=True) puts the argument types into the key tuple on every call.
  3. Objects/typeobject.c:8166 reduce_newobj, used by copy and pickle.
  4. Python/bltinmodule.c:164 __build_class__ metaclass selection. Class creation, cold.
  5. Objects/unicodeobject.c:3061 %T format. Error-message paths only.

Do this as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants