pypy /rpython/translator/c/gcc/test/test_asmgcroot.py

Language Python Lines 271
MD5 Hash 2ce7e7dd685808a80d41aa50486cd388 Estimated Cost $5,458 (why?)
Repository https://bitbucket.org/pypy/pypy/ View Raw File View Project SPDX
  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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
import py
import sys, os, gc
from rpython.translator.c.test import test_newgc
from rpython.translator.translator import TranslationContext
from rpython.translator.c.genc import CStandaloneBuilder
from rpython.annotator.listdef import s_list_of_strings
from rpython.conftest import option
from rpython.translator.tool.cbuild import ExternalCompilationInfo
from rpython.translator.platform import platform as compiler
from rpython.rlib.rarithmetic import is_emulated_long
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rlib.entrypoint import entrypoint_highlevel, secondary_entrypoints
from rpython.rtyper.lltypesystem.lloperation import llop

_MSVC = compiler.name == "msvc"
_MINGW = compiler.name == "mingw32"
_WIN32 = _MSVC or _MINGW
_WIN64 = _WIN32 and is_emulated_long
# XXX get rid of 'is_emulated_long' and have a real config here.

class AbstractTestAsmGCRoot:
    # the asmgcroot gc transformer doesn't generate gc_reload_possibly_moved
    # instructions:
    should_be_moving = False

    @classmethod
    def make_config(cls):
        if _MSVC:
            py.test.skip("all asmgcroot tests disabled for MSVC")
        from rpython.config.translationoption import get_combined_translation_config
        config = get_combined_translation_config(translating=True)
        config.translation.gc = cls.gcpolicy
        config.translation.gcrootfinder = "asmgcc"
        config.translation.taggedpointers = getattr(cls, "taggedpointers", False)
        return config

    @classmethod
    def _makefunc_str_int(cls, func):
        def main(argv):
            arg0 = argv[1]
            arg1 = int(argv[2])
            try:
                res = func(arg0, arg1)
            except MemoryError:
                print 'Result: MemoryError'
            else:
                print 'Result: "%s"' % (res,)
            return 0
        config = cls.make_config()
        t = TranslationContext(config=config)
        a = t.buildannotator()
        sec_ep = getattr(cls, 'secondary_entrypoints', [])
        for f, inputtypes in sec_ep:
            a.build_types(f, inputtypes, False)
        a.build_types(main, [s_list_of_strings])
        t.buildrtyper().specialize()
        t.checkgraphs()

        cbuilder = CStandaloneBuilder(t, main, config=config,
                secondary_entrypoints=sec_ep)
        c_source_filename = cbuilder.generate_source(
            defines = cbuilder.DEBUG_DEFINES)
        cls._patch_makefile(cbuilder.targetdir)
        if option.view:
            t.view()
        exe_name = cbuilder.compile()

        def run(arg0, arg1, runner=None):
            if runner is not None:
                py.test.skip("unsupported test: runner=%r" % (runner,))
            lines = []
            print >> sys.stderr, 'RUN: starting', exe_name, arg0, arg1
            if sys.platform == 'win32':
                redirect = ' 2> NUL'
            else:
                redirect = ''
            if config.translation.shared and os.name == 'posix':
                library_path = exe_name.dirpath()
                if sys.platform == 'darwin':
                    env = 'DYLD_LIBRARY_PATH="%s" ' % library_path
                else:
                    env = 'LD_LIBRARY_PATH="%s" ' % library_path
            else:
                env = ''
            cwd = os.getcwd()
            try:
                os.chdir(str(exe_name.dirpath()))
                g = os.popen(
                    '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r')
            finally:
                os.chdir(cwd)
            for line in g:
                print >> sys.stderr, 'RUN:', line.rstrip()
                lines.append(line)
            g.close()
            if not lines:
                py.test.fail("no output from subprocess")
            if not lines[-1].startswith('Result:'):
                py.test.fail("unexpected output from subprocess")
            result = lines[-1][len('Result:'):].strip()
            if result == 'MemoryError':
                raise MemoryError("subprocess got an RPython MemoryError")
            if result.startswith('"') and result.endswith('"'):
                return result[1:-1]
            else:
                return int(result)
        return run

    @classmethod
    def _patch_makefile(cls, targetdir):
        # for testing, patch the Makefile to add the -r option to
        # trackgcroot.py.
        makefile = targetdir.join('Makefile')
        f = makefile.open()
        lines = f.readlines()
        f.close()
        found = False
        for i in range(len(lines)):
            if 'trackgcroot.py' in lines[i]:
                lines[i] = lines[i].replace('trackgcroot.py',
                                            'trackgcroot.py -r')
                found = True
        assert found
        f = makefile.open('w')
        f.writelines(lines)
        f.close()

    if sys.platform == 'win32':
        def test_callback_with_collect(self):
            py.test.skip("No libffi yet with mingw32")

        def define_callback_with_collect(cls):
            return lambda: 0

