Skip to content

Commit 6b2c84e

Browse files
authored
Merge branch 'main' into fix-issue-129250
2 parents dad90ca + 002c4e2 commit 6b2c84e

25 files changed

+278
-238
lines changed

.github/workflows/reusable-windows.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ env:
2424
2525
jobs:
2626
build:
27-
name: 'build and test (${{ inputs.arch }})'
27+
name: ${{ inputs.arch == 'arm64' && 'build' || 'build and test' }} (${{ inputs.arch }})
2828
runs-on: ${{ inputs.os }}
2929
timeout-minutes: 60
3030
env:

Include/cpython/longintrepr.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ typedef long stwodigits; /* signed variant of twodigits */
7676
- 1: Zero
7777
- 2: Negative
7878
79-
The third lowest bit of lv_tag is reserved for an immortality flag, but is
80-
not currently used.
79+
The third lowest bit of lv_tag is
80+
set to 1 for the small ints.
8181
8282
In a normalized number, ob_digit[ndigits-1] (the most significant
8383
digit) is never zero. Also, in all cases, for all valid i,

Include/cpython/pyatomic.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -574,15 +574,15 @@ static inline void _Py_atomic_fence_release(void);
574574

575575
#if _Py_USE_GCC_BUILTIN_ATOMICS
576576
# define Py_ATOMIC_GCC_H
577-
# include "cpython/pyatomic_gcc.h"
577+
# include "pyatomic_gcc.h"
578578
# undef Py_ATOMIC_GCC_H
579579
#elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_ATOMICS__)
580580
# define Py_ATOMIC_STD_H
581-
# include "cpython/pyatomic_std.h"
581+
# include "pyatomic_std.h"
582582
# undef Py_ATOMIC_STD_H
583583
#elif defined(_MSC_VER)
584584
# define Py_ATOMIC_MSC_H
585-
# include "cpython/pyatomic_msc.h"
585+
# include "pyatomic_msc.h"
586586
# undef Py_ATOMIC_MSC_H
587587
#else
588588
# error "no available pyatomic implementation for this platform/compiler"

Include/cpython/pythread.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ PyAPI_DATA(const long long) PY_TIMEOUT_MAX;
2222
*/
2323
# define NATIVE_TSS_KEY_T unsigned long
2424
#elif defined(HAVE_PTHREAD_STUBS)
25-
# include "cpython/pthread_stubs.h"
25+
# include "pthread_stubs.h"
2626
# define NATIVE_TSS_KEY_T pthread_key_t
2727
#else
2828
# error "Require native threads. See https://bugs.python.org/issue31370"

Include/internal/pycore_frame.h

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,6 @@ static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *
159159
// Don't leave a dangling pointer to the old frame when creating generators
160160
// and coroutines:
161161
dest->previous = NULL;
162-
163-
#ifdef Py_GIL_DISABLED
164-
PyCodeObject *co = _PyFrame_GetCode(dest);
165-
for (int i = stacktop; i < co->co_nlocalsplus + co->co_stacksize; i++) {
166-
dest->localsplus[i] = PyStackRef_NULL;
167-
}
168-
#endif
169162
}
170163

171164
#ifdef Py_GIL_DISABLED
@@ -222,16 +215,6 @@ _PyFrame_Initialize(
222215
for (int i = null_locals_from; i < code->co_nlocalsplus; i++) {
223216
frame->localsplus[i] = PyStackRef_NULL;
224217
}
225-
226-
#ifdef Py_GIL_DISABLED
227-
// On GIL disabled, we walk the entire stack in GC. Since stacktop
228-
// is not always in sync with the real stack pointer, we have
229-
// no choice but to traverse the entire stack.
230-
// This just makes sure we don't pass the GC invalid stack values.
231-
for (int i = code->co_nlocalsplus; i < code->co_nlocalsplus + code->co_stacksize; i++) {
232-
frame->localsplus[i] = PyStackRef_NULL;
233-
}
234-
#endif
235218
}
236219

237220
/* Gets the pointer to the locals array
@@ -405,13 +388,6 @@ _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int
405388
frame->lltrace = 0;
406389
#endif
407390
frame->return_offset = 0;
408-
409-
#ifdef Py_GIL_DISABLED
410-
assert(code->co_nlocalsplus == 0);
411-
for (int i = 0; i < code->co_stacksize; i++) {
412-
frame->localsplus[i] = PyStackRef_NULL;
413-
}
414-
#endif
415391
return frame;
416392
}
417393

Include/internal/pycore_long.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,14 @@ PyAPI_FUNC(int) _PyLong_Size_t_Converter(PyObject *, void *);
159159

160160
/* Long value tag bits:
161161
* 0-1: Sign bits value = (1-sign), ie. negative=2, positive=0, zero=1.
162-
* 2: Reserved for immortality bit
162+
* 2: Set to 1 for the small ints
163163
* 3+ Unsigned digit count
164164
*/
165165
#define SIGN_MASK 3
166166
#define SIGN_ZERO 1
167167
#define SIGN_NEGATIVE 2
168168
#define NON_SIZE_BITS 3
169+
#define IMMORTALITY_BIT_MASK (1 << 2)
169170

