Skip to content

Commit fed64f1

Browse files
yoneymeta-codesync[bot]
authored andcommitted
Add free-threaded JIT list subscript tests
Summary: Add concurrent reader/writer coverage for list subscripting with specialized opcodes enabled and disabled. Reviewed By: alexmalyshev Differential Revision: D115442851 fbshipit-source-id: b31c680bcc476c01d69a42915746419bd9f6ccd0
1 parent 358b016 commit fed64f1

1 file changed

Lines changed: 113 additions & 0 deletions

File tree

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Copyright (c) Meta Platforms, Inc. and affiliates.
2+
3+
# pyre-strict
4+
5+
"""Free-threaded JIT regression tests for list subscripts."""
6+
7+
import dis
8+
import os
9+
import threading
10+
import unittest
11+
from collections.abc import Callable
12+
from concurrent.futures import ThreadPoolExecutor
13+
14+
import cinderx.jit
15+
from cinderx.test_support import run_in_subprocess
16+
17+
18+
class JITListTest(unittest.TestCase):
19+
def warm_up_list_opcode(
20+
self,
21+
read_item: Callable[[list[str]], str],
22+
) -> None:
23+
values = ["w"]
24+
cinderx.jit.jit_suppress(read_item)
25+
for _ in range(100):
26+
read_item(values)
27+
cinderx.jit.jit_unsuppress(read_item)
28+
opnames = {
29+
instruction.opname
30+
for instruction in dis.get_instructions(read_item, adaptive=True)
31+
}
32+
self.assertIn("BINARY_OP_SUBSCR_LIST_INT", opnames)
33+
34+
def exercise_concurrent_access(
35+
self,
36+
read_item: Callable[[list[str]], str],
37+
) -> None:
38+
worker_count = 10
39+
reader_count = worker_count // 2
40+
writer_count = worker_count - reader_count
41+
iterations = 10_000
42+
start = threading.Barrier(worker_count)
43+
values = ["w"]
44+
45+
@cinderx.jit.jit_suppress
46+
def reader() -> bool:
47+
start.wait()
48+
for _ in range(iterations):
49+
if not read_item(values).startswith("w"):
50+
return False
51+
return True
52+
53+
@cinderx.jit.jit_suppress
54+
def writer(prefix: str) -> None:
55+
start.wait()
56+
for i in range(iterations):
57+
values[0] = f"w{prefix}_{i}"
58+
59+
with ThreadPoolExecutor(max_workers=worker_count) as executor:
60+
reader_futures = [executor.submit(reader) for _ in range(reader_count)]
61+
writer_futures = [
62+
executor.submit(writer, str(worker)) for worker in range(writer_count)
63+
]
64+
65+
self.assertEqual(
66+
[future.result() for future in reader_futures],
67+
[True] * reader_count,
68+
)
69+
for future in writer_futures:
70+
future.result()
71+
72+
self.assertTrue(values[0].startswith("w"))
73+
74+
@unittest.skipUnless(hasattr(os, "fork"), "fork not available on Windows")
75+
@run_in_subprocess
76+
def test_concurrent_subscript_without_specialized_opcodes(self) -> None:
77+
"""Keep generic HIR when compiling an adaptive list opcode."""
78+
cinderx.jit.disable_specialized_opcodes()
79+
80+
def read_item(values: list[str]) -> str:
81+
return values[0]
82+
83+
self.warm_up_list_opcode(read_item)
84+
85+
self.assertTrue(cinderx.jit.force_compile(read_item))
86+
opcode_counts = cinderx.jit.get_function_hir_opcode_counts(read_item)
87+
if opcode_counts is None:
88+
self.fail("No HIR opcode counts for compiled read_item")
89+
self.assertIn("BinaryOp", opcode_counts)
90+
self.assertNotIn("ListSubscr", opcode_counts)
91+
self.assertNotIn("LoadArrayItem", opcode_counts)
92+
93+
self.exercise_concurrent_access(read_item)
94+
95+
@unittest.skipUnless(hasattr(os, "fork"), "fork not available on Windows")
96+
@run_in_subprocess
97+
def test_concurrent_subscript_with_simplify(self) -> None:
98+
"""Use the owned-reference ListSubscr path for exact lists."""
99+
cinderx.jit.enable_specialized_opcodes()
100+
101+
def read_item(values: list[str]) -> str:
102+
return values[0]
103+
104+
self.warm_up_list_opcode(read_item)
105+
106+
self.assertTrue(cinderx.jit.force_compile(read_item))
107+
opcode_counts = cinderx.jit.get_function_hir_opcode_counts(read_item)
108+
if opcode_counts is None:
109+
self.fail("No HIR opcode counts for compiled read_item")
110+
self.assertIn("ListSubscr", opcode_counts)
111+
self.assertNotIn("LoadArrayItem", opcode_counts)
112+
113+
self.exercise_concurrent_access(read_item)

0 commit comments

Comments
 (0)