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