Author: Armin Rigo <[email protected]>
Branch: null_byte_after_str
Changeset: r85935:e043ee2bb479
Date: 2016-07-30 21:11 +0200
http://bitbucket.org/pypy/pypy/changeset/e043ee2bb479/
Log: Introduce rffi.scoped_view_charp() and use it more; for now mainly
in rffi.llexternal().
diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py
--- a/rpython/annotator/binaryop.py
+++ b/rpython/annotator/binaryop.py
@@ -201,8 +201,8 @@
return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
knowntype=knowntype)
- or_ = xor = add = mul = _clone(union, [])
- add_ovf = mul_ovf = _clone(union, [OverflowError])
+ or_ = xor = mul = _clone(union, [])
+ mul_ovf = _clone(union, [OverflowError])
div = floordiv = mod = _clone(union, [ZeroDivisionError])
div_ovf= floordiv_ovf = mod_ovf = _clone(union, [ZeroDivisionError,
OverflowError])
@@ -214,6 +214,15 @@
inplace_div = div
inplace_truediv = truediv
+ def add((int1, int2)):
+ # propagate const-ness to help 'tup[j + 1]'
+ result = pair(int1, int2).union()
+ if int1.is_immutable_constant() and int2.is_immutable_constant():
+ result.const = int1.const + int2.const
+ return result
+ add.can_only_throw = []
+ add_ovf = _clone(add, [OverflowError])
+
def sub((int1, int2)):
knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
return SomeInteger(knowntype=knowntype)
diff --git a/rpython/annotator/test/test_annrpython.py
b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -1004,6 +1004,15 @@
a.build_types(f, [])
# if you want to get a r_uint, you have to be explicit about it
+ def test_add_constant(self):
+ def f(a):
+ return a + 5
+ a = self.RPythonAnnotator()
+ s = annmodel.SomeInteger(nonneg=True)
+ s.const = 12
+ s = a.build_types(f, [s])
+ assert s.const == 17
+
def test_add_different_ints(self):
def f(a, b):
return a + b
diff --git a/rpython/rlib/_os_support.py b/rpython/rlib/_os_support.py
--- a/rpython/rlib/_os_support.py
+++ b/rpython/rlib/_os_support.py
@@ -20,6 +20,7 @@
charp2str = staticmethod(rffi.charp2str)
charpsize2str = staticmethod(rffi.charpsize2str)
scoped_str2charp = staticmethod(rffi.scoped_str2charp)
+ scoped_view_charp = staticmethod(rffi.scoped_view_charp)
str2charp = staticmethod(rffi.str2charp)
free_charp = staticmethod(rffi.free_charp)
scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_buffer)
@@ -55,6 +56,8 @@
charpsize2str = staticmethod(rffi.wcharpsize2unicode)
str2charp = staticmethod(rffi.unicode2wcharp)
scoped_str2charp = staticmethod(rffi.scoped_unicode2wcharp)
+ scoped_view_charp = staticmethod(rffi.scoped_unicode2wcharp)
+ # ^^^ XXX there is no unicode variant of rffi.scoped_view_charp
free_charp = staticmethod(rffi.free_wcharp)
scoped_alloc_buffer = staticmethod(rffi.scoped_alloc_unicodebuffer)
diff --git a/rpython/rlib/rdtoa.py b/rpython/rlib/rdtoa.py
--- a/rpython/rlib/rdtoa.py
+++ b/rpython/rlib/rdtoa.py
@@ -56,22 +56,24 @@
raise MemoryError
end_ptr = lltype.malloc(rffi.CCHARPP.TO, 1, flavor='raw')
try:
- ll_input = rffi.str2charp(input)
+ # note: don't use the class scoped_view_charp here, it
+ # break some tests because this function is used by the GC
+ ll_input, flag = rffi.get_nonmovingbuffer_final_null(input)
try:
result = dg_strtod(ll_input, end_ptr)
endpos = (rffi.cast(lltype.Signed, end_ptr[0]) -
rffi.cast(lltype.Signed, ll_input))
-
- if endpos == 0 or endpos < len(input):
- raise ValueError("invalid input at position %d" % (endpos,))
-
- return result
finally:
- rffi.free_charp(ll_input)
+ rffi.free_nonmovingbuffer(input, ll_input, flag)
finally:
lltype.free(end_ptr, flavor='raw')
+ if endpos == 0 or endpos < len(input):
+ raise ValueError("invalid input at position %d" % (endpos,))
+
+ return result
+
lower_special_strings = ['inf', '+inf', '-inf', 'nan']
upper_special_strings = ['INF', '+INF', '-INF', 'NAN']
diff --git a/rpython/rlib/rposix_environ.py b/rpython/rlib/rposix_environ.py
--- a/rpython/rlib/rposix_environ.py
+++ b/rpython/rlib/rposix_environ.py
@@ -163,7 +163,7 @@
return result
def getenv_llimpl(name):
- with traits.scoped_str2charp(name) as l_name:
+ with traits.scoped_view_charp(name) as l_name:
l_result = getenv(l_name)
return traits.charp2str(l_result) if l_result else None
@@ -206,7 +206,7 @@
save_err=rffi.RFFI_SAVE_ERRNO)
def unsetenv_llimpl(name):
- with rffi.scoped_str2charp(name) as l_name:
+ with rffi.scoped_view_charp(name) as l_name:
error = rffi.cast(lltype.Signed, os_unsetenv(l_name))
if error:
from rpython.rlib import rposix
diff --git a/rpython/rlib/rsocket.py b/rpython/rlib/rsocket.py
--- a/rpython/rlib/rsocket.py
+++ b/rpython/rlib/rsocket.py
@@ -963,7 +963,7 @@
self.settimeout(timeout)
def setsockopt(self, level, option, value):
- with rffi.scoped_str2charp(value) as buf:
+ with rffi.scoped_view_charp(value) as buf:
res = _c.socketsetsockopt(self.fd, level, option,
rffi.cast(rffi.VOIDP, buf),
len(value))
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
@@ -232,40 +232,36 @@
call_external_function = jit.dont_look_inside(
call_external_function)
+ def _oops():
+ raise AssertionError("can't pass (any more) a unicode string"
+ " directly to a VOIDP argument")
+ _oops._annspecialcase_ = 'specialize:memo'
+
unrolling_arg_tps = unrolling_iterable(enumerate(args))
def wrapper(*args):
real_args = ()
+ # XXX 'to_free' leaks if an allocation fails with MemoryError
+ # and was not the first in this function
to_free = ()
for i, TARGET in unrolling_arg_tps:
arg = args[i]
- freeme = None
- if TARGET == CCHARP:
+ if TARGET == CCHARP or TARGET is VOIDP:
if arg is None:
arg = lltype.nullptr(CCHARP.TO) # None => (char*)NULL
- freeme = arg
+ to_free = to_free + (arg, '\x04')
elif isinstance(arg, str):
- arg = str2charp(arg)
- # XXX leaks if a str2charp() fails with MemoryError
- # and was not the first in this function
- freeme = arg
+ tup = get_nonmovingbuffer_final_null(arg)
+ to_free = to_free + tup
+ arg = tup[0]
+ elif isinstance(arg, unicode):
+ _oops()
elif TARGET == CWCHARP:
if arg is None:
arg = lltype.nullptr(CWCHARP.TO) # None => (wchar_t*)NULL
- freeme = arg
+ to_free = to_free + (arg,)
elif isinstance(arg, unicode):
arg = unicode2wcharp(arg)
- # XXX leaks if a unicode2wcharp() fails with MemoryError
- # and was not the first in this function
- freeme = arg
- elif TARGET is VOIDP:
- if arg is None:
- arg = lltype.nullptr(VOIDP.TO)
- elif isinstance(arg, str):
- arg = str2charp(arg)
- freeme = arg
- elif isinstance(arg, unicode):
- arg = unicode2wcharp(arg)
- freeme = arg
+ to_free = to_free + (arg,)
elif _isfunctype(TARGET) and not _isllptr(arg):
# XXX pass additional arguments
use_gil = invoke_around_handlers
@@ -283,11 +279,23 @@
or TARGET is lltype.Bool)):
arg = cast(TARGET, arg)
real_args = real_args + (arg,)
- to_free = to_free + (freeme,)
res = call_external_function(*real_args)
+ j = 0
for i, TARGET in unrolling_arg_tps:
- if to_free[i]:
- lltype.free(to_free[i], flavor='raw')
+ arg = args[i]
+ if TARGET == CCHARP or TARGET is VOIDP:
+ if arg is None:
+ j = j + 2
+ elif isinstance(arg, str):
+ free_nonmovingbuffer(arg, to_free[j], to_free[j+1])
+ j = j + 2
+ elif TARGET == CWCHARP:
+ if arg is None:
+ j = j + 1
+ elif isinstance(arg, unicode):
+ free_wcharp(to_free[j])
+ j = j + 1
+ assert j == len(to_free)
if rarithmetic.r_int is not r_int:
if result is INT:
return cast(lltype.Signed, res)
@@ -833,7 +841,7 @@
if not rgc.can_move(data):
flag = '\x04'
else:
- if rgc.pin(data):
+ if we_are_translated() and rgc.pin(data):
flag = '\x05'
else:
buf = lltype.malloc(TYPEP.TO, count + (TYPEP is CCHARP),
@@ -1219,9 +1227,15 @@
__enter__._always_inline_ = 'try'
__exit__._always_inline_ = 'try'
-class scoped_nonmovingbuffer_final_null:
+class scoped_view_charp:
+ """Returns a 'char *' that (tries to) point inside the given RPython
+ string (which must not be None). You can replace scoped_str2charp()
+ with scoped_view_charp() in all places that guarantee that the
+ content of the 'char[]' array will not be modified.
+ """
def __init__(self, data):
self.data = data
+ __init__._annenforceargs_ = [None, annmodel.SomeString(can_be_None=False)]
def __enter__(self):
self.buf, self.flag = get_nonmovingbuffer_final_null(self.data)
return self.buf
diff --git a/rpython/rtyper/lltypesystem/test/test_rffi.py
b/rpython/rtyper/lltypesystem/test/test_rffi.py
--- a/rpython/rtyper/lltypesystem/test/test_rffi.py
+++ b/rpython/rtyper/lltypesystem/test/test_rffi.py
@@ -836,9 +836,9 @@
value = 0xAAAABBBBCCCCDDDD
assert cast(rffi.__INT128_T, r_uint64(value)) == value
-def test_scoped_nonmovingbuffer_final_null():
+def test_scoped_view_charp():
s = 'bar'
- with scoped_nonmovingbuffer_final_null(s) as buf:
+ with scoped_view_charp(s) as buf:
assert buf[0] == 'b'
assert buf[1] == 'a'
assert buf[2] == 'r'
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit