Skip to content

Commit 8748cbe

Browse files
committed
WIP
1 parent 75a6441 commit 8748cbe

File tree

4 files changed

+127
-1
lines changed

4 files changed

+127
-1
lines changed

Include/cpython/code.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ typedef uint16_t _Py_CODEUNIT;
3232
#define _Py_SET_OPCODE(word, opcode) \
3333
do { ((unsigned char *)&(word))[0] = (opcode); } while (0)
3434

35+
3536
// To avoid repeating ourselves in deepfreeze.py, all PyCodeObject members are
3637
// defined in this macro:
3738
#define _PyCode_DEF(SIZE) { \
@@ -88,6 +89,7 @@ typedef uint16_t _Py_CODEUNIT;
8889
PyObject *co_filename; /* unicode (where it was loaded from) */ \
8990
PyObject *co_name; /* unicode (name, for reference) */ \
9091
PyObject *co_qualname; /* unicode (qualname, for reference) */ \
92+
void* co_trampoline; \
9193
PyObject *co_linetable; /* bytes object that holds location info */ \
9294
PyObject *co_weakreflist; /* to support weakrefs to code objects */ \
9395
PyObject *_co_code; /* cached co_code object/attribute */ \

Include/internal/pycore_ceval.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ struct _ceval_runtime_state;
2525

2626
#include "pycore_interp.h" // PyInterpreterState.eval_frame
2727
#include "pycore_pystate.h" // _PyThreadState_GET()
28+
#include "pycore_frame.h" // _PyThreadState_GET()
2829

30+
typedef PyObject* (*py_evaluator)(PyThreadState *, _PyInterpreterFrame *, int throwflag);
31+
typedef PyObject* (*py_trampoline)(py_evaluator, PyThreadState *, _PyInterpreterFrame *, int throwflag);
2932

