File: entrypoint.py

package info (click to toggle)
pypy 5.6.0%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 97,040 kB
  • ctags: 185,069
  • sloc: python: 1,147,862; ansic: 49,642; cpp: 5,245; asm: 5,169; makefile: 529; sh: 481; xml: 232; lisp: 45
file content (111 lines) | stat: -rw-r--r-- 4,028 bytes parent folder | download | duplicates (3)
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.")