-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial commit - pass the first test (albeit requires setting up
LD_LIBRARY_PATH path by hand)
- Loading branch information
Showing
8 changed files
with
125 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,9 @@ | |
__pycache__/ | ||
*.py[cod] | ||
|
||
# backups | ||
*~ | ||
|
||
# C extensions | ||
*.so | ||
|
||
|
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
|
||
typedef struct pypy_defs { | ||
void* (* basic_register)(char *, char *, char *); | ||
} pypy_defs; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
|
||
import cffi, new, os | ||
ffi = cffi.FFI() | ||
ffi.cdef(open(os.path.join(cur_dir, "pypy.defs")).read()) | ||
|
||
MAX_FUNCTIONS = 100 | ||
all_callbacks = [] | ||
|
||
mod = new.module('__global__') | ||
|
||
@ffi.callback("void* (*)(char *, char *, char *)") | ||
def basic_register(ll_source, ll_name, ll_tp): | ||
source = ffi.string(ll_source) | ||
name = ffi.string(ll_name) | ||
tp = ffi.string(ll_tp) | ||
exec source in mod.__dict__ | ||
func = mod.__dict__[name] | ||
ll_callback = ffi.callback(tp)(func) | ||
all_callbacks.append(ll_callback) | ||
return ffi.cast('void *', ll_callback) | ||
|
||
pypy_def = ffi.cast("struct pypy_defs*", c_argument) | ||
pypy_def.basic_register = basic_register |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
|
||
import cffi, os, inspect, py | ||
|
||
def setup(pypy_home): | ||
ffi = cffi.FFI() | ||
ffi.cdef(""" | ||
void rpython_startup_code(void); | ||
long pypy_setup_home(char* home, int verbose); | ||
int pypy_execute_source(char* source); | ||
int pypy_execute_source_ptr(char* source, void* ptr); | ||
""") | ||
os.environ['LD_LIBRARY_PATH'] = os.path.join(pypy_home, 'bin') | ||
|
||
lib = ffi.verify(""" | ||
#include <include/PyPy.h> | ||
""", libraries=["pypy-c"], include_dirs=[pypy_home], library_dirs=[os.path.join(pypy_home, 'bin')]) | ||
curdir = os.path.dirname(os.path.abspath(__file__)) | ||
defs = os.path.join(curdir, 'pypy.defs') | ||
ffi.cdef(open(defs).read()) | ||
lib.rpython_startup_code() | ||
res = lib.pypy_setup_home(os.path.join(os.path.abspath(pypy_home), 'bin'), | ||
1) | ||
pypy_side = os.path.join(curdir, 'pypy_side.py') | ||
if res == -1: | ||
raise Exception("cannot init pypy") | ||
ptr = ffi.new("struct pypy_defs*") | ||
res = lib.pypy_execute_source_ptr(str(py.code.Source(""" | ||
import sys, traceback | ||
try: | ||
import os | ||
cur_dir = '%s' | ||
execfile('%s') | ||
except Exception, e: | ||
traceback.print_tb(sys.exc_info()[2]) | ||
print "%%s:%%s" %% (e.__class__.__name__, e) | ||
raise | ||
""" % (curdir, pypy_side))), ptr) | ||
if res: | ||
raise Exception("error running pypy side") | ||
|
||
converters = { | ||
int: 'long', | ||
float: 'double', | ||
str: 'char*', | ||
} | ||
|
||
def jittify(argtypes, restype): | ||
""" Wrap function into a callable visible from CPython, but run on | ||
underlaying PyPy. | ||
""" | ||
ll_tp = converters[restype] + ' (*)(' + ', '.join( | ||
[converters[arg] for arg in argtypes]) + ')' | ||
def decorator(fn): | ||
lines = inspect.getsource(fn).splitlines() | ||
for i, line in enumerate(lines): | ||
if line.strip(' ').startswith('@'): | ||
continue | ||
lines[i] = line.strip(' ') | ||
break | ||
source = "\n".join(lines[i:]) | ||
name = fn.__name__ | ||
handle = ptr.basic_register(source, name, ll_tp) | ||
if not handle: | ||
raise Exception("basic_register failed") | ||
return ffi.cast(ll_tp, handle) | ||
return decorator | ||
|
||
globals()['jittify'] = jittify |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
cffi |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
|
||
import os | ||
from jitpy.wrapper import setup | ||
if 'PYPY_HOME' not in os.environ: | ||
raise Exception("please setup PYPY_HOME to point to your pypy installation") | ||
setup(os.environ['PYPY_HOME']) | ||
from jitpy.wrapper import jittify | ||
|
||
class TestJitPy(object): | ||
def test_float_func(self): | ||
@jittify([float, float], float) | ||
def func(a, b): | ||
return a + b | ||
|
||
assert func(1.2, 2.4) == 1.2 + 2.4 | ||
|
||
def test_int_func(self): | ||
@jittify([int, int], int) | ||
def func(a, b): | ||
return a + b | ||
|
||
assert func(2, 4) == 6 |