Skip to content

Commit

Permalink
Get rid of the rest of the CALL cache
Browse files Browse the repository at this point in the history
  • Loading branch information
brandtbucher committed Apr 4, 2023
1 parent 5d9ca5f commit d02b607
Show file tree
Hide file tree
Showing 12 changed files with 258 additions and 279 deletions.
2 changes: 1 addition & 1 deletion Doc/library/dis.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ the following command can be used to display the disassembly of
3 2 LOAD_GLOBAL 1 (NULL + len)
12 LOAD_FAST 0 (alist)
14 CALL 1
22 RETURN_VALUE
18 RETURN_VALUE

(The "2" is a line number).

Expand Down
1 change: 0 additions & 1 deletion Include/internal/pycore_code.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@ typedef struct {

typedef struct {
uint16_t counter;
uint16_t func_version[2];
} _PyCallCache;

#define INLINE_CACHE_ENTRIES_CALL CACHE_ENTRIES(_PyCallCache)
Expand Down
2 changes: 2 additions & 0 deletions Include/internal/pycore_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ extern PyFunctionObject* _PyFunction_FromConstructor(PyFrameConstructor *constr)

extern uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func);

extern int _PyFunction_IsSimple(PyFunctionObject *func);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_opcode.h

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

1 change: 0 additions & 1 deletion Lib/opcode.py
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,6 @@ def pseudo_op(name, op, real_ops):
},
"CALL": {
"counter": 1,
"func_version": 2,
},
"STORE_SUBSCR": {
"counter": 1,
Expand Down
258 changes: 129 additions & 129 deletions Lib/test/test_dis.py

Large diffs are not rendered by default.

16 changes: 16 additions & 0 deletions Objects/funcobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,22 @@ uint32_t _PyFunction_GetVersionForCurrentState(PyFunctionObject *func)
return v;
}

int
_PyFunction_IsSimple(PyFunctionObject *function)
{
assert(PyFunction_Check(function));
if (function->vectorcall != _PyFunction_Vectorcall) {
return 0;
}
PyCodeObject *code = (PyCodeObject *)function->func_code;
assert(PyCode_Check(code));
if (code->co_kwonlyargcount) {
return 0;
}
int interesting_flags = CO_OPTIMIZED | CO_VARARGS | CO_VARKEYWORDS;
return (code->co_flags & interesting_flags) == CO_OPTIMIZED;
}

