GH-121784: Generate an error during code gen if a variable is marked `unused`, but is used and thus cached in a prior uop. (#121788)

* Reject uop definitions that declare values as 'unused' that are already cached by prior uops

* Track which variables are defined and only load from memory when needed

* Support explicit `flush` in macro definitions. 

* Make sure stack is flushed in where needed.
This commit is contained in:
Mark Shannon 2024-07-18 12:49:24 +01:00 committed by GitHub
parent 169324c27a
commit 3eacfc1a4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 443 additions and 255 deletions

View File

@ -139,7 +139,7 @@ class TestGeneratedCases(unittest.TestCase):
def test_inst_one_pop(self): def test_inst_one_pop(self):
input = """ input = """
inst(OP, (value --)) { inst(OP, (value --)) {
spam(); spam(value);
} }
""" """
output = """ output = """
@ -149,7 +149,7 @@ class TestGeneratedCases(unittest.TestCase):
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef value; _PyStackRef value;
value = stack_pointer[-1]; value = stack_pointer[-1];
spam(); spam(value);
stack_pointer += -1; stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());
DISPATCH(); DISPATCH();
@ -160,7 +160,7 @@ class TestGeneratedCases(unittest.TestCase):
def test_inst_one_push(self): def test_inst_one_push(self):
input = """ input = """
inst(OP, (-- res)) { inst(OP, (-- res)) {
spam(); res = spam();
} }
""" """
output = """ output = """
@ -169,7 +169,7 @@ class TestGeneratedCases(unittest.TestCase):
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef res; _PyStackRef res;
spam(); res = spam();
stack_pointer[0] = res; stack_pointer[0] = res;
stack_pointer += 1; stack_pointer += 1;
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());
@ -181,7 +181,7 @@ class TestGeneratedCases(unittest.TestCase):
def test_inst_one_push_one_pop(self): def test_inst_one_push_one_pop(self):
input = """ input = """
inst(OP, (value -- res)) { inst(OP, (value -- res)) {
spam(); res = spam(value);
} }
""" """
output = """ output = """
@ -192,7 +192,7 @@ class TestGeneratedCases(unittest.TestCase):
_PyStackRef value; _PyStackRef value;
_PyStackRef res; _PyStackRef res;
value = stack_pointer[-1]; value = stack_pointer[-1];
spam(); res = spam(value);
stack_pointer[-1] = res; stack_pointer[-1] = res;
DISPATCH(); DISPATCH();
} }
@ -202,7 +202,7 @@ class TestGeneratedCases(unittest.TestCase):
def test_binary_op(self): def test_binary_op(self):
input = """ input = """
inst(OP, (left, right -- res)) { inst(OP, (left, right -- res)) {
spam(); res = spam(left, right);
} }
""" """
output = """ output = """
@ -210,12 +210,12 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
right = stack_pointer[-1]; right = stack_pointer[-1];
left = stack_pointer[-2]; left = stack_pointer[-2];
spam(); res = spam(left, right);
stack_pointer[-2] = res; stack_pointer[-2] = res;
stack_pointer += -1; stack_pointer += -1;
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());
@ -227,7 +227,7 @@ class TestGeneratedCases(unittest.TestCase):
def test_overlap(self): def test_overlap(self):
input = """ input = """
inst(OP, (left, right -- left, result)) { inst(OP, (left, right -- left, result)) {
spam(); result = spam(left, right);
} }
""" """
output = """ output = """
@ -235,12 +235,12 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef result; _PyStackRef result;
right = stack_pointer[-1]; right = stack_pointer[-1];
left = stack_pointer[-2]; left = stack_pointer[-2];
spam(); result = spam(left, right);
stack_pointer[-1] = result; stack_pointer[-1] = result;
DISPATCH(); DISPATCH();
} }
@ -253,6 +253,7 @@ class TestGeneratedCases(unittest.TestCase):
} }
inst(OP3, (arg -- res)) { inst(OP3, (arg -- res)) {
DEOPT_IF(xxx); DEOPT_IF(xxx);
res = Py_None;
CHECK_EVAL_BREAKER(); CHECK_EVAL_BREAKER();
} }
family(OP1, INLINE_CACHE_ENTRIES_OP1) = { OP3 }; family(OP1, INLINE_CACHE_ENTRIES_OP1) = { OP3 };
@ -263,9 +264,6 @@ class TestGeneratedCases(unittest.TestCase):
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP1); INSTRUCTION_STATS(OP1);
PREDICTED(OP1); PREDICTED(OP1);
_PyStackRef arg;
_PyStackRef rest;
arg = stack_pointer[-1];
stack_pointer[-1] = rest; stack_pointer[-1] = rest;
DISPATCH(); DISPATCH();
} }
@ -275,10 +273,9 @@ class TestGeneratedCases(unittest.TestCase):
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP3); INSTRUCTION_STATS(OP3);
static_assert(INLINE_CACHE_ENTRIES_OP1 == 0, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_OP1 == 0, "incorrect cache size");
_PyStackRef arg;
_PyStackRef res; _PyStackRef res;
arg = stack_pointer[-1];
DEOPT_IF(xxx, OP1); DEOPT_IF(xxx, OP1);
res = Py_None;
stack_pointer[-1] = res; stack_pointer[-1] = res;
CHECK_EVAL_BREAKER(); CHECK_EVAL_BREAKER();
DISPATCH(); DISPATCH();
@ -324,6 +321,7 @@ class TestGeneratedCases(unittest.TestCase):
def test_error_if_pop(self): def test_error_if_pop(self):
input = """ input = """
inst(OP, (left, right -- res)) { inst(OP, (left, right -- res)) {
res = spam(left, right);
ERROR_IF(cond, label); ERROR_IF(cond, label);
} }
""" """
@ -332,11 +330,12 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
right = stack_pointer[-1]; right = stack_pointer[-1];
left = stack_pointer[-2]; left = stack_pointer[-2];
res = spam(left, right);
if (cond) goto pop_2_label; if (cond) goto pop_2_label;
stack_pointer[-2] = res; stack_pointer[-2] = res;
stack_pointer += -1; stack_pointer += -1;
@ -357,8 +356,6 @@ class TestGeneratedCases(unittest.TestCase):
(void)this_instr; (void)this_instr;
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef value;
value = stack_pointer[-1];
uint16_t counter = read_u16(&this_instr[1].cache); uint16_t counter = read_u16(&this_instr[1].cache);
(void)counter; (void)counter;
uint32_t extra = read_u32(&this_instr[2].cache); uint32_t extra = read_u32(&this_instr[2].cache);
@ -408,8 +405,8 @@ class TestGeneratedCases(unittest.TestCase):
PREDICTED(OP); PREDICTED(OP);
_Py_CODEUNIT *this_instr = next_instr - 6; _Py_CODEUNIT *this_instr = next_instr - 6;
(void)this_instr; (void)this_instr;
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef arg2; _PyStackRef arg2;
_PyStackRef res; _PyStackRef res;
// _OP1 // _OP1
@ -439,8 +436,8 @@ class TestGeneratedCases(unittest.TestCase):
(void)this_instr; (void)this_instr;
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(OP1); INSTRUCTION_STATS(OP1);
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
right = stack_pointer[-1]; right = stack_pointer[-1];
left = stack_pointer[-2]; left = stack_pointer[-2];
uint16_t counter = read_u16(&this_instr[1].cache); uint16_t counter = read_u16(&this_instr[1].cache);
@ -454,9 +451,9 @@ class TestGeneratedCases(unittest.TestCase):
next_instr += 6; next_instr += 6;
INSTRUCTION_STATS(OP3); INSTRUCTION_STATS(OP3);
static_assert(INLINE_CACHE_ENTRIES_OP == 5, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_OP == 5, "incorrect cache size");
_PyStackRef right;
_PyStackRef left;
_PyStackRef arg2; _PyStackRef arg2;
_PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
/* Skip 5 cache entries */ /* Skip 5 cache entries */
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -531,7 +528,7 @@ class TestGeneratedCases(unittest.TestCase):
def test_array_input(self): def test_array_input(self):
input = """ input = """
inst(OP, (below, values[oparg*2], above --)) { inst(OP, (below, values[oparg*2], above --)) {
spam(); spam(values, oparg);
} }
""" """
output = """ output = """
@ -539,13 +536,9 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef above;
_PyStackRef *values; _PyStackRef *values;
_PyStackRef below;
above = stack_pointer[-1];
values = &stack_pointer[-1 - oparg*2]; values = &stack_pointer[-1 - oparg*2];
below = stack_pointer[-2 - oparg*2]; spam(values, oparg);
spam();
stack_pointer += -2 - oparg*2; stack_pointer += -2 - oparg*2;
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());
DISPATCH(); DISPATCH();
@ -564,9 +557,7 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef below;
_PyStackRef *values; _PyStackRef *values;
_PyStackRef above;
values = &stack_pointer[-1]; values = &stack_pointer[-1];
spam(values, oparg); spam(values, oparg);
stack_pointer[-2] = below; stack_pointer[-2] = below;
@ -590,7 +581,6 @@ class TestGeneratedCases(unittest.TestCase):
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef *values; _PyStackRef *values;
_PyStackRef above;
values = &stack_pointer[-oparg]; values = &stack_pointer[-oparg];
spam(values, oparg); spam(values, oparg);
stack_pointer[0] = above; stack_pointer[0] = above;
@ -612,10 +602,6 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef *values;
_PyStackRef extra;
values = &stack_pointer[-oparg];
extra = stack_pointer[-1 - oparg];
if (oparg == 0) { stack_pointer += -1 - oparg; goto somewhere; } if (oparg == 0) { stack_pointer += -1 - oparg; goto somewhere; }
stack_pointer += -1 - oparg; stack_pointer += -1 - oparg;
assert(WITHIN_STACK_BOUNDS()); assert(WITHIN_STACK_BOUNDS());
@ -627,7 +613,7 @@ class TestGeneratedCases(unittest.TestCase):
def test_cond_effect(self): def test_cond_effect(self):
input = """ input = """
inst(OP, (aa, input if ((oparg & 1) == 1), cc -- xx, output if (oparg & 2), zz)) { inst(OP, (aa, input if ((oparg & 1) == 1), cc -- xx, output if (oparg & 2), zz)) {
output = spam(oparg, input); output = spam(oparg, aa, cc, input);
} }
""" """
output = """ output = """
@ -635,16 +621,14 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(OP); INSTRUCTION_STATS(OP);
_PyStackRef cc;
_PyStackRef input = PyStackRef_NULL;
_PyStackRef aa; _PyStackRef aa;
_PyStackRef xx; _PyStackRef input = PyStackRef_NULL;
_PyStackRef cc;
_PyStackRef output = PyStackRef_NULL; _PyStackRef output = PyStackRef_NULL;
_PyStackRef zz;
cc = stack_pointer[-1]; cc = stack_pointer[-1];
if ((oparg & 1) == 1) { input = stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)]; } if ((oparg & 1) == 1) { input = stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)]; }
aa = stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)]; aa = stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)];
output = spam(oparg, input); output = spam(oparg, aa, cc, input);
stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)] = xx; stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)] = xx;
if (oparg & 2) stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)] = output; if (oparg & 2) stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)] = output;
stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0) + ((oparg & 2) ? 1 : 0)] = zz; stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0) + ((oparg & 2) ? 1 : 0)] = zz;
@ -658,10 +642,11 @@ class TestGeneratedCases(unittest.TestCase):
def test_macro_cond_effect(self): def test_macro_cond_effect(self):
input = """ input = """
op(A, (left, middle, right --)) { op(A, (left, middle, right --)) {
# Body of A use(left, middle, right);
} }
op(B, (-- deep, extra if (oparg), res)) { op(B, (-- deep, extra if (oparg), res)) {
# Body of B res = 0;
extra = 1;
} }
macro(M) = A + B; macro(M) = A + B;
""" """
@ -670,10 +655,9 @@ class TestGeneratedCases(unittest.TestCase):
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(M); INSTRUCTION_STATS(M);
_PyStackRef right;
_PyStackRef middle;
_PyStackRef left; _PyStackRef left;
_PyStackRef deep; _PyStackRef middle;
_PyStackRef right;
_PyStackRef extra = PyStackRef_NULL; _PyStackRef extra = PyStackRef_NULL;
_PyStackRef res; _PyStackRef res;
// A // A
@ -681,11 +665,12 @@ class TestGeneratedCases(unittest.TestCase):
middle = stack_pointer[-2]; middle = stack_pointer[-2];
left = stack_pointer[-3]; left = stack_pointer[-3];
{ {
# Body of A use(left, middle, right);
} }
// B // B
{ {
# Body of B res = 0;
extra = 1;
} }
stack_pointer[-3] = deep; stack_pointer[-3] = deep;
if (oparg) stack_pointer[-2] = extra; if (oparg) stack_pointer[-2] = extra;
@ -868,6 +853,165 @@ class TestGeneratedCases(unittest.TestCase):
""" """
self.run_cases_test(input, output) self.run_cases_test(input, output)
def test_unused_cached_value(self):
input = """
op(FIRST, (arg1 -- out)) {
out = arg1;
}
op(SECOND, (unused -- unused)) {
}
macro(BOTH) = FIRST + SECOND;
"""
output = """
"""
with self.assertRaises(SyntaxError):
self.run_cases_test(input, output)
def test_unused_named_values(self):
input = """
op(OP, (named -- named)) {
}
macro(INST) = OP;
"""
output = """
TARGET(INST) {
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(INST);
DISPATCH();
}
"""
self.run_cases_test(input, output)
def test_used_unused_used(self):
input = """
op(FIRST, (w -- w)) {
use(w);
}
op(SECOND, (x -- x)) {
}
op(THIRD, (y -- y)) {
use(y);
}
macro(TEST) = FIRST + SECOND + THIRD;
"""
output = """
TARGET(TEST) {
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(TEST);
_PyStackRef w;
_PyStackRef x;
_PyStackRef y;
// FIRST
w = stack_pointer[-1];
{
use(w);
}
// SECOND
x = w;
{
}
// THIRD
y = x;
{
use(y);
}
DISPATCH();
}
"""
self.run_cases_test(input, output)
def test_unused_used_used(self):
input = """
op(FIRST, (w -- w)) {
}
op(SECOND, (x -- x)) {
use(x);
}
op(THIRD, (y -- y)) {
use(y);
}
macro(TEST) = FIRST + SECOND + THIRD;
"""
output = """
TARGET(TEST) {
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(TEST);
_PyStackRef x;
_PyStackRef y;
// FIRST
{
}
// SECOND
x = stack_pointer[-1];
{
use(x);
}
// THIRD
y = x;
{
use(y);
}
DISPATCH();
}
"""
self.run_cases_test(input, output)
def test_flush(self):
input = """
op(FIRST, ( -- a, b)) {
a = 0;
b = 1;
}
op(SECOND, (a, b -- )) {
use(a, b);
}
macro(TEST) = FIRST + flush + SECOND;
"""
output = """
TARGET(TEST) {
frame->instr_ptr = next_instr;
next_instr += 1;
INSTRUCTION_STATS(TEST);
_PyStackRef a;
_PyStackRef b;
// FIRST
{
a = 0;
b = 1;
}
// flush
stack_pointer[0] = a;
stack_pointer[1] = b;
stack_pointer += 2;
assert(WITHIN_STACK_BOUNDS());
// SECOND
b = stack_pointer[-1];
a = stack_pointer[-2];
{
use(a, b);
}
stack_pointer += -2;
assert(WITHIN_STACK_BOUNDS());
DISPATCH();
}
"""
self.run_cases_test(input, output)
class TestGeneratedAbstractCases(unittest.TestCase): class TestGeneratedAbstractCases(unittest.TestCase):
def setUp(self) -> None: def setUp(self) -> None:
@ -956,7 +1100,6 @@ class TestGeneratedAbstractCases(unittest.TestCase):
case OP: { case OP: {
_Py_UopsSymbol *arg1; _Py_UopsSymbol *arg1;
_Py_UopsSymbol *out; _Py_UopsSymbol *out;
arg1 = stack_pointer[-1];
eggs(); eggs();
stack_pointer[-1] = out; stack_pointer[-1] = out;
break; break;
@ -996,7 +1139,6 @@ class TestGeneratedAbstractCases(unittest.TestCase):
case OP2: { case OP2: {
_Py_UopsSymbol *arg1; _Py_UopsSymbol *arg1;
_Py_UopsSymbol *out; _Py_UopsSymbol *out;
arg1 = stack_pointer[-1];
stack_pointer[-1] = out; stack_pointer[-1] = out;
break; break;
} }

View File

@ -3448,7 +3448,7 @@ dummy_func(
} }
} }
op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
EXIT_IF(!PyFunction_Check(callable_o)); EXIT_IF(!PyFunction_Check(callable_o));
PyFunctionObject *func = (PyFunctionObject *)callable_o; PyFunctionObject *func = (PyFunctionObject *)callable_o;
@ -3479,7 +3479,6 @@ dummy_func(
assert(PyStackRef_IsNull(null)); assert(PyStackRef_IsNull(null));
assert(Py_TYPE(callable_o) == &PyMethod_Type); assert(Py_TYPE(callable_o) == &PyMethod_Type);
self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _PY_FRAME_GENERAL
method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyFunction_Check(PyStackRef_AsPyObjectBorrow(method))); assert(PyFunction_Check(PyStackRef_AsPyObjectBorrow(method)));
PyStackRef_CLOSE(callable); PyStackRef_CLOSE(callable);
@ -3490,6 +3489,7 @@ dummy_func(
_CHECK_PEP_523 + _CHECK_PEP_523 +
_CHECK_METHOD_VERSION + _CHECK_METHOD_VERSION +
_EXPAND_METHOD + _EXPAND_METHOD +
flush + // so that self is in the argument array
_PY_FRAME_GENERAL + _PY_FRAME_GENERAL +
_SAVE_RETURN_OFFSET + _SAVE_RETURN_OFFSET +
_PUSH_FRAME; _PUSH_FRAME;
@ -3544,16 +3544,12 @@ dummy_func(
EXIT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(callable)) != &PyMethod_Type); EXIT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(callable)) != &PyMethod_Type);
} }
op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, unused, unused[oparg] -- func, self, unused[oparg])) { op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null, unused[oparg] -- func, self, unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
STAT_INC(CALL, hit); STAT_INC(CALL, hit);
stack_pointer[-1 - oparg] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); // Patch stack as it is used by _INIT_CALL_PY_EXACT_ARGS self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
stack_pointer[-2 - oparg] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); // This is used by CALL, upon deoptimization func = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
self = stack_pointer[-1 - oparg];
func = stack_pointer[-2 - oparg];
PyStackRef_CLOSE(callable); PyStackRef_CLOSE(callable);
// self may be unused in tier 1, so silence warnings.
(void)self;
} }
op(_CHECK_PEP_523, (--)) { op(_CHECK_PEP_523, (--)) {
@ -3568,7 +3564,7 @@ dummy_func(
EXIT_IF(code->co_argcount != oparg + (!PyStackRef_IsNull(self_or_null))); EXIT_IF(code->co_argcount != oparg + (!PyStackRef_IsNull(self_or_null)));
} }
op(_CHECK_STACK_SPACE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) { op(_CHECK_STACK_SPACE, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyFunctionObject *func = (PyFunctionObject *)callable_o; PyFunctionObject *func = (PyFunctionObject *)callable_o;
PyCodeObject *code = (PyCodeObject *)func->func_code; PyCodeObject *code = (PyCodeObject *)func->func_code;
@ -3609,6 +3605,7 @@ dummy_func(
_CHECK_PEP_523 + _CHECK_PEP_523 +
_CHECK_CALL_BOUND_METHOD_EXACT_ARGS + _CHECK_CALL_BOUND_METHOD_EXACT_ARGS +
_INIT_CALL_BOUND_METHOD_EXACT_ARGS + _INIT_CALL_BOUND_METHOD_EXACT_ARGS +
flush + // In case the following deopt
_CHECK_FUNCTION_VERSION + _CHECK_FUNCTION_VERSION +
_CHECK_FUNCTION_EXACT_ARGS + _CHECK_FUNCTION_EXACT_ARGS +
_CHECK_STACK_SPACE + _CHECK_STACK_SPACE +

View File

@ -3527,7 +3527,6 @@
assert(PyStackRef_IsNull(null)); assert(PyStackRef_IsNull(null));
assert(Py_TYPE(callable_o) == &PyMethod_Type); assert(Py_TYPE(callable_o) == &PyMethod_Type);
self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _PY_FRAME_GENERAL
method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyFunction_Check(PyStackRef_AsPyObjectBorrow(method))); assert(PyFunction_Check(PyStackRef_AsPyObjectBorrow(method)));
PyStackRef_CLOSE(callable); PyStackRef_CLOSE(callable);
@ -3624,13 +3623,9 @@
callable = stack_pointer[-2 - oparg]; callable = stack_pointer[-2 - oparg];
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
STAT_INC(CALL, hit); STAT_INC(CALL, hit);
stack_pointer[-1 - oparg] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); // Patch stack as it is used by _INIT_CALL_PY_EXACT_ARGS self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
stack_pointer[-2 - oparg] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); // This is used by CALL, upon deoptimization func = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
self = stack_pointer[-1 - oparg];
func = stack_pointer[-2 - oparg];
PyStackRef_CLOSE(callable); PyStackRef_CLOSE(callable);
// self may be unused in tier 1, so silence warnings.
(void)self;
stack_pointer[-2 - oparg] = func; stack_pointer[-2 - oparg] = func;
stack_pointer[-1 - oparg] = self; stack_pointer[-1 - oparg] = self;
break; break;

View File

@ -16,8 +16,8 @@
PREDICTED(BINARY_OP); PREDICTED(BINARY_OP);
_Py_CODEUNIT *this_instr = next_instr - 2; _Py_CODEUNIT *this_instr = next_instr - 2;
(void)this_instr; (void)this_instr;
_PyStackRef rhs;
_PyStackRef lhs; _PyStackRef lhs;
_PyStackRef rhs;
_PyStackRef res; _PyStackRef res;
// _SPECIALIZE_BINARY_OP // _SPECIALIZE_BINARY_OP
rhs = stack_pointer[-1]; rhs = stack_pointer[-1];
@ -59,8 +59,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_OP_ADD_FLOAT); INSTRUCTION_STATS(BINARY_OP_ADD_FLOAT);
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _GUARD_BOTH_FLOAT // _GUARD_BOTH_FLOAT
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -95,8 +95,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_OP_ADD_INT); INSTRUCTION_STATS(BINARY_OP_ADD_INT);
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _GUARD_BOTH_INT // _GUARD_BOTH_INT
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -130,8 +130,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_OP_ADD_UNICODE); INSTRUCTION_STATS(BINARY_OP_ADD_UNICODE);
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _GUARD_BOTH_UNICODE // _GUARD_BOTH_UNICODE
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -165,8 +165,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_OP_INPLACE_ADD_UNICODE); INSTRUCTION_STATS(BINARY_OP_INPLACE_ADD_UNICODE);
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
// _GUARD_BOTH_UNICODE // _GUARD_BOTH_UNICODE
right = stack_pointer[-1]; right = stack_pointer[-1];
left = stack_pointer[-2]; left = stack_pointer[-2];
@ -217,8 +217,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_OP_MULTIPLY_FLOAT); INSTRUCTION_STATS(BINARY_OP_MULTIPLY_FLOAT);
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _GUARD_BOTH_FLOAT // _GUARD_BOTH_FLOAT
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -253,8 +253,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_OP_MULTIPLY_INT); INSTRUCTION_STATS(BINARY_OP_MULTIPLY_INT);
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _GUARD_BOTH_INT // _GUARD_BOTH_INT
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -288,8 +288,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_OP_SUBTRACT_FLOAT); INSTRUCTION_STATS(BINARY_OP_SUBTRACT_FLOAT);
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _GUARD_BOTH_FLOAT // _GUARD_BOTH_FLOAT
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -324,8 +324,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_OP_SUBTRACT_INT); INSTRUCTION_STATS(BINARY_OP_SUBTRACT_INT);
static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _GUARD_BOTH_INT // _GUARD_BOTH_INT
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -358,9 +358,9 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(BINARY_SLICE); INSTRUCTION_STATS(BINARY_SLICE);
_PyStackRef stop;
_PyStackRef start;
_PyStackRef container; _PyStackRef container;
_PyStackRef start;
_PyStackRef stop;
_PyStackRef res; _PyStackRef res;
stop = stack_pointer[-1]; stop = stack_pointer[-1];
start = stack_pointer[-2]; start = stack_pointer[-2];
@ -393,8 +393,8 @@
PREDICTED(BINARY_SUBSCR); PREDICTED(BINARY_SUBSCR);
_Py_CODEUNIT *this_instr = next_instr - 2; _Py_CODEUNIT *this_instr = next_instr - 2;
(void)this_instr; (void)this_instr;
_PyStackRef sub;
_PyStackRef container; _PyStackRef container;
_PyStackRef sub;
_PyStackRef res; _PyStackRef res;
// _SPECIALIZE_BINARY_SUBSCR // _SPECIALIZE_BINARY_SUBSCR
sub = stack_pointer[-1]; sub = stack_pointer[-1];
@ -433,8 +433,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_SUBSCR_DICT); INSTRUCTION_STATS(BINARY_SUBSCR_DICT);
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
_PyStackRef sub_st;
_PyStackRef dict_st; _PyStackRef dict_st;
_PyStackRef sub_st;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
sub_st = stack_pointer[-1]; sub_st = stack_pointer[-1];
@ -464,8 +464,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_SUBSCR_GETITEM); INSTRUCTION_STATS(BINARY_SUBSCR_GETITEM);
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
_PyStackRef sub_st;
_PyStackRef container_st; _PyStackRef container_st;
_PyStackRef sub_st;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
sub_st = stack_pointer[-1]; sub_st = stack_pointer[-1];
container_st = stack_pointer[-2]; container_st = stack_pointer[-2];
@ -498,8 +498,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_SUBSCR_LIST_INT); INSTRUCTION_STATS(BINARY_SUBSCR_LIST_INT);
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
_PyStackRef sub_st;
_PyStackRef list_st; _PyStackRef list_st;
_PyStackRef sub_st;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
sub_st = stack_pointer[-1]; sub_st = stack_pointer[-1];
@ -530,8 +530,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_SUBSCR_STR_INT); INSTRUCTION_STATS(BINARY_SUBSCR_STR_INT);
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
_PyStackRef sub_st;
_PyStackRef str_st; _PyStackRef str_st;
_PyStackRef sub_st;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
sub_st = stack_pointer[-1]; sub_st = stack_pointer[-1];
@ -562,8 +562,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(BINARY_SUBSCR_TUPLE_INT); INSTRUCTION_STATS(BINARY_SUBSCR_TUPLE_INT);
static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_BINARY_SUBSCR == 1, "incorrect cache size");
_PyStackRef sub_st;
_PyStackRef tuple_st; _PyStackRef tuple_st;
_PyStackRef sub_st;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
sub_st = stack_pointer[-1]; sub_st = stack_pointer[-1];
@ -593,8 +593,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(BUILD_CONST_KEY_MAP); INSTRUCTION_STATS(BUILD_CONST_KEY_MAP);
_PyStackRef keys;
_PyStackRef *values; _PyStackRef *values;
_PyStackRef keys;
_PyStackRef map; _PyStackRef map;
keys = stack_pointer[-1]; keys = stack_pointer[-1];
values = &stack_pointer[-1 - oparg]; values = &stack_pointer[-1 - oparg];
@ -713,9 +713,9 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(BUILD_SLICE); INSTRUCTION_STATS(BUILD_SLICE);
_PyStackRef step = PyStackRef_NULL;
_PyStackRef stop;
_PyStackRef start; _PyStackRef start;
_PyStackRef stop;
_PyStackRef step = PyStackRef_NULL;
_PyStackRef slice; _PyStackRef slice;
if (oparg == 3) { step = stack_pointer[-((oparg == 3) ? 1 : 0)]; } if (oparg == 3) { step = stack_pointer[-((oparg == 3) ? 1 : 0)]; }
stop = stack_pointer[-1 - ((oparg == 3) ? 1 : 0)]; stop = stack_pointer[-1 - ((oparg == 3) ? 1 : 0)];
@ -794,15 +794,15 @@
PREDICTED(CALL); PREDICTED(CALL);
_Py_CODEUNIT *this_instr = next_instr - 4; _Py_CODEUNIT *this_instr = next_instr - 4;
(void)this_instr; (void)this_instr;
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
// _SPECIALIZE_CALL // _SPECIALIZE_CALL
args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg]; self_or_null = stack_pointer[-1 - oparg];
callable = stack_pointer[-2 - oparg]; callable = stack_pointer[-2 - oparg];
{ {
args = &stack_pointer[-oparg];
uint16_t counter = read_u16(&this_instr[1].cache); uint16_t counter = read_u16(&this_instr[1].cache);
(void)counter; (void)counter;
#if ENABLE_SPECIALIZATION #if ENABLE_SPECIALIZATION
@ -913,9 +913,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_ALLOC_AND_ENTER_INIT); INSTRUCTION_STATS(CALL_ALLOC_AND_ENTER_INIT);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef null;
_PyStackRef *args;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
args = &stack_pointer[-oparg]; args = &stack_pointer[-oparg];
@ -977,8 +977,8 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_BOUND_METHOD_EXACT_ARGS); INSTRUCTION_STATS(CALL_BOUND_METHOD_EXACT_ARGS);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef null;
_PyStackRef func; _PyStackRef func;
_PyStackRef self; _PyStackRef self;
_PyStackRef self_or_null; _PyStackRef self_or_null;
@ -1000,16 +1000,15 @@
{ {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
STAT_INC(CALL, hit); STAT_INC(CALL, hit);
stack_pointer[-1 - oparg] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); // Patch stack as it is used by _INIT_CALL_PY_EXACT_ARGS self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
stack_pointer[-2 - oparg] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); // This is used by CALL, upon deoptimization func = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
self = stack_pointer[-1 - oparg];
func = stack_pointer[-2 - oparg];
PyStackRef_CLOSE(callable); PyStackRef_CLOSE(callable);
// self may be unused in tier 1, so silence warnings.
(void)self;
} }
// flush
stack_pointer[-2 - oparg] = func;
stack_pointer[-1 - oparg] = self;
// _CHECK_FUNCTION_VERSION // _CHECK_FUNCTION_VERSION
callable = func; callable = stack_pointer[-2 - oparg];
{ {
uint32_t func_version = read_u32(&this_instr[2].cache); uint32_t func_version = read_u32(&this_instr[2].cache);
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
@ -1036,7 +1035,6 @@
} }
// _INIT_CALL_PY_EXACT_ARGS // _INIT_CALL_PY_EXACT_ARGS
args = &stack_pointer[-oparg]; args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg];
{ {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null); int has_self = !PyStackRef_IsNull(self_or_null);
@ -1082,12 +1080,12 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_BOUND_METHOD_GENERAL); INSTRUCTION_STATS(CALL_BOUND_METHOD_GENERAL);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef null;
_PyStackRef method; _PyStackRef method;
_PyStackRef self; _PyStackRef self;
_PyStackRef *args;
_PyStackRef self_or_null; _PyStackRef self_or_null;
_PyStackRef *args;
_PyInterpreterFrame *new_frame; _PyInterpreterFrame *new_frame;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
// _CHECK_PEP_523 // _CHECK_PEP_523
@ -1112,15 +1110,17 @@
assert(PyStackRef_IsNull(null)); assert(PyStackRef_IsNull(null));
assert(Py_TYPE(callable_o) == &PyMethod_Type); assert(Py_TYPE(callable_o) == &PyMethod_Type);
self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _PY_FRAME_GENERAL
method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
assert(PyFunction_Check(PyStackRef_AsPyObjectBorrow(method))); assert(PyFunction_Check(PyStackRef_AsPyObjectBorrow(method)));
PyStackRef_CLOSE(callable); PyStackRef_CLOSE(callable);
} }
// flush
stack_pointer[-2 - oparg] = method;
stack_pointer[-1 - oparg] = self;
// _PY_FRAME_GENERAL // _PY_FRAME_GENERAL
args = &stack_pointer[-oparg]; args = &stack_pointer[-oparg];
self_or_null = self; self_or_null = stack_pointer[-1 - oparg];
callable = method; callable = stack_pointer[-2 - oparg];
{ {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
PyObject *self_or_null_o = PyStackRef_AsPyObjectBorrow(self_or_null); PyObject *self_or_null_o = PyStackRef_AsPyObjectBorrow(self_or_null);
@ -1176,9 +1176,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_BUILTIN_CLASS); INSTRUCTION_STATS(CALL_BUILTIN_CLASS);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -1231,9 +1231,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_BUILTIN_FAST); INSTRUCTION_STATS(CALL_BUILTIN_FAST);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -1292,9 +1292,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_BUILTIN_FAST_WITH_KEYWORDS); INSTRUCTION_STATS(CALL_BUILTIN_FAST_WITH_KEYWORDS);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -1352,9 +1352,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_BUILTIN_O); INSTRUCTION_STATS(CALL_BUILTIN_O);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -1404,9 +1404,9 @@
PREDICTED(CALL_FUNCTION_EX); PREDICTED(CALL_FUNCTION_EX);
_Py_CODEUNIT *this_instr = next_instr - 1; _Py_CODEUNIT *this_instr = next_instr - 1;
(void)this_instr; (void)this_instr;
_PyStackRef kwargs_st = PyStackRef_NULL;
_PyStackRef callargs_st;
_PyStackRef func_st; _PyStackRef func_st;
_PyStackRef callargs_st;
_PyStackRef kwargs_st = PyStackRef_NULL;
_PyStackRef result; _PyStackRef result;
if (oparg & 1) { kwargs_st = stack_pointer[-(oparg & 1)]; } if (oparg & 1) { kwargs_st = stack_pointer[-(oparg & 1)]; }
callargs_st = stack_pointer[-1 - (oparg & 1)]; callargs_st = stack_pointer[-1 - (oparg & 1)];
@ -1509,8 +1509,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(CALL_INTRINSIC_2); INSTRUCTION_STATS(CALL_INTRINSIC_2);
_PyStackRef value1_st;
_PyStackRef value2_st; _PyStackRef value2_st;
_PyStackRef value1_st;
_PyStackRef res; _PyStackRef res;
value1_st = stack_pointer[-1]; value1_st = stack_pointer[-1];
value2_st = stack_pointer[-2]; value2_st = stack_pointer[-2];
@ -1533,9 +1533,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_ISINSTANCE); INSTRUCTION_STATS(CALL_ISINSTANCE);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -1577,10 +1577,10 @@
PREDICTED(CALL_KW); PREDICTED(CALL_KW);
_Py_CODEUNIT *this_instr = next_instr - 1; _Py_CODEUNIT *this_instr = next_instr - 1;
(void)this_instr; (void)this_instr;
_PyStackRef kwnames;
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef kwnames;
_PyStackRef res; _PyStackRef res;
kwnames = stack_pointer[-1]; kwnames = stack_pointer[-1];
args = &stack_pointer[-1 - oparg]; args = &stack_pointer[-1 - oparg];
@ -1683,9 +1683,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_LEN); INSTRUCTION_STATS(CALL_LEN);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -1728,9 +1728,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_LIST_APPEND); INSTRUCTION_STATS(CALL_LIST_APPEND);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef arg;
_PyStackRef self;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self;
_PyStackRef arg;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
arg = stack_pointer[-1]; arg = stack_pointer[-1];
@ -1761,9 +1761,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_FAST); INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_FAST);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -1824,9 +1824,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS); INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -1887,9 +1887,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_NOARGS); INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_NOARGS);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -1941,9 +1941,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_O); INSTRUCTION_STATS(CALL_METHOD_DESCRIPTOR_O);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef *args;
_PyStackRef self_or_null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -1999,8 +1999,8 @@
INSTRUCTION_STATS(CALL_NON_PY_GENERAL); INSTRUCTION_STATS(CALL_NON_PY_GENERAL);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef callable; _PyStackRef callable;
_PyStackRef *args;
_PyStackRef self_or_null; _PyStackRef self_or_null;
_PyStackRef *args;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -2100,7 +2100,6 @@
} }
// _INIT_CALL_PY_EXACT_ARGS // _INIT_CALL_PY_EXACT_ARGS
args = &stack_pointer[-oparg]; args = &stack_pointer[-oparg];
self_or_null = stack_pointer[-1 - oparg];
{ {
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
int has_self = !PyStackRef_IsNull(self_or_null); int has_self = !PyStackRef_IsNull(self_or_null);
@ -2147,8 +2146,8 @@
INSTRUCTION_STATS(CALL_PY_GENERAL); INSTRUCTION_STATS(CALL_PY_GENERAL);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef callable; _PyStackRef callable;
_PyStackRef *args;
_PyStackRef self_or_null; _PyStackRef self_or_null;
_PyStackRef *args;
_PyInterpreterFrame *new_frame; _PyInterpreterFrame *new_frame;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
// _CHECK_PEP_523 // _CHECK_PEP_523
@ -2222,9 +2221,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_STR_1); INSTRUCTION_STATS(CALL_STR_1);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef arg;
_PyStackRef null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef null;
_PyStackRef arg;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -2258,9 +2257,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_TUPLE_1); INSTRUCTION_STATS(CALL_TUPLE_1);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef arg;
_PyStackRef null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef null;
_PyStackRef arg;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -2294,9 +2293,9 @@
next_instr += 4; next_instr += 4;
INSTRUCTION_STATS(CALL_TYPE_1); INSTRUCTION_STATS(CALL_TYPE_1);
static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CALL == 3, "incorrect cache size");
_PyStackRef arg;
_PyStackRef null;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef null;
_PyStackRef arg;
_PyStackRef res; _PyStackRef res;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
/* Skip 2 cache entries */ /* Skip 2 cache entries */
@ -2321,8 +2320,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(CHECK_EG_MATCH); INSTRUCTION_STATS(CHECK_EG_MATCH);
_PyStackRef match_type_st;
_PyStackRef exc_value_st; _PyStackRef exc_value_st;
_PyStackRef match_type_st;
_PyStackRef rest; _PyStackRef rest;
_PyStackRef match; _PyStackRef match;
match_type_st = stack_pointer[-1]; match_type_st = stack_pointer[-1];
@ -2357,8 +2356,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(CHECK_EXC_MATCH); INSTRUCTION_STATS(CHECK_EXC_MATCH);
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef b; _PyStackRef b;
right = stack_pointer[-1]; right = stack_pointer[-1];
left = stack_pointer[-2]; left = stack_pointer[-2];
@ -2381,9 +2380,9 @@
(void)this_instr; (void)this_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(CLEANUP_THROW); INSTRUCTION_STATS(CLEANUP_THROW);
_PyStackRef exc_value_st;
_PyStackRef last_sent_val_st;
_PyStackRef sub_iter_st; _PyStackRef sub_iter_st;
_PyStackRef last_sent_val_st;
_PyStackRef exc_value_st;
_PyStackRef none; _PyStackRef none;
_PyStackRef value; _PyStackRef value;
exc_value_st = stack_pointer[-1]; exc_value_st = stack_pointer[-1];
@ -2418,8 +2417,8 @@
PREDICTED(COMPARE_OP); PREDICTED(COMPARE_OP);
_Py_CODEUNIT *this_instr = next_instr - 2; _Py_CODEUNIT *this_instr = next_instr - 2;
(void)this_instr; (void)this_instr;
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _SPECIALIZE_COMPARE_OP // _SPECIALIZE_COMPARE_OP
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -2467,8 +2466,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(COMPARE_OP_FLOAT); INSTRUCTION_STATS(COMPARE_OP_FLOAT);
static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _GUARD_BOTH_FLOAT // _GUARD_BOTH_FLOAT
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -2505,8 +2504,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(COMPARE_OP_INT); INSTRUCTION_STATS(COMPARE_OP_INT);
static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _GUARD_BOTH_INT // _GUARD_BOTH_INT
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -2547,8 +2546,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(COMPARE_OP_STR); INSTRUCTION_STATS(COMPARE_OP_STR);
static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_COMPARE_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef res; _PyStackRef res;
// _GUARD_BOTH_UNICODE // _GUARD_BOTH_UNICODE
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -2588,12 +2587,11 @@
PREDICTED(CONTAINS_OP); PREDICTED(CONTAINS_OP);
_Py_CODEUNIT *this_instr = next_instr - 2; _Py_CODEUNIT *this_instr = next_instr - 2;
(void)this_instr; (void)this_instr;
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef b; _PyStackRef b;
// _SPECIALIZE_CONTAINS_OP // _SPECIALIZE_CONTAINS_OP
right = stack_pointer[-1]; right = stack_pointer[-1];
left = stack_pointer[-2];
{ {
uint16_t counter = read_u16(&this_instr[1].cache); uint16_t counter = read_u16(&this_instr[1].cache);
(void)counter; (void)counter;
@ -2608,6 +2606,7 @@
#endif /* ENABLE_SPECIALIZATION */ #endif /* ENABLE_SPECIALIZATION */
} }
// _CONTAINS_OP // _CONTAINS_OP
left = stack_pointer[-2];
{ {
PyObject *left_o = PyStackRef_AsPyObjectBorrow(left); PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
PyObject *right_o = PyStackRef_AsPyObjectBorrow(right); PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
@ -2628,8 +2627,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(CONTAINS_OP_DICT); INSTRUCTION_STATS(CONTAINS_OP_DICT);
static_assert(INLINE_CACHE_ENTRIES_CONTAINS_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CONTAINS_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef b; _PyStackRef b;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -2654,8 +2653,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(CONTAINS_OP_SET); INSTRUCTION_STATS(CONTAINS_OP_SET);
static_assert(INLINE_CACHE_ENTRIES_CONTAINS_OP == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_CONTAINS_OP == 1, "incorrect cache size");
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef b; _PyStackRef b;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
right = stack_pointer[-1]; right = stack_pointer[-1];
@ -2818,8 +2817,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(DELETE_SUBSCR); INSTRUCTION_STATS(DELETE_SUBSCR);
_PyStackRef sub;
_PyStackRef container; _PyStackRef container;
_PyStackRef sub;
sub = stack_pointer[-1]; sub = stack_pointer[-1];
container = stack_pointer[-2]; container = stack_pointer[-2];
/* del container[sub] */ /* del container[sub] */
@ -2837,9 +2836,9 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(DICT_MERGE); INSTRUCTION_STATS(DICT_MERGE);
_PyStackRef update;
_PyStackRef dict;
_PyStackRef callable; _PyStackRef callable;
_PyStackRef dict;
_PyStackRef update;
update = stack_pointer[-1]; update = stack_pointer[-1];
dict = stack_pointer[-2 - (oparg - 1)]; dict = stack_pointer[-2 - (oparg - 1)];
callable = stack_pointer[-5 - (oparg - 1)]; callable = stack_pointer[-5 - (oparg - 1)];
@ -2861,8 +2860,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(DICT_UPDATE); INSTRUCTION_STATS(DICT_UPDATE);
_PyStackRef update;
_PyStackRef dict; _PyStackRef dict;
_PyStackRef update;
update = stack_pointer[-1]; update = stack_pointer[-1];
dict = stack_pointer[-2 - (oparg - 1)]; dict = stack_pointer[-2 - (oparg - 1)];
PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict); PyObject *dict_o = PyStackRef_AsPyObjectBorrow(dict);
@ -2887,8 +2886,8 @@
(void)this_instr; (void)this_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(END_ASYNC_FOR); INSTRUCTION_STATS(END_ASYNC_FOR);
_PyStackRef exc_st;
_PyStackRef awaitable_st; _PyStackRef awaitable_st;
_PyStackRef exc_st;
exc_st = stack_pointer[-1]; exc_st = stack_pointer[-1];
awaitable_st = stack_pointer[-2]; awaitable_st = stack_pointer[-2];
PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st); PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st);
@ -2924,8 +2923,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(END_SEND); INSTRUCTION_STATS(END_SEND);
_PyStackRef value;
_PyStackRef receiver; _PyStackRef receiver;
_PyStackRef value;
value = stack_pointer[-1]; value = stack_pointer[-1];
receiver = stack_pointer[-2]; receiver = stack_pointer[-2];
(void)receiver; (void)receiver;
@ -3024,8 +3023,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(FORMAT_WITH_SPEC); INSTRUCTION_STATS(FORMAT_WITH_SPEC);
_PyStackRef fmt_spec;
_PyStackRef value; _PyStackRef value;
_PyStackRef fmt_spec;
_PyStackRef res; _PyStackRef res;
fmt_spec = stack_pointer[-1]; fmt_spec = stack_pointer[-1];
value = stack_pointer[-2]; value = stack_pointer[-2];
@ -3502,8 +3501,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(IMPORT_NAME); INSTRUCTION_STATS(IMPORT_NAME);
_PyStackRef fromlist;
_PyStackRef level; _PyStackRef level;
_PyStackRef fromlist;
_PyStackRef res; _PyStackRef res;
fromlist = stack_pointer[-1]; fromlist = stack_pointer[-1];
level = stack_pointer[-2]; level = stack_pointer[-2];
@ -3569,8 +3568,8 @@
(void)this_instr; (void)this_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(INSTRUMENTED_END_FOR); INSTRUCTION_STATS(INSTRUMENTED_END_FOR);
_PyStackRef value;
_PyStackRef receiver; _PyStackRef receiver;
_PyStackRef value;
value = stack_pointer[-1]; value = stack_pointer[-1];
receiver = stack_pointer[-2]; receiver = stack_pointer[-2];
/* Need to create a fake StopIteration error here, /* Need to create a fake StopIteration error here,
@ -3591,8 +3590,8 @@
(void)this_instr; (void)this_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(INSTRUMENTED_END_SEND); INSTRUCTION_STATS(INSTRUMENTED_END_SEND);
_PyStackRef value;
_PyStackRef receiver; _PyStackRef receiver;
_PyStackRef value;
value = stack_pointer[-1]; value = stack_pointer[-1];
receiver = stack_pointer[-2]; receiver = stack_pointer[-2];
PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver); PyObject *receiver_o = PyStackRef_AsPyObjectBorrow(receiver);
@ -3901,8 +3900,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(IS_OP); INSTRUCTION_STATS(IS_OP);
_PyStackRef right;
_PyStackRef left; _PyStackRef left;
_PyStackRef right;
_PyStackRef b; _PyStackRef b;
right = stack_pointer[-1]; right = stack_pointer[-1];
left = stack_pointer[-2]; left = stack_pointer[-2];
@ -3986,8 +3985,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(LIST_APPEND); INSTRUCTION_STATS(LIST_APPEND);
_PyStackRef v;
_PyStackRef list; _PyStackRef list;
_PyStackRef v;
v = stack_pointer[-1]; v = stack_pointer[-1];
list = stack_pointer[-2 - (oparg-1)]; list = stack_pointer[-2 - (oparg-1)];
if (_PyList_AppendTakeRef((PyListObject *)PyStackRef_AsPyObjectBorrow(list), if (_PyList_AppendTakeRef((PyListObject *)PyStackRef_AsPyObjectBorrow(list),
@ -4001,8 +4000,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(LIST_EXTEND); INSTRUCTION_STATS(LIST_EXTEND);
_PyStackRef iterable_st;
_PyStackRef list_st; _PyStackRef list_st;
_PyStackRef iterable_st;
iterable_st = stack_pointer[-1]; iterable_st = stack_pointer[-1];
list_st = stack_pointer[-2 - (oparg-1)]; list_st = stack_pointer[-2 - (oparg-1)];
PyObject *list = PyStackRef_AsPyObjectBorrow(list_st); PyObject *list = PyStackRef_AsPyObjectBorrow(list_st);
@ -5043,8 +5042,8 @@
PREDICTED(LOAD_SUPER_ATTR); PREDICTED(LOAD_SUPER_ATTR);
_Py_CODEUNIT *this_instr = next_instr - 2; _Py_CODEUNIT *this_instr = next_instr - 2;
(void)this_instr; (void)this_instr;
_PyStackRef class_st;
_PyStackRef global_super_st; _PyStackRef global_super_st;
_PyStackRef class_st;
_PyStackRef self_st; _PyStackRef self_st;
_PyStackRef attr; _PyStackRef attr;
_PyStackRef null = PyStackRef_NULL; _PyStackRef null = PyStackRef_NULL;
@ -5120,9 +5119,9 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(LOAD_SUPER_ATTR_ATTR); INSTRUCTION_STATS(LOAD_SUPER_ATTR_ATTR);
static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, "incorrect cache size");
_PyStackRef self_st;
_PyStackRef class_st;
_PyStackRef global_super_st; _PyStackRef global_super_st;
_PyStackRef class_st;
_PyStackRef self_st;
_PyStackRef attr_st; _PyStackRef attr_st;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
self_st = stack_pointer[-1]; self_st = stack_pointer[-1];
@ -5153,9 +5152,9 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(LOAD_SUPER_ATTR_METHOD); INSTRUCTION_STATS(LOAD_SUPER_ATTR_METHOD);
static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_LOAD_SUPER_ATTR == 1, "incorrect cache size");
_PyStackRef self_st;
_PyStackRef class_st;
_PyStackRef global_super_st; _PyStackRef global_super_st;
_PyStackRef class_st;
_PyStackRef self_st;
_PyStackRef attr; _PyStackRef attr;
_PyStackRef self_or_null; _PyStackRef self_or_null;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
@ -5234,9 +5233,9 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(MAP_ADD); INSTRUCTION_STATS(MAP_ADD);
_PyStackRef value;
_PyStackRef key;
_PyStackRef dict_st; _PyStackRef dict_st;
_PyStackRef key;
_PyStackRef value;
value = stack_pointer[-1]; value = stack_pointer[-1];
key = stack_pointer[-2]; key = stack_pointer[-2];
dict_st = stack_pointer[-3 - (oparg - 1)]; dict_st = stack_pointer[-3 - (oparg - 1)];
@ -5254,9 +5253,9 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(MATCH_CLASS); INSTRUCTION_STATS(MATCH_CLASS);
_PyStackRef names;
_PyStackRef type;
_PyStackRef subject; _PyStackRef subject;
_PyStackRef type;
_PyStackRef names;
_PyStackRef attrs; _PyStackRef attrs;
names = stack_pointer[-1]; names = stack_pointer[-1];
type = stack_pointer[-2]; type = stack_pointer[-2];
@ -5290,8 +5289,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(MATCH_KEYS); INSTRUCTION_STATS(MATCH_KEYS);
_PyStackRef keys;
_PyStackRef subject; _PyStackRef subject;
_PyStackRef keys;
_PyStackRef values_or_none; _PyStackRef values_or_none;
keys = stack_pointer[-1]; keys = stack_pointer[-1];
subject = stack_pointer[-2]; subject = stack_pointer[-2];
@ -5548,8 +5547,8 @@
(void)this_instr; (void)this_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(RERAISE); INSTRUCTION_STATS(RERAISE);
_PyStackRef exc_st;
_PyStackRef *values; _PyStackRef *values;
_PyStackRef exc_st;
exc_st = stack_pointer[-1]; exc_st = stack_pointer[-1];
values = &stack_pointer[-1 - oparg]; values = &stack_pointer[-1 - oparg];
PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st); PyObject *exc = PyStackRef_AsPyObjectBorrow(exc_st);
@ -5811,8 +5810,8 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(SEND_GEN); INSTRUCTION_STATS(SEND_GEN);
static_assert(INLINE_CACHE_ENTRIES_SEND == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_SEND == 1, "incorrect cache size");
_PyStackRef v;
_PyStackRef receiver; _PyStackRef receiver;
_PyStackRef v;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
v = stack_pointer[-1]; v = stack_pointer[-1];
receiver = stack_pointer[-2]; receiver = stack_pointer[-2];
@ -5863,8 +5862,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(SET_ADD); INSTRUCTION_STATS(SET_ADD);
_PyStackRef v;
_PyStackRef set; _PyStackRef set;
_PyStackRef v;
v = stack_pointer[-1]; v = stack_pointer[-1];
set = stack_pointer[-2 - (oparg-1)]; set = stack_pointer[-2 - (oparg-1)];
int err = PySet_Add(PyStackRef_AsPyObjectBorrow(set), int err = PySet_Add(PyStackRef_AsPyObjectBorrow(set),
@ -5880,8 +5879,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(SET_FUNCTION_ATTRIBUTE); INSTRUCTION_STATS(SET_FUNCTION_ATTRIBUTE);
_PyStackRef func_st;
_PyStackRef attr_st; _PyStackRef attr_st;
_PyStackRef func_st;
func_st = stack_pointer[-1]; func_st = stack_pointer[-1];
attr_st = stack_pointer[-2]; attr_st = stack_pointer[-2];
PyObject *func = PyStackRef_AsPyObjectBorrow(func_st); PyObject *func = PyStackRef_AsPyObjectBorrow(func_st);
@ -5925,8 +5924,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(SET_UPDATE); INSTRUCTION_STATS(SET_UPDATE);
_PyStackRef iterable;
_PyStackRef set; _PyStackRef set;
_PyStackRef iterable;
iterable = stack_pointer[-1]; iterable = stack_pointer[-1];
set = stack_pointer[-2 - (oparg-1)]; set = stack_pointer[-2 - (oparg-1)];
int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set), int err = _PySet_Update(PyStackRef_AsPyObjectBorrow(set),
@ -6163,8 +6162,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(STORE_FAST_STORE_FAST); INSTRUCTION_STATS(STORE_FAST_STORE_FAST);
_PyStackRef value1;
_PyStackRef value2; _PyStackRef value2;
_PyStackRef value1;
value1 = stack_pointer[-1]; value1 = stack_pointer[-1];
value2 = stack_pointer[-2]; value2 = stack_pointer[-2];
uint32_t oparg1 = oparg >> 4; uint32_t oparg1 = oparg >> 4;
@ -6221,10 +6220,10 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(STORE_SLICE); INSTRUCTION_STATS(STORE_SLICE);
_PyStackRef stop;
_PyStackRef start;
_PyStackRef container;
_PyStackRef v; _PyStackRef v;
_PyStackRef container;
_PyStackRef start;
_PyStackRef stop;
stop = stack_pointer[-1]; stop = stack_pointer[-1];
start = stack_pointer[-2]; start = stack_pointer[-2];
container = stack_pointer[-3]; container = stack_pointer[-3];
@ -6254,8 +6253,8 @@
PREDICTED(STORE_SUBSCR); PREDICTED(STORE_SUBSCR);
_Py_CODEUNIT *this_instr = next_instr - 2; _Py_CODEUNIT *this_instr = next_instr - 2;
(void)this_instr; (void)this_instr;
_PyStackRef sub;
_PyStackRef container; _PyStackRef container;
_PyStackRef sub;
_PyStackRef v; _PyStackRef v;
// _SPECIALIZE_STORE_SUBSCR // _SPECIALIZE_STORE_SUBSCR
sub = stack_pointer[-1]; sub = stack_pointer[-1];
@ -6293,9 +6292,9 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(STORE_SUBSCR_DICT); INSTRUCTION_STATS(STORE_SUBSCR_DICT);
static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size");
_PyStackRef sub_st;
_PyStackRef dict_st;
_PyStackRef value; _PyStackRef value;
_PyStackRef dict_st;
_PyStackRef sub_st;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
sub_st = stack_pointer[-1]; sub_st = stack_pointer[-1];
dict_st = stack_pointer[-2]; dict_st = stack_pointer[-2];
@ -6317,9 +6316,9 @@
next_instr += 2; next_instr += 2;
INSTRUCTION_STATS(STORE_SUBSCR_LIST_INT); INSTRUCTION_STATS(STORE_SUBSCR_LIST_INT);
static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size"); static_assert(INLINE_CACHE_ENTRIES_STORE_SUBSCR == 1, "incorrect cache size");
_PyStackRef sub_st;
_PyStackRef list_st;
_PyStackRef value; _PyStackRef value;
_PyStackRef list_st;
_PyStackRef sub_st;
/* Skip 1 cache entry */ /* Skip 1 cache entry */
sub_st = stack_pointer[-1]; sub_st = stack_pointer[-1];
list_st = stack_pointer[-2]; list_st = stack_pointer[-2];
@ -6349,8 +6348,8 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(SWAP); INSTRUCTION_STATS(SWAP);
_PyStackRef top;
_PyStackRef bottom; _PyStackRef bottom;
_PyStackRef top;
top = stack_pointer[-1]; top = stack_pointer[-1];
bottom = stack_pointer[-2 - (oparg-2)]; bottom = stack_pointer[-2 - (oparg-2)];
assert(oparg >= 2); assert(oparg >= 2);
@ -6698,10 +6697,10 @@
frame->instr_ptr = next_instr; frame->instr_ptr = next_instr;
next_instr += 1; next_instr += 1;
INSTRUCTION_STATS(WITH_EXCEPT_START); INSTRUCTION_STATS(WITH_EXCEPT_START);
_PyStackRef val;
_PyStackRef lasti;
_PyStackRef exit_self;
_PyStackRef exit_func; _PyStackRef exit_func;
_PyStackRef exit_self;
_PyStackRef lasti;
_PyStackRef val;
_PyStackRef res; _PyStackRef res;
val = stack_pointer[-1]; val = stack_pointer[-1];
lasti = stack_pointer[-3]; lasti = stack_pointer[-3];

