Skip to content

Commit 1d841b0

Browse files
Rename to CALL_CFUNCTION and generalize to all c functions
1 parent 68e5451 commit 1d841b0

File tree

6 files changed

+39
-37
lines changed

6 files changed

+39
-37
lines changed

Include/internal/pycore_code.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,15 +338,15 @@ typedef enum {
338338
PYCFUNCTION_WITH_KEYWORDS = 4,
339339
_PYCFUNCTION_FAST = 5,
340340
_PYCFUNCTION_FAST_WITH_KEYWORDS = 6,
341-
PYCMETHOD = 7, /* Isn't normally used in builtins. */
341+
PYCMETHOD = 7,
342342
} _BuiltinCallKinds;
343343

344344
/* Specialization functions */
345345

346346
int _Py_Specialize_LoadAttr(PyObject *owner, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
347347
int _Py_Specialize_LoadGlobal(PyObject *globals, PyObject *builtins, _Py_CODEUNIT *instr, PyObject *name, SpecializedCacheEntry *cache);
348348
int _Py_Specialize_CallFunction(PyObject **stack_pointer, uint8_t original_oparg,
349-
PyObject *builtins, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
349+
_Py_CODEUNIT *instr, SpecializedCacheEntry *cache);
350350

351351
#define SPECIALIZATION_STATS 0
352352
#define SPECIALIZATION_STATS_DETAILED 0

Include/opcode.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/opcode.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,5 +230,5 @@ def jabs_op(name, op):
230230
"LOAD_GLOBAL_MODULE",
231231
"LOAD_GLOBAL_BUILTIN",
232232
"CALL_FUNCTION_ADAPTIVE",
233-
"CALL_FUNCTION_BUILTIN",
233+
"CALL_CFUNCTION",
234234
]