PyObject *
PyFunction_New(PyObject *code, PyObject *globals)
{
Expand Down
27 changes: 13 additions & 14 deletions Programs/test_frozenmain.h

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

44 changes: 22 additions & 22 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2318,7 +2318,7 @@ dummy_func(
kwnames = GETITEM(frame->f_code->co_consts, oparg);
}

// Cache layout: counter/1, func_version/2
// Cache layout: counter/1
// Neither CALL_INTRINSIC_1/2 nor CALL_FUNCTION_EX are members!
family(call, INLINE_CACHE_ENTRIES_CALL) = {
CALL,
Expand Down Expand Up @@ -2348,7 +2348,7 @@ dummy_func(
// (Some args may be keywords, see KW_NAMES, which sets 'kwnames'.)
// On exit, the stack is [result].
// When calling Python, inline the call using DISPATCH_INLINED().
inst(CALL, (unused/1, unused/2, method, callable, args[oparg] -- res)) {
inst(CALL, (unused/1, method, callable, args[oparg] -- res)) {
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
Expand Down Expand Up @@ -2426,7 +2426,7 @@ dummy_func(
// Start out with [NULL, bound_method, arg1, arg2, ...]
// Transform to [callable, self, arg1, arg2, ...]
// Then fall through to CALL_PY_EXACT_ARGS
inst(CALL_BOUND_METHOD_EXACT_ARGS, (unused/1, unused/2, method, callable, unused[oparg] -- unused)) {
inst(CALL_BOUND_METHOD_EXACT_ARGS, (unused/1, method, callable, unused[oparg] -- unused)) {
DEOPT_IF(method != NULL, CALL);
DEOPT_IF(Py_TYPE(callable) != &PyMethod_Type, CALL);
STAT_INC(CALL, hit);
Expand All @@ -2438,7 +2438,7 @@ dummy_func(
GO_TO_INSTRUCTION(CALL_PY_EXACT_ARGS);
}

inst(CALL_PY_EXACT_ARGS, (unused/1, func_version/2, method, callable, args[oparg] -- unused)) {
inst(CALL_PY_EXACT_ARGS, (unused/1, method, callable, args[oparg] -- unused)) {
assert(kwnames == NULL);
DEOPT_IF(tstate->interp->eval_frame, CALL);
int is_meth = method != NULL;
Expand All @@ -2450,7 +2450,7 @@ dummy_func(
}
DEOPT_IF(!PyFunction_Check(callable), CALL);
PyFunctionObject *func = (PyFunctionObject *)callable;
DEOPT_IF(func->func_version != func_version, CALL);
DEOPT_IF(!_PyFunction_IsSimple(func), CALL);
PyCodeObject *code = (PyCodeObject *)func->func_code;
DEOPT_IF(code->co_argcount != argcount, CALL);
DEOPT_IF(!_PyThreadState_HasStackSpace(tstate, code->co_framesize), CALL);
Expand All @@ -2465,7 +2465,7 @@ dummy_func(
DISPATCH_INLINED(new_frame);
}

inst(CALL_PY_WITH_DEFAULTS, (unused/1, func_version/2, method, callable, args[oparg] -- unused)) {
inst(CALL_PY_WITH_DEFAULTS, (unused/1, method, callable, args[oparg] -- unused)) {
assert(kwnames == NULL);
DEOPT_IF(tstate->interp->eval_frame, CALL);
int is_meth = method != NULL;
Expand All @@ -2477,9 +2477,9 @@ dummy_func(
}
DEOPT_IF(!PyFunction_Check(callable), CALL);
PyFunctionObject *func = (PyFunctionObject *)callable;
DEOPT_IF(func->func_version != func_version, CALL);
DEOPT_IF(!_PyFunction_IsSimple(func), CALL);
PyCodeObject *code = (PyCodeObject *)func->func_code;
assert(func->func_defaults);
DEOPT_IF(func->func_defaults == NULL, CALL);
assert(PyTuple_CheckExact(func->func_defaults));
int defcount = (int)PyTuple_GET_SIZE(func->func_defaults);
assert(defcount <= code->co_argcount);
Expand All @@ -2502,7 +2502,7 @@ dummy_func(
DISPATCH_INLINED(new_frame);
}

inst(CALL_NO_KW_TYPE_1, (unused/1, unused/2, null, callable, args[oparg] -- res)) {
inst(CALL_NO_KW_TYPE_1, (unused/1, null, callable, args[oparg] -- res)) {
assert(kwnames == NULL);
assert(cframe.use_tracing == 0);
assert(oparg == 1);
Expand All @@ -2515,7 +2515,7 @@ dummy_func(
Py_DECREF(&PyType_Type); // I.e., callable
}

inst(CALL_NO_KW_STR_1, (unused/1, unused/2, null, callable, args[oparg] -- res)) {
inst(CALL_NO_KW_STR_1, (unused/1, null, callable, args[oparg] -- res)) {
assert(kwnames == NULL);
assert(cframe.use_tracing == 0);
assert(oparg == 1);
Expand All @@ -2530,7 +2530,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}

inst(CALL_NO_KW_TUPLE_1, (unused/1, unused/2, null, callable, args[oparg] -- res)) {
inst(CALL_NO_KW_TUPLE_1, (unused/1, null, callable, args[oparg] -- res)) {
assert(kwnames == NULL);
assert(oparg == 1);
DEOPT_IF(null != NULL, CALL);
Expand All @@ -2544,7 +2544,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}

inst(CALL_BUILTIN_CLASS, (unused/1, unused/2, method, callable, args[oparg] -- res)) {
inst(CALL_BUILTIN_CLASS, (unused/1, method, callable, args[oparg] -- res)) {
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
Expand All @@ -2569,7 +2569,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}

inst(CALL_NO_KW_BUILTIN_O, (unused/1, unused/2, method, callable, args[oparg] -- res)) {
inst(CALL_NO_KW_BUILTIN_O, (unused/1, method, callable, args[oparg] -- res)) {
assert(cframe.use_tracing == 0);
/* Builtin METH_O functions */
assert(kwnames == NULL);
Expand Down Expand Up @@ -2601,7 +2601,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}

inst(CALL_NO_KW_BUILTIN_FAST, (unused/1, unused/2, method, callable, args[oparg] -- res)) {
inst(CALL_NO_KW_BUILTIN_FAST, (unused/1, method, callable, args[oparg] -- res)) {
assert(cframe.use_tracing == 0);
/* Builtin METH_FASTCALL functions, without keywords */
assert(kwnames == NULL);
Expand Down Expand Up @@ -2637,7 +2637,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}

inst(CALL_BUILTIN_FAST_WITH_KEYWORDS, (unused/1, unused/2, method, callable, args[oparg] -- res)) {
inst(CALL_BUILTIN_FAST_WITH_KEYWORDS, (unused/1, method, callable, args[oparg] -- res)) {
assert(cframe.use_tracing == 0);
/* Builtin METH_FASTCALL | METH_KEYWORDS functions */
int is_meth = method != NULL;
Expand Down Expand Up @@ -2673,7 +2673,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}

inst(CALL_NO_KW_LEN, (unused/1, unused/2, method, callable, args[oparg] -- res)) {
inst(CALL_NO_KW_LEN, (unused/1, method, callable, args[oparg] -- res)) {
assert(cframe.use_tracing == 0);
assert(kwnames == NULL);
/* len(o) */
Expand Down Expand Up @@ -2701,7 +2701,7 @@ dummy_func(
ERROR_IF(res == NULL, error);
}

inst(CALL_NO_KW_ISINSTANCE, (unused/1, unused/2, method, callable, args[oparg] -- res)) {
inst(CALL_NO_KW_ISINSTANCE, (unused/1, method, callable, args[oparg] -- res)) {
assert(cframe.use_tracing == 0);
assert(kwnames == NULL);
/* isinstance(o, o2) */
Expand Down Expand Up @@ -2732,7 +2732,7 @@ dummy_func(
}

// This is secretly a super-instruction
inst(CALL_NO_KW_LIST_APPEND, (unused/1, unused/2, method, self, args[oparg] -- unused)) {
inst(CALL_NO_KW_LIST_APPEND, (unused/1, method, self, args[oparg] -- unused)) {
assert(cframe.use_tracing == 0);
assert(kwnames == NULL);
assert(oparg == 1);
Expand All @@ -2753,7 +2753,7 @@ dummy_func(
DISPATCH();
}

inst(CALL_NO_KW_METHOD_DESCRIPTOR_O, (unused/1, unused/2, method, unused, args[oparg] -- res)) {
inst(CALL_NO_KW_METHOD_DESCRIPTOR_O, (unused/1, method, unused, args[oparg] -- res)) {
assert(kwnames == NULL);
int is_meth = method != NULL;
int total_args = oparg;
Expand Down Expand Up @@ -2787,7 +2787,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}

inst(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (unused/1, unused/2, method, unused, args[oparg] -- res)) {
inst(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS, (unused/1, method, unused, args[oparg] -- res)) {
int is_meth = method != NULL;
int total_args = oparg;
if (is_meth) {
Expand Down Expand Up @@ -2819,7 +2819,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}

inst(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, (unused/1, unused/2, method, unused, args[oparg] -- res)) {
inst(CALL_NO_KW_METHOD_DESCRIPTOR_NOARGS, (unused/1, method, unused, args[oparg] -- res)) {
assert(kwnames == NULL);
assert(oparg == 0 || oparg == 1);
int is_meth = method != NULL;
Expand Down Expand Up @@ -2851,7 +2851,7 @@ dummy_func(
CHECK_EVAL_BREAKER();
}

inst(CALL_NO_KW_METHOD_DESCRIPTOR_FAST, (unused/1, unused/2, method, unused, args[oparg] -- res)) {
inst(CALL_NO_KW_METHOD_DESCRIPTOR_FAST, (unused/1, method, unused, args[oparg] -- res)) {
assert(kwnames == NULL);
int is_meth = method != NULL;
int total_args = oparg;
Expand Down
Loading

0 comments on commit d02b607

Please sign in to comment.