Skip to content

Commit 775df6e

Browse files
committed
Generate (some) cases for the executor
1 parent b5feec7 commit 775df6e

File tree

3 files changed

+335
-23
lines changed

3 files changed

+335
-23
lines changed

Python/executor_cases.c.h

+232
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
// This file is generated by Tools/cases_generator/generate_cases.py
2+
// from:
3+
// Python/bytecodes.c
4+
// Do not edit!
5+
6+
case NOP: {
7+
break;
8+
}
9+
10+
case LOAD_FAST: {
11+
PyObject *value;
12+
value = GETLOCAL(oparg);
13+
assert(value != NULL);
14+
Py_INCREF(value);
15+
STACK_GROW(1);
16+
stack_pointer[-1] = value;
17+
break;
18+
}
19+
20+
case LOAD_FAST_AND_CLEAR: {
21+
PyObject *value;
22+
value = GETLOCAL(oparg);
23+
// do not use SETLOCAL here, it decrefs the old value
24+
GETLOCAL(oparg) = NULL;
25+
STACK_GROW(1);
26+
stack_pointer[-1] = value;
27+
break;
28+
}
29+
30+
case LOAD_FAST_LOAD_FAST: {
31+
PyObject *value1;
32+
PyObject *value2;
33+
uint32_t oparg1 = oparg >> 4;
34+
uint32_t oparg2 = oparg & 15;
35+
value1 = GETLOCAL(oparg1);
36+
value2 = GETLOCAL(oparg2);
37+
Py_INCREF(value1);
38+
Py_INCREF(value2);
39+
STACK_GROW(2);
40+
stack_pointer[-1] = value2;
41+
stack_pointer[-2] = value1;
42+
break;
43+
}
44+
45+
case LOAD_CONST: {
46+
PyObject *value;
47+
value = GETITEM(FRAME_CO_CONSTS, oparg);
48+
Py_INCREF(value);
49+
STACK_GROW(1);
50+
stack_pointer[-1] = value;
51+
break;
52+
}
53+
54+
case STORE_FAST: {
55+
PyObject *value = stack_pointer[-1];
56+
SETLOCAL(oparg, value);
57+
STACK_SHRINK(1);
58+
break;
59+
}
60+
61+
case STORE_FAST_LOAD_FAST: {
62+
PyObject *value1 = stack_pointer[-1];
63+
PyObject *value2;
64+
uint32_t oparg1 = oparg >> 4;
65+
uint32_t oparg2 = oparg & 15;
66+
SETLOCAL(oparg1, value1);
67+
value2 = GETLOCAL(oparg2);
68+
Py_INCREF(value2);
69+
stack_pointer[-1] = value2;
70+
break;
71+
}
72+
73+
case STORE_FAST_STORE_FAST: {
74+
PyObject *value1 = stack_pointer[-1];
75+
PyObject *value2 = stack_pointer[-2];
76+
uint32_t oparg1 = oparg >> 4;
77+
uint32_t oparg2 = oparg & 15;
78+
SETLOCAL(oparg1, value1);
79+
SETLOCAL(oparg2, value2);
80+
STACK_SHRINK(2);
81+
break;
82+
}
83+
84+
case POP_TOP: {
85+
PyObject *value = stack_pointer[-1];
86+
Py_DECREF(value);
87+
STACK_SHRINK(1);
88+
break;
89+
}
90+
91+
case PUSH_NULL: {
92+
PyObject *res;
93+
res = NULL;
94+
STACK_GROW(1);
95+
stack_pointer[-1] = res;
96+
break;
97+
}
98+
99+
case END_SEND: {
100+
PyObject *value = stack_pointer[-1];
101+
PyObject *receiver = stack_pointer[-2];
102+
Py_DECREF(receiver);
103+
STACK_SHRINK(1);
104+
stack_pointer[-1] = value;
105+
break;
106+
}
107+
108+
case _BINARY_OP_MULTIPLY_FLOAT: {
109+
PyObject *right = stack_pointer[-1];
110+
PyObject *left = stack_pointer[-2];
111+
PyObject *res;
112+
STAT_INC(BINARY_OP, hit);
113+
double dres =
114+
((PyFloatObject *)left)->ob_fval *
115+
((PyFloatObject *)right)->ob_fval;
116+
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
117+
STACK_SHRINK(1);
118+
stack_pointer[-1] = res;
119+
break;
120+
}
121+
122+
case _BINARY_OP_ADD_FLOAT: {
123+
PyObject *right = stack_pointer[-1];
124+
PyObject *left = stack_pointer[-2];
125+
PyObject *res;
126+
STAT_INC(BINARY_OP, hit);
127+
double dres =
128+
((PyFloatObject *)left)->ob_fval +
129+
((PyFloatObject *)right)->ob_fval;
130+
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
131+
STACK_SHRINK(1);
132+
stack_pointer[-1] = res;
133+
break;
134+
}
135+
136+
case _BINARY_OP_SUBTRACT_FLOAT: {
137+
PyObject *right = stack_pointer[-1];
138+
PyObject *left = stack_pointer[-2];
139+
PyObject *res;
140+
STAT_INC(BINARY_OP, hit);
141+
double dres =
142+
((PyFloatObject *)left)->ob_fval -
143+
((PyFloatObject *)right)->ob_fval;
144+
DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dres, res);
145+
STACK_SHRINK(1);
146+
stack_pointer[-1] = res;
147+
break;
148+
}
149+
150+
case LOAD_ASSERTION_ERROR: {
151+
PyObject *value;
152+
value = Py_NewRef(PyExc_AssertionError);
153+
STACK_GROW(1);
154+
stack_pointer[-1] = value;
155+
break;
156+
}
157+
158+
case STORE_DEREF: {
159+
PyObject *v = stack_pointer[-1];
160+
PyObject *cell = GETLOCAL(oparg);
161+
PyObject *oldobj = PyCell_GET(cell);
162+
PyCell_SET(cell, v);
163+
Py_XDECREF(oldobj);
164+
STACK_SHRINK(1);
165+
break;
166+
}
167+
168+
case COPY_FREE_VARS: {
169+
/* Copy closure variables to free variables */
170+
PyCodeObject *co = _PyFrame_GetCode(frame);
171+
assert(PyFunction_Check(frame->f_funcobj));
172+
PyObject *closure = ((PyFunctionObject *)frame->f_funcobj)->func_closure;
173+
assert(oparg == co->co_nfreevars);
174+
int offset = co->co_nlocalsplus - oparg;
175+
for (int i = 0; i < oparg; ++i) {
176+
PyObject *o = PyTuple_GET_ITEM(closure, i);
177+
frame->localsplus[offset + i] = Py_NewRef(o);
178+
}
179+
break;
180+
}
181+
182+
case IS_OP: {
183+
PyObject *right = stack_pointer[-1];
184+
PyObject *left = stack_pointer[-2];
185+
PyObject *b;
186+
int res = Py_Is(left, right) ^ oparg;
187+
Py_DECREF(left);
188+
Py_DECREF(right);
189+
b = res ? Py_True : Py_False;
190+
STACK_SHRINK(1);
191+
stack_pointer[-1] = b;
192+
break;
193+
}
194+
195+
case MATCH_MAPPING: {
196+
PyObject *subject = stack_pointer[-1];
197+
PyObject *res;
198+
int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_MAPPING;
199+
res = match ? Py_True : Py_False;
200+
STACK_GROW(1);
201+
stack_pointer[-1] = res;
202+
break;
203+
}
204+
205+
case MATCH_SEQUENCE: {
206+
PyObject *subject = stack_pointer[-1];
207+
PyObject *res;
208+
int match = Py_TYPE(subject)->tp_flags & Py_TPFLAGS_SEQUENCE;
209+
res = match ? Py_True : Py_False;
210+
STACK_GROW(1);
211+
stack_pointer[-1] = res;
212+
break;
213+
}
214+
215+
case COPY: {
216+
PyObject *bottom = stack_pointer[-(1 + (oparg-1))];
217+
PyObject *top;
218+
assert(oparg > 0);
219+
top = Py_NewRef(bottom);
220+
STACK_GROW(1);
221+
stack_pointer[-1] = top;
222+
break;
223+
}
224+
225+
case SWAP: {
226+
PyObject *top = stack_pointer[-1];
227+
PyObject *bottom = stack_pointer[-(2 + (oparg-2))];
228+
assert(oparg >= 2);
229+
stack_pointer[-1] = bottom;
230+
stack_pointer[-(2 + (oparg-2))] = top;
231+
break;
232+
}