View File

@ -78,7 +78,7 @@ SKIP_PROPERTIES = Properties(
uses_locals=False, uses_locals=False,
has_free=False, has_free=False,
side_exit=False, side_exit=False,
pure=False, pure=True,
) )
@ -96,6 +96,20 @@ class Skip:
return SKIP_PROPERTIES return SKIP_PROPERTIES
class Flush:
@property
def properties(self) -> Properties:
return SKIP_PROPERTIES
@property
def name(self) -> str:
return "flush"
@property
def size(self) -> int:
return 0
@dataclass @dataclass
class StackItem: class StackItem:
name: str name: str
@ -103,6 +117,7 @@ class StackItem:
condition: str | None condition: str | None
size: str size: str
peek: bool = False peek: bool = False
used: bool = False
def __str__(self) -> str: def __str__(self) -> str:
cond = f" if ({self.condition})" if self.condition else "" cond = f" if ({self.condition})" if self.condition else ""
@ -133,7 +148,6 @@ class CacheEntry:
def __str__(self) -> str: def __str__(self) -> str:
return f"{self.name}/{self.size}" return f"{self.name}/{self.size}"
@dataclass @dataclass
class Uop: class Uop:
name: str name: str
@ -195,7 +209,7 @@ class Uop:
return False return False
Part = Uop | Skip Part = Uop | Skip | Flush
@dataclass @dataclass
@ -306,6 +320,16 @@ def analyze_stack(op: parser.InstDef | parser.Pseudo, replace_op_arg_1: str | No
for input, output in zip(inputs, outputs): for input, output in zip(inputs, outputs):
if input.name == output.name: if input.name == output.name:
input.peek = output.peek = True input.peek = output.peek = True
if isinstance(op, parser.InstDef):
output_names = [out.name for out in outputs]
for input in inputs:
if (variable_used(op, input.name) or
variable_used(op, "DECREF_INPUTS") or
(not input.peek and input.name in output_names)):
input.used = True
for output in outputs:
if variable_used(op, output.name):
output.used = True
return StackEffect(inputs, outputs) return StackEffect(inputs, outputs)
@ -324,7 +348,13 @@ def analyze_caches(inputs: list[parser.InputEffect]) -> list[CacheEntry]:
def variable_used(node: parser.InstDef, name: str) -> bool: def variable_used(node: parser.InstDef, name: str) -> bool:
"""Determine whether a variable with a given name is used in a node.""" """Determine whether a variable with a given name is used in a node."""
return any( return any(
token.kind == "IDENTIFIER" and token.text == name for token in node.tokens token.kind == "IDENTIFIER" and token.text == name for token in node.block.tokens
)
def oparg_used(node: parser.InstDef) -> bool:
"""Determine whether `oparg` is used in a node."""
return any(
token.kind == "IDENTIFIER" and token.text == "oparg" for token in node.tokens
) )
def tier_variable(node: parser.InstDef) -> int | None: def tier_variable(node: parser.InstDef) -> int | None:
@ -570,7 +600,7 @@ def compute_properties(op: parser.InstDef) -> Properties:
error_without_pop=error_without_pop, error_without_pop=error_without_pop,
deopts=deopts_if, deopts=deopts_if,
side_exit=exits_if, side_exit=exits_if,
oparg=variable_used(op, "oparg"), oparg=oparg_used(op),
jumps=variable_used(op, "JUMPBY"), jumps=variable_used(op, "JUMPBY"),
eval_breaker=variable_used(op, "CHECK_EVAL_BREAKER"), eval_breaker=variable_used(op, "CHECK_EVAL_BREAKER"),
ends_with_eval_breaker=eval_breaker_at_end(op), ends_with_eval_breaker=eval_breaker_at_end(op),
@ -689,12 +719,15 @@ def desugar_inst(
def add_macro( def add_macro(
macro: parser.Macro, instructions: dict[str, Instruction], uops: dict[str, Uop] macro: parser.Macro, instructions: dict[str, Instruction], uops: dict[str, Uop]
) -> None: ) -> None:
parts: list[Uop | Skip] = [] parts: list[Part] = []
for part in macro.uops: for part in macro.uops:
match part: match part:
case parser.OpName(): case parser.OpName():
if part.name == "flush":
parts.append(Flush())
else:
if part.name not in uops: if part.name not in uops:
analysis_error(f"No Uop named {part.name}", macro.tokens[0]) raise analysis_error(f"No Uop named {part.name}", macro.tokens[0])
parts.append(uops[part.name]) parts.append(uops[part.name])
case parser.CacheEffect(): case parser.CacheEffect():
parts.append(Skip(part.size)) parts.append(Skip(part.size))

View File

@ -23,7 +23,7 @@ from generators_common import (
from cwriter import CWriter from cwriter import CWriter
from typing import TextIO, Iterator from typing import TextIO, Iterator
from lexer import Token from lexer import Token
from stack import Stack, SizeMismatch from stack import Stack, StackError
DEFAULT_OUTPUT = ROOT / "Python/optimizer_cases.c.h" DEFAULT_OUTPUT = ROOT / "Python/optimizer_cases.c.h"
DEFAULT_ABSTRACT_INPUT = (ROOT / "Python/optimizer_bytecodes.c").absolute().as_posix() DEFAULT_ABSTRACT_INPUT = (ROOT / "Python/optimizer_bytecodes.c").absolute().as_posix()
@ -141,7 +141,7 @@ def write_uop(
out.emit(stack.push(var)) out.emit(stack.push(var))
out.start_line() out.start_line()
stack.flush(out, cast_type="_Py_UopsSymbol *", extract_bits=True) stack.flush(out, cast_type="_Py_UopsSymbol *", extract_bits=True)
except SizeMismatch as ex: except StackError as ex:
raise analysis_error(ex.args[0], uop.body[0]) raise analysis_error(ex.args[0], uop.body[0])

View File

@ -114,7 +114,7 @@ class StackOffset:
self.pushed = [] self.pushed = []
class SizeMismatch(Exception): class StackError(Exception):
pass pass
@ -134,26 +134,28 @@ class Stack:
if self.variables: if self.variables:
popped = self.variables.pop() popped = self.variables.pop()
if popped.size != var.size: if popped.size != var.size:
raise SizeMismatch( raise StackError(
f"Size mismatch when popping '{popped.name}' from stack to assign to {var.name}. " f"Size mismatch when popping '{popped.name}' from stack to assign to {var.name}. "
f"Expected {var.size} got {popped.size}" f"Expected {var.size} got {popped.size}"
) )
if popped.name == var.name: if var.name in UNUSED:
if popped.name not in UNUSED and popped.name in self.defined:
raise StackError(f"Value is declared unused, but is already cached by prior operation")
return "" return ""
elif popped.name in UNUSED: if popped.name in UNUSED or popped.name not in self.defined:
self.defined.add(var.name) self.defined.add(var.name)
return ( return (
f"{var.name} = {indirect}stack_pointer[{self.top_offset.to_c()}];\n" f"{var.name} = {indirect}stack_pointer[{self.top_offset.to_c()}];\n"
) )
elif var.name in UNUSED:
return ""
else: else:
self.defined.add(var.name) self.defined.add(var.name)
return f"{var.name} = {popped.name};\n" if popped.name == var.name:
self.base_offset.pop(var)
if var.name in UNUSED:
return "" return ""
else: else:
return f"{var.name} = {popped.name};\n"
self.base_offset.pop(var)
if var.name in UNUSED or not var.used:
return ""
self.defined.add(var.name) self.defined.add(var.name)
cast = f"({var.type})" if (not indirect and var.type) else "" cast = f"({var.type})" if (not indirect and var.type) else ""
bits = ".bits" if cast and not extract_bits else "" bits = ".bits" if cast and not extract_bits else ""
@ -178,6 +180,8 @@ class Stack:
return f"{var.name} = &stack_pointer[{c_offset}];\n" return f"{var.name} = &stack_pointer[{c_offset}];\n"
else: else:
self.top_offset.push(var) self.top_offset.push(var)
if var.used:
self.defined.add(var.name)
return "" return ""
def flush(self, out: CWriter, cast_type: str = "uintptr_t", extract_bits: bool = False) -> None: def flush(self, out: CWriter, cast_type: str = "uintptr_t", extract_bits: bool = False) -> None:

View File

@ -12,6 +12,7 @@ from analyzer import (
Part, Part,
analyze_files, analyze_files,
Skip, Skip,
Flush,
analysis_error, analysis_error,
StackItem, StackItem,
) )
@ -24,7 +25,7 @@ from generators_common import (
) )
from cwriter import CWriter from cwriter import CWriter
from typing import TextIO from typing import TextIO
from stack import Stack, SizeMismatch from stack import Stack, StackError
DEFAULT_OUTPUT = ROOT / "Python/generated_cases.c.h" DEFAULT_OUTPUT = ROOT / "Python/generated_cases.c.h"
@ -32,30 +33,39 @@ DEFAULT_OUTPUT = ROOT / "Python/generated_cases.c.h"
FOOTER = "#undef TIER_ONE\n" FOOTER = "#undef TIER_ONE\n"
def declare_variable(var: StackItem, out: CWriter) -> None:
type, null = type_and_null(var)
space = " " if type[-1].isalnum() else ""
if var.condition:
out.emit(f"{type}{space}{var.name} = {null};\n")
else:
out.emit(f"{type}{space}{var.name};\n")
def declare_variables(inst: Instruction, out: CWriter) -> None: def declare_variables(inst: Instruction, out: CWriter) -> None:
variables = {"unused"} stack = Stack()
for uop in inst.parts: for part in inst.parts:
if isinstance(uop, Uop): if not isinstance(part, Uop):
for var in reversed(uop.stack.inputs): continue
if var.name not in variables: try:
variables.add(var.name) for var in reversed(part.stack.inputs):
type, null = type_and_null(var) stack.pop(var)
space = " " if type[-1].isalnum() else "" for var in part.stack.outputs:
if var.condition: stack.push(var)
out.emit(f"{type}{space}{var.name} = {null};\n") except StackError as ex:
else: raise analysis_error(ex.args[0], part.body[0]) from None
out.emit(f"{type}{space}{var.name};\n") required = set(stack.defined)
for var in uop.stack.outputs: for part in inst.parts:
if var.name not in variables: if not isinstance(part, Uop):
variables.add(var.name) continue
type, null = type_and_null(var) for var in part.stack.inputs:
space = " " if type[-1].isalnum() else "" if var.name in required:
if var.condition: required.remove(var.name)
out.emit(f"{type}{space}{var.name} = {null};\n") declare_variable(var, out)
else: for var in part.stack.outputs:
out.emit(f"{type}{space}{var.name};\n") if var.name in required:
required.remove(var.name)
declare_variable(var, out)
def write_uop( def write_uop(
uop: Part, out: CWriter, offset: int, stack: Stack, inst: Instruction, braces: bool uop: Part, out: CWriter, offset: int, stack: Stack, inst: Instruction, braces: bool
@ -65,6 +75,10 @@ def write_uop(
entries = "entries" if uop.size > 1 else "entry" entries = "entries" if uop.size > 1 else "entry"
out.emit(f"/* Skip {uop.size} cache {entries} */\n") out.emit(f"/* Skip {uop.size} cache {entries} */\n")
return offset + uop.size return offset + uop.size
if isinstance(uop, Flush):
out.emit(f"// flush\n")
stack.flush(out)
return offset
try: try:
out.start_line() out.start_line()
if braces: if braces:
@ -99,15 +113,15 @@ def write_uop(
out.emit("}\n") out.emit("}\n")
# out.emit(stack.as_comment() + "\n") # out.emit(stack.as_comment() + "\n")
return offset return offset
except SizeMismatch as ex: except StackError as ex:
raise analysis_error(ex.args[0], uop.body[0]) raise analysis_error(ex.args[0], uop.body[0]) from None
def uses_this(inst: Instruction) -> bool: def uses_this(inst: Instruction) -> bool:
if inst.properties.needs_this: if inst.properties.needs_this:
return True return True
for uop in inst.parts: for uop in inst.parts:
if isinstance(uop, Skip): if not isinstance(uop, Uop):
continue continue
for cache in uop.caches: for cache in uop.caches:
if cache.name != "unused": if cache.name != "unused":

View File

@ -25,17 +25,17 @@ from generators_common import (
from cwriter import CWriter from cwriter import CWriter
from typing import TextIO, Iterator from typing import TextIO, Iterator
from lexer import Token from lexer import Token
from stack import Stack, SizeMismatch from stack import Stack, StackError
DEFAULT_OUTPUT = ROOT / "Python/executor_cases.c.h" DEFAULT_OUTPUT = ROOT / "Python/executor_cases.c.h"
def declare_variable( def declare_variable(
var: StackItem, uop: Uop, variables: set[str], out: CWriter var: StackItem, uop: Uop, required: set[str], out: CWriter
) -> None: ) -> None:
if var.name in variables: if var.name not in required:
return return
variables.add(var.name) required.remove(var.name)
type, null = type_and_null(var) type, null = type_and_null(var)
space = " " if type[-1].isalnum() else "" space = " " if type[-1].isalnum() else ""
if var.condition: if var.condition:
@ -49,12 +49,16 @@ def declare_variable(
def declare_variables(uop: Uop, out: CWriter) -> None: def declare_variables(uop: Uop, out: CWriter) -> None:
variables = {"unused"} stack = Stack()
for var in reversed(uop.stack.inputs): for var in reversed(uop.stack.inputs):
declare_variable(var, uop, variables, out) stack.pop(var)
for var in uop.stack.outputs: for var in uop.stack.outputs:
declare_variable(var, uop, variables, out) stack.push(var)
required = set(stack.defined)
for var in reversed(uop.stack.inputs):
declare_variable(var, uop, required, out)
for var in uop.stack.outputs:
declare_variable(var, uop, required, out)
def tier2_replace_error( def tier2_replace_error(
out: CWriter, out: CWriter,
@ -177,8 +181,8 @@ def write_uop(uop: Uop, out: CWriter, stack: Stack) -> None:
if uop.properties.stores_sp: if uop.properties.stores_sp:
for i, var in enumerate(uop.stack.outputs): for i, var in enumerate(uop.stack.outputs):
out.emit(stack.push(var)) out.emit(stack.push(var))
except SizeMismatch as ex: except StackError as ex:
raise analysis_error(ex.args[0], uop.body[0]) raise analysis_error(ex.args[0], uop.body[0]) from None
SKIPS = ("_EXTENDED_ARG",) SKIPS = ("_EXTENDED_ARG",)