3033
extern void _Py_FinishPendingCalls(PyThreadState *tstate);
3134
extern void _PyEval_InitRuntimeState(struct _ceval_runtime_state *);
@@ -71,6 +74,11 @@ _PyEval_EvalFrame(PyThreadState *tstate, struct _PyInterpreterFrame *frame, int
7174
{
7275
EVAL_CALL_STAT_INC(EVAL_CALL_TOTAL);
7376
if (tstate->interp->eval_frame == NULL) {
77+
PyCodeObject *co = frame->f_code;
78+
py_trampoline f = (py_trampoline)(co->co_trampoline);
79+
if (f) {
80+
return f(_PyEval_EvalFrameDefault, tstate, frame, throwflag);
81+
}
7482
return _PyEval_EvalFrameDefault(tstate, frame, throwflag);
7583
}
7684
return tstate->interp->eval_frame(tstate, frame, throwflag);

Objects/codeobject.c

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,22 @@
99
#include "pycore_opcode.h" // _PyOpcode_Deopt
1010
#include "pycore_pystate.h" // _PyInterpreterState_GET()
1111
#include "pycore_tuple.h" // _PyTuple_ITEMS()
12+
#include "pycore_ceval.h" // _PyTuple_ITEMS()
1213
#include "clinic/codeobject.c.h"
1314

15+
#include <stdio.h>
16+
#include <stdlib.h>
17+
#include <sys/mman.h>
18+
#include <stdio.h>
19+
#include <unistd.h>
20+
21+
#include <sys/types.h>
22+
#include <stdio.h>
23+
#include <stdlib.h>
24+
#include <errno.h>
25+
26+
27+
1428

1529
/******************
1630
* generic helpers
@@ -286,6 +300,101 @@ _PyCode_Validate(struct _PyCodeConstructor *con)
286300
return 0;
287301
}
288302

303+
py_trampoline compile_blech(void) {
304+
char *memory = mmap(NULL, // address
305+
4096, // size
306+
PROT_READ | PROT_WRITE | PROT_EXEC,
307+
MAP_PRIVATE | MAP_ANONYMOUS,
308+
-1, // fd (not used here)
309+
0); // offset (not used here)
310+
if (!memory) {
311+
perror("failed to allocate memory");
312+
exit(1);
313+
}
314+
315+
int i = 0;
316+
317+
memory[i++] = 0x55;
318+
memory[i++] = 0x48;
319+
memory[i++] = 0x89;
320+
memory[i++] = 0xe5;
321+
memory[i++] = 0x48;
322+
memory[i++] = 0x83;
323+
memory[i++] = 0xec;
324+
memory[i++] = 0x20;
325+
memory[i++] = 0x48;
326+
memory[i++] = 0x89;
327+
memory[i++] = 0x7d;
328+
memory[i++] = 0xf8;
329+
memory[i++] = 0x48;
330+
memory[i++] = 0x89;
331+
memory[i++] = 0x75;
332+
memory[i++] = 0xf0;
333+
memory[i++] = 0x48;
334+
memory[i++] = 0x89;
335+
memory[i++] = 0x55;
336+
memory[i++] = 0xe8;
337+
memory[i++] = 0x89;
338+
memory[i++] = 0x4d;
339+
memory[i++] = 0xe4;
340+
memory[i++] = 0x8b;
341+
memory[i++] = 0x55;
342+
memory[i++] = 0xe4;
343+
memory[i++] = 0x48;
344+
memory[i++] = 0x8b;
345+
memory[i++] = 0x4d;
346+
memory[i++] = 0xe8;
347+
memory[i++] = 0x48;
348+
memory[i++] = 0x8b;
349+
memory[i++] = 0x45;
350+
memory[i++] = 0xf0;
351+
memory[i++] = 0x4c;
352+
memory[i++] = 0x8b;
353+
memory[i++] = 0x45;
354+
memory[i++] = 0xf8;
355+
memory[i++] = 0x48;
356+
memory[i++] = 0x89;
357+
memory[i++] = 0xce;
358+
memory[i++] = 0x48;
359+
memory[i++] = 0x89;
360+
memory[i++] = 0xc7;
361+
memory[i++] = 0x41;
362+
memory[i++] = 0xff;
363+
memory[i++] = 0xd0;
364+
memory[i++] = 0xc9;
365+
memory[i++] = 0xc3;
366+
367+
return (py_trampoline) memory;
368+
}
369+
370+
FILE *perf_map_open(pid_t pid) {
371+
char filename[500];
372+
snprintf(filename, sizeof(filename), "/tmp/perf-%d.map", pid);
373+
FILE * res = fopen(filename, "a");
374+
if (!res) {
375+
fprintf(stderr, "Couldn't open %s: errno(%d)", filename, errno);
376+
exit(0);
377+
}
378+
return res;
379+
}
380+
381+
int perf_map_close(FILE *fp) {
382+
if (fp)
383+
return fclose(fp);
384+
else
385+
return 0;
386+
}
387+
388+
void perf_map_write_entry(FILE *method_file, const void* code_addr, unsigned int code_size, const char* entry) {
389+
fprintf(method_file, "%lx %x %s\n", (unsigned long) code_addr, code_size, entry);
390+
}
391+
392+
typedef PyObject* (*py_evaluator)(PyThreadState *, _PyInterpreterFrame *, int throwflag);
393+
394+
PyObject* the_trampoline(py_evaluator eval, PyThreadState* t, _PyInterpreterFrame* f, int p) {
395+
return eval(t, f,p);
396+
}
397+
289398
static void
290399
init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
291400
{
@@ -300,6 +409,13 @@ init_code(PyCodeObject *co, struct _PyCodeConstructor *con)
300409
co->co_name = con->name;
301410
Py_INCREF(con->qualname);
302411
co->co_qualname = con->qualname;
412+
413+
py_trampoline f = compile_blech();
414+
FILE* pfile = perf_map_open(getpid());
415+
perf_map_write_entry(pfile, f, 4096, PyUnicode_AsUTF8(con->qualname));
416+
perf_map_close(pfile);
417+
418+
co->co_trampoline = f;
303419
co->co_flags = con->flags;
304420

305421
co->co_firstlineno = con->firstlineno;

Python/ceval.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4812,7 +4812,7 @@ _PyEval_EvalFrameDefault(PyThreadState *tstate, _PyInterpreterFrame *frame, int
48124812
function = PEEK(total_args + 1);
48134813
int positional_args = total_args - KWNAMES_LEN();
48144814
// Check if the call can be inlined or not
4815-
if (Py_TYPE(function) == &PyFunction_Type && tstate->interp->eval_frame == NULL) {
4815+
if (0 && Py_TYPE(function) == &PyFunction_Type && tstate->interp->eval_frame == NULL) {
48164816
int code_flags = ((PyCodeObject*)PyFunction_GET_CODE(function))->co_flags;
48174817
PyObject *locals = code_flags & CO_OPTIMIZED ? NULL : Py_NewRef(PyFunction_GET_GLOBALS(function));
48184818
STACK_SHRINK(total_args);

0 commit comments

Comments
 (0)