Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit4759ba6

Browse files
authored
gh-127022: SimplifyPyStackRef_FromPyObjectSteal (#127024)
This gets rid of the immortal check in `PyStackRef_FromPyObjectSteal()`.Overall, this improves performance about 2% in the free threadingbuild.This also renames `PyStackRef_Is()` to `PyStackRef_IsExactly()` becausethe macro requires that the tag bits of the arguments match, which isonly true in certain special cases.
1 parent8214e0f commit4759ba6

File tree

5 files changed

+57
-72
lines changed

5 files changed

+57
-72
lines changed

‎Include/internal/pycore_stackref.h‎

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,7 @@ _PyStackRef_FromPyObjectSteal(PyObject *obj)
9999
assert(obj!=NULL);
100100
// Make sure we don't take an already tagged value.
101101
assert(((uintptr_t)obj&Py_TAG_BITS)==0);
102-
unsignedinttag=_Py_IsImmortal(obj) ? (Py_TAG_DEFERRED) :Py_TAG_PTR;
103-
return ((_PyStackRef){.bits= ((uintptr_t)(obj)) |tag});
102+
return (_PyStackRef){ .bits= (uintptr_t)obj };
104103
}
105104
# definePyStackRef_FromPyObjectSteal(obj) _PyStackRef_FromPyObjectSteal(_PyObject_CAST(obj))
106105

@@ -190,9 +189,16 @@ static const _PyStackRef PyStackRef_NULL = { .bits = 0 };
190189

191190
#endif// Py_GIL_DISABLED
192191

193-
// Note: this is a macro because MSVC (Windows) has trouble inlining it.
192+
// Check if a stackref is exactly the same as another stackref, including the
193+
// the deferred bit. This can only be used safely if you know that the deferred
194+
// bits of `a` and `b` match.
195+
#definePyStackRef_IsExactly(a,b) \
196+
(assert(((a).bits & Py_TAG_BITS) == ((b).bits & Py_TAG_BITS)), (a).bits == (b).bits)
194197

195-
#definePyStackRef_Is(a,b) ((a).bits == (b).bits)
198+
// Checks that mask out the deferred bit in the free threading build.
199+
#definePyStackRef_IsNone(ref) (PyStackRef_AsPyObjectBorrow(ref) == Py_None)
200+
#definePyStackRef_IsTrue(ref) (PyStackRef_AsPyObjectBorrow(ref) == Py_True)
201+
#definePyStackRef_IsFalse(ref) (PyStackRef_AsPyObjectBorrow(ref) == Py_False)
196202

197203
// Converts a PyStackRef back to a PyObject *, converting the
198204
// stackref to a new reference.

