Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r84933:44f4010275d1
Date: 2016-06-05 12:23 +0200
http://bitbucket.org/pypy/pypy/changeset/44f4010275d1/

Log:    In the C entrypoint, don't make RPython strings for argv. Instead,
        call an RPython function with the "char **argv" argument. Simplifies
        a deprecated bit of genc.

        (Copied from stmgc-c8 with various test fixes. It was also attempted
        on the refactor-translator branch, which was abandoned, but trying
        here to keep close to stmgc-c8 instead.)

diff --git a/rpython/memory/gctransform/test/test_framework.py 
b/rpython/memory/gctransform/test/test_framework.py
--- a/rpython/memory/gctransform/test/test_framework.py
+++ b/rpython/memory/gctransform/test/test_framework.py
@@ -40,6 +40,7 @@
     t.config.translation.gc = "minimark"
     cbuild = CStandaloneBuilder(t, entrypoint, t.config,
                                 gcpolicy=FrameworkGcPolicy2)
+    cbuild.make_entrypoint_wrapper = False
     db = cbuild.build_database()
     entrypointptr = cbuild.getentrypointptr()
     entrygraph = entrypointptr._obj.graph
@@ -115,6 +116,7 @@
     t.config.translation.gc = "minimark"
     cbuild = CStandaloneBuilder(t, entrypoint, t.config,
                                 gcpolicy=FrameworkGcPolicy2)
+    cbuild.make_entrypoint_wrapper = False
     db = cbuild.build_database()
 
 def test_no_collect_detection():
@@ -139,6 +141,7 @@
     t.config.translation.gc = "minimark"
     cbuild = CStandaloneBuilder(t, entrypoint, t.config,
                                 gcpolicy=FrameworkGcPolicy2)
+    cbuild.make_entrypoint_wrapper = False
     with py.test.raises(Exception) as f:
         cbuild.build_database()
     expected = "'no_collect' function can trigger collection: <function g at "
@@ -164,6 +167,7 @@
     t.config.translation.gc = "minimark"
     cbuild = CStandaloneBuilder(t, entrypoint, t.config,
                                 gcpolicy=FrameworkGcPolicy2)
+    cbuild.make_entrypoint_wrapper = False
     with py.test.raises(Exception) as f:
         cbuild.build_database()
     assert 'can cause the GC to be called' in str(f.value)
@@ -254,6 +258,7 @@
     t.config.translation.gc = "minimark"
     cbuild = CStandaloneBuilder(t, g, t.config,
                                 gcpolicy=FrameworkGcPolicy2)
+    cbuild.make_entrypoint_wrapper = False
     db = cbuild.build_database()
 
     ff = graphof(t, f)
diff --git a/rpython/memory/gctransform/test/test_transform.py 
b/rpython/memory/gctransform/test/test_transform.py
--- a/rpython/memory/gctransform/test/test_transform.py
+++ b/rpython/memory/gctransform/test/test_transform.py
@@ -17,6 +17,7 @@
         t = rtype(f, args_s)
         # XXX we shouldn't need an actual gcpolicy here.
         cbuild = CStandaloneBuilder(t, f, t.config, gcpolicy=self.gcpolicy)
+        cbuild.make_entrypoint_wrapper = False
         cbuild.build_database()
         graph = cbuild.getentrypointptr()._obj.graph
         # arguments cannot be GC objects because nobody would put a
diff --git a/rpython/memory/test/test_transformed_gc.py 
b/rpython/memory/test/test_transformed_gc.py
--- a/rpython/memory/test/test_transformed_gc.py
+++ b/rpython/memory/test/test_transformed_gc.py
@@ -113,6 +113,7 @@
 
         cbuild = CStandaloneBuilder(t, entrypoint, config=t.config,
                                     gcpolicy=cls.gcpolicy)
+        cbuild.make_entrypoint_wrapper = False
         db = cbuild.build_database()
         entrypointptr = cbuild.getentrypointptr()
         entrygraph = entrypointptr._obj.graph
diff --git a/rpython/rtyper/lltypesystem/rffi.py 
b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -804,6 +804,7 @@
         while cp[size] != lastchar:
             size += 1
         return assert_str0(charpsize2str(cp, size))
+    charp2str._annenforceargs_ = [lltype.SomePtr(TYPEP)]
 
     # str -> char*, bool, bool
     # Can't inline this because of the raw address manipulation.
diff --git a/rpython/translator/c/extfunc.py b/rpython/translator/c/extfunc.py
--- a/rpython/translator/c/extfunc.py
+++ b/rpython/translator/c/extfunc.py
@@ -7,48 +7,15 @@
 from rpython.translator.c.support import cdecl
 
 