Python/ceval.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ Py_LOCAL_INLINE(PyObject *) call_function(
5555
static PyObject * do_call_core(
5656
PyThreadState *tstate, PyObject *func,
5757
PyObject *callargs, PyObject *kwdict, int use_tracing);
58-
Py_LOCAL_INLINE(PyObject *) call_function_builtin(
58+
Py_LOCAL_INLINE(PyObject *) call_cfunction(
5959
PyThreadState *tstate,
6060
_PyAdaptiveEntry *cache0,
6161
_PyCallFunctionCache *cache1,
@@ -4076,7 +4076,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
40764076
SpecializedCacheEntry *cache = GET_CACHE();
40774077
if (cache->adaptive.counter == 0) {
40784078
next_instr--;
4079-
if (_Py_Specialize_CallFunction(stack_pointer, cache->adaptive.original_oparg, BUILTINS(), next_instr, cache) < 0) {
4079+
if (_Py_Specialize_CallFunction(stack_pointer, cache->adaptive.original_oparg, next_instr, cache) < 0) {
40804080
goto error;
40814081
}
40824082
DISPATCH();
@@ -4088,7 +4088,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
40884088
JUMP_TO_INSTRUCTION(CALL_FUNCTION);
40894089
}
40904090
}
4091-
case TARGET(CALL_FUNCTION_BUILTIN): {
4091+
case TARGET(CALL_CFUNCTION): {
40924092
/* Builtin functions, WITHOUT keywords */
40934093
SpecializedCacheEntry *caches = GET_CACHE();
40944094
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
@@ -4099,7 +4099,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, PyFrameObject *f, int throwflag)
40994099

41004100
PyObject **sp, *res;
41014101
sp = stack_pointer;
4102-
res = call_function_builtin(tstate, cache0, cache1, &sp,
4102+
res = call_cfunction(tstate, cache0, cache1, &sp,
41034103
cache0->original_oparg, cframe.use_tracing);
41044104
stack_pointer = sp;
41054105
PUSH(res);
@@ -5920,9 +5920,9 @@ do_call_core(PyThreadState *tstate,
59205920
return PyObject_Call(func, callargs, kwdict);
59215921
}
59225922

5923-
/* Fast alternative for non-keyword calls to builtins. */
5923+
/* Fast alternative for non-keyword calls to C functions. */
59245924
Py_LOCAL_INLINE(PyObject *) _Py_HOT_FUNCTION
5925-
call_function_builtin(PyThreadState *tstate,
5925+
call_cfunction(PyThreadState *tstate,
59265926
_PyAdaptiveEntry *cache0,
59275927
_PyCallFunctionCache *cache1,
59285928
PyObject ***pp_stack,
@@ -5941,18 +5941,24 @@ call_function_builtin(PyThreadState *tstate,
59415941

59425942
switch ((_BuiltinCallKinds)cache0->index) {
59435943
case PYCFUNCTION_NOARGS:
5944-
case PYCFUNCTION_O: {
5944+
case PYCFUNCTION_O:
59455945
MAYBE_TRACE(cfunc(self, *stack));
59465946
break;
5947-
}
5948-
case _PYCFUNCTION_FAST: {
5947+
case _PYCFUNCTION_FAST:
59495948
MAYBE_TRACE(((_PyCFunctionFast)(void(*)(void))cfunc)(self, stack, oparg));
59505949
break;
5951-
}
5952-
case _PYCFUNCTION_FAST_WITH_KEYWORDS: {
5950+
case _PYCFUNCTION_FAST_WITH_KEYWORDS:
59535951
MAYBE_TRACE(((_PyCFunctionFastWithKeywords)(void(*)(void))cfunc)(
59545952
self, stack, oparg, 0));
59555953
break;
5954+
case PYCFUNCTION: {
5955+
PyObject *args = _PyTuple_FromArray(stack, oparg);
5956+
if (args == NULL) {
5957+
break;
5958+
}
5959+
MAYBE_TRACE(cfunc(self, args));
5960+
Py_DECREF(args);
5961+
break;
59565962
}
59575963
case PYCFUNCTION_WITH_KEYWORDS: {
59585964
PyObject *args = _PyTuple_FromArray(stack, oparg);
@@ -5963,8 +5969,9 @@ call_function_builtin(PyThreadState *tstate,
59635969
Py_DECREF(args);
59645970
break;
59655971
}
5966-
/* Bulitins shouldn't have these flags */
5967-
case PYCFUNCTION:
5972+
/* This flag only applies to PyMethodObject.
5973+
We're only optimizing for PyCfunctionObject
5974+
*/
59685975
case PYCMETHOD:
59695976
default:
59705977
Py_UNREACHABLE();

Python/opcode_targets.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/specialize.c

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -636,40 +636,33 @@ _Py_Specialize_LoadGlobal(
636636
return 0;
637637
}
638638

639+
/* TODO:
640+
- Specialize calling C types like int() with CALL_CTYPE
641+
- Specialize python function calls.
642+
*/
639643
int
640644
_Py_Specialize_CallFunction(PyObject **stack_pointer, uint8_t original_oparg,
641-
PyObject *builtins, _Py_CODEUNIT *instr, SpecializedCacheEntry *cache)
645+
_Py_CODEUNIT *instr, SpecializedCacheEntry *cache)
642646
{
643647
PyObject *callable = stack_pointer[-(original_oparg + 1)];
644648
_PyAdaptiveEntry *cache0 = &cache->adaptive;
645649
_PyCallFunctionCache *cache1 = &cache[-1].call_function;
646650
if (!PyCallable_Check(callable)) {
647651
goto fail;
648652
}
649-
if (!PyDict_CheckExact(builtins)) {
650-
goto fail;
651-
}
652-
PyDictObject *builtins_dict = (PyDictObject *)builtins;
653-
if (builtins_dict->ma_keys->dk_kind != DICT_KEYS_UNICODE) {
654-
goto fail;
655-
}
656-
/* Specialize C methods */
653+
/* Specialize C functions */
657654
if (PyCFunction_CheckExact(callable)) {
658655
PyCFunctionObject *meth = (PyCFunctionObject *)callable;
659656
if (meth->m_ml == NULL) {
660657
goto fail;
661658
}
662659
const char *name_ascii = meth->m_ml->ml_name;
663-
/* Specialize builtins: check method actually exists in builtins */
664-
PyObject *value = PyDict_GetItemString(builtins, name_ascii);
665-
if (value == NULL ||
666-
value != (PyObject *)meth) {
667-
goto fail;
668-
}
669660
_BuiltinCallKinds kind = -1;
670661
switch (PyCFunction_GET_FLAGS(meth) & (METH_VARARGS | METH_FASTCALL |
671662
METH_NOARGS | METH_O | METH_KEYWORDS | METH_METHOD)) {
672663
case METH_VARARGS:
664+
kind = PYCFUNCTION;
665+
break;
673666
case METH_VARARGS | METH_KEYWORDS:
674667
kind = PYCFUNCTION_WITH_KEYWORDS;
675668
break;
@@ -685,17 +678,19 @@ _Py_Specialize_CallFunction(PyObject **stack_pointer, uint8_t original_oparg,
685678
case METH_O:
686679
kind = PYCFUNCTION_O;
687680
break;
681+
/* This case should never happen with PyCFunctionObject -- only
682+
PyMethodObject. See zlib.compressobj()'s methods for an example.
683+
*/
688684
case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
689-
kind = PYCMETHOD;
690-
break;
685+
// kind = PYCMETHOD;
691686
default:
692687
SPECIALIZATION_FAIL(CALL_FUNCTION, type, callable, "bad call flags");
693-
goto fail;
688+
return -1;
694689
}
695690
assert(kind > 0);
696691
PyCFunction cfunc = PyCFunction_GET_FUNCTION(meth);
697692
assert(cfunc != NULL);
698-
*instr = _Py_MAKECODEUNIT(CALL_FUNCTION_BUILTIN, _Py_OPARG(*instr));
693+
*instr = _Py_MAKECODEUNIT(CALL_CFUNCTION, _Py_OPARG(*instr));
699694
cache0->index = (uint16_t)kind;
700695
cache1->cfunc = cfunc;
701696
goto success;

0 commit comments

Comments
 (0)