‎Python/bytecodes.c‎

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ dummy_func(
376376

377377
pureinst(UNARY_NOT, (value--res)) {
378378
assert(PyStackRef_BoolCheck(value));
379-
res=PyStackRef_Is(value,PyStackRef_False)
379+
res=PyStackRef_IsFalse(value)
380380
?PyStackRef_True :PyStackRef_False;
381381
DEAD(value);
382382
}
@@ -441,7 +441,7 @@ dummy_func(
441441

442442
inst(TO_BOOL_NONE, (unused/1,unused/2,value--res)) {
443443
// This one is a bit weird, because we expect *some* failures:
444-
EXIT_IF(!PyStackRef_Is(value,PyStackRef_None));
444+
EXIT_IF(!PyStackRef_IsNone(value));
445445
DEAD(value);
446446
STAT_INC(TO_BOOL,hit);
447447
res=PyStackRef_False;
@@ -651,9 +651,7 @@ dummy_func(
651651
// specializations, but there is no output.
652652
// At the end we just skip over the STORE_FAST.
653653
op(_BINARY_OP_INPLACE_ADD_UNICODE, (left,right--)) {
654-
#ifndefNDEBUG
655654
PyObject*left_o=PyStackRef_AsPyObjectBorrow(left);
656-
#endif
657655
PyObject*right_o=PyStackRef_AsPyObjectBorrow(right);
658656

659657
intnext_oparg;
@@ -664,7 +662,7 @@ dummy_func(
664662
next_oparg=CURRENT_OPERAND0();
665663
#endif
666664
_PyStackRef*target_local=&GETLOCAL(next_oparg);
667-
DEOPT_IF(!PyStackRef_Is(*target_local,left));
665+
DEOPT_IF(PyStackRef_AsPyObjectBorrow(*target_local)!=left_o);
668666
STAT_INC(BINARY_OP,hit);
669667
/* Handle `left = left + right` or `left += right` for str.
670668
*
@@ -1141,7 +1139,7 @@ dummy_func(
11411139
gen_frame->previous=frame;
11421140
DISPATCH_INLINED(gen_frame);
11431141
}
1144-
if (PyStackRef_Is(v,PyStackRef_None)&&PyIter_Check(receiver_o)) {
1142+
if (PyStackRef_IsNone(v)&&PyIter_Check(receiver_o)) {
11451143
retval_o=Py_TYPE(receiver_o)->tp_iternext(receiver_o);
11461144
}
11471145
else {
@@ -1249,7 +1247,7 @@ dummy_func(
12491247
inst(POP_EXCEPT, (exc_value-- )) {
12501248
_PyErr_StackItem*exc_info=tstate->exc_info;
12511249
Py_XSETREF(exc_info->exc_value,
1252-
PyStackRef_Is(exc_value,PyStackRef_None)
1250+
PyStackRef_IsNone(exc_value)
12531251
?NULL :PyStackRef_AsPyObjectSteal(exc_value));
12541252
}
12551253

@@ -2502,13 +2500,7 @@ dummy_func(
25022500
}
25032501

25042502
inst(IS_OP, (left,right--b)) {
2505-
#ifdefPy_GIL_DISABLED
2506-
// On free-threaded builds, objects are conditionally immortalized.
2507-
// So their bits don't always compare equally.
25082503
intres=Py_Is(PyStackRef_AsPyObjectBorrow(left),PyStackRef_AsPyObjectBorrow(right)) ^oparg;
2509-
#else
2510-
intres=PyStackRef_Is(left,right) ^oparg;
2511-
#endif
25122504
DECREF_INPUTS();
25132505
b=res ?PyStackRef_True :PyStackRef_False;
25142506
}
@@ -2715,22 +2707,22 @@ dummy_func(
27152707

27162708
replacedop(_POP_JUMP_IF_FALSE, (cond-- )) {
27172709
assert(PyStackRef_BoolCheck(cond));
2718-
intflag=PyStackRef_Is(cond,PyStackRef_False);
2710+
intflag=PyStackRef_IsFalse(cond);
27192711
DEAD(cond);
27202712
RECORD_BRANCH_TAKEN(this_instr[1].cache,flag);
27212713
JUMPBY(oparg*flag);
27222714
}
27232715

27242716
replacedop(_POP_JUMP_IF_TRUE, (cond-- )) {
27252717
assert(PyStackRef_BoolCheck(cond));
2726-
intflag=PyStackRef_Is(cond,PyStackRef_True);
2718+
intflag=PyStackRef_IsTrue(cond);
27272719
DEAD(cond);
27282720
RECORD_BRANCH_TAKEN(this_instr[1].cache,flag);
27292721
JUMPBY(oparg*flag);
27302722
}
27312723

27322724
op(_IS_NONE, (value--b)) {
2733-
if (PyStackRef_Is(value,PyStackRef_None)) {
2725+
if (PyStackRef_IsNone(value)) {
27342726
b=PyStackRef_True;
27352727
DEAD(value);
27362728
}
@@ -3774,7 +3766,7 @@ dummy_func(
37743766

37753767
inst(EXIT_INIT_CHECK, (should_be_none-- )) {
37763768
assert(STACK_LEVEL()==2);
3777-
if (!PyStackRef_Is(should_be_none,PyStackRef_None)) {
3769+
if (!PyStackRef_IsNone(should_be_none)) {
37783770
PyErr_Format(PyExc_TypeError,
37793771
"__init__() should return None, not '%.200s'",
37803772
Py_TYPE(PyStackRef_AsPyObjectBorrow(should_be_none))->tp_name);
@@ -4734,7 +4726,7 @@ dummy_func(
47344726
inst(INSTRUMENTED_POP_JUMP_IF_TRUE, (unused/1-- )) {
47354727
_PyStackRefcond=POP();
47364728
assert(PyStackRef_BoolCheck(cond));
4737-
intflag=PyStackRef_Is(cond,PyStackRef_True);
4729+
intflag=PyStackRef_IsTrue(cond);
47384730
intoffset=flag*oparg;
47394731
RECORD_BRANCH_TAKEN(this_instr[1].cache,flag);
47404732
INSTRUMENTED_JUMP(this_instr,next_instr+offset,PY_MONITORING_EVENT_BRANCH);
@@ -4743,15 +4735,15 @@ dummy_func(
47434735
inst(INSTRUMENTED_POP_JUMP_IF_FALSE, (unused/1-- )) {
47444736
_PyStackRefcond=POP();
47454737
assert(PyStackRef_BoolCheck(cond));
4746-
intflag=PyStackRef_Is(cond,PyStackRef_False);
4738+
intflag=PyStackRef_IsFalse(cond);
47474739
intoffset=flag*oparg;
47484740
RECORD_BRANCH_TAKEN(this_instr[1].cache,flag);
47494741
INSTRUMENTED_JUMP(this_instr,next_instr+offset,PY_MONITORING_EVENT_BRANCH);
47504742
}
47514743

47524744
inst(INSTRUMENTED_POP_JUMP_IF_NONE, (unused/1-- )) {
47534745
_PyStackRefvalue_stackref=POP();
4754-
intflag=PyStackRef_Is(value_stackref,PyStackRef_None);
4746+
intflag=PyStackRef_IsNone(value_stackref);
47554747
intoffset;
47564748
if (flag) {
47574749
offset=oparg;
@@ -4767,7 +4759,7 @@ dummy_func(
47674759
inst(INSTRUMENTED_POP_JUMP_IF_NOT_NONE, (unused/1-- )) {
47684760
_PyStackRefvalue_stackref=POP();
47694761
intoffset;
4770-
intnflag=PyStackRef_Is(value_stackref,PyStackRef_None);
4762+
intnflag=PyStackRef_IsNone(value_stackref);
47714763
if (nflag) {
47724764
offset=0;
47734765
}
@@ -4802,21 +4794,21 @@ dummy_func(
48024794
///////// Tier-2 only opcodes /////////
48034795

48044796
op (_GUARD_IS_TRUE_POP, (flag-- )) {
4805-
intis_true=PyStackRef_Is(flag,PyStackRef_True);
4797+
intis_true=PyStackRef_IsTrue(flag);
48064798
DEAD(flag);
48074799
SYNC_SP();
48084800
EXIT_IF(!is_true);
48094801
}
48104802

48114803
op (_GUARD_IS_FALSE_POP, (flag-- )) {
4812-
intis_false=PyStackRef_Is(flag,PyStackRef_False);
4804+
intis_false=PyStackRef_IsFalse(flag);
48134805
DEAD(flag);
48144806
SYNC_SP();
48154807
EXIT_IF(!is_false);
48164808
}
48174809

48184810
op (_GUARD_IS_NONE_POP, (val-- )) {
4819-
intis_none=PyStackRef_Is(val,PyStackRef_None);
4811+
intis_none=PyStackRef_IsNone(val);
48204812
if (!is_none) {
48214813
PyStackRef_CLOSE(val);
48224814
SYNC_SP();
@@ -4826,7 +4818,7 @@ dummy_func(
48264818
}
48274819

48284820
op (_GUARD_IS_NOT_NONE_POP, (val-- )) {
4829-
intis_none=PyStackRef_Is(val,PyStackRef_None);
4821+
intis_none=PyStackRef_IsNone(val);
48304822
PyStackRef_CLOSE(val);
48314823
SYNC_SP();
48324824
EXIT_IF(is_none);

‎Python/executor_cases.c.h‎

Lines changed: 10 additions & 18 deletions
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp