Skip to content

Commit

Permalink
bpo-44525: Specialize simple Python calls. (GH-29033)
Browse files Browse the repository at this point in the history
  • Loading branch information
markshannon authored Oct 20, 2021
1 parent 8d6740f commit 8863a0f
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 60 deletions.
7 changes: 7 additions & 0 deletions Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ typedef struct {
PyObject *obj;
} _PyObjectCache;

typedef struct {
uint32_t func_version;
uint16_t defaults_start;
uint16_t defaults_len;
} _PyCallCache;

/* Add specialized versions of entries to this union.
*
* Do not break the invariant: sizeof(SpecializedCacheEntry) == 8
Expand All @@ -51,6 +57,7 @@ typedef union {
_PyAttrCache attr;
_PyLoadGlobalCache load_global;
_PyObjectCache obj;
_PyCallCache call;
} SpecializedCacheEntry;

#define INSTRUCTIONS_PER_ENTRY (sizeof(SpecializedCacheEntry)/sizeof(_Py_CODEUNIT))
Expand Down
47 changes: 24 additions & 23 deletions Include/opcode.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ def jabs_op(name, op):
"CALL_FUNCTION_BUILTIN_FAST",
"CALL_FUNCTION_LEN",
"CALL_FUNCTION_ISINSTANCE",
"CALL_FUNCTION_PY_SIMPLE",
"JUMP_ABSOLUTE_QUICK",
"LOAD_ATTR_ADAPTIVE",
"LOAD_ATTR_INSTANCE_VALUE",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Specialize simple calls to Python functions (no starargs, keyowrd dict, or closure)
45 changes: 42 additions & 3 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -4720,9 +4720,9 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr

TARGET(CALL_FUNCTION_ADAPTIVE) {
SpecializedCacheEntry *cache = GET_CACHE();
nargs = cache->adaptive.original_oparg;
if (cache->adaptive.counter == 0) {
next_instr--;
int nargs = cache->adaptive.original_oparg;
if (_Py_Specialize_CallFunction(
PEEK(nargs + 1), next_instr, nargs, cache, BUILTINS()) < 0) {
goto error;
Expand All @@ -4732,9 +4732,48 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, InterpreterFrame *frame, int thr
else {
STAT_INC(CALL_FUNCTION, deferred);
cache->adaptive.counter--;
oparg = cache->adaptive.original_oparg;
JUMP_TO_INSTRUCTION(CALL_FUNCTION);
oparg = nargs;
kwnames = NULL;
postcall_shrink = 1;
goto call_function;
}
}

TARGET(CALL_FUNCTION_PY_SIMPLE) {
SpecializedCacheEntry *caches = GET_CACHE();
_PyAdaptiveEntry *cache0 = &caches[0].adaptive;
int argcount = cache0->original_oparg;
_PyCallCache *cache1 = &caches[-1].call;
PyObject *callable = PEEK(argcount+1);
DEOPT_IF(!PyFunction_Check(callable), CALL_FUNCTION);
PyFunctionObject *func = (PyFunctionObject *)callable;
DEOPT_IF(func->func_version != cache1->func_version, CALL_FUNCTION);
/* PEP 523 */
DEOPT_IF(tstate->interp->eval_frame != NULL, CALL_FUNCTION);
STAT_INC(CALL_FUNCTION, hit);
record_cache_hit(cache0);
InterpreterFrame *new_frame = _PyThreadState_PushFrame(
tstate, PyFunction_AS_FRAME_CONSTRUCTOR(func), NULL);
if (new_frame == NULL) {
goto error;
}
STACK_SHRINK(argcount);
for (int i = 0; i < argcount; i++) {
new_frame->localsplus[i] = stack_pointer[i];
}
int deflen = cache1->defaults_len;
for (int i = 0; i < deflen; i++) {
PyObject *def = PyTuple_GET_ITEM(func->func_defaults, cache1->defaults_start+i);
Py_INCREF(def);
new_frame->localsplus[argcount+i] = def;
}
STACK_SHRINK(1);
Py_DECREF(func);
_PyFrame_SetStackPointer(frame, stack_pointer);
new_frame->previous = tstate->frame;
new_frame->depth = frame->depth + 1;
tstate->frame = frame = new_frame;
goto start_frame;
}

TARGET(CALL_FUNCTION_BUILTIN_O) {
Expand Down
28 changes: 14 additions & 14 deletions Python/opcode_targets.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8863a0f

Please sign in to comment.