-def find_list_of_str(rtyper):
-    r_strlist = rtyper.getrepr(s_list_of_strings)
-    rtyper.call_all_setups()
-    return r_strlist.lowleveltype.TO
-
-
 def predeclare_common_types(db, rtyper):
     # Common types
     yield ('RPyString', STR)
-    LIST_OF_STR = find_list_of_str(rtyper)
-    yield ('RPyListOfString', LIST_OF_STR)
 
 def predeclare_utility_functions(db, rtyper):
     # Common utility functions
     def RPyString_New(length=lltype.Signed):
         return mallocstr(length)
 
-    # !!!
-    # be extremely careful passing a gc tracked object
-    # from such an helper result to another one
-    # as argument, this could result in leaks
-    # Such result should be only from C code
-    # returned directly as results
-
-    LIST_OF_STR = find_list_of_str(rtyper)
-    p = lltype.Ptr(LIST_OF_STR)
-
-    def _RPyListOfString_New(length=lltype.Signed):
-        return LIST_OF_STR.ll_newlist(length)
-
-    def _RPyListOfString_SetItem(l=p,
-                                index=lltype.Signed,
-                                newstring=lltype.Ptr(STR)):
-        rlist.ll_setitem_nonneg(rlist.dum_nocheck, l, index, newstring)
-
-    def _RPyListOfString_GetItem(l=p,
-                                index=lltype.Signed):
-        return rlist.ll_getitem_fast(l, index)
-
-    def _RPyListOfString_Length(l=p):
-        return rlist.ll_length(l)
-
     for fname, f in locals().items():
         if isinstance(f, types.FunctionType):
             # XXX this is painful :(
diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py
--- a/rpython/translator/c/genc.py
+++ b/rpython/translator/c/genc.py
@@ -3,7 +3,7 @@
 import sys, os
 from rpython.rlib import exports
 from rpython.rtyper.lltypesystem.lltype import getfunctionptr
-from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rtyper.lltypesystem import lltype
 from rpython.tool import runsubprocess
 from rpython.tool.nullpath import NullPyPathLocal
 from rpython.tool.udir import udir
@@ -252,6 +252,8 @@
     split = True
     executable_name = None
     shared_library_name = None
+    _entrypoint_wrapper = None
+    make_entrypoint_wrapper = True    # for tests
 
     def getprofbased(self):
         profbased = None
@@ -277,8 +279,39 @@
     def getentrypointptr(self):
         # XXX check that the entrypoint has the correct
         # signature:  list-of-strings -> int
-        bk = self.translator.annotator.bookkeeper
-        return getfunctionptr(bk.getdesc(self.entrypoint).getuniquegraph())
+        if not self.make_entrypoint_wrapper:
+            bk = self.translator.annotator.bookkeeper
+            return getfunctionptr(bk.getdesc(self.entrypoint).getuniquegraph())
+        if self._entrypoint_wrapper is not None:
+            return self._entrypoint_wrapper
+        #
+        from rpython.annotator import model as annmodel
+        from rpython.rtyper.lltypesystem import rffi
+        from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator
+        from rpython.rtyper.llannotation import lltype_to_annotation
+        entrypoint = self.entrypoint
+        #
+        def entrypoint_wrapper(argc, argv):
+            """This is a wrapper that takes "Signed argc" and "char **argv"
+            like the C main function, and puts them inside an RPython list
+            of strings before invoking the real entrypoint() function.
+            """
+            list = [""] * argc
+            i = 0
+            while i < argc:
+                list[i] = rffi.charp2str(argv[i])
+                i += 1
+            return entrypoint(list)
+        #
+        mix = MixLevelHelperAnnotator(self.translator.rtyper)
+        args_s = [annmodel.SomeInteger(),
+                  lltype_to_annotation(rffi.CCHARPP)]
+        s_result = annmodel.SomeInteger()
+        graph = mix.getgraph(entrypoint_wrapper, args_s, s_result)
+        mix.finish()
+        res = getfunctionptr(graph)
+        self._entrypoint_wrapper = res
+        return res
 
     def cmdexec(self, args='', env=None, err=False, expect_crash=False, 
exe=None):
         assert self._compiled