170171
/* The functions _PyLong_IsCompact and _PyLong_CompactValue are defined
171172
* in Include/cpython/longobject.h, since they need to be inline.
@@ -196,7 +197,7 @@ PyAPI_FUNC(int) _PyLong_Size_t_Converter(PyObject *, void *);
196197
static inline int
197198
_PyLong_IsNonNegativeCompact(const PyLongObject* op) {
198199
assert(PyLong_Check(op));
199-
return op->long_value.lv_tag <= (1 << NON_SIZE_BITS);
200+
return ((op->long_value.lv_tag & ~IMMORTALITY_BIT_MASK) <= (1 << NON_SIZE_BITS));
200201
}
201202

202203

@@ -298,7 +299,7 @@ _PyLong_FlipSign(PyLongObject *op) {
298299
.long_value = { \
299300
.lv_tag = TAG_FROM_SIGN_AND_SIZE( \
300301
(val) == 0 ? 0 : ((val) < 0 ? -1 : 1), \
301-
(val) == 0 ? 0 : 1), \
302+
(val) == 0 ? 0 : 1) | IMMORTALITY_BIT_MASK, \
302303
{ ((val) >= 0 ? (val) : -(val)) }, \
303304
} \
304305
}

Lib/subprocess.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,8 @@
4343
import builtins
4444
import errno
4545
import io
46-
import locale
4746
import os
4847
import time
49-
import signal
5048
import sys
5149
import threading
5250
import warnings
@@ -144,6 +142,8 @@ def __init__(self, returncode, cmd, output=None, stderr=None):
144142

145143
def __str__(self):
146144
if self.returncode and self.returncode < 0:
145+
# Lazy import to improve module import time
146+
import signal
147147
try:
148148
return "Command '%s' died with %r." % (
149149
self.cmd, signal.Signals(-self.returncode))
@@ -381,6 +381,8 @@ def _text_encoding():
381381
if sys.flags.utf8_mode:
382382
return "utf-8"
383383
else:
384+
# Lazy import to improve module import time
385+
import locale
384386
return locale.getencoding()
385387

386388

@@ -1664,6 +1666,9 @@ def send_signal(self, sig):
16641666
# Don't signal a process that we know has already died.
16651667
if self.returncode is not None:
16661668
return
1669+
1670+
# Lazy import to improve module import time
1671+
import signal
16671672
if sig == signal.SIGTERM:
16681673
self.terminate()
16691674
elif sig == signal.CTRL_C_EVENT:
@@ -1765,6 +1770,9 @@ def _posix_spawn(self, args, executable, env, restore_signals, close_fds,
17651770
"""Execute program using os.posix_spawn()."""
17661771
kwargs = {}
17671772
if restore_signals:
1773+
# Lazy import to improve module import time
1774+
import signal
1775+
17681776
# See _Py_RestoreSignals() in Python/pylifecycle.c
17691777
sigset = []
17701778
for signame in ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ'):
@@ -2214,9 +2222,13 @@ def send_signal(self, sig):
22142222
def terminate(self):
22152223
"""Terminate the process with SIGTERM
22162224
"""
2225+
# Lazy import to improve module import time
2226+
import signal
22172227
self.send_signal(signal.SIGTERM)
22182228

22192229
def kill(self):
22202230
"""Kill the process with SIGKILL
22212231
"""
2232+
# Lazy import to improve module import time
2233+
import signal
22222234
self.send_signal(signal.SIGKILL)

Lib/test/test_call.py

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import unittest
22
from test.support import (cpython_only, is_wasi, requires_limited_api, Py_DEBUG,
3-
set_recursion_limit, skip_on_s390x, skip_emscripten_stack_overflow)
3+
set_recursion_limit, skip_on_s390x, skip_emscripten_stack_overflow, import_helper)
44
try:
55
import _testcapi
66
except ImportError:
@@ -616,9 +616,6 @@ def testfunction_kw(self, *, kw):
616616
return self
617617

618618

619-
ADAPTIVE_WARMUP_DELAY = 2
620-
621-
622619
@unittest.skipIf(_testcapi is None, "requires _testcapi")
623620
class TestPEP590(unittest.TestCase):
624621

@@ -802,17 +799,18 @@ def __call__(self, *args):
802799

803800
def test_setvectorcall(self):
804801
from _testcapi import function_setvectorcall
802+
_testinternalcapi = import_helper.import_module("_testinternalcapi")
805803
def f(num): return num + 1
806804
assert_equal = self.assertEqual
807805
num = 10
808806
assert_equal(11, f(num))
809807
function_setvectorcall(f)
810-
# make sure specializer is triggered by running > 50 times
811-
for _ in range(10 * ADAPTIVE_WARMUP_DELAY):
808+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
812809
assert_equal("overridden", f(num))
813810

814811
def test_setvectorcall_load_attr_specialization_skip(self):
815812
from _testcapi import function_setvectorcall
813+
_testinternalcapi = import_helper.import_module("_testinternalcapi")
816814

817815
class X:
818816
def __getattribute__(self, attr):
@@ -824,11 +822,12 @@ def __getattribute__(self, attr):
824822
function_setvectorcall(X.__getattribute__)
825823
# make sure specialization doesn't trigger
826824
# when vectorcall is overridden
827-
for _ in range(ADAPTIVE_WARMUP_DELAY):
825+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
828826
assert_equal("overridden", x.a)
829827

830828
def test_setvectorcall_load_attr_specialization_deopt(self):
831829
from _testcapi import function_setvectorcall
830+
_testinternalcapi = import_helper.import_module("_testinternalcapi")
832831

833832
class X:
834833
def __getattribute__(self, attr):
@@ -840,12 +839,12 @@ def get_a(x):
840839
assert_equal = self.assertEqual
841840
x = X()
842841
# trigger LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN specialization
843-
for _ in range(ADAPTIVE_WARMUP_DELAY):
842+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
844843
assert_equal("a", get_a(x))
845844
function_setvectorcall(X.__getattribute__)
846845
# make sure specialized LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN
847846
# gets deopted due to overridden vectorcall
848-
for _ in range(ADAPTIVE_WARMUP_DELAY):
847+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
849848
assert_equal("overridden", get_a(x))
850849

851850
@requires_limited_api

Lib/test/test_dis.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -931,8 +931,6 @@ def extended_arg_quick():
931931
"""% (extended_arg_quick.__code__.co_firstlineno,
932932
extended_arg_quick.__code__.co_firstlineno + 1,)
933933

934-
ADAPTIVE_WARMUP_DELAY = 2
935-
936934
class DisTestBase(unittest.TestCase):
937935
"Common utilities for DisTests and TestDisTraceback"
938936

@@ -1259,8 +1257,9 @@ def test__try_compile_no_context_exc_on_error(self):
12591257
self.assertIsNone(e.__context__)
12601258

12611259
@staticmethod
1262-
def code_quicken(f, times=ADAPTIVE_WARMUP_DELAY):
1263-
for _ in range(times):
1260+
def code_quicken(f):
1261+
_testinternalcapi = import_helper.import_module("_testinternalcapi")
1262+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
12641263
f()
12651264

12661265
@cpython_only
@@ -1306,7 +1305,7 @@ def test_call_specialize(self):
13061305
@requires_specialization
13071306
def test_loop_quicken(self):
13081307
# Loop can trigger a quicken where the loop is located
1309-
self.code_quicken(loop_test, 4)
1308+
self.code_quicken(loop_test)
13101309
got = self.get_disassembly(loop_test, adaptive=True)
13111310
jit = import_helper.import_module("_testinternalcapi").jit_enabled()
13121311
expected = dis_loop_test_quickened_code.format("JIT" if jit else "NO_JIT")
@@ -1315,8 +1314,9 @@ def test_loop_quicken(self):
13151314
@cpython_only
13161315
@requires_specialization
13171316
def test_loop_with_conditional_at_end_is_quickened(self):
1317+
_testinternalcapi = import_helper.import_module("_testinternalcapi")
13181318
def for_loop_true(x):
1319-
for i in range(10):
1319+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
13201320
if x:
13211321
pass
13221322

@@ -1325,7 +1325,7 @@ def for_loop_true(x):
13251325
self.get_disassembly(for_loop_true, adaptive=True))
13261326

13271327
def for_loop_false(x):
1328-
for i in range(10):
1328+
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
13291329
if x:
13301330
pass
13311331

@@ -1335,7 +1335,7 @@ def for_loop_false(x):
13351335

13361336
def while_loop():
13371337
i = 0
1338-
while i < 10:
1338+
while i < _testinternalcapi.SPECIALIZATION_THRESHOLD:
13391339
i += 1
13401340

13411341
while_loop()

Lib/test/test_embed.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,9 @@ def test_simple_initialization_api(self):
384384
def test_specialized_static_code_gets_unspecialized_at_Py_FINALIZE(self):
385385
# https://github.com/python/cpython/issues/92031
386386

387-
code = textwrap.dedent("""\
387+
_testinternalcapi = import_helper.import_module("_testinternalcapi")
388+
389+
code = textwrap.dedent(f"""\
388390
import dis
389391
import importlib._bootstrap
390392
import opcode
@@ -411,7 +413,7 @@ def is_specialized(f):
411413
412414
assert not is_specialized(func), "specialized instructions found"
413415
414-
for i in range(test.test_dis.ADAPTIVE_WARMUP_DELAY):
416+
for _ in range({_testinternalcapi.SPECIALIZATION_THRESHOLD}):
415417
func(importlib._bootstrap, ["x"], lambda *args: None)
416418
417419
assert is_specialized(func), "no specialized instructions found"

0 commit comments

Comments
 (0)