[pypy-commit] pypy py3k: merge default
pjenvey
noreply at buildbot.pypy.org
Mon Oct 7 21:20:14 CEST 2013
Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r67186:7cd5f50e628b
Date: 2013-10-07 12:18 -0700
http://bitbucket.org/pypy/pypy/changeset/7cd5f50e628b/
Log: merge default
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -363,9 +363,11 @@
pass
-def connect(database, **kwargs):
- factory = kwargs.get("factory", Connection)
- return factory(database, **kwargs)
+def connect(database, timeout=5.0, detect_types=0, isolation_level="",
+ check_same_thread=True, factory=None, cached_statements=100):
+ factory = Connection if not factory else factory
+ return factory(database, timeout, detect_types, isolation_level,
+ check_same_thread, factory, cached_statements)
def _unicode_text_factory(x):
diff --git a/lib_pypy/_tkinter/tclobj.py b/lib_pypy/_tkinter/tclobj.py
--- a/lib_pypy/_tkinter/tclobj.py
+++ b/lib_pypy/_tkinter/tclobj.py
@@ -22,9 +22,11 @@
return result
elif value.typePtr == typeCache.BooleanType:
- return result
+ return bool(value.internalRep.longValue)
elif value.typePtr == typeCache.ByteArrayType:
- return result
+ size = tkffi.new('int*')
+ data = tklib.Tcl_GetByteArrayFromObj(value, size)
+ return tkffi.buffer(data, size[0])[:]
elif value.typePtr == typeCache.DoubleType:
return value.internalRep.doubleValue
elif value.typePtr == typeCache.IntType:
@@ -44,7 +46,7 @@
result.append(FromObj(app, tcl_elem[0]))
return tuple(result)
elif value.typePtr == typeCache.ProcBodyType:
- return result
+ pass # fall through and return tcl object.
elif value.typePtr == typeCache.StringType:
buf = tklib.Tcl_GetUnicode(value)
length = tklib.Tcl_GetCharLength(value)
diff --git a/lib_pypy/_tkinter/tklib.py b/lib_pypy/_tkinter/tklib.py
--- a/lib_pypy/_tkinter/tklib.py
+++ b/lib_pypy/_tkinter/tklib.py
@@ -72,6 +72,7 @@
int Tcl_GetBoolean(Tcl_Interp* interp, const char* src, int* boolPtr);
char *Tcl_GetString(Tcl_Obj* objPtr);
char *Tcl_GetStringFromObj(Tcl_Obj* objPtr, int* lengthPtr);
+unsigned char *Tcl_GetByteArrayFromObj(Tcl_Obj* objPtr, int* lengthPtr);
Tcl_UniChar *Tcl_GetUnicode(Tcl_Obj* objPtr);
int Tcl_GetCharLength(Tcl_Obj* objPtr);
diff --git a/pypy/doc/arm.rst b/pypy/doc/arm.rst
--- a/pypy/doc/arm.rst
+++ b/pypy/doc/arm.rst
@@ -35,6 +35,11 @@
* ``qemu-system``
* ``qemu-user-static``
+- The dependencies above are in addition to the ones needed for a regular
+ translation, `listed here`_.
+
+.. _`listed here`: getting-started-python.html#translating-the-pypy-python-interpreter
+
Creating a Qemu based ARM chroot
--------------------------------
diff --git a/pypy/interpreter/eval.py b/pypy/interpreter/eval.py
--- a/pypy/interpreter/eval.py
+++ b/pypy/interpreter/eval.py
@@ -107,9 +107,15 @@
for i in range(min(len(varnames), self.getfastscopelength())):
name = varnames[i]
w_value = fastscope_w[i]
+ w_name = self.space.wrap(name.decode('utf-8'))
if w_value is not None:
- w_name = self.space.wrap(name.decode('utf-8'))
self.space.setitem(self.w_locals, w_name, w_value)
+ else:
+ try:
+ self.space.delitem(self.w_locals, w_name)
+ except OperationError as e:
+ if not e.match(self.space, self.space.w_KeyError):
+ raise
def locals2fast(self):
# Copy values from self.w_locals to the fastlocals
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -1073,6 +1073,8 @@
sys.path.append(self.goal_dir)
# make sure cwd does not contain a stdlib
+ if self.tmp_dir.startswith(self.trunkdir):
+ skip('TMPDIR is inside the PyPy source')
os.chdir(self.tmp_dir)
tmp_pypy_c = os.path.join(self.tmp_dir, 'pypy-c')
try:
diff --git a/pypy/module/__builtin__/test/test_builtin.py b/pypy/module/__builtin__/test/test_builtin.py
--- a/pypy/module/__builtin__/test/test_builtin.py
+++ b/pypy/module/__builtin__/test/test_builtin.py
@@ -129,10 +129,21 @@
def test_locals(self):
def f():
return locals()
+
def g(c=0, b=0, a=0):
return locals()
+
assert f() == {}
- assert g() == {'a':0, 'b':0, 'c':0}
+ assert g() == {'a': 0, 'b': 0, 'c': 0}
+
+ def test_locals_deleted_local(self):
+ def f():
+ a = 3
+ locals()
+ del a
+ return locals()
+
+ assert f() == {}
def test_dir(self):
def f():
@@ -298,22 +309,6 @@
assert next(x) == 3
def test_range_args(self):
-## # range() attributes are deprecated and were removed in Python 2.3.
-## x = range(2)
-## assert x.start == 0
-## assert x.stop == 2
-## assert x.step == 1
-
-## x = range(2,10,2)
-## assert x.start == 2
-## assert x.stop == 10
-## assert x.step == 2
-
-## x = range(2.3, 10.5, 2.4)
-## assert x.start == 2
-## assert x.stop == 10
-## assert x.step == 2
-
raises(ValueError, range, 0, 1, 0)
def test_range_repr(self):
@@ -374,7 +369,7 @@
raises(TypeError, range, 1, 3+2j)
raises(TypeError, range, 1, 2, '1')
raises(TypeError, range, 1, 2, 3+2j)
-
+
def test_sorted(self):
l = []
sorted_l = sorted(l)
@@ -393,7 +388,7 @@
assert sorted_l is not l
assert sorted_l == ['C', 'b', 'a']
raises(TypeError, sorted, [], reverse=None)
-
+
def test_reversed_simple_sequences(self):
l = range(5)
rev = reversed(l)
@@ -409,7 +404,7 @@
return 42
obj = SomeClass()
assert reversed(obj) == 42
-
+
def test_return_None(self):
class X(object): pass
x = X()
@@ -465,7 +460,7 @@
assert eval("1+2") == 3
assert eval(" \t1+2\n") == 3
assert eval("len([])") == 0
- assert eval("len([])", {}) == 0
+ assert eval("len([])", {}) == 0
# cpython 2.4 allows this (raises in 2.3)
assert eval("3", None, None) == 3
i = 4
diff --git a/pypy/module/cpyext/ndarrayobject.py b/pypy/module/cpyext/ndarrayobject.py
--- a/pypy/module/cpyext/ndarrayobject.py
+++ b/pypy/module/cpyext/ndarrayobject.py
@@ -149,14 +149,17 @@
only used if the array is constructed that way. Almost always this
parameter is NULL.
"""
- if min_depth !=0 or max_depth != 0:
- raise OperationError(space.w_NotImplementedError, space.wrap(
- '_PyArray_FromAny called with not-implemented min_dpeth or max_depth argument'))
if requirements not in (0, NPY_DEFAULT):
raise OperationError(space.w_NotImplementedError, space.wrap(
'_PyArray_FromAny called with not-implemented requirements argument'))
w_array = array(space, w_obj, w_dtype=w_dtype, copy=False)
- if w_array.is_scalar():
+ if min_depth !=0 and len(w_array.get_shape()) < min_depth:
+ raise OperationError(space.w_ValueError, space.wrap(
+ 'object of too small depth for desired array'))
+ elif max_depth !=0 and len(w_array.get_shape()) > max_depth:
+ raise OperationError(space.w_ValueError, space.wrap(
+ 'object of too deep for desired array'))
+ elif w_array.is_scalar():
# since PyArray_DATA() fails on scalars, create a 1D array and set empty
# shape. So the following combination works for *reading* scalars:
# PyObject *arr = PyArray_FromAny(obj);
diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py b/pypy/module/cpyext/test/test_ndarrayobject.py
--- a/pypy/module/cpyext/test/test_ndarrayobject.py
+++ b/pypy/module/cpyext/test/test_ndarrayobject.py
@@ -90,15 +90,16 @@
def test_FromAny(self, space, api):
a = array(space, [10, 5, 3])
assert api._PyArray_FromAny(a, NULL, 0, 0, 0, NULL) is a
- self.raises(space, api, NotImplementedError, api._PyArray_FromAny,
- a, NULL, 0, 3, 0, NULL)
+ assert api._PyArray_FromAny(a, NULL, 1, 4, 0, NULL) is a
+ self.raises(space, api, ValueError, api._PyArray_FromAny,
+ a, NULL, 4, 5, 0, NULL)
def test_FromObject(self, space, api):
a = array(space, [10, 5, 3])
assert api._PyArray_FromObject(a, a.get_dtype().num, 0, 0) is a
- exc = self.raises(space, api, NotImplementedError, api._PyArray_FromObject,
- a, 11, 0, 3)
- assert exc.errorstr(space).find('FromObject') >= 0
+ exc = self.raises(space, api, ValueError, api._PyArray_FromObject,
+ a, 11, 4, 5)
+ assert exc.errorstr(space).find('desired') >= 0
def test_list_from_fixedptr(self, space, api):
A = lltype.GcArray(lltype.Float)
diff --git a/pypy/module/math/interp_math.py b/pypy/module/math/interp_math.py
--- a/pypy/module/math/interp_math.py
+++ b/pypy/module/math/interp_math.py
@@ -350,9 +350,8 @@
v = hi
del partials[added:]
if v != 0.0:
- if rfloat.isinf(v) or rfloat.isnan(v):
- if (not rfloat.isinf(original) and
- not rfloat.isnan(original)):
+ if not rfloat.isfinite(v):
+ if rfloat.isfinite(original):
raise OperationError(space.w_OverflowError,
space.wrap("intermediate overflow"))
if rfloat.isinf(original):
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -2966,6 +2966,12 @@
assert len(list(a[0])) == 2
+ def test_issue_1589(self):
+ import numpypy as numpy
+ c = numpy.array([[(1, 2, 'a'), (3, 4, 'b')], [(5, 6, 'c'), (7, 8, 'd')]],
+ dtype=[('bg', 'i8'), ('fg', 'i8'), ('char', 'S1')])
+ assert c[0][0]["char"] == 'a'
+
class AppTestPyPy(BaseNumpyAppTest):
def setup_class(cls):
if option.runappdirect and '__pypy__' not in sys.builtin_module_names:
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -1766,14 +1766,14 @@
def store(self, arr, i, offset, box):
assert isinstance(box, interp_boxes.W_StringBox)
- # XXX simplify to range(box.dtype.get_size()) ?
return self._store(arr.storage, i, offset, box)
@jit.unroll_safe
def _store(self, storage, i, offset, box):
assert isinstance(box, interp_boxes.W_StringBox)
- for k in range(min(self.size, box.arr.size-offset)):
- storage[k + i] = box.arr.storage[k + offset]
+ # XXX simplify to range(box.dtype.get_size()) ?
+ for k in range(min(self.size, box.arr.size-box.ofs)):
+ storage[k + offset + i] = box.arr.storage[k + box.ofs]
def read(self, arr, i, offset, dtype=None):
if dtype is None:
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -277,3 +277,28 @@
f1 = call_release_gil(..., descr=<Calli 4 ii EF=6 OS=62>)
...
""")
+
+ def test__cffi_bug1(self):
+ from rpython.rlib.test.test_clibffi import get_libm_name
+ def main(libm_name):
+ try:
+ import _cffi_backend
+ except ImportError:
+ sys.stderr.write('SKIP: cannot import _cffi_backend\n')
+ return 0
+
+ libm = _cffi_backend.load_library(libm_name)
+ BDouble = _cffi_backend.new_primitive_type("double")
+ BSin = _cffi_backend.new_function_type([BDouble], BDouble)
+ sin = libm.load_function(BSin, 'sin')
+
+ def f(*args):
+ for i in range(300):
+ sin(*args)
+
+ f(1.0)
+ f(1)
+ #
+ libm_name = get_libm_name(sys.platform)
+ log = self.run(main, [libm_name])
+ # assert did not crash
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -113,7 +113,7 @@
i13 = strgetitem(p9, 0)
i15 = int_eq(i13, 45)
guard_false(i15, descr=...)
- i17 = int_sub(0, i10)
+ i17 = int_neg(i10)
i19 = int_gt(i10, 23)
guard_false(i19, descr=...)
p21 = newstr(23)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_thread.py b/pypy/module/pypyjit/test_pypy_c/test_thread.py
--- a/pypy/module/pypyjit/test_pypy_c/test_thread.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_thread.py
@@ -1,4 +1,3 @@
-import py
from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
@@ -51,7 +50,6 @@
""")
def test_lock_acquire_release(self):
- py.test.skip("test too precise, please fix me")
def main(n):
import threading
lock = threading.Lock()
@@ -62,35 +60,30 @@
assert log.result == main(500)
loop, = log.loops_by_filename(self.filepath)
assert loop.match("""
- i58 = int_gt(i43, 0)
- guard_true(i58, descr=<Guard0x10483adb8>)
- p59 = getfield_gc(p15, descr=<FieldP pypy.module.thread.os_lock.Lock.inst_lock 8>)
- i60 = getfield_gc(p59, descr=<FieldU rpython.rlib.rthread.Lock.inst__lock 8>)
+ i55 = int_gt(i43, 0)
+ guard_true(i55, descr=...)
+ p56 = force_token()
+ setfield_gc(p0, p56, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token .*>)
+ i57 = call_release_gil(..., i36, 1, descr=<Calli 4 ii EF=6>)
+ guard_not_forced(descr=...)
+ guard_no_exception(descr=...)
+ i58 = int_is_true(i57)
+ guard_true(i58, descr=...)
+ i59 = int_sub(i43, 1)
+ guard_not_invalidated(descr=...)
p61 = force_token()
- setfield_gc(p0, p61, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 24>)
- i62 = call_release_gil(4312440032, i60, 1, descr=<Calli 4 ii EF=6>)
- guard_not_forced(descr=<Guard0x103f3cca0>)
- guard_no_exception(descr=<Guard0x10483ad40>)
+ setfield_gc(p0, p61, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token .*>)
+ i62 = call_release_gil(..., i36, 0, descr=<Calli 4 ii EF=6>)
+ guard_not_forced(descr=...)
+ guard_no_exception(descr=...)
i63 = int_is_true(i62)
- guard_true(i63, descr=<Guard0x10483acc8>)
- i64 = int_sub(i43, 1)
- guard_not_invalidated(descr=<Guard0x10483ac50>)
- p66 = getfield_gc(p15, descr=<FieldP pypy.module.thread.os_lock.Lock.inst_lock 8>)
- i67 = getfield_gc(p66, descr=<FieldU rpython.rlib.rthread.Lock.inst__lock 8>)
- p68 = force_token()
- setfield_gc(p0, p68, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 24>)
- i69 = call_release_gil(4312440032, i67, 0, descr=<Calli 4 ii EF=6>)
- guard_not_forced(descr=<Guard0x103f3cc20>)
- guard_no_exception(descr=<Guard0x10483aae8>)
- i70 = int_is_true(i69)
- guard_false(i70, descr=<Guard0x10483aa70>)
- i71 = getfield_gc(p66, descr=<FieldU rpython.rlib.rthread.Lock.inst__lock 8>)
- p72 = force_token()
- setfield_gc(p0, p72, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 24>)
- call_release_gil(4312441056, i71, descr=<Callv 0 i EF=6>)
- guard_not_forced(descr=<Guard0x103f3cba0>)
- guard_no_exception(descr=<Guard0x10483a9f8>)
- guard_not_invalidated(descr=<Guard0x10483a980>)
+ guard_false(i63, descr=...)
+ p64 = force_token()
+ setfield_gc(p0, p64, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token .*>)
+ call_release_gil(..., i36, descr=<Callv 0 i EF=6>)
+ guard_not_forced(descr=...)
+ guard_no_exception(descr=...)
+ guard_not_invalidated(descr=...)
--TICK--
- jump(..., descr=TargetToken(4361239720))
+ jump(..., descr=...)
""")
diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py
--- a/pypy/module/test_lib_pypy/test_sqlite3.py
+++ b/pypy/module/test_lib_pypy/test_sqlite3.py
@@ -31,6 +31,12 @@
result = list(cursor)
assert result == [(42,)]
+def test_connect_takes_same_positional_args_as_Connection(con):
+ from inspect import getargspec
+ clsargs = getargspec(_sqlite3.Connection.__init__).args[1:] # ignore self
+ conargs = getargspec(_sqlite3.connect).args
+ assert clsargs == conargs
+
def test_total_changes_after_close(con):
con.close()
pytest.raises(_sqlite3.ProgrammingError, "con.total_changes")
diff --git a/pypy/module/thread/os_lock.py b/pypy/module/thread/os_lock.py
--- a/pypy/module/thread/os_lock.py
+++ b/pypy/module/thread/os_lock.py
@@ -75,6 +75,8 @@
class Lock(W_Root):
"A wrappable box around an interp-level lock object."
+ _immutable_fields_ = ["lock"]
+
def __init__(self, space):
self.space = space
try:
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -398,21 +398,24 @@
x = w_float1.floatval
y = w_float2.floatval
+ return W_FloatObject(_pow(space, x, y))
+
+def _pow(space, x, y):
# Sort out special cases here instead of relying on pow()
- if y == 2.0: # special case for performance:
- return W_FloatObject(x * x) # x * x is always correct
+ if y == 2.0: # special case for performance:
+ return x * x # x * x is always correct
if y == 0.0:
# x**0 is 1, even 0**0
- return W_FloatObject(1.0)
+ return 1.0
if isnan(x):
# nan**y = nan, unless y == 0
- return W_FloatObject(x)
+ return x
if isnan(y):
# x**nan = nan, unless x == 1; x**nan = x
if x == 1.0:
- return W_FloatObject(1.0)
+ return 1.0
else:
- return W_FloatObject(y)
+ return y
if isinf(y):
# x**inf is: 0.0 if abs(x) < 1; 1.0 if abs(x) == 1; inf if
# abs(x) > 1 (including case where x infinite)
@@ -421,11 +424,11 @@
# abs(x) > 1 (including case where v infinite)
x = abs(x)
if x == 1.0:
- return W_FloatObject(1.0)
+ return 1.0
elif (y > 0.0) == (x > 1.0):
- return W_FloatObject(INFINITY)
+ return INFINITY
else:
- return W_FloatObject(0.0)
+ return 0.0
if isinf(x):
# (+-inf)**w is: inf for w positive, 0 for w negative; in oth
# cases, we need to add the appropriate sign if w is an odd
@@ -433,14 +436,14 @@
y_is_odd = math.fmod(abs(y), 2.0) == 1.0
if y > 0.0:
if y_is_odd:
- return W_FloatObject(x)
+ return x
else:
- return W_FloatObject(abs(x))
+ return abs(x)
else:
if y_is_odd:
- return W_FloatObject(copysign(0.0, x))
+ return copysign(0.0, x)
else:
- return W_FloatObject(0.0)
+ return 0.0
if x == 0.0:
if y < 0.0:
@@ -454,7 +457,7 @@
# - pipermail/python-bugs-list/2003-March/016795.html
if x < 0.0:
if isnan(y):
- return W_FloatObject(NAN)
+ return NAN
if math.floor(y) != y:
# Negative numbers raised to fractional powers become
# complex
@@ -470,9 +473,9 @@
if x == 1.0:
# (-1) ** large_integer also ends up here
if negate_result:
- return W_FloatObject(-1.0)
+ return -1.0
else:
- return W_FloatObject(1.0)
+ return 1.0
try:
# We delegate to our implementation of math.pow() the error detection.
@@ -486,7 +489,7 @@
if negate_result:
z = -z
- return W_FloatObject(z)
+ return z
def neg__Float(space, w_float1):
diff --git a/pypy/objspace/std/tupleobject.py b/pypy/objspace/std/tupleobject.py
--- a/pypy/objspace/std/tupleobject.py
+++ b/pypy/objspace/std/tupleobject.py
@@ -194,10 +194,10 @@
W_AbstractTupleObject.typedef = StdTypeDef(
"tuple",
- __doc__ = '''tuple() -> an empty tuple
+ __doc__ = """tuple() -> an empty tuple
tuple(sequence) -> tuple initialized from sequence's items
-If the argument is a tuple, the return value is the same object.''',
+If the argument is a tuple, the return value is the same object.""",
__new__ = interp2app(W_AbstractTupleObject.descr_new),
__repr__ = interp2app(W_AbstractTupleObject.descr_repr),
__hash__ = interpindirect2app(W_AbstractTupleObject.descr_hash),
diff --git a/pypy/pytest-A.py b/pypy/pytest-A.py
--- a/pypy/pytest-A.py
+++ b/pypy/pytest-A.py
@@ -5,7 +5,6 @@
'arm': ['interpreter/astcompiler/test',
'interpreter/pyparser/test',
'interpreter/test',
- 'interpreter/test2',
'module/test_lib_pypy',
'objspace/std/test',
],
diff --git a/rpython/flowspace/test/test_objspace.py b/rpython/flowspace/test/test_objspace.py
--- a/rpython/flowspace/test/test_objspace.py
+++ b/rpython/flowspace/test/test_objspace.py
@@ -1063,7 +1063,6 @@
assert len(graph.startblock.exits) == 1
assert graph.startblock.exits[0].target == graph.returnblock
-
def test_global_variable(self):
def global_var_missing():
return a
diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -381,6 +381,8 @@
res = self.llinterp.eval_graph(ptr._obj.graph, args)
else:
res = ptr._obj._callable(*args)
+ if RESULT is lltype.Void:
+ return None
return support.cast_result(RESULT, res)
def _do_call(self, func, args_i, args_r, args_f, calldescr):
diff --git a/rpython/jit/metainterp/heapcache.py b/rpython/jit/metainterp/heapcache.py
--- a/rpython/jit/metainterp/heapcache.py
+++ b/rpython/jit/metainterp/heapcache.py
@@ -87,9 +87,11 @@
def _escape(self, box):
if box in self.new_boxes:
self.new_boxes[box] = False
- if box in self.dependencies:
- deps = self.dependencies[box]
- del self.dependencies[box]
+ try:
+ deps = self.dependencies.pop(box)
+ except KeyError:
+ pass
+ else:
for dep in deps:
self._escape(dep)
@@ -117,15 +119,18 @@
# effects are so well defined.
elif effectinfo.oopspecindex == effectinfo.OS_ARRAYCOPY:
# The destination box
- if argboxes[2] in self.new_boxes:
- # XXX: no descr here so we invalidate any of them, not just
- # of the correct type
- # XXX: in theory the indices of the copy could be looked at
- # as well
- for descr, cache in self.heap_array_cache.iteritems():
+ if (
+ argboxes[2] in self.new_boxes and
+ len(effectinfo.write_descrs_arrays) == 1
+ ):
+ # Fish the descr out of the effectinfo
+ cache = self.heap_array_cache.get(effectinfo.write_descrs_arrays[0], None)
+ if cache is not None:
+ # XXX: in theory the indices of the copy could be
+ # looked at
for idx, cache in cache.iteritems():
for frombox in cache.keys():
- if not self.new_boxes.get(frombox, False):
+ if not self.is_unescaped(frombox):
del cache[frombox]
return
else:
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -107,6 +107,11 @@
v2 = self.getvalue(op.getarg(1))
if v2.is_constant() and v2.box.getint() == 0:
self.make_equal_to(op.result, v1)
+ elif v1.is_constant() and v1.box.getint() == 0:
+ op = op.copy_and_change(rop.INT_NEG, args=[v2.box])
+ self.emit_operation(op)
+ elif v1 is v2:
+ self.make_constant_int(op.result, 0)
else:
self.emit_operation(op)
# Synthesize the reverse ops for optimize_default to reuse
@@ -166,6 +171,8 @@
if v2.is_constant() and v2.box.getint() == 0:
self.make_equal_to(op.result, v1)
+ elif v1.is_constant() and v1.box.getint() == 0:
+ self.make_constant_int(op.result, 0)
else:
self.emit_operation(op)
@@ -175,6 +182,8 @@
if v2.is_constant() and v2.box.getint() == 0:
self.make_equal_to(op.result, v1)
+ elif v1.is_constant() and v1.box.getint() == 0:
+ self.make_constant_int(op.result, 0)
else:
self.emit_operation(op)
diff --git a/rpython/jit/metainterp/optimizeopt/simplify.py b/rpython/jit/metainterp/optimizeopt/simplify.py
--- a/rpython/jit/metainterp/optimizeopt/simplify.py
+++ b/rpython/jit/metainterp/optimizeopt/simplify.py
@@ -45,7 +45,7 @@
return self.optimize_JUMP(op.copy_and_change(rop.JUMP))
self.last_label_descr = op.getdescr()
self.emit_operation(op)
-
+
def optimize_JUMP(self, op):
if not self.unroll:
descr = op.getdescr()
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -3735,6 +3735,33 @@
"""
self.optimize_loop(ops, expected)
+ def test_sub_identity(self):
+ ops = """
+ [i0]
+ i1 = int_sub(i0, i0)
+ i2 = int_sub(i1, i0)
+ jump(i1, i2)
+ """
+ expected = """
+ [i0]
+ i2 = int_neg(i0)
+ jump(0, i2)
+ """
+ self.optimize_loop(ops, expected)
+
+ def test_shift_zero(self):
+ ops = """
+ [i0]
+ i1 = int_lshift(0, i0)
+ i2 = int_rshift(0, i0)
+ jump(i1, i2)
+ """
+ expected = """
+ [i0]
+ jump(0, 0)
+ """
+ self.optimize_loop(ops, expected)
+
def test_bound_and(self):
ops = """
[i0]
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -45,6 +45,15 @@
return value
return OptValue(self.force_box(optforce))
+ def get_args_for_fail(self, modifier):
+ # checks for recursion: it is False unless
+ # we have already seen the very same keybox
+ if self.box is None and not modifier.already_seen_virtual(self.keybox):
+ self._get_args_for_fail(modifier)
+
+ def _get_args_for_fail(self, modifier):
+ raise NotImplementedError("abstract base")
+
def make_virtual_info(self, modifier, fieldnums):
if fieldnums is None:
return self._make_virtual(modifier)
@@ -193,16 +202,13 @@
self._cached_sorted_fields = lst
return lst
- def get_args_for_fail(self, modifier):
- if self.box is None and not modifier.already_seen_virtual(self.keybox):
- # checks for recursion: it is False unless
- # we have already seen the very same keybox
- lst = self._get_field_descr_list()
- fieldboxes = [self._fields[ofs].get_key_box() for ofs in lst]
- modifier.register_virtual_fields(self.keybox, fieldboxes)
- for ofs in lst:
- fieldvalue = self._fields[ofs]
- fieldvalue.get_args_for_fail(modifier)
+ def _get_args_for_fail(self, modifier):
+ lst = self._get_field_descr_list()
+ fieldboxes = [self._fields[ofs].get_key_box() for ofs in lst]
+ modifier.register_virtual_fields(self.keybox, fieldboxes)
+ for ofs in lst:
+ fieldvalue = self._fields[ofs]
+ fieldvalue.get_args_for_fail(modifier)
class VirtualValue(AbstractVirtualStructValue):
level = optimizer.LEVEL_KNOWNCLASS
@@ -254,18 +260,15 @@
def set_item_value(self, i, newval):
raise NotImplementedError
- def get_args_for_fail(self, modifier):
- if self.box is None and not modifier.already_seen_virtual(self.keybox):
- # checks for recursion: it is False unless
- # we have already seen the very same keybox
- itemboxes = []
- for i in range(self.getlength()):
- itemvalue = self.get_item_value(i)
- itemboxes.append(itemvalue.get_key_box())
- modifier.register_virtual_fields(self.keybox, itemboxes)
- for i in range(self.getlength()):
- itemvalue = self.get_item_value(i)
- itemvalue.get_args_for_fail(modifier)
+ def _get_args_for_fail(self, modifier):
+ itemboxes = []
+ for i in range(self.getlength()):
+ itemvalue = self.get_item_value(i)
+ itemboxes.append(itemvalue.get_key_box())
+ modifier.register_virtual_fields(self.keybox, itemboxes)
+ for i in range(self.getlength()):
+ itemvalue = self.get_item_value(i)
+ itemvalue.get_args_for_fail(modifier)
class VArrayValue(AbstractVArrayValue):
@@ -370,17 +373,16 @@
descrs.append(item_descrs)
return descrs
- def get_args_for_fail(self, modifier):
- if self.box is None and not modifier.already_seen_virtual(self.keybox):
- itemdescrs = self._get_list_of_descrs()
- itemboxes = []
- for i in range(len(self._items)):
- for descr in itemdescrs[i]:
- itemboxes.append(self._items[i][descr].get_key_box())
- modifier.register_virtual_fields(self.keybox, itemboxes)
- for i in range(len(self._items)):
- for descr in itemdescrs[i]:
- self._items[i][descr].get_args_for_fail(modifier)
+ def _get_args_for_fail(self, modifier):
+ itemdescrs = self._get_list_of_descrs()
+ itemboxes = []
+ for i in range(len(self._items)):
+ for descr in itemdescrs[i]:
+ itemboxes.append(self._items[i][descr].get_key_box())
+ modifier.register_virtual_fields(self.keybox, itemboxes)
+ for i in range(len(self._items)):
+ for descr in itemdescrs[i]:
+ self._items[i][descr].get_args_for_fail(modifier)
def force_at_end_of_preamble(self, already_forced, optforce):
if self in already_forced:
@@ -481,6 +483,15 @@
def getitem_raw(self, offset, length, descr):
return self.rawbuffer_value.getitem_raw(self.offset+offset, length, descr)
+ def _get_args_for_fail(self, modifier):
+ box = self.rawbuffer_value.get_key_box()
+ modifier.register_virtual_fields(self.keybox, [box])
+ self.rawbuffer_value.get_args_for_fail(modifier)
+
+ def _make_virtual(self, modifier):
+ return modifier.make_vrawslice(self.offset)
+
+
class OptVirtualize(optimizer.Optimization):
"Virtualize objects until they escape."
diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py
--- a/rpython/jit/metainterp/resume.py
+++ b/rpython/jit/metainterp/resume.py
@@ -284,7 +284,10 @@
return VArrayStructInfo(arraydescr, fielddescrs)
def make_vrawbuffer(self, size, offsets, descrs):
- return VRawBufferStateInfo(size, offsets, descrs)
+ return VRawBufferInfo(size, offsets, descrs)
+
+ def make_vrawslice(self, offset):
+ return VRawSliceInfo(offset)
def make_vstrplain(self, is_unicode=False):
if is_unicode:
@@ -554,10 +557,13 @@
debug_print("\t\t", str(untag(i)))
-class VRawBufferStateInfo(AbstractVirtualInfo):
+class VAbstractRawInfo(AbstractVirtualInfo):
kind = INT
is_about_raw = True
+
+class VRawBufferInfo(VAbstractRawInfo):
+
def __init__(self, size, offsets, descrs):
self.size = size
self.offsets = offsets
@@ -580,6 +586,25 @@
debug_print("\t\t", str(untag(i)))
+class VRawSliceInfo(VAbstractRawInfo):
+
+ def __init__(self, offset):
+ self.offset = offset
+
+ @specialize.argtype(1)
+ def allocate_int(self, decoder, index):
+ assert len(self.fieldnums) == 1
+ base_buffer = decoder.decode_int(self.fieldnums[0])
+ buffer = decoder.int_add_const(base_buffer, self.offset)
+ decoder.virtuals_cache.set_int(index, buffer)
+ return buffer
+
+ def debug_prints(self):
+ debug_print("\tvrawsliceinfo", " at ", compute_unique_id(self))
+ for i in self.fieldnums:
+ debug_print("\t\t", str(untag(i)))
+
+
class VArrayStructInfo(AbstractVirtualInfo):
def __init__(self, arraydescr, fielddescrs):
self.arraydescr = arraydescr
@@ -783,7 +808,8 @@
v = self.virtuals_cache.get_int(index)
if not v:
v = self.rd_virtuals[index]
- assert v.is_about_raw and isinstance(v, VRawBufferStateInfo)
+ ll_assert(bool(v), "resume.py: null rd_virtuals[index]")
+ assert v.is_about_raw and isinstance(v, VAbstractRawInfo)
v = v.allocate_int(self, index)
ll_assert(v == self.virtuals_cache.get_int(index), "resume.py: bad cache")
return v
@@ -1116,6 +1142,10 @@
def write_a_float(self, index, box):
self.boxes_f[index] = box
+ def int_add_const(self, intbox, offset):
+ return self.metainterp.execute_and_record(rop.INT_ADD, None, intbox,
+ ConstInt(offset))
+
# ---------- when resuming for blackholing, get direct values ----------
def blackhole_from_resumedata(blackholeinterpbuilder, jitdriver_sd, storage,
@@ -1407,6 +1437,9 @@
def write_a_float(self, index, float):
self.blackholeinterp.setarg_f(index, float)
+ def int_add_const(self, base, offset):
+ return base + offset
+
# ____________________________________________________________
def dump_storage(storage, liveboxes):
diff --git a/rpython/jit/metainterp/test/test_fficall.py b/rpython/jit/metainterp/test/test_fficall.py
--- a/rpython/jit/metainterp/test/test_fficall.py
+++ b/rpython/jit/metainterp/test/test_fficall.py
@@ -86,15 +86,17 @@
data = rffi.ptradd(exchange_buffer, ofs)
rffi.cast(lltype.Ptr(TYPE), data)[0] = write_rvalue
- def f():
+ def f(i):
exbuf = lltype.malloc(rffi.CCHARP.TO, (len(avalues)+2) * 16,
- flavor='raw', zero=True)
- ofs = 16
+ flavor='raw')
+
+ targetptr = rffi.ptradd(exbuf, 16)
for avalue in unroll_avalues:
TYPE = rffi.CArray(lltype.typeOf(avalue))
- data = rffi.ptradd(exbuf, ofs)
- rffi.cast(lltype.Ptr(TYPE), data)[0] = avalue
- ofs += 16
+ if i >= 9: # a guard that can fail
+ pass
+ rffi.cast(lltype.Ptr(TYPE), targetptr)[0] = avalue
+ targetptr = rffi.ptradd(targetptr, 16)
jit_ffi_call(cif_description, func_addr, exbuf)
@@ -102,8 +104,7 @@
res = 654321
else:
TYPE = rffi.CArray(lltype.typeOf(rvalue))
- data = rffi.ptradd(exbuf, ofs)
- res = rffi.cast(lltype.Ptr(TYPE), data)[0]
+ res = rffi.cast(lltype.Ptr(TYPE), targetptr)[0]
lltype.free(exbuf, flavor='raw')
if lltype.typeOf(res) is lltype.SingleFloat:
res = float(res)
@@ -117,9 +118,9 @@
return res == rvalue
with FakeFFI(fake_call_impl_any):
- res = f()
+ res = f(-42)
assert matching_result(res, rvalue)
- res = self.interp_operations(f, [],
+ res = self.interp_operations(f, [-42],
supports_floats = supports_floats,
supports_longlong = supports_longlong,
supports_singlefloats = supports_singlefloats)
@@ -132,6 +133,19 @@
self.check_operations_history(call_may_force=0,
call_release_gil=expected_call_release_gil)
+ ##################################################
+ driver = jit.JitDriver(reds=['i'], greens=[])
+ def main():
+ i = 0
+ while 1:
+ driver.jit_merge_point(i=i)
+ res = f(i)
+ i += 1
+ if i == 12:
+ return res
+ self.meta_interp(main, [])
+
+
def test_simple_call_int(self):
self._run([types.signed] * 2, types.signed, [456, 789], -42)
diff --git a/rpython/jit/metainterp/test/test_heapcache.py b/rpython/jit/metainterp/test/test_heapcache.py
--- a/rpython/jit/metainterp/test/test_heapcache.py
+++ b/rpython/jit/metainterp/test/test_heapcache.py
@@ -29,17 +29,24 @@
OS_ARRAYCOPY = 0
- def __init__(self, extraeffect, oopspecindex):
+ def __init__(self, extraeffect, oopspecindex, write_descrs_arrays):
self.extraeffect = extraeffect
self.oopspecindex = oopspecindex
+ self.write_descrs_arrays = write_descrs_arrays
+
class FakeCallDescr(object):
- def __init__(self, extraeffect, oopspecindex=None):
+ def __init__(self, extraeffect, oopspecindex=None, write_descrs_arrays=[]):
self.extraeffect = extraeffect
self.oopspecindex = oopspecindex
+ self.write_descrs_arrays = write_descrs_arrays
def get_extra_info(self):
- return FakeEffectinfo(self.extraeffect, self.oopspecindex)
+ return FakeEffectinfo(
+ self.extraeffect, self.oopspecindex,
+ write_descrs_arrays=self.write_descrs_arrays
+ )
+
class TestHeapCache(object):
def test_known_class_box(self):
@@ -364,13 +371,13 @@
# Just need the destination box for this call
h.invalidate_caches(
rop.CALL,
- FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY),
+ FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
[None, None, box2, None, None]
)
assert h.getarrayitem(box1, index1, descr1) is box2
h.invalidate_caches(
rop.CALL,
- FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY),
+ FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
[None, None, box3, None, None]
)
assert h.getarrayitem(box1, index1, descr1) is None
@@ -379,11 +386,24 @@
assert h.getarrayitem(box4, index1, descr1) is box2
h.invalidate_caches(
rop.CALL,
- FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY),
+ FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]),
[None, None, box2, None, None]
)
assert h.getarrayitem(box4, index1, descr1) is None
+ def test_ll_arraycopy_differing_descrs(self):
+ h = HeapCache()
+ h.setarrayitem(box1, index1, box2, descr1)
+ assert h.getarrayitem(box1, index1, descr1) is box2
+ h.new_array(box2, lengthbox2)
+ h.invalidate_caches(
+ rop.CALL,
+ FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr2]),
+ [None, None, box2, None, None]
+ )
+ assert h.getarrayitem(box1, index1, descr1) is box2
+
+
def test_unescaped(self):
h = HeapCache()
assert not h.is_unescaped(box1)
diff --git a/rpython/memory/support.py b/rpython/memory/support.py
--- a/rpython/memory/support.py
+++ b/rpython/memory/support.py
@@ -121,13 +121,15 @@
cur = next
free_non_gc_object(self)
- def _length_estimate(self):
+ def length(self):
chunk = self.chunk
+ result = 0
count = self.used_in_last_chunk
while chunk:
+ result += count
chunk = chunk.next
- count += chunk_size
- return count
+ count = chunk_size
+ return result
def foreach(self, callback, arg):
"""Invoke 'callback(address, arg)' for all addresses in the stack.
@@ -144,7 +146,7 @@
foreach._annspecialcase_ = 'specialize:arg(1)'
def stack2dict(self):
- result = AddressDict(self._length_estimate())
+ result = AddressDict(self.length())
self.foreach(_add_in_dict, result)
return result
diff --git a/rpython/memory/test/test_support.py b/rpython/memory/test/test_support.py
--- a/rpython/memory/test/test_support.py
+++ b/rpython/memory/test/test_support.py
@@ -94,6 +94,18 @@
assert a == addrs[i]
assert not ll.non_empty()
+ def test_length(self):
+ AddressStack = get_address_stack(10)
+ ll = AddressStack()
+ a = raw_malloc(llmemory.sizeof(lltype.Signed))
+ for i in range(42):
+ assert ll.length() == i
+ ll.append(a)
+ for i in range(42-1, -1, -1):
+ b = ll.pop()
+ assert b == a
+ assert ll.length() == i
+
class TestAddressDeque:
def test_big_access(self):
diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py
--- a/rpython/rlib/rbigint.py
+++ b/rpython/rlib/rbigint.py
@@ -728,10 +728,16 @@
if c.numdigits() == 1 and c._digits[0] == ONEDIGIT:
return NULLRBIGINT
- # if base < 0:
- # base = base % modulus
- # Having the base positive just makes things easier.
- if a.sign < 0:
+ # Reduce base by modulus in some cases:
+ # 1. If base < 0. Forcing the base non-neg makes things easier.
+ # 2. If base is obviously larger than the modulus. The "small
+ # exponent" case later can multiply directly by base repeatedly,
+ # while the "large exponent" case multiplies directly by base 31
+ # times. It can be unboundedly faster to multiply by
+ # base % modulus instead.
+ # We could _always_ do this reduction, but mod() isn't cheap,
+ # so we only do it when it buys something.
+ if a.sign < 0 or a.numdigits() > c.numdigits():
a = a.mod(c)
elif b.sign == 0:
diff --git a/rpython/rlib/rpath.py b/rpython/rlib/rpath.py
--- a/rpython/rlib/rpath.py
+++ b/rpython/rlib/rpath.py
@@ -23,3 +23,103 @@
return path
else:
raise ImportError('Unsupported os: %s' % os.name)
+
+
+def dirname(p):
+ """Returns the directory component of a pathname"""
+ i = p.rfind('/') + 1
+ assert i >= 0
+ head = p[:i]
+ if head and head != '/' * len(head):
+ head = head.rstrip('/')
+ return head
+
+
+def basename(p):
+ """Returns the final component of a pathname"""
+ i = p.rfind('/') + 1
+ assert i >= 0
+ return p[i:]
+
+
+def split(p):
+ """Split a pathname. Returns tuple "(head, tail)" where "tail" is
+ everything after the final slash. Either part may be empty."""
+ i = p.rfind('/') + 1
+ assert i >= 0
+ head, tail = p[:i], p[i:]
+ if head and head != '/' * len(head):
+ head = head.rstrip('/')
+ return head, tail
+
+
+def exists(path):
+ """Test whether a path exists. Returns False for broken symbolic links"""
+ try:
+ assert path is not None
+ os.stat(path)
+ except os.error:
+ return False
+ return True
+
+
+import os
+from os.path import isabs, islink, abspath, normpath
+
+def join(a, p):
+ """Join two or more pathname components, inserting '/' as needed.
+ If any component is an absolute path, all previous path components
+ will be discarded. An empty last part will result in a path that
+ ends with a separator."""
+ path = a
+ for b in p:
+ if b.startswith('/'):
+ path = b
+ elif path == '' or path.endswith('/'):
+ path += b
+ else:
+ path += '/' + b
+ return path
+
+def realpath(filename):
+ """Return the canonical path of the specified filename, eliminating any
+symbolic links encountered in the path."""
+ if isabs(filename):
+ bits = ['/'] + filename.split('/')[1:]
+ else:
+ bits = [''] + filename.split('/')
+
+ for i in range(2, len(bits)+1):
+ component = join(bits[0], bits[1:i])
+ # Resolve symbolic links.
+ if islink(component):
+ resolved = _resolve_link(component)
+ if resolved is None:
+ # Infinite loop -- return original component + rest of the path
+ return abspath(join(component, bits[i:]))
+ else:
+ newpath = join(resolved, bits[i:])
+ return realpath(newpath)
+
+ return abspath(filename)
+
+
+def _resolve_link(path):
+ """Internal helper function. Takes a path and follows symlinks
+ until we either arrive at something that isn't a symlink, or
+ encounter a path we've seen before (meaning that there's a loop).
+ """
+ paths_seen = {}
+ while islink(path):
+ if path in paths_seen:
+ # Already seen this path, so we must have a symlink loop
+ return None
+ paths_seen[path] = None
+ # Resolve where the link points to
+ resolved = os.readlink(path)
+ if not isabs(resolved):
+ dir = dirname(path)
+ path = normpath(join(dir, [resolved]))
+ else:
+ path = normpath(resolved)
+ return path
diff --git a/rpython/rlib/rthread.py b/rpython/rlib/rthread.py
--- a/rpython/rlib/rthread.py
+++ b/rpython/rlib/rthread.py
@@ -117,6 +117,8 @@
""" Container for low-level implementation
of a lock object
"""
+ _immutable_fields_ = ["_lock"]
+
def __init__(self, ll_lock):
self._lock = ll_lock
diff --git a/rpython/rlib/test/test_rstacklet.py b/rpython/rlib/test/test_rstacklet.py
--- a/rpython/rlib/test/test_rstacklet.py
+++ b/rpython/rlib/test/test_rstacklet.py
@@ -1,5 +1,6 @@
import gc, sys
import py
+import platform
from rpython.rtyper.tool.rffi_platform import CompilationError
try:
from rpython.rlib import rstacklet
@@ -332,6 +333,10 @@
gc = 'minimark'
gcrootfinder = 'asmgcc'
+ @py.test.mark.skipif("sys.platform != 'linux2' or platform.machine().startswith('arm')")
+ def test_demo1(self):
+ BaseTestStacklet.test_demo1(self)
+
class TestStackletShadowStack(BaseTestStacklet):
gc = 'minimark'
gcrootfinder = 'shadowstack'
diff --git a/rpython/translator/c/src/stacklet/switch_arm_gcc.h b/rpython/translator/c/src/stacklet/switch_arm_gcc.h
--- a/rpython/translator/c/src/stacklet/switch_arm_gcc.h
+++ b/rpython/translator/c/src/stacklet/switch_arm_gcc.h
@@ -1,3 +1,10 @@
+#if __ARM_ARCH__ >= 5
+# define call_reg(x) "blx " #x "\n"
+#elif defined (__ARM_ARCH_4T__)
+# define call_reg(x) "mov lr, pc ; bx " #x "\n"
+#else
+# define call_reg(x) "mov lr, pc ; mov pc, " #x "\n"
+#endif
static void __attribute__((optimize("O3"))) *slp_switch(void *(*save_state)(void*, void*),
void *(*restore_state)(void*, void*),
@@ -11,7 +18,7 @@
"mov r5, %[extra]\n"
"mov r0, sp\n" /* arg 1: current (old) stack pointer */
"mov r1, r5\n" /* arg 2: extra */
- "blx r3\n" /* call save_state() */
+ call_reg(r3) /* call save_state() */
/* skip the rest if the return value is null */
"cmp r0, #0\n"
@@ -23,7 +30,7 @@
stack is not restored yet. It contains only garbage here. */
"mov r1, r5\n" /* arg 2: extra */
/* arg 1: current (new) stack pointer is already in r0*/
- "blx r4\n" /* call restore_state() */
+ call_reg(r4) /* call restore_state() */
/* The stack's content is now restored. */
"zero:\n"
More information about the pypy-commit
mailing list