Python/optimizer.c

+31-19
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,10 @@ typedef struct {
292292
// UOp opcodes are outside the range of bytecodes or pseudo ops
293293
#define EXIT_TRACE 512
294294
#define SET_IP 513
295+
// TODOL Generate these in Tools/cases_generator
296+
#define _BINARY_OP_MULTIPLY_FLOAT 514
297+
#define _BINARY_OP_ADD_FLOAT 515
298+
#define _BINARY_OP_SUBTRACT_FLOAT 516
295299

296300
typedef struct {
297301
int opcode;
@@ -322,6 +326,25 @@ static PyTypeObject UOpExecutor_Type = {
322326
static _PyInterpreterFrame *
323327
uop_execute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **stack_pointer)
324328
{
329+
// TODO: These macros should be imported from ceval_macros.h or similar
330+
#define GETLOCAL(i) (frame->localsplus[i])
331+
#define SETLOCAL(i, v) do { \
332+
PyObject *tmp = GETLOCAL(i); \
333+
GETLOCAL(i) = (v); \
334+
Py_XDECREF(tmp); \
335+
} while (0)
336+
#define GETITEM(v, i) PyTuple_GET_ITEM((v), (i))
337+
#define STACK_GROW(n) (stack_pointer += (n))
338+
#define STACK_SHRINK(n) (stack_pointer -= (n))
339+
#define FRAME_CO_CONSTS (_PyFrame_GetCode(frame)->co_consts)
340+
#define FRAME_CO_NAMES (_PyFrame_GetCode(frame)->co_names)
341+
#define DECREF_INPUTS_AND_REUSE_FLOAT(left, right, dval, result) do {\
342+
result = PyFloat_FromDouble(dval); \
343+
/* if ((result) == NULL) goto error; */ \
344+
Py_DECREF(left); \
345+
Py_DECREF(right); \
346+
} while (0)
347+
325348
UOpExecutorObject *self = (UOpExecutorObject *)executor;
326349
self->optimizer->traces_executed++;
327350
_Py_CODEUNIT *ip_offset = (_Py_CODEUNIT *)_PyFrame_GetCode(frame)->co_code_adaptive - 1;
@@ -332,38 +355,24 @@ uop_execute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **
332355
pc++;
333356
self->optimizer->instrs_executed++;
334357
switch (opcode) {
335-
// TODO: Tools/cases_generator should generate these from Python/bytecodes.c
336-
case LOAD_FAST:
337-
{
338-
// fprintf(stderr, "LOAD_FAST %d\n", oparg);
339-
PyObject *value = frame->localsplus[oparg];
340-
assert(value != NULL);
341-
Py_INCREF(value);
342-
*stack_pointer++ = value;
343-
break;
344-
}
345-
case LOAD_CONST:
346-
{
347-
// fprintf(stderr, "LOAD_CONST %d\n", oparg);
348-
PyObject *value = PyTuple_GET_ITEM(_PyFrame_GetCode(frame)->co_consts, oparg);
349-
assert(value != NULL);
350-
Py_INCREF(value);
351-
*stack_pointer++ = value;
352-
break;
353-
}
358+
359+
#include "executor_cases.c.h"
360+
354361
case SET_IP:
355362
{
356363
// fprintf(stderr, "SET_IP %d\n", oparg);
357364
frame->prev_instr = ip_offset + oparg;
358365
break;
359366
}
367+
360368
case EXIT_TRACE:
361369
{
362370
// fprintf(stderr, "EXIT_TRACE\n");
363371
_PyFrame_SetStackPointer(frame, stack_pointer);
364372
Py_DECREF(self);
365373
return frame;
366374
}
375+
367376
default:
368377
{
369378
// fprintf(stderr, "Unknown uop %d, oparg %d\n", opcode, oparg);
@@ -372,6 +381,7 @@ uop_execute(_PyExecutorObject *executor, _PyInterpreterFrame *frame, PyObject **
372381
for (;;) {}
373382
// Really unreachable
374383
}
384+
375385
}
376386
}
377387
}
@@ -431,6 +441,8 @@ translate_bytecode_to_trace(
431441
ADD_TO_TRACE(EXIT_TRACE, 0);
432442
}
433443
return trace_length;
444+
445+
#undef ADD_TO_TRACE
434446
}
435447

436448
static int

0 commit comments

Comments
 (0)