class TestAsmGCRootWithSemiSpaceGC(AbstractTestAsmGCRoot,
                                   test_newgc.TestSemiSpaceGC):
    # for the individual tests see
    # ====> ../../test/test_newgc.py
    secondary_entrypoints = []

    def define_large_function(cls):
        class A(object):
            def __init__(self):
                self.x = 0
        d = dict(A=A)
        exec ("def g(a):\n" +
              "    a.x += 1\n" * 1000 +
              "    return A()\n"
              ) in d
        g = d['g']
        def f():
            a = A()
            g(a)
            return a.x
        return f

    def test_large_function(self):        
        res = self.run('large_function')
        assert res == 1000

    def define_callback_simple(cls):
        c_source = py.code.Source("""
        int mystuff(int(*cb)(int, int))
        {
            return cb(40, 2) + cb(3, 4);
        }
        """)
        eci = ExternalCompilationInfo(separate_module_sources=[c_source])
        S = lltype.GcStruct('S', ('x', lltype.Signed))
        CALLBACK = lltype.FuncType([lltype.Signed, lltype.Signed],
                                   lltype.Signed)
        z = rffi.llexternal('mystuff', [lltype.Ptr(CALLBACK)], lltype.Signed,
                            compilation_info=eci)

        def mycallback(a, b):
            gc.collect()
            return a + b

        def f():
            p = lltype.malloc(S)
            p.x = 100
            result = z(mycallback)
            return result * p.x

        return f

    def test_callback_simple(self):
        res = self.run('callback_simple')
        assert res == 4900

    def define_secondary_entrypoint_callback(cls):
        # XXX this is baaaad, cleanup global state
        try:
            del secondary_entrypoints["x42"]
        except KeyError:
            pass
        
        @entrypoint_highlevel("x42", [lltype.Signed, lltype.Signed],
                              c_name='callback')
        def mycallback(a, b):
            gc.collect()
            return a + b

        c_source = py.code.Source("""
        int mystuff2()
        {
            return callback(40, 2) + callback(3, 4);
        }
        """)

        eci = ExternalCompilationInfo(separate_module_sources=[c_source])
        z = rffi.llexternal('mystuff2', [], lltype.Signed,
                            compilation_info=eci)
        S = lltype.GcStruct('S', ('x', lltype.Signed))

        cls.secondary_entrypoints = secondary_entrypoints["x42"]

        def f():
            p = lltype.malloc(S)
            p.x = 100
            result = z()
            return result * p.x

        return f

    def test_secondary_entrypoint_callback(self):
        res = self.run('secondary_entrypoint_callback')
        assert res == 4900

class TestAsmGCRootWithSemiSpaceGC_Mingw32(TestAsmGCRootWithSemiSpaceGC):
    # for the individual tests see
    # ====> ../../test/test_newgc.py

    @classmethod
    def setup_class(cls):
        if sys.platform != 'win32':
            py.test.skip("mingw32 specific test")
        if not ('mingw' in os.popen('gcc --version').read() and
                'GNU' in os.popen('make --version').read()):
            py.test.skip("mingw32 and MSYS are required for this test")

        test_newgc.TestSemiSpaceGC.setup_class.im_func(cls)

    @classmethod
    def make_config(cls):
        config = TestAsmGCRootWithSemiSpaceGC.make_config()
        config.translation.cc = 'mingw32'
        return config


    def test_callback_with_collect(self):
        py.test.skip("No libffi yet with mingw32")

    def define_callback_with_collect(cls):
        return lambda: 0

#class TestAsmGCRootWithSemiSpaceGC_Shared(TestAsmGCRootWithSemiSpaceGC):
#    @classmethod
#    def make_config(cls):
#        config = TestAsmGCRootWithSemiSpaceGC.make_config()
#        config.translation.shared = True
#        return config

class TestAsmGCRootWithHybridTagged(AbstractTestAsmGCRoot,
                                    test_newgc.TestHybridTaggedPointers):
    pass

class TestAsmGCRootWithIncrementalMinimark(AbstractTestAsmGCRoot,
                                    test_newgc.TestIncrementalMiniMarkGC):
    pass
Back to Top