1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
|
secondary_entrypoints = {"main": []}
import py
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rlib.objectmodel import we_are_translated
annotated_jit_entrypoints = []
def export_symbol(func):
func.exported_symbol = True
return func
all_jit_entrypoints = []
def jit_entrypoint(argtypes, restype, c_name):
def deco(func):
func.c_name = c_name
func.relax_sig_check = True
export_symbol(func)
all_jit_entrypoints.append((func, argtypes, restype))
return func
return deco
def entrypoint_lowlevel(key, argtypes, c_name=None, relax=False):
""" Note: entrypoint should acquire the GIL and call
llop.gc_stack_bottom on its own.
If in doubt, use entrypoint_highlevel().
if key == 'main' than it's included by default
"""
def deco(func):
secondary_entrypoints.setdefault(key, []).append((func, argtypes))
if c_name is not None:
func.c_name = c_name
if relax:
func.relax_sig_check = True
export_symbol(func)
return func
return deco
pypy_debug_catch_fatal_exception = rffi.llexternal('pypy_debug_catch_fatal_exception', [], lltype.Void)
def entrypoint_highlevel(key, argtypes, c_name=None):
"""
Export the decorated Python function as C, under the name 'c_name'.
The function is wrapped inside a function that does the necessary
GIL-acquiring and GC-root-stack-bottom-ing.
If key == 'main' then it's included by default; otherwise you need
to list the key in the config's secondaryentrypoints (or give it
on the command-line with --entrypoints when translating).
"""
def deco(func):
source = py.code.Source("""
from rpython.rlib import rgil
def wrapper(%(args)s):
# acquire the GIL
rgil.acquire()
#
rffi.stackcounter.stacks_counter += 1
llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py
# this should not raise
try:
res = func(%(args)s)
except Exception, e:
if not we_are_translated():
import traceback
traceback.print_exc()
raise
else:
print str(e)
pypy_debug_catch_fatal_exception()
llop.debug_fatalerror(lltype.Void, "error in c callback")
assert 0 # dead code
rffi.stackcounter.stacks_counter -= 1
# release the GIL
rgil.release()
#
return res
""" % {'args': ', '.join(['arg%d' % i for i in range(len(argtypes))])})
d = {'rffi': rffi, 'lltype': lltype,
'pypy_debug_catch_fatal_exception': pypy_debug_catch_fatal_exception,
'llop': llop, 'func': func, 'we_are_translated': we_are_translated}
exec source.compile() in d
wrapper = d['wrapper']
secondary_entrypoints.setdefault(key, []).append((wrapper, argtypes))
wrapper.func_name = func.func_name
if c_name is not None:
wrapper.c_name = c_name
export_symbol(wrapper)
#
# the return value of the decorator is *the original function*,
# so that it can be called from Python too. The wrapper is only
# registered in secondary_entrypoints where genc finds it.
func.exported_wrapper = wrapper
return func
return deco
def entrypoint(*args, **kwds):
raise Exception("entrypoint.entrypoint() is removed because of a bug. "
"Remove the 'aroundstate' code in your functions and "
"then call entrypoint_highlevel(), which does that for "
"you. Another difference is that entrypoint_highlevel() "
"returns the normal Python function, which can be safely "
"called from more Python code.")
|