Skip to content

Commit 9d77411

Browse files
authored
[SOT][3.14] fix func_closure lose、fix CALL_FUNCTION_EX kwargs_variable is NullVariable、add MF.MF_HAS_ANNOTATE、add LOAD_COMMON_CONSTANT opcode (#76451)
1 parent e1aa61e commit 9d77411

File tree

7 files changed

+56
-7
lines changed

7 files changed

+56
-7
lines changed

paddle/fluid/pybind/sot/cpython_internals.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -817,6 +817,15 @@ void Internal_PyFrame_ClearLocals(_PyInterpreterFrame *frame) {
817817
}
818818
#endif
819819

820+
#if PY_3_14_PLUS
821+
static inline PyGenObject *_PyGen_GetGeneratorFromFrame(
822+
_PyInterpreterFrame *frame) {
823+
assert(frame->owner == FRAME_OWNED_BY_GENERATOR);
824+
size_t offset_in_gen = offsetof(PyGenObject, gi_iframe);
825+
return (PyGenObject *)(((char *)frame) - offset_in_gen);
826+
}
827+
#endif
828+
820829
// Call on 3.11 _PyFrame_Clear is called on 3.12+ _PyFrame_ClearExceptCode
821830
#if PY_3_12_PLUS
822831
void Internal_PyFrame_ClearExceptCode(_PyInterpreterFrame *frame) {
@@ -825,8 +834,13 @@ void Internal_PyFrame_Clear(_PyInterpreterFrame *frame) {
825834
#endif
826835
/* It is the responsibility of the owning generator/coroutine
827836
* to have cleared the enclosing generator, if any. */
837+
#if PY_3_14_PLUS
838+
assert(frame->owner != FRAME_OWNED_BY_GENERATOR ||
839+
_PyGen_GetGeneratorFromFrame(frame)->gi_frame_state == FRAME_CLEARED);
840+
#else
828841
assert(frame->owner != FRAME_OWNED_BY_GENERATOR ||
829842
_PyFrame_GetGenerator(frame)->gi_frame_state == FRAME_CLEARED);
843+
#endif
830844
// GH-99729: Clearing this frame can expose the stack (via finalizers). It's
831845
// crucial that this frame has been unlinked, and is no longer visible:
832846
#if PY_3_13_PLUS

paddle/fluid/pybind/sot/eval_frame.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ inline static PyObject *eval_custom_code_py311_plus(PyThreadState *tstate,
102102
Py_INCREF(func);
103103

104104
#if PY_3_14_PLUS
105-
func->func_closure =
105+
func->func_closure = Py_XNewRef(
106106
((PyFunctionObject *)PyStackRef_AsPyObjectBorrow((frame)->f_funcobj))
107-
->func_closure;
107+
->func_closure);
108108
_PyStackRef func_stackref = PyStackRef_FromPyObjectSteal((PyObject *)func);
109109
_PyFrame_Initialize(
110110
tstate, shadow, func_stackref, NULL, code, 0, frame->previous);
@@ -151,7 +151,12 @@ inline static PyObject *eval_custom_code_py311_plus(PyThreadState *tstate,
151151
continue;
152152
}
153153
#if PY_3_14_PLUS
154-
fastlocals_new[PyLong_AsSize_t(index)] = PyStackRef_DUP(fastlocals_old[i]);
154+
if (PyStackRef_IsNull(fastlocals_old[i])) {
155+
fastlocals_new[PyLong_AsSize_t(index)] = PyStackRef_NULL;
156+
} else {
157+
fastlocals_new[PyLong_AsSize_t(index)] =
158+
PyStackRef_DUP(fastlocals_old[i]);
159+
}
155160
#else
156161
Py_XINCREF(fastlocals_old[i]);
157162
fastlocals_new[PyLong_AsSize_t(index)] = fastlocals_old[i];

python/paddle/jit/sot/opcode_translator/executor/instr_flag.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ class CONVERT_VALUE_FLAG:
3232
CV_ASCII = 3
3333

3434

35+
# https://github.com/python/cpython/blob/3.14/Include/internal/pycore_opcode_utils.h#L63-L68
3536
class MAKE_FUNCTION_FLAG:
37+
MF_HAS_ANNOTATE = 0x10
3638
MF_HAS_CLOSURE = 0x08
3739
MF_HAS_ANNOTATION = 0x04
3840
MF_HAS_KWDEFAULTS = 0x02
@@ -57,3 +59,14 @@ class IntrinsicsUnaryFunctions(Enum):
5759
INTRINSIC_TYPEVARTUPLE = 9 # no support, PEP 695
5860
INTRINSIC_SUBSCRIPT_GENERIC = 10 # no support, PEP 695
5961
INTRINSIC_TYPEALIAS = 11 # no support, PEP 695
62+
63+
64+
# https://github.com/python/cpython/blob/3.14/Include/internal/pycore_opcode_utils.h#L70-L76
65+
# All are attributes of 'builtins'
66+
LOAD_COMMON_CONSTANT_FLAG = (
67+
"AssertionError",
68+
"NotImplementedError",
69+
"tuple",
70+
"all",
71+
"any",
72+
)

python/paddle/jit/sot/opcode_translator/executor/opcode_executor.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@
7575
CALL_FUNCTION_EX_FLAG as CFE,
7676
CONVERT_VALUE_FLAG as CV,
7777
FORMAT_VALUE_FLAG as FV,
78+
LOAD_COMMON_CONSTANT_FLAG as LCC,
7879
MAKE_FUNCTION_FLAG as MF,
7980
IntrinsicsUnaryFunctions,
8081
)
@@ -965,6 +966,11 @@ def LOAD_CONST(self, instr: Instruction):
965966
var = self.vframe.consts[instr.arg]
966967
self.stack.push(var)
967968

969+
def LOAD_COMMON_CONSTANT(self, instr: Instruction):
970+
assert isinstance(instr.arg, int)
971+
const_var = self.vframe.builtins[LCC[instr.arg]]
972+
self.stack.push(const_var)
973+
968974
def MAKE_CELL(self, instr: Instruction):
969975
self.vframe.locals[instr.argval] = self.vframe.cells[instr.argval]
970976

@@ -1395,8 +1401,12 @@ def CALL_FUNCTION_KW(self, instr: Instruction):
13951401
@call_break_graph_decorator(push_n=1)
13961402
def CALL_FUNCTION_EX(self, instr: Instruction):
13971403
flag = instr.arg
1398-
if flag & CFE.CFE_HAS_KWARGS:
1404+
if sys.version_info >= (3, 14) or flag & CFE.CFE_HAS_KWARGS:
13991405
kwargs_variable = self.stack.pop()
1406+
if isinstance(kwargs_variable, NullVariable):
1407+
kwargs_variable = DictVariable(
1408+
{}, self._graph, DummyTracker([])
1409+
)
14001410
assert isinstance(kwargs_variable, DictVariable)
14011411
kwargs = kwargs_variable.get_wrapped_items()
14021412
else:
@@ -1599,7 +1609,7 @@ def attach_new_attribute(self, flag, related_list):
15991609
else:
16001610
closure = ()
16011611

1602-
if flag & MF.MF_HAS_ANNOTATION:
1612+
if flag & MF.MF_HAS_ANNOTATION or flag & MF.MF_HAS_ANNOTATE:
16031613
# can not set annotation in python env, skip it
16041614
related_list.append(self.stack.pop())
16051615

python/paddle/jit/sot/opcode_translator/executor/pycode_generator.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,8 @@ def gen_subscribe(self):
813813
return self.add_instr("BINARY_OP", arg=BINARY_OP_ARG_MAP["NB_SUBSCR"])
814814

815815
def gen_build_tuple(self, count):
816+
if sys.version_info >= (3, 14) and count == 0:
817+
return self.gen_load_const(())
816818
return self.add_instr("BUILD_TUPLE", arg=count, argval=count)
817819

818820
def gen_build_list(self, count):

python/paddle/jit/sot/opcode_translator/instruction_utils/opcode_info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
if sys.version_info >= (3, 11):
3030
UNCONDITIONAL_JUMP.add("JUMP_BACKWARD")
3131
RETURN = {"RETURN_VALUE"}
32-
if sys.version_info >= (3, 12):
32+
if (3, 12) <= sys.version_info < (3, 14):
3333
RETURN.add("RETURN_CONST")
3434

3535

test/sot/test_24_exceptions.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
import sys
1415
import unittest
1516

1617
from test_case_base import (
@@ -961,9 +962,13 @@ def foo_mod(x):
961962
0,
962963
)
963964
self.assert_results(foo_mod, 10)
965+
if sys.version_info >= (3, 14):
966+
zero_mod_msg = "division by zero"
967+
else:
968+
zero_mod_msg = "integer (.)*modulo by zero"
964969
self.assert_exceptions(
965970
ZeroDivisionError,
966-
"integer (.)*modulo by zero",
971+
zero_mod_msg,
967972
foo_mod,
968973
0,
969974
)

0 commit comments

Comments
 (0)