Thank you for your reply and your patience!

I compiled your code and get the same output as yours.

However my implementation is different from yours. While we both have an EvalFrame function, your implementation built an module in Python, but I prefer to modify Python source and compile a full distribution.

To be more specific, I first implement an EvalFrame function, which is a simple call of _PyEval_EvalFrameDefault. I compile this function into a .so file. Then in Python/pylifecycle.c, I use dlsym to get the EvalFrame function to replace the function interp->eval_frame. So each time when interp->eval_frame(default as _PyEval_EvalFrameDefault) is called, what is really called is my EvalFrame function. This seems should be fine, but it doesn't work.

My code is here:

To compile it, get a Python-3.6.1.tgz source from Python official website. Replace Python/pylifecycle.c with the one on github. Then use CMake to compile the, and get into Python directory to make Python. It will give an error message, and the python.exe target cannot run.

2017-03-31 23:15 GMT+08:00 Siu Kwan Lam <>:
I have never tried PEP0523 before so I have just did a quick look and pushed what I got to

If you run, you should get the following printouts:

** myjit is evaluating frame=0x10c623048 lasti=-1 lineno=10
Enter apple()
** myjit is evaluating frame=0x7f9a74e02178 lasti=-1 lineno=16
Enter orange()
Exit orange()
Exit apple()
** myjit is evaluating frame=0x10c460d48 lasti=-1 lineno=27

The frame is different for each method.  

Can you try your implementation with my test so we can compare?

On Thu, Mar 30, 2017 at 11:46 PM Yuheng Zou <> wrote:

I am building a Python JIT, so I want to change the interp->eval_frame to my own function.

I built a C++ library which contains EvalFrame function, and then use dlopen and dlsym to use it. It looks like this:

extern "C" PyObject *EvalFrame(PyFrameObject *f, int throwflag) {
    return _PyEval_EvalFrameDefault(f, throwflag);

I added following code to Python/pylifecycle.c at function _Py_InitializeEx_Private(Python version is 3.6.1):

void *pyjit = NULL;
pyjit = dlopen("../cmake-build-debug/libPubbon.dylib", 0);
if (pyjit != NULL) {
    interp->eval_frame = (_PyFrameEvalFunction)dlsym(pyjit, "EvalFrame");
    //interp->eval_frame = _PyEval_EvalFrameDefault;

Then something strange happened. I used LLDB to trace the variables. When it ran at EvalFrame, the address of f pointer didn't change, but f->f_lineno changed.

Why the address of the pointer didn't change, but the context change?

I am working on Mac OS X and Python 3.6.1. I want to know how to replace _PyEval_EvalFrameDefault in interp->eval_frame with my own function.

Python-compilers mailing list
Siu Kwan Lam
Software Engineer
Continuum Analytics