GH-98831: Implement basic cache effects (#99313)

This commit is contained in:
Guido van Rossum 2022-11-15 19:59:19 -08:00 committed by GitHub
parent 4636df9feb
commit e37744f289
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 201 additions and 127 deletions

View file

@ -76,13 +76,9 @@ do { \
#define NAME_ERROR_MSG \
"name '%.200s' is not defined"
typedef struct {
PyObject *kwnames;
} CallShape;
// Dummy variables for stack effects.
static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub;
static PyObject *container, *start, *stop, *v;
static PyObject *container, *start, *stop, *v, *lhs, *rhs;
static PyObject *
dummy_func(
@ -101,6 +97,8 @@ dummy_func(
binaryfunc binary_ops[]
)
{
_PyInterpreterFrame entry_frame;
switch (opcode) {
// BEGIN BYTECODES //
@ -193,7 +191,21 @@ dummy_func(
ERROR_IF(res == NULL, error);
}
inst(BINARY_OP_MULTIPLY_INT, (left, right -- prod)) {
family(binary_op, INLINE_CACHE_ENTRIES_BINARY_OP) = {
BINARY_OP,
BINARY_OP_ADD_FLOAT,
BINARY_OP_ADD_INT,
BINARY_OP_ADD_UNICODE,
BINARY_OP_GENERIC,
// BINARY_OP_INPLACE_ADD_UNICODE, // This is an odd duck.
BINARY_OP_MULTIPLY_FLOAT,
BINARY_OP_MULTIPLY_INT,
BINARY_OP_SUBTRACT_FLOAT,
BINARY_OP_SUBTRACT_INT,
};
inst(BINARY_OP_MULTIPLY_INT, (left, right, unused/1 -- prod)) {
assert(cframe.use_tracing == 0);
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
@ -202,10 +214,9 @@ dummy_func(
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
ERROR_IF(prod == NULL, error);
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
}
inst(BINARY_OP_MULTIPLY_FLOAT, (left, right -- prod)) {
inst(BINARY_OP_MULTIPLY_FLOAT, (left, right, unused/1 -- prod)) {
assert(cframe.use_tracing == 0);
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
@ -216,10 +227,9 @@ dummy_func(
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
ERROR_IF(prod == NULL, error);
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
}
inst(BINARY_OP_SUBTRACT_INT, (left, right -- sub)) {
inst(BINARY_OP_SUBTRACT_INT, (left, right, unused/1 -- sub)) {
assert(cframe.use_tracing == 0);
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyLong_CheckExact(right), BINARY_OP);
@ -228,10 +238,9 @@ dummy_func(
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
ERROR_IF(sub == NULL, error);
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
}
inst(BINARY_OP_SUBTRACT_FLOAT, (left, right -- sub)) {
inst(BINARY_OP_SUBTRACT_FLOAT, (left, right, unused/1 -- sub)) {
assert(cframe.use_tracing == 0);
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
DEOPT_IF(!PyFloat_CheckExact(right), BINARY_OP);
@ -241,10 +250,9 @@ dummy_func(
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
ERROR_IF(sub == NULL, error);
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
}
inst(BINARY_OP_ADD_UNICODE, (left, right -- res)) {
inst(BINARY_OP_ADD_UNICODE, (left, right, unused/1 -- res)) {
assert(cframe.use_tracing == 0);
DEOPT_IF(!PyUnicode_CheckExact(left), BINARY_OP);
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
@ -253,7 +261,6 @@ dummy_func(
_Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
ERROR_IF(res == NULL, error);
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
}
// This is a subtle one. It's a super-instruction for
@ -292,7 +299,7 @@ dummy_func(
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP + 1);
}
inst(BINARY_OP_ADD_FLOAT, (left, right -- sum)) {
inst(BINARY_OP_ADD_FLOAT, (left, right, unused/1 -- sum)) {
assert(cframe.use_tracing == 0);
DEOPT_IF(!PyFloat_CheckExact(left), BINARY_OP);
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
@ -303,10 +310,9 @@ dummy_func(
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
ERROR_IF(sum == NULL, error);
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
}
inst(BINARY_OP_ADD_INT, (left, right -- sum)) {
inst(BINARY_OP_ADD_INT, (left, right, unused/1 -- sum)) {
assert(cframe.use_tracing == 0);
DEOPT_IF(!PyLong_CheckExact(left), BINARY_OP);
DEOPT_IF(Py_TYPE(right) != Py_TYPE(left), BINARY_OP);
@ -315,7 +321,6 @@ dummy_func(
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
ERROR_IF(sum == NULL, error);
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
}
inst(BINARY_SUBSCR, (container, sub -- res)) {
@ -3691,30 +3696,21 @@ dummy_func(
PUSH(Py_NewRef(peek));
}
// stack effect: (__0 -- )
inst(BINARY_OP_GENERIC) {
PyObject *rhs = POP();
PyObject *lhs = TOP();
inst(BINARY_OP_GENERIC, (lhs, rhs, unused/1 -- res)) {
assert(0 <= oparg);
assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops));
assert(binary_ops[oparg]);
PyObject *res = binary_ops[oparg](lhs, rhs);
res = binary_ops[oparg](lhs, rhs);
Py_DECREF(lhs);
Py_DECREF(rhs);
SET_TOP(res);
if (res == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
ERROR_IF(res == NULL, error);
}
// stack effect: (__0 -- )
inst(BINARY_OP) {
// This always dispatches, so the result is unused.
inst(BINARY_OP, (lhs, rhs, unused/1 -- unused)) {
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
assert(cframe.use_tracing == 0);
PyObject *lhs = SECOND();
PyObject *rhs = TOP();
next_instr--;
_Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, &GETLOCAL(0));
DISPATCH_SAME_OPARG();
@ -3761,13 +3757,8 @@ dummy_func(
;
}
// Families go below this point //
// Future families go below this point //
family(binary_op) = {
BINARY_OP, BINARY_OP_ADD_FLOAT,
BINARY_OP_ADD_INT, BINARY_OP_ADD_UNICODE, BINARY_OP_GENERIC, BINARY_OP_INPLACE_ADD_UNICODE,
BINARY_OP_MULTIPLY_FLOAT, BINARY_OP_MULTIPLY_INT, BINARY_OP_SUBTRACT_FLOAT,
BINARY_OP_SUBTRACT_INT };
family(binary_subscr) = {
BINARY_SUBSCR, BINARY_SUBSCR_DICT,
BINARY_SUBSCR_GETITEM, BINARY_SUBSCR_LIST_INT, BINARY_SUBSCR_TUPLE_INT };

View file

@ -145,9 +145,9 @@
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
if (prod == NULL) goto pop_2_error;
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
STACK_SHRINK(1);
POKE(1, prod);
next_instr += 1;
DISPATCH();
}
@ -165,9 +165,9 @@
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
if (prod == NULL) goto pop_2_error;
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
STACK_SHRINK(1);
POKE(1, prod);
next_instr += 1;
DISPATCH();
}
@ -183,9 +183,9 @@
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
if (sub == NULL) goto pop_2_error;
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
STACK_SHRINK(1);
POKE(1, sub);
next_instr += 1;
DISPATCH();
}
@ -202,9 +202,9 @@
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
if (sub == NULL) goto pop_2_error;
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
STACK_SHRINK(1);
POKE(1, sub);
next_instr += 1;
DISPATCH();
}
@ -220,9 +220,9 @@
_Py_DECREF_SPECIALIZED(left, _PyUnicode_ExactDealloc);
_Py_DECREF_SPECIALIZED(right, _PyUnicode_ExactDealloc);
if (res == NULL) goto pop_2_error;
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
STACK_SHRINK(1);
POKE(1, res);
next_instr += 1;
DISPATCH();
}
@ -274,9 +274,9 @@
_Py_DECREF_SPECIALIZED(right, _PyFloat_ExactDealloc);
_Py_DECREF_SPECIALIZED(left, _PyFloat_ExactDealloc);
if (sum == NULL) goto pop_2_error;
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
STACK_SHRINK(1);
POKE(1, sum);
next_instr += 1;
DISPATCH();
}
@ -292,9 +292,9 @@
_Py_DECREF_SPECIALIZED(right, (destructor)PyObject_Free);
_Py_DECREF_SPECIALIZED(left, (destructor)PyObject_Free);
if (sum == NULL) goto pop_2_error;
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
STACK_SHRINK(1);
POKE(1, sum);
next_instr += 1;
DISPATCH();
}
@ -3703,29 +3703,30 @@
TARGET(BINARY_OP_GENERIC) {
PREDICTED(BINARY_OP_GENERIC);
PyObject *rhs = POP();
PyObject *lhs = TOP();
PyObject *rhs = PEEK(1);
PyObject *lhs = PEEK(2);
PyObject *res;
assert(0 <= oparg);
assert((unsigned)oparg < Py_ARRAY_LENGTH(binary_ops));
assert(binary_ops[oparg]);
PyObject *res = binary_ops[oparg](lhs, rhs);
res = binary_ops[oparg](lhs, rhs);
Py_DECREF(lhs);
Py_DECREF(rhs);
SET_TOP(res);
if (res == NULL) {
goto error;
}
JUMPBY(INLINE_CACHE_ENTRIES_BINARY_OP);
if (res == NULL) goto pop_2_error;
STACK_SHRINK(1);
POKE(1, res);
next_instr += 1;
DISPATCH();
}
TARGET(BINARY_OP) {
PREDICTED(BINARY_OP);
assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1);
PyObject *rhs = PEEK(1);
PyObject *lhs = PEEK(2);
_PyBinaryOpCache *cache = (_PyBinaryOpCache *)next_instr;
if (ADAPTIVE_COUNTER_IS_ZERO(cache->counter)) {
assert(cframe.use_tracing == 0);
PyObject *lhs = SECOND();
PyObject *rhs = TOP();
next_instr--;
_Py_Specialize_BinaryOp(lhs, rhs, next_instr, oparg, &GETLOCAL(0));
DISPATCH_SAME_OPARG();