Skip to content

Commit 18f1d04

Browse files
committed
Also support non-native classes
1 parent df1ed84 commit 18f1d04

File tree

3 files changed

+25
-7
lines changed

3 files changed

+25
-7
lines changed

mypyc/irbuild/builder.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,10 @@ def new_tuple(self, items: list[Value], line: int) -> Value:
424424
def debug_print(self, toprint: str | Value) -> None:
425425
return self.builder.debug_print(toprint)
426426

427+
def set_immortal_if_free_threaded(self, v: Value, line: int) -> None:
428+
"""Make an object immortal on free-threaded builds (to avoid contention)."""
429+
self.builder.set_immortal_if_free_threaded(v, line)
430+
427431
# Helpers for IR building
428432

429433
def add_to_non_ext_dict(
@@ -433,6 +437,10 @@ def add_to_non_ext_dict(
433437
key_unicode = self.load_str(key)
434438
self.primitive_op(dict_set_item_op, [non_ext.dict, key_unicode, val], line)
435439

440+
# It's important that accessing class dictionary items from multiple threads
441+
# doesn't cause contention.
442+
self.builder.set_immortal_if_free_threaded(val, line)
443+
436444
def gen_import(self, id: str, line: int) -> None:
437445
self.imports[id] = None
438446

mypyc/irbuild/classdef.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
from abc import abstractmethod
66
from typing import Callable, Final
7-
import sys
87

98
from mypy.nodes import (
109
EXCLUDED_ENUM_ATTRIBUTES,
@@ -29,7 +28,7 @@
2928
is_class_var,
3029
)
3130
from mypy.types import Instance, UnboundType, get_proper_type
32-
from mypyc.common import PROPSET_PREFIX, IS_FREE_THREADED
31+
from mypyc.common import PROPSET_PREFIX
3332
from mypyc.ir.class_ir import ClassIR, NonExtClassInfo
3433
from mypyc.ir.func_ir import FuncDecl, FuncSignature
3534
from mypyc.ir.ops import (
@@ -82,7 +81,6 @@
8281
py_calc_meta_op,
8382
pytype_from_template_op,
8483
type_object_op,
85-
set_immortal_op,
8684
)
8785
from mypyc.subtype import is_subtype
8886

@@ -264,6 +262,9 @@ def finalize(self, ir: ClassIR) -> None:
264262
non_ext_class = load_non_ext_class(self.builder, ir, self.non_ext, self.cdef.line)
265263
non_ext_class = load_decorated_class(self.builder, self.cdef, non_ext_class)
266264

265+
# Try to avoid contention when using free threading.
266+
self.builder.set_immortal_if_free_threaded(non_ext_class, self.cdef.line)
267+
267268
# Save the decorated class
268269
self.builder.add(
269270
InitStatic(non_ext_class, self.cdef.name, self.builder.module_name, NAMESPACE_TYPE)
@@ -451,10 +452,11 @@ def allocate_class(builder: IRBuilder, cdef: ClassDef) -> Value:
451452
)
452453
# Create the class
453454
tp = builder.call_c(pytype_from_template_op, [template, tp_bases, modname], cdef.line)
454-
if IS_FREE_THREADED and sys.version_info >= (3, 14):
455-
# Set type object to be immortal, as otherwise reference count contention
456-
# can cause a massive performance hit in the worst case.
457-
builder.call_c(set_immortal_op, [tp], cdef.line)
455+
456+
# Set type object to be immortal if free threaded, as otherwise reference count contention
457+
# can cause a big performance hit.
458+
builder.set_immortal_if_free_threaded(tp, cdef.line)
459+
458460
# Immediately fix up the trait vtables, before doing anything with the class.
459461
ir = builder.mapper.type_to_ir[cdef.info]
460462
if not ir.is_trait and not ir.builtin_base:

mypyc/irbuild/ll_builder.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from __future__ import annotations
88

9+
import sys
910
from collections.abc import Sequence
1011
from typing import Callable, Final, Optional
1112

@@ -16,6 +17,7 @@
1617
from mypyc.common import (
1718
BITMAP_BITS,
1819
FAST_ISINSTANCE_MAX_SUBCLASSES,
20+
IS_FREE_THREADED,
1921
MAX_LITERAL_SHORT_INT,
2022
MAX_SHORT_INT,
2123
MIN_LITERAL_SHORT_INT,
@@ -164,6 +166,7 @@
164166
fast_isinstance_op,
165167
none_object_op,
166168
not_implemented_op,
169+
set_immortal_op,
167170
var_object_size,
168171
)
169172
from mypyc.primitives.registry import (
@@ -2322,6 +2325,11 @@ def new_tuple_with_length(self, length: Value, line: int) -> Value:
23222325
def int_to_float(self, n: Value, line: int) -> Value:
23232326
return self.primitive_op(int_to_float_op, [n], line)
23242327

2328+
def set_immortal_if_free_threaded(self, v: Value, line: int) -> None:
2329+
"""Make an object immortal on free-threaded builds (to avoid contention)."""
2330+
if IS_FREE_THREADED and sys.version_info >= (3, 14):
2331+
self.call_c(set_immortal_op, [v], line)
2332+
23252333
# Internal helpers
23262334

23272335
def decompose_union_helper(

0 commit comments

Comments
 (0)