diff --git a/rpython/translator/c/src/entrypoint.c 
b/rpython/translator/c/src/entrypoint.c
--- a/rpython/translator/c/src/entrypoint.c
+++ b/rpython/translator/c/src/entrypoint.c
@@ -62,7 +62,6 @@
 {
     char *errmsg;
     int i, exitcode;
-    RPyListOfString *list;
 
 #if defined(MS_WINDOWS) && defined(RPY_SANDBOXED)
     _setmode(0, _O_BINARY);
@@ -94,15 +93,7 @@
 
     RPython_StartupCode();
 
-    list = _RPyListOfString_New(argc);
-    if (RPyExceptionOccurred()) goto memory_out;
-    for (i=0; i<argc; i++) {
-        RPyString *s = RPyString_FromString(argv[i]);
-        if (RPyExceptionOccurred()) goto memory_out;
-        _RPyListOfString_SetItem(list, i, s);
-    }
-
-    exitcode = STANDALONE_ENTRY_POINT(list);
+    exitcode = STANDALONE_ENTRY_POINT(argc, argv);
 
     pypy_debug_alloc_results();
 
diff --git a/rpython/translator/c/test/test_genc.py 
b/rpython/translator/c/test/test_genc.py
--- a/rpython/translator/c/test/test_genc.py
+++ b/rpython/translator/c/test/test_genc.py
@@ -243,10 +243,11 @@
 
 
 def test_dont_write_source_files():
-    def f(x):
-        return x*2
+    from rpython.annotator.listdef import s_list_of_strings
+    def f(argv):
+        return len(argv)*2
     t = TranslationContext()
-    t.buildannotator().build_types(f, [int])
+    t.buildannotator().build_types(f, [s_list_of_strings])
     t.buildrtyper().specialize()
 
     t.config.translation.countmallocs = True
diff --git a/rpython/translator/c/test/test_standalone.py 
b/rpython/translator/c/test/test_standalone.py
--- a/rpython/translator/c/test/test_standalone.py
+++ b/rpython/translator/c/test/test_standalone.py
@@ -621,9 +621,10 @@
         lines = err.strip().splitlines()
         idx = lines.index('Fatal RPython error: ValueError')   # assert found
         lines = lines[:idx+1]
-        assert len(lines) >= 4
-        l0, l1, l2 = lines[-4:-1]
+        assert len(lines) >= 5
+        l0, lx, l1, l2 = lines[-5:-1]
         assert l0 == 'RPython traceback:'
+        # lx is a bit strange with reference counting, ignoring it
         assert re.match(r'  File "\w+.c", line \d+, in entry_point', l1)
         assert re.match(r'  File "\w+.c", line \d+, in g', l2)
         #
@@ -632,8 +633,9 @@
         lines2 = err2.strip().splitlines()
         idx = lines2.index('Fatal RPython error: KeyError')    # assert found
         lines2 = lines2[:idx+1]
-        l0, l1, l2 = lines2[-4:-1]
+        l0, lx, l1, l2 = lines2[-5:-1]
         assert l0 == 'RPython traceback:'
+        # lx is a bit strange with reference counting, ignoring it
         assert re.match(r'  File "\w+.c", line \d+, in entry_point', l1)
         assert re.match(r'  File "\w+.c", line \d+, in g', l2)
         assert lines2[-2] != lines[-2]    # different line number
@@ -660,9 +662,10 @@
         lines = err.strip().splitlines()
         idx = lines.index('Fatal RPython error: KeyError')    # assert found
         lines = lines[:idx+1]
-        assert len(lines) >= 5
-        l0, l1, l2, l3 = lines[-5:-1]
+        assert len(lines) >= 6
+        l0, lx, l1, l2, l3 = lines[-6:-1]
         assert l0 == 'RPython traceback:'
+        # lx is a bit strange with reference counting, ignoring it
         assert re.match(r'  File "\w+.c", line \d+, in entry_point', l1)
         assert re.match(r'  File "\w+.c", line \d+, in h', l2)
         assert re.match(r'  File "\w+.c", line \d+, in g', l3)
@@ -697,9 +700,10 @@
         lines = err.strip().splitlines()
         idx = lines.index('Fatal RPython error: KeyError')     # assert found
         lines = lines[:idx+1]
-        assert len(lines) >= 5
-        l0, l1, l2, l3 = lines[-5:-1]
+        assert len(lines) >= 6
+        l0, lx, l1, l2, l3 = lines[-6:-1]
         assert l0 == 'RPython traceback:'
+        # lx is a bit strange with reference counting, ignoring it
         assert re.match(r'  File "\w+.c", line \d+, in entry_point', l1)
         assert re.match(r'  File "\w+.c", line \d+, in h', l2)
         assert re.match(r'  File "\w+.c", line \d+, in g', l3)
@@ -733,9 +737,10 @@
         lines = err.strip().splitlines()
         idx = lines.index('Fatal RPython error: ValueError')    # assert found
         lines = lines[:idx+1]
-        assert len(lines) >= 5
-        l0, l1, l2, l3 = lines[-5:-1]
+        assert len(lines) >= 6
+        l0, lx, l1, l2, l3 = lines[-6:-1]
         assert l0 == 'RPython traceback:'
+        # lx is a bit strange with reference counting, ignoring it
         assert re.match(r'  File "\w+.c", line \d+, in entry_point', l1)
         assert re.match(r'  File "\w+.c", line \d+, in h', l2)
         assert re.match(r'  File "\w+.c", line \d+, in raiseme', l3)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to