mirror of
https://github.com/python/cpython.git
synced 2025-10-13 18:33:34 +00:00
GH-131498: Remove conditional stack effects (GH-131499)
* Adds some missing #includes
This commit is contained in:
parent
443c0cd17c
commit
7ebd71ee14
23 changed files with 129 additions and 272 deletions
|
@ -5,6 +5,10 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "pycore_interp.h"
|
||||||
|
#include "pycore_optimizer.h"
|
||||||
|
#include "pycore_stackref.h"
|
||||||
|
|
||||||
#ifndef Py_BUILD_CORE
|
#ifndef Py_BUILD_CORE
|
||||||
# error "this header requires Py_BUILD_CORE define"
|
# error "this header requires Py_BUILD_CORE define"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -59,14 +59,14 @@ class TestEffects(unittest.TestCase):
|
||||||
def test_effect_sizes(self):
|
def test_effect_sizes(self):
|
||||||
stack = Stack()
|
stack = Stack()
|
||||||
inputs = [
|
inputs = [
|
||||||
x := StackItem("x", None, "", "1"),
|
x := StackItem("x", None, "1"),
|
||||||
y := StackItem("y", None, "", "oparg"),
|
y := StackItem("y", None, "oparg"),
|
||||||
z := StackItem("z", None, "", "oparg*2"),
|
z := StackItem("z", None, "oparg*2"),
|
||||||
]
|
]
|
||||||
outputs = [
|
outputs = [
|
||||||
StackItem("x", None, "", "1"),
|
StackItem("x", None, "1"),
|
||||||
StackItem("b", None, "", "oparg*4"),
|
StackItem("b", None, "oparg*4"),
|
||||||
StackItem("c", None, "", "1"),
|
StackItem("c", None, "1"),
|
||||||
]
|
]
|
||||||
stack.pop(z)
|
stack.pop(z)
|
||||||
stack.pop(y)
|
stack.pop(y)
|
||||||
|
@ -903,98 +903,6 @@ class TestGeneratedCases(unittest.TestCase):
|
||||||
"""
|
"""
|
||||||
self.run_cases_test(input, output)
|
self.run_cases_test(input, output)
|
||||||
|
|
||||||
def test_cond_effect(self):
|
|
||||||
input = """
|
|
||||||
inst(OP, (aa, input if ((oparg & 1) == 1), cc -- xx, output if (oparg & 2), zz)) {
|
|
||||||
output = SPAM(oparg, aa, cc, input);
|
|
||||||
INPUTS_DEAD();
|
|
||||||
xx = 0;
|
|
||||||
zz = 0;
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
output = """
|
|
||||||
TARGET(OP) {
|
|
||||||
#if Py_TAIL_CALL_INTERP
|
|
||||||
int opcode = OP;
|
|
||||||
(void)(opcode);
|
|
||||||
#endif
|
|
||||||
frame->instr_ptr = next_instr;
|
|
||||||
next_instr += 1;
|
|
||||||
INSTRUCTION_STATS(OP);
|
|
||||||
_PyStackRef aa;
|
|
||||||
_PyStackRef input = PyStackRef_NULL;
|
|
||||||
_PyStackRef cc;
|
|
||||||
_PyStackRef xx;
|
|
||||||
_PyStackRef output = PyStackRef_NULL;
|
|
||||||
_PyStackRef zz;
|
|
||||||
cc = stack_pointer[-1];
|
|
||||||
if ((oparg & 1) == 1) { input = stack_pointer[-1 - (((oparg & 1) == 1) ? 1 : 0)]; }
|
|
||||||
aa = stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)];
|
|
||||||
output = SPAM(oparg, aa, cc, input);
|
|
||||||
xx = 0;
|
|
||||||
zz = 0;
|
|
||||||
stack_pointer[-2 - (((oparg & 1) == 1) ? 1 : 0)] = xx;
|
|
||||||
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 += -(((oparg & 1) == 1) ? 1 : 0) + ((oparg & 2) ? 1 : 0);
|
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
self.run_cases_test(input, output)
|
|
||||||
|
|
||||||
def test_macro_cond_effect(self):
|
|
||||||
input = """
|
|
||||||
op(A, (left, middle, right --)) {
|
|
||||||
USE(left, middle, right);
|
|
||||||
INPUTS_DEAD();
|
|
||||||
}
|
|
||||||
op(B, (-- deep, extra if (oparg), res)) {
|
|
||||||
deep = -1;
|
|
||||||
res = 0;
|
|
||||||
extra = 1;
|
|
||||||
INPUTS_DEAD();
|
|
||||||
}
|
|
||||||
macro(M) = A + B;
|
|
||||||
"""
|
|
||||||
output = """
|
|
||||||
TARGET(M) {
|
|
||||||
#if Py_TAIL_CALL_INTERP
|
|
||||||
int opcode = M;
|
|
||||||
(void)(opcode);
|
|
||||||
#endif
|
|
||||||
frame->instr_ptr = next_instr;
|
|
||||||
next_instr += 1;
|
|
||||||
INSTRUCTION_STATS(M);
|
|
||||||
_PyStackRef left;
|
|
||||||
_PyStackRef middle;
|
|
||||||
_PyStackRef right;
|
|
||||||
_PyStackRef deep;
|
|
||||||
_PyStackRef extra = PyStackRef_NULL;
|
|
||||||
_PyStackRef res;
|
|
||||||
// A
|
|
||||||
{
|
|
||||||
right = stack_pointer[-1];
|
|
||||||
middle = stack_pointer[-2];
|
|
||||||
left = stack_pointer[-3];
|
|
||||||
USE(left, middle, right);
|
|
||||||
}
|
|
||||||
// B
|
|
||||||
{
|
|
||||||
deep = -1;
|
|
||||||
res = 0;
|
|
||||||
extra = 1;
|
|
||||||
}
|
|
||||||
stack_pointer[-3] = deep;
|
|
||||||
if (oparg) stack_pointer[-2] = extra;
|
|
||||||
stack_pointer[-2 + ((oparg) ? 1 : 0)] = res;
|
|
||||||
stack_pointer += -1 + ((oparg) ? 1 : 0);
|
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
|
||||||
DISPATCH();
|
|
||||||
}
|
|
||||||
"""
|
|
||||||
self.run_cases_test(input, output)
|
|
||||||
|
|
||||||
def test_macro_push_push(self):
|
def test_macro_push_push(self):
|
||||||
input = """
|
input = """
|
||||||
op(A, (-- val1)) {
|
op(A, (-- val1)) {
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
|
#include "pycore_instruction_sequence.h" // _PyInstructionSequence_New()
|
||||||
#include "pycore_interpframe.h" // _PyFrame_GetFunction()
|
#include "pycore_interpframe.h" // _PyFrame_GetFunction()
|
||||||
#include "pycore_object.h" // _PyObject_IsFreed()
|
#include "pycore_object.h" // _PyObject_IsFreed()
|
||||||
|
#include "pycore_optimizer.h" // _Py_Executor_DependsOn
|
||||||
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
|
#include "pycore_pathconfig.h" // _PyPathConfig_ClearGlobal()
|
||||||
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
|
#include "pycore_pyerrors.h" // _PyErr_ChainExceptions1()
|
||||||
#include "pycore_pylifecycle.h" // _PyInterpreterConfig_InitFromDict()
|
#include "pycore_pylifecycle.h" // _PyInterpreterConfig_InitFromDict()
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "pycore_interpframe.h" // FRAME_SPECIALS_SIZE
|
#include "pycore_interpframe.h" // FRAME_SPECIALS_SIZE
|
||||||
#include "pycore_opcode_metadata.h" // _PyOpcode_Caches
|
#include "pycore_opcode_metadata.h" // _PyOpcode_Caches
|
||||||
#include "pycore_opcode_utils.h" // RESUME_AT_FUNC_START
|
#include "pycore_opcode_utils.h" // RESUME_AT_FUNC_START
|
||||||
|
#include "pycore_optimizer.h" // _Py_ExecutorDetach
|
||||||
#include "pycore_pymem.h" // _PyMem_FreeDelayed()
|
#include "pycore_pymem.h" // _PyMem_FreeDelayed()
|
||||||
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
||||||
#include "pycore_setobject.h" // _PySet_NextEntry()
|
#include "pycore_setobject.h" // _PySet_NextEntry()
|
||||||
|
|
|
@ -59,7 +59,6 @@
|
||||||
#define guard
|
#define guard
|
||||||
#define override
|
#define override
|
||||||
#define specializing
|
#define specializing
|
||||||
#define split
|
|
||||||
#define replicate(TIMES)
|
#define replicate(TIMES)
|
||||||
#define tier1
|
#define tier1
|
||||||
#define no_save_ip
|
#define no_save_ip
|
||||||
|
@ -1686,8 +1685,10 @@ dummy_func(
|
||||||
ERROR_IF(PyStackRef_IsNull(*res), error);
|
ERROR_IF(PyStackRef_IsNull(*res), error);
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_PUSH_NULL_CONDITIONAL, ( -- null if (oparg & 1))) {
|
op(_PUSH_NULL_CONDITIONAL, ( -- null[oparg & 1])) {
|
||||||
null = PyStackRef_NULL;
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro(LOAD_GLOBAL) =
|
macro(LOAD_GLOBAL) =
|
||||||
|
|
8
Python/executor_cases.c.h
generated
8
Python/executor_cases.c.h
generated
|
@ -2285,10 +2285,12 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _PUSH_NULL_CONDITIONAL: {
|
case _PUSH_NULL_CONDITIONAL: {
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
oparg = CURRENT_OPARG();
|
oparg = CURRENT_OPARG();
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[0];
|
||||||
if (oparg & 1) stack_pointer[0] = null;
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
stack_pointer += (oparg & 1);
|
stack_pointer += (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
|
|
88
Python/generated_cases.c.h
generated
88
Python/generated_cases.c.h
generated
|
@ -6982,7 +6982,7 @@
|
||||||
_PyStackRef class_st;
|
_PyStackRef class_st;
|
||||||
_PyStackRef self_st;
|
_PyStackRef self_st;
|
||||||
_PyStackRef attr;
|
_PyStackRef attr;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _LOAD_SUPER_ATTR
|
// _LOAD_SUPER_ATTR
|
||||||
{
|
{
|
||||||
|
@ -7078,10 +7078,12 @@
|
||||||
}
|
}
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[1];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stack_pointer[0] = attr;
|
stack_pointer[0] = attr;
|
||||||
if (oparg & 1) stack_pointer[1] = null;
|
|
||||||
stack_pointer += 1 + (oparg & 1);
|
stack_pointer += 1 + (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -7840,7 +7842,7 @@
|
||||||
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
||||||
_PyStackRef owner;
|
_PyStackRef owner;
|
||||||
_PyStackRef attr;
|
_PyStackRef attr;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _CHECK_ATTR_CLASS
|
// _CHECK_ATTR_CLASS
|
||||||
{
|
{
|
||||||
|
@ -7876,9 +7878,11 @@
|
||||||
}
|
}
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[0];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (oparg & 1) stack_pointer[0] = null;
|
|
||||||
stack_pointer += (oparg & 1);
|
stack_pointer += (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -7897,7 +7901,7 @@
|
||||||
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
||||||
_PyStackRef owner;
|
_PyStackRef owner;
|
||||||
_PyStackRef attr;
|
_PyStackRef attr;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _CHECK_ATTR_CLASS
|
// _CHECK_ATTR_CLASS
|
||||||
{
|
{
|
||||||
|
@ -7943,9 +7947,11 @@
|
||||||
}
|
}
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[0];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (oparg & 1) stack_pointer[0] = null;
|
|
||||||
stack_pointer += (oparg & 1);
|
stack_pointer += (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -8022,7 +8028,7 @@
|
||||||
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
||||||
_PyStackRef owner;
|
_PyStackRef owner;
|
||||||
_PyStackRef attr;
|
_PyStackRef attr;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _GUARD_TYPE_VERSION
|
// _GUARD_TYPE_VERSION
|
||||||
{
|
{
|
||||||
|
@ -8078,9 +8084,11 @@
|
||||||
/* Skip 5 cache entries */
|
/* Skip 5 cache entries */
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[0];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (oparg & 1) stack_pointer[0] = null;
|
|
||||||
stack_pointer += (oparg & 1);
|
stack_pointer += (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -8270,7 +8278,7 @@
|
||||||
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
||||||
_PyStackRef owner;
|
_PyStackRef owner;
|
||||||
_PyStackRef attr;
|
_PyStackRef attr;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _LOAD_ATTR_MODULE
|
// _LOAD_ATTR_MODULE
|
||||||
{
|
{
|
||||||
|
@ -8321,9 +8329,11 @@
|
||||||
/* Skip 5 cache entries */
|
/* Skip 5 cache entries */
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[0];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (oparg & 1) stack_pointer[0] = null;
|
|
||||||
stack_pointer += (oparg & 1);
|
stack_pointer += (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -8552,7 +8562,7 @@
|
||||||
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
||||||
_PyStackRef owner;
|
_PyStackRef owner;
|
||||||
_PyStackRef attr;
|
_PyStackRef attr;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _GUARD_TYPE_VERSION
|
// _GUARD_TYPE_VERSION
|
||||||
{
|
{
|
||||||
|
@ -8599,9 +8609,11 @@
|
||||||
/* Skip 5 cache entries */
|
/* Skip 5 cache entries */
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[0];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (oparg & 1) stack_pointer[0] = null;
|
|
||||||
stack_pointer += (oparg & 1);
|
stack_pointer += (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -8620,7 +8632,7 @@
|
||||||
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_LOAD_ATTR == 9, "incorrect cache size");
|
||||||
_PyStackRef owner;
|
_PyStackRef owner;
|
||||||
_PyStackRef attr;
|
_PyStackRef attr;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _GUARD_TYPE_VERSION
|
// _GUARD_TYPE_VERSION
|
||||||
{
|
{
|
||||||
|
@ -8700,9 +8712,11 @@
|
||||||
/* Skip 5 cache entries */
|
/* Skip 5 cache entries */
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[0];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (oparg & 1) stack_pointer[0] = null;
|
|
||||||
stack_pointer += (oparg & 1);
|
stack_pointer += (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -9080,7 +9094,7 @@
|
||||||
_Py_CODEUNIT* const this_instr = next_instr - 5;
|
_Py_CODEUNIT* const this_instr = next_instr - 5;
|
||||||
(void)this_instr;
|
(void)this_instr;
|
||||||
_PyStackRef *res;
|
_PyStackRef *res;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
// _SPECIALIZE_LOAD_GLOBAL
|
// _SPECIALIZE_LOAD_GLOBAL
|
||||||
{
|
{
|
||||||
uint16_t counter = read_u16(&this_instr[1].cache);
|
uint16_t counter = read_u16(&this_instr[1].cache);
|
||||||
|
@ -9114,9 +9128,11 @@
|
||||||
}
|
}
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[1];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (oparg & 1) stack_pointer[1] = null;
|
|
||||||
stack_pointer += 1 + (oparg & 1);
|
stack_pointer += 1 + (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -9134,7 +9150,7 @@
|
||||||
INSTRUCTION_STATS(LOAD_GLOBAL_BUILTIN);
|
INSTRUCTION_STATS(LOAD_GLOBAL_BUILTIN);
|
||||||
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size");
|
||||||
_PyStackRef res;
|
_PyStackRef res;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _GUARD_GLOBALS_VERSION
|
// _GUARD_GLOBALS_VERSION
|
||||||
{
|
{
|
||||||
|
@ -9191,10 +9207,12 @@
|
||||||
}
|
}
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[1];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stack_pointer[0] = res;
|
stack_pointer[0] = res;
|
||||||
if (oparg & 1) stack_pointer[1] = null;
|
|
||||||
stack_pointer += 1 + (oparg & 1);
|
stack_pointer += 1 + (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -9212,7 +9230,7 @@
|
||||||
INSTRUCTION_STATS(LOAD_GLOBAL_MODULE);
|
INSTRUCTION_STATS(LOAD_GLOBAL_MODULE);
|
||||||
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size");
|
static_assert(INLINE_CACHE_ENTRIES_LOAD_GLOBAL == 4, "incorrect cache size");
|
||||||
_PyStackRef res;
|
_PyStackRef res;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
/* Skip 1 cache entry */
|
/* Skip 1 cache entry */
|
||||||
// _NOP
|
// _NOP
|
||||||
{
|
{
|
||||||
|
@ -9256,10 +9274,12 @@
|
||||||
}
|
}
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[1];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stack_pointer[0] = res;
|
stack_pointer[0] = res;
|
||||||
if (oparg & 1) stack_pointer[1] = null;
|
|
||||||
stack_pointer += 1 + (oparg & 1);
|
stack_pointer += 1 + (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
@ -9387,7 +9407,7 @@
|
||||||
_PyStackRef class_st;
|
_PyStackRef class_st;
|
||||||
_PyStackRef self_st;
|
_PyStackRef self_st;
|
||||||
_PyStackRef attr;
|
_PyStackRef attr;
|
||||||
_PyStackRef null = PyStackRef_NULL;
|
_PyStackRef *null;
|
||||||
// _SPECIALIZE_LOAD_SUPER_ATTR
|
// _SPECIALIZE_LOAD_SUPER_ATTR
|
||||||
{
|
{
|
||||||
class_st = stack_pointer[-2];
|
class_st = stack_pointer[-2];
|
||||||
|
@ -9499,10 +9519,12 @@
|
||||||
}
|
}
|
||||||
// _PUSH_NULL_CONDITIONAL
|
// _PUSH_NULL_CONDITIONAL
|
||||||
{
|
{
|
||||||
null = PyStackRef_NULL;
|
null = &stack_pointer[1];
|
||||||
|
if (oparg & 1) {
|
||||||
|
null[0] = PyStackRef_NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stack_pointer[0] = attr;
|
stack_pointer[0] = attr;
|
||||||
if (oparg & 1) stack_pointer[1] = null;
|
|
||||||
stack_pointer += 1 + (oparg & 1);
|
stack_pointer += 1 + (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
|
|
|
@ -8,7 +8,11 @@
|
||||||
#include "pycore_ceval.h"
|
#include "pycore_ceval.h"
|
||||||
#include "pycore_critical_section.h"
|
#include "pycore_critical_section.h"
|
||||||
#include "pycore_dict.h"
|
#include "pycore_dict.h"
|
||||||
|
#include "pycore_floatobject.h"
|
||||||
|
#include "pycore_frame.h"
|
||||||
|
#include "pycore_interpframe.h"
|
||||||
#include "pycore_intrinsics.h"
|
#include "pycore_intrinsics.h"
|
||||||
|
#include "pycore_list.h"
|
||||||
#include "pycore_long.h"
|
#include "pycore_long.h"
|
||||||
#include "pycore_opcode_metadata.h"
|
#include "pycore_opcode_metadata.h"
|
||||||
#include "pycore_opcode_utils.h"
|
#include "pycore_opcode_utils.h"
|
||||||
|
@ -16,6 +20,9 @@
|
||||||
#include "pycore_pyerrors.h"
|
#include "pycore_pyerrors.h"
|
||||||
#include "pycore_setobject.h"
|
#include "pycore_setobject.h"
|
||||||
#include "pycore_sliceobject.h"
|
#include "pycore_sliceobject.h"
|
||||||
|
#include "pycore_tuple.h"
|
||||||
|
#include "pycore_unicodeobject.h"
|
||||||
|
|
||||||
#include "pycore_jit.h"
|
#include "pycore_jit.h"
|
||||||
|
|
||||||
// Memory management stuff: ////////////////////////////////////////////////////
|
// Memory management stuff: ////////////////////////////////////////////////////
|
||||||
|
|
|
@ -6,11 +6,15 @@
|
||||||
#include "pycore_interp.h"
|
#include "pycore_interp.h"
|
||||||
#include "pycore_backoff.h"
|
#include "pycore_backoff.h"
|
||||||
#include "pycore_bitutils.h" // _Py_popcount32()
|
#include "pycore_bitutils.h" // _Py_popcount32()
|
||||||
|
#include "pycore_code.h" // _Py_GetBaseCodeUnit
|
||||||
|
#include "pycore_interpframe.h"
|
||||||
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
|
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
|
||||||
#include "pycore_opcode_metadata.h" // _PyOpcode_OpName[]
|
#include "pycore_opcode_metadata.h" // _PyOpcode_OpName[]
|
||||||
#include "pycore_opcode_utils.h" // MAX_REAL_OPCODE
|
#include "pycore_opcode_utils.h" // MAX_REAL_OPCODE
|
||||||
#include "pycore_optimizer.h" // _Py_uop_analyze_and_optimize()
|
#include "pycore_optimizer.h" // _Py_uop_analyze_and_optimize()
|
||||||
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
#include "pycore_pystate.h" // _PyInterpreterState_GET()
|
||||||
|
#include "pycore_tuple.h" // _PyTuple_FromArraySteal
|
||||||
|
#include "pycore_unicodeobject.h" // _PyUnicode_FromASCII
|
||||||
#include "pycore_uop_ids.h"
|
#include "pycore_uop_ids.h"
|
||||||
#include "pycore_jit.h"
|
#include "pycore_jit.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -1226,11 +1230,7 @@ uop_optimize(
|
||||||
for (int pc = 0; pc < length; pc++) {
|
for (int pc = 0; pc < length; pc++) {
|
||||||
int opcode = buffer[pc].opcode;
|
int opcode = buffer[pc].opcode;
|
||||||
int oparg = buffer[pc].oparg;
|
int oparg = buffer[pc].oparg;
|
||||||
if (_PyUop_Flags[opcode] & HAS_OPARG_AND_1_FLAG) {
|
if (oparg < _PyUop_Replication[opcode]) {
|
||||||
buffer[pc].opcode = opcode + 1 + (oparg & 1);
|
|
||||||
assert(strncmp(_PyOpcode_uop_name[buffer[pc].opcode], _PyOpcode_uop_name[opcode], strlen(_PyOpcode_uop_name[opcode])) == 0);
|
|
||||||
}
|
|
||||||
else if (oparg < _PyUop_Replication[opcode]) {
|
|
||||||
buffer[pc].opcode = opcode + oparg + 1;
|
buffer[pc].opcode = opcode + oparg + 1;
|
||||||
assert(strncmp(_PyOpcode_uop_name[buffer[pc].opcode], _PyOpcode_uop_name[opcode], strlen(_PyOpcode_uop_name[opcode])) == 0);
|
assert(strncmp(_PyOpcode_uop_name[buffer[pc].opcode], _PyOpcode_uop_name[opcode], strlen(_PyOpcode_uop_name[opcode])) == 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "pycore_uop_metadata.h"
|
#include "pycore_uop_metadata.h"
|
||||||
#include "pycore_dict.h"
|
#include "pycore_dict.h"
|
||||||
#include "pycore_long.h"
|
#include "pycore_long.h"
|
||||||
|
#include "pycore_interpframe.h" // _PyFrame_GetCode
|
||||||
#include "pycore_optimizer.h"
|
#include "pycore_optimizer.h"
|
||||||
#include "pycore_object.h"
|
#include "pycore_object.h"
|
||||||
#include "pycore_dict.h"
|
#include "pycore_dict.h"
|
||||||
|
|
|
@ -546,10 +546,14 @@ dummy_func(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
op (_PUSH_NULL_CONDITIONAL, ( -- null if (oparg & 1))) {
|
op (_PUSH_NULL_CONDITIONAL, ( -- null[oparg & 1])) {
|
||||||
int opcode = (oparg & 1) ? _PUSH_NULL : _NOP;
|
if (oparg & 1) {
|
||||||
REPLACE_OP(this_instr, opcode, 0, 0);
|
REPLACE_OP(this_instr, _PUSH_NULL, 0, 0);
|
||||||
null = sym_new_null(ctx);
|
null[0] = sym_new_null(ctx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
REPLACE_OP(this_instr, _NOP, 0, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_LOAD_ATTR, (owner -- attr, self_or_null[oparg&1])) {
|
op(_LOAD_ATTR, (owner -- attr, self_or_null[oparg&1])) {
|
||||||
|
@ -765,7 +769,7 @@ dummy_func(void) {
|
||||||
Py_UNREACHABLE();
|
Py_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- unused if (0))) {
|
op(_PUSH_FRAME, (new_frame: _Py_UOpsAbstractFrame * -- )) {
|
||||||
SYNC_SP();
|
SYNC_SP();
|
||||||
ctx->frame->stack_pointer = stack_pointer;
|
ctx->frame->stack_pointer = stack_pointer;
|
||||||
ctx->frame = new_frame;
|
ctx->frame = new_frame;
|
||||||
|
|
14
Python/optimizer_cases.c.h
generated
14
Python/optimizer_cases.c.h
generated
|
@ -921,11 +921,15 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
case _PUSH_NULL_CONDITIONAL: {
|
case _PUSH_NULL_CONDITIONAL: {
|
||||||
JitOptSymbol *null = NULL;
|
JitOptSymbol **null;
|
||||||
int opcode = (oparg & 1) ? _PUSH_NULL : _NOP;
|
null = &stack_pointer[0];
|
||||||
REPLACE_OP(this_instr, opcode, 0, 0);
|
if (oparg & 1) {
|
||||||
null = sym_new_null(ctx);
|
REPLACE_OP(this_instr, _PUSH_NULL, 0, 0);
|
||||||
if (oparg & 1) stack_pointer[0] = null;
|
null[0] = sym_new_null(ctx);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
REPLACE_OP(this_instr, _NOP, 0, 0);
|
||||||
|
}
|
||||||
stack_pointer += (oparg & 1);
|
stack_pointer += (oparg & 1);
|
||||||
assert(WITHIN_STACK_BOUNDS());
|
assert(WITHIN_STACK_BOUNDS());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include "pycore_frame.h"
|
#include "pycore_frame.h"
|
||||||
#include "pycore_long.h"
|
#include "pycore_long.h"
|
||||||
#include "pycore_optimizer.h"
|
#include "pycore_optimizer.h"
|
||||||
|
#include "pycore_stats.h"
|
||||||
#include "pycore_tuple.h" // _PyTuple_FromArray()
|
#include "pycore_tuple.h" // _PyTuple_FromArray()
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "pycore_long.h" // _PyLong_InitTypes()
|
#include "pycore_long.h" // _PyLong_InitTypes()
|
||||||
#include "pycore_object.h" // _PyDebug_PrintTotalRefs()
|
#include "pycore_object.h" // _PyDebug_PrintTotalRefs()
|
||||||
#include "pycore_obmalloc.h" // _PyMem_init_obmalloc()
|
#include "pycore_obmalloc.h" // _PyMem_init_obmalloc()
|
||||||
|
#include "pycore_optimizer.h" // _Py_Executors_InvalidateAll
|
||||||
#include "pycore_pathconfig.h" // _PyPathConfig_UpdateGlobal()
|
#include "pycore_pathconfig.h" // _PyPathConfig_UpdateGlobal()
|
||||||
#include "pycore_pyerrors.h" // _PyErr_Occurred()
|
#include "pycore_pyerrors.h" // _PyErr_Occurred()
|
||||||
#include "pycore_pylifecycle.h" // _PyErr_Print()
|
#include "pycore_pylifecycle.h" // _PyErr_Print()
|
||||||
|
|
|
@ -33,7 +33,6 @@ class Properties:
|
||||||
pure: bool
|
pure: bool
|
||||||
uses_opcode: bool
|
uses_opcode: bool
|
||||||
tier: int | None = None
|
tier: int | None = None
|
||||||
oparg_and_1: bool = False
|
|
||||||
const_oparg: int = -1
|
const_oparg: int = -1
|
||||||
needs_prev: bool = False
|
needs_prev: bool = False
|
||||||
no_save_ip: bool = False
|
no_save_ip: bool = False
|
||||||
|
@ -136,16 +135,14 @@ class Flush:
|
||||||
class StackItem:
|
class StackItem:
|
||||||
name: str
|
name: str
|
||||||
type: str | None
|
type: str | None
|
||||||
condition: str | None
|
|
||||||
size: str
|
size: str
|
||||||
peek: bool = False
|
peek: bool = False
|
||||||
used: bool = False
|
used: bool = False
|
||||||
|
|
||||||
def __str__(self) -> str:
|
def __str__(self) -> str:
|
||||||
cond = f" if ({self.condition})" if self.condition else ""
|
|
||||||
size = f"[{self.size}]" if self.size else ""
|
size = f"[{self.size}]" if self.size else ""
|
||||||
type = "" if self.type is None else f"{self.type} "
|
type = "" if self.type is None else f"{self.type} "
|
||||||
return f"{type}{self.name}{size}{cond} {self.peek}"
|
return f"{type}{self.name}{size} {self.peek}"
|
||||||
|
|
||||||
def is_array(self) -> bool:
|
def is_array(self) -> bool:
|
||||||
return self.size != ""
|
return self.size != ""
|
||||||
|
@ -348,10 +345,7 @@ def override_error(
|
||||||
def convert_stack_item(
|
def convert_stack_item(
|
||||||
item: parser.StackEffect, replace_op_arg_1: str | None
|
item: parser.StackEffect, replace_op_arg_1: str | None
|
||||||
) -> StackItem:
|
) -> StackItem:
|
||||||
cond = item.cond
|
return StackItem(item.name, item.type, item.size)
|
||||||
if replace_op_arg_1 and OPARG_AND_1.match(item.cond):
|
|
||||||
cond = replace_op_arg_1
|
|
||||||
return StackItem(item.name, item.type, cond, item.size)
|
|
||||||
|
|
||||||
def check_unused(stack: list[StackItem], input_names: dict[str, lexer.Token]) -> None:
|
def check_unused(stack: list[StackItem], input_names: dict[str, lexer.Token]) -> None:
|
||||||
"Unused items cannot be on the stack above used, non-peek items"
|
"Unused items cannot be on the stack above used, non-peek items"
|
||||||
|
@ -815,33 +809,12 @@ def stack_effect_only_peeks(instr: parser.InstDef) -> bool:
|
||||||
return False
|
return False
|
||||||
if len(stack_inputs) == 0:
|
if len(stack_inputs) == 0:
|
||||||
return False
|
return False
|
||||||
if any(s.cond for s in stack_inputs) or any(s.cond for s in instr.outputs):
|
|
||||||
return False
|
|
||||||
return all(
|
return all(
|
||||||
(s.name == other.name and s.type == other.type and s.size == other.size)
|
(s.name == other.name and s.type == other.type and s.size == other.size)
|
||||||
for s, other in zip(stack_inputs, instr.outputs)
|
for s, other in zip(stack_inputs, instr.outputs)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
OPARG_AND_1 = re.compile("\\(*oparg *& *1")
|
|
||||||
|
|
||||||
|
|
||||||
def effect_depends_on_oparg_1(op: parser.InstDef) -> bool:
|
|
||||||
for effect in op.inputs:
|
|
||||||
if isinstance(effect, parser.CacheEffect):
|
|
||||||
continue
|
|
||||||
if not effect.cond:
|
|
||||||
continue
|
|
||||||
if OPARG_AND_1.match(effect.cond):
|
|
||||||
return True
|
|
||||||
for effect in op.outputs:
|
|
||||||
if not effect.cond:
|
|
||||||
continue
|
|
||||||
if OPARG_AND_1.match(effect.cond):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def compute_properties(op: parser.CodeDef) -> Properties:
|
def compute_properties(op: parser.CodeDef) -> Properties:
|
||||||
escaping_calls = find_escaping_api_calls(op)
|
escaping_calls = find_escaping_api_calls(op)
|
||||||
has_free = (
|
has_free = (
|
||||||
|
@ -908,29 +881,6 @@ def make_uop(
|
||||||
body=op.block.tokens,
|
body=op.block.tokens,
|
||||||
properties=compute_properties(op),
|
properties=compute_properties(op),
|
||||||
)
|
)
|
||||||
if effect_depends_on_oparg_1(op) and "split" in op.annotations:
|
|
||||||
result.properties.oparg_and_1 = True
|
|
||||||
for bit in ("0", "1"):
|
|
||||||
name_x = name + "_" + bit
|
|
||||||
properties = compute_properties(op)
|
|
||||||
if properties.oparg:
|
|
||||||
# May not need oparg anymore
|
|
||||||
properties.oparg = any(
|
|
||||||
token.text == "oparg" for token in op.block.tokens
|
|
||||||
)
|
|
||||||
rep = Uop(
|
|
||||||
name=name_x,
|
|
||||||
context=op.context,
|
|
||||||
annotations=op.annotations,
|
|
||||||
stack=analyze_stack(op, bit),
|
|
||||||
caches=analyze_caches(inputs),
|
|
||||||
deferred_refs=analyze_deferred_refs(op),
|
|
||||||
output_stores=find_stores_outputs(op),
|
|
||||||
body=op.block.tokens,
|
|
||||||
properties=properties,
|
|
||||||
)
|
|
||||||
rep.replicates = result
|
|
||||||
uops[name_x] = rep
|
|
||||||
for anno in op.annotations:
|
for anno in op.annotations:
|
||||||
if anno.startswith("replicate"):
|
if anno.startswith("replicate"):
|
||||||
result.replicated = int(anno[10:-1])
|
result.replicated = int(anno[10:-1])
|
||||||
|
|
|
@ -648,8 +648,6 @@ def cflags(p: Properties) -> str:
|
||||||
flags.append("HAS_PURE_FLAG")
|
flags.append("HAS_PURE_FLAG")
|
||||||
if p.no_save_ip:
|
if p.no_save_ip:
|
||||||
flags.append("HAS_NO_SAVE_IP_FLAG")
|
flags.append("HAS_NO_SAVE_IP_FLAG")
|
||||||
if p.oparg_and_1:
|
|
||||||
flags.append("HAS_OPARG_AND_1_FLAG")
|
|
||||||
if flags:
|
if flags:
|
||||||
return " | ".join(flags)
|
return " | ".join(flags)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -227,7 +227,6 @@ annotations = {
|
||||||
"register",
|
"register",
|
||||||
"replaced",
|
"replaced",
|
||||||
"pure",
|
"pure",
|
||||||
"split",
|
|
||||||
"replicate",
|
"replicate",
|
||||||
"tier1",
|
"tier1",
|
||||||
"tier2",
|
"tier2",
|
||||||
|
|
|
@ -48,19 +48,13 @@ def declare_variables(uop: Uop, out: CWriter, skip_inputs: bool) -> None:
|
||||||
for var in reversed(uop.stack.inputs):
|
for var in reversed(uop.stack.inputs):
|
||||||
if var.used and var.name not in variables:
|
if var.used and var.name not in variables:
|
||||||
variables.add(var.name)
|
variables.add(var.name)
|
||||||
if var.condition:
|
out.emit(f"{type_name(var)}{var.name};\n")
|
||||||
out.emit(f"{type_name(var)}{var.name} = NULL;\n")
|
|
||||||
else:
|
|
||||||
out.emit(f"{type_name(var)}{var.name};\n")
|
|
||||||
for var in uop.stack.outputs:
|
for var in uop.stack.outputs:
|
||||||
if var.peek:
|
if var.peek:
|
||||||
continue
|
continue
|
||||||
if var.name not in variables:
|
if var.name not in variables:
|
||||||
variables.add(var.name)
|
variables.add(var.name)
|
||||||
if var.condition:
|
out.emit(f"{type_name(var)}{var.name};\n")
|
||||||
out.emit(f"{type_name(var)}{var.name} = NULL;\n")
|
|
||||||
else:
|
|
||||||
out.emit(f"{type_name(var)}{var.name};\n")
|
|
||||||
|
|
||||||
|
|
||||||
def decref_inputs(
|
def decref_inputs(
|
||||||
|
|
|
@ -77,12 +77,11 @@ class Block(Node):
|
||||||
class StackEffect(Node):
|
class StackEffect(Node):
|
||||||
name: str = field(compare=False) # __eq__ only uses type, cond, size
|
name: str = field(compare=False) # __eq__ only uses type, cond, size
|
||||||
type: str = "" # Optional `:type`
|
type: str = "" # Optional `:type`
|
||||||
cond: str = "" # Optional `if (cond)`
|
|
||||||
size: str = "" # Optional `[size]`
|
size: str = "" # Optional `[size]`
|
||||||
# Note: size cannot be combined with type or cond
|
# Note: size cannot be combined with type or cond
|
||||||
|
|
||||||
def __repr__(self) -> str:
|
def __repr__(self) -> str:
|
||||||
items = [self.name, self.type, self.cond, self.size]
|
items = [self.name, self.type, self.size]
|
||||||
while items and items[-1] == "":
|
while items and items[-1] == "":
|
||||||
del items[-1]
|
del items[-1]
|
||||||
return f"StackEffect({', '.join(repr(item) for item in items)})"
|
return f"StackEffect({', '.join(repr(item) for item in items)})"
|
||||||
|
@ -299,22 +298,15 @@ class Parser(PLexer):
|
||||||
type_text = self.require(lx.IDENTIFIER).text.strip()
|
type_text = self.require(lx.IDENTIFIER).text.strip()
|
||||||
if self.expect(lx.TIMES):
|
if self.expect(lx.TIMES):
|
||||||
type_text += " *"
|
type_text += " *"
|
||||||
cond_text = ""
|
|
||||||
if self.expect(lx.IF):
|
|
||||||
self.require(lx.LPAREN)
|
|
||||||
if not (cond := self.expression()):
|
|
||||||
raise self.make_syntax_error("Expected condition")
|
|
||||||
self.require(lx.RPAREN)
|
|
||||||
cond_text = cond.text.strip()
|
|
||||||
size_text = ""
|
size_text = ""
|
||||||
if self.expect(lx.LBRACKET):
|
if self.expect(lx.LBRACKET):
|
||||||
if type_text or cond_text:
|
if type_text:
|
||||||
raise self.make_syntax_error("Unexpected [")
|
raise self.make_syntax_error("Unexpected [")
|
||||||
if not (size := self.expression()):
|
if not (size := self.expression()):
|
||||||
raise self.make_syntax_error("Expected expression")
|
raise self.make_syntax_error("Expected expression")
|
||||||
self.require(lx.RBRACKET)
|
self.require(lx.RBRACKET)
|
||||||
size_text = size.text.strip()
|
size_text = size.text.strip()
|
||||||
return StackEffect(tkn.text, type_text, cond_text, size_text)
|
return StackEffect(tkn.text, type_text, size_text)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@contextual
|
@contextual
|
||||||
|
|
|
@ -23,17 +23,7 @@ def maybe_parenthesize(sym: str) -> str:
|
||||||
|
|
||||||
|
|
||||||
def var_size(var: StackItem) -> str:
|
def var_size(var: StackItem) -> str:
|
||||||
if var.condition:
|
if var.size:
|
||||||
# Special case simplifications
|
|
||||||
if var.condition == "0":
|
|
||||||
return "0"
|
|
||||||
elif var.condition == "1":
|
|
||||||
return var.get_size()
|
|
||||||
elif var.condition == "oparg & 1" and not var.size:
|
|
||||||
return f"({var.condition})"
|
|
||||||
else:
|
|
||||||
return f"(({var.condition}) ? {var.get_size()} : 0)"
|
|
||||||
elif var.size:
|
|
||||||
return var.size
|
return var.size
|
||||||
else:
|
else:
|
||||||
return "1"
|
return "1"
|
||||||
|
@ -89,10 +79,6 @@ class Local:
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
return self.item.name
|
return self.item.name
|
||||||
|
|
||||||
@property
|
|
||||||
def condition(self) -> str | None:
|
|
||||||
return self.item.condition
|
|
||||||
|
|
||||||
def is_array(self) -> bool:
|
def is_array(self) -> bool:
|
||||||
return self.item.is_array()
|
return self.item.is_array()
|
||||||
|
|
||||||
|
@ -275,15 +261,7 @@ class Stack:
|
||||||
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 self.extract_bits else ""
|
bits = ".bits" if cast and self.extract_bits else ""
|
||||||
assign = f"{var.name} = {cast}{indirect}stack_pointer[{self.base_offset.to_c()}]{bits};"
|
assign = f"{var.name} = {cast}{indirect}stack_pointer[{self.base_offset.to_c()}]{bits};"
|
||||||
if var.condition:
|
assign = f"{assign}\n"
|
||||||
if var.condition == "1":
|
|
||||||
assign = f"{assign}\n"
|
|
||||||
elif var.condition == "0":
|
|
||||||
return "", Local.unused(var)
|
|
||||||
else:
|
|
||||||
assign = f"if ({var.condition}) {{ {assign} }}\n"
|
|
||||||
else:
|
|
||||||
assign = f"{assign}\n"
|
|
||||||
return assign, Local.from_memory(var)
|
return assign, Local.from_memory(var)
|
||||||
|
|
||||||
def push(self, var: Local) -> None:
|
def push(self, var: Local) -> None:
|
||||||
|
@ -303,10 +281,6 @@ class Stack:
|
||||||
) -> None:
|
) -> None:
|
||||||
cast = f"({cast_type})" if var.type else ""
|
cast = f"({cast_type})" if var.type else ""
|
||||||
bits = ".bits" if cast and extract_bits else ""
|
bits = ".bits" if cast and extract_bits else ""
|
||||||
if var.condition == "0":
|
|
||||||
return
|
|
||||||
if var.condition and var.condition != "1":
|
|
||||||
out.emit(f"if ({var.condition}) ")
|
|
||||||
out.emit(f"stack_pointer[{base_offset.to_c()}]{bits} = {cast}{var.name};\n")
|
out.emit(f"stack_pointer[{base_offset.to_c()}]{bits} = {cast}{var.name};\n")
|
||||||
|
|
||||||
def _adjust_stack_pointer(self, out: CWriter, number: str) -> None:
|
def _adjust_stack_pointer(self, out: CWriter, number: str) -> None:
|
||||||
|
@ -655,7 +629,7 @@ class Storage:
|
||||||
def close_variable(var: Local, overwrite: str) -> None:
|
def close_variable(var: Local, overwrite: str) -> None:
|
||||||
nonlocal tmp_defined
|
nonlocal tmp_defined
|
||||||
close = "PyStackRef_CLOSE"
|
close = "PyStackRef_CLOSE"
|
||||||
if "null" in var.name or var.condition and var.condition != "1":
|
if "null" in var.name:
|
||||||
close = "PyStackRef_XCLOSE"
|
close = "PyStackRef_XCLOSE"
|
||||||
if var.size:
|
if var.size:
|
||||||
if var.size == "1":
|
if var.size == "1":
|
||||||
|
@ -668,8 +642,6 @@ class Storage:
|
||||||
close_named(close, f"{var.name}[_i]", overwrite)
|
close_named(close, f"{var.name}[_i]", overwrite)
|
||||||
out.emit("}\n")
|
out.emit("}\n")
|
||||||
else:
|
else:
|
||||||
if var.condition and var.condition == "0":
|
|
||||||
return
|
|
||||||
close_named(close, var.name, overwrite)
|
close_named(close, var.name, overwrite)
|
||||||
|
|
||||||
self.clear_dead_inputs()
|
self.clear_dead_inputs()
|
||||||
|
|
|
@ -40,10 +40,7 @@ LABEL_END_MARKER = "/* END LABELS */"
|
||||||
def declare_variable(var: StackItem, out: CWriter) -> None:
|
def declare_variable(var: StackItem, out: CWriter) -> None:
|
||||||
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:
|
out.emit(f"{type}{space}{var.name};\n")
|
||||||
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:
|
||||||
|
|
|
@ -41,14 +41,7 @@ def declare_variable(
|
||||||
required.remove(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:
|
out.emit(f"{type}{space}{var.name};\n")
|
||||||
out.emit(f"{type}{space}{var.name} = {null};\n")
|
|
||||||
if uop.replicates:
|
|
||||||
# Replicas may not use all their conditional variables
|
|
||||||
# So avoid a compiler warning with a fake use
|
|
||||||
out.emit(f"(void){var.name};\n")
|
|
||||||
else:
|
|
||||||
out.emit(f"{type}{space}{var.name};\n")
|
|
||||||
|
|
||||||
|
|
||||||
def declare_variables(uop: Uop, out: CWriter) -> None:
|
def declare_variables(uop: Uop, out: CWriter) -> None:
|
||||||
|
@ -189,9 +182,6 @@ def generate_tier2(
|
||||||
for name, uop in analysis.uops.items():
|
for name, uop in analysis.uops.items():
|
||||||
if uop.properties.tier == 1:
|
if uop.properties.tier == 1:
|
||||||
continue
|
continue
|
||||||
if uop.properties.oparg_and_1:
|
|
||||||
out.emit(f"/* {uop.name} is split on (oparg & 1) */\n\n")
|
|
||||||
continue
|
|
||||||
if uop.is_super():
|
if uop.is_super():
|
||||||
continue
|
continue
|
||||||
why_not_viable = uop.why_not_viable()
|
why_not_viable = uop.why_not_viable()
|
||||||
|
|
|
@ -4,10 +4,16 @@
|
||||||
#include "pycore_call.h"
|
#include "pycore_call.h"
|
||||||
#include "pycore_ceval.h"
|
#include "pycore_ceval.h"
|
||||||
#include "pycore_cell.h"
|
#include "pycore_cell.h"
|
||||||
|
#include "pycore_code.h"
|
||||||
#include "pycore_dict.h"
|
#include "pycore_dict.h"
|
||||||
|
#include "pycore_floatobject.h"
|
||||||
#include "pycore_emscripten_signal.h"
|
#include "pycore_emscripten_signal.h"
|
||||||
|
#include "pycore_frame.h"
|
||||||
|
#include "pycore_genobject.h"
|
||||||
|
#include "pycore_interpframe.h"
|
||||||
#include "pycore_intrinsics.h"
|
#include "pycore_intrinsics.h"
|
||||||
#include "pycore_jit.h"
|
#include "pycore_jit.h"
|
||||||
|
#include "pycore_list.h"
|
||||||
#include "pycore_long.h"
|
#include "pycore_long.h"
|
||||||
#include "pycore_opcode_metadata.h"
|
#include "pycore_opcode_metadata.h"
|
||||||
#include "pycore_opcode_utils.h"
|
#include "pycore_opcode_utils.h"
|
||||||
|
@ -18,6 +24,8 @@
|
||||||
#include "pycore_sliceobject.h"
|
#include "pycore_sliceobject.h"
|
||||||
#include "pycore_descrobject.h"
|
#include "pycore_descrobject.h"
|
||||||
#include "pycore_stackref.h"
|
#include "pycore_stackref.h"
|
||||||
|
#include "pycore_tuple.h"
|
||||||
|
#include "pycore_unicodeobject.h"
|
||||||
|
|
||||||
#include "ceval_macros.h"
|
#include "ceval_macros.h"
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue